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/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,
package/dist/swarm.js CHANGED
@@ -4781,7 +4781,7 @@ var ToolRegistry = class {
4781
4781
 
4782
4782
  // src/capabilities/backends/node-backends.ts
4783
4783
  import { promises as fsp } from "node:fs";
4784
- import { spawn as childSpawn } from "node:child_process";
4784
+ import { spawn as childSpawn, spawnSync } from "node:child_process";
4785
4785
  var NodeFs = class {
4786
4786
  async readFile(path, encoding) {
4787
4787
  if (encoding === void 0) {
@@ -4841,6 +4841,21 @@ function joinChunks(chunks) {
4841
4841
  function asSignal(signal) {
4842
4842
  return signal;
4843
4843
  }
4844
+ function killProcessTree(child, signal = "SIGTERM") {
4845
+ if (child.pid === void 0) return;
4846
+ if (process.platform === "win32") {
4847
+ spawnSync("taskkill", ["/F", "/T", "/PID", String(child.pid)], {
4848
+ stdio: "ignore",
4849
+ windowsHide: true
4850
+ });
4851
+ return;
4852
+ }
4853
+ try {
4854
+ process.kill(-child.pid, signal);
4855
+ } catch {
4856
+ child.kill(signal);
4857
+ }
4858
+ }
4844
4859
  var NodeShell = class {
4845
4860
  exec(command, options) {
4846
4861
  if (typeof command !== "string" || command.length === 0) {
@@ -4851,21 +4866,30 @@ var NodeShell = class {
4851
4866
  return new Promise((resolve, reject) => {
4852
4867
  const child = childSpawn(command, {
4853
4868
  shell: true,
4869
+ detached: process.platform !== "win32",
4854
4870
  cwd: options?.cwd,
4855
- env: options?.env ? { ...process.env, ...options.env } : process.env,
4856
- signal: options?.signal
4871
+ env: options?.env ? { ...process.env, ...options.env } : process.env
4857
4872
  });
4858
4873
  const out = [];
4859
4874
  const err = [];
4860
4875
  let settled2 = false;
4861
4876
  let timedOut = false;
4877
+ let aborted = false;
4862
4878
  let timer;
4879
+ const abortSignal = options?.signal;
4880
+ const onAbort = () => {
4881
+ aborted = true;
4882
+ killProcessTree(child);
4883
+ };
4863
4884
  const finish = (fn) => {
4864
4885
  if (settled2) return;
4865
4886
  settled2 = true;
4866
4887
  if (timer !== void 0) clearTimeout(timer);
4888
+ abortSignal?.removeEventListener("abort", onAbort);
4867
4889
  fn();
4868
4890
  };
4891
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
4892
+ if (abortSignal?.aborted) onAbort();
4869
4893
  child.stdout?.on("data", (chunk) => out.push(chunk));
4870
4894
  child.stderr?.on("data", (chunk) => err.push(chunk));
4871
4895
  if (options?.input !== void 0 && child.stdin) {
@@ -4878,7 +4902,7 @@ var NodeShell = class {
4878
4902
  if (limit !== void 0 && limit > 0) {
4879
4903
  timer = setTimeout(() => {
4880
4904
  timedOut = true;
4881
- child.kill("SIGTERM");
4905
+ killProcessTree(child);
4882
4906
  }, limit);
4883
4907
  }
4884
4908
  child.on("error", (cause) => {
@@ -4894,6 +4918,10 @@ var NodeShell = class {
4894
4918
  );
4895
4919
  return;
4896
4920
  }
4921
+ if (aborted) {
4922
+ reject(new Error("The command was aborted and stopped."));
4923
+ return;
4924
+ }
4897
4925
  resolve({
4898
4926
  stdout: joinChunks(out),
4899
4927
  stderr: joinChunks(err),
@@ -4911,11 +4939,11 @@ var NodeShell = class {
4911
4939
  }
4912
4940
  const child = childSpawn(command, {
4913
4941
  shell: true,
4942
+ detached: process.platform !== "win32",
4914
4943
  cwd: options?.cwd,
4915
- env: options?.env ? { ...process.env, ...options.env } : process.env,
4916
- signal: options?.signal
4944
+ env: options?.env ? { ...process.env, ...options.env } : process.env
4917
4945
  });
4918
- return new NodeShellHandle(child);
4946
+ return new NodeShellHandle(child, options?.signal);
4919
4947
  }
4920
4948
  };
4921
4949
  var NodeShellHandle = class {
@@ -4924,27 +4952,33 @@ var NodeShellHandle = class {
4924
4952
  exited = false;
4925
4953
  exitCode = null;
4926
4954
  exitSignal = null;
4927
- constructor(child) {
4955
+ abortSignal;
4956
+ onAbort = () => this.kill();
4957
+ constructor(child, abortSignal) {
4928
4958
  this.child = child;
4959
+ this.abortSignal = abortSignal;
4929
4960
  child.once(
4930
4961
  "close",
4931
4962
  (code, signal) => {
4932
4963
  this.exited = true;
4933
4964
  this.exitCode = code;
4934
4965
  this.exitSignal = asSignal(signal);
4966
+ this.abortSignal?.removeEventListener("abort", this.onAbort);
4935
4967
  for (const listener of [...this.listeners]) {
4936
4968
  listener(this.exitCode, this.exitSignal);
4937
4969
  }
4938
4970
  this.listeners.clear();
4939
4971
  }
4940
4972
  );
4973
+ this.abortSignal?.addEventListener("abort", this.onAbort, { once: true });
4974
+ if (this.abortSignal?.aborted) this.onAbort();
4941
4975
  }
4942
4976
  get pid() {
4943
4977
  return this.child.pid;
4944
4978
  }
4945
4979
  kill(signal) {
4946
4980
  if (this.exited) return;
4947
- this.child.kill(signal ?? "SIGTERM");
4981
+ killProcessTree(this.child, signal);
4948
4982
  }
4949
4983
  onExit(listener) {
4950
4984
  if (this.exited) {
@@ -6375,9 +6409,6 @@ function readInput2(raw) {
6375
6409
  }
6376
6410
  return { action, command, id };
6377
6411
  }
6378
- function shellQuote(value) {
6379
- return `'${value.replace(/'/g, `'\\''`)}'`;
6380
- }
6381
6412
  async function drainCapture(ctx, path, alreadyRead) {
6382
6413
  let full;
6383
6414
  try {
@@ -6413,7 +6444,7 @@ async function startJob(ctx, command) {
6413
6444
  await ctx.fs.mkdir(scratchDir, { recursive: true });
6414
6445
  await ctx.fs.writeFile(outPath, "", "utf8");
6415
6446
  await ctx.fs.writeFile(errPath, "", "utf8");
6416
- const wrapped = `( ${command} ) >${shellQuote(outPath)} 2>${shellQuote(errPath)}`;
6447
+ const wrapped = `( ${command} ) >${SCRATCH_DIR}/${id}.out 2>${SCRATCH_DIR}/${id}.err`;
6417
6448
  const handle = ctx.shell.spawn(wrapped, { cwd: ctx.cwd });
6418
6449
  const entry = {
6419
6450
  id,
@@ -6493,7 +6524,7 @@ async function pollJob(ctx, id) {
6493
6524
  hadNewOutput: out.fresh.length > 0 || err.fresh.length > 0
6494
6525
  });
6495
6526
  }
6496
- function stopJob(id) {
6527
+ async function stopJob(id) {
6497
6528
  const entry = table.remove(id);
6498
6529
  if (entry === void 0) {
6499
6530
  return asText2(
@@ -6501,14 +6532,24 @@ function stopJob(id) {
6501
6532
  true
6502
6533
  );
6503
6534
  }
6504
- entry.unsubscribe();
6505
6535
  const wasRunning = entry.state === "running";
6506
6536
  if (wasRunning) {
6507
- try {
6508
- entry.handle.kill();
6509
- } catch {
6510
- }
6537
+ await new Promise((resolve) => {
6538
+ let unsubscribeExit = () => {
6539
+ };
6540
+ unsubscribeExit = entry.handle.onExit(() => {
6541
+ unsubscribeExit();
6542
+ resolve();
6543
+ });
6544
+ try {
6545
+ entry.handle.kill();
6546
+ } catch {
6547
+ unsubscribeExit();
6548
+ resolve();
6549
+ }
6550
+ });
6511
6551
  }
6552
+ entry.unsubscribe();
6512
6553
  return asJson({
6513
6554
  action: "stop",
6514
6555
  id: entry.id,
@@ -5,6 +5,7 @@
5
5
  * OAuth callback server, so it is meant for CLI use and will not work in a browser.
6
6
  */
7
7
  import type { OAuthCredentials, OAuthPrompt, OAuthProviderInterface } from "./types.js";
8
+ export declare function resolveOpenAICodexClientId(configured?: string | undefined): string;
8
9
  /**
9
10
  * Drive the ChatGPT (Codex) OAuth sign-in end to end.
10
11
  *
@@ -4637,6 +4637,74 @@ export declare const MODELS: {
4637
4637
  contextWindow: number;
4638
4638
  maxTokens: number;
4639
4639
  };
4640
+ readonly "gpt-5.6-sol": {
4641
+ id: string;
4642
+ name: string;
4643
+ api: "openai-responses";
4644
+ provider: string;
4645
+ baseUrl: string;
4646
+ reasoning: true;
4647
+ input: ("text" | "image")[];
4648
+ cost: {
4649
+ input: number;
4650
+ output: number;
4651
+ cacheRead: number;
4652
+ cacheWrite: number;
4653
+ };
4654
+ contextWindow: number;
4655
+ maxTokens: number;
4656
+ };
4657
+ readonly "gpt-5.6-terra": {
4658
+ id: string;
4659
+ name: string;
4660
+ api: "openai-responses";
4661
+ provider: string;
4662
+ baseUrl: string;
4663
+ reasoning: true;
4664
+ input: ("text" | "image")[];
4665
+ cost: {
4666
+ input: number;
4667
+ output: number;
4668
+ cacheRead: number;
4669
+ cacheWrite: number;
4670
+ };
4671
+ contextWindow: number;
4672
+ maxTokens: number;
4673
+ };
4674
+ readonly "gpt-5.6-luna": {
4675
+ id: string;
4676
+ name: string;
4677
+ api: "openai-responses";
4678
+ provider: string;
4679
+ baseUrl: string;
4680
+ reasoning: true;
4681
+ input: ("text" | "image")[];
4682
+ cost: {
4683
+ input: number;
4684
+ output: number;
4685
+ cacheRead: number;
4686
+ cacheWrite: number;
4687
+ };
4688
+ contextWindow: number;
4689
+ maxTokens: number;
4690
+ };
4691
+ readonly "gpt-5.6": {
4692
+ id: string;
4693
+ name: string;
4694
+ api: "openai-responses";
4695
+ provider: string;
4696
+ baseUrl: string;
4697
+ reasoning: true;
4698
+ input: ("text" | "image")[];
4699
+ cost: {
4700
+ input: number;
4701
+ output: number;
4702
+ cacheRead: number;
4703
+ cacheWrite: number;
4704
+ };
4705
+ contextWindow: number;
4706
+ maxTokens: number;
4707
+ };
4640
4708
  readonly o1: {
4641
4709
  id: string;
4642
4710
  name: string;
@@ -4962,6 +5030,74 @@ export declare const MODELS: {
4962
5030
  contextWindow: number;
4963
5031
  maxTokens: number;
4964
5032
  };
5033
+ readonly "gpt-5.6-sol": {
5034
+ id: string;
5035
+ name: string;
5036
+ api: "openai-codex-responses";
5037
+ provider: string;
5038
+ baseUrl: string;
5039
+ reasoning: true;
5040
+ input: ("text" | "image")[];
5041
+ cost: {
5042
+ input: number;
5043
+ output: number;
5044
+ cacheRead: number;
5045
+ cacheWrite: number;
5046
+ };
5047
+ contextWindow: number;
5048
+ maxTokens: number;
5049
+ };
5050
+ readonly "gpt-5.6-terra": {
5051
+ id: string;
5052
+ name: string;
5053
+ api: "openai-codex-responses";
5054
+ provider: string;
5055
+ baseUrl: string;
5056
+ reasoning: true;
5057
+ input: ("text" | "image")[];
5058
+ cost: {
5059
+ input: number;
5060
+ output: number;
5061
+ cacheRead: number;
5062
+ cacheWrite: number;
5063
+ };
5064
+ contextWindow: number;
5065
+ maxTokens: number;
5066
+ };
5067
+ readonly "gpt-5.6-luna": {
5068
+ id: string;
5069
+ name: string;
5070
+ api: "openai-codex-responses";
5071
+ provider: string;
5072
+ baseUrl: string;
5073
+ reasoning: true;
5074
+ input: ("text" | "image")[];
5075
+ cost: {
5076
+ input: number;
5077
+ output: number;
5078
+ cacheRead: number;
5079
+ cacheWrite: number;
5080
+ };
5081
+ contextWindow: number;
5082
+ maxTokens: number;
5083
+ };
5084
+ readonly "gpt-5.6": {
5085
+ id: string;
5086
+ name: string;
5087
+ api: "openai-codex-responses";
5088
+ provider: string;
5089
+ baseUrl: string;
5090
+ reasoning: true;
5091
+ input: ("text" | "image")[];
5092
+ cost: {
5093
+ input: number;
5094
+ output: number;
5095
+ cacheRead: number;
5096
+ cacheWrite: number;
5097
+ };
5098
+ contextWindow: number;
5099
+ maxTokens: number;
5100
+ };
4965
5101
  };
4966
5102
  readonly opencode: {
4967
5103
  readonly "big-pickle": {
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "indusagi",
3
- "version": "0.13.8",
3
+ "version": "0.13.10",
4
4
  "description": "Indusagi — a terminal-first AI coding agent framework. Clean-room implementation.",
5
5
  "author": "Varun Israni",
6
6
  "license": "AGPL-3.0",
@@ -157,6 +157,7 @@
157
157
  "marked": "^18.0.4",
158
158
  "openai": "^6.41.0",
159
159
  "partial-json": "^0.1.7",
160
+ "proxy-agent": "^8.0.2",
160
161
  "react": "^18.3.1",
161
162
  "strip-ansi": "^7.2.0",
162
163
  "ulid": "^3.0.2",