@jun133/kitty 0.0.13 → 0.0.15
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 +19 -133
- package/dist/{App-V6SLDWQH.mjs → App-CBTIS4IK.mjs} +30 -18
- package/dist/{chunk-MMIH75OY.mjs → chunk-7FDXKNTM.mjs} +1612 -767
- package/dist/{chunk-DWGFLIQA.mjs → chunk-AQEMM5VH.mjs} +1 -1
- package/dist/{chunk-4BN45TQG.mjs → chunk-KUP5OMPB.mjs} +1 -1
- package/dist/{chunk-4HIVDFN5.mjs → chunk-NBKU7KA4.mjs} +1 -12
- package/dist/{chunk-3KMC6H5K.mjs → chunk-S4QTRPZ7.mjs} +238 -1221
- package/dist/{chunk-6WGSABUQ.mjs → chunk-WIKLME2V.mjs} +82 -14
- package/dist/cli.js +1477 -1438
- package/dist/cli.js.map +1 -1
- package/dist/{interactive-RSJ35TB5.mjs → interactive-BQMJFYHZ.mjs} +5 -5
- package/dist/{oneShot-7P5FDWFX.mjs → oneShot-4QBXBCNN.mjs} +3 -3
- package/dist/{session-XKWJHRVY.mjs → session-V7AYOK2Q.mjs} +2 -2
- package/dist/tui.mjs +106 -97
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -40,7 +40,7 @@ var init_package = __esm({
|
|
|
40
40
|
"package.json"() {
|
|
41
41
|
package_default = {
|
|
42
42
|
name: "@jun133/kitty",
|
|
43
|
-
version: "0.0.
|
|
43
|
+
version: "0.0.15",
|
|
44
44
|
description: "Agent",
|
|
45
45
|
license: "MIT",
|
|
46
46
|
keywords: [
|
|
@@ -120,7 +120,7 @@ function getErrorMessage(error) {
|
|
|
120
120
|
return "Environment error: network connection failed; the current provider/base URL is unreachable. Check network, proxy settings, or `KITTY_BASE_URL`.";
|
|
121
121
|
}
|
|
122
122
|
if (status === 404 || lower.includes("returned 404")) {
|
|
123
|
-
return "User-fixable error: provider returned 404. Check
|
|
123
|
+
return "User-fixable error: provider endpoint returned 404. Check `KITTY_PROVIDER`, `KITTY_MODEL`, and `KITTY_BASE_URL` as one provider profile; the selected provider may use Responses instead of Chat Completions.";
|
|
124
124
|
}
|
|
125
125
|
if (typeof status === "number" && status >= 500) {
|
|
126
126
|
return `Provider error: service returned ${status}. Retry later or confirm the provider service is healthy.`;
|
|
@@ -1917,14 +1917,21 @@ async function launchCommand(command, cwd, timeoutMs, abortSignal) {
|
|
|
1917
1917
|
function encodePowerShellCommand(command) {
|
|
1918
1918
|
const wrapped = [
|
|
1919
1919
|
"$ProgressPreference = 'SilentlyContinue'",
|
|
1920
|
+
"$ErrorActionPreference = 'Stop'",
|
|
1920
1921
|
"[Console]::InputEncoding = [System.Text.Encoding]::UTF8",
|
|
1921
1922
|
"[Console]::OutputEncoding = [System.Text.Encoding]::UTF8",
|
|
1922
1923
|
"$OutputEncoding = [System.Text.Encoding]::UTF8",
|
|
1923
1924
|
"try { chcp 65001 > $null } catch { }",
|
|
1925
|
+
"$code = 0",
|
|
1926
|
+
"try {",
|
|
1924
1927
|
`& { ${command} }`,
|
|
1925
1928
|
"$code = if ($null -ne $LASTEXITCODE) { [int]$LASTEXITCODE } elseif ($?) { 0 } else { 1 }",
|
|
1929
|
+
"} catch {",
|
|
1930
|
+
"[Console]::Error.WriteLine($_.Exception.Message)",
|
|
1931
|
+
"$code = 1",
|
|
1932
|
+
"}",
|
|
1926
1933
|
"exit $code"
|
|
1927
|
-
].join("
|
|
1934
|
+
].join("\n");
|
|
1928
1935
|
return Buffer.from(wrapped, "utf16le").toString("base64");
|
|
1929
1936
|
}
|
|
1930
1937
|
function buildCommandEnvironment() {
|
|
@@ -1943,6 +1950,26 @@ var init_launch = __esm({
|
|
|
1943
1950
|
}
|
|
1944
1951
|
});
|
|
1945
1952
|
|
|
1953
|
+
// src/utils/commandRunner/output.ts
|
|
1954
|
+
function normalizeCommandOutput(output) {
|
|
1955
|
+
if (!output.includes("#< CLIXML")) {
|
|
1956
|
+
return output;
|
|
1957
|
+
}
|
|
1958
|
+
const errors = [...output.matchAll(/<S\s+S="Error">([\s\S]*?)<\/S>/g)].map((match) => decodePowerShellText(match[1] ?? "")).map((line) => line.trimEnd()).filter(Boolean);
|
|
1959
|
+
if (errors.length === 0) {
|
|
1960
|
+
return output;
|
|
1961
|
+
}
|
|
1962
|
+
return errors.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
1963
|
+
}
|
|
1964
|
+
function decodePowerShellText(value) {
|
|
1965
|
+
return value.replace(/_x000D__x000A_/g, "\n").replace(/_x000D_/g, "\r").replace(/_x000A_/g, "\n").replace(/_x0009_/g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
1966
|
+
}
|
|
1967
|
+
var init_output = __esm({
|
|
1968
|
+
"src/utils/commandRunner/output.ts"() {
|
|
1969
|
+
"use strict";
|
|
1970
|
+
}
|
|
1971
|
+
});
|
|
1972
|
+
|
|
1946
1973
|
// src/extensions/tools/background/tools/backgroundRun.ts
|
|
1947
1974
|
function createBackgroundOutputTracker(onOutput) {
|
|
1948
1975
|
let buffer = "";
|
|
@@ -1978,6 +2005,7 @@ var init_backgroundRun = __esm({
|
|
|
1978
2005
|
"src/extensions/tools/background/tools/backgroundRun.ts"() {
|
|
1979
2006
|
"use strict";
|
|
1980
2007
|
init_launch();
|
|
2008
|
+
init_output();
|
|
1981
2009
|
init_fs();
|
|
1982
2010
|
init_shared2();
|
|
1983
2011
|
init_background();
|
|
@@ -2016,9 +2044,10 @@ var init_backgroundRun = __esm({
|
|
|
2016
2044
|
registerBackgroundProcess(job.id, subprocess);
|
|
2017
2045
|
store.markRunning(job.id, { pid: subprocess.pid ?? 0 });
|
|
2018
2046
|
const outputTracker = createBackgroundOutputTracker((output) => {
|
|
2047
|
+
const normalizedOutput = normalizeCommandOutput(output);
|
|
2019
2048
|
store.updateRunningOutput(job.id, {
|
|
2020
|
-
output,
|
|
2021
|
-
summary: summarizeBackgroundOutput(
|
|
2049
|
+
output: normalizedOutput,
|
|
2050
|
+
summary: summarizeBackgroundOutput(normalizedOutput),
|
|
2022
2051
|
lastOutputAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2023
2052
|
});
|
|
2024
2053
|
});
|
|
@@ -2028,7 +2057,7 @@ var init_backgroundRun = __esm({
|
|
|
2028
2057
|
void subprocess.then(async (result) => {
|
|
2029
2058
|
outputTracker.flush();
|
|
2030
2059
|
const running2 = store.load(job.id);
|
|
2031
|
-
const resultOutput = typeof result.all === "string" ? result.all : "";
|
|
2060
|
+
const resultOutput = normalizeCommandOutput(typeof result.all === "string" ? result.all : "");
|
|
2032
2061
|
const output = resultOutput || running2?.output || "";
|
|
2033
2062
|
store.close(job.id, {
|
|
2034
2063
|
status: result.exitCode === 0 ? "completed" : "failed",
|
|
@@ -2040,7 +2069,7 @@ var init_backgroundRun = __esm({
|
|
|
2040
2069
|
}, async (error) => {
|
|
2041
2070
|
outputTracker.flush();
|
|
2042
2071
|
const running2 = store.load(job.id);
|
|
2043
|
-
const errorOutput = typeof error.all === "string" ? error.all : "";
|
|
2072
|
+
const errorOutput = normalizeCommandOutput(typeof error.all === "string" ? error.all : "");
|
|
2044
2073
|
const output = errorOutput || running2?.output || String(error.message);
|
|
2045
2074
|
store.close(job.id, {
|
|
2046
2075
|
status: "failed",
|
|
@@ -3878,439 +3907,17 @@ var init_outputCapture = __esm({
|
|
|
3878
3907
|
}
|
|
3879
3908
|
});
|
|
3880
3909
|
|
|
3881
|
-
// src/utils/commandRunner/platformArgs.ts
|
|
3882
|
-
function splitByAndAnd(command) {
|
|
3883
|
-
const segments = [];
|
|
3884
|
-
let current = "";
|
|
3885
|
-
let inSingle = false;
|
|
3886
|
-
let inDouble = false;
|
|
3887
|
-
for (let index = 0; index < command.length; index += 1) {
|
|
3888
|
-
const char = command.charAt(index);
|
|
3889
|
-
if (char === "'" && !inDouble) {
|
|
3890
|
-
inSingle = !inSingle;
|
|
3891
|
-
current += char;
|
|
3892
|
-
continue;
|
|
3893
|
-
}
|
|
3894
|
-
if (char === '"' && !inSingle) {
|
|
3895
|
-
inDouble = !inDouble;
|
|
3896
|
-
current += char;
|
|
3897
|
-
continue;
|
|
3898
|
-
}
|
|
3899
|
-
if (!inSingle && !inDouble && char === "&" && command.charAt(index + 1) === "&") {
|
|
3900
|
-
if (current.trim()) {
|
|
3901
|
-
segments.push(current.trim());
|
|
3902
|
-
}
|
|
3903
|
-
current = "";
|
|
3904
|
-
index += 1;
|
|
3905
|
-
continue;
|
|
3906
|
-
}
|
|
3907
|
-
current += char;
|
|
3908
|
-
}
|
|
3909
|
-
if (current.trim()) {
|
|
3910
|
-
segments.push(current.trim());
|
|
3911
|
-
}
|
|
3912
|
-
return segments.length > 0 ? segments : [command];
|
|
3913
|
-
}
|
|
3914
|
-
function joinWithAndSemantics(segments) {
|
|
3915
|
-
if (segments.length <= 1) {
|
|
3916
|
-
return segments[0] ?? "";
|
|
3917
|
-
}
|
|
3918
|
-
let script = segments[0] ?? "";
|
|
3919
|
-
for (let index = 1; index < segments.length; index += 1) {
|
|
3920
|
-
const segment = segments[index];
|
|
3921
|
-
script += `; if ($?) { ${segment} }`;
|
|
3922
|
-
}
|
|
3923
|
-
return script;
|
|
3924
|
-
}
|
|
3925
|
-
function splitArgs(command) {
|
|
3926
|
-
const args = [];
|
|
3927
|
-
let current = "";
|
|
3928
|
-
let inSingle = false;
|
|
3929
|
-
let inDouble = false;
|
|
3930
|
-
for (let index = 0; index < command.length; index += 1) {
|
|
3931
|
-
const char = command.charAt(index);
|
|
3932
|
-
if (char === "'" && !inDouble) {
|
|
3933
|
-
inSingle = !inSingle;
|
|
3934
|
-
continue;
|
|
3935
|
-
}
|
|
3936
|
-
if (char === '"' && !inSingle) {
|
|
3937
|
-
inDouble = !inDouble;
|
|
3938
|
-
continue;
|
|
3939
|
-
}
|
|
3940
|
-
if (!inSingle && !inDouble && /\s/.test(char)) {
|
|
3941
|
-
if (current) {
|
|
3942
|
-
args.push(current);
|
|
3943
|
-
current = "";
|
|
3944
|
-
}
|
|
3945
|
-
continue;
|
|
3946
|
-
}
|
|
3947
|
-
current += char;
|
|
3948
|
-
}
|
|
3949
|
-
if (current) {
|
|
3950
|
-
args.push(current);
|
|
3951
|
-
}
|
|
3952
|
-
return args;
|
|
3953
|
-
}
|
|
3954
|
-
function expandPaths(paths) {
|
|
3955
|
-
return paths.flatMap((targetPath) => expandBraces(targetPath));
|
|
3956
|
-
}
|
|
3957
|
-
function normalizeWindowsPath(value) {
|
|
3958
|
-
if (value.includes("://")) {
|
|
3959
|
-
return value;
|
|
3960
|
-
}
|
|
3961
|
-
return value.replace(/\//g, "\\");
|
|
3962
|
-
}
|
|
3963
|
-
function quotePowerShell(value) {
|
|
3964
|
-
const escaped = value.replace(/'/g, "''");
|
|
3965
|
-
return `'${escaped}'`;
|
|
3966
|
-
}
|
|
3967
|
-
function expandBraces(input) {
|
|
3968
|
-
const start = findBraceStart(input);
|
|
3969
|
-
if (start === -1) {
|
|
3970
|
-
return [input];
|
|
3971
|
-
}
|
|
3972
|
-
const end = findMatchingBrace(input, start);
|
|
3973
|
-
if (end === -1) {
|
|
3974
|
-
return [input];
|
|
3975
|
-
}
|
|
3976
|
-
const prefix = input.slice(0, start);
|
|
3977
|
-
const suffix = input.slice(end + 1);
|
|
3978
|
-
const body = input.slice(start + 1, end);
|
|
3979
|
-
const parts = splitBraceParts(body);
|
|
3980
|
-
const expandedSuffix = expandBraces(suffix);
|
|
3981
|
-
const results = [];
|
|
3982
|
-
for (const part of parts) {
|
|
3983
|
-
for (const expandedPart of expandBraces(part)) {
|
|
3984
|
-
for (const tail of expandedSuffix) {
|
|
3985
|
-
results.push(`${prefix}${expandedPart}${tail}`);
|
|
3986
|
-
}
|
|
3987
|
-
}
|
|
3988
|
-
}
|
|
3989
|
-
return results;
|
|
3990
|
-
}
|
|
3991
|
-
function findBraceStart(input) {
|
|
3992
|
-
let inSingle = false;
|
|
3993
|
-
let inDouble = false;
|
|
3994
|
-
for (let index = 0; index < input.length; index += 1) {
|
|
3995
|
-
const char = input.charAt(index);
|
|
3996
|
-
if (char === "'" && !inDouble) {
|
|
3997
|
-
inSingle = !inSingle;
|
|
3998
|
-
continue;
|
|
3999
|
-
}
|
|
4000
|
-
if (char === '"' && !inSingle) {
|
|
4001
|
-
inDouble = !inDouble;
|
|
4002
|
-
continue;
|
|
4003
|
-
}
|
|
4004
|
-
if (!inSingle && !inDouble && char === "{") {
|
|
4005
|
-
return index;
|
|
4006
|
-
}
|
|
4007
|
-
}
|
|
4008
|
-
return -1;
|
|
4009
|
-
}
|
|
4010
|
-
function findMatchingBrace(input, start) {
|
|
4011
|
-
let depth = 0;
|
|
4012
|
-
let inSingle = false;
|
|
4013
|
-
let inDouble = false;
|
|
4014
|
-
for (let index = start; index < input.length; index += 1) {
|
|
4015
|
-
const char = input.charAt(index);
|
|
4016
|
-
if (char === "'" && !inDouble) {
|
|
4017
|
-
inSingle = !inSingle;
|
|
4018
|
-
continue;
|
|
4019
|
-
}
|
|
4020
|
-
if (char === '"' && !inSingle) {
|
|
4021
|
-
inDouble = !inDouble;
|
|
4022
|
-
continue;
|
|
4023
|
-
}
|
|
4024
|
-
if (inSingle || inDouble) {
|
|
4025
|
-
continue;
|
|
4026
|
-
}
|
|
4027
|
-
if (char === "{") {
|
|
4028
|
-
depth += 1;
|
|
4029
|
-
} else if (char === "}") {
|
|
4030
|
-
depth -= 1;
|
|
4031
|
-
if (depth === 0) {
|
|
4032
|
-
return index;
|
|
4033
|
-
}
|
|
4034
|
-
}
|
|
4035
|
-
}
|
|
4036
|
-
return -1;
|
|
4037
|
-
}
|
|
4038
|
-
function splitBraceParts(input) {
|
|
4039
|
-
const parts = [];
|
|
4040
|
-
let current = "";
|
|
4041
|
-
let depth = 0;
|
|
4042
|
-
for (let index = 0; index < input.length; index += 1) {
|
|
4043
|
-
const char = input.charAt(index);
|
|
4044
|
-
if (char === "{") {
|
|
4045
|
-
depth += 1;
|
|
4046
|
-
current += char;
|
|
4047
|
-
continue;
|
|
4048
|
-
}
|
|
4049
|
-
if (char === "}") {
|
|
4050
|
-
depth -= 1;
|
|
4051
|
-
current += char;
|
|
4052
|
-
continue;
|
|
4053
|
-
}
|
|
4054
|
-
if (char === "," && depth === 0) {
|
|
4055
|
-
parts.push(current);
|
|
4056
|
-
current = "";
|
|
4057
|
-
continue;
|
|
4058
|
-
}
|
|
4059
|
-
current += char;
|
|
4060
|
-
}
|
|
4061
|
-
if (current) {
|
|
4062
|
-
parts.push(current);
|
|
4063
|
-
}
|
|
4064
|
-
return parts.length > 0 ? parts : [input];
|
|
4065
|
-
}
|
|
4066
|
-
var init_platformArgs = __esm({
|
|
4067
|
-
"src/utils/commandRunner/platformArgs.ts"() {
|
|
4068
|
-
"use strict";
|
|
4069
|
-
}
|
|
4070
|
-
});
|
|
4071
|
-
|
|
4072
|
-
// src/utils/commandRunner/platformTransforms.ts
|
|
4073
|
-
function startsWithExplicitShell(command) {
|
|
4074
|
-
return /^\s*(cmd(?:\.exe)?\s+\/c|powershell(?:\.exe)?\b|pwsh\b|bash\b)/i.test(command);
|
|
4075
|
-
}
|
|
4076
|
-
function normalizeWindowsSegment(segment) {
|
|
4077
|
-
const trimmed = segment.trim();
|
|
4078
|
-
if (!trimmed) {
|
|
4079
|
-
return segment;
|
|
4080
|
-
}
|
|
4081
|
-
const lowered = trimmed.toLowerCase();
|
|
4082
|
-
if (lowered.startsWith("get-childitem") || lowered.startsWith("new-item")) {
|
|
4083
|
-
return segment;
|
|
4084
|
-
}
|
|
4085
|
-
if (lowered.startsWith("ls")) {
|
|
4086
|
-
return normalizeLsSegment(trimmed);
|
|
4087
|
-
}
|
|
4088
|
-
if (lowered.startsWith("mkdir") || lowered.startsWith("md ")) {
|
|
4089
|
-
return normalizeMkdirSegment(trimmed);
|
|
4090
|
-
}
|
|
4091
|
-
if (lowered.startsWith("rm ")) {
|
|
4092
|
-
return normalizeRemoveSegment(trimmed);
|
|
4093
|
-
}
|
|
4094
|
-
if (lowered.startsWith("cp ")) {
|
|
4095
|
-
return normalizeCopySegment(trimmed);
|
|
4096
|
-
}
|
|
4097
|
-
if (lowered.startsWith("mv ")) {
|
|
4098
|
-
return normalizeMoveSegment(trimmed);
|
|
4099
|
-
}
|
|
4100
|
-
if (lowered.startsWith("touch ")) {
|
|
4101
|
-
return normalizeTouchSegment(trimmed);
|
|
4102
|
-
}
|
|
4103
|
-
if (lowered.startsWith("cat ")) {
|
|
4104
|
-
return normalizeCatSegment(trimmed);
|
|
4105
|
-
}
|
|
4106
|
-
return segment;
|
|
4107
|
-
}
|
|
4108
|
-
function normalizeLsSegment(segment) {
|
|
4109
|
-
const args = splitArgs(segment).slice(1);
|
|
4110
|
-
const flags = args.filter((arg) => arg.startsWith("-"));
|
|
4111
|
-
const paths = args.filter((arg) => !arg.startsWith("-"));
|
|
4112
|
-
const force = flags.some((flag) => flag.includes("a"));
|
|
4113
|
-
const targetPath = paths[0];
|
|
4114
|
-
let command = "Get-ChildItem";
|
|
4115
|
-
if (force) {
|
|
4116
|
-
command += " -Force";
|
|
4117
|
-
}
|
|
4118
|
-
if (targetPath) {
|
|
4119
|
-
command += ` -LiteralPath ${quotePowerShell(normalizeWindowsPath(targetPath))}`;
|
|
4120
|
-
}
|
|
4121
|
-
return command;
|
|
4122
|
-
}
|
|
4123
|
-
function normalizeMkdirSegment(segment) {
|
|
4124
|
-
const args = splitArgs(segment);
|
|
4125
|
-
if (args.length <= 1) {
|
|
4126
|
-
return segment;
|
|
4127
|
-
}
|
|
4128
|
-
const rest = args.slice(1);
|
|
4129
|
-
let hasParents = false;
|
|
4130
|
-
const paths = rest.filter((arg) => {
|
|
4131
|
-
const lowered = arg.toLowerCase();
|
|
4132
|
-
if (lowered === "-p" || lowered === "--parents") {
|
|
4133
|
-
hasParents = true;
|
|
4134
|
-
return false;
|
|
4135
|
-
}
|
|
4136
|
-
return true;
|
|
4137
|
-
});
|
|
4138
|
-
const needsNormalization = hasParents || paths.some((targetPath) => targetPath.includes("{"));
|
|
4139
|
-
if (!needsNormalization) {
|
|
4140
|
-
return segment;
|
|
4141
|
-
}
|
|
4142
|
-
const expanded = expandPaths(paths);
|
|
4143
|
-
if (expanded.length === 0) {
|
|
4144
|
-
return segment;
|
|
4145
|
-
}
|
|
4146
|
-
const normalizedPaths = expanded.map((targetPath) => quotePowerShell(normalizeWindowsPath(targetPath)));
|
|
4147
|
-
return `New-Item -ItemType Directory -Force -Path ${normalizedPaths.join(", ")}`;
|
|
4148
|
-
}
|
|
4149
|
-
function normalizeRemoveSegment(segment) {
|
|
4150
|
-
const args = splitArgs(segment);
|
|
4151
|
-
if (args.length <= 1) {
|
|
4152
|
-
return segment;
|
|
4153
|
-
}
|
|
4154
|
-
const flags = args.slice(1).filter((arg) => arg.startsWith("-"));
|
|
4155
|
-
const paths = args.slice(1).filter((arg) => !arg.startsWith("-"));
|
|
4156
|
-
if (paths.length === 0) {
|
|
4157
|
-
return segment;
|
|
4158
|
-
}
|
|
4159
|
-
const recurse = flags.some((flag) => /r/i.test(flag));
|
|
4160
|
-
const force = flags.some((flag) => /f/i.test(flag));
|
|
4161
|
-
let command = "Remove-Item";
|
|
4162
|
-
if (recurse) {
|
|
4163
|
-
command += " -Recurse";
|
|
4164
|
-
}
|
|
4165
|
-
if (force) {
|
|
4166
|
-
command += " -Force";
|
|
4167
|
-
}
|
|
4168
|
-
command += ` -LiteralPath ${paths.map((targetPath) => quotePowerShell(normalizeWindowsPath(targetPath))).join(", ")}`;
|
|
4169
|
-
return command;
|
|
4170
|
-
}
|
|
4171
|
-
function normalizeCopySegment(segment) {
|
|
4172
|
-
const args = splitArgs(segment);
|
|
4173
|
-
if (args.length < 3) {
|
|
4174
|
-
return segment;
|
|
4175
|
-
}
|
|
4176
|
-
const flags = args.slice(1).filter((arg) => arg.startsWith("-"));
|
|
4177
|
-
const paths = args.slice(1).filter((arg) => !arg.startsWith("-"));
|
|
4178
|
-
if (paths.length < 2) {
|
|
4179
|
-
return segment;
|
|
4180
|
-
}
|
|
4181
|
-
const recurse = flags.some((flag) => /r/i.test(flag));
|
|
4182
|
-
const force = flags.some((flag) => /f/i.test(flag));
|
|
4183
|
-
const destination = paths[paths.length - 1];
|
|
4184
|
-
if (!destination) {
|
|
4185
|
-
return segment;
|
|
4186
|
-
}
|
|
4187
|
-
const sources = paths.slice(0, -1);
|
|
4188
|
-
let command = "Copy-Item";
|
|
4189
|
-
if (recurse) {
|
|
4190
|
-
command += " -Recurse";
|
|
4191
|
-
}
|
|
4192
|
-
if (force) {
|
|
4193
|
-
command += " -Force";
|
|
4194
|
-
}
|
|
4195
|
-
command += ` -Path ${sources.map((targetPath) => quotePowerShell(normalizeWindowsPath(targetPath))).join(", ")}`;
|
|
4196
|
-
command += ` -Destination ${quotePowerShell(normalizeWindowsPath(destination))}`;
|
|
4197
|
-
return command;
|
|
4198
|
-
}
|
|
4199
|
-
function normalizeMoveSegment(segment) {
|
|
4200
|
-
const args = splitArgs(segment);
|
|
4201
|
-
if (args.length < 3) {
|
|
4202
|
-
return segment;
|
|
4203
|
-
}
|
|
4204
|
-
const flags = args.slice(1).filter((arg) => arg.startsWith("-"));
|
|
4205
|
-
const paths = args.slice(1).filter((arg) => !arg.startsWith("-"));
|
|
4206
|
-
if (paths.length < 2) {
|
|
4207
|
-
return segment;
|
|
4208
|
-
}
|
|
4209
|
-
const force = flags.some((flag) => /f/i.test(flag));
|
|
4210
|
-
const destination = paths[paths.length - 1];
|
|
4211
|
-
if (!destination) {
|
|
4212
|
-
return segment;
|
|
4213
|
-
}
|
|
4214
|
-
const sources = paths.slice(0, -1);
|
|
4215
|
-
let command = "Move-Item";
|
|
4216
|
-
if (force) {
|
|
4217
|
-
command += " -Force";
|
|
4218
|
-
}
|
|
4219
|
-
command += ` -Path ${sources.map((targetPath) => quotePowerShell(normalizeWindowsPath(targetPath))).join(", ")}`;
|
|
4220
|
-
command += ` -Destination ${quotePowerShell(normalizeWindowsPath(destination))}`;
|
|
4221
|
-
return command;
|
|
4222
|
-
}
|
|
4223
|
-
function normalizeTouchSegment(segment) {
|
|
4224
|
-
const args = splitArgs(segment).slice(1);
|
|
4225
|
-
if (args.length === 0) {
|
|
4226
|
-
return segment;
|
|
4227
|
-
}
|
|
4228
|
-
const expanded = expandPaths(args);
|
|
4229
|
-
if (expanded.length === 0) {
|
|
4230
|
-
return segment;
|
|
4231
|
-
}
|
|
4232
|
-
const paths = expanded.map((targetPath) => quotePowerShell(normalizeWindowsPath(targetPath)));
|
|
4233
|
-
return `New-Item -ItemType File -Force -Path ${paths.join(", ")}`;
|
|
4234
|
-
}
|
|
4235
|
-
function normalizeCatSegment(segment) {
|
|
4236
|
-
const args = splitArgs(segment).slice(1);
|
|
4237
|
-
if (args.length === 0) {
|
|
4238
|
-
return segment;
|
|
4239
|
-
}
|
|
4240
|
-
const targetPath = args[0];
|
|
4241
|
-
if (!targetPath) {
|
|
4242
|
-
return segment;
|
|
4243
|
-
}
|
|
4244
|
-
return `Get-Content -LiteralPath ${quotePowerShell(normalizeWindowsPath(targetPath))}`;
|
|
4245
|
-
}
|
|
4246
|
-
var init_platformTransforms = __esm({
|
|
4247
|
-
"src/utils/commandRunner/platformTransforms.ts"() {
|
|
4248
|
-
"use strict";
|
|
4249
|
-
init_platformArgs();
|
|
4250
|
-
}
|
|
4251
|
-
});
|
|
4252
|
-
|
|
4253
|
-
// src/utils/commandRunner/platform.ts
|
|
4254
|
-
function normalizeCommandForPlatform(command) {
|
|
4255
|
-
if (process.platform !== "win32") {
|
|
4256
|
-
return command;
|
|
4257
|
-
}
|
|
4258
|
-
const trimmed = command.trim();
|
|
4259
|
-
if (!trimmed) {
|
|
4260
|
-
return command;
|
|
4261
|
-
}
|
|
4262
|
-
const normalized = normalizeWindowsCommand(trimmed);
|
|
4263
|
-
return normalizeNpmCommandNames(normalized);
|
|
4264
|
-
}
|
|
4265
|
-
function normalizeWindowsCommand(command) {
|
|
4266
|
-
if (startsWithExplicitShell(command)) {
|
|
4267
|
-
return command;
|
|
4268
|
-
}
|
|
4269
|
-
const segments = splitByAndAnd(command);
|
|
4270
|
-
const normalizedSegments = segments.map((segment) => normalizeWindowsSegment(segment));
|
|
4271
|
-
return joinWithAndSemantics(normalizedSegments);
|
|
4272
|
-
}
|
|
4273
|
-
function normalizeNpmCommandNames(command) {
|
|
4274
|
-
const commandNames = {
|
|
4275
|
-
npm: "npm.cmd",
|
|
4276
|
-
npx: "npx.cmd",
|
|
4277
|
-
pnpm: "pnpm.cmd",
|
|
4278
|
-
yarn: "yarn.cmd"
|
|
4279
|
-
};
|
|
4280
|
-
const pattern = /(^|[;&|]|\&\&)\s*(npm|npx|pnpm|yarn)(?=\s|$)/gi;
|
|
4281
|
-
return command.replace(pattern, (match, prefix, tool) => {
|
|
4282
|
-
const replacement = commandNames[String(tool).toLowerCase()];
|
|
4283
|
-
if (!replacement) {
|
|
4284
|
-
return match;
|
|
4285
|
-
}
|
|
4286
|
-
if (!prefix) {
|
|
4287
|
-
return replacement;
|
|
4288
|
-
}
|
|
4289
|
-
return `${prefix} ${replacement}`;
|
|
4290
|
-
});
|
|
4291
|
-
}
|
|
4292
|
-
var init_platform = __esm({
|
|
4293
|
-
"src/utils/commandRunner/platform.ts"() {
|
|
4294
|
-
"use strict";
|
|
4295
|
-
init_platformArgs();
|
|
4296
|
-
init_platformTransforms();
|
|
4297
|
-
}
|
|
4298
|
-
});
|
|
4299
|
-
|
|
4300
3910
|
// src/utils/commandRunner/run.ts
|
|
4301
3911
|
async function runCommandWithPolicy(options) {
|
|
4302
|
-
|
|
4303
|
-
return runCommandOnce({
|
|
4304
|
-
...options,
|
|
4305
|
-
command: normalizedCommand
|
|
4306
|
-
});
|
|
3912
|
+
return runCommandOnce(options);
|
|
4307
3913
|
}
|
|
4308
3914
|
async function runCommandOnce(options) {
|
|
4309
3915
|
const start = Date.now();
|
|
4310
3916
|
let stalled = false;
|
|
4311
3917
|
let stallTimer = null;
|
|
4312
3918
|
let forceKillTimer = null;
|
|
4313
|
-
const
|
|
3919
|
+
const launched = await launchCommand(options.command, options.cwd, options.timeoutMs, options.abortSignal);
|
|
3920
|
+
const { subprocess } = launched;
|
|
4314
3921
|
const outputCapture = await createBashOutputCapture(options.outputCapture ?? {});
|
|
4315
3922
|
const clearTimers = () => {
|
|
4316
3923
|
if (stallTimer) {
|
|
@@ -4363,9 +3970,11 @@ async function runCommandOnce(options) {
|
|
|
4363
3970
|
const result = await subprocess;
|
|
4364
3971
|
clearTimers();
|
|
4365
3972
|
const shellOutput = await outputCapture.finalize();
|
|
3973
|
+
const output = normalizeCommandOutput(shellOutput.outputPreview);
|
|
4366
3974
|
return {
|
|
3975
|
+
command: options.command,
|
|
4367
3976
|
exitCode: typeof result.exitCode === "number" ? result.exitCode : null,
|
|
4368
|
-
output
|
|
3977
|
+
output,
|
|
4369
3978
|
outputPath: shellOutput.outputPath,
|
|
4370
3979
|
truncated: shellOutput.truncated,
|
|
4371
3980
|
outputChars: shellOutput.outputChars,
|
|
@@ -4380,9 +3989,12 @@ async function runCommandOnce(options) {
|
|
|
4380
3989
|
const timedOut = isTimedOutError(error);
|
|
4381
3990
|
clearTimers();
|
|
4382
3991
|
const shellOutput = await outputCapture.finalize();
|
|
3992
|
+
const fallbackOutput = shellOutput.outputChars > 0 ? shellOutput.outputPreview : readProcessOutput(error);
|
|
3993
|
+
const output = normalizeCommandOutput(fallbackOutput);
|
|
4383
3994
|
return {
|
|
3995
|
+
command: options.command,
|
|
4384
3996
|
exitCode: readExitCode(error),
|
|
4385
|
-
output
|
|
3997
|
+
output,
|
|
4386
3998
|
outputPath: shellOutput.outputPath,
|
|
4387
3999
|
truncated: shellOutput.truncated,
|
|
4388
4000
|
outputChars: shellOutput.outputChars,
|
|
@@ -4423,7 +4035,7 @@ var init_run = __esm({
|
|
|
4423
4035
|
init_abort();
|
|
4424
4036
|
init_outputCapture();
|
|
4425
4037
|
init_launch();
|
|
4426
|
-
|
|
4038
|
+
init_output();
|
|
4427
4039
|
STALL_KILL_TIMEOUT_MS = 5e3;
|
|
4428
4040
|
}
|
|
4429
4041
|
});
|
|
@@ -6493,81 +6105,325 @@ var init_config = __esm({
|
|
|
6493
6105
|
}
|
|
6494
6106
|
});
|
|
6495
6107
|
|
|
6496
|
-
// src/provider/
|
|
6497
|
-
function
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
doctorProbeTimeoutMs: DEFAULT_DOCTOR_PROBE_TIMEOUT_MS
|
|
6510
|
-
};
|
|
6108
|
+
// src/provider/catalog.ts
|
|
6109
|
+
function listModelInfos() {
|
|
6110
|
+
return [...MODEL_CATALOG];
|
|
6111
|
+
}
|
|
6112
|
+
function findProviderInfo(providerId) {
|
|
6113
|
+
return PROVIDER_CATALOG.find((provider) => provider.id === normalizeProviderId(providerId));
|
|
6114
|
+
}
|
|
6115
|
+
function findModelInfo(providerId, modelId) {
|
|
6116
|
+
const normalizedProvider = normalizeProviderId(providerId);
|
|
6117
|
+
const normalizedModel = normalizeModelId(modelId);
|
|
6118
|
+
const known = MODEL_CATALOG.find((model) => model.providerId === normalizedProvider && model.id === normalizedModel);
|
|
6119
|
+
if (known) {
|
|
6120
|
+
return known;
|
|
6511
6121
|
}
|
|
6512
|
-
if (
|
|
6513
|
-
return
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
};
|
|
6122
|
+
if (normalizedProvider === "openai-compatible") {
|
|
6123
|
+
return createOpenAiCompatibleModelInfo(normalizedModel);
|
|
6124
|
+
}
|
|
6125
|
+
return void 0;
|
|
6126
|
+
}
|
|
6127
|
+
function resolveModelProfile(input) {
|
|
6128
|
+
const configuredProvider = normalizeProviderId(input.provider);
|
|
6129
|
+
const configuredModel = normalizeModelId(input.model);
|
|
6130
|
+
const provider = findProviderInfo(configuredProvider);
|
|
6131
|
+
if (!provider) {
|
|
6132
|
+
throw new Error(`Unknown provider: ${configuredProvider}. Check KITTY_PROVIDER.`);
|
|
6133
|
+
}
|
|
6134
|
+
const model = findModelInfo(configuredProvider, configuredModel);
|
|
6135
|
+
if (!model) {
|
|
6136
|
+
throw new Error(`Unknown model for provider ${configuredProvider}: ${configuredModel}. Check KITTY_MODEL.`);
|
|
6523
6137
|
}
|
|
6524
6138
|
return {
|
|
6525
6139
|
provider,
|
|
6526
6140
|
model,
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
defaultReasoningEnabled: false,
|
|
6530
|
-
requestTimeoutMs: DEFAULT_REQUEST_TIMEOUT_MS,
|
|
6531
|
-
doctorProbeTimeoutMs: DEFAULT_DOCTOR_PROBE_TIMEOUT_MS
|
|
6141
|
+
configuredProvider,
|
|
6142
|
+
configuredModel
|
|
6532
6143
|
};
|
|
6533
6144
|
}
|
|
6534
|
-
function
|
|
6145
|
+
function normalizeProviderId(value) {
|
|
6535
6146
|
const normalized = String(value ?? "").trim().toLowerCase();
|
|
6536
|
-
return normalized ||
|
|
6147
|
+
return normalized || "openai-compatible";
|
|
6537
6148
|
}
|
|
6538
|
-
function
|
|
6149
|
+
function normalizeModelId(value) {
|
|
6539
6150
|
return String(value ?? "").trim();
|
|
6540
6151
|
}
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6152
|
+
function createOpenAiCompatibleModelInfo(modelId) {
|
|
6153
|
+
return {
|
|
6154
|
+
id: modelId,
|
|
6155
|
+
providerId: "openai-compatible",
|
|
6156
|
+
label: modelId,
|
|
6157
|
+
wireApi: "chat.completions",
|
|
6158
|
+
capabilities: {
|
|
6159
|
+
tools: true,
|
|
6160
|
+
reasoning: false,
|
|
6161
|
+
reasoningContentReplay: "never",
|
|
6162
|
+
streaming: true,
|
|
6163
|
+
usage: true,
|
|
6164
|
+
cache: "none"
|
|
6165
|
+
},
|
|
6166
|
+
request: {
|
|
6167
|
+
thinkingDefault: "disabled",
|
|
6168
|
+
maxOutputTokensParam: "max_tokens"
|
|
6169
|
+
},
|
|
6170
|
+
limit: {
|
|
6171
|
+
context: 128e3,
|
|
6172
|
+
output: 8e3
|
|
6173
|
+
}
|
|
6174
|
+
};
|
|
6175
|
+
}
|
|
6176
|
+
var DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_DOCTOR_PROBE_TIMEOUT_MS, RELAY_REQUEST_TIMEOUT_MS, RELAY_DOCTOR_PROBE_TIMEOUT_MS, PROVIDER_CATALOG, DEEPSEEK_MODEL_BASE, GPT_RESPONSES_MODEL_BASE, MODEL_CATALOG;
|
|
6177
|
+
var init_catalog = __esm({
|
|
6178
|
+
"src/provider/catalog.ts"() {
|
|
6544
6179
|
"use strict";
|
|
6545
|
-
DEFAULT_PROVIDER = "openai-compatible";
|
|
6546
6180
|
DEFAULT_REQUEST_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
6547
6181
|
DEFAULT_DOCTOR_PROBE_TIMEOUT_MS = 1e4;
|
|
6548
6182
|
RELAY_REQUEST_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
6549
6183
|
RELAY_DOCTOR_PROBE_TIMEOUT_MS = 45e3;
|
|
6184
|
+
PROVIDER_CATALOG = [
|
|
6185
|
+
{
|
|
6186
|
+
id: "deepseek",
|
|
6187
|
+
label: "DeepSeek official",
|
|
6188
|
+
apiKind: "deepseek-openai-compatible",
|
|
6189
|
+
transport: "standard",
|
|
6190
|
+
defaultBaseUrl: "https://api.deepseek.com",
|
|
6191
|
+
requestTimeoutMs: DEFAULT_REQUEST_TIMEOUT_MS,
|
|
6192
|
+
doctorProbeTimeoutMs: DEFAULT_DOCTOR_PROBE_TIMEOUT_MS
|
|
6193
|
+
},
|
|
6194
|
+
{
|
|
6195
|
+
id: "yls",
|
|
6196
|
+
label: "YLS Codex",
|
|
6197
|
+
apiKind: "openai-sdk",
|
|
6198
|
+
transport: "relay",
|
|
6199
|
+
defaultBaseUrl: "https://code.ylsagi.com/codex",
|
|
6200
|
+
requestTimeoutMs: RELAY_REQUEST_TIMEOUT_MS,
|
|
6201
|
+
doctorProbeTimeoutMs: RELAY_DOCTOR_PROBE_TIMEOUT_MS
|
|
6202
|
+
},
|
|
6203
|
+
{
|
|
6204
|
+
id: "ttapi",
|
|
6205
|
+
label: "TTAPI",
|
|
6206
|
+
apiKind: "openai-sdk",
|
|
6207
|
+
transport: "relay",
|
|
6208
|
+
defaultBaseUrl: "https://w.ciykj.cn",
|
|
6209
|
+
requestTimeoutMs: RELAY_REQUEST_TIMEOUT_MS,
|
|
6210
|
+
doctorProbeTimeoutMs: RELAY_DOCTOR_PROBE_TIMEOUT_MS
|
|
6211
|
+
},
|
|
6212
|
+
{
|
|
6213
|
+
id: "openai",
|
|
6214
|
+
label: "OpenAI official",
|
|
6215
|
+
apiKind: "openai-sdk",
|
|
6216
|
+
transport: "standard",
|
|
6217
|
+
defaultBaseUrl: "https://api.openai.com/v1",
|
|
6218
|
+
requestTimeoutMs: RELAY_REQUEST_TIMEOUT_MS,
|
|
6219
|
+
doctorProbeTimeoutMs: RELAY_DOCTOR_PROBE_TIMEOUT_MS
|
|
6220
|
+
},
|
|
6221
|
+
{
|
|
6222
|
+
id: "openai-compatible",
|
|
6223
|
+
label: "OpenAI-compatible",
|
|
6224
|
+
apiKind: "openai-compatible",
|
|
6225
|
+
transport: "standard",
|
|
6226
|
+
defaultBaseUrl: "",
|
|
6227
|
+
requestTimeoutMs: DEFAULT_REQUEST_TIMEOUT_MS,
|
|
6228
|
+
doctorProbeTimeoutMs: DEFAULT_DOCTOR_PROBE_TIMEOUT_MS
|
|
6229
|
+
}
|
|
6230
|
+
];
|
|
6231
|
+
DEEPSEEK_MODEL_BASE = {
|
|
6232
|
+
wireApi: "chat.completions",
|
|
6233
|
+
capabilities: {
|
|
6234
|
+
tools: true,
|
|
6235
|
+
reasoning: true,
|
|
6236
|
+
reasoningContentReplay: "tool-call-required",
|
|
6237
|
+
streaming: true,
|
|
6238
|
+
usage: true,
|
|
6239
|
+
cache: "provider-automatic"
|
|
6240
|
+
},
|
|
6241
|
+
request: {
|
|
6242
|
+
thinkingDefault: "enabled",
|
|
6243
|
+
reasoningEffortDefault: "max",
|
|
6244
|
+
maxOutputTokensParam: "max_tokens"
|
|
6245
|
+
},
|
|
6246
|
+
limit: {
|
|
6247
|
+
context: 128e3,
|
|
6248
|
+
output: 8e3
|
|
6249
|
+
}
|
|
6250
|
+
};
|
|
6251
|
+
GPT_RESPONSES_MODEL_BASE = {
|
|
6252
|
+
wireApi: "responses",
|
|
6253
|
+
capabilities: {
|
|
6254
|
+
tools: true,
|
|
6255
|
+
reasoning: true,
|
|
6256
|
+
reasoningContentReplay: "never",
|
|
6257
|
+
streaming: true,
|
|
6258
|
+
usage: true,
|
|
6259
|
+
cache: "prompt-cache-key"
|
|
6260
|
+
},
|
|
6261
|
+
request: {
|
|
6262
|
+
thinkingDefault: "enabled",
|
|
6263
|
+
reasoningEffortDefault: "high",
|
|
6264
|
+
maxOutputTokensParam: "max_output_tokens"
|
|
6265
|
+
},
|
|
6266
|
+
limit: {
|
|
6267
|
+
context: 4e5,
|
|
6268
|
+
output: 128e3
|
|
6269
|
+
}
|
|
6270
|
+
};
|
|
6271
|
+
MODEL_CATALOG = [
|
|
6272
|
+
{
|
|
6273
|
+
id: "deepseek-v4-flash",
|
|
6274
|
+
providerId: "deepseek",
|
|
6275
|
+
label: "DeepSeek V4 Flash",
|
|
6276
|
+
...DEEPSEEK_MODEL_BASE
|
|
6277
|
+
},
|
|
6278
|
+
{
|
|
6279
|
+
id: "deepseek-v4-pro",
|
|
6280
|
+
providerId: "deepseek",
|
|
6281
|
+
label: "DeepSeek V4 Pro",
|
|
6282
|
+
...DEEPSEEK_MODEL_BASE
|
|
6283
|
+
},
|
|
6284
|
+
{
|
|
6285
|
+
id: "gpt-5.5",
|
|
6286
|
+
providerId: "yls",
|
|
6287
|
+
label: "GPT-5.5 via YLS",
|
|
6288
|
+
...GPT_RESPONSES_MODEL_BASE
|
|
6289
|
+
},
|
|
6290
|
+
{
|
|
6291
|
+
id: "gpt-5.4",
|
|
6292
|
+
providerId: "yls",
|
|
6293
|
+
label: "GPT-5.4 via YLS",
|
|
6294
|
+
...GPT_RESPONSES_MODEL_BASE,
|
|
6295
|
+
request: {
|
|
6296
|
+
...GPT_RESPONSES_MODEL_BASE.request,
|
|
6297
|
+
reasoningEffortDefault: "xhigh"
|
|
6298
|
+
}
|
|
6299
|
+
},
|
|
6300
|
+
{
|
|
6301
|
+
id: "gpt-5.4",
|
|
6302
|
+
providerId: "ttapi",
|
|
6303
|
+
label: "GPT-5.4 via TTAPI",
|
|
6304
|
+
...GPT_RESPONSES_MODEL_BASE,
|
|
6305
|
+
request: {
|
|
6306
|
+
...GPT_RESPONSES_MODEL_BASE.request,
|
|
6307
|
+
thinkingDefault: "disabled",
|
|
6308
|
+
reasoningEffortDefault: "xhigh"
|
|
6309
|
+
}
|
|
6310
|
+
},
|
|
6311
|
+
{
|
|
6312
|
+
id: "gpt-5.5",
|
|
6313
|
+
providerId: "openai",
|
|
6314
|
+
label: "GPT-5.5",
|
|
6315
|
+
...GPT_RESPONSES_MODEL_BASE
|
|
6316
|
+
},
|
|
6317
|
+
{
|
|
6318
|
+
id: "gpt-5.4",
|
|
6319
|
+
providerId: "openai",
|
|
6320
|
+
label: "GPT-5.4",
|
|
6321
|
+
...GPT_RESPONSES_MODEL_BASE,
|
|
6322
|
+
request: {
|
|
6323
|
+
...GPT_RESPONSES_MODEL_BASE.request,
|
|
6324
|
+
reasoningEffortDefault: "xhigh"
|
|
6325
|
+
}
|
|
6326
|
+
}
|
|
6327
|
+
];
|
|
6328
|
+
}
|
|
6329
|
+
});
|
|
6330
|
+
|
|
6331
|
+
// src/provider/transport.ts
|
|
6332
|
+
function resolveProviderProbeKind(profile) {
|
|
6333
|
+
if (profile.provider.transport === "relay") {
|
|
6334
|
+
return profile.model.wireApi;
|
|
6335
|
+
}
|
|
6336
|
+
return "models";
|
|
6337
|
+
}
|
|
6338
|
+
function buildProviderProbeRequest(input) {
|
|
6339
|
+
return {
|
|
6340
|
+
endpoint: buildProviderProbeEndpoint(input.baseUrl, input.probe),
|
|
6341
|
+
method: input.probe === "models" ? "GET" : "POST",
|
|
6342
|
+
headers: {
|
|
6343
|
+
Authorization: `Bearer ${input.apiKey}`,
|
|
6344
|
+
...input.probe === "models" ? {} : { "Content-Type": "application/json" }
|
|
6345
|
+
},
|
|
6346
|
+
body: buildProviderProbeBody(input.probe, input.model)
|
|
6347
|
+
};
|
|
6348
|
+
}
|
|
6349
|
+
function buildProviderProbeEndpoint(baseUrl, probe) {
|
|
6350
|
+
if (probe === "responses") {
|
|
6351
|
+
return buildEndpoint(baseUrl, "responses");
|
|
6352
|
+
}
|
|
6353
|
+
if (probe === "chat.completions") {
|
|
6354
|
+
return buildEndpoint(baseUrl, "chat/completions");
|
|
6355
|
+
}
|
|
6356
|
+
return buildEndpoint(baseUrl, "models");
|
|
6357
|
+
}
|
|
6358
|
+
function buildProviderProbeBody(probe, model) {
|
|
6359
|
+
if (probe === "models") {
|
|
6360
|
+
return void 0;
|
|
6361
|
+
}
|
|
6362
|
+
if (probe === "responses") {
|
|
6363
|
+
return JSON.stringify({
|
|
6364
|
+
model,
|
|
6365
|
+
input: [
|
|
6366
|
+
{
|
|
6367
|
+
role: "user",
|
|
6368
|
+
content: "Return ok."
|
|
6369
|
+
}
|
|
6370
|
+
],
|
|
6371
|
+
max_output_tokens: 8
|
|
6372
|
+
});
|
|
6373
|
+
}
|
|
6374
|
+
return JSON.stringify({
|
|
6375
|
+
model,
|
|
6376
|
+
messages: [
|
|
6377
|
+
{
|
|
6378
|
+
role: "user",
|
|
6379
|
+
content: "Return ok."
|
|
6380
|
+
}
|
|
6381
|
+
],
|
|
6382
|
+
max_tokens: 8,
|
|
6383
|
+
stream: false
|
|
6384
|
+
});
|
|
6385
|
+
}
|
|
6386
|
+
function buildEndpoint(baseUrl, path59) {
|
|
6387
|
+
try {
|
|
6388
|
+
return new URL(path59, ensureTrailingSlash(baseUrl)).toString();
|
|
6389
|
+
} catch {
|
|
6390
|
+
throw new Error(
|
|
6391
|
+
`User-fixable error: \`KITTY_BASE_URL\` is not a valid URL: ${baseUrl}. Fix it and rerun \`kitty doctor\`.`
|
|
6392
|
+
);
|
|
6393
|
+
}
|
|
6394
|
+
}
|
|
6395
|
+
function ensureTrailingSlash(baseUrl) {
|
|
6396
|
+
return baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
6397
|
+
}
|
|
6398
|
+
var init_transport = __esm({
|
|
6399
|
+
"src/provider/transport.ts"() {
|
|
6400
|
+
"use strict";
|
|
6550
6401
|
}
|
|
6551
6402
|
});
|
|
6552
6403
|
|
|
6553
6404
|
// src/provider/connection.ts
|
|
6554
6405
|
async function probeProviderConnection(input) {
|
|
6555
|
-
const
|
|
6406
|
+
const profile = resolveModelProfile({
|
|
6556
6407
|
provider: input.provider,
|
|
6557
6408
|
model: input.model
|
|
6558
6409
|
});
|
|
6410
|
+
const probe = resolveProviderProbeKind(profile);
|
|
6559
6411
|
const fetchImpl = input.fetchImpl ?? fetch;
|
|
6560
|
-
const probeTimeoutMs =
|
|
6412
|
+
const probeTimeoutMs = profile.provider.doctorProbeTimeoutMs;
|
|
6561
6413
|
let lastFailure;
|
|
6562
6414
|
for (const candidateBaseUrl of buildProviderBaseUrlCandidates(input.baseUrl)) {
|
|
6563
|
-
const
|
|
6415
|
+
const request = buildProviderProbeRequest({
|
|
6416
|
+
baseUrl: candidateBaseUrl,
|
|
6417
|
+
apiKey: input.apiKey,
|
|
6418
|
+
model: profile.model.id,
|
|
6419
|
+
probe
|
|
6420
|
+
});
|
|
6564
6421
|
let response;
|
|
6565
6422
|
try {
|
|
6566
|
-
response = await fetchImpl(endpoint, {
|
|
6567
|
-
method:
|
|
6568
|
-
headers:
|
|
6569
|
-
|
|
6570
|
-
},
|
|
6423
|
+
response = await fetchImpl(request.endpoint, {
|
|
6424
|
+
method: request.method,
|
|
6425
|
+
headers: request.headers,
|
|
6426
|
+
body: request.body,
|
|
6571
6427
|
signal: AbortSignal.timeout(probeTimeoutMs)
|
|
6572
6428
|
});
|
|
6573
6429
|
} catch (error) {
|
|
@@ -6581,7 +6437,7 @@ async function probeProviderConnection(input) {
|
|
|
6581
6437
|
if (response.status === 404) {
|
|
6582
6438
|
lastFailure = {
|
|
6583
6439
|
kind: "user",
|
|
6584
|
-
message: `User-fixable error:
|
|
6440
|
+
message: `User-fixable error: provider endpoint returned 404 at ${request.endpoint}. Check \`KITTY_PROVIDER\`, \`KITTY_MODEL\`, and \`KITTY_BASE_URL\` together; this provider uses ${profile.model.wireApi}.`,
|
|
6585
6441
|
probeTimeoutMs
|
|
6586
6442
|
};
|
|
6587
6443
|
continue;
|
|
@@ -6607,10 +6463,27 @@ async function probeProviderConnection(input) {
|
|
|
6607
6463
|
probeTimeoutMs
|
|
6608
6464
|
};
|
|
6609
6465
|
}
|
|
6466
|
+
if (probe === "responses") {
|
|
6467
|
+
return {
|
|
6468
|
+
kind: "ok",
|
|
6469
|
+
probe: "responses",
|
|
6470
|
+
resolvedBaseUrl: candidateBaseUrl,
|
|
6471
|
+
probeTimeoutMs
|
|
6472
|
+
};
|
|
6473
|
+
}
|
|
6474
|
+
if (probe === "chat.completions") {
|
|
6475
|
+
return {
|
|
6476
|
+
kind: "ok",
|
|
6477
|
+
probe: "chat.completions",
|
|
6478
|
+
resolvedBaseUrl: candidateBaseUrl,
|
|
6479
|
+
probeTimeoutMs
|
|
6480
|
+
};
|
|
6481
|
+
}
|
|
6610
6482
|
const payload = await response.json().catch(() => null);
|
|
6611
6483
|
const models = Array.isArray(payload?.data) ? payload.data.length : 0;
|
|
6612
6484
|
return {
|
|
6613
6485
|
kind: "ok",
|
|
6486
|
+
probe: "models",
|
|
6614
6487
|
models,
|
|
6615
6488
|
resolvedBaseUrl: candidateBaseUrl,
|
|
6616
6489
|
probeTimeoutMs
|
|
@@ -6631,23 +6504,14 @@ function buildProviderBaseUrlCandidates(baseUrl) {
|
|
|
6631
6504
|
try {
|
|
6632
6505
|
const parsed = new URL(normalized);
|
|
6633
6506
|
if (parsed.pathname === "" || parsed.pathname === "/") {
|
|
6634
|
-
candidates.push(trimTrailingSlash(new URL("v1",
|
|
6507
|
+
candidates.push(trimTrailingSlash(new URL("v1", ensureTrailingSlash2(parsed.toString())).toString()));
|
|
6635
6508
|
}
|
|
6636
6509
|
} catch {
|
|
6637
6510
|
return candidates;
|
|
6638
6511
|
}
|
|
6639
6512
|
return [...new Set(candidates)];
|
|
6640
6513
|
}
|
|
6641
|
-
function
|
|
6642
|
-
try {
|
|
6643
|
-
return new URL("models", ensureTrailingSlash(baseUrl)).toString();
|
|
6644
|
-
} catch {
|
|
6645
|
-
throw new Error(
|
|
6646
|
-
`User-fixable error: \`KITTY_BASE_URL\` is not a valid URL: ${baseUrl}. Fix it and rerun \`kitty doctor\`.`
|
|
6647
|
-
);
|
|
6648
|
-
}
|
|
6649
|
-
}
|
|
6650
|
-
function ensureTrailingSlash(baseUrl) {
|
|
6514
|
+
function ensureTrailingSlash2(baseUrl) {
|
|
6651
6515
|
return baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
6652
6516
|
}
|
|
6653
6517
|
function trimTrailingSlash(baseUrl) {
|
|
@@ -6671,7 +6535,8 @@ function buildNetworkErrorMessage(baseUrl, error) {
|
|
|
6671
6535
|
var init_connection = __esm({
|
|
6672
6536
|
"src/provider/connection.ts"() {
|
|
6673
6537
|
"use strict";
|
|
6674
|
-
|
|
6538
|
+
init_catalog();
|
|
6539
|
+
init_transport();
|
|
6675
6540
|
}
|
|
6676
6541
|
});
|
|
6677
6542
|
|
|
@@ -6684,18 +6549,27 @@ var init_providerPresets = __esm({
|
|
|
6684
6549
|
"src/config/providerPresets.ts"() {
|
|
6685
6550
|
"use strict";
|
|
6686
6551
|
PROVIDER_PRESETS = [
|
|
6552
|
+
{
|
|
6553
|
+
label: "YLS Codex + GPT-5.5",
|
|
6554
|
+
provider: "yls",
|
|
6555
|
+
baseUrl: "https://code.ylsagi.com/codex",
|
|
6556
|
+
model: "gpt-5.5",
|
|
6557
|
+
thinking: "enabled",
|
|
6558
|
+
reasoningEffort: "high",
|
|
6559
|
+
activeByDefault: false
|
|
6560
|
+
},
|
|
6687
6561
|
{
|
|
6688
6562
|
label: "YLS Codex + GPT-5.4",
|
|
6689
|
-
provider: "
|
|
6563
|
+
provider: "yls",
|
|
6690
6564
|
baseUrl: "https://code.ylsagi.com/codex",
|
|
6691
6565
|
model: "gpt-5.4",
|
|
6692
|
-
thinking: "
|
|
6566
|
+
thinking: "enabled",
|
|
6693
6567
|
reasoningEffort: "xhigh",
|
|
6694
6568
|
activeByDefault: false
|
|
6695
6569
|
},
|
|
6696
6570
|
{
|
|
6697
6571
|
label: "TTAPI + GPT-5.4",
|
|
6698
|
-
provider: "
|
|
6572
|
+
provider: "ttapi",
|
|
6699
6573
|
baseUrl: "https://w.ciykj.cn",
|
|
6700
6574
|
model: "gpt-5.4",
|
|
6701
6575
|
thinking: "disabled",
|
|
@@ -6739,7 +6613,8 @@ async function inspectConfigPreflight(rootDir) {
|
|
|
6739
6613
|
const model = parsedEnv[KITTY_ENV.model] ?? "";
|
|
6740
6614
|
const baseUrl = parsedEnv[KITTY_ENV.baseUrl] ?? "";
|
|
6741
6615
|
const providerPreset = readProviderPresetLabel({ provider, model, baseUrl });
|
|
6742
|
-
const
|
|
6616
|
+
const catalog = readCatalogProfile({ provider, model });
|
|
6617
|
+
const ready = files.every((file) => file.exists) && missingKeys.length === 0 && !catalog.error;
|
|
6743
6618
|
return {
|
|
6744
6619
|
rootDir: normalizedRoot,
|
|
6745
6620
|
kittyDir,
|
|
@@ -6748,6 +6623,10 @@ async function inspectConfigPreflight(rootDir) {
|
|
|
6748
6623
|
activeKeys,
|
|
6749
6624
|
missingKeys,
|
|
6750
6625
|
providerPreset,
|
|
6626
|
+
providerProfile: catalog.providerProfile,
|
|
6627
|
+
modelProfile: catalog.modelProfile,
|
|
6628
|
+
wireApi: catalog.wireApi,
|
|
6629
|
+
catalogError: catalog.error,
|
|
6751
6630
|
provider,
|
|
6752
6631
|
model,
|
|
6753
6632
|
baseUrl,
|
|
@@ -6773,6 +6652,10 @@ function formatConfigPreflightReport(report) {
|
|
|
6773
6652
|
`model: ${report.env.model || "(missing)"}`,
|
|
6774
6653
|
`baseUrl: ${report.env.baseUrl || "(missing)"}`,
|
|
6775
6654
|
`provider preset: ${formatProviderPresetFact(report)}`,
|
|
6655
|
+
`provider profile: ${report.env.providerProfile ?? "(unresolved)"}`,
|
|
6656
|
+
`model profile: ${report.env.modelProfile ?? "(unresolved)"}`,
|
|
6657
|
+
`wire API: ${report.env.wireApi ?? "(unresolved)"}`,
|
|
6658
|
+
report.env.catalogError ? `catalog: ${report.env.catalogError}` : "catalog: ok",
|
|
6776
6659
|
`api key: ${report.env.apiKeyPresent ? "present" : "missing"}`,
|
|
6777
6660
|
`preflight: ${report.ready ? "ready" : "not_ready"}`,
|
|
6778
6661
|
"next:",
|
|
@@ -6821,6 +6704,23 @@ function readProviderPresetLabel(input) {
|
|
|
6821
6704
|
(preset) => preset.provider === input.provider && preset.model === input.model && preset.baseUrl === input.baseUrl
|
|
6822
6705
|
)?.label;
|
|
6823
6706
|
}
|
|
6707
|
+
function readCatalogProfile(input) {
|
|
6708
|
+
if (!input.provider || !input.model) {
|
|
6709
|
+
return {};
|
|
6710
|
+
}
|
|
6711
|
+
try {
|
|
6712
|
+
const profile = resolveModelProfile(input);
|
|
6713
|
+
return {
|
|
6714
|
+
providerProfile: profile.provider.label,
|
|
6715
|
+
modelProfile: profile.model.label,
|
|
6716
|
+
wireApi: profile.model.wireApi
|
|
6717
|
+
};
|
|
6718
|
+
} catch (error) {
|
|
6719
|
+
return {
|
|
6720
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6721
|
+
};
|
|
6722
|
+
}
|
|
6723
|
+
}
|
|
6824
6724
|
function formatProviderPresetFact(report) {
|
|
6825
6725
|
if (report.env.providerPreset) {
|
|
6826
6726
|
return report.env.providerPreset;
|
|
@@ -6847,6 +6747,7 @@ var init_preflight = __esm({
|
|
|
6847
6747
|
import_dotenv2 = __toESM(require("dotenv"));
|
|
6848
6748
|
init_envKeys();
|
|
6849
6749
|
init_providerPresets();
|
|
6750
|
+
init_catalog();
|
|
6850
6751
|
init_statePaths();
|
|
6851
6752
|
}
|
|
6852
6753
|
});
|
|
@@ -6901,6 +6802,16 @@ function registerDoctorCommand(program, options) {
|
|
|
6901
6802
|
ui.info(`provider: ${runtime.config.provider}`);
|
|
6902
6803
|
ui.info(`model: ${runtime.config.model}`);
|
|
6903
6804
|
ui.info(`baseUrl: ${runtime.config.baseUrl}`);
|
|
6805
|
+
const profile = resolveModelProfile({
|
|
6806
|
+
provider: runtime.config.provider,
|
|
6807
|
+
model: runtime.config.model
|
|
6808
|
+
});
|
|
6809
|
+
ui.info(`provider profile: ${profile.provider.label}`);
|
|
6810
|
+
ui.info(`model profile: ${profile.model.label}`);
|
|
6811
|
+
ui.info(`wire API: ${profile.model.wireApi}`);
|
|
6812
|
+
ui.info(`reasoning replay: ${profile.model.capabilities.reasoningContentReplay}`);
|
|
6813
|
+
ui.info(`context limit: ${profile.model.limit.context}`);
|
|
6814
|
+
ui.info(`output limit: ${profile.model.limit.output}`);
|
|
6904
6815
|
if (!runtime.config.apiKey.trim()) {
|
|
6905
6816
|
throw new Error(
|
|
6906
6817
|
"User-fixable error: API key not found. Set `KITTY_API_KEY` in the current project `.kitty/.env`, then rerun `kitty doctor`."
|
|
@@ -6914,7 +6825,7 @@ function registerDoctorCommand(program, options) {
|
|
|
6914
6825
|
apiKey: runtime.config.apiKey
|
|
6915
6826
|
});
|
|
6916
6827
|
if (diagnosis.kind === "ok") {
|
|
6917
|
-
ui.success(
|
|
6828
|
+
ui.success(formatProviderProbeSuccess(diagnosis));
|
|
6918
6829
|
if (diagnosis.resolvedBaseUrl !== runtime.config.baseUrl) {
|
|
6919
6830
|
ui.info(`resolvedBaseUrl: ${diagnosis.resolvedBaseUrl}`);
|
|
6920
6831
|
}
|
|
@@ -6927,12 +6838,19 @@ function registerDoctorCommand(program, options) {
|
|
|
6927
6838
|
throw new Error(diagnosis.message);
|
|
6928
6839
|
});
|
|
6929
6840
|
}
|
|
6841
|
+
function formatProviderProbeSuccess(diagnosis) {
|
|
6842
|
+
if (diagnosis.probe === "responses") {
|
|
6843
|
+
return "Provider reachable. responses probe ok";
|
|
6844
|
+
}
|
|
6845
|
+
return `Provider reachable. models=${diagnosis.models ?? 0}`;
|
|
6846
|
+
}
|
|
6930
6847
|
var import_node_path23;
|
|
6931
6848
|
var init_doctor = __esm({
|
|
6932
6849
|
"src/cli/commands/doctor.ts"() {
|
|
6933
6850
|
"use strict";
|
|
6934
6851
|
import_node_path23 = __toESM(require("path"));
|
|
6935
6852
|
init_connection();
|
|
6853
|
+
init_catalog();
|
|
6936
6854
|
init_preflight();
|
|
6937
6855
|
init_console();
|
|
6938
6856
|
init_stdio();
|
|
@@ -9300,7 +9218,7 @@ function isPathIgnored(targetPath, rules, isDirectory3 = false) {
|
|
|
9300
9218
|
if (!relativePath) {
|
|
9301
9219
|
continue;
|
|
9302
9220
|
}
|
|
9303
|
-
const candidate = isDirectory3 ?
|
|
9221
|
+
const candidate = isDirectory3 ? ensureTrailingSlash3(relativePath) : relativePath;
|
|
9304
9222
|
if (!rule.matcher.test(candidate)) {
|
|
9305
9223
|
continue;
|
|
9306
9224
|
}
|
|
@@ -9400,7 +9318,7 @@ function toRelativePosix(baseDir, targetPath) {
|
|
|
9400
9318
|
}
|
|
9401
9319
|
return relativePath.replace(/\\/g, "/");
|
|
9402
9320
|
}
|
|
9403
|
-
function
|
|
9321
|
+
function ensureTrailingSlash3(value) {
|
|
9404
9322
|
return value.endsWith("/") ? value : `${value}/`;
|
|
9405
9323
|
}
|
|
9406
9324
|
function normalizeFastGlobIgnorePattern(rule) {
|
|
@@ -10549,17 +10467,17 @@ __export(cachePolicy_exports, {
|
|
|
10549
10467
|
resolveProviderCachePolicy: () => resolveProviderCachePolicy
|
|
10550
10468
|
});
|
|
10551
10469
|
function resolveProviderCachePolicy(input) {
|
|
10552
|
-
const
|
|
10553
|
-
if (capabilities.
|
|
10470
|
+
const profile = resolveModelProfile(input);
|
|
10471
|
+
if (profile.model.capabilities.cache === "prompt-cache-key") {
|
|
10554
10472
|
return {
|
|
10555
10473
|
provider: "openai",
|
|
10556
10474
|
automaticPrefixCache: true,
|
|
10557
10475
|
promptCacheKey: buildPromptCacheKey(input)
|
|
10558
10476
|
};
|
|
10559
10477
|
}
|
|
10560
|
-
if (capabilities.
|
|
10478
|
+
if (profile.model.capabilities.cache === "provider-automatic") {
|
|
10561
10479
|
return {
|
|
10562
|
-
provider: "deepseek",
|
|
10480
|
+
provider: profile.provider.id === "deepseek" ? "deepseek" : "generic",
|
|
10563
10481
|
automaticPrefixCache: true
|
|
10564
10482
|
};
|
|
10565
10483
|
}
|
|
@@ -10586,852 +10504,33 @@ function stableHash(value) {
|
|
|
10586
10504
|
var init_cachePolicy = __esm({
|
|
10587
10505
|
"src/provider/cachePolicy.ts"() {
|
|
10588
10506
|
"use strict";
|
|
10589
|
-
|
|
10590
|
-
}
|
|
10591
|
-
});
|
|
10592
|
-
|
|
10593
|
-
// src/provider/apiRetry.ts
|
|
10594
|
-
async function withApiRetries(operation, abortSignal) {
|
|
10595
|
-
let lastError;
|
|
10596
|
-
for (let attempt = 1; attempt <= API_MAX_RETRIES; attempt += 1) {
|
|
10597
|
-
try {
|
|
10598
|
-
return await operation();
|
|
10599
|
-
} catch (error) {
|
|
10600
|
-
if (isAbortError(error)) {
|
|
10601
|
-
throw error;
|
|
10602
|
-
}
|
|
10603
|
-
lastError = error;
|
|
10604
|
-
if (!isRetryableApiError(error) || attempt === API_MAX_RETRIES) {
|
|
10605
|
-
break;
|
|
10606
|
-
}
|
|
10607
|
-
await sleepWithSignal(API_RETRY_BASE_DELAY_MS * attempt, abortSignal);
|
|
10608
|
-
}
|
|
10609
|
-
}
|
|
10610
|
-
throw lastError;
|
|
10611
|
-
}
|
|
10612
|
-
function isRetryableApiError(error) {
|
|
10613
|
-
const status = error.status;
|
|
10614
|
-
if (typeof status === "number") {
|
|
10615
|
-
return status === 408 || status === 409 || status === 429 || status >= 500;
|
|
10616
|
-
}
|
|
10617
|
-
const message = String(error.message ?? error).toLowerCase();
|
|
10618
|
-
return message.includes("timeout") || message.includes("network") || message.includes("connection error") || message.includes("connection reset") || message.includes("econnreset") || message.includes("econnrefused") || message.includes("connect timeout") || message.includes("temporarily") || message.includes("rate limit") || message.includes("overloaded");
|
|
10619
|
-
}
|
|
10620
|
-
var API_MAX_RETRIES, API_RETRY_BASE_DELAY_MS;
|
|
10621
|
-
var init_apiRetry = __esm({
|
|
10622
|
-
"src/provider/apiRetry.ts"() {
|
|
10623
|
-
"use strict";
|
|
10624
|
-
init_abort();
|
|
10625
|
-
API_MAX_RETRIES = 3;
|
|
10626
|
-
API_RETRY_BASE_DELAY_MS = 1200;
|
|
10627
|
-
}
|
|
10628
|
-
});
|
|
10629
|
-
|
|
10630
|
-
// src/provider/chatRequestBody.ts
|
|
10631
|
-
function buildProviderRequestBody(input) {
|
|
10632
|
-
const capabilities = resolveProviderCapabilities(input);
|
|
10633
|
-
const thinking = capabilities.provider === "deepseek" ? resolveDeepSeekThinking(input.messages, input.thinking ?? "enabled") : input.thinking;
|
|
10634
|
-
const body = {
|
|
10635
|
-
model: input.model,
|
|
10636
|
-
messages: toChatCompletionMessages(input.messages),
|
|
10637
|
-
tools: input.tools,
|
|
10638
|
-
stream: input.stream
|
|
10639
|
-
};
|
|
10640
|
-
if (capabilities.provider !== "deepseek" && input.tools?.length) {
|
|
10641
|
-
body.tool_choice = "auto";
|
|
10642
|
-
}
|
|
10643
|
-
if (input.stream) {
|
|
10644
|
-
body.stream_options = {
|
|
10645
|
-
include_usage: true
|
|
10646
|
-
};
|
|
10647
|
-
}
|
|
10648
|
-
const cachePolicy = resolveProviderCachePolicy(input);
|
|
10649
|
-
if (cachePolicy.promptCacheKey) {
|
|
10650
|
-
body.prompt_cache_key = cachePolicy.promptCacheKey;
|
|
10651
|
-
}
|
|
10652
|
-
if (typeof input.maxOutputTokens === "number" && Number.isFinite(input.maxOutputTokens)) {
|
|
10653
|
-
body.max_tokens = Math.max(1, Math.trunc(input.maxOutputTokens));
|
|
10654
|
-
}
|
|
10655
|
-
if (capabilities.provider === "deepseek") {
|
|
10656
|
-
body.thinking = { type: thinking };
|
|
10657
|
-
if (thinking === "enabled") {
|
|
10658
|
-
body.reasoning_effort = normalizeDeepSeekReasoningEffort(input.reasoningEffort ?? capabilities.defaultReasoningEffort);
|
|
10659
|
-
}
|
|
10660
|
-
} else if (input.forceReasoning || capabilities.defaultReasoningEnabled) {
|
|
10661
|
-
body.thinking = { type: "enabled" };
|
|
10662
|
-
}
|
|
10663
|
-
return body;
|
|
10664
|
-
}
|
|
10665
|
-
function resolveDeepSeekThinking(messages, requested) {
|
|
10666
|
-
if (requested === "disabled") {
|
|
10667
|
-
return "disabled";
|
|
10668
|
-
}
|
|
10669
|
-
return hasUnreplayableAssistantReasoning(messages) ? "disabled" : "enabled";
|
|
10670
|
-
}
|
|
10671
|
-
function hasUnreplayableAssistantReasoning(messages) {
|
|
10672
|
-
return messages.some(
|
|
10673
|
-
(message) => message.role === "assistant" && Array.isArray(message.toolCalls) && message.toolCalls.length > 0 && message.reasoningContent === void 0
|
|
10674
|
-
);
|
|
10675
|
-
}
|
|
10676
|
-
function normalizeDeepSeekReasoningEffort(effort) {
|
|
10677
|
-
if (effort === void 0 || effort === "minimal" || effort === "low" || effort === "medium" || effort === "high") {
|
|
10678
|
-
return "high";
|
|
10679
|
-
}
|
|
10680
|
-
if (effort === "xhigh" || effort === "max") {
|
|
10681
|
-
return "max";
|
|
10682
|
-
}
|
|
10683
|
-
return "high";
|
|
10684
|
-
}
|
|
10685
|
-
var init_chatRequestBody = __esm({
|
|
10686
|
-
"src/provider/chatRequestBody.ts"() {
|
|
10687
|
-
"use strict";
|
|
10688
|
-
init_cachePolicy();
|
|
10689
|
-
init_capabilities();
|
|
10690
|
-
init_chatCompletionsAdapter();
|
|
10691
|
-
}
|
|
10692
|
-
});
|
|
10693
|
-
|
|
10694
|
-
// src/provider/chatCompletionsAdapter.ts
|
|
10695
|
-
function abortStream(stream) {
|
|
10696
|
-
try {
|
|
10697
|
-
stream?.controller?.abort();
|
|
10698
|
-
} catch {
|
|
10699
|
-
}
|
|
10700
|
-
}
|
|
10701
|
-
function toChatCompletionMessages(messages) {
|
|
10702
|
-
return messages.map((message) => {
|
|
10703
|
-
if (message.role === "tool") {
|
|
10704
|
-
return {
|
|
10705
|
-
role: "tool",
|
|
10706
|
-
content: message.content ?? "",
|
|
10707
|
-
tool_call_id: message.toolCallId ?? ""
|
|
10708
|
-
};
|
|
10709
|
-
}
|
|
10710
|
-
if (message.role === "assistant" && message.toolCalls?.length) {
|
|
10711
|
-
const assistantMessage = {
|
|
10712
|
-
role: "assistant",
|
|
10713
|
-
content: message.content ?? "",
|
|
10714
|
-
tool_calls: message.toolCalls
|
|
10715
|
-
};
|
|
10716
|
-
if (message.reasoningContent !== void 0) {
|
|
10717
|
-
assistantMessage.reasoning_content = message.reasoningContent;
|
|
10718
|
-
}
|
|
10719
|
-
return assistantMessage;
|
|
10720
|
-
}
|
|
10721
|
-
const baseMessage = {
|
|
10722
|
-
role: message.role,
|
|
10723
|
-
content: message.content ?? "",
|
|
10724
|
-
name: message.name
|
|
10725
|
-
};
|
|
10726
|
-
if (message.role === "assistant" && message.reasoningContent !== void 0) {
|
|
10727
|
-
baseMessage.reasoning_content = message.reasoningContent;
|
|
10728
|
-
}
|
|
10729
|
-
return baseMessage;
|
|
10730
|
-
});
|
|
10731
|
-
}
|
|
10732
|
-
var chatCompletionsAdapter;
|
|
10733
|
-
var init_chatCompletionsAdapter = __esm({
|
|
10734
|
-
"src/provider/chatCompletionsAdapter.ts"() {
|
|
10735
|
-
"use strict";
|
|
10736
|
-
init_messages();
|
|
10737
|
-
init_chatRequestBody();
|
|
10738
|
-
init_usageNormalizer();
|
|
10739
|
-
init_abort();
|
|
10740
|
-
chatCompletionsAdapter = {
|
|
10741
|
-
wireApi: "chat.completions",
|
|
10742
|
-
async fetchStreaming(client, request) {
|
|
10743
|
-
const startedAt = Date.now();
|
|
10744
|
-
let usage;
|
|
10745
|
-
throwIfAborted(request.abortSignal, "Streaming request aborted");
|
|
10746
|
-
try {
|
|
10747
|
-
const stream = await client.chat.completions.create(
|
|
10748
|
-
{
|
|
10749
|
-
...buildProviderRequestBody({
|
|
10750
|
-
provider: request.provider,
|
|
10751
|
-
model: request.model,
|
|
10752
|
-
messages: request.messages,
|
|
10753
|
-
tools: request.tools,
|
|
10754
|
-
stream: true,
|
|
10755
|
-
forceReasoning: request.forceReasoning,
|
|
10756
|
-
thinking: request.thinking,
|
|
10757
|
-
reasoningEffort: request.reasoningEffort,
|
|
10758
|
-
maxOutputTokens: request.maxOutputTokens,
|
|
10759
|
-
sessionId: request.sessionId,
|
|
10760
|
-
projectRoot: request.projectRoot
|
|
10761
|
-
}),
|
|
10762
|
-
signal: request.abortSignal
|
|
10763
|
-
}
|
|
10764
|
-
);
|
|
10765
|
-
if (request.abortSignal?.aborted) {
|
|
10766
|
-
abortStream(stream);
|
|
10767
|
-
throw createAbortError("Streaming aborted");
|
|
10768
|
-
}
|
|
10769
|
-
let content = "";
|
|
10770
|
-
let reasoningContent = "";
|
|
10771
|
-
const toolCallParts = /* @__PURE__ */ new Map();
|
|
10772
|
-
for await (const chunk of stream) {
|
|
10773
|
-
if (request.abortSignal?.aborted) {
|
|
10774
|
-
abortStream(stream);
|
|
10775
|
-
throw createAbortError("Streaming aborted");
|
|
10776
|
-
}
|
|
10777
|
-
usage = normalizeProviderUsage(chunk.usage) ?? usage;
|
|
10778
|
-
const delta = chunk.choices?.[0]?.delta;
|
|
10779
|
-
if (!delta) {
|
|
10780
|
-
continue;
|
|
10781
|
-
}
|
|
10782
|
-
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
10783
|
-
content += delta.content;
|
|
10784
|
-
request.callbacks?.onAssistantDelta?.(delta.content);
|
|
10785
|
-
}
|
|
10786
|
-
if (typeof delta.reasoning_content === "string" && delta.reasoning_content.length > 0) {
|
|
10787
|
-
reasoningContent += delta.reasoning_content;
|
|
10788
|
-
request.callbacks?.onReasoningDelta?.(delta.reasoning_content);
|
|
10789
|
-
}
|
|
10790
|
-
if (Array.isArray(delta.tool_calls)) {
|
|
10791
|
-
for (const toolCall of delta.tool_calls) {
|
|
10792
|
-
const index = typeof toolCall.index === "number" ? toolCall.index : 0;
|
|
10793
|
-
const existing = toolCallParts.get(index) ?? {
|
|
10794
|
-
id: toolCall.id ?? `tool-${index}`,
|
|
10795
|
-
name: "",
|
|
10796
|
-
arguments: ""
|
|
10797
|
-
};
|
|
10798
|
-
if (toolCall.id) {
|
|
10799
|
-
existing.id = toolCall.id;
|
|
10800
|
-
}
|
|
10801
|
-
if (toolCall.function?.name) {
|
|
10802
|
-
existing.name += toolCall.function.name;
|
|
10803
|
-
}
|
|
10804
|
-
if (toolCall.function?.arguments) {
|
|
10805
|
-
existing.arguments += toolCall.function.arguments;
|
|
10806
|
-
}
|
|
10807
|
-
toolCallParts.set(index, existing);
|
|
10808
|
-
}
|
|
10809
|
-
}
|
|
10810
|
-
}
|
|
10811
|
-
return {
|
|
10812
|
-
content: content.length > 0 ? content : null,
|
|
10813
|
-
reasoningContent: reasoningContent.length > 0 ? reasoningContent : void 0,
|
|
10814
|
-
streamedAssistantContent: content.length > 0,
|
|
10815
|
-
streamedReasoningContent: reasoningContent.length > 0,
|
|
10816
|
-
toolCalls: [...toolCallParts.entries()].sort((left, right) => left[0] - right[0]).map(([, toolCall]) => ({
|
|
10817
|
-
id: toolCall.id,
|
|
10818
|
-
type: "function",
|
|
10819
|
-
function: {
|
|
10820
|
-
name: toolCall.name,
|
|
10821
|
-
arguments: toolCall.arguments
|
|
10822
|
-
}
|
|
10823
|
-
}))
|
|
10824
|
-
};
|
|
10825
|
-
} finally {
|
|
10826
|
-
request.onRequestMetric?.({
|
|
10827
|
-
durationMs: Date.now() - startedAt,
|
|
10828
|
-
usage
|
|
10829
|
-
});
|
|
10830
|
-
}
|
|
10831
|
-
},
|
|
10832
|
-
async fetchNonStreaming(client, request) {
|
|
10833
|
-
const startedAt = Date.now();
|
|
10834
|
-
let usage;
|
|
10835
|
-
throwIfAborted(request.abortSignal, "Request aborted");
|
|
10836
|
-
try {
|
|
10837
|
-
const completion = await client.chat.completions.create(
|
|
10838
|
-
{
|
|
10839
|
-
...buildProviderRequestBody({
|
|
10840
|
-
provider: request.provider,
|
|
10841
|
-
model: request.model,
|
|
10842
|
-
messages: request.messages,
|
|
10843
|
-
tools: request.tools,
|
|
10844
|
-
stream: false,
|
|
10845
|
-
forceReasoning: request.forceReasoning,
|
|
10846
|
-
thinking: request.thinking,
|
|
10847
|
-
reasoningEffort: request.reasoningEffort,
|
|
10848
|
-
maxOutputTokens: request.maxOutputTokens,
|
|
10849
|
-
sessionId: request.sessionId,
|
|
10850
|
-
projectRoot: request.projectRoot
|
|
10851
|
-
}),
|
|
10852
|
-
signal: request.abortSignal
|
|
10853
|
-
}
|
|
10854
|
-
);
|
|
10855
|
-
usage = normalizeProviderUsage(completion.usage);
|
|
10856
|
-
const message = completion.choices[0]?.message;
|
|
10857
|
-
if (!message) {
|
|
10858
|
-
throw new Error("API returned no message.");
|
|
10859
|
-
}
|
|
10860
|
-
return {
|
|
10861
|
-
content: typeof message.content === "string" ? message.content : collapseContentParts(message.content),
|
|
10862
|
-
reasoningContent: readReasoningContent(message),
|
|
10863
|
-
streamedAssistantContent: false,
|
|
10864
|
-
streamedReasoningContent: false,
|
|
10865
|
-
toolCalls: (message.tool_calls ?? []).filter((call) => call.type === "function").map((call) => ({
|
|
10866
|
-
id: call.id,
|
|
10867
|
-
type: "function",
|
|
10868
|
-
function: {
|
|
10869
|
-
name: call.function.name,
|
|
10870
|
-
arguments: call.function.arguments
|
|
10871
|
-
}
|
|
10872
|
-
}))
|
|
10873
|
-
};
|
|
10874
|
-
} finally {
|
|
10875
|
-
request.onRequestMetric?.({
|
|
10876
|
-
durationMs: Date.now() - startedAt,
|
|
10877
|
-
usage
|
|
10878
|
-
});
|
|
10879
|
-
}
|
|
10880
|
-
}
|
|
10881
|
-
};
|
|
10882
|
-
}
|
|
10883
|
-
});
|
|
10884
|
-
|
|
10885
|
-
// src/provider/responsesAdapter.ts
|
|
10886
|
-
function buildResponsesRequestBody(request) {
|
|
10887
|
-
const capabilities = resolveProviderCapabilities({
|
|
10888
|
-
provider: request.provider,
|
|
10889
|
-
model: request.model
|
|
10890
|
-
});
|
|
10891
|
-
const body = {
|
|
10892
|
-
model: request.model,
|
|
10893
|
-
input: toResponsesInput(request.messages),
|
|
10894
|
-
tools: request.tools?.map((tool) => ({
|
|
10895
|
-
type: "function",
|
|
10896
|
-
name: tool.function.name,
|
|
10897
|
-
description: tool.function.description,
|
|
10898
|
-
parameters: tool.function.parameters ?? null,
|
|
10899
|
-
strict: false
|
|
10900
|
-
})),
|
|
10901
|
-
tool_choice: request.tools?.length ? "auto" : void 0
|
|
10902
|
-
};
|
|
10903
|
-
if (typeof request.maxOutputTokens === "number" && Number.isFinite(request.maxOutputTokens)) {
|
|
10904
|
-
body.max_output_tokens = Math.max(1, Math.trunc(request.maxOutputTokens));
|
|
10905
|
-
}
|
|
10906
|
-
const cachePolicy = resolveProviderCachePolicy({
|
|
10907
|
-
provider: request.provider,
|
|
10908
|
-
model: request.model,
|
|
10909
|
-
sessionId: request.sessionId,
|
|
10910
|
-
projectRoot: request.projectRoot
|
|
10911
|
-
});
|
|
10912
|
-
if (cachePolicy.promptCacheKey) {
|
|
10913
|
-
body.prompt_cache_key = cachePolicy.promptCacheKey;
|
|
10914
|
-
}
|
|
10915
|
-
const reasoningEffort = normalizeResponsesReasoningEffort(
|
|
10916
|
-
request.reasoningEffort ?? capabilities.defaultReasoningEffort
|
|
10917
|
-
);
|
|
10918
|
-
if (request.forceReasoning || capabilities.defaultReasoningEnabled || reasoningEffort) {
|
|
10919
|
-
body.reasoning = {
|
|
10920
|
-
effort: reasoningEffort ?? "high",
|
|
10921
|
-
summary: "detailed"
|
|
10922
|
-
};
|
|
10923
|
-
}
|
|
10924
|
-
return body;
|
|
10925
|
-
}
|
|
10926
|
-
function normalizeResponsesReasoningEffort(effort) {
|
|
10927
|
-
return effort === "max" ? void 0 : effort;
|
|
10928
|
-
}
|
|
10929
|
-
function toResponsesInput(messages) {
|
|
10930
|
-
const items = [];
|
|
10931
|
-
for (const message of messages) {
|
|
10932
|
-
if (message.role === "tool") {
|
|
10933
|
-
items.push({
|
|
10934
|
-
type: "function_call_output",
|
|
10935
|
-
call_id: message.toolCallId ?? "",
|
|
10936
|
-
output: message.content ?? ""
|
|
10937
|
-
});
|
|
10938
|
-
continue;
|
|
10939
|
-
}
|
|
10940
|
-
if (message.role === "assistant" && message.toolCalls?.length) {
|
|
10941
|
-
if (typeof message.content === "string" && message.content.trim().length > 0) {
|
|
10942
|
-
items.push({
|
|
10943
|
-
type: "message",
|
|
10944
|
-
role: "assistant",
|
|
10945
|
-
content: message.content
|
|
10946
|
-
});
|
|
10947
|
-
}
|
|
10948
|
-
for (const toolCall of message.toolCalls) {
|
|
10949
|
-
items.push({
|
|
10950
|
-
type: "function_call",
|
|
10951
|
-
call_id: toolCall.id,
|
|
10952
|
-
name: toolCall.function.name,
|
|
10953
|
-
arguments: toolCall.function.arguments
|
|
10954
|
-
});
|
|
10955
|
-
}
|
|
10956
|
-
continue;
|
|
10957
|
-
}
|
|
10958
|
-
items.push({
|
|
10959
|
-
type: "message",
|
|
10960
|
-
role: message.role,
|
|
10961
|
-
content: message.content ?? ""
|
|
10962
|
-
});
|
|
10963
|
-
}
|
|
10964
|
-
return items;
|
|
10965
|
-
}
|
|
10966
|
-
function normalizeOutputText(response) {
|
|
10967
|
-
const outputText = response.output_text;
|
|
10968
|
-
if (typeof outputText === "string" && outputText.trim().length > 0) {
|
|
10969
|
-
return outputText;
|
|
10970
|
-
}
|
|
10971
|
-
const output = response.output;
|
|
10972
|
-
if (!Array.isArray(output)) {
|
|
10973
|
-
return null;
|
|
10974
|
-
}
|
|
10975
|
-
const fragments = output.flatMap((item) => {
|
|
10976
|
-
if (!item || typeof item !== "object" || item.type !== "message") {
|
|
10977
|
-
return [];
|
|
10978
|
-
}
|
|
10979
|
-
const content = item.content;
|
|
10980
|
-
if (!Array.isArray(content)) {
|
|
10981
|
-
return [];
|
|
10982
|
-
}
|
|
10983
|
-
return content.flatMap((part) => {
|
|
10984
|
-
if (!part || typeof part !== "object" || part.type !== "output_text") {
|
|
10985
|
-
return [];
|
|
10986
|
-
}
|
|
10987
|
-
return typeof part.text === "string" ? [part.text] : [];
|
|
10988
|
-
});
|
|
10989
|
-
});
|
|
10990
|
-
return fragments.length > 0 ? fragments.join("") : null;
|
|
10991
|
-
}
|
|
10992
|
-
function readResponseToolCalls(response) {
|
|
10993
|
-
const output = response.output;
|
|
10994
|
-
if (!Array.isArray(output)) {
|
|
10995
|
-
return [];
|
|
10996
|
-
}
|
|
10997
|
-
return output.filter((item) => Boolean(item) && typeof item === "object" && item.type === "function_call").map((item) => ({
|
|
10998
|
-
id: item.call_id ?? item.id ?? crypto.randomUUID(),
|
|
10999
|
-
type: "function",
|
|
11000
|
-
function: {
|
|
11001
|
-
name: item.name ?? "",
|
|
11002
|
-
arguments: item.arguments ?? ""
|
|
11003
|
-
}
|
|
11004
|
-
}));
|
|
11005
|
-
}
|
|
11006
|
-
function readResponseReasoning(response) {
|
|
11007
|
-
const output = response.output;
|
|
11008
|
-
if (!Array.isArray(output)) {
|
|
11009
|
-
return void 0;
|
|
11010
|
-
}
|
|
11011
|
-
const fragments = output.flatMap((item) => {
|
|
11012
|
-
if (!item || typeof item !== "object" || item.type !== "reasoning") {
|
|
11013
|
-
return [];
|
|
11014
|
-
}
|
|
11015
|
-
const reasoningItem = item;
|
|
11016
|
-
const summary = Array.isArray(reasoningItem.summary) ? reasoningItem.summary.map((entry) => typeof entry?.text === "string" ? entry.text : "").filter(Boolean) : [];
|
|
11017
|
-
const content = Array.isArray(reasoningItem.content) ? reasoningItem.content.map((entry) => typeof entry?.text === "string" ? entry.text : "").filter(Boolean) : [];
|
|
11018
|
-
return [...content, ...summary];
|
|
11019
|
-
});
|
|
11020
|
-
return fragments.length > 0 ? fragments.join("") : void 0;
|
|
11021
|
-
}
|
|
11022
|
-
function abortStream2(stream) {
|
|
11023
|
-
try {
|
|
11024
|
-
stream?.controller?.abort();
|
|
11025
|
-
} catch {
|
|
11026
|
-
}
|
|
11027
|
-
}
|
|
11028
|
-
var responsesAdapter;
|
|
11029
|
-
var init_responsesAdapter = __esm({
|
|
11030
|
-
"src/provider/responsesAdapter.ts"() {
|
|
11031
|
-
"use strict";
|
|
11032
|
-
init_capabilities();
|
|
11033
|
-
init_cachePolicy();
|
|
11034
|
-
init_usageNormalizer();
|
|
11035
|
-
init_abort();
|
|
11036
|
-
responsesAdapter = {
|
|
11037
|
-
wireApi: "responses",
|
|
11038
|
-
async fetchStreaming(client, request) {
|
|
11039
|
-
const startedAt = Date.now();
|
|
11040
|
-
let usage;
|
|
11041
|
-
throwIfAborted(request.abortSignal, "Streaming request aborted");
|
|
11042
|
-
try {
|
|
11043
|
-
const stream = await client.responses.create(
|
|
11044
|
-
{
|
|
11045
|
-
...buildResponsesRequestBody(request),
|
|
11046
|
-
stream: true
|
|
11047
|
-
},
|
|
11048
|
-
{
|
|
11049
|
-
signal: request.abortSignal
|
|
11050
|
-
}
|
|
11051
|
-
);
|
|
11052
|
-
if (request.abortSignal?.aborted) {
|
|
11053
|
-
abortStream2(stream);
|
|
11054
|
-
throw createAbortError("Streaming aborted");
|
|
11055
|
-
}
|
|
11056
|
-
let content = "";
|
|
11057
|
-
let reasoningContent = "";
|
|
11058
|
-
const toolCalls = /* @__PURE__ */ new Map();
|
|
11059
|
-
for await (const event of stream) {
|
|
11060
|
-
if (request.abortSignal?.aborted) {
|
|
11061
|
-
abortStream2(stream);
|
|
11062
|
-
throw createAbortError("Streaming aborted");
|
|
11063
|
-
}
|
|
11064
|
-
usage = normalizeProviderUsage(event.response?.usage) ?? usage;
|
|
11065
|
-
if (event.type === "response.output_text.delta" && typeof event.delta === "string") {
|
|
11066
|
-
content += event.delta;
|
|
11067
|
-
request.callbacks?.onAssistantDelta?.(event.delta);
|
|
11068
|
-
continue;
|
|
11069
|
-
}
|
|
11070
|
-
if ((event.type === "response.reasoning_text.delta" || event.type === "response.reasoning_summary_text.delta") && typeof event.delta === "string") {
|
|
11071
|
-
reasoningContent += event.delta;
|
|
11072
|
-
request.callbacks?.onReasoningDelta?.(event.delta);
|
|
11073
|
-
continue;
|
|
11074
|
-
}
|
|
11075
|
-
if (event.type === "response.function_call_arguments.delta" && typeof event.delta === "string") {
|
|
11076
|
-
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
11077
|
-
const existing = toolCalls.get(index) ?? {
|
|
11078
|
-
id: event.item_id ?? `tool-${index}`,
|
|
11079
|
-
name: "",
|
|
11080
|
-
arguments: ""
|
|
11081
|
-
};
|
|
11082
|
-
existing.arguments += event.delta;
|
|
11083
|
-
toolCalls.set(index, existing);
|
|
11084
|
-
continue;
|
|
11085
|
-
}
|
|
11086
|
-
if (event.type === "response.function_call_arguments.done") {
|
|
11087
|
-
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
11088
|
-
const existing = toolCalls.get(index) ?? {
|
|
11089
|
-
id: event.item_id ?? `tool-${index}`,
|
|
11090
|
-
name: "",
|
|
11091
|
-
arguments: ""
|
|
11092
|
-
};
|
|
11093
|
-
if (typeof event.name === "string") {
|
|
11094
|
-
existing.name = event.name;
|
|
11095
|
-
}
|
|
11096
|
-
if (typeof event.arguments === "string" && event.arguments.length > 0) {
|
|
11097
|
-
existing.arguments = event.arguments;
|
|
11098
|
-
}
|
|
11099
|
-
toolCalls.set(index, existing);
|
|
11100
|
-
continue;
|
|
11101
|
-
}
|
|
11102
|
-
if (event.type === "response.output_item.done" && event.item?.type === "function_call") {
|
|
11103
|
-
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
11104
|
-
toolCalls.set(index, {
|
|
11105
|
-
id: event.item.call_id ?? event.item.id ?? `tool-${index}`,
|
|
11106
|
-
name: event.item.name ?? "",
|
|
11107
|
-
arguments: event.item.arguments ?? ""
|
|
11108
|
-
});
|
|
11109
|
-
}
|
|
11110
|
-
}
|
|
11111
|
-
return {
|
|
11112
|
-
content: content.length > 0 ? content : null,
|
|
11113
|
-
reasoningContent: reasoningContent.length > 0 ? reasoningContent : void 0,
|
|
11114
|
-
streamedAssistantContent: content.length > 0,
|
|
11115
|
-
streamedReasoningContent: reasoningContent.length > 0,
|
|
11116
|
-
toolCalls: [...toolCalls.entries()].sort((left, right) => left[0] - right[0]).map(([, toolCall]) => ({
|
|
11117
|
-
id: toolCall.id,
|
|
11118
|
-
type: "function",
|
|
11119
|
-
function: {
|
|
11120
|
-
name: toolCall.name,
|
|
11121
|
-
arguments: toolCall.arguments
|
|
11122
|
-
}
|
|
11123
|
-
}))
|
|
11124
|
-
};
|
|
11125
|
-
} finally {
|
|
11126
|
-
request.onRequestMetric?.({
|
|
11127
|
-
durationMs: Date.now() - startedAt,
|
|
11128
|
-
usage
|
|
11129
|
-
});
|
|
11130
|
-
}
|
|
11131
|
-
},
|
|
11132
|
-
async fetchNonStreaming(client, request) {
|
|
11133
|
-
const startedAt = Date.now();
|
|
11134
|
-
let usage;
|
|
11135
|
-
throwIfAborted(request.abortSignal, "Request aborted");
|
|
11136
|
-
try {
|
|
11137
|
-
const response = await client.responses.create(
|
|
11138
|
-
{
|
|
11139
|
-
...buildResponsesRequestBody(request),
|
|
11140
|
-
stream: false
|
|
11141
|
-
},
|
|
11142
|
-
{
|
|
11143
|
-
signal: request.abortSignal
|
|
11144
|
-
}
|
|
11145
|
-
);
|
|
11146
|
-
usage = normalizeProviderUsage(response.usage);
|
|
11147
|
-
return {
|
|
11148
|
-
content: normalizeOutputText(response),
|
|
11149
|
-
reasoningContent: readResponseReasoning(response),
|
|
11150
|
-
streamedAssistantContent: false,
|
|
11151
|
-
streamedReasoningContent: false,
|
|
11152
|
-
toolCalls: readResponseToolCalls(response)
|
|
11153
|
-
};
|
|
11154
|
-
} finally {
|
|
11155
|
-
request.onRequestMetric?.({
|
|
11156
|
-
durationMs: Date.now() - startedAt,
|
|
11157
|
-
usage
|
|
11158
|
-
});
|
|
11159
|
-
}
|
|
11160
|
-
}
|
|
11161
|
-
};
|
|
10507
|
+
init_catalog();
|
|
11162
10508
|
}
|
|
11163
10509
|
});
|
|
11164
10510
|
|
|
11165
|
-
// src/provider/
|
|
11166
|
-
function
|
|
11167
|
-
const
|
|
11168
|
-
provider: config.provider,
|
|
11169
|
-
model: config.model
|
|
11170
|
-
});
|
|
11171
|
-
const baseUrls = buildProviderBaseUrlCandidates(config.baseUrl);
|
|
11172
|
-
const clients = /* @__PURE__ */ new Map();
|
|
11173
|
-
let preferredBaseUrl;
|
|
10511
|
+
// src/provider/capabilities.ts
|
|
10512
|
+
function resolveProviderCapabilities(input) {
|
|
10513
|
+
const profile = resolveModelProfile(input);
|
|
11174
10514
|
return {
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11181
|
-
|
|
11182
|
-
|
|
11183
|
-
preferredBaseUrl = baseUrl;
|
|
11184
|
-
}
|
|
11185
|
-
};
|
|
11186
|
-
function getOrCreateClient(baseUrl) {
|
|
11187
|
-
const existing = clients.get(baseUrl);
|
|
11188
|
-
if (existing) {
|
|
11189
|
-
return existing;
|
|
11190
|
-
}
|
|
11191
|
-
const client = new import_openai.default({
|
|
11192
|
-
apiKey: config.apiKey,
|
|
11193
|
-
baseURL: baseUrl,
|
|
11194
|
-
timeout: capabilities.requestTimeoutMs,
|
|
11195
|
-
maxRetries: 0
|
|
11196
|
-
});
|
|
11197
|
-
clients.set(baseUrl, client);
|
|
11198
|
-
return client;
|
|
11199
|
-
}
|
|
11200
|
-
}
|
|
11201
|
-
function isProviderClientPool(value) {
|
|
11202
|
-
return Boolean(
|
|
11203
|
-
value && typeof value === "object" && typeof value.candidates === "function" && typeof value.markHealthy === "function"
|
|
11204
|
-
);
|
|
11205
|
-
}
|
|
11206
|
-
var import_openai;
|
|
11207
|
-
var init_client = __esm({
|
|
11208
|
-
"src/provider/client.ts"() {
|
|
11209
|
-
"use strict";
|
|
11210
|
-
import_openai = __toESM(require("openai"));
|
|
11211
|
-
init_capabilities();
|
|
11212
|
-
init_connection();
|
|
11213
|
-
}
|
|
11214
|
-
});
|
|
11215
|
-
|
|
11216
|
-
// src/provider/request.ts
|
|
11217
|
-
async function fetchAssistantResponse(client, messages, request, tools, callbacks, abortSignal, onRequestMetric, observability) {
|
|
11218
|
-
const capabilities = resolveProviderCapabilities(request);
|
|
11219
|
-
const adapter = selectProviderWireAdapter(capabilities.wireApi);
|
|
11220
|
-
return tryFetch(
|
|
11221
|
-
adapter,
|
|
11222
|
-
client,
|
|
11223
|
-
messages,
|
|
11224
|
-
request,
|
|
11225
|
-
tools,
|
|
11226
|
-
callbacks,
|
|
11227
|
-
false,
|
|
11228
|
-
abortSignal,
|
|
11229
|
-
onRequestMetric,
|
|
11230
|
-
observability
|
|
11231
|
-
);
|
|
11232
|
-
}
|
|
11233
|
-
async function tryFetch(adapter, client, messages, request, tools, callbacks, forceReasoning, abortSignal, onRequestMetric, observability) {
|
|
11234
|
-
const startedAt = Date.now();
|
|
11235
|
-
let latestMetric;
|
|
11236
|
-
let resolvedBaseUrl;
|
|
11237
|
-
const forwardMetric = (metric) => {
|
|
11238
|
-
latestMetric = metric;
|
|
11239
|
-
onRequestMetric?.(metric);
|
|
10515
|
+
provider: profile.provider.id,
|
|
10516
|
+
model: profile.model.id,
|
|
10517
|
+
wireApi: profile.model.wireApi,
|
|
10518
|
+
supportsReasoningContent: profile.model.capabilities.reasoningContentReplay !== "never",
|
|
10519
|
+
defaultReasoningEnabled: profile.model.capabilities.reasoning,
|
|
10520
|
+
defaultReasoningEffort: profile.model.request.reasoningEffortDefault,
|
|
10521
|
+
requestTimeoutMs: profile.provider.requestTimeoutMs,
|
|
10522
|
+
doctorProbeTimeoutMs: profile.provider.doctorProbeTimeoutMs
|
|
11240
10523
|
};
|
|
11241
|
-
if (observability) {
|
|
11242
|
-
await recordObservabilityEvent(observability.rootDir, {
|
|
11243
|
-
event: "model.request",
|
|
11244
|
-
status: "started",
|
|
11245
|
-
sessionId: observability.sessionId,
|
|
11246
|
-
identityKind: observability.identityKind,
|
|
11247
|
-
identityName: observability.identityName,
|
|
11248
|
-
model: request.model,
|
|
11249
|
-
details: {
|
|
11250
|
-
provider: request.provider,
|
|
11251
|
-
configuredModel: observability.configuredModel,
|
|
11252
|
-
requestModel: request.model,
|
|
11253
|
-
wireApi: adapter.wireApi,
|
|
11254
|
-
baseUrl: resolvedBaseUrl
|
|
11255
|
-
}
|
|
11256
|
-
});
|
|
11257
|
-
}
|
|
11258
|
-
try {
|
|
11259
|
-
const response = await withApiRetries(
|
|
11260
|
-
() => invokeWithProviderClients(client, async (providerClient, baseUrl) => {
|
|
11261
|
-
resolvedBaseUrl = baseUrl;
|
|
11262
|
-
return adapter.fetchStreaming(providerClient, {
|
|
11263
|
-
provider: request.provider,
|
|
11264
|
-
model: request.model,
|
|
11265
|
-
messages,
|
|
11266
|
-
tools,
|
|
11267
|
-
callbacks,
|
|
11268
|
-
forceReasoning,
|
|
11269
|
-
thinking: request.thinking,
|
|
11270
|
-
reasoningEffort: request.reasoningEffort,
|
|
11271
|
-
maxOutputTokens: request.maxOutputTokens,
|
|
11272
|
-
sessionId: request.sessionId,
|
|
11273
|
-
projectRoot: request.projectRoot,
|
|
11274
|
-
abortSignal,
|
|
11275
|
-
onRequestMetric: forwardMetric
|
|
11276
|
-
});
|
|
11277
|
-
}),
|
|
11278
|
-
abortSignal
|
|
11279
|
-
);
|
|
11280
|
-
if (observability) {
|
|
11281
|
-
await recordObservabilityEvent(observability.rootDir, {
|
|
11282
|
-
event: "model.request",
|
|
11283
|
-
status: "completed",
|
|
11284
|
-
sessionId: observability.sessionId,
|
|
11285
|
-
identityKind: observability.identityKind,
|
|
11286
|
-
identityName: observability.identityName,
|
|
11287
|
-
model: request.model,
|
|
11288
|
-
durationMs: Date.now() - startedAt,
|
|
11289
|
-
details: {
|
|
11290
|
-
provider: request.provider,
|
|
11291
|
-
configuredModel: observability.configuredModel,
|
|
11292
|
-
requestModel: request.model,
|
|
11293
|
-
wireApi: adapter.wireApi,
|
|
11294
|
-
baseUrl: resolvedBaseUrl,
|
|
11295
|
-
usage: latestMetric?.usage,
|
|
11296
|
-
usageAvailable: hasProviderUsageSnapshot(latestMetric?.usage)
|
|
11297
|
-
}
|
|
11298
|
-
});
|
|
11299
|
-
}
|
|
11300
|
-
return response;
|
|
11301
|
-
} catch (error) {
|
|
11302
|
-
if (isAbortError(error)) {
|
|
11303
|
-
throw error;
|
|
11304
|
-
}
|
|
11305
|
-
try {
|
|
11306
|
-
const response = await withApiRetries(
|
|
11307
|
-
() => invokeWithProviderClients(client, async (providerClient, baseUrl) => {
|
|
11308
|
-
resolvedBaseUrl = baseUrl;
|
|
11309
|
-
return adapter.fetchNonStreaming(providerClient, {
|
|
11310
|
-
provider: request.provider,
|
|
11311
|
-
model: request.model,
|
|
11312
|
-
messages,
|
|
11313
|
-
tools,
|
|
11314
|
-
callbacks,
|
|
11315
|
-
forceReasoning,
|
|
11316
|
-
thinking: request.thinking,
|
|
11317
|
-
reasoningEffort: request.reasoningEffort,
|
|
11318
|
-
maxOutputTokens: request.maxOutputTokens,
|
|
11319
|
-
sessionId: request.sessionId,
|
|
11320
|
-
projectRoot: request.projectRoot,
|
|
11321
|
-
abortSignal,
|
|
11322
|
-
onRequestMetric: forwardMetric
|
|
11323
|
-
});
|
|
11324
|
-
}),
|
|
11325
|
-
abortSignal
|
|
11326
|
-
);
|
|
11327
|
-
if (observability) {
|
|
11328
|
-
await recordObservabilityEvent(observability.rootDir, {
|
|
11329
|
-
event: "model.request",
|
|
11330
|
-
status: "completed",
|
|
11331
|
-
sessionId: observability.sessionId,
|
|
11332
|
-
identityKind: observability.identityKind,
|
|
11333
|
-
identityName: observability.identityName,
|
|
11334
|
-
model: request.model,
|
|
11335
|
-
durationMs: Date.now() - startedAt,
|
|
11336
|
-
details: {
|
|
11337
|
-
provider: request.provider,
|
|
11338
|
-
configuredModel: observability.configuredModel,
|
|
11339
|
-
requestModel: request.model,
|
|
11340
|
-
wireApi: adapter.wireApi,
|
|
11341
|
-
baseUrl: resolvedBaseUrl,
|
|
11342
|
-
usage: latestMetric?.usage,
|
|
11343
|
-
usageAvailable: hasProviderUsageSnapshot(latestMetric?.usage)
|
|
11344
|
-
}
|
|
11345
|
-
});
|
|
11346
|
-
}
|
|
11347
|
-
return response;
|
|
11348
|
-
} catch (fallbackError) {
|
|
11349
|
-
if (!isAbortError(fallbackError) && observability) {
|
|
11350
|
-
await recordObservabilityEvent(observability.rootDir, {
|
|
11351
|
-
event: "model.request",
|
|
11352
|
-
status: "failed",
|
|
11353
|
-
sessionId: observability.sessionId,
|
|
11354
|
-
identityKind: observability.identityKind,
|
|
11355
|
-
identityName: observability.identityName,
|
|
11356
|
-
model: request.model,
|
|
11357
|
-
durationMs: Date.now() - startedAt,
|
|
11358
|
-
error: fallbackError,
|
|
11359
|
-
details: {
|
|
11360
|
-
provider: request.provider,
|
|
11361
|
-
configuredModel: observability.configuredModel,
|
|
11362
|
-
requestModel: request.model,
|
|
11363
|
-
wireApi: adapter.wireApi,
|
|
11364
|
-
baseUrl: resolvedBaseUrl,
|
|
11365
|
-
usage: latestMetric?.usage,
|
|
11366
|
-
usageAvailable: hasProviderUsageSnapshot(latestMetric?.usage)
|
|
11367
|
-
}
|
|
11368
|
-
});
|
|
11369
|
-
}
|
|
11370
|
-
throw fallbackError;
|
|
11371
|
-
}
|
|
11372
|
-
}
|
|
11373
|
-
}
|
|
11374
|
-
function selectProviderWireAdapter(wireApi) {
|
|
11375
|
-
if (wireApi === "responses") {
|
|
11376
|
-
return responsesAdapter;
|
|
11377
|
-
}
|
|
11378
|
-
return chatCompletionsAdapter;
|
|
11379
|
-
}
|
|
11380
|
-
async function invokeWithProviderClients(client, operation) {
|
|
11381
|
-
if (!isProviderClientPool(client)) {
|
|
11382
|
-
return operation(client, void 0);
|
|
11383
|
-
}
|
|
11384
|
-
let lastError;
|
|
11385
|
-
const candidates = client.candidates();
|
|
11386
|
-
for (let index = 0; index < candidates.length; index += 1) {
|
|
11387
|
-
const candidate = candidates[index];
|
|
11388
|
-
try {
|
|
11389
|
-
const result = await operation(candidate.client, candidate.baseUrl);
|
|
11390
|
-
client.markHealthy(candidate.baseUrl);
|
|
11391
|
-
return result;
|
|
11392
|
-
} catch (error) {
|
|
11393
|
-
lastError = error;
|
|
11394
|
-
if (isAbortError(error)) {
|
|
11395
|
-
throw error;
|
|
11396
|
-
}
|
|
11397
|
-
const hasMoreCandidates = index < candidates.length - 1;
|
|
11398
|
-
if (!hasMoreCandidates || !canRetryWithAlternateBaseUrl(error)) {
|
|
11399
|
-
throw error;
|
|
11400
|
-
}
|
|
11401
|
-
}
|
|
11402
|
-
}
|
|
11403
|
-
throw lastError;
|
|
11404
10524
|
}
|
|
11405
|
-
|
|
11406
|
-
|
|
11407
|
-
const message = String(error.message ?? error).toLowerCase();
|
|
11408
|
-
return status === 404 || status === 405 || message.includes("404") || message.includes("not found");
|
|
11409
|
-
}
|
|
11410
|
-
var init_request = __esm({
|
|
11411
|
-
"src/provider/request.ts"() {
|
|
11412
|
-
"use strict";
|
|
11413
|
-
init_apiRetry();
|
|
11414
|
-
init_usageNormalizer();
|
|
11415
|
-
init_abort();
|
|
11416
|
-
init_writer();
|
|
11417
|
-
init_capabilities();
|
|
11418
|
-
init_chatCompletionsAdapter();
|
|
11419
|
-
init_responsesAdapter();
|
|
11420
|
-
init_client();
|
|
11421
|
-
}
|
|
11422
|
-
});
|
|
11423
|
-
|
|
11424
|
-
// src/provider/index.ts
|
|
11425
|
-
var init_provider = __esm({
|
|
11426
|
-
"src/provider/index.ts"() {
|
|
10525
|
+
var init_capabilities = __esm({
|
|
10526
|
+
"src/provider/capabilities.ts"() {
|
|
11427
10527
|
"use strict";
|
|
11428
|
-
|
|
11429
|
-
init_request();
|
|
10528
|
+
init_catalog();
|
|
11430
10529
|
}
|
|
11431
10530
|
});
|
|
11432
10531
|
|
|
11433
10532
|
// src/session/messages.ts
|
|
11434
|
-
function buildChatMessages(systemPrompt, messages, contextWindowMessages, model) {
|
|
10533
|
+
function buildChatMessages(systemPrompt, messages, contextWindowMessages, model, provider) {
|
|
11435
10534
|
const recentMessages = messages.slice(-contextWindowMessages);
|
|
11436
10535
|
return [
|
|
11437
10536
|
{
|
|
@@ -11440,7 +10539,8 @@ function buildChatMessages(systemPrompt, messages, contextWindowMessages, model)
|
|
|
11440
10539
|
},
|
|
11441
10540
|
...recentMessages.map(
|
|
11442
10541
|
(message, index) => toChatMessage(message, {
|
|
11443
|
-
includeReasoning: shouldIncludeStoredAssistantReasoning(recentMessages, index, model)
|
|
10542
|
+
includeReasoning: shouldIncludeStoredAssistantReasoning(recentMessages, index, model, provider),
|
|
10543
|
+
provider
|
|
11444
10544
|
})
|
|
11445
10545
|
)
|
|
11446
10546
|
];
|
|
@@ -11525,19 +10625,23 @@ function expandStartToToolBoundary(messages, startIndex) {
|
|
|
11525
10625
|
}
|
|
11526
10626
|
return index;
|
|
11527
10627
|
}
|
|
11528
|
-
function modelUsesReasoningContent(model) {
|
|
11529
|
-
|
|
10628
|
+
function modelUsesReasoningContent(model, provider) {
|
|
10629
|
+
if (provider) {
|
|
10630
|
+
return resolveProviderCapabilities({ provider, model }).supportsReasoningContent;
|
|
10631
|
+
}
|
|
10632
|
+
return listModelInfos().some((item) => item.id === model && item.capabilities.reasoningContentReplay !== "never");
|
|
11530
10633
|
}
|
|
11531
10634
|
function isAssistantMessageInLatestTurn(messages, index) {
|
|
11532
10635
|
return messages[index]?.role === "assistant" && index > findLatestUserIndex(messages);
|
|
11533
10636
|
}
|
|
11534
|
-
function shouldIncludeStoredAssistantReasoning(messages, index, model) {
|
|
11535
|
-
return
|
|
10637
|
+
function shouldIncludeStoredAssistantReasoning(messages, index, model, provider) {
|
|
10638
|
+
return resolveProviderCapabilities({ provider, model }).supportsReasoningContent && messages[index]?.role === "assistant";
|
|
11536
10639
|
}
|
|
11537
10640
|
var init_messages = __esm({
|
|
11538
10641
|
"src/session/messages.ts"() {
|
|
11539
10642
|
"use strict";
|
|
11540
|
-
|
|
10643
|
+
init_catalog();
|
|
10644
|
+
init_capabilities();
|
|
11541
10645
|
}
|
|
11542
10646
|
});
|
|
11543
10647
|
|
|
@@ -11689,7 +10793,8 @@ function buildCompressedContextRequest(systemPrompt, messages, config) {
|
|
|
11689
10793
|
const safeMaxChars = Math.max(8e3, config.maxContextChars);
|
|
11690
10794
|
const conversation = buildVisibleConversationWindow(messages);
|
|
11691
10795
|
const conversationMessages = conversation.messages;
|
|
11692
|
-
const
|
|
10796
|
+
const provider = config.provider ?? "openai-compatible";
|
|
10797
|
+
const fullMessages = composeChatMessages(systemPrompt, conversationMessages, config.model, provider);
|
|
11693
10798
|
const initialEstimatedChars = estimateChatMessagesChars(fullMessages);
|
|
11694
10799
|
const initialPromptMetrics = measureSystemPrompt(systemPrompt);
|
|
11695
10800
|
const initialSources = buildBudgetSources(systemPrompt, conversationMessages);
|
|
@@ -11718,7 +10823,7 @@ function buildCompressedContextRequest(systemPrompt, messages, config) {
|
|
|
11718
10823
|
const summary = compressedFrameHead.length > 0 ? summarizeConversation(compressedFrameHead, config.contextSummaryChars) : void 0;
|
|
11719
10824
|
const summaryPrompt = appendSummary(systemPrompt, summary);
|
|
11720
10825
|
let workingTail = compactTailMessages(tailMessages, "normal");
|
|
11721
|
-
let requestMessages = composeChatMessages(summaryPrompt, workingTail, config.model);
|
|
10826
|
+
let requestMessages = composeChatMessages(summaryPrompt, workingTail, config.model, provider);
|
|
11722
10827
|
let estimatedChars = estimateChatMessagesChars(requestMessages);
|
|
11723
10828
|
let promptMetrics = measureSystemPrompt(summaryPrompt);
|
|
11724
10829
|
let cacheLayout = buildCacheLayoutReport(summaryPrompt, workingTail);
|
|
@@ -11743,7 +10848,7 @@ function buildCompressedContextRequest(systemPrompt, messages, config) {
|
|
|
11743
10848
|
};
|
|
11744
10849
|
}
|
|
11745
10850
|
workingTail = compactTailMessages(tailMessages, "aggressive");
|
|
11746
|
-
requestMessages = composeChatMessages(summaryPrompt, workingTail, config.model);
|
|
10851
|
+
requestMessages = composeChatMessages(summaryPrompt, workingTail, config.model, provider);
|
|
11747
10852
|
estimatedChars = estimateChatMessagesChars(requestMessages);
|
|
11748
10853
|
promptMetrics = measureSystemPrompt(summaryPrompt);
|
|
11749
10854
|
cacheLayout = buildCacheLayoutReport(summaryPrompt, workingTail);
|
|
@@ -11779,7 +10884,8 @@ function buildCompressedContextRequest(systemPrompt, messages, config) {
|
|
|
11779
10884
|
const hardMessages = composeChatMessages(
|
|
11780
10885
|
hardPrompt,
|
|
11781
10886
|
compactedHardTail,
|
|
11782
|
-
config.model
|
|
10887
|
+
config.model,
|
|
10888
|
+
provider
|
|
11783
10889
|
);
|
|
11784
10890
|
const hardEstimatedChars = estimateChatMessagesChars(hardMessages);
|
|
11785
10891
|
const hardCacheLayout = buildCacheLayoutReport(hardPrompt, compactedHardTail);
|
|
@@ -11814,7 +10920,7 @@ function sliceTailMessages(messages, tailCount) {
|
|
|
11814
10920
|
const safeStartIndex = expandStartToToolBoundary(messages, startIndex);
|
|
11815
10921
|
return messages.slice(safeStartIndex);
|
|
11816
10922
|
}
|
|
11817
|
-
function composeChatMessages(systemPrompt, messages, model) {
|
|
10923
|
+
function composeChatMessages(systemPrompt, messages, model, provider) {
|
|
11818
10924
|
return [
|
|
11819
10925
|
{
|
|
11820
10926
|
role: "system",
|
|
@@ -11826,7 +10932,7 @@ function composeChatMessages(systemPrompt, messages, model) {
|
|
|
11826
10932
|
name: message.name,
|
|
11827
10933
|
toolCallId: message.tool_call_id,
|
|
11828
10934
|
toolCalls: message.tool_calls,
|
|
11829
|
-
reasoningContent: shouldIncludeStoredAssistantReasoning(messages, index, model) ? message.reasoningContent : void 0
|
|
10935
|
+
reasoningContent: shouldIncludeStoredAssistantReasoning(messages, index, model, provider) ? message.reasoningContent : void 0
|
|
11830
10936
|
}))
|
|
11831
10937
|
];
|
|
11832
10938
|
}
|
|
@@ -12864,6 +11970,853 @@ var init_finalize = __esm({
|
|
|
12864
11970
|
}
|
|
12865
11971
|
});
|
|
12866
11972
|
|
|
11973
|
+
// src/provider/apiRetry.ts
|
|
11974
|
+
async function withApiRetries(operation, abortSignal) {
|
|
11975
|
+
let lastError;
|
|
11976
|
+
for (let attempt = 1; attempt <= API_MAX_RETRIES; attempt += 1) {
|
|
11977
|
+
try {
|
|
11978
|
+
return await operation();
|
|
11979
|
+
} catch (error) {
|
|
11980
|
+
if (isAbortError(error)) {
|
|
11981
|
+
throw error;
|
|
11982
|
+
}
|
|
11983
|
+
lastError = error;
|
|
11984
|
+
if (!isRetryableApiError(error) || attempt === API_MAX_RETRIES) {
|
|
11985
|
+
break;
|
|
11986
|
+
}
|
|
11987
|
+
await sleepWithSignal(API_RETRY_BASE_DELAY_MS * attempt, abortSignal);
|
|
11988
|
+
}
|
|
11989
|
+
}
|
|
11990
|
+
throw lastError;
|
|
11991
|
+
}
|
|
11992
|
+
function isRetryableApiError(error) {
|
|
11993
|
+
const status = error.status;
|
|
11994
|
+
if (typeof status === "number") {
|
|
11995
|
+
return status === 408 || status === 409 || status === 429 || status >= 500;
|
|
11996
|
+
}
|
|
11997
|
+
const message = String(error.message ?? error).toLowerCase();
|
|
11998
|
+
return message.includes("timeout") || message.includes("network") || message.includes("connection error") || message.includes("connection reset") || message.includes("econnreset") || message.includes("econnrefused") || message.includes("connect timeout") || message.includes("temporarily") || message.includes("rate limit") || message.includes("overloaded");
|
|
11999
|
+
}
|
|
12000
|
+
var API_MAX_RETRIES, API_RETRY_BASE_DELAY_MS;
|
|
12001
|
+
var init_apiRetry = __esm({
|
|
12002
|
+
"src/provider/apiRetry.ts"() {
|
|
12003
|
+
"use strict";
|
|
12004
|
+
init_abort();
|
|
12005
|
+
API_MAX_RETRIES = 3;
|
|
12006
|
+
API_RETRY_BASE_DELAY_MS = 1200;
|
|
12007
|
+
}
|
|
12008
|
+
});
|
|
12009
|
+
|
|
12010
|
+
// src/provider/chatRequestBody.ts
|
|
12011
|
+
function buildProviderRequestBody(input) {
|
|
12012
|
+
const capabilities = resolveProviderCapabilities(input);
|
|
12013
|
+
const thinking = capabilities.provider === "deepseek" ? resolveDeepSeekThinking(input.messages, input.thinking ?? "enabled") : input.thinking;
|
|
12014
|
+
const body = {
|
|
12015
|
+
model: input.model,
|
|
12016
|
+
messages: toChatCompletionMessages(input.messages),
|
|
12017
|
+
tools: input.tools,
|
|
12018
|
+
stream: input.stream
|
|
12019
|
+
};
|
|
12020
|
+
if (capabilities.provider !== "deepseek" && input.tools?.length) {
|
|
12021
|
+
body.tool_choice = "auto";
|
|
12022
|
+
}
|
|
12023
|
+
if (input.stream) {
|
|
12024
|
+
body.stream_options = {
|
|
12025
|
+
include_usage: true
|
|
12026
|
+
};
|
|
12027
|
+
}
|
|
12028
|
+
const cachePolicy = resolveProviderCachePolicy(input);
|
|
12029
|
+
if (cachePolicy.promptCacheKey) {
|
|
12030
|
+
body.prompt_cache_key = cachePolicy.promptCacheKey;
|
|
12031
|
+
}
|
|
12032
|
+
if (typeof input.maxOutputTokens === "number" && Number.isFinite(input.maxOutputTokens)) {
|
|
12033
|
+
body.max_tokens = Math.max(1, Math.trunc(input.maxOutputTokens));
|
|
12034
|
+
}
|
|
12035
|
+
if (capabilities.provider === "deepseek") {
|
|
12036
|
+
body.thinking = { type: thinking };
|
|
12037
|
+
if (thinking === "enabled") {
|
|
12038
|
+
body.reasoning_effort = normalizeDeepSeekReasoningEffort(input.reasoningEffort ?? capabilities.defaultReasoningEffort);
|
|
12039
|
+
}
|
|
12040
|
+
} else if (input.forceReasoning || capabilities.defaultReasoningEnabled) {
|
|
12041
|
+
body.thinking = { type: "enabled" };
|
|
12042
|
+
}
|
|
12043
|
+
return body;
|
|
12044
|
+
}
|
|
12045
|
+
function resolveDeepSeekThinking(messages, requested) {
|
|
12046
|
+
if (requested === "disabled") {
|
|
12047
|
+
return "disabled";
|
|
12048
|
+
}
|
|
12049
|
+
if (hasUnreplayableAssistantReasoning(messages)) {
|
|
12050
|
+
throw new Error("DeepSeek thinking tool-call replay requires stored reasoning_content. Start a new turn or disable KITTY_THINKING.");
|
|
12051
|
+
}
|
|
12052
|
+
return "enabled";
|
|
12053
|
+
}
|
|
12054
|
+
function hasUnreplayableAssistantReasoning(messages) {
|
|
12055
|
+
return messages.some(
|
|
12056
|
+
(message) => message.role === "assistant" && Array.isArray(message.toolCalls) && message.toolCalls.length > 0 && message.reasoningContent === void 0
|
|
12057
|
+
);
|
|
12058
|
+
}
|
|
12059
|
+
function normalizeDeepSeekReasoningEffort(effort) {
|
|
12060
|
+
if (effort === void 0 || effort === "minimal" || effort === "low" || effort === "medium" || effort === "high") {
|
|
12061
|
+
return "high";
|
|
12062
|
+
}
|
|
12063
|
+
if (effort === "xhigh" || effort === "max") {
|
|
12064
|
+
return "max";
|
|
12065
|
+
}
|
|
12066
|
+
return "high";
|
|
12067
|
+
}
|
|
12068
|
+
var init_chatRequestBody = __esm({
|
|
12069
|
+
"src/provider/chatRequestBody.ts"() {
|
|
12070
|
+
"use strict";
|
|
12071
|
+
init_cachePolicy();
|
|
12072
|
+
init_capabilities();
|
|
12073
|
+
init_chatCompletionsAdapter();
|
|
12074
|
+
}
|
|
12075
|
+
});
|
|
12076
|
+
|
|
12077
|
+
// src/provider/chatCompletionsAdapter.ts
|
|
12078
|
+
function abortStream(stream) {
|
|
12079
|
+
try {
|
|
12080
|
+
stream?.controller?.abort();
|
|
12081
|
+
} catch {
|
|
12082
|
+
}
|
|
12083
|
+
}
|
|
12084
|
+
function toChatCompletionMessages(messages) {
|
|
12085
|
+
return messages.map((message) => {
|
|
12086
|
+
if (message.role === "tool") {
|
|
12087
|
+
return {
|
|
12088
|
+
role: "tool",
|
|
12089
|
+
content: message.content ?? "",
|
|
12090
|
+
tool_call_id: message.toolCallId ?? ""
|
|
12091
|
+
};
|
|
12092
|
+
}
|
|
12093
|
+
if (message.role === "assistant" && message.toolCalls?.length) {
|
|
12094
|
+
const assistantMessage = {
|
|
12095
|
+
role: "assistant",
|
|
12096
|
+
content: message.content ?? "",
|
|
12097
|
+
tool_calls: message.toolCalls
|
|
12098
|
+
};
|
|
12099
|
+
if (message.reasoningContent !== void 0) {
|
|
12100
|
+
assistantMessage.reasoning_content = message.reasoningContent;
|
|
12101
|
+
}
|
|
12102
|
+
return assistantMessage;
|
|
12103
|
+
}
|
|
12104
|
+
const baseMessage = {
|
|
12105
|
+
role: message.role,
|
|
12106
|
+
content: message.content ?? "",
|
|
12107
|
+
name: message.name
|
|
12108
|
+
};
|
|
12109
|
+
if (message.role === "assistant" && message.reasoningContent !== void 0) {
|
|
12110
|
+
baseMessage.reasoning_content = message.reasoningContent;
|
|
12111
|
+
}
|
|
12112
|
+
return baseMessage;
|
|
12113
|
+
});
|
|
12114
|
+
}
|
|
12115
|
+
var chatCompletionsAdapter;
|
|
12116
|
+
var init_chatCompletionsAdapter = __esm({
|
|
12117
|
+
"src/provider/chatCompletionsAdapter.ts"() {
|
|
12118
|
+
"use strict";
|
|
12119
|
+
init_messages();
|
|
12120
|
+
init_chatRequestBody();
|
|
12121
|
+
init_usageNormalizer();
|
|
12122
|
+
init_abort();
|
|
12123
|
+
chatCompletionsAdapter = {
|
|
12124
|
+
wireApi: "chat.completions",
|
|
12125
|
+
async fetchStreaming(client, request) {
|
|
12126
|
+
const startedAt = Date.now();
|
|
12127
|
+
let usage;
|
|
12128
|
+
throwIfAborted(request.abortSignal, "Streaming request aborted");
|
|
12129
|
+
try {
|
|
12130
|
+
const stream = await client.chat.completions.create(
|
|
12131
|
+
{
|
|
12132
|
+
...buildProviderRequestBody({
|
|
12133
|
+
provider: request.provider,
|
|
12134
|
+
model: request.model,
|
|
12135
|
+
messages: request.messages,
|
|
12136
|
+
tools: request.tools,
|
|
12137
|
+
stream: true,
|
|
12138
|
+
forceReasoning: request.forceReasoning,
|
|
12139
|
+
thinking: request.thinking,
|
|
12140
|
+
reasoningEffort: request.reasoningEffort,
|
|
12141
|
+
maxOutputTokens: request.maxOutputTokens,
|
|
12142
|
+
sessionId: request.sessionId,
|
|
12143
|
+
projectRoot: request.projectRoot
|
|
12144
|
+
}),
|
|
12145
|
+
signal: request.abortSignal
|
|
12146
|
+
}
|
|
12147
|
+
);
|
|
12148
|
+
if (request.abortSignal?.aborted) {
|
|
12149
|
+
abortStream(stream);
|
|
12150
|
+
throw createAbortError("Streaming aborted");
|
|
12151
|
+
}
|
|
12152
|
+
let content = "";
|
|
12153
|
+
let reasoningContent = "";
|
|
12154
|
+
const toolCallParts = /* @__PURE__ */ new Map();
|
|
12155
|
+
for await (const chunk of stream) {
|
|
12156
|
+
if (request.abortSignal?.aborted) {
|
|
12157
|
+
abortStream(stream);
|
|
12158
|
+
throw createAbortError("Streaming aborted");
|
|
12159
|
+
}
|
|
12160
|
+
usage = normalizeProviderUsage(chunk.usage) ?? usage;
|
|
12161
|
+
const delta = chunk.choices?.[0]?.delta;
|
|
12162
|
+
if (!delta) {
|
|
12163
|
+
continue;
|
|
12164
|
+
}
|
|
12165
|
+
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
12166
|
+
content += delta.content;
|
|
12167
|
+
request.callbacks?.onAssistantDelta?.(delta.content);
|
|
12168
|
+
}
|
|
12169
|
+
if (typeof delta.reasoning_content === "string" && delta.reasoning_content.length > 0) {
|
|
12170
|
+
reasoningContent += delta.reasoning_content;
|
|
12171
|
+
request.callbacks?.onReasoningDelta?.(delta.reasoning_content);
|
|
12172
|
+
}
|
|
12173
|
+
if (Array.isArray(delta.tool_calls)) {
|
|
12174
|
+
for (const toolCall of delta.tool_calls) {
|
|
12175
|
+
const index = typeof toolCall.index === "number" ? toolCall.index : 0;
|
|
12176
|
+
const existing = toolCallParts.get(index) ?? {
|
|
12177
|
+
id: toolCall.id ?? `tool-${index}`,
|
|
12178
|
+
name: "",
|
|
12179
|
+
arguments: ""
|
|
12180
|
+
};
|
|
12181
|
+
if (toolCall.id) {
|
|
12182
|
+
existing.id = toolCall.id;
|
|
12183
|
+
}
|
|
12184
|
+
if (toolCall.function?.name) {
|
|
12185
|
+
existing.name += toolCall.function.name;
|
|
12186
|
+
}
|
|
12187
|
+
if (toolCall.function?.arguments) {
|
|
12188
|
+
existing.arguments += toolCall.function.arguments;
|
|
12189
|
+
}
|
|
12190
|
+
toolCallParts.set(index, existing);
|
|
12191
|
+
}
|
|
12192
|
+
}
|
|
12193
|
+
}
|
|
12194
|
+
return {
|
|
12195
|
+
content: content.length > 0 ? content : null,
|
|
12196
|
+
reasoningContent: reasoningContent.length > 0 ? reasoningContent : void 0,
|
|
12197
|
+
streamedAssistantContent: content.length > 0,
|
|
12198
|
+
streamedReasoningContent: reasoningContent.length > 0,
|
|
12199
|
+
toolCalls: [...toolCallParts.entries()].sort((left, right) => left[0] - right[0]).map(([, toolCall]) => ({
|
|
12200
|
+
id: toolCall.id,
|
|
12201
|
+
type: "function",
|
|
12202
|
+
function: {
|
|
12203
|
+
name: toolCall.name,
|
|
12204
|
+
arguments: toolCall.arguments
|
|
12205
|
+
}
|
|
12206
|
+
}))
|
|
12207
|
+
};
|
|
12208
|
+
} finally {
|
|
12209
|
+
request.onRequestMetric?.({
|
|
12210
|
+
durationMs: Date.now() - startedAt,
|
|
12211
|
+
usage
|
|
12212
|
+
});
|
|
12213
|
+
}
|
|
12214
|
+
},
|
|
12215
|
+
async fetchNonStreaming(client, request) {
|
|
12216
|
+
const startedAt = Date.now();
|
|
12217
|
+
let usage;
|
|
12218
|
+
throwIfAborted(request.abortSignal, "Request aborted");
|
|
12219
|
+
try {
|
|
12220
|
+
const completion = await client.chat.completions.create(
|
|
12221
|
+
{
|
|
12222
|
+
...buildProviderRequestBody({
|
|
12223
|
+
provider: request.provider,
|
|
12224
|
+
model: request.model,
|
|
12225
|
+
messages: request.messages,
|
|
12226
|
+
tools: request.tools,
|
|
12227
|
+
stream: false,
|
|
12228
|
+
forceReasoning: request.forceReasoning,
|
|
12229
|
+
thinking: request.thinking,
|
|
12230
|
+
reasoningEffort: request.reasoningEffort,
|
|
12231
|
+
maxOutputTokens: request.maxOutputTokens,
|
|
12232
|
+
sessionId: request.sessionId,
|
|
12233
|
+
projectRoot: request.projectRoot
|
|
12234
|
+
}),
|
|
12235
|
+
signal: request.abortSignal
|
|
12236
|
+
}
|
|
12237
|
+
);
|
|
12238
|
+
usage = normalizeProviderUsage(completion.usage);
|
|
12239
|
+
const message = completion.choices[0]?.message;
|
|
12240
|
+
if (!message) {
|
|
12241
|
+
throw new Error("API returned no message.");
|
|
12242
|
+
}
|
|
12243
|
+
return {
|
|
12244
|
+
content: typeof message.content === "string" ? message.content : collapseContentParts(message.content),
|
|
12245
|
+
reasoningContent: readReasoningContent(message),
|
|
12246
|
+
streamedAssistantContent: false,
|
|
12247
|
+
streamedReasoningContent: false,
|
|
12248
|
+
toolCalls: (message.tool_calls ?? []).filter((call) => call.type === "function").map((call) => ({
|
|
12249
|
+
id: call.id,
|
|
12250
|
+
type: "function",
|
|
12251
|
+
function: {
|
|
12252
|
+
name: call.function.name,
|
|
12253
|
+
arguments: call.function.arguments
|
|
12254
|
+
}
|
|
12255
|
+
}))
|
|
12256
|
+
};
|
|
12257
|
+
} finally {
|
|
12258
|
+
request.onRequestMetric?.({
|
|
12259
|
+
durationMs: Date.now() - startedAt,
|
|
12260
|
+
usage
|
|
12261
|
+
});
|
|
12262
|
+
}
|
|
12263
|
+
}
|
|
12264
|
+
};
|
|
12265
|
+
}
|
|
12266
|
+
});
|
|
12267
|
+
|
|
12268
|
+
// src/provider/responsesAdapter.ts
|
|
12269
|
+
function buildResponsesRequestBody(request) {
|
|
12270
|
+
const capabilities = resolveProviderCapabilities({
|
|
12271
|
+
provider: request.provider,
|
|
12272
|
+
model: request.model
|
|
12273
|
+
});
|
|
12274
|
+
const body = {
|
|
12275
|
+
model: request.model,
|
|
12276
|
+
input: toResponsesInput(request.messages),
|
|
12277
|
+
tools: request.tools?.map((tool) => ({
|
|
12278
|
+
type: "function",
|
|
12279
|
+
name: tool.function.name,
|
|
12280
|
+
description: tool.function.description,
|
|
12281
|
+
parameters: tool.function.parameters ?? null,
|
|
12282
|
+
strict: false
|
|
12283
|
+
})),
|
|
12284
|
+
tool_choice: request.tools?.length ? "auto" : void 0
|
|
12285
|
+
};
|
|
12286
|
+
if (typeof request.maxOutputTokens === "number" && Number.isFinite(request.maxOutputTokens)) {
|
|
12287
|
+
body.max_output_tokens = Math.max(1, Math.trunc(request.maxOutputTokens));
|
|
12288
|
+
}
|
|
12289
|
+
const cachePolicy = resolveProviderCachePolicy({
|
|
12290
|
+
provider: request.provider,
|
|
12291
|
+
model: request.model,
|
|
12292
|
+
sessionId: request.sessionId,
|
|
12293
|
+
projectRoot: request.projectRoot
|
|
12294
|
+
});
|
|
12295
|
+
if (cachePolicy.promptCacheKey) {
|
|
12296
|
+
body.prompt_cache_key = cachePolicy.promptCacheKey;
|
|
12297
|
+
}
|
|
12298
|
+
const reasoningEffort = request.thinking === "disabled" ? void 0 : normalizeResponsesReasoningEffort(
|
|
12299
|
+
request.reasoningEffort ?? capabilities.defaultReasoningEffort
|
|
12300
|
+
);
|
|
12301
|
+
if (request.thinking !== "disabled" && (request.forceReasoning || capabilities.defaultReasoningEnabled || request.thinking === "enabled" || reasoningEffort)) {
|
|
12302
|
+
body.reasoning = {
|
|
12303
|
+
effort: reasoningEffort ?? "high",
|
|
12304
|
+
summary: "detailed"
|
|
12305
|
+
};
|
|
12306
|
+
}
|
|
12307
|
+
return body;
|
|
12308
|
+
}
|
|
12309
|
+
function normalizeResponsesReasoningEffort(effort) {
|
|
12310
|
+
if (effort === "xhigh") {
|
|
12311
|
+
return "xhigh";
|
|
12312
|
+
}
|
|
12313
|
+
return effort === "max" ? void 0 : effort;
|
|
12314
|
+
}
|
|
12315
|
+
function toResponsesInput(messages) {
|
|
12316
|
+
const items = [];
|
|
12317
|
+
for (const message of messages) {
|
|
12318
|
+
if (message.role === "tool") {
|
|
12319
|
+
items.push({
|
|
12320
|
+
type: "function_call_output",
|
|
12321
|
+
call_id: message.toolCallId ?? "",
|
|
12322
|
+
output: message.content ?? ""
|
|
12323
|
+
});
|
|
12324
|
+
continue;
|
|
12325
|
+
}
|
|
12326
|
+
if (message.role === "assistant" && message.toolCalls?.length) {
|
|
12327
|
+
if (typeof message.content === "string" && message.content.trim().length > 0) {
|
|
12328
|
+
items.push({
|
|
12329
|
+
type: "message",
|
|
12330
|
+
role: "assistant",
|
|
12331
|
+
content: message.content
|
|
12332
|
+
});
|
|
12333
|
+
}
|
|
12334
|
+
for (const toolCall of message.toolCalls) {
|
|
12335
|
+
items.push({
|
|
12336
|
+
type: "function_call",
|
|
12337
|
+
call_id: toolCall.id,
|
|
12338
|
+
name: toolCall.function.name,
|
|
12339
|
+
arguments: toolCall.function.arguments
|
|
12340
|
+
});
|
|
12341
|
+
}
|
|
12342
|
+
continue;
|
|
12343
|
+
}
|
|
12344
|
+
items.push({
|
|
12345
|
+
type: "message",
|
|
12346
|
+
role: message.role,
|
|
12347
|
+
content: message.content ?? ""
|
|
12348
|
+
});
|
|
12349
|
+
}
|
|
12350
|
+
return items;
|
|
12351
|
+
}
|
|
12352
|
+
function normalizeOutputText(response) {
|
|
12353
|
+
const outputText = response.output_text;
|
|
12354
|
+
if (typeof outputText === "string" && outputText.trim().length > 0) {
|
|
12355
|
+
return outputText;
|
|
12356
|
+
}
|
|
12357
|
+
const output = response.output;
|
|
12358
|
+
if (!Array.isArray(output)) {
|
|
12359
|
+
return null;
|
|
12360
|
+
}
|
|
12361
|
+
const fragments = output.flatMap((item) => {
|
|
12362
|
+
if (!item || typeof item !== "object" || item.type !== "message") {
|
|
12363
|
+
return [];
|
|
12364
|
+
}
|
|
12365
|
+
const content = item.content;
|
|
12366
|
+
if (!Array.isArray(content)) {
|
|
12367
|
+
return [];
|
|
12368
|
+
}
|
|
12369
|
+
return content.flatMap((part) => {
|
|
12370
|
+
if (!part || typeof part !== "object" || part.type !== "output_text") {
|
|
12371
|
+
return [];
|
|
12372
|
+
}
|
|
12373
|
+
return typeof part.text === "string" ? [part.text] : [];
|
|
12374
|
+
});
|
|
12375
|
+
});
|
|
12376
|
+
return fragments.length > 0 ? fragments.join("") : null;
|
|
12377
|
+
}
|
|
12378
|
+
function readResponseToolCalls(response) {
|
|
12379
|
+
const output = response.output;
|
|
12380
|
+
if (!Array.isArray(output)) {
|
|
12381
|
+
return [];
|
|
12382
|
+
}
|
|
12383
|
+
return output.filter((item) => Boolean(item) && typeof item === "object" && item.type === "function_call").map((item) => ({
|
|
12384
|
+
id: item.call_id ?? item.id ?? crypto.randomUUID(),
|
|
12385
|
+
type: "function",
|
|
12386
|
+
function: {
|
|
12387
|
+
name: item.name ?? "",
|
|
12388
|
+
arguments: item.arguments ?? ""
|
|
12389
|
+
}
|
|
12390
|
+
}));
|
|
12391
|
+
}
|
|
12392
|
+
function readResponseReasoning(response) {
|
|
12393
|
+
const output = response.output;
|
|
12394
|
+
if (!Array.isArray(output)) {
|
|
12395
|
+
return void 0;
|
|
12396
|
+
}
|
|
12397
|
+
const fragments = output.flatMap((item) => {
|
|
12398
|
+
if (!item || typeof item !== "object" || item.type !== "reasoning") {
|
|
12399
|
+
return [];
|
|
12400
|
+
}
|
|
12401
|
+
const reasoningItem = item;
|
|
12402
|
+
const summary = Array.isArray(reasoningItem.summary) ? reasoningItem.summary.map((entry) => typeof entry?.text === "string" ? entry.text : "").filter(Boolean) : [];
|
|
12403
|
+
const content = Array.isArray(reasoningItem.content) ? reasoningItem.content.map((entry) => typeof entry?.text === "string" ? entry.text : "").filter(Boolean) : [];
|
|
12404
|
+
return [...content, ...summary];
|
|
12405
|
+
});
|
|
12406
|
+
return fragments.length > 0 ? fragments.join("") : void 0;
|
|
12407
|
+
}
|
|
12408
|
+
function abortStream2(stream) {
|
|
12409
|
+
try {
|
|
12410
|
+
stream?.controller?.abort();
|
|
12411
|
+
} catch {
|
|
12412
|
+
}
|
|
12413
|
+
}
|
|
12414
|
+
var responsesAdapter;
|
|
12415
|
+
var init_responsesAdapter = __esm({
|
|
12416
|
+
"src/provider/responsesAdapter.ts"() {
|
|
12417
|
+
"use strict";
|
|
12418
|
+
init_capabilities();
|
|
12419
|
+
init_cachePolicy();
|
|
12420
|
+
init_usageNormalizer();
|
|
12421
|
+
init_abort();
|
|
12422
|
+
responsesAdapter = {
|
|
12423
|
+
wireApi: "responses",
|
|
12424
|
+
async fetchStreaming(client, request) {
|
|
12425
|
+
const startedAt = Date.now();
|
|
12426
|
+
let usage;
|
|
12427
|
+
throwIfAborted(request.abortSignal, "Streaming request aborted");
|
|
12428
|
+
try {
|
|
12429
|
+
const stream = await client.responses.create(
|
|
12430
|
+
{
|
|
12431
|
+
...buildResponsesRequestBody(request),
|
|
12432
|
+
stream: true
|
|
12433
|
+
},
|
|
12434
|
+
{
|
|
12435
|
+
signal: request.abortSignal
|
|
12436
|
+
}
|
|
12437
|
+
);
|
|
12438
|
+
if (request.abortSignal?.aborted) {
|
|
12439
|
+
abortStream2(stream);
|
|
12440
|
+
throw createAbortError("Streaming aborted");
|
|
12441
|
+
}
|
|
12442
|
+
let content = "";
|
|
12443
|
+
let reasoningContent = "";
|
|
12444
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
12445
|
+
for await (const event of stream) {
|
|
12446
|
+
if (request.abortSignal?.aborted) {
|
|
12447
|
+
abortStream2(stream);
|
|
12448
|
+
throw createAbortError("Streaming aborted");
|
|
12449
|
+
}
|
|
12450
|
+
usage = normalizeProviderUsage(event.response?.usage) ?? usage;
|
|
12451
|
+
if (event.type === "response.output_text.delta" && typeof event.delta === "string") {
|
|
12452
|
+
content += event.delta;
|
|
12453
|
+
request.callbacks?.onAssistantDelta?.(event.delta);
|
|
12454
|
+
continue;
|
|
12455
|
+
}
|
|
12456
|
+
if ((event.type === "response.reasoning_text.delta" || event.type === "response.reasoning_summary_text.delta") && typeof event.delta === "string") {
|
|
12457
|
+
reasoningContent += event.delta;
|
|
12458
|
+
request.callbacks?.onReasoningDelta?.(event.delta);
|
|
12459
|
+
continue;
|
|
12460
|
+
}
|
|
12461
|
+
if (event.type === "response.function_call_arguments.delta" && typeof event.delta === "string") {
|
|
12462
|
+
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
12463
|
+
const existing = toolCalls.get(index) ?? {
|
|
12464
|
+
id: event.item_id ?? `tool-${index}`,
|
|
12465
|
+
name: "",
|
|
12466
|
+
arguments: ""
|
|
12467
|
+
};
|
|
12468
|
+
existing.arguments += event.delta;
|
|
12469
|
+
toolCalls.set(index, existing);
|
|
12470
|
+
continue;
|
|
12471
|
+
}
|
|
12472
|
+
if (event.type === "response.function_call_arguments.done") {
|
|
12473
|
+
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
12474
|
+
const existing = toolCalls.get(index) ?? {
|
|
12475
|
+
id: event.item_id ?? `tool-${index}`,
|
|
12476
|
+
name: "",
|
|
12477
|
+
arguments: ""
|
|
12478
|
+
};
|
|
12479
|
+
if (typeof event.name === "string") {
|
|
12480
|
+
existing.name = event.name;
|
|
12481
|
+
}
|
|
12482
|
+
if (typeof event.arguments === "string" && event.arguments.length > 0) {
|
|
12483
|
+
existing.arguments = event.arguments;
|
|
12484
|
+
}
|
|
12485
|
+
toolCalls.set(index, existing);
|
|
12486
|
+
continue;
|
|
12487
|
+
}
|
|
12488
|
+
if (event.type === "response.output_item.done" && event.item?.type === "function_call") {
|
|
12489
|
+
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
12490
|
+
toolCalls.set(index, {
|
|
12491
|
+
id: event.item.call_id ?? event.item.id ?? `tool-${index}`,
|
|
12492
|
+
name: event.item.name ?? "",
|
|
12493
|
+
arguments: event.item.arguments ?? ""
|
|
12494
|
+
});
|
|
12495
|
+
}
|
|
12496
|
+
}
|
|
12497
|
+
return {
|
|
12498
|
+
content: content.length > 0 ? content : null,
|
|
12499
|
+
reasoningContent: reasoningContent.length > 0 ? reasoningContent : void 0,
|
|
12500
|
+
streamedAssistantContent: content.length > 0,
|
|
12501
|
+
streamedReasoningContent: reasoningContent.length > 0,
|
|
12502
|
+
toolCalls: [...toolCalls.entries()].sort((left, right) => left[0] - right[0]).map(([, toolCall]) => ({
|
|
12503
|
+
id: toolCall.id,
|
|
12504
|
+
type: "function",
|
|
12505
|
+
function: {
|
|
12506
|
+
name: toolCall.name,
|
|
12507
|
+
arguments: toolCall.arguments
|
|
12508
|
+
}
|
|
12509
|
+
}))
|
|
12510
|
+
};
|
|
12511
|
+
} finally {
|
|
12512
|
+
request.onRequestMetric?.({
|
|
12513
|
+
durationMs: Date.now() - startedAt,
|
|
12514
|
+
usage
|
|
12515
|
+
});
|
|
12516
|
+
}
|
|
12517
|
+
},
|
|
12518
|
+
async fetchNonStreaming(client, request) {
|
|
12519
|
+
const startedAt = Date.now();
|
|
12520
|
+
let usage;
|
|
12521
|
+
throwIfAborted(request.abortSignal, "Request aborted");
|
|
12522
|
+
try {
|
|
12523
|
+
const response = await client.responses.create(
|
|
12524
|
+
{
|
|
12525
|
+
...buildResponsesRequestBody(request),
|
|
12526
|
+
stream: false
|
|
12527
|
+
},
|
|
12528
|
+
{
|
|
12529
|
+
signal: request.abortSignal
|
|
12530
|
+
}
|
|
12531
|
+
);
|
|
12532
|
+
usage = normalizeProviderUsage(response.usage);
|
|
12533
|
+
return {
|
|
12534
|
+
content: normalizeOutputText(response),
|
|
12535
|
+
reasoningContent: readResponseReasoning(response),
|
|
12536
|
+
streamedAssistantContent: false,
|
|
12537
|
+
streamedReasoningContent: false,
|
|
12538
|
+
toolCalls: readResponseToolCalls(response)
|
|
12539
|
+
};
|
|
12540
|
+
} finally {
|
|
12541
|
+
request.onRequestMetric?.({
|
|
12542
|
+
durationMs: Date.now() - startedAt,
|
|
12543
|
+
usage
|
|
12544
|
+
});
|
|
12545
|
+
}
|
|
12546
|
+
}
|
|
12547
|
+
};
|
|
12548
|
+
}
|
|
12549
|
+
});
|
|
12550
|
+
|
|
12551
|
+
// src/provider/client.ts
|
|
12552
|
+
function createProviderClientPool(config) {
|
|
12553
|
+
const capabilities = resolveProviderCapabilities({
|
|
12554
|
+
provider: config.provider,
|
|
12555
|
+
model: config.model
|
|
12556
|
+
});
|
|
12557
|
+
const baseUrls = buildProviderBaseUrlCandidates(config.baseUrl);
|
|
12558
|
+
const clients = /* @__PURE__ */ new Map();
|
|
12559
|
+
let preferredBaseUrl;
|
|
12560
|
+
return {
|
|
12561
|
+
candidates() {
|
|
12562
|
+
const ordered = preferredBaseUrl ? [preferredBaseUrl, ...baseUrls.filter((baseUrl) => baseUrl !== preferredBaseUrl)] : baseUrls;
|
|
12563
|
+
return ordered.map((baseUrl) => ({
|
|
12564
|
+
baseUrl,
|
|
12565
|
+
client: getOrCreateClient(baseUrl)
|
|
12566
|
+
}));
|
|
12567
|
+
},
|
|
12568
|
+
markHealthy(baseUrl) {
|
|
12569
|
+
preferredBaseUrl = baseUrl;
|
|
12570
|
+
}
|
|
12571
|
+
};
|
|
12572
|
+
function getOrCreateClient(baseUrl) {
|
|
12573
|
+
const existing = clients.get(baseUrl);
|
|
12574
|
+
if (existing) {
|
|
12575
|
+
return existing;
|
|
12576
|
+
}
|
|
12577
|
+
const client = new import_openai.default({
|
|
12578
|
+
apiKey: config.apiKey,
|
|
12579
|
+
baseURL: baseUrl,
|
|
12580
|
+
timeout: capabilities.requestTimeoutMs,
|
|
12581
|
+
maxRetries: 0
|
|
12582
|
+
});
|
|
12583
|
+
clients.set(baseUrl, client);
|
|
12584
|
+
return client;
|
|
12585
|
+
}
|
|
12586
|
+
}
|
|
12587
|
+
function isProviderClientPool(value) {
|
|
12588
|
+
return Boolean(
|
|
12589
|
+
value && typeof value === "object" && typeof value.candidates === "function" && typeof value.markHealthy === "function"
|
|
12590
|
+
);
|
|
12591
|
+
}
|
|
12592
|
+
var import_openai;
|
|
12593
|
+
var init_client = __esm({
|
|
12594
|
+
"src/provider/client.ts"() {
|
|
12595
|
+
"use strict";
|
|
12596
|
+
import_openai = __toESM(require("openai"));
|
|
12597
|
+
init_capabilities();
|
|
12598
|
+
init_connection();
|
|
12599
|
+
}
|
|
12600
|
+
});
|
|
12601
|
+
|
|
12602
|
+
// src/provider/request.ts
|
|
12603
|
+
async function fetchAssistantResponse(client, messages, request, tools, callbacks, abortSignal, onRequestMetric, observability) {
|
|
12604
|
+
const capabilities = resolveProviderCapabilities(request);
|
|
12605
|
+
const adapter = selectProviderWireAdapter(capabilities.wireApi);
|
|
12606
|
+
return tryFetch(
|
|
12607
|
+
adapter,
|
|
12608
|
+
client,
|
|
12609
|
+
messages,
|
|
12610
|
+
request,
|
|
12611
|
+
tools,
|
|
12612
|
+
callbacks,
|
|
12613
|
+
false,
|
|
12614
|
+
abortSignal,
|
|
12615
|
+
onRequestMetric,
|
|
12616
|
+
observability
|
|
12617
|
+
);
|
|
12618
|
+
}
|
|
12619
|
+
async function tryFetch(adapter, client, messages, request, tools, callbacks, forceReasoning, abortSignal, onRequestMetric, observability) {
|
|
12620
|
+
const startedAt = Date.now();
|
|
12621
|
+
let latestMetric;
|
|
12622
|
+
let resolvedBaseUrl;
|
|
12623
|
+
const forwardMetric = (metric) => {
|
|
12624
|
+
latestMetric = metric;
|
|
12625
|
+
onRequestMetric?.(metric);
|
|
12626
|
+
};
|
|
12627
|
+
if (observability) {
|
|
12628
|
+
await recordObservabilityEvent(observability.rootDir, {
|
|
12629
|
+
event: "model.request",
|
|
12630
|
+
status: "started",
|
|
12631
|
+
sessionId: observability.sessionId,
|
|
12632
|
+
identityKind: observability.identityKind,
|
|
12633
|
+
identityName: observability.identityName,
|
|
12634
|
+
model: request.model,
|
|
12635
|
+
details: {
|
|
12636
|
+
provider: request.provider,
|
|
12637
|
+
configuredModel: observability.configuredModel,
|
|
12638
|
+
requestModel: request.model,
|
|
12639
|
+
wireApi: adapter.wireApi,
|
|
12640
|
+
baseUrl: resolvedBaseUrl
|
|
12641
|
+
}
|
|
12642
|
+
});
|
|
12643
|
+
}
|
|
12644
|
+
try {
|
|
12645
|
+
const response = await withApiRetries(
|
|
12646
|
+
() => invokeWithProviderClients(client, async (providerClient, baseUrl) => {
|
|
12647
|
+
resolvedBaseUrl = baseUrl;
|
|
12648
|
+
return adapter.fetchStreaming(providerClient, {
|
|
12649
|
+
provider: request.provider,
|
|
12650
|
+
model: request.model,
|
|
12651
|
+
messages,
|
|
12652
|
+
tools,
|
|
12653
|
+
callbacks,
|
|
12654
|
+
forceReasoning,
|
|
12655
|
+
thinking: request.thinking,
|
|
12656
|
+
reasoningEffort: request.reasoningEffort,
|
|
12657
|
+
maxOutputTokens: request.maxOutputTokens,
|
|
12658
|
+
sessionId: request.sessionId,
|
|
12659
|
+
projectRoot: request.projectRoot,
|
|
12660
|
+
abortSignal,
|
|
12661
|
+
onRequestMetric: forwardMetric
|
|
12662
|
+
});
|
|
12663
|
+
}),
|
|
12664
|
+
abortSignal
|
|
12665
|
+
);
|
|
12666
|
+
if (observability) {
|
|
12667
|
+
await recordObservabilityEvent(observability.rootDir, {
|
|
12668
|
+
event: "model.request",
|
|
12669
|
+
status: "completed",
|
|
12670
|
+
sessionId: observability.sessionId,
|
|
12671
|
+
identityKind: observability.identityKind,
|
|
12672
|
+
identityName: observability.identityName,
|
|
12673
|
+
model: request.model,
|
|
12674
|
+
durationMs: Date.now() - startedAt,
|
|
12675
|
+
details: {
|
|
12676
|
+
provider: request.provider,
|
|
12677
|
+
configuredModel: observability.configuredModel,
|
|
12678
|
+
requestModel: request.model,
|
|
12679
|
+
wireApi: adapter.wireApi,
|
|
12680
|
+
baseUrl: resolvedBaseUrl,
|
|
12681
|
+
usage: latestMetric?.usage,
|
|
12682
|
+
usageAvailable: hasProviderUsageSnapshot(latestMetric?.usage)
|
|
12683
|
+
}
|
|
12684
|
+
});
|
|
12685
|
+
}
|
|
12686
|
+
return response;
|
|
12687
|
+
} catch (error) {
|
|
12688
|
+
if (isAbortError(error)) {
|
|
12689
|
+
throw error;
|
|
12690
|
+
}
|
|
12691
|
+
try {
|
|
12692
|
+
const response = await withApiRetries(
|
|
12693
|
+
() => invokeWithProviderClients(client, async (providerClient, baseUrl) => {
|
|
12694
|
+
resolvedBaseUrl = baseUrl;
|
|
12695
|
+
return adapter.fetchNonStreaming(providerClient, {
|
|
12696
|
+
provider: request.provider,
|
|
12697
|
+
model: request.model,
|
|
12698
|
+
messages,
|
|
12699
|
+
tools,
|
|
12700
|
+
callbacks,
|
|
12701
|
+
forceReasoning,
|
|
12702
|
+
thinking: request.thinking,
|
|
12703
|
+
reasoningEffort: request.reasoningEffort,
|
|
12704
|
+
maxOutputTokens: request.maxOutputTokens,
|
|
12705
|
+
sessionId: request.sessionId,
|
|
12706
|
+
projectRoot: request.projectRoot,
|
|
12707
|
+
abortSignal,
|
|
12708
|
+
onRequestMetric: forwardMetric
|
|
12709
|
+
});
|
|
12710
|
+
}),
|
|
12711
|
+
abortSignal
|
|
12712
|
+
);
|
|
12713
|
+
if (observability) {
|
|
12714
|
+
await recordObservabilityEvent(observability.rootDir, {
|
|
12715
|
+
event: "model.request",
|
|
12716
|
+
status: "completed",
|
|
12717
|
+
sessionId: observability.sessionId,
|
|
12718
|
+
identityKind: observability.identityKind,
|
|
12719
|
+
identityName: observability.identityName,
|
|
12720
|
+
model: request.model,
|
|
12721
|
+
durationMs: Date.now() - startedAt,
|
|
12722
|
+
details: {
|
|
12723
|
+
provider: request.provider,
|
|
12724
|
+
configuredModel: observability.configuredModel,
|
|
12725
|
+
requestModel: request.model,
|
|
12726
|
+
wireApi: adapter.wireApi,
|
|
12727
|
+
baseUrl: resolvedBaseUrl,
|
|
12728
|
+
usage: latestMetric?.usage,
|
|
12729
|
+
usageAvailable: hasProviderUsageSnapshot(latestMetric?.usage)
|
|
12730
|
+
}
|
|
12731
|
+
});
|
|
12732
|
+
}
|
|
12733
|
+
return response;
|
|
12734
|
+
} catch (fallbackError) {
|
|
12735
|
+
if (!isAbortError(fallbackError) && observability) {
|
|
12736
|
+
await recordObservabilityEvent(observability.rootDir, {
|
|
12737
|
+
event: "model.request",
|
|
12738
|
+
status: "failed",
|
|
12739
|
+
sessionId: observability.sessionId,
|
|
12740
|
+
identityKind: observability.identityKind,
|
|
12741
|
+
identityName: observability.identityName,
|
|
12742
|
+
model: request.model,
|
|
12743
|
+
durationMs: Date.now() - startedAt,
|
|
12744
|
+
error: fallbackError,
|
|
12745
|
+
details: {
|
|
12746
|
+
provider: request.provider,
|
|
12747
|
+
configuredModel: observability.configuredModel,
|
|
12748
|
+
requestModel: request.model,
|
|
12749
|
+
wireApi: adapter.wireApi,
|
|
12750
|
+
baseUrl: resolvedBaseUrl,
|
|
12751
|
+
usage: latestMetric?.usage,
|
|
12752
|
+
usageAvailable: hasProviderUsageSnapshot(latestMetric?.usage)
|
|
12753
|
+
}
|
|
12754
|
+
});
|
|
12755
|
+
}
|
|
12756
|
+
throw fallbackError;
|
|
12757
|
+
}
|
|
12758
|
+
}
|
|
12759
|
+
}
|
|
12760
|
+
function selectProviderWireAdapter(wireApi) {
|
|
12761
|
+
if (wireApi === "responses") {
|
|
12762
|
+
return responsesAdapter;
|
|
12763
|
+
}
|
|
12764
|
+
return chatCompletionsAdapter;
|
|
12765
|
+
}
|
|
12766
|
+
async function invokeWithProviderClients(client, operation) {
|
|
12767
|
+
if (!isProviderClientPool(client)) {
|
|
12768
|
+
return operation(client, void 0);
|
|
12769
|
+
}
|
|
12770
|
+
let lastError;
|
|
12771
|
+
const candidates = client.candidates();
|
|
12772
|
+
for (let index = 0; index < candidates.length; index += 1) {
|
|
12773
|
+
const candidate = candidates[index];
|
|
12774
|
+
try {
|
|
12775
|
+
const result = await operation(candidate.client, candidate.baseUrl);
|
|
12776
|
+
client.markHealthy(candidate.baseUrl);
|
|
12777
|
+
return result;
|
|
12778
|
+
} catch (error) {
|
|
12779
|
+
lastError = error;
|
|
12780
|
+
if (isAbortError(error)) {
|
|
12781
|
+
throw error;
|
|
12782
|
+
}
|
|
12783
|
+
const hasMoreCandidates = index < candidates.length - 1;
|
|
12784
|
+
if (!hasMoreCandidates || !canRetryWithAlternateBaseUrl(error)) {
|
|
12785
|
+
throw error;
|
|
12786
|
+
}
|
|
12787
|
+
}
|
|
12788
|
+
}
|
|
12789
|
+
throw lastError;
|
|
12790
|
+
}
|
|
12791
|
+
function canRetryWithAlternateBaseUrl(error) {
|
|
12792
|
+
const status = error.status;
|
|
12793
|
+
const message = String(error.message ?? error).toLowerCase();
|
|
12794
|
+
return status === 404 || status === 405 || message.includes("404") || message.includes("not found");
|
|
12795
|
+
}
|
|
12796
|
+
var init_request = __esm({
|
|
12797
|
+
"src/provider/request.ts"() {
|
|
12798
|
+
"use strict";
|
|
12799
|
+
init_apiRetry();
|
|
12800
|
+
init_usageNormalizer();
|
|
12801
|
+
init_abort();
|
|
12802
|
+
init_writer();
|
|
12803
|
+
init_capabilities();
|
|
12804
|
+
init_chatCompletionsAdapter();
|
|
12805
|
+
init_responsesAdapter();
|
|
12806
|
+
init_client();
|
|
12807
|
+
}
|
|
12808
|
+
});
|
|
12809
|
+
|
|
12810
|
+
// src/provider/index.ts
|
|
12811
|
+
var init_provider = __esm({
|
|
12812
|
+
"src/provider/index.ts"() {
|
|
12813
|
+
"use strict";
|
|
12814
|
+
init_capabilities();
|
|
12815
|
+
init_catalog();
|
|
12816
|
+
init_request();
|
|
12817
|
+
}
|
|
12818
|
+
});
|
|
12819
|
+
|
|
12867
12820
|
// src/provider/retryPolicy.ts
|
|
12868
12821
|
function isRecoverableTurnError(error) {
|
|
12869
12822
|
if (isRetryableApiError(error)) {
|
|
@@ -13167,6 +13120,7 @@ async function updateSessionMemoryAfterTurn(input) {
|
|
|
13167
13120
|
identityName: input.identity.name,
|
|
13168
13121
|
model: input.requestModel
|
|
13169
13122
|
});
|
|
13123
|
+
input.options.callbacks?.onStatus?.("\u603B\u7ED3\u4E2D");
|
|
13170
13124
|
try {
|
|
13171
13125
|
const memoryResponse = input.options.fetchSessionMemoryResponse ? await input.options.fetchSessionMemoryResponse(modelRequest) : await fetchAssistantResponse(
|
|
13172
13126
|
input.client,
|
|
@@ -13217,6 +13171,8 @@ async function updateSessionMemoryAfterTurn(input) {
|
|
|
13217
13171
|
error
|
|
13218
13172
|
});
|
|
13219
13173
|
return input.session;
|
|
13174
|
+
} finally {
|
|
13175
|
+
input.options.callbacks?.onStatus?.("");
|
|
13220
13176
|
}
|
|
13221
13177
|
}
|
|
13222
13178
|
async function updateSessionTitleAfterTurn(input) {
|
|
@@ -13264,6 +13220,7 @@ async function updateSessionTitleAfterTurn(input) {
|
|
|
13264
13220
|
identityName: input.identity.name,
|
|
13265
13221
|
model: input.requestModel
|
|
13266
13222
|
});
|
|
13223
|
+
input.options.callbacks?.onStatus?.("\u6807\u9898\u751F\u6210\u4E2D");
|
|
13267
13224
|
try {
|
|
13268
13225
|
const titleResponse = input.options.fetchSessionTitleResponse ? await input.options.fetchSessionTitleResponse(modelRequest) : await fetchAssistantResponse(
|
|
13269
13226
|
input.client,
|
|
@@ -13315,6 +13272,8 @@ async function updateSessionTitleAfterTurn(input) {
|
|
|
13315
13272
|
error
|
|
13316
13273
|
});
|
|
13317
13274
|
return input.session;
|
|
13275
|
+
} finally {
|
|
13276
|
+
input.options.callbacks?.onStatus?.("");
|
|
13318
13277
|
}
|
|
13319
13278
|
}
|
|
13320
13279
|
var init_lifecycle = __esm({
|
|
@@ -14033,7 +13992,7 @@ var init_bash = __esm({
|
|
|
14033
13992
|
const status = result.aborted ? "aborted" : result.stalled ? "stalled" : result.timedOut ? "timed_out" : result.exitCode === 0 ? "completed" : "failed";
|
|
14034
13993
|
const outputGovernance = governToolOutput({
|
|
14035
13994
|
toolName: "bash",
|
|
14036
|
-
command,
|
|
13995
|
+
command: result.command,
|
|
14037
13996
|
status,
|
|
14038
13997
|
exitCode: result.exitCode,
|
|
14039
13998
|
durationMs: result.durationMs,
|
|
@@ -14061,7 +14020,7 @@ var init_bash = __esm({
|
|
|
14061
14020
|
return okResult(
|
|
14062
14021
|
JSON.stringify(
|
|
14063
14022
|
{
|
|
14064
|
-
command,
|
|
14023
|
+
command: result.command,
|
|
14065
14024
|
cwd: resolvedCwd,
|
|
14066
14025
|
exitCode: result.exitCode,
|
|
14067
14026
|
status,
|
|
@@ -226409,6 +226368,63 @@ var init_toolBatch = __esm({
|
|
|
226409
226368
|
}
|
|
226410
226369
|
});
|
|
226411
226370
|
|
|
226371
|
+
// src/session/events.ts
|
|
226372
|
+
var events_exports = {};
|
|
226373
|
+
__export(events_exports, {
|
|
226374
|
+
SessionEventStore: () => SessionEventStore
|
|
226375
|
+
});
|
|
226376
|
+
function createEventId() {
|
|
226377
|
+
return `${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:.TZ]/g, "").slice(0, 14)}-${Math.random().toString(16).slice(2, 10)}`;
|
|
226378
|
+
}
|
|
226379
|
+
function sanitizeSessionId2(sessionId) {
|
|
226380
|
+
return sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
226381
|
+
}
|
|
226382
|
+
var import_promises30, import_node_path42, SessionEventStore;
|
|
226383
|
+
var init_events = __esm({
|
|
226384
|
+
"src/session/events.ts"() {
|
|
226385
|
+
"use strict";
|
|
226386
|
+
import_promises30 = __toESM(require("fs/promises"));
|
|
226387
|
+
import_node_path42 = __toESM(require("path"));
|
|
226388
|
+
SessionEventStore = class {
|
|
226389
|
+
constructor(eventsDir) {
|
|
226390
|
+
this.eventsDir = eventsDir;
|
|
226391
|
+
}
|
|
226392
|
+
async append(event) {
|
|
226393
|
+
const record = {
|
|
226394
|
+
id: createEventId(),
|
|
226395
|
+
createdAt: event.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
226396
|
+
type: event.type,
|
|
226397
|
+
sessionId: event.sessionId,
|
|
226398
|
+
cwd: event.cwd,
|
|
226399
|
+
host: event.host,
|
|
226400
|
+
message: event.message,
|
|
226401
|
+
details: event.details
|
|
226402
|
+
};
|
|
226403
|
+
await import_promises30.default.mkdir(this.eventsDir, { recursive: true });
|
|
226404
|
+
await import_promises30.default.appendFile(this.getSessionEventPath(event.sessionId), `${JSON.stringify(record)}
|
|
226405
|
+
`, "utf8");
|
|
226406
|
+
return record;
|
|
226407
|
+
}
|
|
226408
|
+
async list(sessionId, limit = 100) {
|
|
226409
|
+
const filePath = this.getSessionEventPath(sessionId);
|
|
226410
|
+
let raw = "";
|
|
226411
|
+
try {
|
|
226412
|
+
raw = await import_promises30.default.readFile(filePath, "utf8");
|
|
226413
|
+
} catch (error) {
|
|
226414
|
+
if (error.code === "ENOENT") {
|
|
226415
|
+
return [];
|
|
226416
|
+
}
|
|
226417
|
+
throw error;
|
|
226418
|
+
}
|
|
226419
|
+
return raw.split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line)).slice(-limit);
|
|
226420
|
+
}
|
|
226421
|
+
getSessionEventPath(sessionId) {
|
|
226422
|
+
return import_node_path42.default.join(this.eventsDir, `${sanitizeSessionId2(sessionId)}.jsonl`);
|
|
226423
|
+
}
|
|
226424
|
+
};
|
|
226425
|
+
}
|
|
226426
|
+
});
|
|
226427
|
+
|
|
226412
226428
|
// src/agent/turn/toolFailure.ts
|
|
226413
226429
|
function readToolFailureError(output) {
|
|
226414
226430
|
try {
|
|
@@ -226449,9 +226465,16 @@ async function processToolCallBatch(input) {
|
|
|
226449
226465
|
const batchToolMessages = [];
|
|
226450
226466
|
const batchModelOutputs = [];
|
|
226451
226467
|
const batchChangedPaths = /* @__PURE__ */ new Set();
|
|
226468
|
+
const sessionEvents = new SessionEventStore(options.config.paths.eventsDir);
|
|
226452
226469
|
const leadWaitExecutionsBefore = identity.kind === "lead" ? listLeadWaitExecutions(projectContext.stateRootDir) : [];
|
|
226453
226470
|
for (const toolCall of response.toolCalls) {
|
|
226454
226471
|
throwIfAborted(options.abortSignal, "Turn aborted by user.");
|
|
226472
|
+
await sessionEvents.append({
|
|
226473
|
+
type: "tool.started",
|
|
226474
|
+
sessionId: session.id,
|
|
226475
|
+
cwd: options.cwd,
|
|
226476
|
+
details: buildToolStartedEventDetails(toolCall, identity)
|
|
226477
|
+
});
|
|
226455
226478
|
options.callbacks?.onToolCall?.(toolCall.function.name, toolCall.function.arguments);
|
|
226456
226479
|
await recordObservabilityEvent(projectContext.stateRootDir, {
|
|
226457
226480
|
event: "tool.execution",
|
|
@@ -226485,6 +226508,7 @@ async function processToolCallBatch(input) {
|
|
|
226485
226508
|
} else if (metadata?.sessionDiff) {
|
|
226486
226509
|
session = await options.sessionStore.save(noteSessionDiff(session, metadata.sessionDiff));
|
|
226487
226510
|
}
|
|
226511
|
+
const failureError = result.ok ? void 0 : readToolFailureError(result.output);
|
|
226488
226512
|
await recordObservabilityEvent(projectContext.stateRootDir, {
|
|
226489
226513
|
event: "tool.execution",
|
|
226490
226514
|
status: result.ok ? "completed" : "failed",
|
|
@@ -226493,11 +226517,23 @@ async function processToolCallBatch(input) {
|
|
|
226493
226517
|
identityName: identity.name,
|
|
226494
226518
|
toolName: toolCall.function.name,
|
|
226495
226519
|
durationMs,
|
|
226496
|
-
error:
|
|
226520
|
+
error: failureError,
|
|
226497
226521
|
details: {
|
|
226498
226522
|
changedPathCount: metadata?.changedPaths?.length ?? 0
|
|
226499
226523
|
}
|
|
226500
226524
|
});
|
|
226525
|
+
await sessionEvents.append({
|
|
226526
|
+
type: result.ok ? "tool.completed" : "tool.failed",
|
|
226527
|
+
sessionId: session.id,
|
|
226528
|
+
cwd: options.cwd,
|
|
226529
|
+
details: buildToolFinishedEventDetails({
|
|
226530
|
+
toolCall,
|
|
226531
|
+
identity,
|
|
226532
|
+
durationMs,
|
|
226533
|
+
changedPathCount: metadata?.changedPaths?.length ?? 0,
|
|
226534
|
+
error: failureError ? formatToolFailureError(failureError) : void 0
|
|
226535
|
+
})
|
|
226536
|
+
});
|
|
226501
226537
|
if (metadata?.outputGovernance) {
|
|
226502
226538
|
await recordObservabilityEvent(projectContext.stateRootDir, {
|
|
226503
226539
|
event: "tool.output",
|
|
@@ -226591,6 +226627,33 @@ async function processToolCallBatch(input) {
|
|
|
226591
226627
|
}
|
|
226592
226628
|
};
|
|
226593
226629
|
}
|
|
226630
|
+
function buildToolStartedEventDetails(toolCall, identity) {
|
|
226631
|
+
return {
|
|
226632
|
+
toolName: toolCall.function.name,
|
|
226633
|
+
toolCallId: toolCall.id,
|
|
226634
|
+
identityKind: identity.kind,
|
|
226635
|
+
identityName: identity.name,
|
|
226636
|
+
argumentsPreview: previewToolArguments(toolCall.function.arguments)
|
|
226637
|
+
};
|
|
226638
|
+
}
|
|
226639
|
+
function buildToolFinishedEventDetails(input) {
|
|
226640
|
+
return {
|
|
226641
|
+
toolName: input.toolCall.function.name,
|
|
226642
|
+
toolCallId: input.toolCall.id,
|
|
226643
|
+
identityKind: input.identity.kind,
|
|
226644
|
+
identityName: input.identity.name,
|
|
226645
|
+
durationMs: input.durationMs,
|
|
226646
|
+
changedPathCount: input.changedPathCount,
|
|
226647
|
+
error: input.error
|
|
226648
|
+
};
|
|
226649
|
+
}
|
|
226650
|
+
function previewToolArguments(rawArgs) {
|
|
226651
|
+
const normalized = rawArgs.replace(/\s+/g, " ").trim();
|
|
226652
|
+
return normalized.length > 240 ? `${normalized.slice(0, 237)}...` : normalized;
|
|
226653
|
+
}
|
|
226654
|
+
function formatToolFailureError(error) {
|
|
226655
|
+
return error.code ? `${error.code}: ${error.message}` : error.message;
|
|
226656
|
+
}
|
|
226594
226657
|
var init_toolBatchLifecycle = __esm({
|
|
226595
226658
|
"src/agent/turn/toolBatchLifecycle.ts"() {
|
|
226596
226659
|
"use strict";
|
|
@@ -226603,6 +226666,7 @@ var init_toolBatchLifecycle = __esm({
|
|
|
226603
226666
|
init_persistence();
|
|
226604
226667
|
init_toolBatch();
|
|
226605
226668
|
init_writer();
|
|
226669
|
+
init_events();
|
|
226606
226670
|
init_abort();
|
|
226607
226671
|
init_toolFailure();
|
|
226608
226672
|
}
|
|
@@ -226718,13 +226782,13 @@ function createChangeId() {
|
|
|
226718
226782
|
const random = import_node_crypto4.default.randomUUID().slice(0, 8);
|
|
226719
226783
|
return `${date}-${random}`;
|
|
226720
226784
|
}
|
|
226721
|
-
var import_node_crypto4,
|
|
226785
|
+
var import_node_crypto4, import_promises31, import_node_path43, ChangeStore;
|
|
226722
226786
|
var init_store5 = __esm({
|
|
226723
226787
|
"src/agent/changes/store.ts"() {
|
|
226724
226788
|
"use strict";
|
|
226725
226789
|
import_node_crypto4 = __toESM(require("crypto"));
|
|
226726
|
-
|
|
226727
|
-
|
|
226790
|
+
import_promises31 = __toESM(require("fs/promises"));
|
|
226791
|
+
import_node_path43 = __toESM(require("path"));
|
|
226728
226792
|
ChangeStore = class {
|
|
226729
226793
|
constructor(changesDir) {
|
|
226730
226794
|
this.changesDir = changesDir;
|
|
@@ -226732,8 +226796,8 @@ var init_store5 = __esm({
|
|
|
226732
226796
|
async record(input) {
|
|
226733
226797
|
const id = createChangeId();
|
|
226734
226798
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
226735
|
-
const blobDir =
|
|
226736
|
-
await
|
|
226799
|
+
const blobDir = import_node_path43.default.join(this.changesDir, id);
|
|
226800
|
+
await import_promises31.default.mkdir(blobDir, { recursive: true });
|
|
226737
226801
|
const operations = await Promise.all(
|
|
226738
226802
|
input.operations.map(async (operation, index) => {
|
|
226739
226803
|
const beforeSnapshotPath = await this.writeSnapshot(
|
|
@@ -226773,21 +226837,21 @@ var init_store5 = __esm({
|
|
|
226773
226837
|
preview: input.preview,
|
|
226774
226838
|
operations
|
|
226775
226839
|
};
|
|
226776
|
-
await
|
|
226777
|
-
await
|
|
226840
|
+
await import_promises31.default.mkdir(this.changesDir, { recursive: true });
|
|
226841
|
+
await import_promises31.default.writeFile(this.getMetadataPath(id), `${JSON.stringify(record, null, 2)}
|
|
226778
226842
|
`, "utf8");
|
|
226779
226843
|
return record;
|
|
226780
226844
|
}
|
|
226781
226845
|
async list(limit = 20) {
|
|
226782
|
-
await
|
|
226783
|
-
const entries = await
|
|
226846
|
+
await import_promises31.default.mkdir(this.changesDir, { recursive: true });
|
|
226847
|
+
const entries = await import_promises31.default.readdir(this.changesDir, { withFileTypes: true });
|
|
226784
226848
|
const changes = await Promise.all(
|
|
226785
|
-
entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => this.load(
|
|
226849
|
+
entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => this.load(import_node_path43.default.basename(entry.name, ".json")))
|
|
226786
226850
|
);
|
|
226787
226851
|
return changes.sort((left, right) => right.createdAt.localeCompare(left.createdAt)).slice(0, limit);
|
|
226788
226852
|
}
|
|
226789
226853
|
async load(id) {
|
|
226790
|
-
const raw = await
|
|
226854
|
+
const raw = await import_promises31.default.readFile(this.getMetadataPath(id), "utf8");
|
|
226791
226855
|
return JSON.parse(raw);
|
|
226792
226856
|
}
|
|
226793
226857
|
async loadLatestUndoable() {
|
|
@@ -226811,17 +226875,17 @@ var init_store5 = __esm({
|
|
|
226811
226875
|
restoredPaths.push(operation.path);
|
|
226812
226876
|
if (operation.beforeSnapshotPath) {
|
|
226813
226877
|
const buffer = await this.readSnapshot(operation.beforeSnapshotPath);
|
|
226814
|
-
await
|
|
226815
|
-
await
|
|
226878
|
+
await import_promises31.default.mkdir(import_node_path43.default.dirname(operation.path), { recursive: true });
|
|
226879
|
+
await import_promises31.default.writeFile(operation.path, buffer);
|
|
226816
226880
|
continue;
|
|
226817
226881
|
}
|
|
226818
|
-
await
|
|
226882
|
+
await import_promises31.default.rm(operation.path, { force: true });
|
|
226819
226883
|
}
|
|
226820
226884
|
const updated = {
|
|
226821
226885
|
...record,
|
|
226822
226886
|
undoneAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
226823
226887
|
};
|
|
226824
|
-
await
|
|
226888
|
+
await import_promises31.default.writeFile(this.getMetadataPath(updated.id), `${JSON.stringify(updated, null, 2)}
|
|
226825
226889
|
`, "utf8");
|
|
226826
226890
|
return {
|
|
226827
226891
|
record: updated,
|
|
@@ -226829,19 +226893,19 @@ var init_store5 = __esm({
|
|
|
226829
226893
|
};
|
|
226830
226894
|
}
|
|
226831
226895
|
getMetadataPath(id) {
|
|
226832
|
-
return
|
|
226896
|
+
return import_node_path43.default.join(this.changesDir, `${id}.json`);
|
|
226833
226897
|
}
|
|
226834
226898
|
async writeSnapshot(blobDir, label, buffer) {
|
|
226835
226899
|
if (!buffer) {
|
|
226836
226900
|
return void 0;
|
|
226837
226901
|
}
|
|
226838
226902
|
const fileName = `${label}.bin`;
|
|
226839
|
-
const absolutePath =
|
|
226840
|
-
await
|
|
226841
|
-
return
|
|
226903
|
+
const absolutePath = import_node_path43.default.join(blobDir, fileName);
|
|
226904
|
+
await import_promises31.default.writeFile(absolutePath, buffer);
|
|
226905
|
+
return import_node_path43.default.relative(this.changesDir, absolutePath);
|
|
226842
226906
|
}
|
|
226843
226907
|
async readSnapshot(relativePath) {
|
|
226844
|
-
return
|
|
226908
|
+
return import_promises31.default.readFile(import_node_path43.default.join(this.changesDir, relativePath));
|
|
226845
226909
|
}
|
|
226846
226910
|
};
|
|
226847
226911
|
}
|
|
@@ -227233,14 +227297,14 @@ async function recordHostTurnFinished(rootDir, input) {
|
|
|
227233
227297
|
});
|
|
227234
227298
|
}
|
|
227235
227299
|
function resolveHostStateRoot(stateDir, fallbackCwd) {
|
|
227236
|
-
const kittyDir =
|
|
227237
|
-
return
|
|
227300
|
+
const kittyDir = import_node_path44.default.dirname(stateDir);
|
|
227301
|
+
return import_node_path44.default.basename(kittyDir).toLowerCase() === PROJECT_STATE_DIR_NAME ? import_node_path44.default.dirname(kittyDir) : fallbackCwd;
|
|
227238
227302
|
}
|
|
227239
|
-
var
|
|
227303
|
+
var import_node_path44, QueuedHostMessageRecorder;
|
|
227240
227304
|
var init_hostEvents = __esm({
|
|
227241
227305
|
"src/observability/hostEvents.ts"() {
|
|
227242
227306
|
"use strict";
|
|
227243
|
-
|
|
227307
|
+
import_node_path44 = __toESM(require("path"));
|
|
227244
227308
|
init_writer();
|
|
227245
227309
|
init_statePaths();
|
|
227246
227310
|
QueuedHostMessageRecorder = class {
|
|
@@ -227270,63 +227334,6 @@ var init_hostEvents = __esm({
|
|
|
227270
227334
|
}
|
|
227271
227335
|
});
|
|
227272
227336
|
|
|
227273
|
-
// src/session/events.ts
|
|
227274
|
-
var events_exports = {};
|
|
227275
|
-
__export(events_exports, {
|
|
227276
|
-
SessionEventStore: () => SessionEventStore
|
|
227277
|
-
});
|
|
227278
|
-
function createEventId() {
|
|
227279
|
-
return `${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:.TZ]/g, "").slice(0, 14)}-${Math.random().toString(16).slice(2, 10)}`;
|
|
227280
|
-
}
|
|
227281
|
-
function sanitizeSessionId2(sessionId) {
|
|
227282
|
-
return sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
227283
|
-
}
|
|
227284
|
-
var import_promises31, import_node_path44, SessionEventStore;
|
|
227285
|
-
var init_events = __esm({
|
|
227286
|
-
"src/session/events.ts"() {
|
|
227287
|
-
"use strict";
|
|
227288
|
-
import_promises31 = __toESM(require("fs/promises"));
|
|
227289
|
-
import_node_path44 = __toESM(require("path"));
|
|
227290
|
-
SessionEventStore = class {
|
|
227291
|
-
constructor(eventsDir) {
|
|
227292
|
-
this.eventsDir = eventsDir;
|
|
227293
|
-
}
|
|
227294
|
-
async append(event) {
|
|
227295
|
-
const record = {
|
|
227296
|
-
id: createEventId(),
|
|
227297
|
-
createdAt: event.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
227298
|
-
type: event.type,
|
|
227299
|
-
sessionId: event.sessionId,
|
|
227300
|
-
cwd: event.cwd,
|
|
227301
|
-
host: event.host,
|
|
227302
|
-
message: event.message,
|
|
227303
|
-
details: event.details
|
|
227304
|
-
};
|
|
227305
|
-
await import_promises31.default.mkdir(this.eventsDir, { recursive: true });
|
|
227306
|
-
await import_promises31.default.appendFile(this.getSessionEventPath(event.sessionId), `${JSON.stringify(record)}
|
|
227307
|
-
`, "utf8");
|
|
227308
|
-
return record;
|
|
227309
|
-
}
|
|
227310
|
-
async list(sessionId, limit = 100) {
|
|
227311
|
-
const filePath = this.getSessionEventPath(sessionId);
|
|
227312
|
-
let raw = "";
|
|
227313
|
-
try {
|
|
227314
|
-
raw = await import_promises31.default.readFile(filePath, "utf8");
|
|
227315
|
-
} catch (error) {
|
|
227316
|
-
if (error.code === "ENOENT") {
|
|
227317
|
-
return [];
|
|
227318
|
-
}
|
|
227319
|
-
throw error;
|
|
227320
|
-
}
|
|
227321
|
-
return raw.split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line)).slice(-limit);
|
|
227322
|
-
}
|
|
227323
|
-
getSessionEventPath(sessionId) {
|
|
227324
|
-
return import_node_path44.default.join(this.eventsDir, `${sanitizeSessionId2(sessionId)}.jsonl`);
|
|
227325
|
-
}
|
|
227326
|
-
};
|
|
227327
|
-
}
|
|
227328
|
-
});
|
|
227329
|
-
|
|
227330
227337
|
// src/host/toolRegistry.ts
|
|
227331
227338
|
async function createHostToolRegistry(config, options = {}) {
|
|
227332
227339
|
const extraTools = options.extraTools ?? [];
|
|
@@ -231040,7 +231047,7 @@ function createCliOutputPort() {
|
|
|
231040
231047
|
}
|
|
231041
231048
|
};
|
|
231042
231049
|
}
|
|
231043
|
-
var
|
|
231050
|
+
var init_output2 = __esm({
|
|
231044
231051
|
"src/shell/cli/output.ts"() {
|
|
231045
231052
|
"use strict";
|
|
231046
231053
|
init_console();
|
|
@@ -231387,7 +231394,7 @@ function createCliInteractionShell() {
|
|
|
231387
231394
|
var init_shell = __esm({
|
|
231388
231395
|
"src/shell/cli/shell.ts"() {
|
|
231389
231396
|
"use strict";
|
|
231390
|
-
|
|
231397
|
+
init_output2();
|
|
231391
231398
|
init_readlineInput();
|
|
231392
231399
|
init_turnDisplay();
|
|
231393
231400
|
}
|
|
@@ -231641,6 +231648,9 @@ function formatSessionEventsForCli(result) {
|
|
|
231641
231648
|
return result.events.map(formatSessionEventForCli).join("\n");
|
|
231642
231649
|
}
|
|
231643
231650
|
function formatSessionEventForCli(event) {
|
|
231651
|
+
if (isToolEvent(event)) {
|
|
231652
|
+
return formatToolEventForCli(event);
|
|
231653
|
+
}
|
|
231644
231654
|
const parts = [
|
|
231645
231655
|
event.createdAt,
|
|
231646
231656
|
event.type,
|
|
@@ -231650,10 +231660,39 @@ function formatSessionEventForCli(event) {
|
|
|
231650
231660
|
];
|
|
231651
231661
|
return parts.filter(Boolean).join(" ");
|
|
231652
231662
|
}
|
|
231663
|
+
function formatToolEventForCli(event) {
|
|
231664
|
+
const details = event.details ?? {};
|
|
231665
|
+
const toolName = readString7(details.toolName);
|
|
231666
|
+
const toolCallId = readString7(details.toolCallId);
|
|
231667
|
+
const durationMs = readNumber3(details.durationMs);
|
|
231668
|
+
const changedPathCount = readNumber3(details.changedPathCount);
|
|
231669
|
+
const error = readString7(details.error);
|
|
231670
|
+
const parts = [
|
|
231671
|
+
event.createdAt,
|
|
231672
|
+
event.type,
|
|
231673
|
+
toolName ? `tool=${toolName}` : void 0,
|
|
231674
|
+
toolCallId ? `call=${toolCallId}` : void 0,
|
|
231675
|
+
durationMs === void 0 ? void 0 : `duration=${durationMs}ms`,
|
|
231676
|
+
changedPathCount === void 0 ? void 0 : `changed=${changedPathCount}`,
|
|
231677
|
+
error ? `error=${formatInline(error)}` : void 0,
|
|
231678
|
+
event.host ? `host=${event.host}` : void 0,
|
|
231679
|
+
event.message ? `message=${formatInline(event.message)}` : void 0
|
|
231680
|
+
];
|
|
231681
|
+
return parts.filter(Boolean).join(" ");
|
|
231682
|
+
}
|
|
231683
|
+
function isToolEvent(event) {
|
|
231684
|
+
return event.type === "tool.started" || event.type === "tool.completed" || event.type === "tool.failed";
|
|
231685
|
+
}
|
|
231653
231686
|
function formatInline(value) {
|
|
231654
231687
|
const normalized = value.replace(/\s+/g, " ").trim();
|
|
231655
231688
|
return normalized.length > 120 ? `${normalized.slice(0, 117)}...` : normalized;
|
|
231656
231689
|
}
|
|
231690
|
+
function readString7(value) {
|
|
231691
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
231692
|
+
}
|
|
231693
|
+
function readNumber3(value) {
|
|
231694
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
231695
|
+
}
|
|
231657
231696
|
var init_events3 = __esm({
|
|
231658
231697
|
"src/cli/commands/events.ts"() {
|
|
231659
231698
|
"use strict";
|