indusagi 0.13.8 → 0.13.9

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/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,
package/dist/smithy.js CHANGED
@@ -540,7 +540,7 @@ var ToolRegistry = class {
540
540
 
541
541
  // src/capabilities/backends/node-backends.ts
542
542
  import { promises as fsp } from "node:fs";
543
- import { spawn as childSpawn } from "node:child_process";
543
+ import { spawn as childSpawn, spawnSync } from "node:child_process";
544
544
  var NodeFs = class {
545
545
  async readFile(path, encoding) {
546
546
  if (encoding === void 0) {
@@ -600,6 +600,21 @@ function joinChunks(chunks) {
600
600
  function asSignal(signal) {
601
601
  return signal;
602
602
  }
603
+ function killProcessTree(child, signal = "SIGTERM") {
604
+ if (child.pid === void 0) return;
605
+ if (process.platform === "win32") {
606
+ spawnSync("taskkill", ["/F", "/T", "/PID", String(child.pid)], {
607
+ stdio: "ignore",
608
+ windowsHide: true
609
+ });
610
+ return;
611
+ }
612
+ try {
613
+ process.kill(-child.pid, signal);
614
+ } catch {
615
+ child.kill(signal);
616
+ }
617
+ }
603
618
  var NodeShell = class {
604
619
  exec(command, options) {
605
620
  if (typeof command !== "string" || command.length === 0) {
@@ -610,21 +625,30 @@ var NodeShell = class {
610
625
  return new Promise((resolve2, reject) => {
611
626
  const child = childSpawn(command, {
612
627
  shell: true,
628
+ detached: process.platform !== "win32",
613
629
  cwd: options?.cwd,
614
- env: options?.env ? { ...process.env, ...options.env } : process.env,
615
- signal: options?.signal
630
+ env: options?.env ? { ...process.env, ...options.env } : process.env
616
631
  });
617
632
  const out = [];
618
633
  const err = [];
619
634
  let settled2 = false;
620
635
  let timedOut = false;
636
+ let aborted = false;
621
637
  let timer;
638
+ const abortSignal = options?.signal;
639
+ const onAbort = () => {
640
+ aborted = true;
641
+ killProcessTree(child);
642
+ };
622
643
  const finish = (fn) => {
623
644
  if (settled2) return;
624
645
  settled2 = true;
625
646
  if (timer !== void 0) clearTimeout(timer);
647
+ abortSignal?.removeEventListener("abort", onAbort);
626
648
  fn();
627
649
  };
650
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
651
+ if (abortSignal?.aborted) onAbort();
628
652
  child.stdout?.on("data", (chunk) => out.push(chunk));
629
653
  child.stderr?.on("data", (chunk) => err.push(chunk));
630
654
  if (options?.input !== void 0 && child.stdin) {
@@ -637,7 +661,7 @@ var NodeShell = class {
637
661
  if (limit !== void 0 && limit > 0) {
638
662
  timer = setTimeout(() => {
639
663
  timedOut = true;
640
- child.kill("SIGTERM");
664
+ killProcessTree(child);
641
665
  }, limit);
642
666
  }
643
667
  child.on("error", (cause) => {
@@ -653,6 +677,10 @@ var NodeShell = class {
653
677
  );
654
678
  return;
655
679
  }
680
+ if (aborted) {
681
+ reject(new Error("The command was aborted and stopped."));
682
+ return;
683
+ }
656
684
  resolve2({
657
685
  stdout: joinChunks(out),
658
686
  stderr: joinChunks(err),
@@ -670,11 +698,11 @@ var NodeShell = class {
670
698
  }
671
699
  const child = childSpawn(command, {
672
700
  shell: true,
701
+ detached: process.platform !== "win32",
673
702
  cwd: options?.cwd,
674
- env: options?.env ? { ...process.env, ...options.env } : process.env,
675
- signal: options?.signal
703
+ env: options?.env ? { ...process.env, ...options.env } : process.env
676
704
  });
677
- return new NodeShellHandle(child);
705
+ return new NodeShellHandle(child, options?.signal);
678
706
  }
679
707
  };
680
708
  var NodeShellHandle = class {
@@ -683,27 +711,33 @@ var NodeShellHandle = class {
683
711
  exited = false;
684
712
  exitCode = null;
685
713
  exitSignal = null;
686
- constructor(child) {
714
+ abortSignal;
715
+ onAbort = () => this.kill();
716
+ constructor(child, abortSignal) {
687
717
  this.child = child;
718
+ this.abortSignal = abortSignal;
688
719
  child.once(
689
720
  "close",
690
721
  (code, signal) => {
691
722
  this.exited = true;
692
723
  this.exitCode = code;
693
724
  this.exitSignal = asSignal(signal);
725
+ this.abortSignal?.removeEventListener("abort", this.onAbort);
694
726
  for (const listener of [...this.listeners]) {
695
727
  listener(this.exitCode, this.exitSignal);
696
728
  }
697
729
  this.listeners.clear();
698
730
  }
699
731
  );
732
+ this.abortSignal?.addEventListener("abort", this.onAbort, { once: true });
733
+ if (this.abortSignal?.aborted) this.onAbort();
700
734
  }
701
735
  get pid() {
702
736
  return this.child.pid;
703
737
  }
704
738
  kill(signal) {
705
739
  if (this.exited) return;
706
- this.child.kill(signal ?? "SIGTERM");
740
+ killProcessTree(this.child, signal);
707
741
  }
708
742
  onExit(listener) {
709
743
  if (this.exited) {
@@ -2134,9 +2168,6 @@ function readInput2(raw) {
2134
2168
  }
2135
2169
  return { action, command, id };
2136
2170
  }
2137
- function shellQuote(value) {
2138
- return `'${value.replace(/'/g, `'\\''`)}'`;
2139
- }
2140
2171
  async function drainCapture(ctx, path, alreadyRead) {
2141
2172
  let full;
2142
2173
  try {
@@ -2172,7 +2203,7 @@ async function startJob(ctx, command) {
2172
2203
  await ctx.fs.mkdir(scratchDir, { recursive: true });
2173
2204
  await ctx.fs.writeFile(outPath, "", "utf8");
2174
2205
  await ctx.fs.writeFile(errPath, "", "utf8");
2175
- const wrapped = `( ${command} ) >${shellQuote(outPath)} 2>${shellQuote(errPath)}`;
2206
+ const wrapped = `( ${command} ) >${SCRATCH_DIR}/${id}.out 2>${SCRATCH_DIR}/${id}.err`;
2176
2207
  const handle = ctx.shell.spawn(wrapped, { cwd: ctx.cwd });
2177
2208
  const entry = {
2178
2209
  id,
@@ -2252,7 +2283,7 @@ async function pollJob(ctx, id) {
2252
2283
  hadNewOutput: out.fresh.length > 0 || err.fresh.length > 0
2253
2284
  });
2254
2285
  }
2255
- function stopJob(id) {
2286
+ async function stopJob(id) {
2256
2287
  const entry = table.remove(id);
2257
2288
  if (entry === void 0) {
2258
2289
  return asText2(
@@ -2260,14 +2291,24 @@ function stopJob(id) {
2260
2291
  true
2261
2292
  );
2262
2293
  }
2263
- entry.unsubscribe();
2264
2294
  const wasRunning = entry.state === "running";
2265
2295
  if (wasRunning) {
2266
- try {
2267
- entry.handle.kill();
2268
- } catch {
2269
- }
2296
+ await new Promise((resolve2) => {
2297
+ let unsubscribeExit = () => {
2298
+ };
2299
+ unsubscribeExit = entry.handle.onExit(() => {
2300
+ unsubscribeExit();
2301
+ resolve2();
2302
+ });
2303
+ try {
2304
+ entry.handle.kill();
2305
+ } catch {
2306
+ unsubscribeExit();
2307
+ resolve2();
2308
+ }
2309
+ });
2270
2310
  }
2311
+ entry.unsubscribe();
2271
2312
  return asJson({
2272
2313
  action: "stop",
2273
2314
  id: entry.id,