@jun133/kitty 0.0.13 → 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/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.13",
43
+ version: "0.0.14",
44
44
  description: "Agent",
45
45
  license: "MIT",
46
46
  keywords: [
@@ -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(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/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(output),
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
- const normalizedCommand = normalizeCommandForPlatform(options.command);
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 { subprocess } = await launchCommand(options.command, options.cwd, options.timeoutMs, options.abortSignal);
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: shellOutput.outputPreview,
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: shellOutput.outputChars > 0 ? shellOutput.outputPreview : readProcessOutput(error),
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
- init_platform();
4038
+ init_output();
4427
4039
  STALL_KILL_TIMEOUT_MS = 5e3;
4428
4040
  }
4429
4041
  });
@@ -14033,7 +13645,7 @@ var init_bash = __esm({
14033
13645
  const status = result.aborted ? "aborted" : result.stalled ? "stalled" : result.timedOut ? "timed_out" : result.exitCode === 0 ? "completed" : "failed";
14034
13646
  const outputGovernance = governToolOutput({
14035
13647
  toolName: "bash",
14036
- command,
13648
+ command: result.command,
14037
13649
  status,
14038
13650
  exitCode: result.exitCode,
14039
13651
  durationMs: result.durationMs,
@@ -14061,7 +13673,7 @@ var init_bash = __esm({
14061
13673
  return okResult(
14062
13674
  JSON.stringify(
14063
13675
  {
14064
- command,
13676
+ command: result.command,
14065
13677
  cwd: resolvedCwd,
14066
13678
  exitCode: result.exitCode,
14067
13679
  status,
@@ -226409,6 +226021,63 @@ var init_toolBatch = __esm({
226409
226021
  }
226410
226022
  });
226411
226023
 
226024
+ // src/session/events.ts
226025
+ var events_exports = {};
226026
+ __export(events_exports, {
226027
+ SessionEventStore: () => SessionEventStore
226028
+ });
226029
+ function createEventId() {
226030
+ return `${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:.TZ]/g, "").slice(0, 14)}-${Math.random().toString(16).slice(2, 10)}`;
226031
+ }
226032
+ function sanitizeSessionId2(sessionId) {
226033
+ return sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
226034
+ }
226035
+ var import_promises30, import_node_path42, SessionEventStore;
226036
+ var init_events = __esm({
226037
+ "src/session/events.ts"() {
226038
+ "use strict";
226039
+ import_promises30 = __toESM(require("fs/promises"));
226040
+ import_node_path42 = __toESM(require("path"));
226041
+ SessionEventStore = class {
226042
+ constructor(eventsDir) {
226043
+ this.eventsDir = eventsDir;
226044
+ }
226045
+ async append(event) {
226046
+ const record = {
226047
+ id: createEventId(),
226048
+ createdAt: event.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
226049
+ type: event.type,
226050
+ sessionId: event.sessionId,
226051
+ cwd: event.cwd,
226052
+ host: event.host,
226053
+ message: event.message,
226054
+ details: event.details
226055
+ };
226056
+ await import_promises30.default.mkdir(this.eventsDir, { recursive: true });
226057
+ await import_promises30.default.appendFile(this.getSessionEventPath(event.sessionId), `${JSON.stringify(record)}
226058
+ `, "utf8");
226059
+ return record;
226060
+ }
226061
+ async list(sessionId, limit = 100) {
226062
+ const filePath = this.getSessionEventPath(sessionId);
226063
+ let raw = "";
226064
+ try {
226065
+ raw = await import_promises30.default.readFile(filePath, "utf8");
226066
+ } catch (error) {
226067
+ if (error.code === "ENOENT") {
226068
+ return [];
226069
+ }
226070
+ throw error;
226071
+ }
226072
+ return raw.split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line)).slice(-limit);
226073
+ }
226074
+ getSessionEventPath(sessionId) {
226075
+ return import_node_path42.default.join(this.eventsDir, `${sanitizeSessionId2(sessionId)}.jsonl`);
226076
+ }
226077
+ };
226078
+ }
226079
+ });
226080
+
226412
226081
  // src/agent/turn/toolFailure.ts
226413
226082
  function readToolFailureError(output) {
226414
226083
  try {
@@ -226449,9 +226118,16 @@ async function processToolCallBatch(input) {
226449
226118
  const batchToolMessages = [];
226450
226119
  const batchModelOutputs = [];
226451
226120
  const batchChangedPaths = /* @__PURE__ */ new Set();
226121
+ const sessionEvents = new SessionEventStore(options.config.paths.eventsDir);
226452
226122
  const leadWaitExecutionsBefore = identity.kind === "lead" ? listLeadWaitExecutions(projectContext.stateRootDir) : [];
226453
226123
  for (const toolCall of response.toolCalls) {
226454
226124
  throwIfAborted(options.abortSignal, "Turn aborted by user.");
226125
+ await sessionEvents.append({
226126
+ type: "tool.started",
226127
+ sessionId: session.id,
226128
+ cwd: options.cwd,
226129
+ details: buildToolStartedEventDetails(toolCall, identity)
226130
+ });
226455
226131
  options.callbacks?.onToolCall?.(toolCall.function.name, toolCall.function.arguments);
226456
226132
  await recordObservabilityEvent(projectContext.stateRootDir, {
226457
226133
  event: "tool.execution",
@@ -226485,6 +226161,7 @@ async function processToolCallBatch(input) {
226485
226161
  } else if (metadata?.sessionDiff) {
226486
226162
  session = await options.sessionStore.save(noteSessionDiff(session, metadata.sessionDiff));
226487
226163
  }
226164
+ const failureError = result.ok ? void 0 : readToolFailureError(result.output);
226488
226165
  await recordObservabilityEvent(projectContext.stateRootDir, {
226489
226166
  event: "tool.execution",
226490
226167
  status: result.ok ? "completed" : "failed",
@@ -226493,11 +226170,23 @@ async function processToolCallBatch(input) {
226493
226170
  identityName: identity.name,
226494
226171
  toolName: toolCall.function.name,
226495
226172
  durationMs,
226496
- error: result.ok ? void 0 : readToolFailureError(result.output),
226173
+ error: failureError,
226497
226174
  details: {
226498
226175
  changedPathCount: metadata?.changedPaths?.length ?? 0
226499
226176
  }
226500
226177
  });
226178
+ await sessionEvents.append({
226179
+ type: result.ok ? "tool.completed" : "tool.failed",
226180
+ sessionId: session.id,
226181
+ cwd: options.cwd,
226182
+ details: buildToolFinishedEventDetails({
226183
+ toolCall,
226184
+ identity,
226185
+ durationMs,
226186
+ changedPathCount: metadata?.changedPaths?.length ?? 0,
226187
+ error: failureError ? formatToolFailureError(failureError) : void 0
226188
+ })
226189
+ });
226501
226190
  if (metadata?.outputGovernance) {
226502
226191
  await recordObservabilityEvent(projectContext.stateRootDir, {
226503
226192
  event: "tool.output",
@@ -226591,6 +226280,33 @@ async function processToolCallBatch(input) {
226591
226280
  }
226592
226281
  };
226593
226282
  }
226283
+ function buildToolStartedEventDetails(toolCall, identity) {
226284
+ return {
226285
+ toolName: toolCall.function.name,
226286
+ toolCallId: toolCall.id,
226287
+ identityKind: identity.kind,
226288
+ identityName: identity.name,
226289
+ argumentsPreview: previewToolArguments(toolCall.function.arguments)
226290
+ };
226291
+ }
226292
+ function buildToolFinishedEventDetails(input) {
226293
+ return {
226294
+ toolName: input.toolCall.function.name,
226295
+ toolCallId: input.toolCall.id,
226296
+ identityKind: input.identity.kind,
226297
+ identityName: input.identity.name,
226298
+ durationMs: input.durationMs,
226299
+ changedPathCount: input.changedPathCount,
226300
+ error: input.error
226301
+ };
226302
+ }
226303
+ function previewToolArguments(rawArgs) {
226304
+ const normalized = rawArgs.replace(/\s+/g, " ").trim();
226305
+ return normalized.length > 240 ? `${normalized.slice(0, 237)}...` : normalized;
226306
+ }
226307
+ function formatToolFailureError(error) {
226308
+ return error.code ? `${error.code}: ${error.message}` : error.message;
226309
+ }
226594
226310
  var init_toolBatchLifecycle = __esm({
226595
226311
  "src/agent/turn/toolBatchLifecycle.ts"() {
226596
226312
  "use strict";
@@ -226603,6 +226319,7 @@ var init_toolBatchLifecycle = __esm({
226603
226319
  init_persistence();
226604
226320
  init_toolBatch();
226605
226321
  init_writer();
226322
+ init_events();
226606
226323
  init_abort();
226607
226324
  init_toolFailure();
226608
226325
  }
@@ -226718,13 +226435,13 @@ function createChangeId() {
226718
226435
  const random = import_node_crypto4.default.randomUUID().slice(0, 8);
226719
226436
  return `${date}-${random}`;
226720
226437
  }
226721
- var import_node_crypto4, import_promises30, import_node_path42, ChangeStore;
226438
+ var import_node_crypto4, import_promises31, import_node_path43, ChangeStore;
226722
226439
  var init_store5 = __esm({
226723
226440
  "src/agent/changes/store.ts"() {
226724
226441
  "use strict";
226725
226442
  import_node_crypto4 = __toESM(require("crypto"));
226726
- import_promises30 = __toESM(require("fs/promises"));
226727
- import_node_path42 = __toESM(require("path"));
226443
+ import_promises31 = __toESM(require("fs/promises"));
226444
+ import_node_path43 = __toESM(require("path"));
226728
226445
  ChangeStore = class {
226729
226446
  constructor(changesDir) {
226730
226447
  this.changesDir = changesDir;
@@ -226732,8 +226449,8 @@ var init_store5 = __esm({
226732
226449
  async record(input) {
226733
226450
  const id = createChangeId();
226734
226451
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
226735
- const blobDir = import_node_path42.default.join(this.changesDir, id);
226736
- await import_promises30.default.mkdir(blobDir, { recursive: true });
226452
+ const blobDir = import_node_path43.default.join(this.changesDir, id);
226453
+ await import_promises31.default.mkdir(blobDir, { recursive: true });
226737
226454
  const operations = await Promise.all(
226738
226455
  input.operations.map(async (operation, index) => {
226739
226456
  const beforeSnapshotPath = await this.writeSnapshot(
@@ -226773,21 +226490,21 @@ var init_store5 = __esm({
226773
226490
  preview: input.preview,
226774
226491
  operations
226775
226492
  };
226776
- await import_promises30.default.mkdir(this.changesDir, { recursive: true });
226777
- await import_promises30.default.writeFile(this.getMetadataPath(id), `${JSON.stringify(record, null, 2)}
226493
+ await import_promises31.default.mkdir(this.changesDir, { recursive: true });
226494
+ await import_promises31.default.writeFile(this.getMetadataPath(id), `${JSON.stringify(record, null, 2)}
226778
226495
  `, "utf8");
226779
226496
  return record;
226780
226497
  }
226781
226498
  async list(limit = 20) {
226782
- await import_promises30.default.mkdir(this.changesDir, { recursive: true });
226783
- const entries = await import_promises30.default.readdir(this.changesDir, { withFileTypes: true });
226499
+ await import_promises31.default.mkdir(this.changesDir, { recursive: true });
226500
+ const entries = await import_promises31.default.readdir(this.changesDir, { withFileTypes: true });
226784
226501
  const changes = await Promise.all(
226785
- entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => this.load(import_node_path42.default.basename(entry.name, ".json")))
226502
+ entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => this.load(import_node_path43.default.basename(entry.name, ".json")))
226786
226503
  );
226787
226504
  return changes.sort((left, right) => right.createdAt.localeCompare(left.createdAt)).slice(0, limit);
226788
226505
  }
226789
226506
  async load(id) {
226790
- const raw = await import_promises30.default.readFile(this.getMetadataPath(id), "utf8");
226507
+ const raw = await import_promises31.default.readFile(this.getMetadataPath(id), "utf8");
226791
226508
  return JSON.parse(raw);
226792
226509
  }
226793
226510
  async loadLatestUndoable() {
@@ -226811,17 +226528,17 @@ var init_store5 = __esm({
226811
226528
  restoredPaths.push(operation.path);
226812
226529
  if (operation.beforeSnapshotPath) {
226813
226530
  const buffer = await this.readSnapshot(operation.beforeSnapshotPath);
226814
- await import_promises30.default.mkdir(import_node_path42.default.dirname(operation.path), { recursive: true });
226815
- await import_promises30.default.writeFile(operation.path, buffer);
226531
+ await import_promises31.default.mkdir(import_node_path43.default.dirname(operation.path), { recursive: true });
226532
+ await import_promises31.default.writeFile(operation.path, buffer);
226816
226533
  continue;
226817
226534
  }
226818
- await import_promises30.default.rm(operation.path, { force: true });
226535
+ await import_promises31.default.rm(operation.path, { force: true });
226819
226536
  }
226820
226537
  const updated = {
226821
226538
  ...record,
226822
226539
  undoneAt: (/* @__PURE__ */ new Date()).toISOString()
226823
226540
  };
226824
- await import_promises30.default.writeFile(this.getMetadataPath(updated.id), `${JSON.stringify(updated, null, 2)}
226541
+ await import_promises31.default.writeFile(this.getMetadataPath(updated.id), `${JSON.stringify(updated, null, 2)}
226825
226542
  `, "utf8");
226826
226543
  return {
226827
226544
  record: updated,
@@ -226829,19 +226546,19 @@ var init_store5 = __esm({
226829
226546
  };
226830
226547
  }
226831
226548
  getMetadataPath(id) {
226832
- return import_node_path42.default.join(this.changesDir, `${id}.json`);
226549
+ return import_node_path43.default.join(this.changesDir, `${id}.json`);
226833
226550
  }
226834
226551
  async writeSnapshot(blobDir, label, buffer) {
226835
226552
  if (!buffer) {
226836
226553
  return void 0;
226837
226554
  }
226838
226555
  const fileName = `${label}.bin`;
226839
- const absolutePath = import_node_path42.default.join(blobDir, fileName);
226840
- await import_promises30.default.writeFile(absolutePath, buffer);
226841
- return import_node_path42.default.relative(this.changesDir, absolutePath);
226556
+ const absolutePath = import_node_path43.default.join(blobDir, fileName);
226557
+ await import_promises31.default.writeFile(absolutePath, buffer);
226558
+ return import_node_path43.default.relative(this.changesDir, absolutePath);
226842
226559
  }
226843
226560
  async readSnapshot(relativePath) {
226844
- return import_promises30.default.readFile(import_node_path42.default.join(this.changesDir, relativePath));
226561
+ return import_promises31.default.readFile(import_node_path43.default.join(this.changesDir, relativePath));
226845
226562
  }
226846
226563
  };
226847
226564
  }
@@ -227233,14 +226950,14 @@ async function recordHostTurnFinished(rootDir, input) {
227233
226950
  });
227234
226951
  }
227235
226952
  function resolveHostStateRoot(stateDir, fallbackCwd) {
227236
- const kittyDir = import_node_path43.default.dirname(stateDir);
227237
- return import_node_path43.default.basename(kittyDir).toLowerCase() === PROJECT_STATE_DIR_NAME ? import_node_path43.default.dirname(kittyDir) : fallbackCwd;
226953
+ const kittyDir = import_node_path44.default.dirname(stateDir);
226954
+ return import_node_path44.default.basename(kittyDir).toLowerCase() === PROJECT_STATE_DIR_NAME ? import_node_path44.default.dirname(kittyDir) : fallbackCwd;
227238
226955
  }
227239
- var import_node_path43, QueuedHostMessageRecorder;
226956
+ var import_node_path44, QueuedHostMessageRecorder;
227240
226957
  var init_hostEvents = __esm({
227241
226958
  "src/observability/hostEvents.ts"() {
227242
226959
  "use strict";
227243
- import_node_path43 = __toESM(require("path"));
226960
+ import_node_path44 = __toESM(require("path"));
227244
226961
  init_writer();
227245
226962
  init_statePaths();
227246
226963
  QueuedHostMessageRecorder = class {
@@ -227270,63 +226987,6 @@ var init_hostEvents = __esm({
227270
226987
  }
227271
226988
  });
227272
226989
 
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
226990
  // src/host/toolRegistry.ts
227331
226991
  async function createHostToolRegistry(config, options = {}) {
227332
226992
  const extraTools = options.extraTools ?? [];
@@ -231040,7 +230700,7 @@ function createCliOutputPort() {
231040
230700
  }
231041
230701
  };
231042
230702
  }
231043
- var init_output = __esm({
230703
+ var init_output2 = __esm({
231044
230704
  "src/shell/cli/output.ts"() {
231045
230705
  "use strict";
231046
230706
  init_console();
@@ -231387,7 +231047,7 @@ function createCliInteractionShell() {
231387
231047
  var init_shell = __esm({
231388
231048
  "src/shell/cli/shell.ts"() {
231389
231049
  "use strict";
231390
- init_output();
231050
+ init_output2();
231391
231051
  init_readlineInput();
231392
231052
  init_turnDisplay();
231393
231053
  }
@@ -231641,6 +231301,9 @@ function formatSessionEventsForCli(result) {
231641
231301
  return result.events.map(formatSessionEventForCli).join("\n");
231642
231302
  }
231643
231303
  function formatSessionEventForCli(event) {
231304
+ if (isToolEvent(event)) {
231305
+ return formatToolEventForCli(event);
231306
+ }
231644
231307
  const parts = [
231645
231308
  event.createdAt,
231646
231309
  event.type,
@@ -231650,10 +231313,39 @@ function formatSessionEventForCli(event) {
231650
231313
  ];
231651
231314
  return parts.filter(Boolean).join(" ");
231652
231315
  }
231316
+ function formatToolEventForCli(event) {
231317
+ const details = event.details ?? {};
231318
+ const toolName = readString7(details.toolName);
231319
+ const toolCallId = readString7(details.toolCallId);
231320
+ const durationMs = readNumber3(details.durationMs);
231321
+ const changedPathCount = readNumber3(details.changedPathCount);
231322
+ const error = readString7(details.error);
231323
+ const parts = [
231324
+ event.createdAt,
231325
+ event.type,
231326
+ toolName ? `tool=${toolName}` : void 0,
231327
+ toolCallId ? `call=${toolCallId}` : void 0,
231328
+ durationMs === void 0 ? void 0 : `duration=${durationMs}ms`,
231329
+ changedPathCount === void 0 ? void 0 : `changed=${changedPathCount}`,
231330
+ error ? `error=${formatInline(error)}` : void 0,
231331
+ event.host ? `host=${event.host}` : void 0,
231332
+ event.message ? `message=${formatInline(event.message)}` : void 0
231333
+ ];
231334
+ return parts.filter(Boolean).join(" ");
231335
+ }
231336
+ function isToolEvent(event) {
231337
+ return event.type === "tool.started" || event.type === "tool.completed" || event.type === "tool.failed";
231338
+ }
231653
231339
  function formatInline(value) {
231654
231340
  const normalized = value.replace(/\s+/g, " ").trim();
231655
231341
  return normalized.length > 120 ? `${normalized.slice(0, 117)}...` : normalized;
231656
231342
  }
231343
+ function readString7(value) {
231344
+ return typeof value === "string" && value.length > 0 ? value : void 0;
231345
+ }
231346
+ function readNumber3(value) {
231347
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
231348
+ }
231657
231349
  var init_events3 = __esm({
231658
231350
  "src/cli/commands/events.ts"() {
231659
231351
  "use strict";