@ycodium-ai/agent-claude 0.2.3488 → 0.2.3502
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 +21 -0
- package/dist/index.js +860 -670
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -349,8 +349,8 @@ async function* historyBytes(path, start, end, signal) {
|
|
|
349
349
|
async function* historyText(path, range, signal) {
|
|
350
350
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
351
351
|
for await (const bytes of historyBytes(path, range.start, range.end, signal)) {
|
|
352
|
-
const
|
|
353
|
-
if (
|
|
352
|
+
const text2 = decoder.decode(bytes, { stream: true });
|
|
353
|
+
if (text2) yield text2;
|
|
354
354
|
}
|
|
355
355
|
const last = decoder.decode();
|
|
356
356
|
if (last) yield last;
|
|
@@ -693,33 +693,33 @@ var OversizedRecordParser = class {
|
|
|
693
693
|
this.#strCap = cap;
|
|
694
694
|
}
|
|
695
695
|
/** 字符串里的一个解码后片段;按保留规则累积。 */
|
|
696
|
-
#append(
|
|
697
|
-
if (
|
|
696
|
+
#append(text2) {
|
|
697
|
+
if (text2.length === 0) return;
|
|
698
698
|
if (this.#stringIsKey) {
|
|
699
699
|
if (this.#keyOverflow) return;
|
|
700
|
-
this.#key +=
|
|
700
|
+
this.#key += text2;
|
|
701
701
|
if (this.#key.length > MAX_KEY_CHARS) {
|
|
702
702
|
this.#keyOverflow = true;
|
|
703
703
|
this.#key = "";
|
|
704
704
|
}
|
|
705
705
|
return;
|
|
706
706
|
}
|
|
707
|
-
this.#strLength +=
|
|
708
|
-
this.#strObserver?.onChunk?.(
|
|
707
|
+
this.#strLength += text2.length;
|
|
708
|
+
this.#strObserver?.onChunk?.(text2);
|
|
709
709
|
if (!this.#strRetain) return;
|
|
710
710
|
const cap = this.#strCap;
|
|
711
711
|
if (cap === void 0) {
|
|
712
|
-
this.#strHead +=
|
|
713
|
-
this.#charge(
|
|
712
|
+
this.#strHead += text2;
|
|
713
|
+
this.#charge(text2.length);
|
|
714
714
|
return;
|
|
715
715
|
}
|
|
716
716
|
if (this.#strHead.length < cap) {
|
|
717
717
|
const room = cap - this.#strHead.length;
|
|
718
|
-
this.#strHead +=
|
|
719
|
-
|
|
720
|
-
if (
|
|
718
|
+
this.#strHead += text2.slice(0, room);
|
|
719
|
+
text2 = text2.slice(room);
|
|
720
|
+
if (text2.length === 0) return;
|
|
721
721
|
}
|
|
722
|
-
this.#strTail +=
|
|
722
|
+
this.#strTail += text2;
|
|
723
723
|
if (this.#strTail.length > cap * 2) this.#strTail = this.#strTail.slice(-cap);
|
|
724
724
|
}
|
|
725
725
|
#consumeString(chunk, start) {
|
|
@@ -809,35 +809,35 @@ var OversizedRecordParser = class {
|
|
|
809
809
|
return;
|
|
810
810
|
}
|
|
811
811
|
const cap = this.#strCap;
|
|
812
|
-
let
|
|
812
|
+
let text2 = this.#strHead;
|
|
813
813
|
if (cap !== void 0) {
|
|
814
814
|
let tail = this.#strTail;
|
|
815
815
|
if (tail.length > cap) tail = tail.slice(-cap);
|
|
816
|
-
if (this.#strLength >
|
|
817
|
-
if (isHighSurrogate(
|
|
816
|
+
if (this.#strLength > text2.length + tail.length) {
|
|
817
|
+
if (isHighSurrogate(text2.charCodeAt(text2.length - 1))) text2 = text2.slice(0, -1);
|
|
818
818
|
if (isLowSurrogate(tail.charCodeAt(0))) tail = tail.slice(1);
|
|
819
|
-
const omitted = this.#strLength -
|
|
820
|
-
|
|
819
|
+
const omitted = this.#strLength - text2.length - tail.length;
|
|
820
|
+
text2 = `${text2}
|
|
821
821
|
[\u2026 ${omitted} chars omitted \u2026]
|
|
822
822
|
${tail}`;
|
|
823
823
|
} else {
|
|
824
|
-
|
|
824
|
+
text2 = `${text2}${tail}`;
|
|
825
825
|
}
|
|
826
|
-
this.#charge(
|
|
826
|
+
this.#charge(text2.length);
|
|
827
827
|
}
|
|
828
828
|
this.#strHead = "";
|
|
829
829
|
this.#strTail = "";
|
|
830
|
-
this.#store(
|
|
830
|
+
this.#store(text2);
|
|
831
831
|
}
|
|
832
832
|
#finishBare() {
|
|
833
|
-
const
|
|
833
|
+
const text2 = this.#bare;
|
|
834
834
|
this.#bare = "";
|
|
835
835
|
const { mode, path } = this.#childMode(false);
|
|
836
836
|
let value;
|
|
837
|
-
if (
|
|
838
|
-
else if (
|
|
839
|
-
else if (
|
|
840
|
-
else if (NUMBER_PATTERN.test(
|
|
837
|
+
if (text2 === "true") value = true;
|
|
838
|
+
else if (text2 === "false") value = false;
|
|
839
|
+
else if (text2 === "null") value = null;
|
|
840
|
+
else if (NUMBER_PATTERN.test(text2)) value = Number(text2);
|
|
841
841
|
else this.#fail();
|
|
842
842
|
const observer = this.#fields.find(
|
|
843
843
|
(field) => field.path.length === path.length && matchesPrefix(field.path, path, path.length)
|
|
@@ -893,14 +893,14 @@ async function* readJsonlEntries(fs2, path, options) {
|
|
|
893
893
|
pending2 = 0;
|
|
894
894
|
return next;
|
|
895
895
|
};
|
|
896
|
-
const append = (
|
|
897
|
-
if (
|
|
896
|
+
const append = (text2) => {
|
|
897
|
+
if (text2.length === 0) return;
|
|
898
898
|
if (parser !== null) {
|
|
899
|
-
parser.write(
|
|
899
|
+
parser.write(text2);
|
|
900
900
|
return;
|
|
901
901
|
}
|
|
902
|
-
pieces.push(
|
|
903
|
-
pending2 +=
|
|
902
|
+
pieces.push(text2);
|
|
903
|
+
pending2 += text2.length;
|
|
904
904
|
if (pending2 > options.maxLineChars) parser = startOversized();
|
|
905
905
|
};
|
|
906
906
|
const takeLine = () => {
|
|
@@ -916,15 +916,15 @@ async function* readJsonlEntries(fs2, path, options) {
|
|
|
916
916
|
if (line.endsWith("\r")) line = line.slice(0, -1);
|
|
917
917
|
return line.length === 0 ? null : { line };
|
|
918
918
|
};
|
|
919
|
-
const feed = function* (
|
|
919
|
+
const feed = function* (text2) {
|
|
920
920
|
let from = 0;
|
|
921
|
-
while (from <=
|
|
922
|
-
const newline =
|
|
921
|
+
while (from <= text2.length) {
|
|
922
|
+
const newline = text2.indexOf("\n", from);
|
|
923
923
|
if (newline < 0) {
|
|
924
|
-
append(
|
|
924
|
+
append(text2.slice(from));
|
|
925
925
|
return;
|
|
926
926
|
}
|
|
927
|
-
append(
|
|
927
|
+
append(text2.slice(from, newline));
|
|
928
928
|
const entry = takeLine();
|
|
929
929
|
if (entry !== null) yield entry;
|
|
930
930
|
from = newline + 1;
|
|
@@ -950,9 +950,9 @@ var textFields = (paths, accept) => {
|
|
|
950
950
|
return paths.map((path) => ({
|
|
951
951
|
path,
|
|
952
952
|
scalarOnly: true,
|
|
953
|
-
onChunk: (
|
|
953
|
+
onChunk: (text2) => {
|
|
954
954
|
begin();
|
|
955
|
-
accept(
|
|
955
|
+
accept(text2);
|
|
956
956
|
},
|
|
957
957
|
onEnd: () => {
|
|
958
958
|
begin();
|
|
@@ -970,16 +970,16 @@ var createHistoryRecordAccumulator = (layout) => {
|
|
|
970
970
|
const parser = new OversizedRecordParser(
|
|
971
971
|
[
|
|
972
972
|
...selected.fields,
|
|
973
|
-
...textFields(selected.textPaths, (
|
|
974
|
-
messageTotal +=
|
|
973
|
+
...textFields(selected.textPaths, (text2) => {
|
|
974
|
+
messageTotal += text2.length;
|
|
975
975
|
})
|
|
976
976
|
],
|
|
977
977
|
Number.MAX_SAFE_INTEGER,
|
|
978
978
|
{ pruneEmpty: true }
|
|
979
979
|
);
|
|
980
|
-
const accept = (
|
|
981
|
-
rawTotal +=
|
|
982
|
-
parser.write(
|
|
980
|
+
const accept = (text2) => {
|
|
981
|
+
rawTotal += text2.length;
|
|
982
|
+
parser.write(text2);
|
|
983
983
|
};
|
|
984
984
|
return {
|
|
985
985
|
write: (bytes) => {
|
|
@@ -1021,11 +1021,11 @@ async function* historyRecordWindows(path, info, mode, from, until, limit, layou
|
|
|
1021
1021
|
let offset = from;
|
|
1022
1022
|
let pending2 = "";
|
|
1023
1023
|
const ready = [];
|
|
1024
|
-
const accept = (
|
|
1024
|
+
const accept = (text2) => {
|
|
1025
1025
|
const begin = Math.max(0, from - seen);
|
|
1026
|
-
const end = Math.min(
|
|
1027
|
-
seen +=
|
|
1028
|
-
if (end > begin) pending2 +=
|
|
1026
|
+
const end = Math.min(text2.length, until - seen);
|
|
1027
|
+
seen += text2.length;
|
|
1028
|
+
if (end > begin) pending2 += text2.slice(begin, end);
|
|
1029
1029
|
while (pending2.length >= limit) {
|
|
1030
1030
|
let size = limit;
|
|
1031
1031
|
const code = pending2.charCodeAt(size - 1);
|
|
@@ -1039,9 +1039,9 @@ async function* historyRecordWindows(path, info, mode, from, until, limit, layou
|
|
|
1039
1039
|
const parser = mode === "raw" ? void 0 : new OversizedRecordParser(textFields(selected.textPaths, accept), Number.MAX_SAFE_INTEGER, {
|
|
1040
1040
|
pruneEmpty: true
|
|
1041
1041
|
});
|
|
1042
|
-
for await (const
|
|
1043
|
-
if (parser === void 0) accept(
|
|
1044
|
-
else parser.write(
|
|
1042
|
+
for await (const text2 of historyText(path, info.range, signal)) {
|
|
1043
|
+
if (parser === void 0) accept(text2);
|
|
1044
|
+
else parser.write(text2);
|
|
1045
1045
|
while (ready.length > 0) yield ready.shift();
|
|
1046
1046
|
if (seen >= until) break;
|
|
1047
1047
|
}
|
|
@@ -1053,7 +1053,7 @@ var verifyHistoryRecord = async (path, range, layout, signal) => {
|
|
|
1053
1053
|
pruneEmpty: true
|
|
1054
1054
|
});
|
|
1055
1055
|
try {
|
|
1056
|
-
for await (const
|
|
1056
|
+
for await (const text2 of historyText(path, range, signal)) parser.write(text2);
|
|
1057
1057
|
} catch (error) {
|
|
1058
1058
|
if (!range.terminated && error instanceof TypeError) return false;
|
|
1059
1059
|
throw error;
|
|
@@ -1092,7 +1092,7 @@ var width = (n) => String(n).padStart(20, "0");
|
|
|
1092
1092
|
var high = (n) => n >= 55296 && n <= 56319;
|
|
1093
1093
|
var low = (n) => n >= 56320 && n <= 57343;
|
|
1094
1094
|
var totalOf = (info, index) => info.items[index].text === "raw" ? info.rawTotal : info.messageTotal;
|
|
1095
|
-
var nativeItem = (identity, info, index, offset,
|
|
1095
|
+
var nativeItem = (identity, info, index, offset, text2) => {
|
|
1096
1096
|
const { text: _mode, ...item } = info.items[index];
|
|
1097
1097
|
const total = totalOf(info, index);
|
|
1098
1098
|
const position = { e: identity, p: info.range.start, k: index, h: info.hash };
|
|
@@ -1101,13 +1101,13 @@ var nativeItem = (identity, info, index, offset, text) => {
|
|
|
1101
1101
|
id: `${identity}:${info.range.start}:${index}`,
|
|
1102
1102
|
orderKey: `${width(info.range.start)}:${width(index)}`,
|
|
1103
1103
|
beforeCursor: encode({ ...position, o: offset }),
|
|
1104
|
-
afterCursor: encode({ ...position, o: offset +
|
|
1105
|
-
text,
|
|
1104
|
+
afterCursor: encode({ ...position, o: offset + text2.length }),
|
|
1105
|
+
text: text2,
|
|
1106
1106
|
textWindow: {
|
|
1107
1107
|
offset,
|
|
1108
|
-
returned:
|
|
1108
|
+
returned: text2.length,
|
|
1109
1109
|
total,
|
|
1110
|
-
nextOffset: offset +
|
|
1110
|
+
nextOffset: offset + text2.length < total ? offset + text2.length : null
|
|
1111
1111
|
}
|
|
1112
1112
|
};
|
|
1113
1113
|
};
|
|
@@ -1131,7 +1131,7 @@ var readWindow = async (path, info, index, from, until, layout, signal, cached)
|
|
|
1131
1131
|
cached.text = parts.join("");
|
|
1132
1132
|
cached.mode = mode;
|
|
1133
1133
|
}
|
|
1134
|
-
let
|
|
1134
|
+
let text2 = cached.mode === mode ? cached.text?.slice(base, end) ?? "" : "";
|
|
1135
1135
|
if (cached.mode !== mode) {
|
|
1136
1136
|
for await (const window2 of historyRecordWindows(
|
|
1137
1137
|
path,
|
|
@@ -1143,13 +1143,13 @@ var readWindow = async (path, info, index, from, until, layout, signal, cached)
|
|
|
1143
1143
|
layout,
|
|
1144
1144
|
signal
|
|
1145
1145
|
))
|
|
1146
|
-
|
|
1146
|
+
text2 += window2.text;
|
|
1147
1147
|
}
|
|
1148
1148
|
let startIndex = from - base;
|
|
1149
1149
|
let endIndex = until - base;
|
|
1150
|
-
if (low(
|
|
1151
|
-
if (low(
|
|
1152
|
-
return { offset: base + startIndex, text:
|
|
1150
|
+
if (low(text2.charCodeAt(startIndex)) && high(text2.charCodeAt(startIndex - 1))) startIndex -= 1;
|
|
1151
|
+
if (low(text2.charCodeAt(endIndex)) && high(text2.charCodeAt(endIndex - 1))) endIndex -= 1;
|
|
1152
|
+
return { offset: base + startIndex, text: text2.slice(startIndex, endIndex) };
|
|
1153
1153
|
};
|
|
1154
1154
|
async function openJsonlHistory(path, layout, signal) {
|
|
1155
1155
|
const controller = new AbortController();
|
|
@@ -1546,10 +1546,10 @@ async function readClaudeTranscriptDigest(filePath) {
|
|
|
1546
1546
|
continue;
|
|
1547
1547
|
}
|
|
1548
1548
|
if (typed.type !== "user") continue;
|
|
1549
|
-
const
|
|
1550
|
-
if (
|
|
1549
|
+
const text2 = textFromContent(typed.message?.content);
|
|
1550
|
+
if (text2.length === 0) continue;
|
|
1551
1551
|
turnCount += 1;
|
|
1552
|
-
if (preview === null) preview =
|
|
1552
|
+
if (preview === null) preview = text2;
|
|
1553
1553
|
}
|
|
1554
1554
|
} catch {
|
|
1555
1555
|
return null;
|
|
@@ -1731,20 +1731,20 @@ async function readClaudeSessionRecord(input) {
|
|
|
1731
1731
|
const content = message.content;
|
|
1732
1732
|
const blocks = typeof content === "string" ? [{ type: "text", text: content }] : Array.isArray(content) ? content : [];
|
|
1733
1733
|
const hasToolResult = blocks.some((block) => isRecord(block) && block.type === "tool_result");
|
|
1734
|
-
const
|
|
1734
|
+
const text2 = blocks.flatMap((block) => {
|
|
1735
1735
|
const typed = isRecord(block) ? block : void 0;
|
|
1736
1736
|
if (!typed) return [];
|
|
1737
1737
|
if (typed.type === "text" && typeof typed.text === "string") return [typed.text];
|
|
1738
1738
|
return [];
|
|
1739
1739
|
}).join("\n\n").trim();
|
|
1740
|
-
if (
|
|
1740
|
+
if (text2.length === 0) continue;
|
|
1741
1741
|
if (value.type === "user" && hasToolResult) continue;
|
|
1742
1742
|
const role = value.type === "assistant" ? "assistant" : "user";
|
|
1743
1743
|
if (role === "assistant" && typeof message.model === "string") model = message.model;
|
|
1744
1744
|
const timestamp = typeof value.timestamp === "string" ? Date.parse(value.timestamp) : typeof value.timestamp === "number" ? value.timestamp : void 0;
|
|
1745
1745
|
messages.push({
|
|
1746
1746
|
role,
|
|
1747
|
-
text,
|
|
1747
|
+
text: text2,
|
|
1748
1748
|
...timestamp !== void 0 && Number.isFinite(timestamp) ? { createdAt: timestamp } : {}
|
|
1749
1749
|
});
|
|
1750
1750
|
}
|
|
@@ -1791,8 +1791,8 @@ var claudeHistoryLayout = (input) => () => {
|
|
|
1791
1791
|
].map((key) => ({ path: [key], scalarOnly: true, maxChars: 2048 })),
|
|
1792
1792
|
{
|
|
1793
1793
|
path: ["message", "content", "*", "type"],
|
|
1794
|
-
onChunk: (
|
|
1795
|
-
blockType = (blockType +
|
|
1794
|
+
onChunk: (text2) => {
|
|
1795
|
+
blockType = (blockType + text2).slice(0, 128);
|
|
1796
1796
|
},
|
|
1797
1797
|
onEnd: () => {
|
|
1798
1798
|
hasTools ||= blockType === "tool_use" || blockType === "tool_result";
|
|
@@ -1802,20 +1802,20 @@ var claudeHistoryLayout = (input) => () => {
|
|
|
1802
1802
|
},
|
|
1803
1803
|
{
|
|
1804
1804
|
path: ["message", "content", "*", "name"],
|
|
1805
|
-
onChunk: (
|
|
1806
|
-
name = (name +
|
|
1805
|
+
onChunk: (text2) => {
|
|
1806
|
+
name = (name + text2).slice(0, 256);
|
|
1807
1807
|
}
|
|
1808
1808
|
},
|
|
1809
1809
|
{
|
|
1810
1810
|
path: ["message", "content", "*", "id"],
|
|
1811
|
-
onChunk: (
|
|
1812
|
-
toolCallId = (toolCallId +
|
|
1811
|
+
onChunk: (text2) => {
|
|
1812
|
+
toolCallId = (toolCallId + text2).slice(0, 256);
|
|
1813
1813
|
}
|
|
1814
1814
|
},
|
|
1815
1815
|
{
|
|
1816
1816
|
path: ["message", "content", "*", "tool_use_id"],
|
|
1817
|
-
onChunk: (
|
|
1818
|
-
toolCallId = (toolCallId +
|
|
1817
|
+
onChunk: (text2) => {
|
|
1818
|
+
toolCallId = (toolCallId + text2).slice(0, 256);
|
|
1819
1819
|
}
|
|
1820
1820
|
}
|
|
1821
1821
|
],
|
|
@@ -1869,7 +1869,7 @@ var openClaudeHistory = (input) => {
|
|
|
1869
1869
|
};
|
|
1870
1870
|
|
|
1871
1871
|
// src/claudeInstance.ts
|
|
1872
|
-
import * as
|
|
1872
|
+
import * as NodeOS10 from "node:os";
|
|
1873
1873
|
import * as NodePath19 from "node:path";
|
|
1874
1874
|
|
|
1875
1875
|
// ../../node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.3.170_@anthropic-ai+sdk@0.93.0_zod@4.6.5__@modelcontex_64204813d4dba2ebc464c3aa751485a4/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
|
|
@@ -21303,15 +21303,19 @@ function HU(e, t) {
|
|
|
21303
21303
|
}
|
|
21304
21304
|
|
|
21305
21305
|
// src/claudeInstance.ts
|
|
21306
|
-
import { mergeLaunchEnv as
|
|
21306
|
+
import { mergeLaunchEnv as mergeLaunchEnv4 } from "@ycodium-ai/plugin-api/executor";
|
|
21307
|
+
import { isOperationCleanupError as isOperationCleanupError3 } from "@ycodium-ai/plugin-api/process-operation";
|
|
21307
21308
|
|
|
21308
21309
|
// src/claudeProbe.ts
|
|
21309
21310
|
import {
|
|
21310
21311
|
describeExecutorSpawnFailure,
|
|
21311
21312
|
ExecutorSpawnAbortedError,
|
|
21312
|
-
ExecutorSpawnRefusedError
|
|
21313
|
-
raceAbort
|
|
21313
|
+
ExecutorSpawnRefusedError
|
|
21314
21314
|
} from "@ycodium-ai/plugin-api/executor";
|
|
21315
|
+
import {
|
|
21316
|
+
runProcessOperation,
|
|
21317
|
+
isOperationCleanupError
|
|
21318
|
+
} from "@ycodium-ai/plugin-api/process-operation";
|
|
21315
21319
|
|
|
21316
21320
|
// src/claudeAccount.ts
|
|
21317
21321
|
import * as NodeFS4 from "node:fs";
|
|
@@ -21370,10 +21374,10 @@ function claudeCredentialCandidatePaths(input) {
|
|
|
21370
21374
|
NodePath5.join(input.homePath, ".credentials.json")
|
|
21371
21375
|
] : [NodePath5.join(input.credentialsDirPath, ".credentials.json")];
|
|
21372
21376
|
}
|
|
21373
|
-
function readClaudeAccount(credentialsDirPath) {
|
|
21377
|
+
function readClaudeAccount(credentialsDirPath, credentialCandidates) {
|
|
21374
21378
|
const accountDirectory = resolveClaudeAccountDirectory(credentialsDirPath);
|
|
21375
21379
|
const exists = directoryExists(accountDirectory);
|
|
21376
|
-
const candidates = claudeCredentialCandidatePaths({
|
|
21380
|
+
const candidates = credentialCandidates ?? claudeCredentialCandidatePaths({
|
|
21377
21381
|
homePath: NodeOS2.homedir(),
|
|
21378
21382
|
credentialsDirPath
|
|
21379
21383
|
});
|
|
@@ -21400,6 +21404,14 @@ function readClaudeAccount(credentialsDirPath) {
|
|
|
21400
21404
|
};
|
|
21401
21405
|
}
|
|
21402
21406
|
|
|
21407
|
+
// src/usageRead/quota.ts
|
|
21408
|
+
import * as NodeFS5 from "node:fs";
|
|
21409
|
+
import * as NodePath8 from "node:path";
|
|
21410
|
+
import { mergeLaunchEnv, setsOwnModelConnection } from "@ycodium-ai/plugin-api/executor";
|
|
21411
|
+
import {
|
|
21412
|
+
parseRetryAfterMs
|
|
21413
|
+
} from "@ycodium-ai/plugin-api/usage";
|
|
21414
|
+
|
|
21403
21415
|
// src/claudeHome.ts
|
|
21404
21416
|
import * as NodeOS4 from "node:os";
|
|
21405
21417
|
import * as NodePath7 from "node:path";
|
|
@@ -21549,9 +21561,171 @@ function claudeFailureHint(input) {
|
|
|
21549
21561
|
return void 0;
|
|
21550
21562
|
}
|
|
21551
21563
|
|
|
21564
|
+
// src/usageRead/quota.ts
|
|
21565
|
+
var CLAUDE_QUOTA_URL = "https://api.anthropic.com/api/oauth/usage";
|
|
21566
|
+
var REQUEST_TIMEOUT_MS = 1e4;
|
|
21567
|
+
var HOUR_MS = 60 * 60 * 1e3;
|
|
21568
|
+
var CLAUDE_QUOTA_WINDOWS = [
|
|
21569
|
+
{ field: "five_hour", id: "session", labelKey: "usage.window.session", windowMs: 5 * HOUR_MS },
|
|
21570
|
+
{ field: "seven_day", id: "weekly", labelKey: "usage.window.weekly", windowMs: 7 * 24 * HOUR_MS }
|
|
21571
|
+
];
|
|
21572
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21573
|
+
var launchEnvironment = (recipe) => mergeLaunchEnv({
|
|
21574
|
+
inherited: process.env,
|
|
21575
|
+
instanceTable: recipe.environment,
|
|
21576
|
+
handOverrides: claudeHomeVariables(resolveClaudeHomeLayout(recipe))
|
|
21577
|
+
});
|
|
21578
|
+
var claudeCredentialFileCandidates = (recipe) => {
|
|
21579
|
+
const environment = launchEnvironment(recipe);
|
|
21580
|
+
const credentialsDir = resolveClaudeCredentialsDirPath(
|
|
21581
|
+
environment[CLAUDE_CREDENTIALS_DIR_ENVIRONMENT_VARIABLE] ?? ""
|
|
21582
|
+
);
|
|
21583
|
+
if (credentialsDir !== null) return [NodePath8.join(credentialsDir, ".credentials.json")];
|
|
21584
|
+
const configDir = resolveClaudeConfigDirPath(recipe.homePath, environment);
|
|
21585
|
+
const home = resolveClaudeHomePath(recipe.homePath);
|
|
21586
|
+
return [
|
|
21587
|
+
.../* @__PURE__ */ new Set([
|
|
21588
|
+
NodePath8.join(configDir, ".credentials.json"),
|
|
21589
|
+
NodePath8.join(home, ".claude", ".credentials.json"),
|
|
21590
|
+
NodePath8.join(home, ".credentials.json")
|
|
21591
|
+
])
|
|
21592
|
+
];
|
|
21593
|
+
};
|
|
21594
|
+
var readString = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
21595
|
+
var readLoginCredential = (candidates) => {
|
|
21596
|
+
for (const path of candidates) {
|
|
21597
|
+
let raw;
|
|
21598
|
+
try {
|
|
21599
|
+
raw = NodeFS5.readFileSync(path, "utf8");
|
|
21600
|
+
} catch {
|
|
21601
|
+
continue;
|
|
21602
|
+
}
|
|
21603
|
+
if (raw.trim().length === 0) continue;
|
|
21604
|
+
let parsed;
|
|
21605
|
+
try {
|
|
21606
|
+
parsed = JSON.parse(raw);
|
|
21607
|
+
} catch {
|
|
21608
|
+
continue;
|
|
21609
|
+
}
|
|
21610
|
+
const oauth = isRecord3(parsed) ? parsed["claudeAiOauth"] : void 0;
|
|
21611
|
+
if (!isRecord3(oauth)) continue;
|
|
21612
|
+
const accessToken = readString(oauth["accessToken"]);
|
|
21613
|
+
if (accessToken === void 0) continue;
|
|
21614
|
+
return {
|
|
21615
|
+
accessToken,
|
|
21616
|
+
subscriptionType: readString(oauth["subscriptionType"]),
|
|
21617
|
+
rateLimitTier: readString(oauth["rateLimitTier"]),
|
|
21618
|
+
path
|
|
21619
|
+
};
|
|
21620
|
+
}
|
|
21621
|
+
return null;
|
|
21622
|
+
};
|
|
21623
|
+
var claudePlanName = (credential) => {
|
|
21624
|
+
const type4 = credential.subscriptionType;
|
|
21625
|
+
if (type4 === void 0) return void 0;
|
|
21626
|
+
const name = `${type4.charAt(0).toUpperCase()}${type4.slice(1)}`;
|
|
21627
|
+
const multiplier = /(?:^|_)(\d+x)$/.exec(credential.rateLimitTier ?? "")?.[1];
|
|
21628
|
+
return multiplier === void 0 ? name : `${name} ${multiplier}`;
|
|
21629
|
+
};
|
|
21630
|
+
var toIso = (value) => {
|
|
21631
|
+
if (typeof value !== "string") return null;
|
|
21632
|
+
const parsed = Date.parse(value);
|
|
21633
|
+
return Number.isNaN(parsed) ? null : new Date(parsed).toISOString();
|
|
21634
|
+
};
|
|
21635
|
+
var readClaudeQuotaWindows = (body) => CLAUDE_QUOTA_WINDOWS.flatMap((spec) => {
|
|
21636
|
+
const row = body[spec.field];
|
|
21637
|
+
if (!isRecord3(row)) return [];
|
|
21638
|
+
const utilization = row["utilization"];
|
|
21639
|
+
if (typeof utilization !== "number" || !Number.isFinite(utilization)) return [];
|
|
21640
|
+
return [
|
|
21641
|
+
{
|
|
21642
|
+
id: spec.id,
|
|
21643
|
+
label: { key: spec.labelKey },
|
|
21644
|
+
usedPercent: Math.min(100, Math.max(0, utilization)),
|
|
21645
|
+
resetsAt: toIso(row["resets_at"]),
|
|
21646
|
+
windowMs: spec.windowMs
|
|
21647
|
+
}
|
|
21648
|
+
];
|
|
21649
|
+
});
|
|
21650
|
+
var readClaudeQuota = async (request) => {
|
|
21651
|
+
const { recipe } = request;
|
|
21652
|
+
const connectivity = CLAUDE_CARD.modelConnectivity;
|
|
21653
|
+
const environmentRows = Object.entries(recipe.environment).map(([name, value]) => ({
|
|
21654
|
+
name,
|
|
21655
|
+
value
|
|
21656
|
+
}));
|
|
21657
|
+
if (connectivity !== void 0 && setsOwnModelConnection(connectivity, environmentRows)) {
|
|
21658
|
+
const changesEndpoint = setsOwnModelConnection(
|
|
21659
|
+
{
|
|
21660
|
+
baseUrlEnvKey: connectivity.baseUrlEnvKey,
|
|
21661
|
+
backendSwitchEnvKeys: connectivity.backendSwitchEnvKeys
|
|
21662
|
+
},
|
|
21663
|
+
environmentRows
|
|
21664
|
+
);
|
|
21665
|
+
return {
|
|
21666
|
+
status: "unavailable",
|
|
21667
|
+
reason: changesEndpoint ? "customEndpoint" : "unsupportedLogin"
|
|
21668
|
+
};
|
|
21669
|
+
}
|
|
21670
|
+
const credential = readLoginCredential(claudeCredentialFileCandidates(recipe));
|
|
21671
|
+
if (credential === null) return { status: "unavailable", reason: "missingCredentials" };
|
|
21672
|
+
const now = request.now ?? Date.now;
|
|
21673
|
+
let response;
|
|
21674
|
+
try {
|
|
21675
|
+
response = await request.fetch(CLAUDE_QUOTA_URL, {
|
|
21676
|
+
method: "GET",
|
|
21677
|
+
headers: {
|
|
21678
|
+
Accept: "application/json",
|
|
21679
|
+
"anthropic-beta": "oauth-2025-04-20",
|
|
21680
|
+
Authorization: `Bearer ${credential.accessToken}`
|
|
21681
|
+
},
|
|
21682
|
+
redirect: "error",
|
|
21683
|
+
signal: request.signal === void 0 ? AbortSignal.timeout(REQUEST_TIMEOUT_MS) : AbortSignal.any([request.signal, AbortSignal.timeout(REQUEST_TIMEOUT_MS)])
|
|
21684
|
+
});
|
|
21685
|
+
} catch (cause) {
|
|
21686
|
+
if (request.signal?.aborted === true) throw cause;
|
|
21687
|
+
return { status: "unavailable", reason: "unreachable" };
|
|
21688
|
+
}
|
|
21689
|
+
const release = () => {
|
|
21690
|
+
void response.body?.cancel().catch(() => void 0);
|
|
21691
|
+
};
|
|
21692
|
+
if (response.status === 429) {
|
|
21693
|
+
const retryAfterMs = parseRetryAfterMs(response.headers.get("Retry-After"), now());
|
|
21694
|
+
release();
|
|
21695
|
+
return {
|
|
21696
|
+
status: "unavailable",
|
|
21697
|
+
reason: "rateLimited",
|
|
21698
|
+
...retryAfterMs === null ? {} : { retryAfterMs }
|
|
21699
|
+
};
|
|
21700
|
+
}
|
|
21701
|
+
if (response.status === 401 || response.status === 403) {
|
|
21702
|
+
release();
|
|
21703
|
+
return { status: "unavailable", reason: "authRejected" };
|
|
21704
|
+
}
|
|
21705
|
+
if (response.status < 200 || response.status >= 300) {
|
|
21706
|
+
release();
|
|
21707
|
+
return { status: "unavailable", reason: "unreachable" };
|
|
21708
|
+
}
|
|
21709
|
+
let body;
|
|
21710
|
+
try {
|
|
21711
|
+
body = JSON.parse(await response.text());
|
|
21712
|
+
} catch {
|
|
21713
|
+
return { status: "unavailable", reason: "unreachable" };
|
|
21714
|
+
}
|
|
21715
|
+
if (!isRecord3(body)) return { status: "unavailable", reason: "unreachable" };
|
|
21716
|
+
const plan = claudePlanName(credential);
|
|
21717
|
+
return {
|
|
21718
|
+
status: "available",
|
|
21719
|
+
...plan === void 0 ? {} : { plan },
|
|
21720
|
+
windows: readClaudeQuotaWindows(body),
|
|
21721
|
+
balances: [],
|
|
21722
|
+
accountKey: credential.path
|
|
21723
|
+
};
|
|
21724
|
+
};
|
|
21725
|
+
|
|
21552
21726
|
// src/claudeSkills.ts
|
|
21553
21727
|
import * as NodeFSP3 from "node:fs/promises";
|
|
21554
|
-
import * as
|
|
21728
|
+
import * as NodePath9 from "node:path";
|
|
21555
21729
|
import * as NodeProcess3 from "node:process";
|
|
21556
21730
|
var FRONT_MATTER_KEY = /^(description|disable-model-invocation|user-invocable|argument-hint):[ \t]*(.*)$/;
|
|
21557
21731
|
var BLOCK_SCALAR = /^[|>][+-]?$/;
|
|
@@ -21617,7 +21791,7 @@ function claudeManagedSettingsPath(platform4, environment) {
|
|
|
21617
21791
|
}
|
|
21618
21792
|
if (platform4 === "win32") {
|
|
21619
21793
|
const programData = environment["PROGRAMDATA"]?.trim();
|
|
21620
|
-
return programData ?
|
|
21794
|
+
return programData ? NodePath9.join(programData, "ClaudeCode", "managed-settings.json") : void 0;
|
|
21621
21795
|
}
|
|
21622
21796
|
return "/etc/claude-code/managed-settings.json";
|
|
21623
21797
|
}
|
|
@@ -21625,44 +21799,44 @@ function skillOverrideSettingsPaths(configDirPath, cwd, platform4, environment,
|
|
|
21625
21799
|
const managedPath = claudeManagedSettingsPath(platform4, environment);
|
|
21626
21800
|
const root = repositoryRoot !== void 0 && repositoryRoot !== cwd ? repositoryRoot : void 0;
|
|
21627
21801
|
return [
|
|
21628
|
-
|
|
21802
|
+
NodePath9.join(configDirPath, "settings.json"),
|
|
21629
21803
|
...cwd ? [
|
|
21630
|
-
|
|
21631
|
-
|
|
21804
|
+
NodePath9.join(cwd, ".claude", "settings.json"),
|
|
21805
|
+
NodePath9.join(cwd, ".claude", "settings.local.json")
|
|
21632
21806
|
] : [],
|
|
21633
|
-
...root ? [
|
|
21807
|
+
...root ? [NodePath9.join(root, ".claude", "settings.local.json")] : [],
|
|
21634
21808
|
...managedPath ? [managedPath] : []
|
|
21635
21809
|
];
|
|
21636
21810
|
}
|
|
21637
21811
|
async function findRepositoryRoot(cwd) {
|
|
21638
|
-
let current =
|
|
21812
|
+
let current = NodePath9.resolve(cwd);
|
|
21639
21813
|
for (; ; ) {
|
|
21640
|
-
const found = await NodeFSP3.stat(
|
|
21814
|
+
const found = await NodeFSP3.stat(NodePath9.join(current, ".git")).then(
|
|
21641
21815
|
() => true,
|
|
21642
21816
|
() => false
|
|
21643
21817
|
);
|
|
21644
21818
|
if (found) return current;
|
|
21645
|
-
const parent =
|
|
21819
|
+
const parent = NodePath9.dirname(current);
|
|
21646
21820
|
if (parent === current) return void 0;
|
|
21647
21821
|
current = parent;
|
|
21648
21822
|
}
|
|
21649
21823
|
}
|
|
21650
|
-
function parseLenientJson(
|
|
21824
|
+
function parseLenientJson(text2) {
|
|
21651
21825
|
let output = "";
|
|
21652
21826
|
let index = 0;
|
|
21653
|
-
while (index <
|
|
21654
|
-
const char =
|
|
21655
|
-
const next =
|
|
21827
|
+
while (index < text2.length) {
|
|
21828
|
+
const char = text2[index];
|
|
21829
|
+
const next = text2[index + 1];
|
|
21656
21830
|
if (char === '"') {
|
|
21657
21831
|
let end = index + 1;
|
|
21658
|
-
while (end <
|
|
21659
|
-
output +=
|
|
21832
|
+
while (end < text2.length && text2[end] !== '"') end += text2[end] === "\\" ? 2 : 1;
|
|
21833
|
+
output += text2.slice(index, end + 1);
|
|
21660
21834
|
index = end + 1;
|
|
21661
21835
|
} else if (char === "/" && next === "/") {
|
|
21662
|
-
while (index <
|
|
21836
|
+
while (index < text2.length && text2[index] !== "\n") index += 1;
|
|
21663
21837
|
} else if (char === "/" && next === "*") {
|
|
21664
|
-
const end =
|
|
21665
|
-
index = end === -1 ?
|
|
21838
|
+
const end = text2.indexOf("*/", index + 2);
|
|
21839
|
+
index = end === -1 ? text2.length : end + 2;
|
|
21666
21840
|
} else {
|
|
21667
21841
|
output += char;
|
|
21668
21842
|
index += 1;
|
|
@@ -21677,10 +21851,10 @@ var SKILL_OVERRIDE_BY_VALUE = {
|
|
|
21677
21851
|
on: { enabled: true, userInvocationOnly: false },
|
|
21678
21852
|
"name-only": { enabled: true, userInvocationOnly: false }
|
|
21679
21853
|
};
|
|
21680
|
-
function readOverridesFromSettings(
|
|
21854
|
+
function readOverridesFromSettings(text2) {
|
|
21681
21855
|
let parsed;
|
|
21682
21856
|
try {
|
|
21683
|
-
parsed = parseLenientJson(
|
|
21857
|
+
parsed = parseLenientJson(text2);
|
|
21684
21858
|
} catch {
|
|
21685
21859
|
return void 0;
|
|
21686
21860
|
}
|
|
@@ -21724,8 +21898,8 @@ async function discoverClaudeSkills(configDirPath, options = {}) {
|
|
|
21724
21898
|
options.environment ?? NodeProcess3.env
|
|
21725
21899
|
);
|
|
21726
21900
|
const roots = [
|
|
21727
|
-
{ directory:
|
|
21728
|
-
...cwd ? [{ directory:
|
|
21901
|
+
{ directory: NodePath9.join(configDirPath, "skills"), scope: "user" },
|
|
21902
|
+
...cwd ? [{ directory: NodePath9.join(cwd, ".claude", "skills"), scope: "project" }] : []
|
|
21729
21903
|
];
|
|
21730
21904
|
const skills = /* @__PURE__ */ new Map();
|
|
21731
21905
|
for (const root of roots) {
|
|
@@ -21733,7 +21907,7 @@ async function discoverClaudeSkills(configDirPath, options = {}) {
|
|
|
21733
21907
|
for (const entry of entries.toSorted()) {
|
|
21734
21908
|
const name = entry.trim();
|
|
21735
21909
|
if (name.length === 0 || skills.has(name)) continue;
|
|
21736
|
-
const skillPath =
|
|
21910
|
+
const skillPath = NodePath9.join(root.directory, entry, "SKILL.md");
|
|
21737
21911
|
const contents = await NodeFSP3.readFile(skillPath, "utf8").catch(() => void 0);
|
|
21738
21912
|
if (contents === void 0) continue;
|
|
21739
21913
|
const frontMatter = parseSkillFrontMatter(contents);
|
|
@@ -21796,15 +21970,15 @@ function knownClaudeModelCapabilities(model, catalog, customModels) {
|
|
|
21796
21970
|
function claudeModelCapabilities(model, catalog, customModels) {
|
|
21797
21971
|
return knownClaudeModelCapabilities(model, catalog, customModels) ?? DEFAULT_CLAUDE_MODEL_CAPABILITIES;
|
|
21798
21972
|
}
|
|
21799
|
-
function
|
|
21973
|
+
function isRecord4(value) {
|
|
21800
21974
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21801
21975
|
}
|
|
21802
21976
|
function getModelSelectionStringOptionValue(modelSelection, optionId) {
|
|
21803
|
-
if (!
|
|
21977
|
+
if (!isRecord4(modelSelection)) return void 0;
|
|
21804
21978
|
const options = modelSelection["options"];
|
|
21805
21979
|
if (!Array.isArray(options)) return void 0;
|
|
21806
21980
|
for (const entry of options) {
|
|
21807
|
-
if (!
|
|
21981
|
+
if (!isRecord4(entry)) continue;
|
|
21808
21982
|
if (entry["id"] === optionId && typeof entry["value"] === "string") {
|
|
21809
21983
|
const trimmed = entry["value"].trim();
|
|
21810
21984
|
if (trimmed.length > 0) return trimmed;
|
|
@@ -21813,11 +21987,11 @@ function getModelSelectionStringOptionValue(modelSelection, optionId) {
|
|
|
21813
21987
|
return void 0;
|
|
21814
21988
|
}
|
|
21815
21989
|
function getModelSelectionBooleanOptionValue(modelSelection, optionId) {
|
|
21816
|
-
if (!
|
|
21990
|
+
if (!isRecord4(modelSelection)) return void 0;
|
|
21817
21991
|
const options = modelSelection["options"];
|
|
21818
21992
|
if (!Array.isArray(options)) return void 0;
|
|
21819
21993
|
for (const entry of options) {
|
|
21820
|
-
if (!
|
|
21994
|
+
if (!isRecord4(entry)) continue;
|
|
21821
21995
|
if (entry["id"] === optionId && typeof entry["value"] === "boolean") {
|
|
21822
21996
|
return entry["value"];
|
|
21823
21997
|
}
|
|
@@ -21825,7 +21999,7 @@ function getModelSelectionBooleanOptionValue(modelSelection, optionId) {
|
|
|
21825
21999
|
return void 0;
|
|
21826
22000
|
}
|
|
21827
22001
|
function modelIdFromSelection(selection) {
|
|
21828
|
-
if (!
|
|
22002
|
+
if (!isRecord4(selection)) return void 0;
|
|
21829
22003
|
const model = selection["model"];
|
|
21830
22004
|
return typeof model === "string" ? model.trim() || void 0 : void 0;
|
|
21831
22005
|
}
|
|
@@ -22067,16 +22241,12 @@ function claudeToolSearchNotice(version, environment) {
|
|
|
22067
22241
|
var CLAUDE_PROGRAM_NOT_CONFIGURED = "Claude program path is not configured";
|
|
22068
22242
|
function createClaudeProbe(input) {
|
|
22069
22243
|
const { recipe, host, modelCatalog } = input;
|
|
22070
|
-
const collectProcessText = async (stream) => {
|
|
22071
|
-
const chunks = [];
|
|
22072
|
-
for await (const chunk of stream) {
|
|
22073
|
-
chunks.push(Buffer.from(chunk));
|
|
22074
|
-
}
|
|
22075
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
22076
|
-
};
|
|
22077
22244
|
const probeAuth = () => {
|
|
22078
|
-
const
|
|
22079
|
-
|
|
22245
|
+
const native = modelCatalog.currentAuth?.();
|
|
22246
|
+
if (native !== void 0) return native;
|
|
22247
|
+
const environment = input.launchEnvironment();
|
|
22248
|
+
const hasEnvToken = (environment.ANTHROPIC_AUTH_TOKEN ?? "").trim().length > 0;
|
|
22249
|
+
const hasEnvApiKey = (environment.ANTHROPIC_API_KEY ?? "").trim().length > 0;
|
|
22080
22250
|
if (hasEnvToken || hasEnvApiKey) {
|
|
22081
22251
|
return {
|
|
22082
22252
|
status: "authenticated",
|
|
@@ -22084,13 +22254,15 @@ function createClaudeProbe(input) {
|
|
|
22084
22254
|
label: hasEnvToken ? "ANTHROPIC_AUTH_TOKEN" : "ANTHROPIC_API_KEY"
|
|
22085
22255
|
};
|
|
22086
22256
|
}
|
|
22087
|
-
const account = readClaudeAccount(
|
|
22257
|
+
const account = readClaudeAccount(
|
|
22258
|
+
resolveClaudeCredentialsDirPath(recipe.credentialsPath),
|
|
22259
|
+
claudeCredentialFileCandidates(recipe)
|
|
22260
|
+
);
|
|
22088
22261
|
switch (account.state) {
|
|
22089
22262
|
case "signed-in":
|
|
22090
|
-
case "expired":
|
|
22091
22263
|
return { status: "authenticated" };
|
|
22264
|
+
case "expired":
|
|
22092
22265
|
case "signed-out":
|
|
22093
|
-
return { status: "unauthenticated" };
|
|
22094
22266
|
case "unreadable":
|
|
22095
22267
|
return { status: "unknown" };
|
|
22096
22268
|
}
|
|
@@ -22109,16 +22281,31 @@ function createClaudeProbe(input) {
|
|
|
22109
22281
|
if (signal?.aborted) {
|
|
22110
22282
|
throw new ExecutorSpawnAbortedError();
|
|
22111
22283
|
}
|
|
22112
|
-
let
|
|
22284
|
+
let command;
|
|
22285
|
+
let commandStarted = false;
|
|
22286
|
+
const commandHost = {
|
|
22287
|
+
...host,
|
|
22288
|
+
process: {
|
|
22289
|
+
spawn: async (request) => {
|
|
22290
|
+
const handle = await host.process.spawn(request);
|
|
22291
|
+
commandStarted = true;
|
|
22292
|
+
return handle;
|
|
22293
|
+
}
|
|
22294
|
+
}
|
|
22295
|
+
};
|
|
22113
22296
|
try {
|
|
22114
|
-
|
|
22297
|
+
command = await runProcessOperation(commandHost, {
|
|
22115
22298
|
program: recipe.binaryPath,
|
|
22116
22299
|
args: ["--version"],
|
|
22300
|
+
timeoutMs: CLAUDE_VERSION_TIMEOUT_MS,
|
|
22301
|
+
maxOutputBytes: 64 * 1024,
|
|
22117
22302
|
owner: { bindingId: host.bindingId },
|
|
22118
22303
|
...signal === void 0 ? {} : { signal }
|
|
22119
22304
|
});
|
|
22120
22305
|
} catch (error) {
|
|
22121
|
-
if (error
|
|
22306
|
+
if (isOperationCleanupError(error)) throw error;
|
|
22307
|
+
if (signal?.aborted) throw new ExecutorSpawnAbortedError();
|
|
22308
|
+
if (commandStarted || error instanceof ExecutorSpawnRefusedError || error instanceof ExecutorSpawnAbortedError) {
|
|
22122
22309
|
throw error;
|
|
22123
22310
|
}
|
|
22124
22311
|
const failure = describeExecutorSpawnFailure(error);
|
|
@@ -22130,14 +22317,7 @@ function createClaudeProbe(input) {
|
|
|
22130
22317
|
detail: failure.detail
|
|
22131
22318
|
};
|
|
22132
22319
|
}
|
|
22133
|
-
const
|
|
22134
|
-
Promise.all([
|
|
22135
|
-
collectProcessText(handle.stdout),
|
|
22136
|
-
collectProcessText(handle.stderr),
|
|
22137
|
-
handle.exited
|
|
22138
|
-
]),
|
|
22139
|
-
signal
|
|
22140
|
-
);
|
|
22320
|
+
const { stdout, stderr, exitCode } = command;
|
|
22141
22321
|
if (signal?.aborted) throw new ExecutorSpawnAbortedError();
|
|
22142
22322
|
const version = parseGenericCliVersion(`${stdout}
|
|
22143
22323
|
${stderr}`);
|
|
@@ -22197,49 +22377,29 @@ ${stderr}`);
|
|
|
22197
22377
|
}
|
|
22198
22378
|
var CLAUDE_VERSION_TIMEOUT_MS = 15e3;
|
|
22199
22379
|
async function readClaudeCliVersion(input) {
|
|
22380
|
+
input.signal?.throwIfAborted();
|
|
22200
22381
|
if (input.recipe.binaryPath.length === 0) return null;
|
|
22201
|
-
let handle;
|
|
22202
22382
|
try {
|
|
22203
|
-
|
|
22383
|
+
const { stdout, stderr } = await runProcessOperation(input.host, {
|
|
22204
22384
|
program: input.recipe.binaryPath,
|
|
22205
22385
|
args: ["--version"],
|
|
22206
|
-
owner: { bindingId: input.host.bindingId }
|
|
22386
|
+
owner: { bindingId: input.host.bindingId },
|
|
22387
|
+
signal: input.signal,
|
|
22388
|
+
timeoutMs: CLAUDE_VERSION_TIMEOUT_MS,
|
|
22389
|
+
maxOutputBytes: 64 * 1024
|
|
22207
22390
|
});
|
|
22208
|
-
|
|
22209
|
-
|
|
22210
|
-
|
|
22211
|
-
|
|
22212
|
-
const chunks = [];
|
|
22213
|
-
for await (const chunk of stream) chunks.push(Buffer.from(chunk));
|
|
22214
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
22215
|
-
};
|
|
22216
|
-
const collected = Promise.all([collect(handle.stdout), collect(handle.stderr), handle.exited]);
|
|
22217
|
-
let timer;
|
|
22218
|
-
const timeout = new Promise((resolve5) => {
|
|
22219
|
-
timer = setTimeout(() => resolve5("timeout"), CLAUDE_VERSION_TIMEOUT_MS);
|
|
22220
|
-
timer.unref?.();
|
|
22221
|
-
});
|
|
22222
|
-
try {
|
|
22223
|
-
const settled = await Promise.race([collected, timeout]);
|
|
22224
|
-
if (settled === "timeout") {
|
|
22225
|
-
collected.catch(() => void 0);
|
|
22226
|
-
return null;
|
|
22227
|
-
}
|
|
22228
|
-
const [stdout, stderr] = settled;
|
|
22229
|
-
return parseGenericCliVersion(`${stdout}
|
|
22230
|
-
${stderr}`);
|
|
22231
|
-
} catch {
|
|
22391
|
+
return parseGenericCliVersion(stdout + "\n" + stderr);
|
|
22392
|
+
} catch (error) {
|
|
22393
|
+
if (isOperationCleanupError(error)) throw error;
|
|
22394
|
+
input.signal?.throwIfAborted();
|
|
22232
22395
|
return null;
|
|
22233
|
-
} finally {
|
|
22234
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
22235
|
-
await handle.kill("SIGTERM").catch(() => void 0);
|
|
22236
22396
|
}
|
|
22237
22397
|
}
|
|
22238
22398
|
|
|
22239
22399
|
// src/claudeExecutable.ts
|
|
22240
|
-
import * as
|
|
22400
|
+
import * as NodeFS6 from "node:fs";
|
|
22241
22401
|
import * as NodeOS5 from "node:os";
|
|
22242
|
-
import * as
|
|
22402
|
+
import * as NodePath10 from "node:path";
|
|
22243
22403
|
var WINDOWS_SHIM_EXTENSIONS = /* @__PURE__ */ new Set([".cmd", ".bat", ".ps1"]);
|
|
22244
22404
|
var NPM_PACKAGE_ENTRY_CANDIDATES = [
|
|
22245
22405
|
["node_modules", "@anthropic-ai", "claude-code", "bin", "claude.exe"],
|
|
@@ -22247,7 +22407,7 @@ var NPM_PACKAGE_ENTRY_CANDIDATES = [
|
|
|
22247
22407
|
];
|
|
22248
22408
|
function isExistingFile(filePath) {
|
|
22249
22409
|
try {
|
|
22250
|
-
return
|
|
22410
|
+
return NodeFS6.statSync(filePath).isFile();
|
|
22251
22411
|
} catch {
|
|
22252
22412
|
return false;
|
|
22253
22413
|
}
|
|
@@ -22257,13 +22417,13 @@ function resolveClaudeSdkExecutablePath(binaryPath, environment = process.env, i
|
|
|
22257
22417
|
return binaryPath;
|
|
22258
22418
|
}
|
|
22259
22419
|
const resolved = resolveWindowsExecutable(binaryPath, environment) ?? binaryPath;
|
|
22260
|
-
const extension =
|
|
22420
|
+
const extension = NodePath10.win32.extname(resolved).toLowerCase();
|
|
22261
22421
|
if (!WINDOWS_SHIM_EXTENSIONS.has(extension)) {
|
|
22262
22422
|
return resolved;
|
|
22263
22423
|
}
|
|
22264
|
-
const shimDirectory =
|
|
22424
|
+
const shimDirectory = NodePath10.win32.dirname(resolved);
|
|
22265
22425
|
for (const entrySegments of NPM_PACKAGE_ENTRY_CANDIDATES) {
|
|
22266
|
-
const candidate =
|
|
22426
|
+
const candidate = NodePath10.win32.join(shimDirectory, ...entrySegments);
|
|
22267
22427
|
if (isFile(candidate)) {
|
|
22268
22428
|
return candidate;
|
|
22269
22429
|
}
|
|
@@ -22273,14 +22433,14 @@ function resolveClaudeSdkExecutablePath(binaryPath, environment = process.env, i
|
|
|
22273
22433
|
function resolveWindowsExecutable(binaryPath, environment) {
|
|
22274
22434
|
const trimmed = binaryPath.trim();
|
|
22275
22435
|
if (trimmed.length === 0) return void 0;
|
|
22276
|
-
if (
|
|
22436
|
+
if (NodePath10.win32.isAbsolute(trimmed) && isExistingFile(trimmed)) return trimmed;
|
|
22277
22437
|
const pathValue = environment.PATH ?? environment.Path ?? "";
|
|
22278
22438
|
const pathext = environment.PATHEXT ?? ".EXE;.CMD;.BAT;.COM";
|
|
22279
22439
|
const extensions = pathext.split(";").filter((ext) => ext.length > 0);
|
|
22280
|
-
const hasExt =
|
|
22440
|
+
const hasExt = NodePath10.win32.extname(trimmed).length > 0;
|
|
22281
22441
|
for (const dir of pathValue.split(";")) {
|
|
22282
22442
|
if (dir.trim().length === 0) continue;
|
|
22283
|
-
const candidates = hasExt ? [
|
|
22443
|
+
const candidates = hasExt ? [NodePath10.win32.join(dir, trimmed)] : extensions.map((ext) => NodePath10.win32.join(dir, `${trimmed}${ext}`));
|
|
22284
22444
|
for (const candidate of candidates) {
|
|
22285
22445
|
if (isExistingFile(candidate)) return candidate;
|
|
22286
22446
|
}
|
|
@@ -22330,7 +22490,7 @@ function asStringField(input, key) {
|
|
|
22330
22490
|
const value = input[key];
|
|
22331
22491
|
return typeof value === "string" ? value : void 0;
|
|
22332
22492
|
}
|
|
22333
|
-
function
|
|
22493
|
+
function readString2(value) {
|
|
22334
22494
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
22335
22495
|
}
|
|
22336
22496
|
function readStringArray(value) {
|
|
@@ -22500,14 +22660,14 @@ function readRangeSuffix(input) {
|
|
|
22500
22660
|
function loneStringValue(input) {
|
|
22501
22661
|
let found;
|
|
22502
22662
|
for (const value of Object.values(input)) {
|
|
22503
|
-
const
|
|
22504
|
-
if (
|
|
22663
|
+
const text2 = asTrimmedString(value);
|
|
22664
|
+
if (text2 === void 0) {
|
|
22505
22665
|
continue;
|
|
22506
22666
|
}
|
|
22507
22667
|
if (found !== void 0) {
|
|
22508
22668
|
return void 0;
|
|
22509
22669
|
}
|
|
22510
|
-
found =
|
|
22670
|
+
found = text2;
|
|
22511
22671
|
}
|
|
22512
22672
|
return found;
|
|
22513
22673
|
}
|
|
@@ -23322,11 +23482,11 @@ var makeAssistantText = (emitter) => {
|
|
|
23322
23482
|
blockIndex: block.blockIndex,
|
|
23323
23483
|
block
|
|
23324
23484
|
}));
|
|
23325
|
-
for (const [position,
|
|
23485
|
+
for (const [position, text2] of snapshotTextBlocks.entries()) {
|
|
23326
23486
|
const existingEntry = orderedBlocks[position];
|
|
23327
23487
|
let entry = existingEntry;
|
|
23328
23488
|
if (!entry) {
|
|
23329
|
-
const created = await createSyntheticAssistantTextBlock(context,
|
|
23489
|
+
const created = await createSyntheticAssistantTextBlock(context, text2);
|
|
23330
23490
|
if (created) {
|
|
23331
23491
|
orderedBlocks.push(created);
|
|
23332
23492
|
}
|
|
@@ -23336,7 +23496,7 @@ var makeAssistantText = (emitter) => {
|
|
|
23336
23496
|
continue;
|
|
23337
23497
|
}
|
|
23338
23498
|
if (entry.block.fallbackText.length === 0) {
|
|
23339
|
-
entry.block.fallbackText =
|
|
23499
|
+
entry.block.fallbackText = text2;
|
|
23340
23500
|
}
|
|
23341
23501
|
if (entry.block.streamClosed && !entry.block.completionEmitted) {
|
|
23342
23502
|
await completeAssistantTextBlock(context, entry.block, {
|
|
@@ -23434,8 +23594,8 @@ function applyClaudeTaskToolResult(tasks, tool, result) {
|
|
|
23434
23594
|
continue;
|
|
23435
23595
|
}
|
|
23436
23596
|
const task2 = entry;
|
|
23437
|
-
const id2 =
|
|
23438
|
-
const subject2 =
|
|
23597
|
+
const id2 = readString2(task2.id);
|
|
23598
|
+
const subject2 = readString2(task2.subject);
|
|
23439
23599
|
if (!id2 || !subject2) {
|
|
23440
23600
|
continue;
|
|
23441
23601
|
}
|
|
@@ -23450,8 +23610,8 @@ function applyClaudeTaskToolResult(tasks, tool, result) {
|
|
|
23450
23610
|
}
|
|
23451
23611
|
if (tool.toolName === "TaskCreate") {
|
|
23452
23612
|
const resultTask = readClaudeTaskFromResult(result);
|
|
23453
|
-
const id2 =
|
|
23454
|
-
const subject2 =
|
|
23613
|
+
const id2 = readString2(resultTask?.id);
|
|
23614
|
+
const subject2 = readString2(resultTask?.subject) ?? readString2(tool.input.subject);
|
|
23455
23615
|
if (!id2 || !subject2) {
|
|
23456
23616
|
return false;
|
|
23457
23617
|
}
|
|
@@ -23463,7 +23623,7 @@ function applyClaudeTaskToolResult(tasks, tool, result) {
|
|
|
23463
23623
|
});
|
|
23464
23624
|
return true;
|
|
23465
23625
|
}
|
|
23466
|
-
const taskId =
|
|
23626
|
+
const taskId = readString2(tool.input.taskId) ?? readString2(result?.taskId);
|
|
23467
23627
|
if (!taskId) {
|
|
23468
23628
|
return false;
|
|
23469
23629
|
}
|
|
@@ -23471,7 +23631,7 @@ function applyClaudeTaskToolResult(tasks, tool, result) {
|
|
|
23471
23631
|
if (!task) {
|
|
23472
23632
|
return false;
|
|
23473
23633
|
}
|
|
23474
|
-
const subject =
|
|
23634
|
+
const subject = readString2(tool.input.subject);
|
|
23475
23635
|
if (subject && task.subject !== subject) {
|
|
23476
23636
|
task.subject = subject;
|
|
23477
23637
|
changed = true;
|
|
@@ -23882,23 +24042,23 @@ function tokenizeShellWords(value) {
|
|
|
23882
24042
|
|
|
23883
24043
|
// src/config.ts
|
|
23884
24044
|
var CLAUDE_AUTO_COMPACT_WINDOW_PATTERN = /^(?:|[1-9]\d{5}|1000000)$/;
|
|
23885
|
-
function
|
|
24045
|
+
function isRecord5(value) {
|
|
23886
24046
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23887
24047
|
}
|
|
23888
|
-
function
|
|
24048
|
+
function readString3(value) {
|
|
23889
24049
|
return typeof value === "string" ? value : "";
|
|
23890
24050
|
}
|
|
23891
24051
|
function readTrimmed(value) {
|
|
23892
|
-
return
|
|
24052
|
+
return readString3(value).trim();
|
|
23893
24053
|
}
|
|
23894
24054
|
function readEnvironment(value) {
|
|
23895
24055
|
if (!Array.isArray(value)) return {};
|
|
23896
24056
|
const env2 = {};
|
|
23897
24057
|
for (const entry of value) {
|
|
23898
|
-
if (!
|
|
24058
|
+
if (!isRecord5(entry)) continue;
|
|
23899
24059
|
const name = readTrimmed(entry["name"]);
|
|
23900
24060
|
if (name.length === 0) continue;
|
|
23901
|
-
env2[name] =
|
|
24061
|
+
env2[name] = readString3(entry["value"]);
|
|
23902
24062
|
}
|
|
23903
24063
|
return env2;
|
|
23904
24064
|
}
|
|
@@ -23911,12 +24071,12 @@ function readCustomModels(value) {
|
|
|
23911
24071
|
if (slug2.length > 0) models.push({ slug: slug2 });
|
|
23912
24072
|
continue;
|
|
23913
24073
|
}
|
|
23914
|
-
if (!
|
|
24074
|
+
if (!isRecord5(entry)) continue;
|
|
23915
24075
|
const slug = readTrimmed(entry["slug"]);
|
|
23916
24076
|
if (slug.length === 0) continue;
|
|
23917
24077
|
const thinkingRaw = entry["thinkingOptions"];
|
|
23918
24078
|
const thinkingOptions = Array.isArray(thinkingRaw) ? thinkingRaw.flatMap((option) => {
|
|
23919
|
-
if (!
|
|
24079
|
+
if (!isRecord5(option)) return [];
|
|
23920
24080
|
const id2 = readTrimmed(option["id"]) || readTrimmed(option["value"]);
|
|
23921
24081
|
const label = readTrimmed(option["label"]) || id2;
|
|
23922
24082
|
if (id2.length === 0) return [];
|
|
@@ -23949,7 +24109,7 @@ function readAutoCompactWindow(value) {
|
|
|
23949
24109
|
return CLAUDE_AUTO_COMPACT_WINDOW_PATTERN.test(trimmed) ? trimmed : "";
|
|
23950
24110
|
}
|
|
23951
24111
|
function parseClaudeInstanceConfig(config) {
|
|
23952
|
-
if (!
|
|
24112
|
+
if (!isRecord5(config)) {
|
|
23953
24113
|
return {
|
|
23954
24114
|
binaryPath: "",
|
|
23955
24115
|
homePath: "",
|
|
@@ -23962,13 +24122,13 @@ function parseClaudeInstanceConfig(config) {
|
|
|
23962
24122
|
envelopeDriver: void 0
|
|
23963
24123
|
};
|
|
23964
24124
|
}
|
|
23965
|
-
const nested =
|
|
24125
|
+
const nested = isRecord5(config["config"]) ? config["config"] : void 0;
|
|
23966
24126
|
const settings = nested ?? config;
|
|
23967
24127
|
return {
|
|
23968
24128
|
binaryPath: readTrimmed(settings["binaryPath"]),
|
|
23969
24129
|
homePath: readTrimmed(settings["homePath"]) || readTrimmed(config["homePath"]),
|
|
23970
24130
|
credentialsPath: readTrimmed(settings["credentialsPath"]) || readTrimmed(config["credentialsPath"]),
|
|
23971
|
-
launchArgs:
|
|
24131
|
+
launchArgs: readString3(settings["launchArgs"]),
|
|
23972
24132
|
autoCompactWindow: readAutoCompactWindow(settings["autoCompactWindow"]),
|
|
23973
24133
|
customModels: readCustomModels(settings["customModels"]),
|
|
23974
24134
|
enabled: settings["enabled"] !== false,
|
|
@@ -24017,91 +24177,295 @@ function parseCliArgs(args, options) {
|
|
|
24017
24177
|
return { flags, positionals, variadicArgs };
|
|
24018
24178
|
}
|
|
24019
24179
|
|
|
24180
|
+
// src/adapter/modelCatalog.ts
|
|
24181
|
+
import {
|
|
24182
|
+
raceAbort
|
|
24183
|
+
} from "@ycodium-ai/plugin-api/executor";
|
|
24184
|
+
|
|
24020
24185
|
// src/sdkModels.ts
|
|
24021
24186
|
import * as NodeOS6 from "node:os";
|
|
24022
24187
|
import { REASONING_OPTION_LABEL as REASONING_OPTION_LABEL2, reasoningEffortShortLabel } from "@ycodium-ai/plugin-api/executor";
|
|
24023
|
-
|
|
24024
|
-
|
|
24025
|
-
|
|
24026
|
-
var
|
|
24027
|
-
|
|
24028
|
-
|
|
24029
|
-
|
|
24030
|
-
|
|
24031
|
-
|
|
24032
|
-
|
|
24033
|
-
|
|
24034
|
-
|
|
24035
|
-
|
|
24036
|
-
|
|
24037
|
-
|
|
24038
|
-
|
|
24039
|
-
|
|
24188
|
+
import { OperationCleanupError } from "@ycodium-ai/plugin-api/process-operation";
|
|
24189
|
+
|
|
24190
|
+
// src/sdkAccount.ts
|
|
24191
|
+
var text = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
24192
|
+
function claudeAuthFromSdk(value) {
|
|
24193
|
+
if (value === void 0) return void 0;
|
|
24194
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
24195
|
+
return { status: "unknown" };
|
|
24196
|
+
const account = value;
|
|
24197
|
+
const token = text(account.tokenSource);
|
|
24198
|
+
const key = text(account.apiKeySource);
|
|
24199
|
+
const hasToken = token !== void 0 && token !== "none";
|
|
24200
|
+
const hasKey = key !== void 0 && key !== "none";
|
|
24201
|
+
if (hasToken || hasKey) {
|
|
24202
|
+
const email2 = text(account.email);
|
|
24203
|
+
const label2 = text(account.subscriptionType) ?? text(account.organization);
|
|
24204
|
+
return {
|
|
24205
|
+
status: "authenticated",
|
|
24206
|
+
type: hasToken ? "oauth" : "api-key",
|
|
24207
|
+
...email2 === void 0 ? {} : { email: email2 },
|
|
24208
|
+
...label2 === void 0 ? {} : { label: label2 }
|
|
24209
|
+
};
|
|
24040
24210
|
}
|
|
24041
|
-
|
|
24042
|
-
|
|
24043
|
-
|
|
24044
|
-
|
|
24045
|
-
|
|
24046
|
-
|
|
24047
|
-
|
|
24048
|
-
|
|
24049
|
-
const seen = /* @__PURE__ */ new Set();
|
|
24050
|
-
const out = [];
|
|
24051
|
-
for (const info of models) {
|
|
24052
|
-
if (typeof info.value !== "string" || info.value.trim().length === 0) continue;
|
|
24053
|
-
if (seen.has(info.value)) continue;
|
|
24054
|
-
seen.add(info.value);
|
|
24055
|
-
out.push(claudeCatalogModelFromSdk(info));
|
|
24211
|
+
const provider = text(account.apiProvider);
|
|
24212
|
+
if (provider !== void 0 && provider !== "firstParty")
|
|
24213
|
+
return { status: "unknown", type: provider };
|
|
24214
|
+
if (token === "none" && key === "none") return { status: "unauthenticated" };
|
|
24215
|
+
const email = text(account.email);
|
|
24216
|
+
const label = text(account.subscriptionType);
|
|
24217
|
+
if (provider === "firstParty" && email !== void 0) {
|
|
24218
|
+
return { status: "authenticated", email, ...label === void 0 ? {} : { label } };
|
|
24056
24219
|
}
|
|
24057
|
-
return
|
|
24058
|
-
}
|
|
24059
|
-
|
|
24060
|
-
|
|
24061
|
-
|
|
24062
|
-
|
|
24063
|
-
|
|
24064
|
-
|
|
24065
|
-
|
|
24066
|
-
|
|
24067
|
-
|
|
24068
|
-
|
|
24069
|
-
|
|
24070
|
-
|
|
24071
|
-
|
|
24072
|
-
|
|
24073
|
-
|
|
24074
|
-
|
|
24075
|
-
|
|
24076
|
-
|
|
24077
|
-
|
|
24078
|
-
|
|
24079
|
-
|
|
24080
|
-
|
|
24081
|
-
|
|
24082
|
-
|
|
24083
|
-
|
|
24084
|
-
|
|
24085
|
-
|
|
24086
|
-
|
|
24087
|
-
|
|
24088
|
-
|
|
24089
|
-
|
|
24090
|
-
|
|
24091
|
-
});
|
|
24092
|
-
|
|
24093
|
-
|
|
24094
|
-
|
|
24095
|
-
|
|
24096
|
-
|
|
24097
|
-
|
|
24098
|
-
|
|
24099
|
-
|
|
24100
|
-
|
|
24101
|
-
|
|
24102
|
-
|
|
24103
|
-
}
|
|
24220
|
+
return { status: "unknown" };
|
|
24221
|
+
}
|
|
24222
|
+
|
|
24223
|
+
// src/sdkRead.ts
|
|
24224
|
+
import { withProcessOperation } from "@ycodium-ai/plugin-api/process-operation";
|
|
24225
|
+
|
|
24226
|
+
// src/claudeProcess.ts
|
|
24227
|
+
import * as NodeEvents from "node:events";
|
|
24228
|
+
import * as NodeStream from "node:stream";
|
|
24229
|
+
import { adoptChildStdin, nodeWritableFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
|
|
24230
|
+
var asError = (cause) => cause instanceof Error ? cause : new Error(String(cause));
|
|
24231
|
+
var ClaudeProcess = class extends NodeEvents.EventEmitter {
|
|
24232
|
+
stdin;
|
|
24233
|
+
stdout;
|
|
24234
|
+
killed = false;
|
|
24235
|
+
exitCode = null;
|
|
24236
|
+
handle;
|
|
24237
|
+
ended = false;
|
|
24238
|
+
constructor(host, options, stderr, cleanup) {
|
|
24239
|
+
super();
|
|
24240
|
+
const env2 = {
|
|
24241
|
+
...Object.fromEntries(Object.keys(process.env).map((key) => [key, void 0])),
|
|
24242
|
+
...options.env
|
|
24243
|
+
};
|
|
24244
|
+
const ready = host.process.spawn({
|
|
24245
|
+
program: options.command,
|
|
24246
|
+
args: options.args,
|
|
24247
|
+
...options.cwd === void 0 ? {} : { cwd: options.cwd },
|
|
24248
|
+
env: env2,
|
|
24249
|
+
owner: { bindingId: host.bindingId }
|
|
24250
|
+
});
|
|
24251
|
+
this.stdin = nodeWritableFromHandle({
|
|
24252
|
+
writeStdin: (chunk) => ready.then((handle) => handle.writeStdin(chunk)),
|
|
24253
|
+
closeStdin: () => ready.then((handle) => handle.closeStdin())
|
|
24254
|
+
});
|
|
24255
|
+
this.stdout = NodeStream.Readable.from(
|
|
24256
|
+
(async function* () {
|
|
24257
|
+
const handle = await ready.catch(() => void 0);
|
|
24258
|
+
if (handle) yield* handle.stdout;
|
|
24259
|
+
})(),
|
|
24260
|
+
{ objectMode: false }
|
|
24261
|
+
);
|
|
24262
|
+
adoptChildStdin(this.stdin, {
|
|
24263
|
+
onError: (error) => {
|
|
24264
|
+
this.emit("error", error);
|
|
24265
|
+
}
|
|
24266
|
+
});
|
|
24267
|
+
this.stdout.on("error", (error) => this.emit("error", error));
|
|
24268
|
+
this.requestKill = (signal) => {
|
|
24269
|
+
void ready.then((handle) => this.ended ? void 0 : handle.kill(signal)).catch((cause) => this.emit("error", asError(cause)));
|
|
24270
|
+
};
|
|
24271
|
+
const abort = () => {
|
|
24272
|
+
this.kill("SIGTERM");
|
|
24273
|
+
};
|
|
24274
|
+
options.signal.addEventListener("abort", abort, { once: true });
|
|
24275
|
+
if (options.signal.aborted) abort();
|
|
24276
|
+
void ready.then(async (handle) => {
|
|
24277
|
+
this.handle = handle;
|
|
24278
|
+
const drainStderr = (async () => {
|
|
24279
|
+
const decoder = new TextDecoder();
|
|
24280
|
+
for await (const chunk of handle.stderr) stderr(decoder.decode(chunk, { stream: true }));
|
|
24281
|
+
const tail = decoder.decode();
|
|
24282
|
+
if (tail) stderr(tail);
|
|
24283
|
+
})();
|
|
24284
|
+
void drainStderr.catch((cause) => this.emit("error", asError(cause)));
|
|
24285
|
+
try {
|
|
24286
|
+
const code = await handle.exited;
|
|
24287
|
+
this.ended = true;
|
|
24288
|
+
this.handle = void 0;
|
|
24289
|
+
this.exitCode = code;
|
|
24290
|
+
await cleanup();
|
|
24291
|
+
this.emit("exit", code, null);
|
|
24292
|
+
} finally {
|
|
24293
|
+
options.signal.removeEventListener("abort", abort);
|
|
24294
|
+
}
|
|
24295
|
+
}).catch(async (cause) => {
|
|
24296
|
+
this.ended = true;
|
|
24297
|
+
this.handle = void 0;
|
|
24298
|
+
options.signal.removeEventListener("abort", abort);
|
|
24299
|
+
await cleanup();
|
|
24300
|
+
this.emit("error", asError(cause));
|
|
24301
|
+
});
|
|
24302
|
+
}
|
|
24303
|
+
requestKill;
|
|
24304
|
+
kill(signal) {
|
|
24305
|
+
if (this.ended || signal !== "SIGTERM" && signal !== "SIGKILL") return false;
|
|
24306
|
+
this.killed = true;
|
|
24307
|
+
this.requestKill(signal);
|
|
24308
|
+
return true;
|
|
24309
|
+
}
|
|
24310
|
+
};
|
|
24311
|
+
function makeClaudeProcessSpawner(host, stderr, config = {}) {
|
|
24312
|
+
const cleanup = config.cleanup ?? (async () => {
|
|
24313
|
+
});
|
|
24314
|
+
let process2;
|
|
24315
|
+
let launch;
|
|
24316
|
+
return {
|
|
24317
|
+
spawn: (options) => {
|
|
24318
|
+
const args = [...options.args, ...config.mcpConfigArgs ?? []];
|
|
24319
|
+
if (config.mcpConfigPath !== void 0) {
|
|
24320
|
+
const flag = args.findLastIndex(
|
|
24321
|
+
(arg) => arg === "--mcp-config" || arg.startsWith("--mcp-config=")
|
|
24322
|
+
);
|
|
24323
|
+
if (flag === -1) args.push("--mcp-config", config.mcpConfigPath);
|
|
24324
|
+
else {
|
|
24325
|
+
let end = flag + 1;
|
|
24326
|
+
while (end < args.length && !args[end].startsWith("-")) end++;
|
|
24327
|
+
args.splice(end, 0, config.mcpConfigPath);
|
|
24328
|
+
}
|
|
24329
|
+
}
|
|
24330
|
+
launch = { ...options, args };
|
|
24331
|
+
process2 = new ClaudeProcess(host, launch, stderr, cleanup);
|
|
24332
|
+
return process2;
|
|
24333
|
+
},
|
|
24334
|
+
current: () => process2?.handle && launch ? { handle: process2.handle, command: launch.command, args: launch.args } : void 0,
|
|
24335
|
+
clear: () => {
|
|
24336
|
+
process2 = void 0;
|
|
24337
|
+
launch = void 0;
|
|
24338
|
+
return cleanup();
|
|
24339
|
+
}
|
|
24340
|
+
};
|
|
24341
|
+
}
|
|
24342
|
+
|
|
24343
|
+
// src/sdkRead.ts
|
|
24344
|
+
var silentPrompt = (signal) => ({
|
|
24345
|
+
[Symbol.asyncIterator]: () => ({
|
|
24346
|
+
next: () => new Promise((resolve5) => {
|
|
24347
|
+
if (signal.aborted) {
|
|
24348
|
+
resolve5({ done: true, value: void 0 });
|
|
24349
|
+
return;
|
|
24350
|
+
}
|
|
24351
|
+
signal.addEventListener("abort", () => resolve5({ done: true, value: void 0 }), {
|
|
24352
|
+
once: true
|
|
24353
|
+
});
|
|
24354
|
+
}),
|
|
24355
|
+
return: async () => ({ done: true, value: void 0 })
|
|
24356
|
+
})
|
|
24357
|
+
});
|
|
24358
|
+
async function withClaudeSdkRead(input, read) {
|
|
24359
|
+
return withProcessOperation(
|
|
24360
|
+
input.host,
|
|
24361
|
+
{
|
|
24362
|
+
signal: input.signal,
|
|
24363
|
+
timeoutMs: input.timeoutMs ?? 2e4
|
|
24364
|
+
},
|
|
24365
|
+
async (operation) => {
|
|
24366
|
+
const processHost = {
|
|
24367
|
+
...input.host,
|
|
24368
|
+
process: {
|
|
24369
|
+
spawn: (options) => operation.spawn(options).then(
|
|
24370
|
+
(handle) => input.stdin === void 0 ? handle : {
|
|
24371
|
+
...handle,
|
|
24372
|
+
writeStdin: input.stdin(handle.writeStdin)
|
|
24373
|
+
}
|
|
24374
|
+
)
|
|
24375
|
+
}
|
|
24376
|
+
};
|
|
24377
|
+
const spawner = makeClaudeProcessSpawner(processHost, () => {
|
|
24378
|
+
});
|
|
24379
|
+
operation.defer(() => spawner.clear());
|
|
24380
|
+
const flags = input.options.extraArgs ?? {};
|
|
24381
|
+
if (["resume", "continue", "fork-session", "session-id", "prompt", "print"].some(
|
|
24382
|
+
(key) => key in flags
|
|
24383
|
+
)) {
|
|
24384
|
+
throw new Error("Read-only SDK queries cannot resume a session");
|
|
24385
|
+
}
|
|
24386
|
+
const runtime = input.createQuery({
|
|
24387
|
+
prompt: silentPrompt(operation.signal),
|
|
24388
|
+
options: {
|
|
24389
|
+
...input.options,
|
|
24390
|
+
persistSession: false,
|
|
24391
|
+
tools: [],
|
|
24392
|
+
mcpServers: {},
|
|
24393
|
+
strictMcpConfig: true,
|
|
24394
|
+
extraArgs: {
|
|
24395
|
+
...flags,
|
|
24396
|
+
"no-session-persistence": null,
|
|
24397
|
+
tools: "",
|
|
24398
|
+
"mcp-config": JSON.stringify({ mcpServers: {} }),
|
|
24399
|
+
"strict-mcp-config": null,
|
|
24400
|
+
"disable-slash-commands": null
|
|
24401
|
+
},
|
|
24402
|
+
abortController: operation.abortController,
|
|
24403
|
+
spawnClaudeCodeProcess: spawner.spawn
|
|
24404
|
+
}
|
|
24405
|
+
});
|
|
24406
|
+
operation.defer(() => runtime.close());
|
|
24407
|
+
return operation.track(read(runtime));
|
|
24104
24408
|
}
|
|
24409
|
+
);
|
|
24410
|
+
}
|
|
24411
|
+
|
|
24412
|
+
// src/sdkModels.ts
|
|
24413
|
+
var CLAUDE_SDK_MODELS_TIMEOUT_MS = 2e4;
|
|
24414
|
+
var CLAUDE_SDK_MODELS_TTL_MS = 30 * 6e4;
|
|
24415
|
+
var CLAUDE_SDK_MODELS_RETRY_MS = 2 * 6e4;
|
|
24416
|
+
var effortLabel = (level) => reasoningEffortShortLabel(level) ?? `${level.slice(0, 1).toUpperCase()}${level.slice(1)}`;
|
|
24417
|
+
var claudeCatalogModelFromSdk = (info) => {
|
|
24418
|
+
const descriptors = [];
|
|
24419
|
+
const levels = info.supportsEffort === false ? [] : info.supportedEffortLevels ?? [];
|
|
24420
|
+
if (levels.length > 0) {
|
|
24421
|
+
descriptors.push({
|
|
24422
|
+
type: "select",
|
|
24423
|
+
id: "effort",
|
|
24424
|
+
label: REASONING_OPTION_LABEL2,
|
|
24425
|
+
options: levels.map((level) => ({ id: level, label: effortLabel(level) }))
|
|
24426
|
+
});
|
|
24427
|
+
}
|
|
24428
|
+
if (info.supportsFastMode === true) {
|
|
24429
|
+
descriptors.push({ type: "boolean", id: "fastMode", label: "Fast Mode" });
|
|
24430
|
+
}
|
|
24431
|
+
return {
|
|
24432
|
+
slug: info.value,
|
|
24433
|
+
name: info.displayName.trim().length > 0 ? info.displayName : info.value,
|
|
24434
|
+
isCustom: false,
|
|
24435
|
+
capabilities: { optionDescriptors: descriptors }
|
|
24436
|
+
};
|
|
24437
|
+
};
|
|
24438
|
+
var claudeCatalogFromSdk = (models) => {
|
|
24439
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24440
|
+
const out = [];
|
|
24441
|
+
for (const info of models) {
|
|
24442
|
+
if (typeof info.value !== "string" || info.value.trim().length === 0) continue;
|
|
24443
|
+
if (seen.has(info.value)) continue;
|
|
24444
|
+
seen.add(info.value);
|
|
24445
|
+
out.push(claudeCatalogModelFromSdk(info));
|
|
24446
|
+
}
|
|
24447
|
+
return out;
|
|
24448
|
+
};
|
|
24449
|
+
var readClaudeSdkProbe = async (input) => {
|
|
24450
|
+
try {
|
|
24451
|
+
return await withClaudeSdkRead(
|
|
24452
|
+
{
|
|
24453
|
+
...input,
|
|
24454
|
+
timeoutMs: input.timeoutMs ?? CLAUDE_SDK_MODELS_TIMEOUT_MS
|
|
24455
|
+
},
|
|
24456
|
+
async (runtime) => {
|
|
24457
|
+
if (runtime.supportedModels === void 0) throw new Error("SDK model probe unavailable");
|
|
24458
|
+
const [models, account] = await Promise.all([
|
|
24459
|
+
runtime.supportedModels(),
|
|
24460
|
+
runtime.accountInfo?.()
|
|
24461
|
+
]);
|
|
24462
|
+
return { models, auth: claudeAuthFromSdk(account) };
|
|
24463
|
+
}
|
|
24464
|
+
);
|
|
24465
|
+
} catch (cause) {
|
|
24466
|
+
if (cause instanceof OperationCleanupError) throw cause;
|
|
24467
|
+
input.signal?.throwIfAborted();
|
|
24468
|
+
return void 0;
|
|
24105
24469
|
}
|
|
24106
24470
|
};
|
|
24107
24471
|
function claudeModelProbeEnvironment(environment) {
|
|
@@ -24134,10 +24498,12 @@ var makeClaudeModelCatalog = (deps) => {
|
|
|
24134
24498
|
let modelCatalogRead;
|
|
24135
24499
|
let modelCatalogFailedAt;
|
|
24136
24500
|
let catalogReadOk = false;
|
|
24501
|
+
let auth;
|
|
24137
24502
|
let successfulReadAt;
|
|
24138
24503
|
let skipPairedRefresh = false;
|
|
24139
24504
|
const current = () => modelCatalog?.models ?? [];
|
|
24140
24505
|
const refresh = (input) => {
|
|
24506
|
+
input?.signal?.throwIfAborted();
|
|
24141
24507
|
if (input?.paired === true && skipPairedRefresh) {
|
|
24142
24508
|
skipPairedRefresh = false;
|
|
24143
24509
|
return Promise.resolve();
|
|
@@ -24151,10 +24517,11 @@ var makeClaudeModelCatalog = (deps) => {
|
|
|
24151
24517
|
catalogReadOk = false;
|
|
24152
24518
|
return Promise.resolve();
|
|
24153
24519
|
}
|
|
24154
|
-
if (modelCatalogRead !== void 0) return modelCatalogRead;
|
|
24520
|
+
if (modelCatalogRead !== void 0) return raceAbort(modelCatalogRead, input?.signal);
|
|
24155
24521
|
const read = (async () => {
|
|
24156
24522
|
const extraArgs = parseCliArgs(deps.recipe.launchArgs).flags;
|
|
24157
|
-
const
|
|
24523
|
+
const probe = await readClaudeSdkProbe({
|
|
24524
|
+
host: deps.host,
|
|
24158
24525
|
createQuery: deps.createQuery,
|
|
24159
24526
|
signal: input?.signal,
|
|
24160
24527
|
options: {
|
|
@@ -24165,7 +24532,9 @@ var makeClaudeModelCatalog = (deps) => {
|
|
|
24165
24532
|
...Object.keys(extraArgs).length > 0 ? { extraArgs } : {}
|
|
24166
24533
|
}
|
|
24167
24534
|
});
|
|
24168
|
-
|
|
24535
|
+
input?.signal?.throwIfAborted();
|
|
24536
|
+
auth = probe?.auth;
|
|
24537
|
+
if (probe === void 0) {
|
|
24169
24538
|
modelCatalogFailedAt = deps.now();
|
|
24170
24539
|
catalogReadOk = false;
|
|
24171
24540
|
successfulReadAt = void 0;
|
|
@@ -24174,7 +24543,7 @@ var makeClaudeModelCatalog = (deps) => {
|
|
|
24174
24543
|
modelCatalogFailedAt = void 0;
|
|
24175
24544
|
catalogReadOk = true;
|
|
24176
24545
|
successfulReadAt = readAt;
|
|
24177
|
-
modelCatalog = { models: claudeCatalogFromSdk(models), readAt };
|
|
24546
|
+
modelCatalog = { models: claudeCatalogFromSdk(probe.models), readAt };
|
|
24178
24547
|
}
|
|
24179
24548
|
})().finally(() => {
|
|
24180
24549
|
modelCatalogRead = void 0;
|
|
@@ -24184,6 +24553,7 @@ var makeClaudeModelCatalog = (deps) => {
|
|
|
24184
24553
|
};
|
|
24185
24554
|
return {
|
|
24186
24555
|
current,
|
|
24556
|
+
currentAuth: () => catalogReadOk ? auth : void 0,
|
|
24187
24557
|
refresh,
|
|
24188
24558
|
/** 此刻正在进行的那次读取;没有就是 undefined。起会话等它读完,不为此另起一次。 */
|
|
24189
24559
|
pendingRead: () => modelCatalogRead,
|
|
@@ -24319,8 +24689,8 @@ var SKILL_TOKEN_REGEX = new RegExp(
|
|
|
24319
24689
|
String.raw`(^|\s)([$/])(${SKILL_TOKEN_NAME_PATTERN})(?=\s|$)`,
|
|
24320
24690
|
"g"
|
|
24321
24691
|
);
|
|
24322
|
-
function findSkillTokens(
|
|
24323
|
-
return [...
|
|
24692
|
+
function findSkillTokens(text2) {
|
|
24693
|
+
return [...text2.matchAll(SKILL_TOKEN_REGEX)].map((match) => {
|
|
24324
24694
|
const start = (match.index ?? 0) + (match[1]?.length ?? 0);
|
|
24325
24695
|
const name = match[3] ?? "";
|
|
24326
24696
|
return { sigil: match[2], name, start, end: start + name.length + 1 };
|
|
@@ -24341,9 +24711,9 @@ function lookupSkill(name, index) {
|
|
|
24341
24711
|
return session?.scope === SESSION_SKILL_NAMESPACE ? session : void 0;
|
|
24342
24712
|
}
|
|
24343
24713
|
var SLASH_SKILL_TOKEN = new RegExp(String.raw`^/(${SKILL_TOKEN_NAME_PATTERN})$`);
|
|
24344
|
-
function matchSkillTokens(
|
|
24714
|
+
function matchSkillTokens(text2, index) {
|
|
24345
24715
|
if (index.size === 0) return [];
|
|
24346
|
-
return findSkillTokens(
|
|
24716
|
+
return findSkillTokens(text2).flatMap((token) => {
|
|
24347
24717
|
const skill = lookupSkill(token.name, index);
|
|
24348
24718
|
return skill === void 0 ? [] : [{ ...token, skill }];
|
|
24349
24719
|
});
|
|
@@ -24357,7 +24727,7 @@ import { EXECUTOR_SEND_TURN_MAX_INPUT_CHARS as EXECUTOR_SEND_TURN_MAX_INPUT_CHAR
|
|
|
24357
24727
|
|
|
24358
24728
|
// src/claudeInlineSkill.ts
|
|
24359
24729
|
import * as NodeFSP4 from "node:fs/promises";
|
|
24360
|
-
import * as
|
|
24730
|
+
import * as NodePath11 from "node:path";
|
|
24361
24731
|
import { EXECUTOR_SEND_TURN_MAX_INPUT_CHARS } from "@ycodium-ai/plugin-api/executor";
|
|
24362
24732
|
|
|
24363
24733
|
// src/claudeSkillArguments.ts
|
|
@@ -24468,7 +24838,7 @@ var notLoadedBlock = (name, reason) => skillBlock(name, [
|
|
|
24468
24838
|
`The user invoked the skill "${name}" in this message, but it could not be included: ${reason}. It is not applied; don't assume its instructions.`
|
|
24469
24839
|
]);
|
|
24470
24840
|
var renderLoaded = (invocation, source, variables) => {
|
|
24471
|
-
const skillDir =
|
|
24841
|
+
const skillDir = NodePath11.dirname(invocation.path);
|
|
24472
24842
|
const known = {
|
|
24473
24843
|
CLAUDE_SKILL_DIR: skillDir,
|
|
24474
24844
|
CLAUDE_PROJECT_DIR: variables.projectDir,
|
|
@@ -24619,14 +24989,14 @@ function assertSteeringTarget(expectedTurnId, turnState) {
|
|
|
24619
24989
|
}
|
|
24620
24990
|
|
|
24621
24991
|
// src/hostMcpAllowRules.ts
|
|
24622
|
-
import { setsOwnModelConnection } from "@ycodium-ai/plugin-api/executor";
|
|
24992
|
+
import { setsOwnModelConnection as setsOwnModelConnection2 } from "@ycodium-ai/plugin-api/executor";
|
|
24623
24993
|
function claudeHostMcpAllowRules(servers) {
|
|
24624
24994
|
return (servers ?? []).filter((server) => server.hostOwned === true).map((server) => `mcp__${server.name}`);
|
|
24625
24995
|
}
|
|
24626
24996
|
function claudeUsesOfficialChannel(env2) {
|
|
24627
24997
|
const connectivity = CLAUDE_CARD.modelConnectivity;
|
|
24628
24998
|
const rows = Object.entries(env2).map(([name, value]) => ({ name, value }));
|
|
24629
|
-
if (
|
|
24999
|
+
if (setsOwnModelConnection2({ backendSwitchEnvKeys: connectivity?.backendSwitchEnvKeys }, rows))
|
|
24630
25000
|
return false;
|
|
24631
25001
|
const key = connectivity?.baseUrlEnvKey;
|
|
24632
25002
|
const baseUrl = key === void 0 ? void 0 : env2[key]?.trim();
|
|
@@ -25649,127 +26019,10 @@ var makeSessionLifecycle = (deps) => {
|
|
|
25649
26019
|
};
|
|
25650
26020
|
};
|
|
25651
26021
|
|
|
25652
|
-
// src/claudeProcess.ts
|
|
25653
|
-
import * as NodeEvents from "node:events";
|
|
25654
|
-
import * as NodeStream from "node:stream";
|
|
25655
|
-
import { adoptChildStdin, nodeWritableFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
|
|
25656
|
-
var asError = (cause) => cause instanceof Error ? cause : new Error(String(cause));
|
|
25657
|
-
var ClaudeProcess = class extends NodeEvents.EventEmitter {
|
|
25658
|
-
stdin;
|
|
25659
|
-
stdout;
|
|
25660
|
-
killed = false;
|
|
25661
|
-
exitCode = null;
|
|
25662
|
-
handle;
|
|
25663
|
-
ended = false;
|
|
25664
|
-
constructor(host, options, stderr, cleanup) {
|
|
25665
|
-
super();
|
|
25666
|
-
const env2 = {
|
|
25667
|
-
...Object.fromEntries(Object.keys(process.env).map((key) => [key, void 0])),
|
|
25668
|
-
...options.env
|
|
25669
|
-
};
|
|
25670
|
-
const ready = host.process.spawn({
|
|
25671
|
-
program: options.command,
|
|
25672
|
-
args: options.args,
|
|
25673
|
-
...options.cwd === void 0 ? {} : { cwd: options.cwd },
|
|
25674
|
-
env: env2,
|
|
25675
|
-
owner: { bindingId: host.bindingId }
|
|
25676
|
-
});
|
|
25677
|
-
this.stdin = nodeWritableFromHandle({
|
|
25678
|
-
writeStdin: (chunk) => ready.then((handle) => handle.writeStdin(chunk)),
|
|
25679
|
-
closeStdin: () => ready.then((handle) => handle.closeStdin())
|
|
25680
|
-
});
|
|
25681
|
-
this.stdout = NodeStream.Readable.from(
|
|
25682
|
-
(async function* () {
|
|
25683
|
-
const handle = await ready.catch(() => void 0);
|
|
25684
|
-
if (handle) yield* handle.stdout;
|
|
25685
|
-
})(),
|
|
25686
|
-
{ objectMode: false }
|
|
25687
|
-
);
|
|
25688
|
-
adoptChildStdin(this.stdin, {
|
|
25689
|
-
onError: (error) => {
|
|
25690
|
-
this.emit("error", error);
|
|
25691
|
-
}
|
|
25692
|
-
});
|
|
25693
|
-
this.stdout.on("error", (error) => this.emit("error", error));
|
|
25694
|
-
this.requestKill = (signal) => {
|
|
25695
|
-
void ready.then((handle) => this.ended ? void 0 : handle.kill(signal)).catch((cause) => this.emit("error", asError(cause)));
|
|
25696
|
-
};
|
|
25697
|
-
const abort = () => {
|
|
25698
|
-
this.kill("SIGTERM");
|
|
25699
|
-
};
|
|
25700
|
-
options.signal.addEventListener("abort", abort, { once: true });
|
|
25701
|
-
if (options.signal.aborted) abort();
|
|
25702
|
-
void ready.then(async (handle) => {
|
|
25703
|
-
this.handle = handle;
|
|
25704
|
-
const drainStderr = (async () => {
|
|
25705
|
-
const decoder = new TextDecoder();
|
|
25706
|
-
for await (const chunk of handle.stderr) stderr(decoder.decode(chunk, { stream: true }));
|
|
25707
|
-
const tail = decoder.decode();
|
|
25708
|
-
if (tail) stderr(tail);
|
|
25709
|
-
})();
|
|
25710
|
-
void drainStderr.catch((cause) => this.emit("error", asError(cause)));
|
|
25711
|
-
try {
|
|
25712
|
-
const code = await handle.exited;
|
|
25713
|
-
this.ended = true;
|
|
25714
|
-
this.handle = void 0;
|
|
25715
|
-
this.exitCode = code;
|
|
25716
|
-
await cleanup();
|
|
25717
|
-
this.emit("exit", code, null);
|
|
25718
|
-
} finally {
|
|
25719
|
-
options.signal.removeEventListener("abort", abort);
|
|
25720
|
-
}
|
|
25721
|
-
}).catch(async (cause) => {
|
|
25722
|
-
this.ended = true;
|
|
25723
|
-
this.handle = void 0;
|
|
25724
|
-
options.signal.removeEventListener("abort", abort);
|
|
25725
|
-
await cleanup();
|
|
25726
|
-
this.emit("error", asError(cause));
|
|
25727
|
-
});
|
|
25728
|
-
}
|
|
25729
|
-
requestKill;
|
|
25730
|
-
kill(signal) {
|
|
25731
|
-
if (this.ended || signal !== "SIGTERM" && signal !== "SIGKILL") return false;
|
|
25732
|
-
this.killed = true;
|
|
25733
|
-
this.requestKill(signal);
|
|
25734
|
-
return true;
|
|
25735
|
-
}
|
|
25736
|
-
};
|
|
25737
|
-
function makeClaudeProcessSpawner(host, stderr, config = {}) {
|
|
25738
|
-
const cleanup = config.cleanup ?? (async () => {
|
|
25739
|
-
});
|
|
25740
|
-
let process2;
|
|
25741
|
-
let launch;
|
|
25742
|
-
return {
|
|
25743
|
-
spawn: (options) => {
|
|
25744
|
-
const args = [...options.args, ...config.mcpConfigArgs ?? []];
|
|
25745
|
-
if (config.mcpConfigPath !== void 0) {
|
|
25746
|
-
const flag = args.findLastIndex(
|
|
25747
|
-
(arg) => arg === "--mcp-config" || arg.startsWith("--mcp-config=")
|
|
25748
|
-
);
|
|
25749
|
-
if (flag === -1) args.push("--mcp-config", config.mcpConfigPath);
|
|
25750
|
-
else {
|
|
25751
|
-
let end = flag + 1;
|
|
25752
|
-
while (end < args.length && !args[end].startsWith("-")) end++;
|
|
25753
|
-
args.splice(end, 0, config.mcpConfigPath);
|
|
25754
|
-
}
|
|
25755
|
-
}
|
|
25756
|
-
launch = { ...options, args };
|
|
25757
|
-
process2 = new ClaudeProcess(host, launch, stderr, cleanup);
|
|
25758
|
-
return process2;
|
|
25759
|
-
},
|
|
25760
|
-
current: () => process2?.handle && launch ? { handle: process2.handle, command: launch.command, args: launch.args } : void 0,
|
|
25761
|
-
clear: () => {
|
|
25762
|
-
process2 = void 0;
|
|
25763
|
-
launch = void 0;
|
|
25764
|
-
return cleanup();
|
|
25765
|
-
}
|
|
25766
|
-
};
|
|
25767
|
-
}
|
|
25768
|
-
|
|
25769
26022
|
// src/claudeMcpConfig.ts
|
|
25770
26023
|
import * as NodeFSP5 from "node:fs/promises";
|
|
25771
26024
|
import * as NodeOS7 from "node:os";
|
|
25772
|
-
import * as
|
|
26025
|
+
import * as NodePath12 from "node:path";
|
|
25773
26026
|
import * as NodeProcess4 from "node:process";
|
|
25774
26027
|
async function createClaudeMcpConfig(mcpServers, log) {
|
|
25775
26028
|
let directory;
|
|
@@ -25784,8 +26037,8 @@ async function createClaudeMcpConfig(mcpServers, log) {
|
|
|
25784
26037
|
return { path: void 0, cleanup };
|
|
25785
26038
|
}
|
|
25786
26039
|
try {
|
|
25787
|
-
directory = await NodeFSP5.mkdtemp(
|
|
25788
|
-
const file =
|
|
26040
|
+
directory = await NodeFSP5.mkdtemp(NodePath12.join(NodeOS7.tmpdir(), "ycodium-claude-mcp-"));
|
|
26041
|
+
const file = NodePath12.join(directory, "mcp.json");
|
|
25789
26042
|
await NodeFSP5.writeFile(file, JSON.stringify({ mcpServers }), { mode: 384 });
|
|
25790
26043
|
await NodeFSP5.chmod(file, 384).catch((cause) => {
|
|
25791
26044
|
if (NodeProcess4.platform !== "win32") throw cause;
|
|
@@ -26451,7 +26704,7 @@ var makeStreamEventHandler = (deps) => {
|
|
|
26451
26704
|
|
|
26452
26705
|
// src/claudeWorkspaceInventory.ts
|
|
26453
26706
|
import * as NodeFSP6 from "node:fs/promises";
|
|
26454
|
-
import * as
|
|
26707
|
+
import * as NodePath13 from "node:path";
|
|
26455
26708
|
var MAX_COMMAND_DEPTH = 5;
|
|
26456
26709
|
var MAX_COMMAND_FILES = 500;
|
|
26457
26710
|
var MAX_DESCRIPTION_LENGTH = 200;
|
|
@@ -26469,7 +26722,7 @@ var firstBodyLine = (contents) => {
|
|
|
26469
26722
|
return void 0;
|
|
26470
26723
|
};
|
|
26471
26724
|
var scanCommands = async (claudeDir) => {
|
|
26472
|
-
const root =
|
|
26725
|
+
const root = NodePath13.join(claudeDir, "commands");
|
|
26473
26726
|
const commands = /* @__PURE__ */ new Map();
|
|
26474
26727
|
const watched = [root];
|
|
26475
26728
|
let level = [root];
|
|
@@ -26479,7 +26732,7 @@ var scanCommands = async (claudeDir) => {
|
|
|
26479
26732
|
for (const directory of level) {
|
|
26480
26733
|
const entries = await NodeFSP6.readdir(directory, { withFileTypes: true }).catch(() => []);
|
|
26481
26734
|
for (const entry of entries.toSorted((left, right) => left.name.localeCompare(right.name))) {
|
|
26482
|
-
const entryPath =
|
|
26735
|
+
const entryPath = NodePath13.join(directory, entry.name);
|
|
26483
26736
|
if (entry.isDirectory()) {
|
|
26484
26737
|
next.push(entryPath);
|
|
26485
26738
|
watched.push(entryPath);
|
|
@@ -26507,13 +26760,13 @@ var scanCommands = async (claudeDir) => {
|
|
|
26507
26760
|
return { commands: [...commands.values()], watched };
|
|
26508
26761
|
};
|
|
26509
26762
|
var watchSkillsRoot = async (claudeDir) => {
|
|
26510
|
-
const root =
|
|
26763
|
+
const root = NodePath13.join(claudeDir, "skills");
|
|
26511
26764
|
const entries = await NodeFSP6.readdir(root).catch(() => []);
|
|
26512
26765
|
return [
|
|
26513
26766
|
root,
|
|
26514
26767
|
...entries.flatMap((entry) => [
|
|
26515
|
-
|
|
26516
|
-
|
|
26768
|
+
NodePath13.join(root, entry),
|
|
26769
|
+
NodePath13.join(root, entry, "SKILL.md")
|
|
26517
26770
|
])
|
|
26518
26771
|
];
|
|
26519
26772
|
};
|
|
@@ -26524,7 +26777,7 @@ var mergeByName = (base, preferred) => {
|
|
|
26524
26777
|
return [...merged.values()].toSorted((left, right) => left.name.localeCompare(right.name));
|
|
26525
26778
|
};
|
|
26526
26779
|
var discoverClaudeWorkspaceInventory = async (input) => {
|
|
26527
|
-
const projectClaudeDir =
|
|
26780
|
+
const projectClaudeDir = NodePath13.join(input.cwd, ".claude");
|
|
26528
26781
|
const [userCommands, projectCommands, skills, userSkillWatch, projectSkillWatch] = await Promise.all([
|
|
26529
26782
|
scanCommands(input.configDirPath),
|
|
26530
26783
|
scanCommands(projectClaudeDir),
|
|
@@ -26546,9 +26799,9 @@ var discoverClaudeWorkspaceInventory = async (input) => {
|
|
|
26546
26799
|
...userSkillWatch,
|
|
26547
26800
|
...projectSkillWatch,
|
|
26548
26801
|
// `skillOverrides` 在这几个设置文件里:开关一个技能也要重查。
|
|
26549
|
-
|
|
26550
|
-
|
|
26551
|
-
|
|
26802
|
+
NodePath13.join(input.configDirPath, "settings.json"),
|
|
26803
|
+
NodePath13.join(projectClaudeDir, "settings.json"),
|
|
26804
|
+
NodePath13.join(projectClaudeDir, "settings.local.json")
|
|
26552
26805
|
]
|
|
26553
26806
|
};
|
|
26554
26807
|
};
|
|
@@ -26672,8 +26925,8 @@ var makeSystemMessageHandler = (deps) => {
|
|
|
26672
26925
|
case "model_refusal_no_fallback": {
|
|
26673
26926
|
const explanation = typeof record2.api_refusal_explanation === "string" ? record2.api_refusal_explanation.trim() : "";
|
|
26674
26927
|
const content = typeof record2.content === "string" ? record2.content : "";
|
|
26675
|
-
const
|
|
26676
|
-
if (
|
|
26928
|
+
const text2 = explanation || content;
|
|
26929
|
+
if (text2.length > 0) await emitRuntimeWarning(context, text2, message);
|
|
26677
26930
|
return;
|
|
26678
26931
|
}
|
|
26679
26932
|
}
|
|
@@ -27315,7 +27568,7 @@ var makeTurnLifecycle = (deps) => {
|
|
|
27315
27568
|
};
|
|
27316
27569
|
|
|
27317
27570
|
// src/adapter/turnMessages.ts
|
|
27318
|
-
import * as
|
|
27571
|
+
import * as NodePath14 from "node:path";
|
|
27319
27572
|
var makeTurnMessageHandlers = (deps) => {
|
|
27320
27573
|
const {
|
|
27321
27574
|
emitter,
|
|
@@ -27581,7 +27834,7 @@ var makeTurnMessageHandlers = (deps) => {
|
|
|
27581
27834
|
claudeFailureHint({
|
|
27582
27835
|
authenticationFailed: context.turnState?.authenticationFailed === true,
|
|
27583
27836
|
environment: buildLaunchEnvironment(),
|
|
27584
|
-
cwd:
|
|
27837
|
+
cwd: NodePath14.resolve(context.session.cwd ?? "."),
|
|
27585
27838
|
...context.turnState === void 0 ? {} : {
|
|
27586
27839
|
usageLimit: {
|
|
27587
27840
|
rejected: context.turnState.rejectedRateLimits,
|
|
@@ -27685,8 +27938,13 @@ function buildTurnSummaryPrompt(raw) {
|
|
|
27685
27938
|
// src/textGeneration.ts
|
|
27686
27939
|
import * as NodeFSP7 from "node:fs/promises";
|
|
27687
27940
|
import * as NodeOS8 from "node:os";
|
|
27688
|
-
import * as
|
|
27689
|
-
import { mergeLaunchEnv } from "@ycodium-ai/plugin-api/executor";
|
|
27941
|
+
import * as NodePath15 from "node:path";
|
|
27942
|
+
import { mergeLaunchEnv as mergeLaunchEnv2 } from "@ycodium-ai/plugin-api/executor";
|
|
27943
|
+
import {
|
|
27944
|
+
OperationCleanupError as OperationCleanupError2,
|
|
27945
|
+
isOperationCleanupError as isOperationCleanupError2,
|
|
27946
|
+
runProcessOperation as runProcessOperation2
|
|
27947
|
+
} from "@ycodium-ai/plugin-api/process-operation";
|
|
27690
27948
|
|
|
27691
27949
|
// src/textGenerationUtils.ts
|
|
27692
27950
|
function limitSection(value, maxChars) {
|
|
@@ -27732,14 +27990,14 @@ function unwrapNestedTitleObject(raw) {
|
|
|
27732
27990
|
return raw;
|
|
27733
27991
|
}
|
|
27734
27992
|
var MAX_THREAD_TITLE_CHARS = 120;
|
|
27735
|
-
function limitTitleMessage(
|
|
27993
|
+
function limitTitleMessage(text2, budget) {
|
|
27736
27994
|
const marker = "\n[Content truncated]\n";
|
|
27737
|
-
if (
|
|
27995
|
+
if (text2.length <= budget) return text2;
|
|
27738
27996
|
if (budget <= marker.length) return "";
|
|
27739
27997
|
const available = budget - marker.length;
|
|
27740
27998
|
const head = Math.ceil(available / 2);
|
|
27741
27999
|
const tail = available - head;
|
|
27742
|
-
return `${
|
|
28000
|
+
return `${text2.slice(0, head)}${marker}${tail > 0 ? text2.slice(-tail) : ""}`;
|
|
27743
28001
|
}
|
|
27744
28002
|
function sanitizeThreadTitle(raw) {
|
|
27745
28003
|
const normalized = unwrapNestedTitleObject(raw).trim().split(/\r?\n/g)[0]?.trim().replace(/^['"`]+|['"`]+$/g, "").trim().replace(/\s+/g, " ");
|
|
@@ -28050,19 +28308,12 @@ function buildHandoverSummaryPrompt(input) {
|
|
|
28050
28308
|
|
|
28051
28309
|
// src/textGeneration.ts
|
|
28052
28310
|
var CLAUDE_TIMEOUT_MS = 18e4;
|
|
28053
|
-
function
|
|
28311
|
+
function isRecord6(value) {
|
|
28054
28312
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28055
28313
|
}
|
|
28056
|
-
function
|
|
28314
|
+
function readString4(value) {
|
|
28057
28315
|
return typeof value === "string" ? value : "";
|
|
28058
28316
|
}
|
|
28059
|
-
async function collectText(stream) {
|
|
28060
|
-
const chunks = [];
|
|
28061
|
-
for await (const chunk of stream) {
|
|
28062
|
-
chunks.push(Buffer.from(chunk));
|
|
28063
|
-
}
|
|
28064
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
28065
|
-
}
|
|
28066
28317
|
function decodeStructuredOutput(stdout, operation) {
|
|
28067
28318
|
let parsed;
|
|
28068
28319
|
try {
|
|
@@ -28072,19 +28323,20 @@ function decodeStructuredOutput(stdout, operation) {
|
|
|
28072
28323
|
cause: error
|
|
28073
28324
|
});
|
|
28074
28325
|
}
|
|
28075
|
-
const envelope = Array.isArray(parsed) ? parsed.findLast((message) =>
|
|
28076
|
-
if (!
|
|
28326
|
+
const envelope = Array.isArray(parsed) ? parsed.findLast((message) => isRecord6(message) && message["type"] === "result") : parsed;
|
|
28327
|
+
if (!isRecord6(envelope) || !("structured_output" in envelope)) {
|
|
28077
28328
|
throw new Error(`${operation}: Claude CLI returned unexpected output format.`);
|
|
28078
28329
|
}
|
|
28079
28330
|
return envelope["structured_output"];
|
|
28080
28331
|
}
|
|
28081
28332
|
function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
28082
28333
|
const runClaudeJson = async (input) => {
|
|
28083
|
-
|
|
28334
|
+
input.signal?.throwIfAborted();
|
|
28335
|
+
const processEnv = mergeLaunchEnv2({
|
|
28084
28336
|
instanceTable: recipe.environment,
|
|
28085
28337
|
handOverrides: claudeHomeVariables(resolveClaudeHomeLayout(recipe))
|
|
28086
28338
|
});
|
|
28087
|
-
const modelSelection =
|
|
28339
|
+
const modelSelection = isRecord6(input.modelSelection) ? input.modelSelection : {};
|
|
28088
28340
|
const requestedModel = modelIdFromSelection(modelSelection) ?? "claude-haiku-4-5";
|
|
28089
28341
|
const caps = claudeModelCapabilities(requestedModel, modelCatalog(), recipe.customModels);
|
|
28090
28342
|
const rawEffort = getModelSelectionStringOptionValue(modelSelection, "effort");
|
|
@@ -28120,52 +28372,46 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28120
28372
|
"--strict-mcp-config"
|
|
28121
28373
|
];
|
|
28122
28374
|
const program = recipe.binaryPath.trim() || "claude";
|
|
28375
|
+
let safeToRemove = true;
|
|
28123
28376
|
const runIn = async (cwd) => {
|
|
28124
|
-
|
|
28125
|
-
|
|
28126
|
-
|
|
28127
|
-
|
|
28128
|
-
|
|
28129
|
-
|
|
28130
|
-
|
|
28131
|
-
|
|
28132
|
-
|
|
28133
|
-
|
|
28134
|
-
|
|
28135
|
-
|
|
28136
|
-
|
|
28137
|
-
|
|
28138
|
-
|
|
28139
|
-
|
|
28140
|
-
|
|
28141
|
-
|
|
28142
|
-
|
|
28143
|
-
|
|
28144
|
-
|
|
28145
|
-
if (signal.aborted && !input.signal?.aborted) {
|
|
28146
|
-
throw new Error(`${input.operation}: Claude CLI request timed out.`);
|
|
28147
|
-
}
|
|
28148
|
-
if (exitCode !== 0) {
|
|
28149
|
-
const detail = stderr.trim() || stdout.trim();
|
|
28150
|
-
throw new Error(
|
|
28151
|
-
detail.length > 0 ? `Claude CLI command failed: ${detail}` : `Claude CLI command failed with code ${exitCode}.`
|
|
28152
|
-
);
|
|
28377
|
+
try {
|
|
28378
|
+
const { stdout, stderr, exitCode } = await runProcessOperation2(host, {
|
|
28379
|
+
program,
|
|
28380
|
+
args,
|
|
28381
|
+
cwd,
|
|
28382
|
+
env: processEnv,
|
|
28383
|
+
owner: { bindingId: host.bindingId },
|
|
28384
|
+
signal: input.signal,
|
|
28385
|
+
timeoutMs: CLAUDE_TIMEOUT_MS,
|
|
28386
|
+
input: input.prompt
|
|
28387
|
+
});
|
|
28388
|
+
if (exitCode !== 0) {
|
|
28389
|
+
const detail = stderr.trim() || stdout.trim();
|
|
28390
|
+
throw new Error(
|
|
28391
|
+
detail.length > 0 ? `Claude CLI command failed: ${detail}` : `Claude CLI command failed with code ${exitCode}.`
|
|
28392
|
+
);
|
|
28393
|
+
}
|
|
28394
|
+
return decodeStructuredOutput(stdout, input.operation);
|
|
28395
|
+
} catch (cause) {
|
|
28396
|
+
if (cause instanceof OperationCleanupError2) safeToRemove = false;
|
|
28397
|
+
throw cause;
|
|
28153
28398
|
}
|
|
28154
|
-
return decodeStructuredOutput(stdout, input.operation);
|
|
28155
28399
|
};
|
|
28156
28400
|
if (input.operation !== "generateThreadTitle" && input.operation !== "summarizeTurn")
|
|
28157
28401
|
return runIn(input.cwd);
|
|
28158
28402
|
const scratchDirectory = await NodeFSP7.mkdtemp(
|
|
28159
|
-
|
|
28403
|
+
NodePath15.join(NodeOS8.tmpdir(), "ycodium-claude-title-")
|
|
28160
28404
|
);
|
|
28161
28405
|
try {
|
|
28162
28406
|
return await runIn(scratchDirectory);
|
|
28163
28407
|
} finally {
|
|
28164
|
-
|
|
28408
|
+
if (safeToRemove) {
|
|
28409
|
+
await NodeFSP7.rm(scratchDirectory, { recursive: true, force: true }).catch(() => void 0);
|
|
28410
|
+
}
|
|
28165
28411
|
}
|
|
28166
28412
|
};
|
|
28167
28413
|
const asRecord2 = (value, operation) => {
|
|
28168
|
-
if (!
|
|
28414
|
+
if (!isRecord6(value))
|
|
28169
28415
|
throw new Error(`${operation}: Claude returned invalid structured output.`);
|
|
28170
28416
|
return value;
|
|
28171
28417
|
};
|
|
@@ -28176,15 +28422,15 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28176
28422
|
const includeBranch = input["includeBranch"] === true;
|
|
28177
28423
|
const { prompt, outputSchema } = buildCommitMessagePrompt({
|
|
28178
28424
|
branch: typeof input["branch"] === "string" ? input["branch"] : null,
|
|
28179
|
-
stagedSummary:
|
|
28180
|
-
stagedPatch:
|
|
28425
|
+
stagedSummary: readString4(input["stagedSummary"]),
|
|
28426
|
+
stagedPatch: readString4(input["stagedPatch"]),
|
|
28181
28427
|
includeBranch,
|
|
28182
|
-
...
|
|
28428
|
+
...isRecord6(input["policy"]) ? { policy: input["policy"] } : {}
|
|
28183
28429
|
});
|
|
28184
28430
|
const generated = asRecord2(
|
|
28185
28431
|
await runClaudeJson({
|
|
28186
28432
|
operation: "generateCommitMessage",
|
|
28187
|
-
cwd:
|
|
28433
|
+
cwd: readString4(input["cwd"]) || ".",
|
|
28188
28434
|
prompt,
|
|
28189
28435
|
outputSchema,
|
|
28190
28436
|
modelSelection: input["modelSelection"],
|
|
@@ -28193,11 +28439,12 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28193
28439
|
"generateCommitMessage"
|
|
28194
28440
|
);
|
|
28195
28441
|
return {
|
|
28196
|
-
subject: sanitizeCommitSubject(
|
|
28197
|
-
body:
|
|
28442
|
+
subject: sanitizeCommitSubject(readString4(generated["subject"])),
|
|
28443
|
+
body: readString4(generated["body"]).trim(),
|
|
28198
28444
|
...typeof generated["branch"] === "string" ? { branch: sanitizeFeatureBranchName(generated["branch"]) } : {}
|
|
28199
28445
|
};
|
|
28200
28446
|
} catch (error) {
|
|
28447
|
+
if (isOperationCleanupError2(error)) throw error;
|
|
28201
28448
|
throw normalizeCliError("claude", error, "Failed to generate commit message");
|
|
28202
28449
|
}
|
|
28203
28450
|
},
|
|
@@ -28205,18 +28452,18 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28205
28452
|
try {
|
|
28206
28453
|
const input = asRecord2(raw, "generatePrContent");
|
|
28207
28454
|
const { prompt, outputSchema } = buildPrContentPrompt({
|
|
28208
|
-
baseBranch:
|
|
28209
|
-
headBranch:
|
|
28210
|
-
commitSummary:
|
|
28211
|
-
diffSummary:
|
|
28212
|
-
diffPatch:
|
|
28455
|
+
baseBranch: readString4(input["baseBranch"]),
|
|
28456
|
+
headBranch: readString4(input["headBranch"]),
|
|
28457
|
+
commitSummary: readString4(input["commitSummary"]),
|
|
28458
|
+
diffSummary: readString4(input["diffSummary"]),
|
|
28459
|
+
diffPatch: readString4(input["diffPatch"]),
|
|
28213
28460
|
...typeof input["changeRequestTemplate"] === "string" ? { changeRequestTemplate: input["changeRequestTemplate"] } : {},
|
|
28214
|
-
...
|
|
28461
|
+
...isRecord6(input["policy"]) ? { policy: input["policy"] } : {}
|
|
28215
28462
|
});
|
|
28216
28463
|
const generated = asRecord2(
|
|
28217
28464
|
await runClaudeJson({
|
|
28218
28465
|
operation: "generatePrContent",
|
|
28219
|
-
cwd:
|
|
28466
|
+
cwd: readString4(input["cwd"]) || ".",
|
|
28220
28467
|
prompt,
|
|
28221
28468
|
outputSchema,
|
|
28222
28469
|
modelSelection: input["modelSelection"],
|
|
@@ -28225,10 +28472,11 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28225
28472
|
"generatePrContent"
|
|
28226
28473
|
);
|
|
28227
28474
|
return {
|
|
28228
|
-
title: sanitizePrTitle(
|
|
28229
|
-
body:
|
|
28475
|
+
title: sanitizePrTitle(readString4(generated["title"])),
|
|
28476
|
+
body: readString4(generated["body"]).trim()
|
|
28230
28477
|
};
|
|
28231
28478
|
} catch (error) {
|
|
28479
|
+
if (isOperationCleanupError2(error)) throw error;
|
|
28232
28480
|
throw normalizeCliError("claude", error, "Failed to generate change request content");
|
|
28233
28481
|
}
|
|
28234
28482
|
},
|
|
@@ -28236,14 +28484,14 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28236
28484
|
try {
|
|
28237
28485
|
const input = asRecord2(raw, "generateBranchName");
|
|
28238
28486
|
const { prompt, outputSchema } = buildBranchNamePrompt({
|
|
28239
|
-
message:
|
|
28487
|
+
message: readString4(input["message"]),
|
|
28240
28488
|
...Array.isArray(input["attachments"]) ? { attachments: input["attachments"] } : {},
|
|
28241
|
-
...
|
|
28489
|
+
...isRecord6(input["policy"]) ? { policy: input["policy"] } : {}
|
|
28242
28490
|
});
|
|
28243
28491
|
const generated = asRecord2(
|
|
28244
28492
|
await runClaudeJson({
|
|
28245
28493
|
operation: "generateBranchName",
|
|
28246
|
-
cwd:
|
|
28494
|
+
cwd: readString4(input["cwd"]) || ".",
|
|
28247
28495
|
prompt,
|
|
28248
28496
|
outputSchema,
|
|
28249
28497
|
modelSelection: input["modelSelection"],
|
|
@@ -28251,8 +28499,9 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28251
28499
|
}),
|
|
28252
28500
|
"generateBranchName"
|
|
28253
28501
|
);
|
|
28254
|
-
return { branch: sanitizeBranchFragment(
|
|
28502
|
+
return { branch: sanitizeBranchFragment(readString4(generated["branch"])) };
|
|
28255
28503
|
} catch (error) {
|
|
28504
|
+
if (isOperationCleanupError2(error)) throw error;
|
|
28256
28505
|
throw normalizeCliError("claude", error, "Failed to generate branch name");
|
|
28257
28506
|
}
|
|
28258
28507
|
},
|
|
@@ -28260,16 +28509,16 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28260
28509
|
try {
|
|
28261
28510
|
const input = asRecord2(raw, "generateThreadTitle");
|
|
28262
28511
|
const { prompt, outputSchema } = buildThreadTitlePrompt({
|
|
28263
|
-
message:
|
|
28512
|
+
message: readString4(input["message"]),
|
|
28264
28513
|
...typeof input["linkedContext"] === "string" && input["linkedContext"].length > 0 ? { linkedContext: input["linkedContext"] } : {},
|
|
28265
28514
|
...typeof input["previousTitle"] === "string" ? { previousTitle: input["previousTitle"] } : {},
|
|
28266
28515
|
...Array.isArray(input["attachments"]) ? { attachments: input["attachments"] } : {},
|
|
28267
|
-
...
|
|
28516
|
+
...isRecord6(input["policy"]) ? { policy: input["policy"] } : {}
|
|
28268
28517
|
});
|
|
28269
28518
|
const generated = asRecord2(
|
|
28270
28519
|
await runClaudeJson({
|
|
28271
28520
|
operation: "generateThreadTitle",
|
|
28272
|
-
cwd:
|
|
28521
|
+
cwd: readString4(input["cwd"]) || ".",
|
|
28273
28522
|
prompt,
|
|
28274
28523
|
outputSchema,
|
|
28275
28524
|
modelSelection: input["modelSelection"],
|
|
@@ -28278,10 +28527,11 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28278
28527
|
"generateThreadTitle"
|
|
28279
28528
|
);
|
|
28280
28529
|
return {
|
|
28281
|
-
title: sanitizeThreadTitle(
|
|
28530
|
+
title: sanitizeThreadTitle(readString4(generated["title"])),
|
|
28282
28531
|
...generated["needsRefinement"] === true ? { needsRefinement: true } : {}
|
|
28283
28532
|
};
|
|
28284
28533
|
} catch (error) {
|
|
28534
|
+
if (isOperationCleanupError2(error)) throw error;
|
|
28285
28535
|
throw normalizeCliError("claude", error, "Failed to generate thread title");
|
|
28286
28536
|
}
|
|
28287
28537
|
},
|
|
@@ -28291,7 +28541,7 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28291
28541
|
const generated = asRecord2(
|
|
28292
28542
|
await runClaudeJson({
|
|
28293
28543
|
operation: "summarizeTurn",
|
|
28294
|
-
cwd:
|
|
28544
|
+
cwd: readString4(input["cwd"]) || ".",
|
|
28295
28545
|
prompt: buildTurnSummaryPrompt(input),
|
|
28296
28546
|
outputSchema: {
|
|
28297
28547
|
type: "object",
|
|
@@ -28304,8 +28554,9 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28304
28554
|
}),
|
|
28305
28555
|
"summarizeTurn"
|
|
28306
28556
|
);
|
|
28307
|
-
return { summary:
|
|
28557
|
+
return { summary: readString4(generated["summary"]).trim() };
|
|
28308
28558
|
} catch (error) {
|
|
28559
|
+
if (isOperationCleanupError2(error)) throw error;
|
|
28309
28560
|
throw normalizeCliError("claude", error, "Failed to summarize turn");
|
|
28310
28561
|
}
|
|
28311
28562
|
},
|
|
@@ -28313,12 +28564,12 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28313
28564
|
try {
|
|
28314
28565
|
const input = asRecord2(raw, "summarizeHandover");
|
|
28315
28566
|
const { prompt, outputSchema } = buildHandoverSummaryPrompt({
|
|
28316
|
-
transcript:
|
|
28567
|
+
transcript: readString4(input["transcript"])
|
|
28317
28568
|
});
|
|
28318
28569
|
const generated = asRecord2(
|
|
28319
28570
|
await runClaudeJson({
|
|
28320
28571
|
operation: "summarizeHandover",
|
|
28321
|
-
cwd:
|
|
28572
|
+
cwd: readString4(input["cwd"]) || ".",
|
|
28322
28573
|
prompt,
|
|
28323
28574
|
outputSchema,
|
|
28324
28575
|
modelSelection: input["modelSelection"],
|
|
@@ -28326,8 +28577,9 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28326
28577
|
}),
|
|
28327
28578
|
"summarizeHandover"
|
|
28328
28579
|
);
|
|
28329
|
-
return { summary:
|
|
28580
|
+
return { summary: readString4(generated["summary"]).trim() };
|
|
28330
28581
|
} catch (error) {
|
|
28582
|
+
if (isOperationCleanupError2(error)) throw error;
|
|
28331
28583
|
throw normalizeCliError("claude", error, "Failed to summarize handover");
|
|
28332
28584
|
}
|
|
28333
28585
|
}
|
|
@@ -28337,179 +28589,99 @@ function createClaudeTextGeneration(recipe, host, modelCatalog) {
|
|
|
28337
28589
|
// src/usageRead/index.ts
|
|
28338
28590
|
import * as NodePath18 from "node:path";
|
|
28339
28591
|
|
|
28340
|
-
// src/usageRead/
|
|
28341
|
-
import * as
|
|
28342
|
-
import
|
|
28343
|
-
|
|
28344
|
-
|
|
28345
|
-
|
|
28346
|
-
|
|
28347
|
-
|
|
28348
|
-
|
|
28349
|
-
|
|
28350
|
-
|
|
28351
|
-
|
|
28352
|
-
|
|
28353
|
-
|
|
28354
|
-
|
|
28355
|
-
|
|
28356
|
-
|
|
28357
|
-
|
|
28358
|
-
|
|
28359
|
-
});
|
|
28360
|
-
var claudeCredentialFileCandidates = (recipe) => {
|
|
28361
|
-
const environment = launchEnvironment(recipe);
|
|
28362
|
-
const credentialsDir = resolveClaudeCredentialsDirPath(
|
|
28363
|
-
environment[CLAUDE_CREDENTIALS_DIR_ENVIRONMENT_VARIABLE] ?? ""
|
|
28364
|
-
);
|
|
28365
|
-
if (credentialsDir !== null) return [NodePath15.join(credentialsDir, ".credentials.json")];
|
|
28366
|
-
const configDir = resolveClaudeConfigDirPath(recipe.homePath, environment);
|
|
28367
|
-
const home = resolveClaudeHomePath(recipe.homePath);
|
|
28368
|
-
return [
|
|
28369
|
-
.../* @__PURE__ */ new Set([
|
|
28370
|
-
NodePath15.join(configDir, ".credentials.json"),
|
|
28371
|
-
NodePath15.join(home, ".claude", ".credentials.json"),
|
|
28372
|
-
NodePath15.join(home, ".credentials.json")
|
|
28373
|
-
])
|
|
28374
|
-
];
|
|
28375
|
-
};
|
|
28376
|
-
var readString4 = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
28377
|
-
var readLoginCredential = (candidates) => {
|
|
28378
|
-
for (const path of candidates) {
|
|
28379
|
-
let raw;
|
|
28380
|
-
try {
|
|
28381
|
-
raw = NodeFS6.readFileSync(path, "utf8");
|
|
28382
|
-
} catch {
|
|
28383
|
-
continue;
|
|
28384
|
-
}
|
|
28385
|
-
if (raw.trim().length === 0) continue;
|
|
28386
|
-
let parsed;
|
|
28387
|
-
try {
|
|
28388
|
-
parsed = JSON.parse(raw);
|
|
28389
|
-
} catch {
|
|
28390
|
-
continue;
|
|
28391
|
-
}
|
|
28392
|
-
const oauth = isRecord6(parsed) ? parsed["claudeAiOauth"] : void 0;
|
|
28393
|
-
if (!isRecord6(oauth)) continue;
|
|
28394
|
-
const accessToken = readString4(oauth["accessToken"]);
|
|
28395
|
-
if (accessToken === void 0) continue;
|
|
28396
|
-
return {
|
|
28397
|
-
accessToken,
|
|
28398
|
-
subscriptionType: readString4(oauth["subscriptionType"]),
|
|
28399
|
-
rateLimitTier: readString4(oauth["rateLimitTier"]),
|
|
28400
|
-
path
|
|
28401
|
-
};
|
|
28402
|
-
}
|
|
28403
|
-
return null;
|
|
28404
|
-
};
|
|
28405
|
-
var claudePlanName = (credential) => {
|
|
28406
|
-
const type4 = credential.subscriptionType;
|
|
28407
|
-
if (type4 === void 0) return void 0;
|
|
28408
|
-
const name = `${type4.charAt(0).toUpperCase()}${type4.slice(1)}`;
|
|
28409
|
-
const multiplier = /(?:^|_)(\d+x)$/.exec(credential.rateLimitTier ?? "")?.[1];
|
|
28410
|
-
return multiplier === void 0 ? name : `${name} ${multiplier}`;
|
|
28411
|
-
};
|
|
28412
|
-
var toIso = (value) => {
|
|
28413
|
-
if (typeof value !== "string") return null;
|
|
28414
|
-
const parsed = Date.parse(value);
|
|
28415
|
-
return Number.isNaN(parsed) ? null : new Date(parsed).toISOString();
|
|
28416
|
-
};
|
|
28417
|
-
var readWindows = (body) => CLAUDE_QUOTA_WINDOWS.flatMap((spec) => {
|
|
28418
|
-
const row = body[spec.field];
|
|
28419
|
-
if (!isRecord6(row)) return [];
|
|
28420
|
-
const utilization = row["utilization"];
|
|
28421
|
-
if (typeof utilization !== "number" || !Number.isFinite(utilization)) return [];
|
|
28422
|
-
return [
|
|
28423
|
-
{
|
|
28424
|
-
id: spec.id,
|
|
28425
|
-
label: { key: spec.labelKey },
|
|
28426
|
-
usedPercent: Math.min(100, Math.max(0, utilization)),
|
|
28427
|
-
resetsAt: toIso(row["resets_at"]),
|
|
28428
|
-
windowMs: spec.windowMs
|
|
28592
|
+
// src/usageRead/nativeQuota.ts
|
|
28593
|
+
import * as NodeOS9 from "node:os";
|
|
28594
|
+
import { mergeLaunchEnv as mergeLaunchEnv3 } from "@ycodium-ai/plugin-api/executor";
|
|
28595
|
+
var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28596
|
+
function quotaWriter(write) {
|
|
28597
|
+
const decoder = new TextDecoder();
|
|
28598
|
+
let pending2 = "";
|
|
28599
|
+
return async (chunk) => {
|
|
28600
|
+
pending2 += typeof chunk === "string" ? chunk : decoder.decode(chunk, { stream: true });
|
|
28601
|
+
let end;
|
|
28602
|
+
while ((end = pending2.indexOf("\n")) !== -1) {
|
|
28603
|
+
const line = pending2.slice(0, end);
|
|
28604
|
+
pending2 = pending2.slice(end + 1);
|
|
28605
|
+
if (line.trim().length === 0) continue;
|
|
28606
|
+
const frame = JSON.parse(line);
|
|
28607
|
+
if (isRecord7(frame) && frame.type === "control_request" && isRecord7(frame.request) && frame.request.subtype === "get_usage") {
|
|
28608
|
+
frame.request = { ...frame.request, skip_behaviors: true };
|
|
28609
|
+
}
|
|
28610
|
+
await write(JSON.stringify(frame) + "\n");
|
|
28429
28611
|
}
|
|
28430
|
-
];
|
|
28431
|
-
});
|
|
28432
|
-
var readClaudeQuota = async (request) => {
|
|
28433
|
-
const { recipe } = request;
|
|
28434
|
-
const connectivity = CLAUDE_CARD.modelConnectivity;
|
|
28435
|
-
const environmentRows = Object.entries(recipe.environment).map(([name, value]) => ({
|
|
28436
|
-
name,
|
|
28437
|
-
value
|
|
28438
|
-
}));
|
|
28439
|
-
if (connectivity !== void 0 && setsOwnModelConnection2(connectivity, environmentRows)) {
|
|
28440
|
-
const changesEndpoint = setsOwnModelConnection2(
|
|
28441
|
-
{
|
|
28442
|
-
baseUrlEnvKey: connectivity.baseUrlEnvKey,
|
|
28443
|
-
backendSwitchEnvKeys: connectivity.backendSwitchEnvKeys
|
|
28444
|
-
},
|
|
28445
|
-
environmentRows
|
|
28446
|
-
);
|
|
28447
|
-
return {
|
|
28448
|
-
status: "unavailable",
|
|
28449
|
-
reason: changesEndpoint ? "customEndpoint" : "unsupportedLogin"
|
|
28450
|
-
};
|
|
28451
|
-
}
|
|
28452
|
-
const credential = readLoginCredential(claudeCredentialFileCandidates(recipe));
|
|
28453
|
-
if (credential === null) return { status: "unavailable", reason: "missingCredentials" };
|
|
28454
|
-
const now = request.now ?? Date.now;
|
|
28455
|
-
let response;
|
|
28456
|
-
try {
|
|
28457
|
-
response = await request.fetch(CLAUDE_QUOTA_URL, {
|
|
28458
|
-
method: "GET",
|
|
28459
|
-
headers: {
|
|
28460
|
-
Accept: "application/json",
|
|
28461
|
-
"anthropic-beta": "oauth-2025-04-20",
|
|
28462
|
-
Authorization: `Bearer ${credential.accessToken}`
|
|
28463
|
-
},
|
|
28464
|
-
redirect: "error",
|
|
28465
|
-
signal: request.signal === void 0 ? AbortSignal.timeout(REQUEST_TIMEOUT_MS) : AbortSignal.any([request.signal, AbortSignal.timeout(REQUEST_TIMEOUT_MS)])
|
|
28466
|
-
});
|
|
28467
|
-
} catch (cause) {
|
|
28468
|
-
if (request.signal?.aborted === true) throw cause;
|
|
28469
|
-
return { status: "unavailable", reason: "unreachable" };
|
|
28470
|
-
}
|
|
28471
|
-
const release = () => {
|
|
28472
|
-
void response.body?.cancel().catch(() => void 0);
|
|
28473
28612
|
};
|
|
28474
|
-
|
|
28475
|
-
|
|
28476
|
-
|
|
28477
|
-
|
|
28478
|
-
|
|
28479
|
-
reason: "rateLimited",
|
|
28480
|
-
...retryAfterMs === null ? {} : { retryAfterMs }
|
|
28481
|
-
};
|
|
28482
|
-
}
|
|
28483
|
-
if (response.status === 401 || response.status === 403) {
|
|
28484
|
-
release();
|
|
28485
|
-
return { status: "unavailable", reason: "authRejected" };
|
|
28486
|
-
}
|
|
28487
|
-
if (response.status < 200 || response.status >= 300) {
|
|
28488
|
-
release();
|
|
28489
|
-
return { status: "unavailable", reason: "unreachable" };
|
|
28613
|
+
}
|
|
28614
|
+
function quotaReading(value) {
|
|
28615
|
+
if (!isRecord7(value)) return { status: "unavailable", reason: "unreachable" };
|
|
28616
|
+
if (value.rate_limits_available === false) {
|
|
28617
|
+
return { status: "unavailable", reason: "unsupportedLogin" };
|
|
28490
28618
|
}
|
|
28491
|
-
|
|
28492
|
-
try {
|
|
28493
|
-
body = JSON.parse(await response.text());
|
|
28494
|
-
} catch {
|
|
28619
|
+
if (value.rate_limits_available !== true || !isRecord7(value.rate_limits)) {
|
|
28495
28620
|
return { status: "unavailable", reason: "unreachable" };
|
|
28496
28621
|
}
|
|
28497
|
-
|
|
28498
|
-
|
|
28622
|
+
const plan = claudePlanName({
|
|
28623
|
+
subscriptionType: typeof value.subscription_type === "string" ? value.subscription_type : void 0,
|
|
28624
|
+
rateLimitTier: void 0
|
|
28625
|
+
});
|
|
28499
28626
|
return {
|
|
28500
28627
|
status: "available",
|
|
28501
28628
|
...plan === void 0 ? {} : { plan },
|
|
28502
|
-
windows:
|
|
28503
|
-
balances: []
|
|
28504
|
-
accountKey: credential.path
|
|
28629
|
+
windows: readClaudeQuotaWindows(value.rate_limits),
|
|
28630
|
+
balances: []
|
|
28505
28631
|
};
|
|
28506
|
-
}
|
|
28632
|
+
}
|
|
28633
|
+
async function readClaudeNativeQuota(input) {
|
|
28634
|
+
const { recipe, host, signal } = input;
|
|
28635
|
+
signal?.throwIfAborted();
|
|
28636
|
+
if (!recipe.binaryPath) return void 0;
|
|
28637
|
+
try {
|
|
28638
|
+
const environment = mergeLaunchEnv3({
|
|
28639
|
+
inherited: process.env,
|
|
28640
|
+
instanceTable: recipe.environment,
|
|
28641
|
+
handOverrides: claudeHomeVariables(resolveClaudeHomeLayout(recipe))
|
|
28642
|
+
});
|
|
28643
|
+
const { flags, positionals } = parseCliArgs(recipe.launchArgs);
|
|
28644
|
+
if (positionals.length > 0 || ["resume", "continue", "fork-session", "session-id", "prompt", "print"].some(
|
|
28645
|
+
(key) => key in flags
|
|
28646
|
+
)) {
|
|
28647
|
+
return { status: "unavailable", reason: "unreachable" };
|
|
28648
|
+
}
|
|
28649
|
+
const result = await withClaudeSdkRead(
|
|
28650
|
+
{
|
|
28651
|
+
host,
|
|
28652
|
+
signal,
|
|
28653
|
+
timeoutMs: input.timeoutMs,
|
|
28654
|
+
createQuery: XAe,
|
|
28655
|
+
stdin: quotaWriter,
|
|
28656
|
+
options: {
|
|
28657
|
+
cwd: NodeOS9.tmpdir(),
|
|
28658
|
+
pathToClaudeCodeExecutable: resolveClaudeSdkExecutablePath(
|
|
28659
|
+
recipe.binaryPath,
|
|
28660
|
+
environment
|
|
28661
|
+
),
|
|
28662
|
+
env: compactEnv(claudeModelProbeEnvironment(environment)),
|
|
28663
|
+
settingSources: [...CLAUDE_SETTING_SOURCES],
|
|
28664
|
+
extraArgs: flags
|
|
28665
|
+
}
|
|
28666
|
+
},
|
|
28667
|
+
(runtime) => runtime.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET()
|
|
28668
|
+
);
|
|
28669
|
+
return quotaReading(result);
|
|
28670
|
+
} catch (error) {
|
|
28671
|
+
signal?.throwIfAborted();
|
|
28672
|
+
const message = error instanceof Error ? error.message : "";
|
|
28673
|
+
if (/get_usage/i.test(message) && /not supported|unknown|unrecognized|unsupported/i.test(message)) {
|
|
28674
|
+
return void 0;
|
|
28675
|
+
}
|
|
28676
|
+
return { status: "unavailable", reason: "unreachable" };
|
|
28677
|
+
}
|
|
28678
|
+
}
|
|
28507
28679
|
|
|
28508
28680
|
// src/usageRead/rateLimitEvent.ts
|
|
28509
|
-
var
|
|
28681
|
+
var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28510
28682
|
var claudeQuotaFromRateLimitEvent = (message) => {
|
|
28511
|
-
const info =
|
|
28512
|
-
if (!
|
|
28683
|
+
const info = isRecord8(message) ? message["rate_limit_info"] : void 0;
|
|
28684
|
+
if (!isRecord8(info)) return null;
|
|
28513
28685
|
const spec = CLAUDE_QUOTA_WINDOWS.find((window2) => window2.field === info["rateLimitType"]);
|
|
28514
28686
|
const utilization = info["utilization"];
|
|
28515
28687
|
if (spec === void 0 || typeof utilization !== "number" || !Number.isFinite(utilization)) {
|
|
@@ -28917,7 +29089,7 @@ var createClaudeTokenReader = (options) => {
|
|
|
28917
29089
|
status: "missing",
|
|
28918
29090
|
scannedFiles: 0,
|
|
28919
29091
|
skippedFiles: 0,
|
|
28920
|
-
message: "No Claude Code session records found
|
|
29092
|
+
message: "No Claude Code session records found in the configured directory."
|
|
28921
29093
|
}
|
|
28922
29094
|
};
|
|
28923
29095
|
}
|
|
@@ -29014,7 +29186,12 @@ var createClaudeUsage = (input) => {
|
|
|
29014
29186
|
cache: input.cache
|
|
29015
29187
|
});
|
|
29016
29188
|
return {
|
|
29017
|
-
readQuota: ({ signal }) =>
|
|
29189
|
+
readQuota: async ({ signal }) => {
|
|
29190
|
+
const native = await readClaudeNativeQuota({ recipe, host, signal });
|
|
29191
|
+
if (native !== void 0) return native;
|
|
29192
|
+
const fallback = await readClaudeQuota({ recipe, fetch: host.fetch, signal });
|
|
29193
|
+
return recipe.binaryPath && fallback.status === "unavailable" && fallback.reason === "missingCredentials" ? { status: "unavailable", reason: "unreachable" } : fallback;
|
|
29194
|
+
},
|
|
29018
29195
|
quotaFromRateLimits: claudeQuotaFromRateLimitEvent,
|
|
29019
29196
|
readTokenUsage: tokens.readTokenUsage
|
|
29020
29197
|
};
|
|
@@ -29085,12 +29262,13 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
29085
29262
|
if (recipe.binaryPath.length === 0) throw new Error(CLAUDE_PROGRAM_NOT_CONFIGURED);
|
|
29086
29263
|
return sdkCreateQuery(input);
|
|
29087
29264
|
};
|
|
29088
|
-
const buildLaunchEnvironment = () =>
|
|
29265
|
+
const buildLaunchEnvironment = () => mergeLaunchEnv4({
|
|
29089
29266
|
inherited: { ...process.env, ...options?.environment },
|
|
29090
29267
|
instanceTable: recipe.environment,
|
|
29091
29268
|
handOverrides: claudeHomeVariables(resolveClaudeHomeLayout(recipe))
|
|
29092
29269
|
});
|
|
29093
29270
|
const modelCatalog = makeClaudeModelCatalog({
|
|
29271
|
+
host,
|
|
29094
29272
|
recipe,
|
|
29095
29273
|
now,
|
|
29096
29274
|
createQuery,
|
|
@@ -29238,6 +29416,7 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
29238
29416
|
modelCatalog: {
|
|
29239
29417
|
refresh: modelCatalog.refresh,
|
|
29240
29418
|
current: currentModelCatalog,
|
|
29419
|
+
currentAuth: modelCatalog.currentAuth,
|
|
29241
29420
|
lastRefreshOk: modelCatalog.lastRefreshOk,
|
|
29242
29421
|
notePairedRefresh: modelCatalog.notePairedRefresh
|
|
29243
29422
|
},
|
|
@@ -29300,18 +29479,25 @@ function createClaudeInstance(config, host, attachments, overrides, usageCache)
|
|
|
29300
29479
|
};
|
|
29301
29480
|
return {
|
|
29302
29481
|
probe,
|
|
29303
|
-
readCliVersion: () => readClaudeCliVersion({ recipe, host }),
|
|
29482
|
+
readCliVersion: (signal) => readClaudeCliVersion({ recipe, host, ...signal ? { signal } : {} }),
|
|
29304
29483
|
// `force: false` 立刻返回。每天那次探测自己按清单 TTL 决定要不要读;这里只服务「版本变了」和手动刷新。
|
|
29305
|
-
refreshModelCatalog: async ({ force }) => {
|
|
29484
|
+
refreshModelCatalog: async ({ force, signal }) => {
|
|
29485
|
+
signal?.throwIfAborted();
|
|
29306
29486
|
if (!force) return;
|
|
29487
|
+
let cleanupFailed = false;
|
|
29307
29488
|
try {
|
|
29308
|
-
await adapter.modelCatalog.refresh({ force: true });
|
|
29489
|
+
await adapter.modelCatalog.refresh({ force: true, signal });
|
|
29309
29490
|
} catch (error) {
|
|
29491
|
+
if (isOperationCleanupError3(error)) {
|
|
29492
|
+
cleanupFailed = true;
|
|
29493
|
+
throw error;
|
|
29494
|
+
}
|
|
29495
|
+
signal?.throwIfAborted();
|
|
29310
29496
|
host.log.warn("claude model catalog refresh failed", {
|
|
29311
29497
|
detail: error instanceof Error ? error.message : String(error)
|
|
29312
29498
|
});
|
|
29313
29499
|
} finally {
|
|
29314
|
-
adapter.modelCatalog.notePairedRefresh();
|
|
29500
|
+
if (!signal?.aborted && !cleanupFailed) adapter.modelCatalog.notePairedRefresh();
|
|
29315
29501
|
}
|
|
29316
29502
|
},
|
|
29317
29503
|
startSession: adapter.startSession,
|
|
@@ -29367,7 +29553,7 @@ function createClaudeInstance(config, host, attachments, overrides, usageCache)
|
|
|
29367
29553
|
start: async () => {
|
|
29368
29554
|
const command = claudeSignInCommand(
|
|
29369
29555
|
recipe.credentialsPath,
|
|
29370
|
-
|
|
29556
|
+
NodeOS10.type() === "Windows_NT" ? "win32" : "linux"
|
|
29371
29557
|
);
|
|
29372
29558
|
return {
|
|
29373
29559
|
operationId: `claude-sign-in-${crypto.randomUUID()}`,
|
|
@@ -29376,7 +29562,11 @@ function createClaudeInstance(config, host, attachments, overrides, usageCache)
|
|
|
29376
29562
|
},
|
|
29377
29563
|
cancel: async () => {
|
|
29378
29564
|
},
|
|
29379
|
-
verify: async (signal) =>
|
|
29565
|
+
verify: async (signal) => {
|
|
29566
|
+
await adapter.modelCatalog.refresh({ signal, force: true });
|
|
29567
|
+
adapter.modelCatalog.notePairedRefresh();
|
|
29568
|
+
return probe(signal);
|
|
29569
|
+
}
|
|
29380
29570
|
}
|
|
29381
29571
|
};
|
|
29382
29572
|
}
|
|
@@ -29395,7 +29585,7 @@ var executors = [
|
|
|
29395
29585
|
];
|
|
29396
29586
|
var index_default = definePlugin({
|
|
29397
29587
|
id: "agent-claude",
|
|
29398
|
-
apiVersion:
|
|
29588
|
+
apiVersion: 41,
|
|
29399
29589
|
executors,
|
|
29400
29590
|
activate(ctx) {
|
|
29401
29591
|
capturedAttachments = ctx.attachments;
|