@jun133/kitty 0.0.12 → 0.0.14
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/dist/{App-V6SLDWQH.mjs → App-CBTIS4IK.mjs} +30 -18
- package/dist/{chunk-TISOA5U6.mjs → chunk-KKGULDIF.mjs} +55 -7
- package/dist/{chunk-MV5BYUNW.mjs → chunk-KROQCOWD.mjs} +188 -513
- package/dist/{chunk-4HIVDFN5.mjs → chunk-NBKU7KA4.mjs} +1 -12
- package/dist/{chunk-TOBF3KV3.mjs → chunk-VR3L2EPP.mjs} +1 -1
- package/dist/cli.js +235 -526
- package/dist/cli.js.map +1 -1
- package/dist/{interactive-WYSTB4UQ.mjs → interactive-KRRDJYBR.mjs} +3 -3
- package/dist/{oneShot-INJ27LNB.mjs → oneShot-PHU3JOPP.mjs} +2 -2
- package/dist/tui.mjs +93 -94
- package/package.json +1 -1
|
@@ -1034,6 +1034,7 @@ function buildToolBlock() {
|
|
|
1034
1034
|
function buildCommunicationBlock() {
|
|
1035
1035
|
return [
|
|
1036
1036
|
"Always reply in Simplified Chinese.",
|
|
1037
|
+
"No Markdown in user-facing conversational replies; prefer plain text whenever possible.",
|
|
1037
1038
|
"Provide concise progress updates during multi-step work.",
|
|
1038
1039
|
"Make every sentence carry decision, execution, evidence, or understanding.",
|
|
1039
1040
|
"Claim changed files, passed commands, and successful tools only when tool evidence supports them.",
|
|
@@ -3557,14 +3558,21 @@ async function launchCommand(command, cwd, timeoutMs, abortSignal) {
|
|
|
3557
3558
|
function encodePowerShellCommand(command) {
|
|
3558
3559
|
const wrapped = [
|
|
3559
3560
|
"$ProgressPreference = 'SilentlyContinue'",
|
|
3561
|
+
"$ErrorActionPreference = 'Stop'",
|
|
3560
3562
|
"[Console]::InputEncoding = [System.Text.Encoding]::UTF8",
|
|
3561
3563
|
"[Console]::OutputEncoding = [System.Text.Encoding]::UTF8",
|
|
3562
3564
|
"$OutputEncoding = [System.Text.Encoding]::UTF8",
|
|
3563
3565
|
"try { chcp 65001 > $null } catch { }",
|
|
3566
|
+
"$code = 0",
|
|
3567
|
+
"try {",
|
|
3564
3568
|
`& { ${command} }`,
|
|
3565
3569
|
"$code = if ($null -ne $LASTEXITCODE) { [int]$LASTEXITCODE } elseif ($?) { 0 } else { 1 }",
|
|
3570
|
+
"} catch {",
|
|
3571
|
+
"[Console]::Error.WriteLine($_.Exception.Message)",
|
|
3572
|
+
"$code = 1",
|
|
3573
|
+
"}",
|
|
3566
3574
|
"exit $code"
|
|
3567
|
-
].join("
|
|
3575
|
+
].join("\n");
|
|
3568
3576
|
return Buffer.from(wrapped, "utf16le").toString("base64");
|
|
3569
3577
|
}
|
|
3570
3578
|
function buildCommandEnvironment() {
|
|
@@ -3576,422 +3584,33 @@ function buildCommandEnvironment() {
|
|
|
3576
3584
|
};
|
|
3577
3585
|
}
|
|
3578
3586
|
|
|
3579
|
-
// src/utils/commandRunner/
|
|
3580
|
-
function
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
let inSingle = false;
|
|
3584
|
-
let inDouble = false;
|
|
3585
|
-
for (let index = 0; index < command.length; index += 1) {
|
|
3586
|
-
const char = command.charAt(index);
|
|
3587
|
-
if (char === "'" && !inDouble) {
|
|
3588
|
-
inSingle = !inSingle;
|
|
3589
|
-
current += char;
|
|
3590
|
-
continue;
|
|
3591
|
-
}
|
|
3592
|
-
if (char === '"' && !inSingle) {
|
|
3593
|
-
inDouble = !inDouble;
|
|
3594
|
-
current += char;
|
|
3595
|
-
continue;
|
|
3596
|
-
}
|
|
3597
|
-
if (!inSingle && !inDouble && char === "&" && command.charAt(index + 1) === "&") {
|
|
3598
|
-
if (current.trim()) {
|
|
3599
|
-
segments.push(current.trim());
|
|
3600
|
-
}
|
|
3601
|
-
current = "";
|
|
3602
|
-
index += 1;
|
|
3603
|
-
continue;
|
|
3604
|
-
}
|
|
3605
|
-
current += char;
|
|
3606
|
-
}
|
|
3607
|
-
if (current.trim()) {
|
|
3608
|
-
segments.push(current.trim());
|
|
3609
|
-
}
|
|
3610
|
-
return segments.length > 0 ? segments : [command];
|
|
3611
|
-
}
|
|
3612
|
-
function joinWithAndSemantics(segments) {
|
|
3613
|
-
if (segments.length <= 1) {
|
|
3614
|
-
return segments[0] ?? "";
|
|
3615
|
-
}
|
|
3616
|
-
let script = segments[0] ?? "";
|
|
3617
|
-
for (let index = 1; index < segments.length; index += 1) {
|
|
3618
|
-
const segment = segments[index];
|
|
3619
|
-
script += `; if ($?) { ${segment} }`;
|
|
3620
|
-
}
|
|
3621
|
-
return script;
|
|
3622
|
-
}
|
|
3623
|
-
function splitArgs(command) {
|
|
3624
|
-
const args = [];
|
|
3625
|
-
let current = "";
|
|
3626
|
-
let inSingle = false;
|
|
3627
|
-
let inDouble = false;
|
|
3628
|
-
for (let index = 0; index < command.length; index += 1) {
|
|
3629
|
-
const char = command.charAt(index);
|
|
3630
|
-
if (char === "'" && !inDouble) {
|
|
3631
|
-
inSingle = !inSingle;
|
|
3632
|
-
continue;
|
|
3633
|
-
}
|
|
3634
|
-
if (char === '"' && !inSingle) {
|
|
3635
|
-
inDouble = !inDouble;
|
|
3636
|
-
continue;
|
|
3637
|
-
}
|
|
3638
|
-
if (!inSingle && !inDouble && /\s/.test(char)) {
|
|
3639
|
-
if (current) {
|
|
3640
|
-
args.push(current);
|
|
3641
|
-
current = "";
|
|
3642
|
-
}
|
|
3643
|
-
continue;
|
|
3644
|
-
}
|
|
3645
|
-
current += char;
|
|
3646
|
-
}
|
|
3647
|
-
if (current) {
|
|
3648
|
-
args.push(current);
|
|
3649
|
-
}
|
|
3650
|
-
return args;
|
|
3651
|
-
}
|
|
3652
|
-
function expandPaths(paths) {
|
|
3653
|
-
return paths.flatMap((targetPath) => expandBraces(targetPath));
|
|
3654
|
-
}
|
|
3655
|
-
function normalizeWindowsPath(value) {
|
|
3656
|
-
if (value.includes("://")) {
|
|
3657
|
-
return value;
|
|
3658
|
-
}
|
|
3659
|
-
return value.replace(/\//g, "\\");
|
|
3660
|
-
}
|
|
3661
|
-
function quotePowerShell(value) {
|
|
3662
|
-
const escaped = value.replace(/'/g, "''");
|
|
3663
|
-
return `'${escaped}'`;
|
|
3664
|
-
}
|
|
3665
|
-
function expandBraces(input) {
|
|
3666
|
-
const start = findBraceStart(input);
|
|
3667
|
-
if (start === -1) {
|
|
3668
|
-
return [input];
|
|
3669
|
-
}
|
|
3670
|
-
const end = findMatchingBrace(input, start);
|
|
3671
|
-
if (end === -1) {
|
|
3672
|
-
return [input];
|
|
3673
|
-
}
|
|
3674
|
-
const prefix = input.slice(0, start);
|
|
3675
|
-
const suffix = input.slice(end + 1);
|
|
3676
|
-
const body = input.slice(start + 1, end);
|
|
3677
|
-
const parts = splitBraceParts(body);
|
|
3678
|
-
const expandedSuffix = expandBraces(suffix);
|
|
3679
|
-
const results = [];
|
|
3680
|
-
for (const part of parts) {
|
|
3681
|
-
for (const expandedPart of expandBraces(part)) {
|
|
3682
|
-
for (const tail of expandedSuffix) {
|
|
3683
|
-
results.push(`${prefix}${expandedPart}${tail}`);
|
|
3684
|
-
}
|
|
3685
|
-
}
|
|
3686
|
-
}
|
|
3687
|
-
return results;
|
|
3688
|
-
}
|
|
3689
|
-
function findBraceStart(input) {
|
|
3690
|
-
let inSingle = false;
|
|
3691
|
-
let inDouble = false;
|
|
3692
|
-
for (let index = 0; index < input.length; index += 1) {
|
|
3693
|
-
const char = input.charAt(index);
|
|
3694
|
-
if (char === "'" && !inDouble) {
|
|
3695
|
-
inSingle = !inSingle;
|
|
3696
|
-
continue;
|
|
3697
|
-
}
|
|
3698
|
-
if (char === '"' && !inSingle) {
|
|
3699
|
-
inDouble = !inDouble;
|
|
3700
|
-
continue;
|
|
3701
|
-
}
|
|
3702
|
-
if (!inSingle && !inDouble && char === "{") {
|
|
3703
|
-
return index;
|
|
3704
|
-
}
|
|
3705
|
-
}
|
|
3706
|
-
return -1;
|
|
3707
|
-
}
|
|
3708
|
-
function findMatchingBrace(input, start) {
|
|
3709
|
-
let depth = 0;
|
|
3710
|
-
let inSingle = false;
|
|
3711
|
-
let inDouble = false;
|
|
3712
|
-
for (let index = start; index < input.length; index += 1) {
|
|
3713
|
-
const char = input.charAt(index);
|
|
3714
|
-
if (char === "'" && !inDouble) {
|
|
3715
|
-
inSingle = !inSingle;
|
|
3716
|
-
continue;
|
|
3717
|
-
}
|
|
3718
|
-
if (char === '"' && !inSingle) {
|
|
3719
|
-
inDouble = !inDouble;
|
|
3720
|
-
continue;
|
|
3721
|
-
}
|
|
3722
|
-
if (inSingle || inDouble) {
|
|
3723
|
-
continue;
|
|
3724
|
-
}
|
|
3725
|
-
if (char === "{") {
|
|
3726
|
-
depth += 1;
|
|
3727
|
-
} else if (char === "}") {
|
|
3728
|
-
depth -= 1;
|
|
3729
|
-
if (depth === 0) {
|
|
3730
|
-
return index;
|
|
3731
|
-
}
|
|
3732
|
-
}
|
|
3733
|
-
}
|
|
3734
|
-
return -1;
|
|
3735
|
-
}
|
|
3736
|
-
function splitBraceParts(input) {
|
|
3737
|
-
const parts = [];
|
|
3738
|
-
let current = "";
|
|
3739
|
-
let depth = 0;
|
|
3740
|
-
for (let index = 0; index < input.length; index += 1) {
|
|
3741
|
-
const char = input.charAt(index);
|
|
3742
|
-
if (char === "{") {
|
|
3743
|
-
depth += 1;
|
|
3744
|
-
current += char;
|
|
3745
|
-
continue;
|
|
3746
|
-
}
|
|
3747
|
-
if (char === "}") {
|
|
3748
|
-
depth -= 1;
|
|
3749
|
-
current += char;
|
|
3750
|
-
continue;
|
|
3751
|
-
}
|
|
3752
|
-
if (char === "," && depth === 0) {
|
|
3753
|
-
parts.push(current);
|
|
3754
|
-
current = "";
|
|
3755
|
-
continue;
|
|
3756
|
-
}
|
|
3757
|
-
current += char;
|
|
3758
|
-
}
|
|
3759
|
-
if (current) {
|
|
3760
|
-
parts.push(current);
|
|
3761
|
-
}
|
|
3762
|
-
return parts.length > 0 ? parts : [input];
|
|
3763
|
-
}
|
|
3764
|
-
|
|
3765
|
-
// src/utils/commandRunner/platformTransforms.ts
|
|
3766
|
-
function startsWithExplicitShell(command) {
|
|
3767
|
-
return /^\s*(cmd(?:\.exe)?\s+\/c|powershell(?:\.exe)?\b|pwsh\b|bash\b)/i.test(command);
|
|
3768
|
-
}
|
|
3769
|
-
function normalizeWindowsSegment(segment) {
|
|
3770
|
-
const trimmed = segment.trim();
|
|
3771
|
-
if (!trimmed) {
|
|
3772
|
-
return segment;
|
|
3773
|
-
}
|
|
3774
|
-
const lowered = trimmed.toLowerCase();
|
|
3775
|
-
if (lowered.startsWith("get-childitem") || lowered.startsWith("new-item")) {
|
|
3776
|
-
return segment;
|
|
3777
|
-
}
|
|
3778
|
-
if (lowered.startsWith("ls")) {
|
|
3779
|
-
return normalizeLsSegment(trimmed);
|
|
3780
|
-
}
|
|
3781
|
-
if (lowered.startsWith("mkdir") || lowered.startsWith("md ")) {
|
|
3782
|
-
return normalizeMkdirSegment(trimmed);
|
|
3783
|
-
}
|
|
3784
|
-
if (lowered.startsWith("rm ")) {
|
|
3785
|
-
return normalizeRemoveSegment(trimmed);
|
|
3786
|
-
}
|
|
3787
|
-
if (lowered.startsWith("cp ")) {
|
|
3788
|
-
return normalizeCopySegment(trimmed);
|
|
3789
|
-
}
|
|
3790
|
-
if (lowered.startsWith("mv ")) {
|
|
3791
|
-
return normalizeMoveSegment(trimmed);
|
|
3792
|
-
}
|
|
3793
|
-
if (lowered.startsWith("touch ")) {
|
|
3794
|
-
return normalizeTouchSegment(trimmed);
|
|
3587
|
+
// src/utils/commandRunner/output.ts
|
|
3588
|
+
function normalizeCommandOutput(output) {
|
|
3589
|
+
if (!output.includes("#< CLIXML")) {
|
|
3590
|
+
return output;
|
|
3795
3591
|
}
|
|
3796
|
-
|
|
3797
|
-
|
|
3592
|
+
const errors = [...output.matchAll(/<S\s+S="Error">([\s\S]*?)<\/S>/g)].map((match) => decodePowerShellText(match[1] ?? "")).map((line) => line.trimEnd()).filter(Boolean);
|
|
3593
|
+
if (errors.length === 0) {
|
|
3594
|
+
return output;
|
|
3798
3595
|
}
|
|
3799
|
-
return
|
|
3596
|
+
return errors.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
3800
3597
|
}
|
|
3801
|
-
function
|
|
3802
|
-
|
|
3803
|
-
const flags = args.filter((arg) => arg.startsWith("-"));
|
|
3804
|
-
const paths = args.filter((arg) => !arg.startsWith("-"));
|
|
3805
|
-
const force = flags.some((flag) => flag.includes("a"));
|
|
3806
|
-
const targetPath = paths[0];
|
|
3807
|
-
let command = "Get-ChildItem";
|
|
3808
|
-
if (force) {
|
|
3809
|
-
command += " -Force";
|
|
3810
|
-
}
|
|
3811
|
-
if (targetPath) {
|
|
3812
|
-
command += ` -LiteralPath ${quotePowerShell(normalizeWindowsPath(targetPath))}`;
|
|
3813
|
-
}
|
|
3814
|
-
return command;
|
|
3815
|
-
}
|
|
3816
|
-
function normalizeMkdirSegment(segment) {
|
|
3817
|
-
const args = splitArgs(segment);
|
|
3818
|
-
if (args.length <= 1) {
|
|
3819
|
-
return segment;
|
|
3820
|
-
}
|
|
3821
|
-
const rest = args.slice(1);
|
|
3822
|
-
let hasParents = false;
|
|
3823
|
-
const paths = rest.filter((arg) => {
|
|
3824
|
-
const lowered = arg.toLowerCase();
|
|
3825
|
-
if (lowered === "-p" || lowered === "--parents") {
|
|
3826
|
-
hasParents = true;
|
|
3827
|
-
return false;
|
|
3828
|
-
}
|
|
3829
|
-
return true;
|
|
3830
|
-
});
|
|
3831
|
-
const needsNormalization = hasParents || paths.some((targetPath) => targetPath.includes("{"));
|
|
3832
|
-
if (!needsNormalization) {
|
|
3833
|
-
return segment;
|
|
3834
|
-
}
|
|
3835
|
-
const expanded = expandPaths(paths);
|
|
3836
|
-
if (expanded.length === 0) {
|
|
3837
|
-
return segment;
|
|
3838
|
-
}
|
|
3839
|
-
const normalizedPaths = expanded.map((targetPath) => quotePowerShell(normalizeWindowsPath(targetPath)));
|
|
3840
|
-
return `New-Item -ItemType Directory -Force -Path ${normalizedPaths.join(", ")}`;
|
|
3841
|
-
}
|
|
3842
|
-
function normalizeRemoveSegment(segment) {
|
|
3843
|
-
const args = splitArgs(segment);
|
|
3844
|
-
if (args.length <= 1) {
|
|
3845
|
-
return segment;
|
|
3846
|
-
}
|
|
3847
|
-
const flags = args.slice(1).filter((arg) => arg.startsWith("-"));
|
|
3848
|
-
const paths = args.slice(1).filter((arg) => !arg.startsWith("-"));
|
|
3849
|
-
if (paths.length === 0) {
|
|
3850
|
-
return segment;
|
|
3851
|
-
}
|
|
3852
|
-
const recurse = flags.some((flag) => /r/i.test(flag));
|
|
3853
|
-
const force = flags.some((flag) => /f/i.test(flag));
|
|
3854
|
-
let command = "Remove-Item";
|
|
3855
|
-
if (recurse) {
|
|
3856
|
-
command += " -Recurse";
|
|
3857
|
-
}
|
|
3858
|
-
if (force) {
|
|
3859
|
-
command += " -Force";
|
|
3860
|
-
}
|
|
3861
|
-
command += ` -LiteralPath ${paths.map((targetPath) => quotePowerShell(normalizeWindowsPath(targetPath))).join(", ")}`;
|
|
3862
|
-
return command;
|
|
3863
|
-
}
|
|
3864
|
-
function normalizeCopySegment(segment) {
|
|
3865
|
-
const args = splitArgs(segment);
|
|
3866
|
-
if (args.length < 3) {
|
|
3867
|
-
return segment;
|
|
3868
|
-
}
|
|
3869
|
-
const flags = args.slice(1).filter((arg) => arg.startsWith("-"));
|
|
3870
|
-
const paths = args.slice(1).filter((arg) => !arg.startsWith("-"));
|
|
3871
|
-
if (paths.length < 2) {
|
|
3872
|
-
return segment;
|
|
3873
|
-
}
|
|
3874
|
-
const recurse = flags.some((flag) => /r/i.test(flag));
|
|
3875
|
-
const force = flags.some((flag) => /f/i.test(flag));
|
|
3876
|
-
const destination = paths[paths.length - 1];
|
|
3877
|
-
if (!destination) {
|
|
3878
|
-
return segment;
|
|
3879
|
-
}
|
|
3880
|
-
const sources = paths.slice(0, -1);
|
|
3881
|
-
let command = "Copy-Item";
|
|
3882
|
-
if (recurse) {
|
|
3883
|
-
command += " -Recurse";
|
|
3884
|
-
}
|
|
3885
|
-
if (force) {
|
|
3886
|
-
command += " -Force";
|
|
3887
|
-
}
|
|
3888
|
-
command += ` -Path ${sources.map((targetPath) => quotePowerShell(normalizeWindowsPath(targetPath))).join(", ")}`;
|
|
3889
|
-
command += ` -Destination ${quotePowerShell(normalizeWindowsPath(destination))}`;
|
|
3890
|
-
return command;
|
|
3891
|
-
}
|
|
3892
|
-
function normalizeMoveSegment(segment) {
|
|
3893
|
-
const args = splitArgs(segment);
|
|
3894
|
-
if (args.length < 3) {
|
|
3895
|
-
return segment;
|
|
3896
|
-
}
|
|
3897
|
-
const flags = args.slice(1).filter((arg) => arg.startsWith("-"));
|
|
3898
|
-
const paths = args.slice(1).filter((arg) => !arg.startsWith("-"));
|
|
3899
|
-
if (paths.length < 2) {
|
|
3900
|
-
return segment;
|
|
3901
|
-
}
|
|
3902
|
-
const force = flags.some((flag) => /f/i.test(flag));
|
|
3903
|
-
const destination = paths[paths.length - 1];
|
|
3904
|
-
if (!destination) {
|
|
3905
|
-
return segment;
|
|
3906
|
-
}
|
|
3907
|
-
const sources = paths.slice(0, -1);
|
|
3908
|
-
let command = "Move-Item";
|
|
3909
|
-
if (force) {
|
|
3910
|
-
command += " -Force";
|
|
3911
|
-
}
|
|
3912
|
-
command += ` -Path ${sources.map((targetPath) => quotePowerShell(normalizeWindowsPath(targetPath))).join(", ")}`;
|
|
3913
|
-
command += ` -Destination ${quotePowerShell(normalizeWindowsPath(destination))}`;
|
|
3914
|
-
return command;
|
|
3915
|
-
}
|
|
3916
|
-
function normalizeTouchSegment(segment) {
|
|
3917
|
-
const args = splitArgs(segment).slice(1);
|
|
3918
|
-
if (args.length === 0) {
|
|
3919
|
-
return segment;
|
|
3920
|
-
}
|
|
3921
|
-
const expanded = expandPaths(args);
|
|
3922
|
-
if (expanded.length === 0) {
|
|
3923
|
-
return segment;
|
|
3924
|
-
}
|
|
3925
|
-
const paths = expanded.map((targetPath) => quotePowerShell(normalizeWindowsPath(targetPath)));
|
|
3926
|
-
return `New-Item -ItemType File -Force -Path ${paths.join(", ")}`;
|
|
3927
|
-
}
|
|
3928
|
-
function normalizeCatSegment(segment) {
|
|
3929
|
-
const args = splitArgs(segment).slice(1);
|
|
3930
|
-
if (args.length === 0) {
|
|
3931
|
-
return segment;
|
|
3932
|
-
}
|
|
3933
|
-
const targetPath = args[0];
|
|
3934
|
-
if (!targetPath) {
|
|
3935
|
-
return segment;
|
|
3936
|
-
}
|
|
3937
|
-
return `Get-Content -LiteralPath ${quotePowerShell(normalizeWindowsPath(targetPath))}`;
|
|
3938
|
-
}
|
|
3939
|
-
|
|
3940
|
-
// src/utils/commandRunner/platform.ts
|
|
3941
|
-
function normalizeCommandForPlatform(command) {
|
|
3942
|
-
if (process.platform !== "win32") {
|
|
3943
|
-
return command;
|
|
3944
|
-
}
|
|
3945
|
-
const trimmed = command.trim();
|
|
3946
|
-
if (!trimmed) {
|
|
3947
|
-
return command;
|
|
3948
|
-
}
|
|
3949
|
-
const normalized = normalizeWindowsCommand(trimmed);
|
|
3950
|
-
return normalizeNpmCommandNames(normalized);
|
|
3951
|
-
}
|
|
3952
|
-
function normalizeWindowsCommand(command) {
|
|
3953
|
-
if (startsWithExplicitShell(command)) {
|
|
3954
|
-
return command;
|
|
3955
|
-
}
|
|
3956
|
-
const segments = splitByAndAnd(command);
|
|
3957
|
-
const normalizedSegments = segments.map((segment) => normalizeWindowsSegment(segment));
|
|
3958
|
-
return joinWithAndSemantics(normalizedSegments);
|
|
3959
|
-
}
|
|
3960
|
-
function normalizeNpmCommandNames(command) {
|
|
3961
|
-
const commandNames = {
|
|
3962
|
-
npm: "npm.cmd",
|
|
3963
|
-
npx: "npx.cmd",
|
|
3964
|
-
pnpm: "pnpm.cmd",
|
|
3965
|
-
yarn: "yarn.cmd"
|
|
3966
|
-
};
|
|
3967
|
-
const pattern = /(^|[;&|]|\&\&)\s*(npm|npx|pnpm|yarn)(?=\s|$)/gi;
|
|
3968
|
-
return command.replace(pattern, (match, prefix, tool) => {
|
|
3969
|
-
const replacement = commandNames[String(tool).toLowerCase()];
|
|
3970
|
-
if (!replacement) {
|
|
3971
|
-
return match;
|
|
3972
|
-
}
|
|
3973
|
-
if (!prefix) {
|
|
3974
|
-
return replacement;
|
|
3975
|
-
}
|
|
3976
|
-
return `${prefix} ${replacement}`;
|
|
3977
|
-
});
|
|
3598
|
+
function decodePowerShellText(value) {
|
|
3599
|
+
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, "&");
|
|
3978
3600
|
}
|
|
3979
3601
|
|
|
3980
3602
|
// src/utils/commandRunner/run.ts
|
|
3981
3603
|
var STALL_KILL_TIMEOUT_MS = 5e3;
|
|
3982
3604
|
async function runCommandWithPolicy(options) {
|
|
3983
|
-
|
|
3984
|
-
return runCommandOnce({
|
|
3985
|
-
...options,
|
|
3986
|
-
command: normalizedCommand
|
|
3987
|
-
});
|
|
3605
|
+
return runCommandOnce(options);
|
|
3988
3606
|
}
|
|
3989
3607
|
async function runCommandOnce(options) {
|
|
3990
3608
|
const start = Date.now();
|
|
3991
3609
|
let stalled = false;
|
|
3992
3610
|
let stallTimer = null;
|
|
3993
3611
|
let forceKillTimer = null;
|
|
3994
|
-
const
|
|
3612
|
+
const launched = await launchCommand(options.command, options.cwd, options.timeoutMs, options.abortSignal);
|
|
3613
|
+
const { subprocess } = launched;
|
|
3995
3614
|
const outputCapture = await createBashOutputCapture(options.outputCapture ?? {});
|
|
3996
3615
|
const clearTimers = () => {
|
|
3997
3616
|
if (stallTimer) {
|
|
@@ -4044,9 +3663,11 @@ async function runCommandOnce(options) {
|
|
|
4044
3663
|
const result = await subprocess;
|
|
4045
3664
|
clearTimers();
|
|
4046
3665
|
const shellOutput = await outputCapture.finalize();
|
|
3666
|
+
const output = normalizeCommandOutput(shellOutput.outputPreview);
|
|
4047
3667
|
return {
|
|
3668
|
+
command: options.command,
|
|
4048
3669
|
exitCode: typeof result.exitCode === "number" ? result.exitCode : null,
|
|
4049
|
-
output
|
|
3670
|
+
output,
|
|
4050
3671
|
outputPath: shellOutput.outputPath,
|
|
4051
3672
|
truncated: shellOutput.truncated,
|
|
4052
3673
|
outputChars: shellOutput.outputChars,
|
|
@@ -4061,9 +3682,12 @@ async function runCommandOnce(options) {
|
|
|
4061
3682
|
const timedOut = isTimedOutError(error);
|
|
4062
3683
|
clearTimers();
|
|
4063
3684
|
const shellOutput = await outputCapture.finalize();
|
|
3685
|
+
const fallbackOutput = shellOutput.outputChars > 0 ? shellOutput.outputPreview : readProcessOutput(error);
|
|
3686
|
+
const output = normalizeCommandOutput(fallbackOutput);
|
|
4064
3687
|
return {
|
|
3688
|
+
command: options.command,
|
|
4065
3689
|
exitCode: readExitCode(error),
|
|
4066
|
-
output
|
|
3690
|
+
output,
|
|
4067
3691
|
outputPath: shellOutput.outputPath,
|
|
4068
3692
|
truncated: shellOutput.truncated,
|
|
4069
3693
|
outputChars: shellOutput.outputChars,
|
|
@@ -4624,7 +4248,7 @@ var bashToolDefinition = {
|
|
|
4624
4248
|
const status = result.aborted ? "aborted" : result.stalled ? "stalled" : result.timedOut ? "timed_out" : result.exitCode === 0 ? "completed" : "failed";
|
|
4625
4249
|
const outputGovernance = governToolOutput({
|
|
4626
4250
|
toolName: "bash",
|
|
4627
|
-
command,
|
|
4251
|
+
command: result.command,
|
|
4628
4252
|
status,
|
|
4629
4253
|
exitCode: result.exitCode,
|
|
4630
4254
|
durationMs: result.durationMs,
|
|
@@ -4652,7 +4276,7 @@ var bashToolDefinition = {
|
|
|
4652
4276
|
return okResult(
|
|
4653
4277
|
JSON.stringify(
|
|
4654
4278
|
{
|
|
4655
|
-
command,
|
|
4279
|
+
command: result.command,
|
|
4656
4280
|
cwd: resolvedCwd,
|
|
4657
4281
|
exitCode: result.exitCode,
|
|
4658
4282
|
status,
|
|
@@ -6099,6 +5723,53 @@ async function executeToolBatch(params) {
|
|
|
6099
5723
|
};
|
|
6100
5724
|
}
|
|
6101
5725
|
|
|
5726
|
+
// src/session/events.ts
|
|
5727
|
+
import fs15 from "fs/promises";
|
|
5728
|
+
import path15 from "path";
|
|
5729
|
+
var SessionEventStore = class {
|
|
5730
|
+
constructor(eventsDir) {
|
|
5731
|
+
this.eventsDir = eventsDir;
|
|
5732
|
+
}
|
|
5733
|
+
async append(event) {
|
|
5734
|
+
const record = {
|
|
5735
|
+
id: createEventId(),
|
|
5736
|
+
createdAt: event.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
5737
|
+
type: event.type,
|
|
5738
|
+
sessionId: event.sessionId,
|
|
5739
|
+
cwd: event.cwd,
|
|
5740
|
+
host: event.host,
|
|
5741
|
+
message: event.message,
|
|
5742
|
+
details: event.details
|
|
5743
|
+
};
|
|
5744
|
+
await fs15.mkdir(this.eventsDir, { recursive: true });
|
|
5745
|
+
await fs15.appendFile(this.getSessionEventPath(event.sessionId), `${JSON.stringify(record)}
|
|
5746
|
+
`, "utf8");
|
|
5747
|
+
return record;
|
|
5748
|
+
}
|
|
5749
|
+
async list(sessionId, limit = 100) {
|
|
5750
|
+
const filePath = this.getSessionEventPath(sessionId);
|
|
5751
|
+
let raw = "";
|
|
5752
|
+
try {
|
|
5753
|
+
raw = await fs15.readFile(filePath, "utf8");
|
|
5754
|
+
} catch (error) {
|
|
5755
|
+
if (error.code === "ENOENT") {
|
|
5756
|
+
return [];
|
|
5757
|
+
}
|
|
5758
|
+
throw error;
|
|
5759
|
+
}
|
|
5760
|
+
return raw.split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line)).slice(-limit);
|
|
5761
|
+
}
|
|
5762
|
+
getSessionEventPath(sessionId) {
|
|
5763
|
+
return path15.join(this.eventsDir, `${sanitizeSessionId(sessionId)}.jsonl`);
|
|
5764
|
+
}
|
|
5765
|
+
};
|
|
5766
|
+
function createEventId() {
|
|
5767
|
+
return `${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:.TZ]/g, "").slice(0, 14)}-${Math.random().toString(16).slice(2, 10)}`;
|
|
5768
|
+
}
|
|
5769
|
+
function sanitizeSessionId(sessionId) {
|
|
5770
|
+
return sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
5771
|
+
}
|
|
5772
|
+
|
|
6102
5773
|
// src/agent/turn/toolFailure.ts
|
|
6103
5774
|
function readToolFailureError(output) {
|
|
6104
5775
|
try {
|
|
@@ -6134,9 +5805,16 @@ async function processToolCallBatch(input) {
|
|
|
6134
5805
|
const batchToolMessages = [];
|
|
6135
5806
|
const batchModelOutputs = [];
|
|
6136
5807
|
const batchChangedPaths = /* @__PURE__ */ new Set();
|
|
5808
|
+
const sessionEvents = new SessionEventStore(options.config.paths.eventsDir);
|
|
6137
5809
|
const leadWaitExecutionsBefore = identity.kind === "lead" ? listLeadWaitExecutions(projectContext.stateRootDir) : [];
|
|
6138
5810
|
for (const toolCall of response.toolCalls) {
|
|
6139
5811
|
throwIfAborted(options.abortSignal, "Turn aborted by user.");
|
|
5812
|
+
await sessionEvents.append({
|
|
5813
|
+
type: "tool.started",
|
|
5814
|
+
sessionId: session.id,
|
|
5815
|
+
cwd: options.cwd,
|
|
5816
|
+
details: buildToolStartedEventDetails(toolCall, identity)
|
|
5817
|
+
});
|
|
6140
5818
|
options.callbacks?.onToolCall?.(toolCall.function.name, toolCall.function.arguments);
|
|
6141
5819
|
await recordObservabilityEvent(projectContext.stateRootDir, {
|
|
6142
5820
|
event: "tool.execution",
|
|
@@ -6170,6 +5848,7 @@ async function processToolCallBatch(input) {
|
|
|
6170
5848
|
} else if (metadata?.sessionDiff) {
|
|
6171
5849
|
session = await options.sessionStore.save(noteSessionDiff(session, metadata.sessionDiff));
|
|
6172
5850
|
}
|
|
5851
|
+
const failureError = result.ok ? void 0 : readToolFailureError(result.output);
|
|
6173
5852
|
await recordObservabilityEvent(projectContext.stateRootDir, {
|
|
6174
5853
|
event: "tool.execution",
|
|
6175
5854
|
status: result.ok ? "completed" : "failed",
|
|
@@ -6178,11 +5857,23 @@ async function processToolCallBatch(input) {
|
|
|
6178
5857
|
identityName: identity.name,
|
|
6179
5858
|
toolName: toolCall.function.name,
|
|
6180
5859
|
durationMs,
|
|
6181
|
-
error:
|
|
5860
|
+
error: failureError,
|
|
6182
5861
|
details: {
|
|
6183
5862
|
changedPathCount: metadata?.changedPaths?.length ?? 0
|
|
6184
5863
|
}
|
|
6185
5864
|
});
|
|
5865
|
+
await sessionEvents.append({
|
|
5866
|
+
type: result.ok ? "tool.completed" : "tool.failed",
|
|
5867
|
+
sessionId: session.id,
|
|
5868
|
+
cwd: options.cwd,
|
|
5869
|
+
details: buildToolFinishedEventDetails({
|
|
5870
|
+
toolCall,
|
|
5871
|
+
identity,
|
|
5872
|
+
durationMs,
|
|
5873
|
+
changedPathCount: metadata?.changedPaths?.length ?? 0,
|
|
5874
|
+
error: failureError ? formatToolFailureError(failureError) : void 0
|
|
5875
|
+
})
|
|
5876
|
+
});
|
|
6186
5877
|
if (metadata?.outputGovernance) {
|
|
6187
5878
|
await recordObservabilityEvent(projectContext.stateRootDir, {
|
|
6188
5879
|
event: "tool.output",
|
|
@@ -6276,6 +5967,33 @@ async function processToolCallBatch(input) {
|
|
|
6276
5967
|
}
|
|
6277
5968
|
};
|
|
6278
5969
|
}
|
|
5970
|
+
function buildToolStartedEventDetails(toolCall, identity) {
|
|
5971
|
+
return {
|
|
5972
|
+
toolName: toolCall.function.name,
|
|
5973
|
+
toolCallId: toolCall.id,
|
|
5974
|
+
identityKind: identity.kind,
|
|
5975
|
+
identityName: identity.name,
|
|
5976
|
+
argumentsPreview: previewToolArguments(toolCall.function.arguments)
|
|
5977
|
+
};
|
|
5978
|
+
}
|
|
5979
|
+
function buildToolFinishedEventDetails(input) {
|
|
5980
|
+
return {
|
|
5981
|
+
toolName: input.toolCall.function.name,
|
|
5982
|
+
toolCallId: input.toolCall.id,
|
|
5983
|
+
identityKind: input.identity.kind,
|
|
5984
|
+
identityName: input.identity.name,
|
|
5985
|
+
durationMs: input.durationMs,
|
|
5986
|
+
changedPathCount: input.changedPathCount,
|
|
5987
|
+
error: input.error
|
|
5988
|
+
};
|
|
5989
|
+
}
|
|
5990
|
+
function previewToolArguments(rawArgs) {
|
|
5991
|
+
const normalized = rawArgs.replace(/\s+/g, " ").trim();
|
|
5992
|
+
return normalized.length > 240 ? `${normalized.slice(0, 237)}...` : normalized;
|
|
5993
|
+
}
|
|
5994
|
+
function formatToolFailureError(error) {
|
|
5995
|
+
return error.code ? `${error.code}: ${error.message}` : error.message;
|
|
5996
|
+
}
|
|
6279
5997
|
|
|
6280
5998
|
// src/agent/turn/toolless.ts
|
|
6281
5999
|
async function resolveToollessTurn(params) {
|
|
@@ -6362,8 +6080,8 @@ function normalizeToolArguments(raw) {
|
|
|
6362
6080
|
|
|
6363
6081
|
// src/agent/changes/store.ts
|
|
6364
6082
|
import crypto2 from "crypto";
|
|
6365
|
-
import
|
|
6366
|
-
import
|
|
6083
|
+
import fs16 from "fs/promises";
|
|
6084
|
+
import path16 from "path";
|
|
6367
6085
|
var ChangeStore = class {
|
|
6368
6086
|
constructor(changesDir) {
|
|
6369
6087
|
this.changesDir = changesDir;
|
|
@@ -6371,8 +6089,8 @@ var ChangeStore = class {
|
|
|
6371
6089
|
async record(input) {
|
|
6372
6090
|
const id = createChangeId();
|
|
6373
6091
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
6374
|
-
const blobDir =
|
|
6375
|
-
await
|
|
6092
|
+
const blobDir = path16.join(this.changesDir, id);
|
|
6093
|
+
await fs16.mkdir(blobDir, { recursive: true });
|
|
6376
6094
|
const operations = await Promise.all(
|
|
6377
6095
|
input.operations.map(async (operation, index) => {
|
|
6378
6096
|
const beforeSnapshotPath = await this.writeSnapshot(
|
|
@@ -6412,21 +6130,21 @@ var ChangeStore = class {
|
|
|
6412
6130
|
preview: input.preview,
|
|
6413
6131
|
operations
|
|
6414
6132
|
};
|
|
6415
|
-
await
|
|
6416
|
-
await
|
|
6133
|
+
await fs16.mkdir(this.changesDir, { recursive: true });
|
|
6134
|
+
await fs16.writeFile(this.getMetadataPath(id), `${JSON.stringify(record, null, 2)}
|
|
6417
6135
|
`, "utf8");
|
|
6418
6136
|
return record;
|
|
6419
6137
|
}
|
|
6420
6138
|
async list(limit = 20) {
|
|
6421
|
-
await
|
|
6422
|
-
const entries = await
|
|
6139
|
+
await fs16.mkdir(this.changesDir, { recursive: true });
|
|
6140
|
+
const entries = await fs16.readdir(this.changesDir, { withFileTypes: true });
|
|
6423
6141
|
const changes = await Promise.all(
|
|
6424
|
-
entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => this.load(
|
|
6142
|
+
entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => this.load(path16.basename(entry.name, ".json")))
|
|
6425
6143
|
);
|
|
6426
6144
|
return changes.sort((left, right) => right.createdAt.localeCompare(left.createdAt)).slice(0, limit);
|
|
6427
6145
|
}
|
|
6428
6146
|
async load(id) {
|
|
6429
|
-
const raw = await
|
|
6147
|
+
const raw = await fs16.readFile(this.getMetadataPath(id), "utf8");
|
|
6430
6148
|
return JSON.parse(raw);
|
|
6431
6149
|
}
|
|
6432
6150
|
async loadLatestUndoable() {
|
|
@@ -6450,17 +6168,17 @@ var ChangeStore = class {
|
|
|
6450
6168
|
restoredPaths.push(operation.path);
|
|
6451
6169
|
if (operation.beforeSnapshotPath) {
|
|
6452
6170
|
const buffer = await this.readSnapshot(operation.beforeSnapshotPath);
|
|
6453
|
-
await
|
|
6454
|
-
await
|
|
6171
|
+
await fs16.mkdir(path16.dirname(operation.path), { recursive: true });
|
|
6172
|
+
await fs16.writeFile(operation.path, buffer);
|
|
6455
6173
|
continue;
|
|
6456
6174
|
}
|
|
6457
|
-
await
|
|
6175
|
+
await fs16.rm(operation.path, { force: true });
|
|
6458
6176
|
}
|
|
6459
6177
|
const updated = {
|
|
6460
6178
|
...record,
|
|
6461
6179
|
undoneAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6462
6180
|
};
|
|
6463
|
-
await
|
|
6181
|
+
await fs16.writeFile(this.getMetadataPath(updated.id), `${JSON.stringify(updated, null, 2)}
|
|
6464
6182
|
`, "utf8");
|
|
6465
6183
|
return {
|
|
6466
6184
|
record: updated,
|
|
@@ -6468,19 +6186,19 @@ var ChangeStore = class {
|
|
|
6468
6186
|
};
|
|
6469
6187
|
}
|
|
6470
6188
|
getMetadataPath(id) {
|
|
6471
|
-
return
|
|
6189
|
+
return path16.join(this.changesDir, `${id}.json`);
|
|
6472
6190
|
}
|
|
6473
6191
|
async writeSnapshot(blobDir, label, buffer) {
|
|
6474
6192
|
if (!buffer) {
|
|
6475
6193
|
return void 0;
|
|
6476
6194
|
}
|
|
6477
6195
|
const fileName = `${label}.bin`;
|
|
6478
|
-
const absolutePath =
|
|
6479
|
-
await
|
|
6480
|
-
return
|
|
6196
|
+
const absolutePath = path16.join(blobDir, fileName);
|
|
6197
|
+
await fs16.writeFile(absolutePath, buffer);
|
|
6198
|
+
return path16.relative(this.changesDir, absolutePath);
|
|
6481
6199
|
}
|
|
6482
6200
|
async readSnapshot(relativePath) {
|
|
6483
|
-
return
|
|
6201
|
+
return fs16.readFile(path16.join(this.changesDir, relativePath));
|
|
6484
6202
|
}
|
|
6485
6203
|
};
|
|
6486
6204
|
function createChangeId() {
|
|
@@ -6866,9 +6584,10 @@ var backgroundRunTool = {
|
|
|
6866
6584
|
registerBackgroundProcess(job.id, subprocess);
|
|
6867
6585
|
store.markRunning(job.id, { pid: subprocess.pid ?? 0 });
|
|
6868
6586
|
const outputTracker = createBackgroundOutputTracker((output) => {
|
|
6587
|
+
const normalizedOutput = normalizeCommandOutput(output);
|
|
6869
6588
|
store.updateRunningOutput(job.id, {
|
|
6870
|
-
output,
|
|
6871
|
-
summary: summarizeBackgroundOutput(
|
|
6589
|
+
output: normalizedOutput,
|
|
6590
|
+
summary: summarizeBackgroundOutput(normalizedOutput),
|
|
6872
6591
|
lastOutputAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6873
6592
|
});
|
|
6874
6593
|
});
|
|
@@ -6878,7 +6597,7 @@ var backgroundRunTool = {
|
|
|
6878
6597
|
void subprocess.then(async (result) => {
|
|
6879
6598
|
outputTracker.flush();
|
|
6880
6599
|
const running2 = store.load(job.id);
|
|
6881
|
-
const resultOutput = typeof result.all === "string" ? result.all : "";
|
|
6600
|
+
const resultOutput = normalizeCommandOutput(typeof result.all === "string" ? result.all : "");
|
|
6882
6601
|
const output = resultOutput || running2?.output || "";
|
|
6883
6602
|
store.close(job.id, {
|
|
6884
6603
|
status: result.exitCode === 0 ? "completed" : "failed",
|
|
@@ -6890,7 +6609,7 @@ var backgroundRunTool = {
|
|
|
6890
6609
|
}, async (error) => {
|
|
6891
6610
|
outputTracker.flush();
|
|
6892
6611
|
const running2 = store.load(job.id);
|
|
6893
|
-
const errorOutput = typeof error.all === "string" ? error.all : "";
|
|
6612
|
+
const errorOutput = normalizeCommandOutput(typeof error.all === "string" ? error.all : "");
|
|
6894
6613
|
const output = errorOutput || running2?.output || String(error.message);
|
|
6895
6614
|
store.close(job.id, {
|
|
6896
6615
|
status: "failed",
|
|
@@ -7058,20 +6777,20 @@ function createBackgroundTools() {
|
|
|
7058
6777
|
}
|
|
7059
6778
|
|
|
7060
6779
|
// src/extensions/tools/network/tools/downloadUrl.ts
|
|
7061
|
-
import
|
|
6780
|
+
import fs18 from "fs/promises";
|
|
7062
6781
|
|
|
7063
6782
|
// src/extensions/shared.ts
|
|
7064
|
-
import
|
|
7065
|
-
import
|
|
6783
|
+
import fs17 from "fs/promises";
|
|
6784
|
+
import path17 from "path";
|
|
7066
6785
|
async function ensureExtensionDir(rootDir, extensionId) {
|
|
7067
6786
|
const paths = await ensureProjectStateDirectories(rootDir);
|
|
7068
|
-
const dir =
|
|
7069
|
-
await
|
|
6787
|
+
const dir = path17.join(paths.extensionsDir, extensionId);
|
|
6788
|
+
await fs17.mkdir(dir, { recursive: true });
|
|
7070
6789
|
return dir;
|
|
7071
6790
|
}
|
|
7072
6791
|
async function readJsonFile(filePath, fallback) {
|
|
7073
6792
|
try {
|
|
7074
|
-
return JSON.parse(await
|
|
6793
|
+
return JSON.parse(await fs17.readFile(filePath, "utf8"));
|
|
7075
6794
|
} catch (error) {
|
|
7076
6795
|
if (error.code === "ENOENT") {
|
|
7077
6796
|
return fallback;
|
|
@@ -7080,8 +6799,8 @@ async function readJsonFile(filePath, fallback) {
|
|
|
7080
6799
|
}
|
|
7081
6800
|
}
|
|
7082
6801
|
async function writeJsonFile(filePath, value) {
|
|
7083
|
-
await
|
|
7084
|
-
await
|
|
6802
|
+
await fs17.mkdir(path17.dirname(filePath), { recursive: true });
|
|
6803
|
+
await fs17.writeFile(filePath, `${JSON.stringify(value, null, 2)}
|
|
7085
6804
|
`, "utf8");
|
|
7086
6805
|
}
|
|
7087
6806
|
function jsonResult(value) {
|
|
@@ -7097,7 +6816,7 @@ function sanitizeStateSegment(value) {
|
|
|
7097
6816
|
}
|
|
7098
6817
|
|
|
7099
6818
|
// src/extensions/tools/network/session.ts
|
|
7100
|
-
import
|
|
6819
|
+
import path18 from "path";
|
|
7101
6820
|
async function listHttpSessions(rootDir) {
|
|
7102
6821
|
const state = await readJsonFile(await sessionFile(rootDir), { sessions: [] });
|
|
7103
6822
|
return Array.isArray(state.sessions) ? state.sessions.map(normalizeSession) : [];
|
|
@@ -7122,7 +6841,7 @@ async function getHttpSessionStateFile(rootDir) {
|
|
|
7122
6841
|
return sessionFile(rootDir);
|
|
7123
6842
|
}
|
|
7124
6843
|
async function sessionFile(rootDir) {
|
|
7125
|
-
return
|
|
6844
|
+
return path18.join(await ensureExtensionDir(rootDir, "network"), "http-sessions.json");
|
|
7126
6845
|
}
|
|
7127
6846
|
function normalizeSession(value) {
|
|
7128
6847
|
return {
|
|
@@ -7351,7 +7070,7 @@ var downloadUrlTool = {
|
|
|
7351
7070
|
}
|
|
7352
7071
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
7353
7072
|
await ensureParentDirectory(targetPath);
|
|
7354
|
-
await
|
|
7073
|
+
await fs18.writeFile(targetPath, bytes);
|
|
7355
7074
|
return changedJsonResult({
|
|
7356
7075
|
ok: response.ok,
|
|
7357
7076
|
url,
|
|
@@ -7416,17 +7135,17 @@ var httpProbeTool = {
|
|
|
7416
7135
|
};
|
|
7417
7136
|
|
|
7418
7137
|
// src/extensions/tools/network/traceStore.ts
|
|
7419
|
-
import
|
|
7420
|
-
import
|
|
7138
|
+
import fs19 from "fs/promises";
|
|
7139
|
+
import path19 from "path";
|
|
7421
7140
|
async function writeNetworkTrace(rootDir, traceId, record) {
|
|
7422
7141
|
const filePath = await networkTraceFilePath(rootDir, traceId);
|
|
7423
|
-
await
|
|
7424
|
-
await
|
|
7142
|
+
await fs19.mkdir(path19.dirname(filePath), { recursive: true });
|
|
7143
|
+
await fs19.writeFile(filePath, `${JSON.stringify(record, null, 2)}
|
|
7425
7144
|
`, "utf8");
|
|
7426
7145
|
return filePath;
|
|
7427
7146
|
}
|
|
7428
7147
|
async function networkTraceFilePath(rootDir, traceId) {
|
|
7429
|
-
return
|
|
7148
|
+
return path19.join(await ensureExtensionDir(rootDir, "network"), "traces", `${sanitizeStateSegment(traceId)}.json`);
|
|
7430
7149
|
}
|
|
7431
7150
|
|
|
7432
7151
|
// src/extensions/tools/network/tools/httpRequest.ts
|
|
@@ -7826,14 +7545,14 @@ function readStringMap2(value) {
|
|
|
7826
7545
|
}
|
|
7827
7546
|
|
|
7828
7547
|
// src/extensions/tools/network/openapi.ts
|
|
7829
|
-
import
|
|
7548
|
+
import fs20 from "fs/promises";
|
|
7830
7549
|
async function loadOpenApiDocument(source, context) {
|
|
7831
7550
|
const normalizedSource = source.trim();
|
|
7832
7551
|
if (!normalizedSource) {
|
|
7833
7552
|
throw new ToolExecutionError("OpenAPI source is required.", { code: "OPENAPI_SOURCE_INVALID" });
|
|
7834
7553
|
}
|
|
7835
7554
|
const resolvedSource = /^https?:\/\//i.test(normalizedSource) ? normalizedSource : resolveUserPath(normalizedSource, context.cwd);
|
|
7836
|
-
const raw = /^https?:\/\//i.test(normalizedSource) ? await (await fetchWithTimeout(normalizedSource, { method: "GET" }, 2e4, context.abortSignal)).text() : stripBom(await
|
|
7555
|
+
const raw = /^https?:\/\//i.test(normalizedSource) ? await (await fetchWithTimeout(normalizedSource, { method: "GET" }, 2e4, context.abortSignal)).text() : stripBom(await fs20.readFile(resolvedSource, "utf8"));
|
|
7837
7556
|
const parsed = parseOpenApiDocument(raw, normalizedSource);
|
|
7838
7557
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7839
7558
|
throw new ToolExecutionError("OpenAPI document root must be an object.", { code: "OPENAPI_ROOT_INVALID" });
|
|
@@ -8181,8 +7900,8 @@ async function recordSkillUse(rootDir, input) {
|
|
|
8181
7900
|
}
|
|
8182
7901
|
|
|
8183
7902
|
// src/extensions/tools/skills/tools/skillReadResource.ts
|
|
8184
|
-
import
|
|
8185
|
-
import
|
|
7903
|
+
import fs21 from "fs/promises";
|
|
7904
|
+
import path20 from "path";
|
|
8186
7905
|
var MAX_RESOURCE_CHARS = 24e3;
|
|
8187
7906
|
var skillReadResourceTool = {
|
|
8188
7907
|
definition: {
|
|
@@ -8219,8 +7938,8 @@ var skillReadResourceTool = {
|
|
|
8219
7938
|
if (!resource) {
|
|
8220
7939
|
throw new Error(`Skill "${name}" does not declare resource: ${requestedPath}`);
|
|
8221
7940
|
}
|
|
8222
|
-
const absolutePath =
|
|
8223
|
-
const content = await
|
|
7941
|
+
const absolutePath = path20.resolve(context.projectContext.rootDir, resource.path);
|
|
7942
|
+
const content = await fs21.readFile(absolutePath, "utf8");
|
|
8224
7943
|
return jsonResult({
|
|
8225
7944
|
ok: true,
|
|
8226
7945
|
skill: {
|
|
@@ -8238,7 +7957,7 @@ function normalizeResourcePath(value) {
|
|
|
8238
7957
|
}
|
|
8239
7958
|
|
|
8240
7959
|
// src/extensions/tools/skills/tools/skillRunScript.ts
|
|
8241
|
-
import
|
|
7960
|
+
import path21 from "path";
|
|
8242
7961
|
var skillRunScriptTool = {
|
|
8243
7962
|
definition: {
|
|
8244
7963
|
type: "function",
|
|
@@ -8282,12 +8001,12 @@ var skillRunScriptTool = {
|
|
|
8282
8001
|
if (!resource) {
|
|
8283
8002
|
throw new Error(`Skill "${name}" does not declare script resource: ${requestedPath}`);
|
|
8284
8003
|
}
|
|
8285
|
-
const skillDir =
|
|
8286
|
-
const relativeToSkill = normalizeResourcePath2(
|
|
8004
|
+
const skillDir = path21.dirname(skill.path);
|
|
8005
|
+
const relativeToSkill = normalizeResourcePath2(path21.relative(skillDir, resource.path));
|
|
8287
8006
|
if (!relativeToSkill.startsWith("scripts/")) {
|
|
8288
8007
|
throw new Error(`Skill "${name}" resource is not executable because it is outside scripts/: ${requestedPath}`);
|
|
8289
8008
|
}
|
|
8290
|
-
const scriptPath =
|
|
8009
|
+
const scriptPath = path21.resolve(context.projectContext.rootDir, resource.path);
|
|
8291
8010
|
const argumentText = typeof args.args === "string" ? args.args.trim() : "";
|
|
8292
8011
|
const command = buildScriptCommand(scriptPath, argumentText);
|
|
8293
8012
|
const result = await runCommandWithPolicy({
|
|
@@ -8362,7 +8081,7 @@ function quotePath(value) {
|
|
|
8362
8081
|
return `"${value.replace(/"/g, '\\"')}"`;
|
|
8363
8082
|
}
|
|
8364
8083
|
function buildScriptCommand(scriptPath, argumentText) {
|
|
8365
|
-
const extension =
|
|
8084
|
+
const extension = path21.extname(scriptPath).toLowerCase();
|
|
8366
8085
|
const quoted = quotePath(scriptPath);
|
|
8367
8086
|
const suffix = argumentText ? ` ${argumentText}` : "";
|
|
8368
8087
|
if (extension === ".js" || extension === ".mjs" || extension === ".cjs") {
|
|
@@ -8416,12 +8135,12 @@ var subagentCheckTool = {
|
|
|
8416
8135
|
|
|
8417
8136
|
// src/execution/launch.ts
|
|
8418
8137
|
import { spawn } from "child_process";
|
|
8419
|
-
import
|
|
8138
|
+
import path22 from "path";
|
|
8420
8139
|
function spawnExecutionWorker(input) {
|
|
8421
8140
|
if (process.env.KITTY_TEST_WORKER_MODE === "stub") {
|
|
8422
8141
|
return process.pid;
|
|
8423
8142
|
}
|
|
8424
|
-
const cliEntry =
|
|
8143
|
+
const cliEntry = path22.resolve(process.argv[1] ?? "");
|
|
8425
8144
|
if (!cliEntry) {
|
|
8426
8145
|
throw new Error("Unable to locate Kitty CLI entrypoint for execution worker.");
|
|
8427
8146
|
}
|
|
@@ -8627,7 +8346,7 @@ function parseWorktreeBlock(block) {
|
|
|
8627
8346
|
}
|
|
8628
8347
|
|
|
8629
8348
|
// src/extensions/tools/worktree/state.ts
|
|
8630
|
-
import
|
|
8349
|
+
import path23 from "path";
|
|
8631
8350
|
async function readWorktreeState(rootDir) {
|
|
8632
8351
|
return normalizeWorktreeState(await readJsonFile(await stateFile(rootDir), {
|
|
8633
8352
|
schemaVersion: 1,
|
|
@@ -8650,7 +8369,7 @@ async function recordWorktreeEvent(rootDir, event) {
|
|
|
8650
8369
|
return writeWorktreeState(rootDir, state);
|
|
8651
8370
|
}
|
|
8652
8371
|
async function stateFile(rootDir) {
|
|
8653
|
-
return
|
|
8372
|
+
return path23.join(await ensureExtensionDir(rootDir, "worktree"), "state.json");
|
|
8654
8373
|
}
|
|
8655
8374
|
function normalizeWorktreeState(value) {
|
|
8656
8375
|
return {
|
|
@@ -9273,8 +8992,8 @@ function looksLikeToolProtocolText(content) {
|
|
|
9273
8992
|
}
|
|
9274
8993
|
|
|
9275
8994
|
// src/observability/crashRecorder.ts
|
|
9276
|
-
import
|
|
9277
|
-
import
|
|
8995
|
+
import fs22 from "fs";
|
|
8996
|
+
import path24 from "path";
|
|
9278
8997
|
var activeCrashContexts = /* @__PURE__ */ new Map();
|
|
9279
8998
|
var nextCrashContextId = 0;
|
|
9280
8999
|
function enterCrashContext(context) {
|
|
@@ -9286,7 +9005,7 @@ function enterCrashContext(context) {
|
|
|
9286
9005
|
}
|
|
9287
9006
|
|
|
9288
9007
|
// src/observability/hostEvents.ts
|
|
9289
|
-
import
|
|
9008
|
+
import path25 from "path";
|
|
9290
9009
|
async function recordHostTurnStarted(rootDir, input) {
|
|
9291
9010
|
await recordObservabilityEvent(rootDir, {
|
|
9292
9011
|
event: "host.turn",
|
|
@@ -9317,53 +9036,6 @@ async function recordHostTurnFinished(rootDir, input) {
|
|
|
9317
9036
|
});
|
|
9318
9037
|
}
|
|
9319
9038
|
|
|
9320
|
-
// src/session/events.ts
|
|
9321
|
-
import fs22 from "fs/promises";
|
|
9322
|
-
import path25 from "path";
|
|
9323
|
-
var SessionEventStore = class {
|
|
9324
|
-
constructor(eventsDir) {
|
|
9325
|
-
this.eventsDir = eventsDir;
|
|
9326
|
-
}
|
|
9327
|
-
async append(event) {
|
|
9328
|
-
const record = {
|
|
9329
|
-
id: createEventId(),
|
|
9330
|
-
createdAt: event.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
9331
|
-
type: event.type,
|
|
9332
|
-
sessionId: event.sessionId,
|
|
9333
|
-
cwd: event.cwd,
|
|
9334
|
-
host: event.host,
|
|
9335
|
-
message: event.message,
|
|
9336
|
-
details: event.details
|
|
9337
|
-
};
|
|
9338
|
-
await fs22.mkdir(this.eventsDir, { recursive: true });
|
|
9339
|
-
await fs22.appendFile(this.getSessionEventPath(event.sessionId), `${JSON.stringify(record)}
|
|
9340
|
-
`, "utf8");
|
|
9341
|
-
return record;
|
|
9342
|
-
}
|
|
9343
|
-
async list(sessionId, limit = 100) {
|
|
9344
|
-
const filePath = this.getSessionEventPath(sessionId);
|
|
9345
|
-
let raw = "";
|
|
9346
|
-
try {
|
|
9347
|
-
raw = await fs22.readFile(filePath, "utf8");
|
|
9348
|
-
} catch (error) {
|
|
9349
|
-
if (error.code === "ENOENT") {
|
|
9350
|
-
return [];
|
|
9351
|
-
}
|
|
9352
|
-
throw error;
|
|
9353
|
-
}
|
|
9354
|
-
return raw.split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line)).slice(-limit);
|
|
9355
|
-
}
|
|
9356
|
-
getSessionEventPath(sessionId) {
|
|
9357
|
-
return path25.join(this.eventsDir, `${sanitizeSessionId(sessionId)}.jsonl`);
|
|
9358
|
-
}
|
|
9359
|
-
};
|
|
9360
|
-
function createEventId() {
|
|
9361
|
-
return `${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:.TZ]/g, "").slice(0, 14)}-${Math.random().toString(16).slice(2, 10)}`;
|
|
9362
|
-
}
|
|
9363
|
-
function sanitizeSessionId(sessionId) {
|
|
9364
|
-
return sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
9365
|
-
}
|
|
9366
|
-
|
|
9367
9039
|
// src/host/toolRegistry.ts
|
|
9368
9040
|
async function createHostToolRegistry(config, options = {}) {
|
|
9369
9041
|
const extraTools = options.extraTools ?? [];
|
|
@@ -10292,6 +9964,7 @@ export {
|
|
|
10292
9964
|
getErrorMessage,
|
|
10293
9965
|
ControlPlaneLedger,
|
|
10294
9966
|
ExecutionStore,
|
|
9967
|
+
SessionEventStore,
|
|
10295
9968
|
isProcessAlive,
|
|
10296
9969
|
terminatePid,
|
|
10297
9970
|
BackgroundExecutionStore,
|
|
@@ -10300,12 +9973,14 @@ export {
|
|
|
10300
9973
|
summarizeExecution,
|
|
10301
9974
|
summarizeExecutionSet,
|
|
10302
9975
|
EXTENSION_ENV_KEYS,
|
|
10303
|
-
SessionEventStore,
|
|
10304
9976
|
runHostTurn,
|
|
10305
9977
|
writeStdout,
|
|
10306
9978
|
writeStdoutLine,
|
|
10307
9979
|
writeStderrLine,
|
|
10308
9980
|
createRuntimeUiEvent,
|
|
9981
|
+
tryParseJson,
|
|
9982
|
+
buildToolCallDisplay,
|
|
9983
|
+
buildToolResultDisplay,
|
|
10309
9984
|
colorRuntimeUiText,
|
|
10310
9985
|
createRuntimeUiTerminalRenderer,
|
|
10311
9986
|
formatRuntimeUiEventLine
|