indusagi 0.13.8 → 0.13.10

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/index.js CHANGED
@@ -4916,7 +4916,7 @@ var ToolRegistry = class {
4916
4916
 
4917
4917
  // src/capabilities/backends/node-backends.ts
4918
4918
  import { promises as fsp } from "node:fs";
4919
- import { spawn as childSpawn } from "node:child_process";
4919
+ import { spawn as childSpawn, spawnSync } from "node:child_process";
4920
4920
  var NodeFs = class {
4921
4921
  async readFile(path2, encoding) {
4922
4922
  if (encoding === void 0) {
@@ -4976,6 +4976,21 @@ function joinChunks(chunks) {
4976
4976
  function asSignal(signal) {
4977
4977
  return signal;
4978
4978
  }
4979
+ function killProcessTree(child, signal = "SIGTERM") {
4980
+ if (child.pid === void 0) return;
4981
+ if (process.platform === "win32") {
4982
+ spawnSync("taskkill", ["/F", "/T", "/PID", String(child.pid)], {
4983
+ stdio: "ignore",
4984
+ windowsHide: true
4985
+ });
4986
+ return;
4987
+ }
4988
+ try {
4989
+ process.kill(-child.pid, signal);
4990
+ } catch {
4991
+ child.kill(signal);
4992
+ }
4993
+ }
4979
4994
  var NodeShell = class {
4980
4995
  exec(command, options) {
4981
4996
  if (typeof command !== "string" || command.length === 0) {
@@ -4986,21 +5001,30 @@ var NodeShell = class {
4986
5001
  return new Promise((resolve3, reject) => {
4987
5002
  const child = childSpawn(command, {
4988
5003
  shell: true,
5004
+ detached: process.platform !== "win32",
4989
5005
  cwd: options?.cwd,
4990
- env: options?.env ? { ...process.env, ...options.env } : process.env,
4991
- signal: options?.signal
5006
+ env: options?.env ? { ...process.env, ...options.env } : process.env
4992
5007
  });
4993
5008
  const out = [];
4994
5009
  const err = [];
4995
5010
  let settled2 = false;
4996
5011
  let timedOut = false;
5012
+ let aborted = false;
4997
5013
  let timer;
5014
+ const abortSignal = options?.signal;
5015
+ const onAbort = () => {
5016
+ aborted = true;
5017
+ killProcessTree(child);
5018
+ };
4998
5019
  const finish = (fn) => {
4999
5020
  if (settled2) return;
5000
5021
  settled2 = true;
5001
5022
  if (timer !== void 0) clearTimeout(timer);
5023
+ abortSignal?.removeEventListener("abort", onAbort);
5002
5024
  fn();
5003
5025
  };
5026
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
5027
+ if (abortSignal?.aborted) onAbort();
5004
5028
  child.stdout?.on("data", (chunk) => out.push(chunk));
5005
5029
  child.stderr?.on("data", (chunk) => err.push(chunk));
5006
5030
  if (options?.input !== void 0 && child.stdin) {
@@ -5013,7 +5037,7 @@ var NodeShell = class {
5013
5037
  if (limit !== void 0 && limit > 0) {
5014
5038
  timer = setTimeout(() => {
5015
5039
  timedOut = true;
5016
- child.kill("SIGTERM");
5040
+ killProcessTree(child);
5017
5041
  }, limit);
5018
5042
  }
5019
5043
  child.on("error", (cause) => {
@@ -5029,6 +5053,10 @@ var NodeShell = class {
5029
5053
  );
5030
5054
  return;
5031
5055
  }
5056
+ if (aborted) {
5057
+ reject(new Error("The command was aborted and stopped."));
5058
+ return;
5059
+ }
5032
5060
  resolve3({
5033
5061
  stdout: joinChunks(out),
5034
5062
  stderr: joinChunks(err),
@@ -5046,11 +5074,11 @@ var NodeShell = class {
5046
5074
  }
5047
5075
  const child = childSpawn(command, {
5048
5076
  shell: true,
5077
+ detached: process.platform !== "win32",
5049
5078
  cwd: options?.cwd,
5050
- env: options?.env ? { ...process.env, ...options.env } : process.env,
5051
- signal: options?.signal
5079
+ env: options?.env ? { ...process.env, ...options.env } : process.env
5052
5080
  });
5053
- return new NodeShellHandle(child);
5081
+ return new NodeShellHandle(child, options?.signal);
5054
5082
  }
5055
5083
  };
5056
5084
  var NodeShellHandle = class {
@@ -5059,27 +5087,33 @@ var NodeShellHandle = class {
5059
5087
  exited = false;
5060
5088
  exitCode = null;
5061
5089
  exitSignal = null;
5062
- constructor(child) {
5090
+ abortSignal;
5091
+ onAbort = () => this.kill();
5092
+ constructor(child, abortSignal) {
5063
5093
  this.child = child;
5094
+ this.abortSignal = abortSignal;
5064
5095
  child.once(
5065
5096
  "close",
5066
5097
  (code, signal) => {
5067
5098
  this.exited = true;
5068
5099
  this.exitCode = code;
5069
5100
  this.exitSignal = asSignal(signal);
5101
+ this.abortSignal?.removeEventListener("abort", this.onAbort);
5070
5102
  for (const listener of [...this.listeners]) {
5071
5103
  listener(this.exitCode, this.exitSignal);
5072
5104
  }
5073
5105
  this.listeners.clear();
5074
5106
  }
5075
5107
  );
5108
+ this.abortSignal?.addEventListener("abort", this.onAbort, { once: true });
5109
+ if (this.abortSignal?.aborted) this.onAbort();
5076
5110
  }
5077
5111
  get pid() {
5078
5112
  return this.child.pid;
5079
5113
  }
5080
5114
  kill(signal) {
5081
5115
  if (this.exited) return;
5082
- this.child.kill(signal ?? "SIGTERM");
5116
+ killProcessTree(this.child, signal);
5083
5117
  }
5084
5118
  onExit(listener) {
5085
5119
  if (this.exited) {
@@ -6513,9 +6547,6 @@ function readInput2(raw) {
6513
6547
  }
6514
6548
  return { action, command, id };
6515
6549
  }
6516
- function shellQuote(value) {
6517
- return `'${value.replace(/'/g, `'\\''`)}'`;
6518
- }
6519
6550
  async function drainCapture(ctx, path2, alreadyRead) {
6520
6551
  let full;
6521
6552
  try {
@@ -6551,7 +6582,7 @@ async function startJob(ctx, command) {
6551
6582
  await ctx.fs.mkdir(scratchDir, { recursive: true });
6552
6583
  await ctx.fs.writeFile(outPath, "", "utf8");
6553
6584
  await ctx.fs.writeFile(errPath, "", "utf8");
6554
- const wrapped = `( ${command} ) >${shellQuote(outPath)} 2>${shellQuote(errPath)}`;
6585
+ const wrapped = `( ${command} ) >${SCRATCH_DIR}/${id}.out 2>${SCRATCH_DIR}/${id}.err`;
6555
6586
  const handle = ctx.shell.spawn(wrapped, { cwd: ctx.cwd });
6556
6587
  const entry = {
6557
6588
  id,
@@ -6631,7 +6662,7 @@ async function pollJob(ctx, id) {
6631
6662
  hadNewOutput: out.fresh.length > 0 || err.fresh.length > 0
6632
6663
  });
6633
6664
  }
6634
- function stopJob(id) {
6665
+ async function stopJob(id) {
6635
6666
  const entry = table.remove(id);
6636
6667
  if (entry === void 0) {
6637
6668
  return asText2(
@@ -6639,14 +6670,24 @@ function stopJob(id) {
6639
6670
  true
6640
6671
  );
6641
6672
  }
6642
- entry.unsubscribe();
6643
6673
  const wasRunning = entry.state === "running";
6644
6674
  if (wasRunning) {
6645
- try {
6646
- entry.handle.kill();
6647
- } catch {
6648
- }
6675
+ await new Promise((resolve3) => {
6676
+ let unsubscribeExit = () => {
6677
+ };
6678
+ unsubscribeExit = entry.handle.onExit(() => {
6679
+ unsubscribeExit();
6680
+ resolve3();
6681
+ });
6682
+ try {
6683
+ entry.handle.kill();
6684
+ } catch {
6685
+ unsubscribeExit();
6686
+ resolve3();
6687
+ }
6688
+ });
6649
6689
  }
6690
+ entry.unsubscribe();
6650
6691
  return asJson({
6651
6692
  action: "stop",
6652
6693
  id: entry.id,
package/dist/interop.js CHANGED
@@ -691,7 +691,7 @@ var ToolRegistry = class {
691
691
 
692
692
  // src/capabilities/backends/node-backends.ts
693
693
  import { promises as fsp } from "node:fs";
694
- import { spawn as childSpawn } from "node:child_process";
694
+ import { spawn as childSpawn, spawnSync } from "node:child_process";
695
695
  var NodeFs = class {
696
696
  async readFile(path, encoding) {
697
697
  if (encoding === void 0) {
@@ -751,6 +751,21 @@ function joinChunks(chunks) {
751
751
  function asSignal(signal) {
752
752
  return signal;
753
753
  }
754
+ function killProcessTree(child, signal = "SIGTERM") {
755
+ if (child.pid === void 0) return;
756
+ if (process.platform === "win32") {
757
+ spawnSync("taskkill", ["/F", "/T", "/PID", String(child.pid)], {
758
+ stdio: "ignore",
759
+ windowsHide: true
760
+ });
761
+ return;
762
+ }
763
+ try {
764
+ process.kill(-child.pid, signal);
765
+ } catch {
766
+ child.kill(signal);
767
+ }
768
+ }
754
769
  var NodeShell = class {
755
770
  exec(command, options) {
756
771
  if (typeof command !== "string" || command.length === 0) {
@@ -761,21 +776,30 @@ var NodeShell = class {
761
776
  return new Promise((resolve, reject) => {
762
777
  const child = childSpawn(command, {
763
778
  shell: true,
779
+ detached: process.platform !== "win32",
764
780
  cwd: options?.cwd,
765
- env: options?.env ? { ...process.env, ...options.env } : process.env,
766
- signal: options?.signal
781
+ env: options?.env ? { ...process.env, ...options.env } : process.env
767
782
  });
768
783
  const out = [];
769
784
  const err = [];
770
785
  let settled = false;
771
786
  let timedOut = false;
787
+ let aborted = false;
772
788
  let timer;
789
+ const abortSignal = options?.signal;
790
+ const onAbort = () => {
791
+ aborted = true;
792
+ killProcessTree(child);
793
+ };
773
794
  const finish = (fn) => {
774
795
  if (settled) return;
775
796
  settled = true;
776
797
  if (timer !== void 0) clearTimeout(timer);
798
+ abortSignal?.removeEventListener("abort", onAbort);
777
799
  fn();
778
800
  };
801
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
802
+ if (abortSignal?.aborted) onAbort();
779
803
  child.stdout?.on("data", (chunk) => out.push(chunk));
780
804
  child.stderr?.on("data", (chunk) => err.push(chunk));
781
805
  if (options?.input !== void 0 && child.stdin) {
@@ -788,7 +812,7 @@ var NodeShell = class {
788
812
  if (limit !== void 0 && limit > 0) {
789
813
  timer = setTimeout(() => {
790
814
  timedOut = true;
791
- child.kill("SIGTERM");
815
+ killProcessTree(child);
792
816
  }, limit);
793
817
  }
794
818
  child.on("error", (cause) => {
@@ -804,6 +828,10 @@ var NodeShell = class {
804
828
  );
805
829
  return;
806
830
  }
831
+ if (aborted) {
832
+ reject(new Error("The command was aborted and stopped."));
833
+ return;
834
+ }
807
835
  resolve({
808
836
  stdout: joinChunks(out),
809
837
  stderr: joinChunks(err),
@@ -821,11 +849,11 @@ var NodeShell = class {
821
849
  }
822
850
  const child = childSpawn(command, {
823
851
  shell: true,
852
+ detached: process.platform !== "win32",
824
853
  cwd: options?.cwd,
825
- env: options?.env ? { ...process.env, ...options.env } : process.env,
826
- signal: options?.signal
854
+ env: options?.env ? { ...process.env, ...options.env } : process.env
827
855
  });
828
- return new NodeShellHandle(child);
856
+ return new NodeShellHandle(child, options?.signal);
829
857
  }
830
858
  };
831
859
  var NodeShellHandle = class {
@@ -834,27 +862,33 @@ var NodeShellHandle = class {
834
862
  exited = false;
835
863
  exitCode = null;
836
864
  exitSignal = null;
837
- constructor(child) {
865
+ abortSignal;
866
+ onAbort = () => this.kill();
867
+ constructor(child, abortSignal) {
838
868
  this.child = child;
869
+ this.abortSignal = abortSignal;
839
870
  child.once(
840
871
  "close",
841
872
  (code, signal) => {
842
873
  this.exited = true;
843
874
  this.exitCode = code;
844
875
  this.exitSignal = asSignal(signal);
876
+ this.abortSignal?.removeEventListener("abort", this.onAbort);
845
877
  for (const listener of [...this.listeners]) {
846
878
  listener(this.exitCode, this.exitSignal);
847
879
  }
848
880
  this.listeners.clear();
849
881
  }
850
882
  );
883
+ this.abortSignal?.addEventListener("abort", this.onAbort, { once: true });
884
+ if (this.abortSignal?.aborted) this.onAbort();
851
885
  }
852
886
  get pid() {
853
887
  return this.child.pid;
854
888
  }
855
889
  kill(signal) {
856
890
  if (this.exited) return;
857
- this.child.kill(signal ?? "SIGTERM");
891
+ killProcessTree(this.child, signal);
858
892
  }
859
893
  onExit(listener) {
860
894
  if (this.exited) {
@@ -2269,9 +2303,6 @@ function readInput2(raw) {
2269
2303
  }
2270
2304
  return { action, command, id };
2271
2305
  }
2272
- function shellQuote(value) {
2273
- return `'${value.replace(/'/g, `'\\''`)}'`;
2274
- }
2275
2306
  async function drainCapture(ctx, path, alreadyRead) {
2276
2307
  let full;
2277
2308
  try {
@@ -2307,7 +2338,7 @@ async function startJob(ctx, command) {
2307
2338
  await ctx.fs.mkdir(scratchDir, { recursive: true });
2308
2339
  await ctx.fs.writeFile(outPath, "", "utf8");
2309
2340
  await ctx.fs.writeFile(errPath, "", "utf8");
2310
- const wrapped = `( ${command} ) >${shellQuote(outPath)} 2>${shellQuote(errPath)}`;
2341
+ const wrapped = `( ${command} ) >${SCRATCH_DIR}/${id}.out 2>${SCRATCH_DIR}/${id}.err`;
2311
2342
  const handle = ctx.shell.spawn(wrapped, { cwd: ctx.cwd });
2312
2343
  const entry = {
2313
2344
  id,
@@ -2387,7 +2418,7 @@ async function pollJob(ctx, id) {
2387
2418
  hadNewOutput: out.fresh.length > 0 || err.fresh.length > 0
2388
2419
  });
2389
2420
  }
2390
- function stopJob(id) {
2421
+ async function stopJob(id) {
2391
2422
  const entry = table.remove(id);
2392
2423
  if (entry === void 0) {
2393
2424
  return asText2(
@@ -2395,14 +2426,24 @@ function stopJob(id) {
2395
2426
  true
2396
2427
  );
2397
2428
  }
2398
- entry.unsubscribe();
2399
2429
  const wasRunning = entry.state === "running";
2400
2430
  if (wasRunning) {
2401
- try {
2402
- entry.handle.kill();
2403
- } catch {
2404
- }
2431
+ await new Promise((resolve) => {
2432
+ let unsubscribeExit = () => {
2433
+ };
2434
+ unsubscribeExit = entry.handle.onExit(() => {
2435
+ unsubscribeExit();
2436
+ resolve();
2437
+ });
2438
+ try {
2439
+ entry.handle.kill();
2440
+ } catch {
2441
+ unsubscribeExit();
2442
+ resolve();
2443
+ }
2444
+ });
2405
2445
  }
2446
+ entry.unsubscribe();
2406
2447
  return asJson({
2407
2448
  action: "stop",
2408
2449
  id: entry.id,
package/dist/shell-app.js CHANGED
@@ -5033,7 +5033,7 @@ var ToolRegistry = class {
5033
5033
 
5034
5034
  // src/capabilities/backends/node-backends.ts
5035
5035
  import { promises as fsp } from "node:fs";
5036
- import { spawn as childSpawn } from "node:child_process";
5036
+ import { spawn as childSpawn, spawnSync } from "node:child_process";
5037
5037
  var NodeFs = class {
5038
5038
  async readFile(path2, encoding) {
5039
5039
  if (encoding === void 0) {
@@ -5093,6 +5093,21 @@ function joinChunks(chunks) {
5093
5093
  function asSignal(signal) {
5094
5094
  return signal;
5095
5095
  }
5096
+ function killProcessTree(child, signal = "SIGTERM") {
5097
+ if (child.pid === void 0) return;
5098
+ if (process.platform === "win32") {
5099
+ spawnSync("taskkill", ["/F", "/T", "/PID", String(child.pid)], {
5100
+ stdio: "ignore",
5101
+ windowsHide: true
5102
+ });
5103
+ return;
5104
+ }
5105
+ try {
5106
+ process.kill(-child.pid, signal);
5107
+ } catch {
5108
+ child.kill(signal);
5109
+ }
5110
+ }
5096
5111
  var NodeShell = class {
5097
5112
  exec(command, options) {
5098
5113
  if (typeof command !== "string" || command.length === 0) {
@@ -5103,21 +5118,30 @@ var NodeShell = class {
5103
5118
  return new Promise((resolve2, reject) => {
5104
5119
  const child = childSpawn(command, {
5105
5120
  shell: true,
5121
+ detached: process.platform !== "win32",
5106
5122
  cwd: options?.cwd,
5107
- env: options?.env ? { ...process.env, ...options.env } : process.env,
5108
- signal: options?.signal
5123
+ env: options?.env ? { ...process.env, ...options.env } : process.env
5109
5124
  });
5110
5125
  const out = [];
5111
5126
  const err = [];
5112
5127
  let settled2 = false;
5113
5128
  let timedOut = false;
5129
+ let aborted = false;
5114
5130
  let timer;
5131
+ const abortSignal = options?.signal;
5132
+ const onAbort = () => {
5133
+ aborted = true;
5134
+ killProcessTree(child);
5135
+ };
5115
5136
  const finish = (fn) => {
5116
5137
  if (settled2) return;
5117
5138
  settled2 = true;
5118
5139
  if (timer !== void 0) clearTimeout(timer);
5140
+ abortSignal?.removeEventListener("abort", onAbort);
5119
5141
  fn();
5120
5142
  };
5143
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
5144
+ if (abortSignal?.aborted) onAbort();
5121
5145
  child.stdout?.on("data", (chunk) => out.push(chunk));
5122
5146
  child.stderr?.on("data", (chunk) => err.push(chunk));
5123
5147
  if (options?.input !== void 0 && child.stdin) {
@@ -5130,7 +5154,7 @@ var NodeShell = class {
5130
5154
  if (limit !== void 0 && limit > 0) {
5131
5155
  timer = setTimeout(() => {
5132
5156
  timedOut = true;
5133
- child.kill("SIGTERM");
5157
+ killProcessTree(child);
5134
5158
  }, limit);
5135
5159
  }
5136
5160
  child.on("error", (cause) => {
@@ -5146,6 +5170,10 @@ var NodeShell = class {
5146
5170
  );
5147
5171
  return;
5148
5172
  }
5173
+ if (aborted) {
5174
+ reject(new Error("The command was aborted and stopped."));
5175
+ return;
5176
+ }
5149
5177
  resolve2({
5150
5178
  stdout: joinChunks(out),
5151
5179
  stderr: joinChunks(err),
@@ -5163,11 +5191,11 @@ var NodeShell = class {
5163
5191
  }
5164
5192
  const child = childSpawn(command, {
5165
5193
  shell: true,
5194
+ detached: process.platform !== "win32",
5166
5195
  cwd: options?.cwd,
5167
- env: options?.env ? { ...process.env, ...options.env } : process.env,
5168
- signal: options?.signal
5196
+ env: options?.env ? { ...process.env, ...options.env } : process.env
5169
5197
  });
5170
- return new NodeShellHandle(child);
5198
+ return new NodeShellHandle(child, options?.signal);
5171
5199
  }
5172
5200
  };
5173
5201
  var NodeShellHandle = class {
@@ -5176,27 +5204,33 @@ var NodeShellHandle = class {
5176
5204
  exited = false;
5177
5205
  exitCode = null;
5178
5206
  exitSignal = null;
5179
- constructor(child) {
5207
+ abortSignal;
5208
+ onAbort = () => this.kill();
5209
+ constructor(child, abortSignal) {
5180
5210
  this.child = child;
5211
+ this.abortSignal = abortSignal;
5181
5212
  child.once(
5182
5213
  "close",
5183
5214
  (code, signal) => {
5184
5215
  this.exited = true;
5185
5216
  this.exitCode = code;
5186
5217
  this.exitSignal = asSignal(signal);
5218
+ this.abortSignal?.removeEventListener("abort", this.onAbort);
5187
5219
  for (const listener of [...this.listeners]) {
5188
5220
  listener(this.exitCode, this.exitSignal);
5189
5221
  }
5190
5222
  this.listeners.clear();
5191
5223
  }
5192
5224
  );
5225
+ this.abortSignal?.addEventListener("abort", this.onAbort, { once: true });
5226
+ if (this.abortSignal?.aborted) this.onAbort();
5193
5227
  }
5194
5228
  get pid() {
5195
5229
  return this.child.pid;
5196
5230
  }
5197
5231
  kill(signal) {
5198
5232
  if (this.exited) return;
5199
- this.child.kill(signal ?? "SIGTERM");
5233
+ killProcessTree(this.child, signal);
5200
5234
  }
5201
5235
  onExit(listener) {
5202
5236
  if (this.exited) {
@@ -6627,9 +6661,6 @@ function readInput2(raw) {
6627
6661
  }
6628
6662
  return { action, command, id };
6629
6663
  }
6630
- function shellQuote(value) {
6631
- return `'${value.replace(/'/g, `'\\''`)}'`;
6632
- }
6633
6664
  async function drainCapture(ctx, path2, alreadyRead) {
6634
6665
  let full;
6635
6666
  try {
@@ -6665,7 +6696,7 @@ async function startJob(ctx, command) {
6665
6696
  await ctx.fs.mkdir(scratchDir, { recursive: true });
6666
6697
  await ctx.fs.writeFile(outPath, "", "utf8");
6667
6698
  await ctx.fs.writeFile(errPath, "", "utf8");
6668
- const wrapped = `( ${command} ) >${shellQuote(outPath)} 2>${shellQuote(errPath)}`;
6699
+ const wrapped = `( ${command} ) >${SCRATCH_DIR}/${id}.out 2>${SCRATCH_DIR}/${id}.err`;
6669
6700
  const handle = ctx.shell.spawn(wrapped, { cwd: ctx.cwd });
6670
6701
  const entry = {
6671
6702
  id,
@@ -6745,7 +6776,7 @@ async function pollJob(ctx, id) {
6745
6776
  hadNewOutput: out.fresh.length > 0 || err.fresh.length > 0
6746
6777
  });
6747
6778
  }
6748
- function stopJob(id) {
6779
+ async function stopJob(id) {
6749
6780
  const entry = table.remove(id);
6750
6781
  if (entry === void 0) {
6751
6782
  return asText2(
@@ -6753,14 +6784,24 @@ function stopJob(id) {
6753
6784
  true
6754
6785
  );
6755
6786
  }
6756
- entry.unsubscribe();
6757
6787
  const wasRunning = entry.state === "running";
6758
6788
  if (wasRunning) {
6759
- try {
6760
- entry.handle.kill();
6761
- } catch {
6762
- }
6789
+ await new Promise((resolve2) => {
6790
+ let unsubscribeExit = () => {
6791
+ };
6792
+ unsubscribeExit = entry.handle.onExit(() => {
6793
+ unsubscribeExit();
6794
+ resolve2();
6795
+ });
6796
+ try {
6797
+ entry.handle.kill();
6798
+ } catch {
6799
+ unsubscribeExit();
6800
+ resolve2();
6801
+ }
6802
+ });
6763
6803
  }
6804
+ entry.unsubscribe();
6764
6805
  return asJson({
6765
6806
  action: "stop",
6766
6807
  id: entry.id,