@jun133/kitty 0.0.5 → 0.0.6

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.5",
43
+ version: "0.0.6",
44
44
  description: "Agent",
45
45
  license: "MIT",
46
46
  keywords: [
@@ -18204,10 +18204,10 @@ var require_typescript = __commonJS({
18204
18204
  function and(f, g) {
18205
18205
  return (arg) => f(arg) && g(arg);
18206
18206
  }
18207
- function or(...fs50) {
18207
+ function or(...fs51) {
18208
18208
  return (...args) => {
18209
18209
  let lastResult;
18210
- for (const f of fs50) {
18210
+ for (const f of fs51) {
18211
18211
  lastResult = f(...args);
18212
18212
  if (lastResult) {
18213
18213
  return lastResult;
@@ -19782,7 +19782,7 @@ ${lanes.join("\n")}
19782
19782
  var tracing;
19783
19783
  var tracingEnabled;
19784
19784
  ((tracingEnabled2) => {
19785
- let fs50;
19785
+ let fs51;
19786
19786
  let traceCount = 0;
19787
19787
  let traceFd = 0;
19788
19788
  let mode;
@@ -19791,9 +19791,9 @@ ${lanes.join("\n")}
19791
19791
  const legend = [];
19792
19792
  function startTracing2(tracingMode, traceDir, configFilePath) {
19793
19793
  Debug.assert(!tracing, "Tracing already started");
19794
- if (fs50 === void 0) {
19794
+ if (fs51 === void 0) {
19795
19795
  try {
19796
- fs50 = require("fs");
19796
+ fs51 = require("fs");
19797
19797
  } catch (e) {
19798
19798
  throw new Error(`tracing requires having fs
19799
19799
  (original error: ${e.message || e})`);
@@ -19804,8 +19804,8 @@ ${lanes.join("\n")}
19804
19804
  if (legendPath === void 0) {
19805
19805
  legendPath = combinePaths(traceDir, "legend.json");
19806
19806
  }
19807
- if (!fs50.existsSync(traceDir)) {
19808
- fs50.mkdirSync(traceDir, { recursive: true });
19807
+ if (!fs51.existsSync(traceDir)) {
19808
+ fs51.mkdirSync(traceDir, { recursive: true });
19809
19809
  }
19810
19810
  const countPart = mode === "build" ? `.${process.pid}-${++traceCount}` : mode === "server" ? `.${process.pid}` : ``;
19811
19811
  const tracePath = combinePaths(traceDir, `trace${countPart}.json`);
@@ -19815,10 +19815,10 @@ ${lanes.join("\n")}
19815
19815
  tracePath,
19816
19816
  typesPath
19817
19817
  });
19818
- traceFd = fs50.openSync(tracePath, "w");
19818
+ traceFd = fs51.openSync(tracePath, "w");
19819
19819
  tracing = tracingEnabled2;
19820
19820
  const meta = { cat: "__metadata", ph: "M", ts: 1e3 * timestamp(), pid: 1, tid: 1 };
19821
- fs50.writeSync(
19821
+ fs51.writeSync(
19822
19822
  traceFd,
19823
19823
  "[\n" + [{ name: "process_name", args: { name: "tsc" }, ...meta }, { name: "thread_name", args: { name: "Main" }, ...meta }, { name: "TracingStartedInBrowser", ...meta, cat: "disabled-by-default-devtools.timeline" }].map((v) => JSON.stringify(v)).join(",\n")
19824
19824
  );
@@ -19827,10 +19827,10 @@ ${lanes.join("\n")}
19827
19827
  function stopTracing() {
19828
19828
  Debug.assert(tracing, "Tracing is not in progress");
19829
19829
  Debug.assert(!!typeCatalog.length === (mode !== "server"));
19830
- fs50.writeSync(traceFd, `
19830
+ fs51.writeSync(traceFd, `
19831
19831
  ]
19832
19832
  `);
19833
- fs50.closeSync(traceFd);
19833
+ fs51.closeSync(traceFd);
19834
19834
  tracing = void 0;
19835
19835
  if (typeCatalog.length) {
19836
19836
  dumpTypes(typeCatalog);
@@ -19902,11 +19902,11 @@ ${lanes.join("\n")}
19902
19902
  function writeEvent(eventType, phase, name, args, extras, time = 1e3 * timestamp()) {
19903
19903
  if (mode === "server" && phase === "checkTypes") return;
19904
19904
  mark("beginTracing");
19905
- fs50.writeSync(traceFd, `,
19905
+ fs51.writeSync(traceFd, `,
19906
19906
  {"pid":1,"tid":1,"ph":"${eventType}","cat":"${phase}","ts":${time},"name":"${name}"`);
19907
- if (extras) fs50.writeSync(traceFd, `,${extras}`);
19908
- if (args) fs50.writeSync(traceFd, `,"args":${JSON.stringify(args)}`);
19909
- fs50.writeSync(traceFd, `}`);
19907
+ if (extras) fs51.writeSync(traceFd, `,${extras}`);
19908
+ if (args) fs51.writeSync(traceFd, `,"args":${JSON.stringify(args)}`);
19909
+ fs51.writeSync(traceFd, `}`);
19910
19910
  mark("endTracing");
19911
19911
  measure("Tracing", "beginTracing", "endTracing");
19912
19912
  }
@@ -19928,9 +19928,9 @@ ${lanes.join("\n")}
19928
19928
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
19929
19929
  mark("beginDumpTypes");
19930
19930
  const typesPath = legend[legend.length - 1].typesPath;
19931
- const typesFd = fs50.openSync(typesPath, "w");
19931
+ const typesFd = fs51.openSync(typesPath, "w");
19932
19932
  const recursionIdentityMap = /* @__PURE__ */ new Map();
19933
- fs50.writeSync(typesFd, "[");
19933
+ fs51.writeSync(typesFd, "[");
19934
19934
  const numTypes = types.length;
19935
19935
  for (let i = 0; i < numTypes; i++) {
19936
19936
  const type = types[i];
@@ -20026,13 +20026,13 @@ ${lanes.join("\n")}
20026
20026
  flags: Debug.formatTypeFlags(type.flags).split("|"),
20027
20027
  display
20028
20028
  };
20029
- fs50.writeSync(typesFd, JSON.stringify(descriptor));
20029
+ fs51.writeSync(typesFd, JSON.stringify(descriptor));
20030
20030
  if (i < numTypes - 1) {
20031
- fs50.writeSync(typesFd, ",\n");
20031
+ fs51.writeSync(typesFd, ",\n");
20032
20032
  }
20033
20033
  }
20034
- fs50.writeSync(typesFd, "]\n");
20035
- fs50.closeSync(typesFd);
20034
+ fs51.writeSync(typesFd, "]\n");
20035
+ fs51.closeSync(typesFd);
20036
20036
  mark("endDumpTypes");
20037
20037
  measure("Dump types", "beginDumpTypes", "endDumpTypes");
20038
20038
  }
@@ -20040,7 +20040,7 @@ ${lanes.join("\n")}
20040
20040
  if (!legendPath) {
20041
20041
  return;
20042
20042
  }
20043
- fs50.writeFileSync(legendPath, JSON.stringify(legend));
20043
+ fs51.writeFileSync(legendPath, JSON.stringify(legend));
20044
20044
  }
20045
20045
  tracingEnabled2.dumpLegend = dumpLegend;
20046
20046
  })(tracingEnabled || (tracingEnabled = {}));
@@ -226117,6 +226117,80 @@ var init_write = __esm({
226117
226117
  }
226118
226118
  });
226119
226119
 
226120
+ // src/tools/sendFile.ts
226121
+ var import_promises34, sendFileToolDefinition;
226122
+ var init_sendFile = __esm({
226123
+ "src/tools/sendFile.ts"() {
226124
+ "use strict";
226125
+ import_promises34 = __toESM(require("fs/promises"));
226126
+ init_shared2();
226127
+ sendFileToolDefinition = {
226128
+ definition: {
226129
+ type: "function",
226130
+ function: {
226131
+ name: "send_file",
226132
+ description: "Send a local file back to the conversation. Only available when the host supports file delivery (e.g. Telegram). In CLI mode this tool returns an error.",
226133
+ parameters: {
226134
+ type: "object",
226135
+ properties: {
226136
+ filePath: {
226137
+ type: "string",
226138
+ description: "Absolute or relative path to the local file to send."
226139
+ },
226140
+ fileName: {
226141
+ type: "string",
226142
+ description: "Optional display file name. Defaults to the basename of the file path."
226143
+ },
226144
+ caption: {
226145
+ type: "string",
226146
+ description: "Optional caption attached to the file."
226147
+ }
226148
+ },
226149
+ required: ["filePath"],
226150
+ additionalProperties: false
226151
+ }
226152
+ }
226153
+ },
226154
+ async execute(rawArgs, context) {
226155
+ const args = parseArgs(rawArgs);
226156
+ const filePath = readString(args.filePath, "filePath");
226157
+ const fileName = typeof args.fileName === "string" ? args.fileName : void 0;
226158
+ const caption = typeof args.caption === "string" ? args.caption : void 0;
226159
+ if (!context.enqueueFile) {
226160
+ return {
226161
+ ok: false,
226162
+ output: JSON.stringify({
226163
+ ok: false,
226164
+ error: "send_file tool is only available when the host supports file delivery (Telegram mode). The current host does not provide file delivery capability."
226165
+ })
226166
+ };
226167
+ }
226168
+ try {
226169
+ await import_promises34.default.access(filePath);
226170
+ } catch {
226171
+ return {
226172
+ ok: false,
226173
+ output: JSON.stringify({
226174
+ ok: false,
226175
+ error: `File not found: ${filePath}`
226176
+ })
226177
+ };
226178
+ }
226179
+ const entryId = await context.enqueueFile(filePath, fileName, caption);
226180
+ return okResult(
226181
+ JSON.stringify({
226182
+ ok: true,
226183
+ filePath,
226184
+ fileName: fileName ?? filePath.split(/[/\\]/).pop(),
226185
+ caption,
226186
+ entryId
226187
+ })
226188
+ );
226189
+ }
226190
+ };
226191
+ }
226192
+ });
226193
+
226120
226194
  // src/tools/toolCatalog.ts
226121
226195
  function getBuiltinTools() {
226122
226196
  return agentCoreToolCatalog;
@@ -226143,7 +226217,8 @@ var init_toolCatalog = __esm({
226143
226217
  withChangeSignal(readToolDefinition, "none"),
226144
226218
  withChangeSignal(writeToolDefinition, "required"),
226145
226219
  withChangeSignal(editToolDefinition, "required"),
226146
- withChangeSignal(bashToolDefinition, "none")
226220
+ withChangeSignal(bashToolDefinition, "none"),
226221
+ withChangeSignal(sendFileToolDefinition, "none")
226147
226222
  ];
226148
226223
  }
226149
226224
  });
@@ -226574,6 +226649,7 @@ var init_tools = __esm({
226574
226649
  init_edit();
226575
226650
  init_read();
226576
226651
  init_write();
226652
+ init_sendFile();
226577
226653
  init_registry2();
226578
226654
  init_runtimeRegistry();
226579
226655
  }
@@ -226598,6 +226674,7 @@ async function executeToolCallWithRecovery(toolRegistry, toolCall, options, sess
226598
226674
  projectContext,
226599
226675
  changeStore,
226600
226676
  createToolRegistry,
226677
+ enqueueFile: options.callbacks?.enqueueFile,
226601
226678
  recordWorksetFile: async (input) => {
226602
226679
  const nextSession = recordSessionWorksetFile(session, {
226603
226680
  cwd: options.cwd,
@@ -226904,12 +226981,12 @@ function createChangeId() {
226904
226981
  const random = import_node_crypto4.default.randomUUID().slice(0, 8);
226905
226982
  return `${date}-${random}`;
226906
226983
  }
226907
- var import_node_crypto4, import_promises34, import_node_path49, ChangeStore;
226984
+ var import_node_crypto4, import_promises35, import_node_path49, ChangeStore;
226908
226985
  var init_store6 = __esm({
226909
226986
  "src/agent/changes/store.ts"() {
226910
226987
  "use strict";
226911
226988
  import_node_crypto4 = __toESM(require("crypto"));
226912
- import_promises34 = __toESM(require("fs/promises"));
226989
+ import_promises35 = __toESM(require("fs/promises"));
226913
226990
  import_node_path49 = __toESM(require("path"));
226914
226991
  ChangeStore = class {
226915
226992
  constructor(changesDir) {
@@ -226919,7 +226996,7 @@ var init_store6 = __esm({
226919
226996
  const id = createChangeId();
226920
226997
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
226921
226998
  const blobDir = import_node_path49.default.join(this.changesDir, id);
226922
- await import_promises34.default.mkdir(blobDir, { recursive: true });
226999
+ await import_promises35.default.mkdir(blobDir, { recursive: true });
226923
227000
  const operations = await Promise.all(
226924
227001
  input.operations.map(async (operation, index) => {
226925
227002
  const beforeSnapshotPath = await this.writeSnapshot(
@@ -226959,21 +227036,21 @@ var init_store6 = __esm({
226959
227036
  preview: input.preview,
226960
227037
  operations
226961
227038
  };
226962
- await import_promises34.default.mkdir(this.changesDir, { recursive: true });
226963
- await import_promises34.default.writeFile(this.getMetadataPath(id), `${JSON.stringify(record, null, 2)}
227039
+ await import_promises35.default.mkdir(this.changesDir, { recursive: true });
227040
+ await import_promises35.default.writeFile(this.getMetadataPath(id), `${JSON.stringify(record, null, 2)}
226964
227041
  `, "utf8");
226965
227042
  return record;
226966
227043
  }
226967
227044
  async list(limit = 20) {
226968
- await import_promises34.default.mkdir(this.changesDir, { recursive: true });
226969
- const entries = await import_promises34.default.readdir(this.changesDir, { withFileTypes: true });
227045
+ await import_promises35.default.mkdir(this.changesDir, { recursive: true });
227046
+ const entries = await import_promises35.default.readdir(this.changesDir, { withFileTypes: true });
226970
227047
  const changes = await Promise.all(
226971
227048
  entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => this.load(import_node_path49.default.basename(entry.name, ".json")))
226972
227049
  );
226973
227050
  return changes.sort((left, right) => right.createdAt.localeCompare(left.createdAt)).slice(0, limit);
226974
227051
  }
226975
227052
  async load(id) {
226976
- const raw = await import_promises34.default.readFile(this.getMetadataPath(id), "utf8");
227053
+ const raw = await import_promises35.default.readFile(this.getMetadataPath(id), "utf8");
226977
227054
  return JSON.parse(raw);
226978
227055
  }
226979
227056
  async loadLatestUndoable() {
@@ -226997,17 +227074,17 @@ var init_store6 = __esm({
226997
227074
  restoredPaths.push(operation.path);
226998
227075
  if (operation.beforeSnapshotPath) {
226999
227076
  const buffer = await this.readSnapshot(operation.beforeSnapshotPath);
227000
- await import_promises34.default.mkdir(import_node_path49.default.dirname(operation.path), { recursive: true });
227001
- await import_promises34.default.writeFile(operation.path, buffer);
227077
+ await import_promises35.default.mkdir(import_node_path49.default.dirname(operation.path), { recursive: true });
227078
+ await import_promises35.default.writeFile(operation.path, buffer);
227002
227079
  continue;
227003
227080
  }
227004
- await import_promises34.default.rm(operation.path, { force: true });
227081
+ await import_promises35.default.rm(operation.path, { force: true });
227005
227082
  }
227006
227083
  const updated = {
227007
227084
  ...record,
227008
227085
  undoneAt: (/* @__PURE__ */ new Date()).toISOString()
227009
227086
  };
227010
- await import_promises34.default.writeFile(this.getMetadataPath(updated.id), `${JSON.stringify(updated, null, 2)}
227087
+ await import_promises35.default.writeFile(this.getMetadataPath(updated.id), `${JSON.stringify(updated, null, 2)}
227011
227088
  `, "utf8");
227012
227089
  return {
227013
227090
  record: updated,
@@ -227023,11 +227100,11 @@ var init_store6 = __esm({
227023
227100
  }
227024
227101
  const fileName = `${label}.bin`;
227025
227102
  const absolutePath = import_node_path49.default.join(blobDir, fileName);
227026
- await import_promises34.default.writeFile(absolutePath, buffer);
227103
+ await import_promises35.default.writeFile(absolutePath, buffer);
227027
227104
  return import_node_path49.default.relative(this.changesDir, absolutePath);
227028
227105
  }
227029
227106
  async readSnapshot(relativePath) {
227030
- return import_promises34.default.readFile(import_node_path49.default.join(this.changesDir, relativePath));
227107
+ return import_promises35.default.readFile(import_node_path49.default.join(this.changesDir, relativePath));
227031
227108
  }
227032
227109
  };
227033
227110
  }
@@ -227453,11 +227530,11 @@ function createEventId() {
227453
227530
  function sanitizeSessionId2(sessionId) {
227454
227531
  return sessionId.replace(/[^a-zA-Z0-9_.-]/g, "_");
227455
227532
  }
227456
- var import_promises35, import_node_path51, SessionEventStore;
227533
+ var import_promises36, import_node_path51, SessionEventStore;
227457
227534
  var init_events = __esm({
227458
227535
  "src/session/events.ts"() {
227459
227536
  "use strict";
227460
- import_promises35 = __toESM(require("fs/promises"));
227537
+ import_promises36 = __toESM(require("fs/promises"));
227461
227538
  import_node_path51 = __toESM(require("path"));
227462
227539
  SessionEventStore = class {
227463
227540
  constructor(eventsDir) {
@@ -227474,8 +227551,8 @@ var init_events = __esm({
227474
227551
  message: event.message,
227475
227552
  details: event.details
227476
227553
  };
227477
- await import_promises35.default.mkdir(this.eventsDir, { recursive: true });
227478
- await import_promises35.default.appendFile(this.getSessionEventPath(event.sessionId), `${JSON.stringify(record)}
227554
+ await import_promises36.default.mkdir(this.eventsDir, { recursive: true });
227555
+ await import_promises36.default.appendFile(this.getSessionEventPath(event.sessionId), `${JSON.stringify(record)}
227479
227556
  `, "utf8");
227480
227557
  return record;
227481
227558
  }
@@ -227483,7 +227560,7 @@ var init_events = __esm({
227483
227560
  const filePath = this.getSessionEventPath(sessionId);
227484
227561
  let raw = "";
227485
227562
  try {
227486
- raw = await import_promises35.default.readFile(filePath, "utf8");
227563
+ raw = await import_promises36.default.readFile(filePath, "utf8");
227487
227564
  } catch (error) {
227488
227565
  if (error.code === "ENOENT") {
227489
227566
  return [];
@@ -227746,9 +227823,9 @@ var init_turn2 = __esm({
227746
227823
  // src/evaluation/golden.ts
227747
227824
  async function runGoldenEvaluationScenario(rootDir, id) {
227748
227825
  const workspace = import_node_path52.default.join(rootDir, ".kitty", "eval-workspaces", id);
227749
- await import_promises36.default.rm(workspace, { recursive: true, force: true });
227750
- await import_promises36.default.mkdir(workspace, { recursive: true });
227751
- await import_promises36.default.writeFile(import_node_path52.default.join(workspace, "golden.txt"), "before\n", "utf8");
227826
+ await import_promises37.default.rm(workspace, { recursive: true, force: true });
227827
+ await import_promises37.default.mkdir(workspace, { recursive: true });
227828
+ await import_promises37.default.writeFile(import_node_path52.default.join(workspace, "golden.txt"), "before\n", "utf8");
227752
227829
  const initial = getInitialRuntimeConfig();
227753
227830
  const config = {
227754
227831
  ...initial,
@@ -227876,11 +227953,11 @@ function buildGoldenWorksetCheck(id, session) {
227876
227953
  fact: file ? `workset golden.txt read=${file.readCount} changed=${file.changedCount} change=${file.lastChangeId ?? "none"}` : "workset golden.txt absent"
227877
227954
  };
227878
227955
  }
227879
- var import_promises36, import_node_path52;
227956
+ var import_promises37, import_node_path52;
227880
227957
  var init_golden = __esm({
227881
227958
  "src/evaluation/golden.ts"() {
227882
227959
  "use strict";
227883
- import_promises36 = __toESM(require("fs/promises"));
227960
+ import_promises37 = __toESM(require("fs/promises"));
227884
227961
  import_node_path52 = __toESM(require("path"));
227885
227962
  init_turn();
227886
227963
  init_hosts();
@@ -228280,7 +228357,7 @@ function resolveSessionPickerIo(io) {
228280
228357
  };
228281
228358
  }
228282
228359
  async function readCliSessionChoice(promptLabel) {
228283
- const rl = import_promises37.default.createInterface({
228360
+ const rl = import_promises38.default.createInterface({
228284
228361
  input: import_node_process2.default.stdin,
228285
228362
  output: import_node_process2.default.stdout,
228286
228363
  terminal: true
@@ -228295,11 +228372,11 @@ async function readCliSessionChoice(promptLabel) {
228295
228372
  rl.close();
228296
228373
  }
228297
228374
  }
228298
- var import_promises37, import_node_process2, DEFAULT_SESSION_PICKER_LIMIT;
228375
+ var import_promises38, import_node_process2, DEFAULT_SESSION_PICKER_LIMIT;
228299
228376
  var init_sessionPicker = __esm({
228300
228377
  "src/cli/commands/sessionPicker.ts"() {
228301
228378
  "use strict";
228302
- import_promises37 = __toESM(require("readline/promises"));
228379
+ import_promises38 = __toESM(require("readline/promises"));
228303
228380
  import_node_process2 = __toESM(require("process"));
228304
228381
  init_stdio();
228305
228382
  init_session2();
@@ -228477,7 +228554,7 @@ async function isSameOrDescendant2(targetPath, possibleAncestor) {
228477
228554
  }
228478
228555
  async function pathExists2(targetPath) {
228479
228556
  try {
228480
- await import_promises38.default.access(targetPath);
228557
+ await import_promises39.default.access(targetPath);
228481
228558
  return true;
228482
228559
  } catch {
228483
228560
  return false;
@@ -228488,7 +228565,7 @@ async function canonicalizePathForComparison(targetPath) {
228488
228565
  const tail = [];
228489
228566
  while (true) {
228490
228567
  try {
228491
- const real = await import_promises38.default.realpath(candidate);
228568
+ const real = await import_promises39.default.realpath(candidate);
228492
228569
  return tail.length > 0 ? import_node_path53.default.join(real, ...tail.reverse()) : real;
228493
228570
  } catch (error) {
228494
228571
  if (error.code !== "ENOENT") {
@@ -228503,11 +228580,11 @@ async function canonicalizePathForComparison(targetPath) {
228503
228580
  candidate = parent;
228504
228581
  }
228505
228582
  }
228506
- var import_promises38, import_node_path53;
228583
+ var import_promises39, import_node_path53;
228507
228584
  var init_resetSupport = __esm({
228508
228585
  "src/project/resetSupport.ts"() {
228509
228586
  "use strict";
228510
- import_promises38 = __toESM(require("fs/promises"));
228587
+ import_promises39 = __toESM(require("fs/promises"));
228511
228588
  import_node_path53 = __toESM(require("path"));
228512
228589
  }
228513
228590
  });
@@ -228542,7 +228619,7 @@ async function resetProjectRuntime(input) {
228542
228619
  async function removeProjectSessions(input) {
228543
228620
  const removedIds = [];
228544
228621
  try {
228545
- const entries = await import_promises39.default.readdir(input.sessionsDir, { withFileTypes: true });
228622
+ const entries = await import_promises40.default.readdir(input.sessionsDir, { withFileTypes: true });
228546
228623
  for (const entry of entries) {
228547
228624
  if (!entry.isFile() || !entry.name.endsWith(".json")) {
228548
228625
  continue;
@@ -228552,14 +228629,14 @@ async function removeProjectSessions(input) {
228552
228629
  const removeById = input.currentSessionId === sessionId;
228553
228630
  let removeByPath = false;
228554
228631
  if (!removeById) {
228555
- const raw = await import_promises39.default.readFile(absolutePath, "utf8");
228632
+ const raw = await import_promises40.default.readFile(absolutePath, "utf8");
228556
228633
  const parsed = JSON.parse(raw);
228557
228634
  removeByPath = await isSameOrDescendant2(String(parsed.cwd ?? ""), input.stateRootDir);
228558
228635
  }
228559
228636
  if (!removeById && !removeByPath) {
228560
228637
  continue;
228561
228638
  }
228562
- await import_promises39.default.rm(absolutePath, { force: true });
228639
+ await import_promises40.default.rm(absolutePath, { force: true });
228563
228640
  removedIds.push(sessionId);
228564
228641
  }
228565
228642
  } catch (error) {
@@ -228573,21 +228650,21 @@ async function removeProjectChanges(input) {
228573
228650
  const removedIds = [];
228574
228651
  const removedSessionIds = new Set(input.removedSessionIds);
228575
228652
  try {
228576
- const entries = await import_promises39.default.readdir(input.changesDir, { withFileTypes: true });
228653
+ const entries = await import_promises40.default.readdir(input.changesDir, { withFileTypes: true });
228577
228654
  for (const entry of entries) {
228578
228655
  if (!entry.isFile() || !entry.name.endsWith(".json")) {
228579
228656
  continue;
228580
228657
  }
228581
228658
  const changeId = import_node_path54.default.basename(entry.name, ".json");
228582
228659
  const metadataPath = import_node_path54.default.join(input.changesDir, entry.name);
228583
- const raw = await import_promises39.default.readFile(metadataPath, "utf8");
228660
+ const raw = await import_promises40.default.readFile(metadataPath, "utf8");
228584
228661
  const parsed = JSON.parse(raw);
228585
228662
  const remove = typeof parsed.sessionId === "string" && removedSessionIds.has(parsed.sessionId) || await isSameOrDescendant2(String(parsed.cwd ?? ""), input.stateRootDir);
228586
228663
  if (!remove) {
228587
228664
  continue;
228588
228665
  }
228589
- await import_promises39.default.rm(metadataPath, { force: true });
228590
- await import_promises39.default.rm(import_node_path54.default.join(input.changesDir, changeId), { recursive: true, force: true }).catch(() => null);
228666
+ await import_promises40.default.rm(metadataPath, { force: true });
228667
+ await import_promises40.default.rm(import_node_path54.default.join(input.changesDir, changeId), { recursive: true, force: true }).catch(() => null);
228591
228668
  removedIds.push(changeId);
228592
228669
  }
228593
228670
  } catch (error) {
@@ -228601,14 +228678,14 @@ async function clearProjectKittyDirectory(kittyDir) {
228601
228678
  const removedEntries = [];
228602
228679
  const preservedEntries = [];
228603
228680
  try {
228604
- const entries = await import_promises39.default.readdir(kittyDir, { withFileTypes: true });
228681
+ const entries = await import_promises40.default.readdir(kittyDir, { withFileTypes: true });
228605
228682
  for (const entry of entries) {
228606
228683
  const absolutePath = import_node_path54.default.join(kittyDir, entry.name);
228607
228684
  if (PRESERVED_PROJECT_STATE_ENTRIES.has(entry.name)) {
228608
228685
  preservedEntries.push(entry.name);
228609
228686
  continue;
228610
228687
  }
228611
- await import_promises39.default.rm(absolutePath, { recursive: true, force: true });
228688
+ await import_promises40.default.rm(absolutePath, { recursive: true, force: true });
228612
228689
  removedEntries.push(entry.name);
228613
228690
  }
228614
228691
  } catch (error) {
@@ -228621,11 +228698,11 @@ async function clearProjectKittyDirectory(kittyDir) {
228621
228698
  preservedEntries
228622
228699
  };
228623
228700
  }
228624
- var import_promises39, import_node_path54, PRESERVED_PROJECT_STATE_ENTRIES;
228701
+ var import_promises40, import_node_path54, PRESERVED_PROJECT_STATE_ENTRIES;
228625
228702
  var init_reset = __esm({
228626
228703
  "src/project/reset.ts"() {
228627
228704
  "use strict";
228628
- import_promises39 = __toESM(require("fs/promises"));
228705
+ import_promises40 = __toESM(require("fs/promises"));
228629
228706
  import_node_path54 = __toESM(require("path"));
228630
228707
  init_repoRoots();
228631
228708
  init_statePaths();
@@ -231166,23 +231243,23 @@ async function initializeProjectFiles(cwd) {
231166
231243
  const ignorePath = import_node_path57.default.join(kittyDir, PROJECT_STATE_IGNORE_FILE_NAME);
231167
231244
  const envTemplate = buildProjectEnvTemplate(false);
231168
231245
  const envExampleTemplate = buildProjectEnvTemplate(true);
231169
- await import_promises40.default.mkdir(kittyDir, { recursive: true });
231246
+ await import_promises41.default.mkdir(kittyDir, { recursive: true });
231170
231247
  if (await fileExists2(envPath)) {
231171
231248
  skipped.push(envPath);
231172
231249
  } else {
231173
- await import_promises40.default.writeFile(envPath, envTemplate, "utf8");
231250
+ await import_promises41.default.writeFile(envPath, envTemplate, "utf8");
231174
231251
  created.push(envPath);
231175
231252
  }
231176
231253
  if (await fileExists2(envExamplePath)) {
231177
231254
  skipped.push(envExamplePath);
231178
231255
  } else {
231179
- await import_promises40.default.writeFile(envExamplePath, envExampleTemplate, "utf8");
231256
+ await import_promises41.default.writeFile(envExamplePath, envExampleTemplate, "utf8");
231180
231257
  created.push(envExamplePath);
231181
231258
  }
231182
231259
  if (await fileExists2(ignorePath)) {
231183
231260
  skipped.push(ignorePath);
231184
231261
  } else {
231185
- await import_promises40.default.writeFile(ignorePath, getDefaultKittyIgnoreContent(), "utf8");
231262
+ await import_promises41.default.writeFile(ignorePath, getDefaultKittyIgnoreContent(), "utf8");
231186
231263
  created.push(ignorePath);
231187
231264
  }
231188
231265
  return {
@@ -231193,17 +231270,17 @@ async function initializeProjectFiles(cwd) {
231193
231270
  }
231194
231271
  async function fileExists2(targetPath) {
231195
231272
  try {
231196
- await import_promises40.default.access(targetPath);
231273
+ await import_promises41.default.access(targetPath);
231197
231274
  return true;
231198
231275
  } catch {
231199
231276
  return false;
231200
231277
  }
231201
231278
  }
231202
- var import_promises40, import_node_path57;
231279
+ var import_promises41, import_node_path57;
231203
231280
  var init_init = __esm({
231204
231281
  "src/config/init.ts"() {
231205
231282
  "use strict";
231206
- import_promises40 = __toESM(require("fs/promises"));
231283
+ import_promises41 = __toESM(require("fs/promises"));
231207
231284
  import_node_path57 = __toESM(require("path"));
231208
231285
  init_projectEnvTemplate();
231209
231286
  init_ignore();
@@ -231827,11 +231904,11 @@ var botApiClient_exports = {};
231827
231904
  __export(botApiClient_exports, {
231828
231905
  FetchTelegramBotApiClient: () => FetchTelegramBotApiClient
231829
231906
  });
231830
- var import_promises41, import_node_path59, FetchTelegramBotApiClient;
231907
+ var import_promises42, import_node_path59, FetchTelegramBotApiClient;
231831
231908
  var init_botApiClient = __esm({
231832
231909
  "src/telegram/botApiClient.ts"() {
231833
231910
  "use strict";
231834
- import_promises41 = __toESM(require("fs/promises"));
231911
+ import_promises42 = __toESM(require("fs/promises"));
231835
231912
  import_node_path59 = __toESM(require("path"));
231836
231913
  FetchTelegramBotApiClient = class {
231837
231914
  baseUrl;
@@ -231889,7 +231966,7 @@ var init_botApiClient = __esm({
231889
231966
  }
231890
231967
  async sendDocument(request) {
231891
231968
  const fileName = request.fileName?.trim() || import_node_path59.default.basename(request.filePath);
231892
- const buffer = await import_promises41.default.readFile(request.filePath);
231969
+ const buffer = await import_promises42.default.readFile(request.filePath);
231893
231970
  const form = new FormData();
231894
231971
  form.set("chat_id", String(request.chatId));
231895
231972
  form.set("document", new Blob([buffer]), fileName);
@@ -231950,7 +232027,7 @@ var init_botApiClient = __esm({
231950
232027
  // src/telegram/storage.ts
231951
232028
  async function readJsonFile2(filePath, fallback) {
231952
232029
  try {
231953
- const raw = await import_promises42.default.readFile(filePath, "utf8");
232030
+ const raw = await import_promises43.default.readFile(filePath, "utf8");
231954
232031
  return JSON.parse(raw);
231955
232032
  } catch (error) {
231956
232033
  if (error.code === "ENOENT") {
@@ -231960,17 +232037,17 @@ async function readJsonFile2(filePath, fallback) {
231960
232037
  }
231961
232038
  }
231962
232039
  async function writeJsonFileAtomically(filePath, value) {
231963
- await import_promises42.default.mkdir(import_node_path60.default.dirname(filePath), { recursive: true });
232040
+ await import_promises43.default.mkdir(import_node_path60.default.dirname(filePath), { recursive: true });
231964
232041
  const temporaryPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
231965
- await import_promises42.default.writeFile(temporaryPath, `${JSON.stringify(value, null, 2)}
232042
+ await import_promises43.default.writeFile(temporaryPath, `${JSON.stringify(value, null, 2)}
231966
232043
  `, "utf8");
231967
- await import_promises42.default.rename(temporaryPath, filePath);
232044
+ await import_promises43.default.rename(temporaryPath, filePath);
231968
232045
  }
231969
- var import_promises42, import_node_path60;
232046
+ var import_promises43, import_node_path60;
231970
232047
  var init_storage = __esm({
231971
232048
  "src/telegram/storage.ts"() {
231972
232049
  "use strict";
231973
- import_promises42 = __toESM(require("fs/promises"));
232050
+ import_promises43 = __toESM(require("fs/promises"));
231974
232051
  import_node_path60 = __toESM(require("path"));
231975
232052
  }
231976
232053
  });
@@ -232609,10 +232686,10 @@ async function downloadTelegramAttachment(options) {
232609
232686
  );
232610
232687
  }
232611
232688
  const filesDir = import_node_path61.default.join(options.config.stateDir, "files", sanitizePathSegment(options.message.peerKey));
232612
- await import_promises43.default.mkdir(filesDir, { recursive: true });
232689
+ await import_promises44.default.mkdir(filesDir, { recursive: true });
232613
232690
  const safeFileName = sanitizeFileName(options.message.fileName ?? `${options.message.fileUniqueId}.bin`);
232614
232691
  const localFilePath = import_node_path61.default.join(filesDir, `${String(options.message.updateId).padStart(8, "0")}-${safeFileName}`);
232615
- await import_promises43.default.writeFile(localFilePath, download);
232692
+ await import_promises44.default.writeFile(localFilePath, download);
232616
232693
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
232617
232694
  const record = {
232618
232695
  id: `${options.message.peerKey}:${options.message.messageId}:${options.message.fileUniqueId}`,
@@ -232698,11 +232775,11 @@ function readConfiguredDownloadLimit(config) {
232698
232775
  }
232699
232776
  return DEFAULT_MAX_DOWNLOAD_BYTES;
232700
232777
  }
232701
- var import_promises43, import_node_path61, DEFAULT_MAX_DOWNLOAD_BYTES;
232778
+ var import_promises44, import_node_path61, DEFAULT_MAX_DOWNLOAD_BYTES;
232702
232779
  var init_inboundFiles = __esm({
232703
232780
  "src/telegram/inboundFiles.ts"() {
232704
232781
  "use strict";
232705
- import_promises43 = __toESM(require("fs/promises"));
232782
+ import_promises44 = __toESM(require("fs/promises"));
232706
232783
  import_node_path61 = __toESM(require("path"));
232707
232784
  DEFAULT_MAX_DOWNLOAD_BYTES = 45 * 1024 * 1024;
232708
232785
  }
@@ -233086,9 +233163,10 @@ var init_turnDisplay2 = __esm({
233086
233163
  });
233087
233164
 
233088
233165
  // src/telegram/turnLogging.ts
233089
- function createLoggedTelegramCallbacks(display, logger, context) {
233166
+ function createLoggedTelegramCallbacks(display, logger, context, enqueueFile) {
233090
233167
  return {
233091
233168
  ...display.callbacks,
233169
+ enqueueFile,
233092
233170
  onStatus: (text) => {
233093
233171
  logger.info("phase", {
233094
233172
  ...context,
@@ -233181,12 +233259,26 @@ async function runTelegramTurn(options) {
233181
233259
  enqueueVisibleMessage: async (target, text) => options.enqueueReply(target.chatId, text),
233182
233260
  typingIntervalMs: options.config.telegram.typingIntervalMs
233183
233261
  });
233184
- const callbacks = createLoggedTelegramCallbacks(display, options.logger, {
233185
- peerKey: options.message.peerKey,
233186
- userId: options.message.userId,
233187
- chatId: options.message.chatId,
233188
- sessionId: session.id
233189
- });
233262
+ const enqueueFile = async (filePath, fileName, caption) => {
233263
+ const entry = await options.deliveryQueue.enqueueFile({
233264
+ chatId: options.message.chatId,
233265
+ filePath,
233266
+ fileName,
233267
+ caption
233268
+ });
233269
+ return entry.id;
233270
+ };
233271
+ const callbacks = createLoggedTelegramCallbacks(
233272
+ display,
233273
+ options.logger,
233274
+ {
233275
+ peerKey: options.message.peerKey,
233276
+ userId: options.message.userId,
233277
+ chatId: options.message.chatId,
233278
+ sessionId: session.id
233279
+ },
233280
+ enqueueFile
233281
+ );
233190
233282
  options.logger.info("starting turn", {
233191
233283
  peerKey: options.message.peerKey,
233192
233284
  userId: options.message.userId,
@@ -233551,11 +233643,11 @@ var service_exports = {};
233551
233643
  __export(service_exports, {
233552
233644
  TelegramService: () => TelegramService
233553
233645
  });
233554
- var import_promises44, import_node_path62, TelegramService;
233646
+ var import_promises45, import_node_path62, TelegramService;
233555
233647
  var init_service = __esm({
233556
233648
  "src/telegram/service.ts"() {
233557
233649
  "use strict";
233558
- import_promises44 = __toESM(require("fs/promises"));
233650
+ import_promises45 = __toESM(require("fs/promises"));
233559
233651
  import_node_path62 = __toESM(require("path"));
233560
233652
  init_commandQueue();
233561
233653
  init_attachmentStore();
@@ -233784,7 +233876,7 @@ var init_service = __esm({
233784
233876
  await this.options.deliveryQueue.flushDue();
233785
233877
  }
233786
233878
  async ensureStateDirectory() {
233787
- await import_promises44.default.mkdir(this.options.config.telegram.stateDir, { recursive: true });
233879
+ await import_promises45.default.mkdir(this.options.config.telegram.stateDir, { recursive: true });
233788
233880
  }
233789
233881
  trackTask(task, context) {
233790
233882
  const tracked = task.catch((error) => {
@@ -233831,14 +233923,14 @@ async function acquireTelegramProcessLock(options) {
233831
233923
  const processId = options.processId ?? process.pid;
233832
233924
  const pidFilePath = import_node_path63.default.join(options.stateDir, "service.pid");
233833
233925
  const isProcessAlive2 = options.isProcessAlive ?? defaultIsProcessAlive;
233834
- await import_promises45.default.mkdir(options.stateDir, { recursive: true });
233926
+ await import_promises46.default.mkdir(options.stateDir, { recursive: true });
233835
233927
  const existingPid = await readPidFile(pidFilePath);
233836
233928
  if (existingPid && existingPid !== processId && await isProcessAlive2(existingPid)) {
233837
233929
  throw new Error(
233838
233930
  `Telegram service already running with PID ${existingPid}. Stop the existing process before starting a new one.`
233839
233931
  );
233840
233932
  }
233841
- await import_promises45.default.writeFile(pidFilePath, `${processId}
233933
+ await import_promises46.default.writeFile(pidFilePath, `${processId}
233842
233934
  `, "utf8");
233843
233935
  return {
233844
233936
  pidFilePath,
@@ -233847,13 +233939,13 @@ async function acquireTelegramProcessLock(options) {
233847
233939
  if (currentPid !== processId) {
233848
233940
  return;
233849
233941
  }
233850
- await import_promises45.default.rm(pidFilePath, { force: true });
233942
+ await import_promises46.default.rm(pidFilePath, { force: true });
233851
233943
  }
233852
233944
  };
233853
233945
  }
233854
233946
  async function readPidFile(filePath) {
233855
233947
  try {
233856
- const raw = await import_promises45.default.readFile(filePath, "utf8");
233948
+ const raw = await import_promises46.default.readFile(filePath, "utf8");
233857
233949
  const parsed = Number.parseInt(raw.trim(), 10);
233858
233950
  return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
233859
233951
  } catch (error) {
@@ -233874,11 +233966,11 @@ async function defaultIsProcessAlive(targetPid) {
233874
233966
  return false;
233875
233967
  }
233876
233968
  }
233877
- var import_promises45, import_node_path63;
233969
+ var import_promises46, import_node_path63;
233878
233970
  var init_processLock = __esm({
233879
233971
  "src/telegram/processLock.ts"() {
233880
233972
  "use strict";
233881
- import_promises45 = __toESM(require("fs/promises"));
233973
+ import_promises46 = __toESM(require("fs/promises"));
233882
233974
  import_node_path63 = __toESM(require("path"));
233883
233975
  }
233884
233976
  });