claude-threads 1.38.0 → 1.39.0

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
@@ -2278,6 +2278,27 @@ function resolveTurnMarker(mode, emoji, platformType, fieldPath) {
2278
2278
  return { mode: "reaction", emoji: emoji ?? DEFAULT_TURN_MARKER_EMOJI };
2279
2279
  return { mode: m };
2280
2280
  }
2281
+ function resolveToolActivity(activity, details, fieldPath) {
2282
+ const act = activity === undefined || activity === null ? "full" : activity;
2283
+ if (!TOOL_ACTIVITY_VALUES.includes(act)) {
2284
+ throw new Error(`Invalid ${fieldPath}.toolActivity: expected one of ${TOOL_ACTIVITY_VALUES.join(", ")}, got ${JSON.stringify(activity)}`);
2285
+ }
2286
+ const mode = act;
2287
+ if (details !== undefined && details !== null && !TOOL_DETAILS_VALUES.includes(details)) {
2288
+ throw new Error(`Invalid ${fieldPath}.toolDetails: expected one of ${TOOL_DETAILS_VALUES.join(", ")}, got ${JSON.stringify(details)}`);
2289
+ }
2290
+ const det = details;
2291
+ if (mode === "full") {
2292
+ if (det !== undefined && det !== null) {
2293
+ throw new Error(`Invalid ${fieldPath}.toolDetails: only meaningful with toolActivity summary or hidden`);
2294
+ }
2295
+ return { activity: "full", details: "none" };
2296
+ }
2297
+ if (mode === "hidden" && det === "thread") {
2298
+ throw new Error(`Invalid ${fieldPath}.toolDetails: hidden has no post of its own to thread under; use summary, or none`);
2299
+ }
2300
+ return { activity: mode, details: det ?? (mode === "summary" ? "thread" : "none") };
2301
+ }
2281
2302
  function resolveMemoryConfig(value, fieldPath) {
2282
2303
  if (value === undefined || value === null || value === true)
2283
2304
  return DEFAULT_MEMORY_CONFIG;
@@ -2452,7 +2473,7 @@ function effectivePermissionMode(input) {
2452
2473
  return "default";
2453
2474
  return input.botWideMode;
2454
2475
  }
2455
- var OVERHEAD_VISIBILITY_VALUES, DEFAULT_OVERHEAD_VISIBILITY = "full", RECONNECT_POLICY_VALUES, DEFAULT_RECONNECT_POLICY = "retry", PRESENTATION_MODE_VALUES, PRESENTATION_MODE_EXPANSIONS, TURN_MARKER_VALUES, DEFAULT_TURN_MARKER, DEFAULT_TURN_MARKER_EMOJI = "checkered_flag", TURN_COMPLETE_EVENT_TYPE = "claude_threads_turn_complete", TURN_COMPLETE_PAYLOAD_VERSION = 1, DEFAULT_MEMORY_CONFIG, MEMORY_DISABLED, BOT_MCP_SERVER_NAME = "claude-threads-mcp", STDIO_KEYS, REMOTE_KEYS, LIMITS_DEFAULTS, MODE_INFO;
2476
+ var OVERHEAD_VISIBILITY_VALUES, DEFAULT_OVERHEAD_VISIBILITY = "full", RECONNECT_POLICY_VALUES, DEFAULT_RECONNECT_POLICY = "retry", PRESENTATION_MODE_VALUES, PRESENTATION_MODE_EXPANSIONS, TURN_MARKER_VALUES, DEFAULT_TURN_MARKER, DEFAULT_TURN_MARKER_EMOJI = "checkered_flag", TURN_COMPLETE_EVENT_TYPE = "claude_threads_turn_complete", TURN_COMPLETE_PAYLOAD_VERSION = 1, TOOL_ACTIVITY_VALUES, TOOL_DETAILS_VALUES, DEFAULT_TOOL_ACTIVITY, DEFAULT_MEMORY_CONFIG, MEMORY_DISABLED, BOT_MCP_SERVER_NAME = "claude-threads-mcp", STDIO_KEYS, REMOTE_KEYS, LIMITS_DEFAULTS, MODE_INFO;
2456
2477
  var init_types = __esm(() => {
2457
2478
  OVERHEAD_VISIBILITY_VALUES = ["full", "minimal", "hidden"];
2458
2479
  RECONNECT_POLICY_VALUES = ["retry", "exit"];
@@ -2467,6 +2488,9 @@ var init_types = __esm(() => {
2467
2488
  };
2468
2489
  TURN_MARKER_VALUES = ["reaction", "metadata", "off"];
2469
2490
  DEFAULT_TURN_MARKER = { mode: "off" };
2491
+ TOOL_ACTIVITY_VALUES = ["full", "summary", "hidden"];
2492
+ TOOL_DETAILS_VALUES = ["thread", "none"];
2493
+ DEFAULT_TOOL_ACTIVITY = { activity: "full", details: "none" };
2470
2494
  DEFAULT_MEMORY_CONFIG = {
2471
2495
  enabled: true,
2472
2496
  repoLayer: true,
@@ -2514,20 +2538,487 @@ var init_types = __esm(() => {
2514
2538
  };
2515
2539
  });
2516
2540
 
2517
- // src/utils/spawn.ts
2518
- import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "child_process";
2519
- function addWindowsShell(options) {
2520
- if (isWindows && options.shell === undefined) {
2521
- return { ...options, shell: true };
2541
+ // node_modules/isexe/windows.js
2542
+ var require_windows = __commonJS(function(exports, module) {
2543
+ module.exports = isexe;
2544
+ isexe.sync = sync;
2545
+ var fs = __require("fs");
2546
+ function checkPathExt(path, options) {
2547
+ var pathext = options.pathExt !== undefined ? options.pathExt : process.env.PATHEXT;
2548
+ if (!pathext) {
2549
+ return true;
2550
+ }
2551
+ pathext = pathext.split(";");
2552
+ if (pathext.indexOf("") !== -1) {
2553
+ return true;
2554
+ }
2555
+ for (var i = 0;i < pathext.length; i++) {
2556
+ var p = pathext[i].toLowerCase();
2557
+ if (p && path.substr(-p.length).toLowerCase() === p) {
2558
+ return true;
2559
+ }
2560
+ }
2561
+ return false;
2522
2562
  }
2523
- return options;
2524
- }
2563
+ function checkStat(stat, path, options) {
2564
+ if (!stat.isSymbolicLink() && !stat.isFile()) {
2565
+ return false;
2566
+ }
2567
+ return checkPathExt(path, options);
2568
+ }
2569
+ function isexe(path, options, cb) {
2570
+ fs.stat(path, function(er, stat) {
2571
+ cb(er, er ? false : checkStat(stat, path, options));
2572
+ });
2573
+ }
2574
+ function sync(path, options) {
2575
+ return checkStat(fs.statSync(path), path, options);
2576
+ }
2577
+ });
2578
+
2579
+ // node_modules/isexe/mode.js
2580
+ var require_mode = __commonJS(function(exports, module) {
2581
+ module.exports = isexe;
2582
+ isexe.sync = sync;
2583
+ var fs = __require("fs");
2584
+ function isexe(path, options, cb) {
2585
+ fs.stat(path, function(er, stat) {
2586
+ cb(er, er ? false : checkStat(stat, options));
2587
+ });
2588
+ }
2589
+ function sync(path, options) {
2590
+ return checkStat(fs.statSync(path), options);
2591
+ }
2592
+ function checkStat(stat, options) {
2593
+ return stat.isFile() && checkMode(stat, options);
2594
+ }
2595
+ function checkMode(stat, options) {
2596
+ var mod = stat.mode;
2597
+ var uid = stat.uid;
2598
+ var gid = stat.gid;
2599
+ var myUid = options.uid !== undefined ? options.uid : process.getuid && process.getuid();
2600
+ var myGid = options.gid !== undefined ? options.gid : process.getgid && process.getgid();
2601
+ var u = parseInt("100", 8);
2602
+ var g = parseInt("010", 8);
2603
+ var o = parseInt("001", 8);
2604
+ var ug = u | g;
2605
+ var ret = mod & o || mod & g && gid === myGid || mod & u && uid === myUid || mod & ug && myUid === 0;
2606
+ return ret;
2607
+ }
2608
+ });
2609
+
2610
+ // node_modules/isexe/index.js
2611
+ var require_isexe = __commonJS(function(exports, module) {
2612
+ var fs = __require("fs");
2613
+ var core;
2614
+ if (process.platform === "win32" || global.TESTING_WINDOWS) {
2615
+ core = require_windows();
2616
+ } else {
2617
+ core = require_mode();
2618
+ }
2619
+ module.exports = isexe;
2620
+ isexe.sync = sync;
2621
+ function isexe(path, options, cb) {
2622
+ if (typeof options === "function") {
2623
+ cb = options;
2624
+ options = {};
2625
+ }
2626
+ if (!cb) {
2627
+ if (typeof Promise !== "function") {
2628
+ throw new TypeError("callback not provided");
2629
+ }
2630
+ return new Promise(function(resolve, reject) {
2631
+ isexe(path, options || {}, function(er, is) {
2632
+ if (er) {
2633
+ reject(er);
2634
+ } else {
2635
+ resolve(is);
2636
+ }
2637
+ });
2638
+ });
2639
+ }
2640
+ core(path, options || {}, function(er, is) {
2641
+ if (er) {
2642
+ if (er.code === "EACCES" || options && options.ignoreErrors) {
2643
+ er = null;
2644
+ is = false;
2645
+ }
2646
+ }
2647
+ cb(er, is);
2648
+ });
2649
+ }
2650
+ function sync(path, options) {
2651
+ try {
2652
+ return core.sync(path, options || {});
2653
+ } catch (er) {
2654
+ if (options && options.ignoreErrors || er.code === "EACCES") {
2655
+ return false;
2656
+ } else {
2657
+ throw er;
2658
+ }
2659
+ }
2660
+ }
2661
+ });
2662
+
2663
+ // node_modules/which/which.js
2664
+ var require_which = __commonJS(function(exports, module) {
2665
+ var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
2666
+ var path = __require("path");
2667
+ var COLON = isWindows ? ";" : ":";
2668
+ var isexe = require_isexe();
2669
+ var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
2670
+ var getPathInfo = (cmd, opt) => {
2671
+ const colon = opt.colon || COLON;
2672
+ const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [
2673
+ ...isWindows ? [process.cwd()] : [],
2674
+ ...(opt.path || process.env.PATH || "").split(colon)
2675
+ ];
2676
+ const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
2677
+ const pathExt = isWindows ? pathExtExe.split(colon) : [""];
2678
+ if (isWindows) {
2679
+ if (cmd.indexOf(".") !== -1 && pathExt[0] !== "")
2680
+ pathExt.unshift("");
2681
+ }
2682
+ return {
2683
+ pathEnv,
2684
+ pathExt,
2685
+ pathExtExe
2686
+ };
2687
+ };
2688
+ var which = (cmd, opt, cb) => {
2689
+ if (typeof opt === "function") {
2690
+ cb = opt;
2691
+ opt = {};
2692
+ }
2693
+ if (!opt)
2694
+ opt = {};
2695
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
2696
+ const found = [];
2697
+ const step = (i) => new Promise((resolve, reject) => {
2698
+ if (i === pathEnv.length)
2699
+ return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
2700
+ const ppRaw = pathEnv[i];
2701
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
2702
+ const pCmd = path.join(pathPart, cmd);
2703
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
2704
+ resolve(subStep(p, i, 0));
2705
+ });
2706
+ const subStep = (p, i, ii) => new Promise((resolve, reject) => {
2707
+ if (ii === pathExt.length)
2708
+ return resolve(step(i + 1));
2709
+ const ext = pathExt[ii];
2710
+ isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
2711
+ if (!er && is) {
2712
+ if (opt.all)
2713
+ found.push(p + ext);
2714
+ else
2715
+ return resolve(p + ext);
2716
+ }
2717
+ return resolve(subStep(p, i, ii + 1));
2718
+ });
2719
+ });
2720
+ return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
2721
+ };
2722
+ var whichSync = (cmd, opt) => {
2723
+ opt = opt || {};
2724
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
2725
+ const found = [];
2726
+ for (let i = 0;i < pathEnv.length; i++) {
2727
+ const ppRaw = pathEnv[i];
2728
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
2729
+ const pCmd = path.join(pathPart, cmd);
2730
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
2731
+ for (let j = 0;j < pathExt.length; j++) {
2732
+ const cur = p + pathExt[j];
2733
+ try {
2734
+ const is = isexe.sync(cur, { pathExt: pathExtExe });
2735
+ if (is) {
2736
+ if (opt.all)
2737
+ found.push(cur);
2738
+ else
2739
+ return cur;
2740
+ }
2741
+ } catch (ex) {}
2742
+ }
2743
+ }
2744
+ if (opt.all && found.length)
2745
+ return found;
2746
+ if (opt.nothrow)
2747
+ return null;
2748
+ throw getNotFoundError(cmd);
2749
+ };
2750
+ module.exports = which;
2751
+ which.sync = whichSync;
2752
+ });
2753
+
2754
+ // node_modules/path-key/index.js
2755
+ var require_path_key = __commonJS(function(exports, module) {
2756
+ var pathKey = (options = {}) => {
2757
+ const environment = options.env || process.env;
2758
+ const platform = options.platform || process.platform;
2759
+ if (platform !== "win32") {
2760
+ return "PATH";
2761
+ }
2762
+ return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
2763
+ };
2764
+ module.exports = pathKey;
2765
+ module.exports.default = pathKey;
2766
+ });
2767
+
2768
+ // node_modules/cross-spawn/lib/util/resolveCommand.js
2769
+ var require_resolveCommand = __commonJS(function(exports, module) {
2770
+ var path = __require("path");
2771
+ var which = require_which();
2772
+ var getPathKey = require_path_key();
2773
+ function resolveCommandAttempt(parsed, withoutPathExt) {
2774
+ const env = parsed.options.env || process.env;
2775
+ const cwd = process.cwd();
2776
+ const hasCustomCwd = parsed.options.cwd != null;
2777
+ const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled;
2778
+ if (shouldSwitchCwd) {
2779
+ try {
2780
+ process.chdir(parsed.options.cwd);
2781
+ } catch (err) {}
2782
+ }
2783
+ let resolved;
2784
+ try {
2785
+ resolved = which.sync(parsed.command, {
2786
+ path: env[getPathKey({ env })],
2787
+ pathExt: withoutPathExt ? path.delimiter : undefined
2788
+ });
2789
+ } catch (e) {} finally {
2790
+ if (shouldSwitchCwd) {
2791
+ process.chdir(cwd);
2792
+ }
2793
+ }
2794
+ if (resolved) {
2795
+ resolved = path.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
2796
+ }
2797
+ return resolved;
2798
+ }
2799
+ function resolveCommand(parsed) {
2800
+ return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
2801
+ }
2802
+ module.exports = resolveCommand;
2803
+ });
2804
+
2805
+ // node_modules/cross-spawn/lib/util/escape.js
2806
+ var require_escape = __commonJS(function(exports, module) {
2807
+ var metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
2808
+ function escapeCommand(arg) {
2809
+ arg = arg.replace(metaCharsRegExp, "^$1");
2810
+ return arg;
2811
+ }
2812
+ function escapeArgument(arg, doubleEscapeMetaChars) {
2813
+ arg = `${arg}`;
2814
+ arg = arg.replace(/(?=(\\+?)?)\1"/g, "$1$1\\\"");
2815
+ arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
2816
+ arg = `"${arg}"`;
2817
+ arg = arg.replace(metaCharsRegExp, "^$1");
2818
+ if (doubleEscapeMetaChars) {
2819
+ arg = arg.replace(metaCharsRegExp, "^$1");
2820
+ }
2821
+ return arg;
2822
+ }
2823
+ exports.command = escapeCommand;
2824
+ exports.argument = escapeArgument;
2825
+ });
2826
+
2827
+ // node_modules/shebang-regex/index.js
2828
+ var require_shebang_regex = __commonJS(function(exports, module) {
2829
+ module.exports = /^#!(.*)/;
2830
+ });
2831
+
2832
+ // node_modules/shebang-command/index.js
2833
+ var require_shebang_command = __commonJS(function(exports, module) {
2834
+ var shebangRegex = require_shebang_regex();
2835
+ module.exports = (string = "") => {
2836
+ const match = string.match(shebangRegex);
2837
+ if (!match) {
2838
+ return null;
2839
+ }
2840
+ const [path, argument] = match[0].replace(/#! ?/, "").split(" ");
2841
+ const binary = path.split("/").pop();
2842
+ if (binary === "env") {
2843
+ return argument;
2844
+ }
2845
+ return argument ? `${binary} ${argument}` : binary;
2846
+ };
2847
+ });
2848
+
2849
+ // node_modules/cross-spawn/lib/util/readShebang.js
2850
+ var require_readShebang = __commonJS(function(exports, module) {
2851
+ var fs = __require("fs");
2852
+ var shebangCommand = require_shebang_command();
2853
+ function readShebang(command) {
2854
+ const size = 150;
2855
+ const buffer = Buffer.alloc(size);
2856
+ let fd;
2857
+ try {
2858
+ fd = fs.openSync(command, "r");
2859
+ fs.readSync(fd, buffer, 0, size, 0);
2860
+ fs.closeSync(fd);
2861
+ } catch (e) {}
2862
+ return shebangCommand(buffer.toString());
2863
+ }
2864
+ module.exports = readShebang;
2865
+ });
2866
+
2867
+ // node_modules/cross-spawn/lib/parse.js
2868
+ var require_parse = __commonJS(function(exports, module) {
2869
+ var path = __require("path");
2870
+ var resolveCommand = require_resolveCommand();
2871
+ var escape = require_escape();
2872
+ var readShebang = require_readShebang();
2873
+ var isWin = process.platform === "win32";
2874
+ var isExecutableRegExp = /\.(?:com|exe)$/i;
2875
+ var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
2876
+ function detectShebang(parsed) {
2877
+ parsed.file = resolveCommand(parsed);
2878
+ const shebang = parsed.file && readShebang(parsed.file);
2879
+ if (shebang) {
2880
+ parsed.args.unshift(parsed.file);
2881
+ parsed.command = shebang;
2882
+ return resolveCommand(parsed);
2883
+ }
2884
+ return parsed.file;
2885
+ }
2886
+ function parseNonShell(parsed) {
2887
+ if (!isWin) {
2888
+ return parsed;
2889
+ }
2890
+ const commandFile = detectShebang(parsed);
2891
+ const needsShell = !isExecutableRegExp.test(commandFile);
2892
+ if (parsed.options.forceShell || needsShell) {
2893
+ const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
2894
+ parsed.command = path.normalize(parsed.command);
2895
+ parsed.command = escape.command(parsed.command);
2896
+ parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
2897
+ const shellCommand = [parsed.command].concat(parsed.args).join(" ");
2898
+ parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`];
2899
+ parsed.command = process.env.comspec || "cmd.exe";
2900
+ parsed.options.windowsVerbatimArguments = true;
2901
+ }
2902
+ return parsed;
2903
+ }
2904
+ function parse(command, args, options) {
2905
+ if (args && !Array.isArray(args)) {
2906
+ options = args;
2907
+ args = null;
2908
+ }
2909
+ args = args ? args.slice(0) : [];
2910
+ options = Object.assign({}, options);
2911
+ const parsed = {
2912
+ command,
2913
+ args,
2914
+ options,
2915
+ file: undefined,
2916
+ original: {
2917
+ command,
2918
+ args
2919
+ }
2920
+ };
2921
+ return options.shell ? parsed : parseNonShell(parsed);
2922
+ }
2923
+ module.exports = parse;
2924
+ });
2925
+
2926
+ // node_modules/cross-spawn/lib/enoent.js
2927
+ var require_enoent = __commonJS(function(exports, module) {
2928
+ var isWin = process.platform === "win32";
2929
+ function notFoundError(original, syscall) {
2930
+ return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
2931
+ code: "ENOENT",
2932
+ errno: "ENOENT",
2933
+ syscall: `${syscall} ${original.command}`,
2934
+ path: original.command,
2935
+ spawnargs: original.args
2936
+ });
2937
+ }
2938
+ function hookChildProcess(cp, parsed) {
2939
+ if (!isWin) {
2940
+ return;
2941
+ }
2942
+ const originalEmit = cp.emit;
2943
+ cp.emit = function(name, arg1) {
2944
+ if (name === "exit") {
2945
+ const err = verifyENOENT(arg1, parsed);
2946
+ if (err) {
2947
+ return originalEmit.call(cp, "error", err);
2948
+ }
2949
+ }
2950
+ return originalEmit.apply(cp, arguments);
2951
+ };
2952
+ }
2953
+ function verifyENOENT(status, parsed) {
2954
+ if (isWin && status === 1 && !parsed.file) {
2955
+ return notFoundError(parsed.original, "spawn");
2956
+ }
2957
+ return null;
2958
+ }
2959
+ function verifyENOENTSync(status, parsed) {
2960
+ if (isWin && status === 1 && !parsed.file) {
2961
+ return notFoundError(parsed.original, "spawnSync");
2962
+ }
2963
+ return null;
2964
+ }
2965
+ module.exports = {
2966
+ hookChildProcess,
2967
+ verifyENOENT,
2968
+ verifyENOENTSync,
2969
+ notFoundError
2970
+ };
2971
+ });
2972
+
2973
+ // node_modules/cross-spawn/index.js
2974
+ var require_cross_spawn = __commonJS(function(exports, module) {
2975
+ var cp = __require("child_process");
2976
+ var parse = require_parse();
2977
+ var enoent = require_enoent();
2978
+ function spawn(command, args, options) {
2979
+ const parsed = parse(command, args, options);
2980
+ const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
2981
+ enoent.hookChildProcess(spawned, parsed);
2982
+ return spawned;
2983
+ }
2984
+ function spawnSync(command, args, options) {
2985
+ const parsed = parse(command, args, options);
2986
+ const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
2987
+ result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
2988
+ return result;
2989
+ }
2990
+ module.exports = spawn;
2991
+ module.exports.spawn = spawn;
2992
+ module.exports.sync = spawnSync;
2993
+ module.exports._parse = parse;
2994
+ module.exports._enoent = enoent;
2995
+ });
2996
+
2997
+ // src/utils/spawn.ts
2998
+ import { win32 as win32Path } from "path";
2525
2999
  function crossSpawn(command, args, options) {
2526
- return nodeSpawn(command, args, addWindowsShell(options ?? {}));
3000
+ return import_cross_spawn.default(command, args, options ?? {});
3001
+ }
3002
+ function crossSpawnSync(command, args, options) {
3003
+ return import_cross_spawn.default.sync(command, args, options ?? {});
3004
+ }
3005
+ function findWindowsGitBash(env, exists) {
3006
+ const systemRoot = (env.SystemRoot ?? env.SYSTEMROOT ?? "C:\\Windows").toLowerCase();
3007
+ const isWslLauncher = (dir) => {
3008
+ const lower = dir.toLowerCase().replace(/[\\/]+$/, "");
3009
+ return lower.startsWith(`${systemRoot}\\system32`) || lower.startsWith(`${systemRoot}\\sysnative`) || lower.endsWith("\\windowsapps");
3010
+ };
3011
+ const pathDirs = (env.PATH ?? env.Path ?? "").split(";").filter(Boolean);
3012
+ const candidates = [
3013
+ ...pathDirs.filter((dir) => !isWslLauncher(dir)).map((dir) => win32Path.join(dir, "bash.exe")),
3014
+ ...[env.ProgramFiles, env.ProgramW6432, env["ProgramFiles(x86)"]].filter((dir) => Boolean(dir)).map((dir) => win32Path.join(dir, "Git", "bin", "bash.exe")),
3015
+ ...env.LOCALAPPDATA ? [win32Path.join(env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
3016
+ ];
3017
+ return candidates.find((candidate) => exists(candidate)) ?? null;
2527
3018
  }
2528
- var isWindows;
3019
+ var import_cross_spawn;
2529
3020
  var init_spawn = __esm(() => {
2530
- isWindows = process.platform === "win32";
3021
+ import_cross_spawn = __toESM(require_cross_spawn(), 1);
2531
3022
  });
2532
3023
 
2533
3024
  // node_modules/semver/internal/constants.js
@@ -2970,7 +3461,7 @@ var require_semver = __commonJS(function(exports, module) {
2970
3461
  });
2971
3462
 
2972
3463
  // node_modules/semver/functions/parse.js
2973
- var require_parse = __commonJS(function(exports, module) {
3464
+ var require_parse2 = __commonJS(function(exports, module) {
2974
3465
  var SemVer = require_semver();
2975
3466
  var parse = (version, options, throwErrors = false) => {
2976
3467
  if (version instanceof SemVer) {
@@ -2990,7 +3481,7 @@ var require_parse = __commonJS(function(exports, module) {
2990
3481
 
2991
3482
  // node_modules/semver/functions/valid.js
2992
3483
  var require_valid = __commonJS(function(exports, module) {
2993
- var parse = require_parse();
3484
+ var parse = require_parse2();
2994
3485
  var valid = (version, options) => {
2995
3486
  const v = parse(version, options);
2996
3487
  return v ? v.version : null;
@@ -3000,7 +3491,7 @@ var require_valid = __commonJS(function(exports, module) {
3000
3491
 
3001
3492
  // node_modules/semver/functions/clean.js
3002
3493
  var require_clean = __commonJS(function(exports, module) {
3003
- var parse = require_parse();
3494
+ var parse = require_parse2();
3004
3495
  var clean = (version, options) => {
3005
3496
  const s = parse(version.trim().replace(/^[=v]+/, ""), options);
3006
3497
  return s ? s.version : null;
@@ -3028,7 +3519,7 @@ var require_inc = __commonJS(function(exports, module) {
3028
3519
 
3029
3520
  // node_modules/semver/functions/diff.js
3030
3521
  var require_diff = __commonJS(function(exports, module) {
3031
- var parse = require_parse();
3522
+ var parse = require_parse2();
3032
3523
  var diff = (version1, version2) => {
3033
3524
  const v1 = parse(version1, null, true);
3034
3525
  const v2 = parse(version2, null, true);
@@ -3090,7 +3581,7 @@ var require_patch = __commonJS(function(exports, module) {
3090
3581
 
3091
3582
  // node_modules/semver/functions/prerelease.js
3092
3583
  var require_prerelease = __commonJS(function(exports, module) {
3093
- var parse = require_parse();
3584
+ var parse = require_parse2();
3094
3585
  var prerelease = (version, options) => {
3095
3586
  const parsed = parse(version, options);
3096
3587
  return parsed && parsed.prerelease.length ? parsed.prerelease : null;
@@ -3236,7 +3727,7 @@ var require_cmp = __commonJS(function(exports, module) {
3236
3727
  // node_modules/semver/functions/coerce.js
3237
3728
  var require_coerce = __commonJS(function(exports, module) {
3238
3729
  var SemVer = require_semver();
3239
- var parse = require_parse();
3730
+ var parse = require_parse2();
3240
3731
  var { safeRe: re, t } = require_re();
3241
3732
  var coerce = (version, options) => {
3242
3733
  if (version instanceof SemVer) {
@@ -3278,7 +3769,7 @@ var require_coerce = __commonJS(function(exports, module) {
3278
3769
 
3279
3770
  // node_modules/semver/functions/truncate.js
3280
3771
  var require_truncate = __commonJS(function(exports, module) {
3281
- var parse = require_parse();
3772
+ var parse = require_parse2();
3282
3773
  var constants = require_constants();
3283
3774
  var SemVer = require_semver();
3284
3775
  var truncate = (version, truncation, options) => {
@@ -4286,7 +4777,7 @@ var require_semver2 = __commonJS(function(exports, module) {
4286
4777
  var constants = require_constants();
4287
4778
  var SemVer = require_semver();
4288
4779
  var identifiers = require_identifiers();
4289
- var parse = require_parse();
4780
+ var parse = require_parse2();
4290
4781
  var valid = require_valid();
4291
4782
  var clean = require_clean();
4292
4783
  var inc = require_inc();
@@ -55272,7 +55763,7 @@ import process8 from "node:process";
55272
55763
  import path9 from "node:path";
55273
55764
  import os4 from "node:os";
55274
55765
  import fs4 from "node:fs";
55275
- var isWindows2 = process8.platform === "win32";
55766
+ var isWindows = process8.platform === "win32";
55276
55767
  var readRc = (filePath) => {
55277
55768
  try {
55278
55769
  return import_ini.default.parse(fs4.readFileSync(filePath, "utf8")).prefix;
@@ -55280,7 +55771,7 @@ var readRc = (filePath) => {
55280
55771
  };
55281
55772
  var getEnvNpmPrefix = () => Object.keys(process8.env).reduce((prefix, name) => /^npm_config_prefix$/i.test(name) ? process8.env[name] : prefix, undefined);
55282
55773
  var getGlobalNpmrc = () => {
55283
- if (isWindows2 && process8.env.APPDATA) {
55774
+ if (isWindows && process8.env.APPDATA) {
55284
55775
  return path9.join(process8.env.APPDATA, "/npm/etc/npmrc");
55285
55776
  }
55286
55777
  if (process8.execPath.includes("/Cellar/node")) {
@@ -55293,7 +55784,7 @@ var getGlobalNpmrc = () => {
55293
55784
  }
55294
55785
  };
55295
55786
  var getDefaultNpmPrefix = () => {
55296
- if (isWindows2) {
55787
+ if (isWindows) {
55297
55788
  const { APPDATA } = process8.env;
55298
55789
  return APPDATA ? path9.join(APPDATA, "npm") : path9.dirname(process8.execPath);
55299
55790
  }
@@ -55319,7 +55810,7 @@ var getNpmPrefix = () => {
55319
55810
  };
55320
55811
  var npmPrefix = path9.resolve(getNpmPrefix());
55321
55812
  var getYarnWindowsDirectory = () => {
55322
- if (isWindows2 && process8.env.LOCALAPPDATA) {
55813
+ if (isWindows && process8.env.LOCALAPPDATA) {
55323
55814
  const dir = path9.join(process8.env.LOCALAPPDATA, "Yarn");
55324
55815
  if (fs4.existsSync(dir)) {
55325
55816
  return dir;
@@ -55348,8 +55839,8 @@ var getYarnPrefix = () => {
55348
55839
  var globalDirectory = {};
55349
55840
  globalDirectory.npm = {};
55350
55841
  globalDirectory.npm.prefix = npmPrefix;
55351
- globalDirectory.npm.packages = path9.join(npmPrefix, isWindows2 ? "node_modules" : "lib/node_modules");
55352
- globalDirectory.npm.binaries = isWindows2 ? npmPrefix : path9.join(npmPrefix, "bin");
55842
+ globalDirectory.npm.packages = path9.join(npmPrefix, isWindows ? "node_modules" : "lib/node_modules");
55843
+ globalDirectory.npm.binaries = isWindows ? npmPrefix : path9.join(npmPrefix, "bin");
55353
55844
  var yarnPrefix = path9.resolve(getYarnPrefix());
55354
55845
  globalDirectory.yarn = {};
55355
55846
  globalDirectory.yarn.prefix = yarnPrefix;
@@ -59034,6 +59525,9 @@ toolFormatterRegistry.register(playwrightToolsFormatter);
59034
59525
  toolFormatterRegistry.register(figmaToolsFormatter);
59035
59526
  toolFormatterRegistry.register(context7ToolsFormatter);
59036
59527
  // src/operations/types.ts
59528
+ function isToolActivityOp(op) {
59529
+ return op.type === "tool_activity";
59530
+ }
59037
59531
  function isContentOp(op) {
59038
59532
  return op.type === "append_content";
59039
59533
  }
@@ -59070,6 +59564,9 @@ function createAppendContentOp(sessionId, content, isToolOutput) {
59070
59564
  isToolOutput
59071
59565
  };
59072
59566
  }
59567
+ function createToolActivityOp(sessionId, detail) {
59568
+ return { type: "tool_activity", sessionId, timestamp: Date.now(), ...detail };
59569
+ }
59073
59570
  function createFlushOp(sessionId, reason, resultOk) {
59074
59571
  return {
59075
59572
  type: "flush",
@@ -59132,6 +59629,9 @@ function createStatusUpdateOp(sessionId, options) {
59132
59629
  }
59133
59630
  // src/operations/transformer.ts
59134
59631
  init_cli();
59632
+ function toolsInline(ctx) {
59633
+ return (ctx.toolActivity ?? "full") === "full";
59634
+ }
59135
59635
  function transformEvent(event, ctx) {
59136
59636
  if (event.parent_tool_use_id) {
59137
59637
  return [];
@@ -59181,7 +59681,16 @@ function transformAssistant(event, ctx) {
59181
59681
  });
59182
59682
  if (result.display && !result.hidden) {
59183
59683
  flushTextBuffer();
59184
- operations.push(createAppendContentOp(ctx.sessionId, result.display, true));
59684
+ if (toolsInline(ctx)) {
59685
+ operations.push(createAppendContentOp(ctx.sessionId, result.display, true));
59686
+ } else {
59687
+ operations.push(createToolActivityOp(ctx.sessionId, {
59688
+ kind: "start",
59689
+ toolUseId: block.id || "",
59690
+ name: block.name,
59691
+ display: result.display
59692
+ }));
59693
+ }
59185
59694
  if (block.id) {
59186
59695
  ctx.toolStartTimes.set(block.id, Date.now());
59187
59696
  }
@@ -59195,7 +59704,14 @@ function transformAssistant(event, ctx) {
59195
59704
  } else if (block.type === "server_tool_use" && block.name) {
59196
59705
  flushTextBuffer();
59197
59706
  const inputStr = block.input ? JSON.stringify(block.input).substring(0, 50) : "";
59198
- operations.push(createAppendContentOp(ctx.sessionId, `\uD83C\uDF10 ${ctx.formatter.formatBold(block.name)} ${inputStr}`, true));
59707
+ const display = `\uD83C\uDF10 ${ctx.formatter.formatBold(block.name)} ${inputStr}`;
59708
+ if (toolsInline(ctx)) {
59709
+ operations.push(createAppendContentOp(ctx.sessionId, display, true));
59710
+ } else {
59711
+ const toolUseId = block.id || "";
59712
+ operations.push(createToolActivityOp(ctx.sessionId, { kind: "start", toolUseId, name: block.name, display }));
59713
+ operations.push(createToolActivityOp(ctx.sessionId, { kind: "end", toolUseId, ok: true, elapsedMs: 0, display: " ↳ ✓" }));
59714
+ }
59199
59715
  }
59200
59716
  }
59201
59717
  flushTextBuffer();
@@ -59224,7 +59740,7 @@ function transformUser(event, ctx) {
59224
59740
  }
59225
59741
  }
59226
59742
  if (ctx.toolStartTimes.has(block.tool_use_id)) {
59227
- operations.push(createResultIndicatorOp(block.tool_use_id, block.is_error === true, ctx));
59743
+ operations.push(toolsInline(ctx) ? createResultIndicatorOp(block.tool_use_id, block.is_error === true, ctx) : createToolEndOp(block.tool_use_id, block.is_error === true, ctx));
59228
59744
  indicatorCount++;
59229
59745
  }
59230
59746
  }
@@ -59263,6 +59779,12 @@ function createResultIndicatorOp(toolUseId, isError, ctx) {
59263
59779
  const errorNote = isError ? " Error" : "";
59264
59780
  return createAppendContentOp(ctx.sessionId, ` ↳ ${icon}${errorNote}${elapsed}`, true);
59265
59781
  }
59782
+ function createToolEndOp(toolUseId, isError, ctx) {
59783
+ const startTime = ctx.toolStartTimes.get(toolUseId);
59784
+ const elapsedMs = startTime ? Date.now() - startTime : 0;
59785
+ const indicator = createResultIndicatorOp(toolUseId, isError, ctx);
59786
+ return createToolActivityOp(ctx.sessionId, { kind: "end", toolUseId, ok: !isError, elapsedMs, display: indicator.content });
59787
+ }
59266
59788
  function transformToolUse(event, ctx) {
59267
59789
  const tool = event.tool_use;
59268
59790
  if (tool.id) {
@@ -59278,7 +59800,9 @@ function transformToolUse(event, ctx) {
59278
59800
  worktreeInfo: ctx.worktreeInfo
59279
59801
  });
59280
59802
  if (result.display && !result.hidden) {
59281
- return [createAppendContentOp(ctx.sessionId, result.display, true)];
59803
+ return [
59804
+ toolsInline(ctx) ? createAppendContentOp(ctx.sessionId, result.display, true) : createToolActivityOp(ctx.sessionId, { kind: "start", toolUseId: tool.id || "", name: tool.name, display: result.display })
59805
+ ];
59282
59806
  }
59283
59807
  return [];
59284
59808
  }
@@ -59287,13 +59811,18 @@ function transformToolResult(event, ctx) {
59287
59811
  return [];
59288
59812
  }
59289
59813
  const result = event.tool_result;
59814
+ const toolUseId = result.tool_use_id || "";
59815
+ const isError = result.is_error === true;
59290
59816
  return [
59291
- createResultIndicatorOp(result.tool_use_id || "", result.is_error === true, ctx),
59817
+ toolsInline(ctx) ? createResultIndicatorOp(toolUseId, isError, ctx) : createToolEndOp(toolUseId, isError, ctx),
59292
59818
  createFlushOp(ctx.sessionId, "tool_complete")
59293
59819
  ];
59294
59820
  }
59295
59821
  function transformResult(event, ctx) {
59296
59822
  const operations = [];
59823
+ if (!toolsInline(ctx)) {
59824
+ operations.push(createToolActivityOp(ctx.sessionId, { kind: "turn_end" }));
59825
+ }
59297
59826
  operations.push(createFlushOp(ctx.sessionId, "result", !isErrorResultEvent(event)));
59298
59827
  const result = event;
59299
59828
  const r = result.result;
@@ -59377,6 +59906,210 @@ function truncateAtWord2(text, maxLength) {
59377
59906
  }
59378
59907
  return truncated + "...";
59379
59908
  }
59909
+ // src/operations/executors/tool-activity.ts
59910
+ var fresh = () => ({ started: 0, finished: 0, failed: 0, firstStartAt: null, lastEndAt: null, lastTool: null });
59911
+ function shortToolName(name) {
59912
+ return parseMcpToolName(name)?.tool || name;
59913
+ }
59914
+ function renderToolSummary(stats, now, link, formatter) {
59915
+ const running = stats.started > stats.finished;
59916
+ const until = running || stats.lastEndAt === null ? now : stats.lastEndAt;
59917
+ const seconds = stats.firstStartAt === null ? 0 : Math.max(0, Math.round((until - stats.firstStartAt) / 1000));
59918
+ const parts = [`\uD83D\uDD27 ${stats.started} ${stats.started === 1 ? "tool" : "tools"}`, `${seconds} s${running ? "…" : ""}`];
59919
+ if (stats.lastTool)
59920
+ parts.push(shortToolName(stats.lastTool));
59921
+ if (stats.failed > 0)
59922
+ parts.push(`${stats.failed} ❌`);
59923
+ if (link)
59924
+ parts.push(formatter.formatLink("details", link));
59925
+ return parts.join(" · ");
59926
+ }
59927
+
59928
+ class ToolActivityExecutor {
59929
+ options;
59930
+ stats = fresh();
59931
+ open = new Set;
59932
+ constructor(options) {
59933
+ this.options = options;
59934
+ }
59935
+ getStats() {
59936
+ return this.stats;
59937
+ }
59938
+ async execute(op, ctx) {
59939
+ const now = this.options.now?.() ?? Date.now();
59940
+ if (op.kind === "start") {
59941
+ this.stats.started++;
59942
+ this.open.add(op.toolUseId);
59943
+ this.stats.firstStartAt ??= now;
59944
+ this.stats.lastTool = op.name;
59945
+ this.renderHeader(now, ctx);
59946
+ await this.options.sink.append(op, ctx);
59947
+ } else if (op.kind === "end") {
59948
+ if (!this.open.delete(op.toolUseId))
59949
+ return;
59950
+ this.stats.finished++;
59951
+ if (!op.ok)
59952
+ this.stats.failed++;
59953
+ this.stats.lastEndAt = now;
59954
+ this.renderHeader(now, ctx);
59955
+ await this.options.sink.append(op, ctx);
59956
+ } else if (this.stats.started > 0) {
59957
+ if (this.stats.started > this.stats.finished) {
59958
+ this.stats.finished = this.stats.started;
59959
+ this.stats.lastEndAt = now;
59960
+ }
59961
+ this.open.clear();
59962
+ this.renderHeader(now, ctx);
59963
+ }
59964
+ }
59965
+ async afterResultFlush(ctx) {
59966
+ if (this.stats.started === 0)
59967
+ return;
59968
+ this.stats = fresh();
59969
+ this.open.clear();
59970
+ try {
59971
+ await this.options.sink.turnEnded(ctx);
59972
+ } catch (err) {
59973
+ ctx.logger.warn(`tool details: delivering the turn failed: ${err.message ?? err}`);
59974
+ }
59975
+ }
59976
+ reset() {
59977
+ if (this.stats.started === 0)
59978
+ return;
59979
+ this.stats = fresh();
59980
+ this.open.clear();
59981
+ this.options.sink.reset();
59982
+ }
59983
+ wake() {
59984
+ this.options.sink.wake?.();
59985
+ }
59986
+ renderHeader(now, ctx) {
59987
+ if (this.options.mode !== "summary")
59988
+ return;
59989
+ this.options.onHeader(renderToolSummary(this.stats, now, this.options.sink.link(), ctx.formatter));
59990
+ }
59991
+ }
59992
+
59993
+ // src/operations/tool-details/thread.ts
59994
+ function createThreadSink(deps) {
59995
+ const flushDelayMs = deps.flushDelayMs ?? 500;
59996
+ const newTurn = () => ({ queued: [], executor: null, ctx: null, timer: null, chain: Promise.resolve(), dead: false });
59997
+ let turn = newTurn();
59998
+ function enqueue(t, work) {
59999
+ const run = t.chain.then(() => t.dead ? undefined : work());
60000
+ t.chain = run.catch(() => {
60001
+ return;
60002
+ });
60003
+ return run;
60004
+ }
60005
+ async function drain(t) {
60006
+ if (t.queued.length === 0)
60007
+ return;
60008
+ t.ctx ??= deps.contextFor();
60009
+ if (!t.ctx)
60010
+ return;
60011
+ t.executor ??= deps.makeExecutor();
60012
+ const lines = t.queued;
60013
+ t.queued = [];
60014
+ const chunk = Math.floor(t.ctx.platform.getMessageLimits().hardThreshold / 2);
60015
+ let nextFlushAt = chunk;
60016
+ for (const line of lines) {
60017
+ await t.executor.executeAppend(createAppendContentOp(t.ctx.sessionId, line, true), t.ctx);
60018
+ if (t.dead)
60019
+ return;
60020
+ const pending = t.executor.getState().pendingContent.length;
60021
+ if (pending >= nextFlushAt) {
60022
+ await t.executor.executeFlush(createFlushOp(t.ctx.sessionId, "soft_threshold"), t.ctx);
60023
+ if (t.dead)
60024
+ return;
60025
+ const left = t.executor.getState().pendingContent.length;
60026
+ nextFlushAt = left >= pending ? pending * 2 : chunk;
60027
+ }
60028
+ }
60029
+ }
60030
+ function scheduleFlush(t) {
60031
+ if (t.timer || t.dead)
60032
+ return;
60033
+ t.timer = setTimeout(() => {
60034
+ t.timer = null;
60035
+ enqueue(t, async () => {
60036
+ if (t.executor && t.ctx)
60037
+ await t.executor.executeFlush(createFlushOp(t.ctx.sessionId, "soft_threshold"), t.ctx);
60038
+ });
60039
+ }, flushDelayMs);
60040
+ }
60041
+ function stopTimer(t) {
60042
+ if (t.timer) {
60043
+ clearTimeout(t.timer);
60044
+ t.timer = null;
60045
+ }
60046
+ }
60047
+ return {
60048
+ async append(op) {
60049
+ const t = turn;
60050
+ t.queued.push(op.display);
60051
+ if (deps.holdUntilTurnEnd)
60052
+ return;
60053
+ await enqueue(t, async () => {
60054
+ await drain(t);
60055
+ if (t.executor)
60056
+ scheduleFlush(t);
60057
+ });
60058
+ },
60059
+ async turnEnded(ctx) {
60060
+ const t = turn;
60061
+ turn = newTurn();
60062
+ stopTimer(t);
60063
+ t.ctx ??= deps.contextFor();
60064
+ await enqueue(t, async () => {
60065
+ await drain(t);
60066
+ if (t.executor && t.ctx) {
60067
+ await t.executor.executeFlush(createFlushOp(t.ctx.sessionId, "result"), t.ctx);
60068
+ t.executor.closeCurrentPost(t.ctx);
60069
+ }
60070
+ if (t.queued.length > 0) {
60071
+ ctx.logger.warn(`tool details: ${t.queued.length} line(s) dropped, the turn has no post to thread under`);
60072
+ t.queued = [];
60073
+ }
60074
+ });
60075
+ },
60076
+ link: () => null,
60077
+ wake() {
60078
+ const t = turn;
60079
+ if (deps.holdUntilTurnEnd || t.ctx || t.queued.length === 0)
60080
+ return;
60081
+ enqueue(t, async () => {
60082
+ await drain(t);
60083
+ if (t.executor)
60084
+ scheduleFlush(t);
60085
+ }).catch(() => {
60086
+ return;
60087
+ });
60088
+ },
60089
+ reset() {
60090
+ const t = turn;
60091
+ t.dead = true;
60092
+ stopTimer(t);
60093
+ t.executor?.reset();
60094
+ turn = newTurn();
60095
+ }
60096
+ };
60097
+ }
60098
+
60099
+ // src/operations/tool-details/types.ts
60100
+ var noneSink = {
60101
+ append: async () => {
60102
+ return;
60103
+ },
60104
+ turnEnded: async () => {
60105
+ return;
60106
+ },
60107
+ link: () => null,
60108
+ reset: () => {
60109
+ return;
60110
+ }
60111
+ };
60112
+
59380
60113
  // src/operations/message-manager.ts
59381
60114
  init_types();
59382
60115
 
@@ -59542,9 +60275,66 @@ class ContentExecutor extends BaseExecutor {
59542
60275
  currentPostId: null,
59543
60276
  currentPostContent: "",
59544
60277
  pendingContent: "",
59545
- updateTimer: null
60278
+ updateTimer: null,
60279
+ header: null,
60280
+ headerDirty: false,
60281
+ headerPostId: null,
60282
+ headerBody: "",
60283
+ turnOpen: false,
60284
+ paragraphBreak: false
59546
60285
  };
59547
60286
  }
60287
+ setHeader(line) {
60288
+ if (!this.state.turnOpen) {
60289
+ this.state.turnOpen = true;
60290
+ this.state.headerPostId = this.state.currentPostId;
60291
+ this.state.headerBody = this.state.currentPostContent;
60292
+ }
60293
+ this.state.header = line;
60294
+ this.state.headerDirty = true;
60295
+ }
60296
+ getHeaderPostId() {
60297
+ return this.state.headerPostId;
60298
+ }
60299
+ abandonHeaderTurn() {
60300
+ this.state.header = null;
60301
+ this.state.headerDirty = false;
60302
+ this.state.headerPostId = null;
60303
+ this.state.headerBody = "";
60304
+ this.state.turnOpen = false;
60305
+ }
60306
+ getRenderedCurrentPost() {
60307
+ const postId = this.state.currentPostId;
60308
+ if (!postId)
60309
+ return null;
60310
+ return { postId, text: this.renderFor(postId, this.state.currentPostContent) };
60311
+ }
60312
+ renderFor(postId, body) {
60313
+ if (this.state.header && postId !== null && postId === this.state.headerPostId) {
60314
+ return body ? `${this.state.header}
60315
+
60316
+ ${body}` : this.state.header;
60317
+ }
60318
+ return body;
60319
+ }
60320
+ headerReserve(postId) {
60321
+ const header = this.state.header;
60322
+ if (!header)
60323
+ return 0;
60324
+ const applies = postId === this.state.headerPostId || postId === null && this.state.headerPostId === null && this.state.turnOpen;
60325
+ return applies ? header.length + 2 : 0;
60326
+ }
60327
+ async renderHeaderOnly(ctx) {
60328
+ this.state.headerDirty = false;
60329
+ if (this.state.headerPostId) {
60330
+ const postId = this.state.headerPostId;
60331
+ await this.tryUpdatePost(ctx, postId, this.state.headerBody, "header", { reason: "header_update", headerLength: this.state.header?.length ?? 0 }, { reason: "header_update_failed" }, () => {}, () => {});
60332
+ return;
60333
+ }
60334
+ if (this.state.header && this.state.turnOpen) {
60335
+ await this.createNewPost(ctx, "", "");
60336
+ }
60337
+ }
59548
60338
  getInitialState() {
59549
60339
  return ContentExecutor.createInitialState();
59550
60340
  }
@@ -59556,7 +60346,11 @@ class ContentExecutor extends BaseExecutor {
59556
60346
  }
59557
60347
  async tryUpdatePost(ctx, postId, content, logTag, successDetails, failureDetails, onSuccess, onFailure) {
59558
60348
  try {
59559
- await ctx.platform.updatePost(postId, content);
60349
+ await ctx.platform.updatePost(postId, this.renderFor(postId, content));
60350
+ if (postId === this.state.headerPostId) {
60351
+ this.state.headerBody = content;
60352
+ this.state.headerDirty = false;
60353
+ }
59560
60354
  onSuccess();
59561
60355
  ctx.threadLogger?.logExecutor("content", "update", postId, successDetails, logTag);
59562
60356
  } catch (err) {
@@ -59578,8 +60372,14 @@ class ContentExecutor extends BaseExecutor {
59578
60372
  }, "closeCurrentPost");
59579
60373
  }
59580
60374
  }
60375
+ markParagraphBreak() {
60376
+ this.state.paragraphBreak = true;
60377
+ }
59581
60378
  async executeAppend(op, _ctx) {
59582
- if (op.isToolOutput && this.state.pendingContent.length > 0) {
60379
+ const breakBefore = this.state.paragraphBreak && !op.isToolOutput;
60380
+ if (!op.isToolOutput)
60381
+ this.state.paragraphBreak = false;
60382
+ if ((op.isToolOutput || breakBefore) && this.state.pendingContent.length > 0) {
59583
60383
  if (!this.state.pendingContent.endsWith(`
59584
60384
 
59585
60385
  `)) {
@@ -59612,10 +60412,21 @@ class ContentExecutor extends BaseExecutor {
59612
60412
  this.flush(ctx, "soft_threshold");
59613
60413
  }, delayMs);
59614
60414
  }
59615
- async flush(ctx, _reason) {
60415
+ async flush(ctx, reason) {
59616
60416
  if (!this.state.pendingContent.trim()) {
60417
+ if (this.state.headerDirty)
60418
+ await this.renderHeaderOnly(ctx);
60419
+ if (reason === "result")
60420
+ this.state.turnOpen = false;
59617
60421
  return;
59618
60422
  }
60423
+ await this.flushPending(ctx);
60424
+ if (this.state.headerDirty)
60425
+ await this.renderHeaderOnly(ctx);
60426
+ if (reason === "result")
60427
+ this.state.turnOpen = false;
60428
+ }
60429
+ async flushPending(ctx) {
59619
60430
  const pendingAtFlushStart = this.state.pendingContent;
59620
60431
  let content = ctx.formatter.formatMarkdown(pendingAtFlushStart).trim();
59621
60432
  const { maxLength: MAX_POST_LENGTH, hardThreshold: HARD_CONTINUATION_THRESHOLD } = ctx.platform.getMessageLimits();
@@ -59631,13 +60442,14 @@ class ContentExecutor extends BaseExecutor {
59631
60442
  combinedContent = content;
59632
60443
  }
59633
60444
  const shouldBreakEarly = this.state.currentPostId && combinedContent.length > MIN_BREAK_THRESHOLD && ctx.contentBreaker.shouldFlushEarly(combinedContent);
59634
- if (this.state.currentPostId && (combinedContent.length > HARD_CONTINUATION_THRESHOLD || shouldBreakEarly)) {
60445
+ const reserve = this.headerReserve(this.state.currentPostId);
60446
+ if (this.state.currentPostId && (combinedContent.length + reserve > HARD_CONTINUATION_THRESHOLD || shouldBreakEarly)) {
59635
60447
  await this.handleSplit(ctx, combinedContent, pendingAtFlushStart, HARD_CONTINUATION_THRESHOLD);
59636
60448
  return;
59637
60449
  }
59638
- if (content.length > MAX_POST_LENGTH) {
60450
+ if (this.state.currentPostId && content.length + reserve > MAX_POST_LENGTH) {
59639
60451
  ctx.logger.warn(`Content too long (${content.length}), truncating`);
59640
- content = truncateMessageSafely(content, MAX_POST_LENGTH, ctx.formatter.formatItalic("... (truncated)"));
60452
+ content = truncateMessageSafely(content, MAX_POST_LENGTH - reserve, ctx.formatter.formatItalic("... (truncated)"));
59641
60453
  }
59642
60454
  if (this.state.currentPostId) {
59643
60455
  const postId = this.state.currentPostId;
@@ -59652,7 +60464,7 @@ class ContentExecutor extends BaseExecutor {
59652
60464
  } else {
59653
60465
  combinedContent = content;
59654
60466
  }
59655
- if (combinedContent.length > MAX_POST_LENGTH) {
60467
+ if (combinedContent.length + reserve > MAX_POST_LENGTH) {
59656
60468
  ctx.logger.debug(`Combined content (${combinedContent.length}) would exceed max (${MAX_POST_LENGTH}), creating continuation post`);
59657
60469
  ctx.threadLogger?.logExecutor("content", "create_start", "none", {
59658
60470
  contentLength: content.length,
@@ -59672,14 +60484,28 @@ class ContentExecutor extends BaseExecutor {
59672
60484
  this.state.currentPostContent = "";
59673
60485
  });
59674
60486
  } else {
59675
- const chunks = splitContentForHeight(content, ctx.contentBreaker);
60487
+ const chunks = splitContentForHeight(content, ctx.contentBreaker).flatMap((chunk) => chunk.length + reserve > MAX_POST_LENGTH ? splitByLength(chunk, HARD_CONTINUATION_THRESHOLD - reserve) : [chunk]);
59676
60488
  ctx.threadLogger?.logExecutor("content", "create_start", "none", {
59677
60489
  contentLength: content.length,
59678
60490
  chunkCount: chunks.length,
59679
60491
  reason: "no_currentPostId"
59680
60492
  }, "flush");
60493
+ let lastPosted = null;
59681
60494
  for (let i = 0;i < chunks.length; i++) {
59682
- await this.createNewPost(ctx, chunks[i], pendingAtFlushStart);
60495
+ const created = await this.createNewPost(ctx, chunks[i], lastPosted ? "" : pendingAtFlushStart);
60496
+ if (!created) {
60497
+ if (lastPosted) {
60498
+ this.state.pendingContent = chunks.slice(i).join(`
60499
+
60500
+ `) + (this.state.pendingContent ? `
60501
+
60502
+ ${this.state.pendingContent}` : "");
60503
+ }
60504
+ this.state.currentPostId = null;
60505
+ this.state.currentPostContent = "";
60506
+ break;
60507
+ }
60508
+ lastPosted = { id: this.state.currentPostId, content: this.state.currentPostContent };
59683
60509
  if (i < chunks.length - 1) {
59684
60510
  this.state.currentPostId = null;
59685
60511
  this.state.currentPostContent = "";
@@ -59778,7 +60604,11 @@ class ContentExecutor extends BaseExecutor {
59778
60604
  const remainder = content.substring(breakPoint).trim();
59779
60605
  if (this.state.currentPostId) {
59780
60606
  const postId = this.state.currentPostId;
59781
- await this.tryUpdatePost(ctx, postId, firstPart, "handleSplit", { reason: "split_first_part", firstPartLength: firstPart.length, remainderLength: remainder.length }, { reason: "split_first_part_failed" }, () => {}, () => {});
60607
+ await this.tryUpdatePost(ctx, postId, firstPart, "handleSplit", { reason: "split_first_part", firstPartLength: firstPart.length, remainderLength: remainder.length }, { reason: "split_first_part_failed" }, () => {}, () => {
60608
+ if (postId === this.state.headerPostId) {
60609
+ this.state.headerBody = firstPart;
60610
+ }
60611
+ });
59782
60612
  }
59783
60613
  this.state.currentPostId = null;
59784
60614
  this.state.currentPostContent = "";
@@ -59787,9 +60617,22 @@ class ContentExecutor extends BaseExecutor {
59787
60617
  }
59788
60618
  }
59789
60619
  async createNewPost(ctx, content, pendingAtFlushStart) {
60620
+ const header = this.state.header;
60621
+ const becomesHeaderPost = this.state.turnOpen && this.state.headerPostId === null && header !== null;
60622
+ const rendered = becomesHeaderPost && header !== null ? content ? `${header}
60623
+
60624
+ ${content}` : header : content;
60625
+ const adoptAsHeaderPost = (postId) => {
60626
+ if (becomesHeaderPost) {
60627
+ this.state.headerPostId = postId;
60628
+ this.state.headerBody = content;
60629
+ this.state.headerDirty = false;
60630
+ }
60631
+ };
59790
60632
  if (this.onBumpTaskList) {
59791
- const bumpedPostId = await this.onBumpTaskList(content, ctx);
60633
+ const bumpedPostId = await this.onBumpTaskList(rendered, ctx);
59792
60634
  if (bumpedPostId) {
60635
+ adoptAsHeaderPost(bumpedPostId);
59793
60636
  this.state.currentPostId = bumpedPostId;
59794
60637
  this.state.currentPostContent = content;
59795
60638
  this.clearFlushedContent(pendingAtFlushStart);
@@ -59800,11 +60643,12 @@ class ContentExecutor extends BaseExecutor {
59800
60643
  if (this.onBumpTaskListToBottom) {
59801
60644
  await this.onBumpTaskListToBottom();
59802
60645
  }
59803
- return;
60646
+ return true;
59804
60647
  }
59805
60648
  }
59806
60649
  try {
59807
- const post = await ctx.createPost(content, { type: "content" });
60650
+ const post = await ctx.createPost(rendered, { type: "content" });
60651
+ adoptAsHeaderPost(post.id);
59808
60652
  this.state.currentPostId = post.id;
59809
60653
  this.state.currentPostContent = content;
59810
60654
  this.clearFlushedContent(pendingAtFlushStart);
@@ -59816,8 +60660,10 @@ class ContentExecutor extends BaseExecutor {
59816
60660
  if (this.onBumpTaskListToBottom) {
59817
60661
  await this.onBumpTaskListToBottom();
59818
60662
  }
60663
+ return true;
59819
60664
  } catch (err) {
59820
60665
  ctx.logger.error(`Failed to create post: ${err}`);
60666
+ return false;
59821
60667
  }
59822
60668
  }
59823
60669
  clearFlushedContent(flushedContent) {
@@ -59828,6 +60674,40 @@ class ContentExecutor extends BaseExecutor {
59828
60674
  }
59829
60675
  }
59830
60676
  }
60677
+ var FENCE_LINE = /^```.*$/gm;
60678
+ var FENCE_CLOSE = "\n```";
60679
+ function splitByLength(text, max) {
60680
+ const room = max - FENCE_CLOSE.length;
60681
+ if (room < 1)
60682
+ return [text];
60683
+ const pieces = [];
60684
+ let rest = text;
60685
+ while (rest.length > max) {
60686
+ let cut = rest.lastIndexOf(`
60687
+ `, room);
60688
+ if (cut < room * 0.5)
60689
+ cut = room;
60690
+ let piece = rest.slice(0, cut);
60691
+ let next = rest.slice(cut).replace(/^\n+/, "");
60692
+ const fences = piece.match(FENCE_LINE) ?? [];
60693
+ const opener = fences[fences.length - 1];
60694
+ if (fences.length % 2 === 1 && opener !== undefined && `${opener}
60695
+ ${next}`.length < rest.length) {
60696
+ piece += FENCE_CLOSE;
60697
+ next = `${opener}
60698
+ ${next}`;
60699
+ }
60700
+ pieces.push(piece);
60701
+ if (next.length >= rest.length) {
60702
+ rest = next;
60703
+ break;
60704
+ }
60705
+ rest = next;
60706
+ }
60707
+ if (rest)
60708
+ pieces.push(rest);
60709
+ return pieces;
60710
+ }
59831
60711
  // src/operations/executors/task-list.ts
59832
60712
  init_emoji();
59833
60713
  class TaskListExecutor extends BaseExecutor {
@@ -61339,6 +62219,8 @@ class MessageManager {
61339
62219
  platform;
61340
62220
  postTracker;
61341
62221
  contentBreaker;
62222
+ toolActivity;
62223
+ toolActivityExecutor = null;
61342
62224
  turnMarker;
61343
62225
  flushInFlight = null;
61344
62226
  turn = 0;
@@ -61430,6 +62312,39 @@ class MessageManager {
61430
62312
  updateLastMessage: options.updateLastMessage,
61431
62313
  events: this.events
61432
62314
  });
62315
+ this.toolActivity = options.toolActivity ?? { activity: "full", details: "none" };
62316
+ if (this.toolActivity.activity !== "full") {
62317
+ const sink = this.toolActivity.details === "thread" ? createThreadSink({
62318
+ contextFor: () => this.toolDetailsContext(),
62319
+ holdUntilTurnEnd: !isDcmThreadId(this.threadId),
62320
+ makeExecutor: () => new ContentExecutor({ registerPost: options.registerPost, updateLastMessage: () => {
62321
+ return;
62322
+ } })
62323
+ }) : noneSink;
62324
+ this.toolActivityExecutor = new ToolActivityExecutor({
62325
+ mode: this.toolActivity.activity,
62326
+ sink,
62327
+ onHeader: (line) => {
62328
+ this.contentExecutor.setHeader(line);
62329
+ this.scheduleFlush(this.getExecutorContext());
62330
+ }
62331
+ });
62332
+ }
62333
+ }
62334
+ toolDetailsContext() {
62335
+ const replyPost = this.contentExecutor.getHeaderPostId();
62336
+ if (!replyPost)
62337
+ return null;
62338
+ const root = isDcmThreadId(this.threadId) ? replyPost : this.threadId;
62339
+ const base = this.getExecutorContext();
62340
+ return {
62341
+ ...base,
62342
+ createPost: async (content, options) => {
62343
+ const post = await this.platform.createPost(content, root);
62344
+ this.registerPost(post.id, { ...options, type: "tool_details" });
62345
+ return post;
62346
+ }
62347
+ };
61433
62348
  }
61434
62349
  async handleEvent(event) {
61435
62350
  const logger = log16.forSession(this.sessionId);
@@ -61439,6 +62354,7 @@ class MessageManager {
61439
62354
  toolStartTimes: this.toolStartTimes,
61440
62355
  taskTracker: this.taskTracker,
61441
62356
  detailed: true,
62357
+ toolActivity: this.toolActivity.activity,
61442
62358
  worktreeInfo: this.worktreePath && this.worktreeBranch ? { path: this.worktreePath, branch: this.worktreeBranch } : undefined
61443
62359
  };
61444
62360
  const ops = transformEvent(event, transformCtx);
@@ -61491,6 +62407,10 @@ class MessageManager {
61491
62407
  try {
61492
62408
  if (isContentOp(op)) {
61493
62409
  await this.handleContentOp(op, ctx);
62410
+ } else if (isToolActivityOp(op)) {
62411
+ if (op.kind === "start")
62412
+ this.contentExecutor.markParagraphBreak();
62413
+ await this.toolActivityExecutor?.execute(op, ctx);
61494
62414
  } else if (isFlushOp(op)) {
61495
62415
  await this.handleFlushOp(op, ctx);
61496
62416
  } else if (isTaskListOp(op)) {
@@ -61530,25 +62450,26 @@ class MessageManager {
61530
62450
  await this.flushInFlight.catch(() => {
61531
62451
  return;
61532
62452
  });
61533
- if (op.reason === "result")
61534
- this.turn++;
62453
+ const turn = op.reason === "result" ? ++this.turn : this.turn;
61535
62454
  await this.runTrackedFlush(op, ctx);
61536
62455
  if (op.reason === "result") {
61537
- await this.markTurnComplete(ctx, op.resultOk !== false);
62456
+ await this.toolActivityExecutor?.afterResultFlush(ctx);
62457
+ await this.markTurnComplete(ctx, op.resultOk !== false, turn);
61538
62458
  }
61539
62459
  }
61540
- async markTurnComplete(ctx, ok) {
62460
+ async markTurnComplete(ctx, ok, turn) {
61541
62461
  if (this.turnMarker.mode === "off")
61542
62462
  return;
61543
- const { currentPostId, currentPostContent } = this.contentExecutor.getState();
61544
- if (!currentPostId)
62463
+ const current = this.contentExecutor.getRenderedCurrentPost();
62464
+ if (!current)
61545
62465
  return;
62466
+ const { postId: currentPostId, text: currentPostText } = current;
61546
62467
  try {
61547
62468
  if (this.turnMarker.mode === "metadata") {
61548
- await this.platform.updatePost(currentPostId, currentPostContent, {
62469
+ await this.platform.updatePost(currentPostId, currentPostText, {
61549
62470
  metadata: {
61550
62471
  event_type: TURN_COMPLETE_EVENT_TYPE,
61551
- event_payload: { v: TURN_COMPLETE_PAYLOAD_VERSION, session: this.sessionId, turn: this.turn, ok }
62472
+ event_payload: { v: TURN_COMPLETE_PAYLOAD_VERSION, session: this.sessionId, turn, ok }
61552
62473
  }
61553
62474
  });
61554
62475
  } else {
@@ -61568,6 +62489,7 @@ class MessageManager {
61568
62489
  });
61569
62490
  this.flushInFlight = running;
61570
62491
  await running;
62492
+ this.toolActivityExecutor?.wake();
61571
62493
  }
61572
62494
  scheduleFlush(ctx) {
61573
62495
  if (this.flushTimer)
@@ -61964,15 +62886,21 @@ class MessageManager {
61964
62886
  this.pendingBridgeQuestion = null;
61965
62887
  }
61966
62888
  clearClaudeSessionState() {
62889
+ this.clearTurnState();
61967
62890
  this.toolStartTimes.clear();
61968
62891
  this.taskTracker.clear();
61969
62892
  this.denyPendingBridgeRequests("Claude was restarted before a decision was made");
61970
62893
  }
62894
+ clearTurnState() {
62895
+ this.toolActivityExecutor?.reset();
62896
+ this.contentExecutor.abandonHeaderTurn();
62897
+ }
61971
62898
  reset() {
61972
62899
  this.cancelScheduledFlush();
61973
62900
  this.toolStartTimes.clear();
61974
62901
  this.taskTracker.clear();
61975
62902
  this.contentExecutor.reset();
62903
+ this.toolActivityExecutor?.reset();
61976
62904
  this.taskListExecutor.reset();
61977
62905
  this.questionApprovalExecutor.reset();
61978
62906
  this.messageApprovalExecutor.reset();
@@ -65315,6 +66243,7 @@ async function restartClaudeSession(session, cliOptions, ctx, actionName) {
65315
66243
  await session.claude.kill();
65316
66244
  await ctx.ops.flush(session);
65317
66245
  session.messageManager?.denyPendingBridgeRequests("Claude was restarted before a decision was made");
66246
+ session.messageManager?.clearTurnState();
65318
66247
  if (!cliOptions.resume) {
65319
66248
  session.messageManager?.clearClaudeSessionState();
65320
66249
  }
@@ -66834,6 +67763,7 @@ function createMessageManager(session, ctx) {
66834
67763
  sessionId: session.sessionId,
66835
67764
  worktreePath: session.worktreeInfo?.worktreePath,
66836
67765
  worktreeBranch: session.worktreeInfo?.branch,
67766
+ toolActivity: ctx.ops.getPlatformOverhead(session.platformId).tools,
66837
67767
  turnMarker: ctx.ops.getPlatformOverhead(session.platformId).turnMarker,
66838
67768
  registerPost: (postId, options) => {
66839
67769
  ctx.ops.registerPost(postId, session.threadId);
@@ -72487,7 +73417,8 @@ class SessionManager extends EventEmitter4 {
72487
73417
  sessionHeader: options?.overhead?.sessionHeader ?? DEFAULT_OVERHEAD_VISIBILITY,
72488
73418
  stickyMessage: options?.overhead?.stickyMessage ?? DEFAULT_OVERHEAD_VISIBILITY,
72489
73419
  lifecycle: options?.overhead?.lifecycle ?? DEFAULT_OVERHEAD_VISIBILITY,
72490
- turnMarker: options?.overhead?.turnMarker ?? DEFAULT_TURN_MARKER
73420
+ turnMarker: options?.overhead?.turnMarker ?? DEFAULT_TURN_MARKER,
73421
+ tools: options?.overhead?.tools ?? DEFAULT_TOOL_ACTIVITY
72491
73422
  });
72492
73423
  this.platformMemory.set(platformId, options?.memory ?? DEFAULT_MEMORY_CONFIG);
72493
73424
  this.platformRoutines.set(platformId, options?.routinesEnabled ?? true);
@@ -72627,7 +73558,8 @@ class SessionManager extends EventEmitter4 {
72627
73558
  sessionHeader: DEFAULT_OVERHEAD_VISIBILITY,
72628
73559
  stickyMessage: DEFAULT_OVERHEAD_VISIBILITY,
72629
73560
  lifecycle: DEFAULT_OVERHEAD_VISIBILITY,
72630
- turnMarker: DEFAULT_TURN_MARKER
73561
+ turnMarker: DEFAULT_TURN_MARKER,
73562
+ tools: DEFAULT_TOOL_ACTIVITY
72631
73563
  },
72632
73564
  getPlatformMemoryConfig: (pid) => this.platformMemory.get(pid) ?? DEFAULT_MEMORY_CONFIG,
72633
73565
  isRoutinesEnabled: (pid) => this.platformRoutines.get(pid) ?? true,
@@ -73708,7 +74640,7 @@ var isSharedWorker = typeof SharedWorkerGlobalScope !== "undefined" && globalThi
73708
74640
  var isServiceWorker = typeof ServiceWorkerGlobalScope !== "undefined" && globalThis instanceof ServiceWorkerGlobalScope;
73709
74641
  var platform = globalThis.navigator?.userAgentData?.platform;
73710
74642
  var isMacOs = platform === "macOS" || globalThis.navigator?.platform === "MacIntel" || globalThis.navigator?.userAgent?.includes(" Mac ") === true || globalThis.process?.platform === "darwin";
73711
- var isWindows3 = platform === "Windows" || globalThis.navigator?.platform === "Win32" || globalThis.process?.platform === "win32";
74643
+ var isWindows2 = platform === "Windows" || globalThis.navigator?.platform === "Win32" || globalThis.process?.platform === "win32";
73712
74644
  var isLinux = platform === "Linux" || globalThis.navigator?.platform?.startsWith("Linux") === true || globalThis.navigator?.userAgent?.includes(" Linux ") === true || globalThis.process?.platform === "linux";
73713
74645
  var isIos = platform === "iOS" || globalThis.navigator?.platform === "MacIntel" && globalThis.navigator?.maxTouchPoints > 1 || /iPad|iPhone|iPod/.test(globalThis.navigator?.platform);
73714
74646
  var isAndroid = platform === "Android" || globalThis.navigator?.platform === "Android" || globalThis.navigator?.userAgent?.includes(" Android ") === true || globalThis.process?.platform === "android";
@@ -73717,7 +74649,7 @@ var isAndroid = platform === "Android" || globalThis.navigator?.platform === "An
73717
74649
  var ESC = "\x1B[";
73718
74650
  var SEP = ";";
73719
74651
  var isTerminalApp = !isBrowser && process11.env.TERM_PROGRAM === "Apple_Terminal";
73720
- var isWindows4 = !isBrowser && process11.platform === "win32";
74652
+ var isWindows3 = !isBrowser && process11.platform === "win32";
73721
74653
  var isTmux = !isBrowser && (process11.env.TERM?.startsWith("screen") || process11.env.TERM?.startsWith("tmux") || process11.env.TMUX !== undefined);
73722
74654
  var cwdFunction = isBrowser ? () => {
73723
74655
  throw new Error("`process.cwd()` only works in Node.js, not the browser.");
@@ -73761,7 +74693,7 @@ var scrollUp = ESC + "S";
73761
74693
  var scrollDown = ESC + "T";
73762
74694
  var clearViewport = `${eraseScreen}${ESC}H`;
73763
74695
  var isOldWindows = () => {
73764
- if (isBrowser || !isWindows4) {
74696
+ if (isBrowser || !isWindows3) {
73765
74697
  return false;
73766
74698
  }
73767
74699
  const parts = os5.release().split(".");
@@ -86036,37 +86968,37 @@ class UpdateScheduler extends EventEmitter8 {
86036
86968
  }
86037
86969
 
86038
86970
  // src/auto-update/installer.ts
86971
+ init_spawn();
86039
86972
  init_state_home();
86040
- import { spawn as spawn4, spawnSync } from "child_process";
86041
86973
  import { existsSync as existsSync17, readFileSync as readFileSync12, mkdirSync as mkdirSync8 } from "fs";
86042
86974
  import { dirname as dirname9, resolve as resolve8 } from "path";
86043
86975
  import { homedir as homedir3 } from "os";
86044
86976
  init_logger();
86045
86977
  var log56 = createLogger("installer");
86046
86978
  function detectPackageManager() {
86047
- const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
86979
+ const npmCmd = "npm";
86048
86980
  const originalInstaller = detectOriginalInstaller();
86049
86981
  if (originalInstaller) {
86050
86982
  log56.debug(`Detected original installer: ${originalInstaller}`);
86051
86983
  if (originalInstaller === "bun") {
86052
- const bunCheck = spawnSync("bun", ["--version"], { stdio: "ignore" });
86984
+ const bunCheck = crossSpawnSync("bun", ["--version"], { stdio: "ignore" });
86053
86985
  if (bunCheck.status === 0) {
86054
86986
  return { cmd: "bun", isBun: true };
86055
86987
  }
86056
86988
  log56.warn("Originally installed with bun, but bun not found. Falling back to npm.");
86057
86989
  } else {
86058
- const npmCheck = spawnSync(npmCmd, ["--version"], { stdio: "ignore" });
86990
+ const npmCheck = crossSpawnSync(npmCmd, ["--version"], { stdio: "ignore" });
86059
86991
  if (npmCheck.status === 0) {
86060
86992
  return { cmd: npmCmd, isBun: false };
86061
86993
  }
86062
86994
  log56.warn("Originally installed with npm, but npm not found. Falling back to bun.");
86063
86995
  }
86064
86996
  }
86065
- const bunCheck = spawnSync("bun", ["--version"], { stdio: "ignore" });
86997
+ const bunCheck = crossSpawnSync("bun", ["--version"], { stdio: "ignore" });
86066
86998
  if (bunCheck.status === 0) {
86067
86999
  return { cmd: "bun", isBun: true };
86068
87000
  }
86069
- const npmCheck = spawnSync(npmCmd, ["--version"], { stdio: "ignore" });
87001
+ const npmCheck = crossSpawnSync(npmCmd, ["--version"], { stdio: "ignore" });
86070
87002
  if (npmCheck.status === 0) {
86071
87003
  return { cmd: npmCmd, isBun: false };
86072
87004
  }
@@ -86085,13 +87017,12 @@ function detectOriginalInstaller() {
86085
87017
  if (scriptPath.startsWith(bunGlobalDir)) {
86086
87018
  return "bun";
86087
87019
  }
86088
- const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
86089
- const npmPrefixResult = spawnSync(npmCmd, ["prefix", "-g"], {
87020
+ const npmPrefixResult = crossSpawnSync("npm", ["prefix", "-g"], {
86090
87021
  encoding: "utf-8",
86091
87022
  stdio: ["ignore", "pipe", "ignore"]
86092
87023
  });
86093
87024
  if (npmPrefixResult.status === 0 && npmPrefixResult.stdout) {
86094
- const npmPrefix = normalizePath(npmPrefixResult.stdout.trim());
87025
+ const npmPrefix = normalizePath(String(npmPrefixResult.stdout).trim());
86095
87026
  if (scriptPath.startsWith(npmPrefix)) {
86096
87027
  return "npm";
86097
87028
  }
@@ -86181,7 +87112,7 @@ async function installVersion(version) {
86181
87112
  const { cmd, isBun } = pm;
86182
87113
  const args = ["install", "-g", `${PACKAGE_NAME2}@${version}`];
86183
87114
  log56.debug(`Using ${isBun ? "bun" : "npm"} for installation`);
86184
- const child = spawn4(cmd, args, {
87115
+ const child = crossSpawn(cmd, args, {
86185
87116
  stdio: ["ignore", "pipe", "pipe"],
86186
87117
  env: {
86187
87118
  ...process.env,
@@ -86264,7 +87195,7 @@ class UpdateInstaller {
86264
87195
 
86265
87196
  // src/auto-update/respawn.ts
86266
87197
  init_logger();
86267
- import { spawn as spawn5 } from "child_process";
87198
+ init_spawn();
86268
87199
  import { existsSync as existsSync18, statSync as statSync5 } from "fs";
86269
87200
  import { delimiter, join as join18 } from "path";
86270
87201
  var log57 = createLogger("respawn");
@@ -86334,14 +87265,12 @@ function spawnReplacement(argv = process.argv.slice(2), binPath = resolveClaudeT
86334
87265
  const childEnv = { ...process.env };
86335
87266
  delete childEnv.CLAUDE_THREADS_BIN;
86336
87267
  delete childEnv.CLAUDE_THREADS_INTERACTIVE;
86337
- const useShell = process.platform === "win32";
86338
87268
  let child;
86339
87269
  try {
86340
- child = spawn5(binPath, argv, {
87270
+ child = crossSpawn(binPath, argv, {
86341
87271
  detached: true,
86342
87272
  stdio: "inherit",
86343
- env: childEnv,
86344
- shell: useShell
87273
+ env: childEnv
86345
87274
  });
86346
87275
  } catch (err) {
86347
87276
  log57.error(`spawn() threw: ${err instanceof Error ? err.message : String(err)}`);
@@ -86708,6 +87637,8 @@ async function main() {
86708
87637
  const { spawn } = await import("child_process");
86709
87638
  const { dirname, resolve } = await import("path");
86710
87639
  const { fileURLToPath } = await import("url");
87640
+ const { existsSync } = await import("fs");
87641
+ await Promise.resolve().then(() => init_spawn());
86711
87642
  const __filename2 = fileURLToPath(import.meta.url);
86712
87643
  const __dirname2 = dirname(__filename2);
86713
87644
  const daemonPath = resolve(__dirname2, "..", "bin", "claude-threads-daemon");
@@ -86717,7 +87648,14 @@ async function main() {
86717
87648
  const binPath = __filename2;
86718
87649
  let child;
86719
87650
  if (process.platform === "win32") {
86720
- child = spawn("bash", [daemonPath, "--restart-on-error", ...args], {
87651
+ const bashPath = findWindowsGitBash(process.env, existsSync);
87652
+ if (!bashPath) {
87653
+ console.error("Auto-restart requires Git for Windows (bash.exe). Starting without auto-restart...");
87654
+ console.error("");
87655
+ await startWithoutDaemon();
87656
+ return;
87657
+ }
87658
+ child = spawn(bashPath, [daemonPath, "--restart-on-error", ...args], {
86721
87659
  stdio: "inherit",
86722
87660
  env: {
86723
87661
  ...process.env,
@@ -87046,7 +87984,8 @@ async function startWithoutDaemon() {
87046
87984
  session.addPlatform(platformConfig.id, client, {
87047
87985
  overhead: {
87048
87986
  ...resolvePresentationOverhead(platformConfig, `platforms[${platformConfig.id}]`),
87049
- turnMarker: resolveTurnMarker(platformConfig.turnMarker, platformConfig.turnMarkerEmoji, platformConfig.type, `platforms[${platformConfig.id}]`)
87987
+ turnMarker: resolveTurnMarker(platformConfig.turnMarker, platformConfig.turnMarkerEmoji, platformConfig.type, `platforms[${platformConfig.id}]`),
87988
+ tools: resolveToolActivity(platformConfig.toolActivity, platformConfig.toolDetails, `platforms[${platformConfig.id}]`)
87050
87989
  },
87051
87990
  memory: resolveMemoryConfig(platformConfig.memory, `platforms[${platformConfig.id}].memory`),
87052
87991
  routinesEnabled: resolveRoutinesEnabled(platformConfig.routines, `platforms[${platformConfig.id}].routines`),
@@ -87074,6 +88013,7 @@ async function startWithoutDaemon() {
87074
88013
  overhead: {
87075
88014
  ...resolvePresentationOverhead(dmConfig, `dm[${dmConfig.id}]`),
87076
88015
  stickyMessage: "hidden",
88016
+ tools: resolveToolActivity(dmConfig.toolActivity, dmConfig.toolDetails, `dm[${dmConfig.id}]`),
87077
88017
  turnMarker: resolveTurnMarker(dmConfig.turnMarker, dmConfig.turnMarkerEmoji, dmConfig.type, `dm[${dmConfig.id}]`)
87078
88018
  },
87079
88019
  memory: resolveMemoryConfig(dmConfig.memory, `dm[${dmConfig.id}].memory`),