@linzumi/cli 0.0.51-beta → 0.0.52-beta

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
@@ -4,21 +4,35 @@ var __getProtoOf = Object.getPrototypeOf;
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ function __accessProp(key) {
8
+ return this[key];
9
+ }
10
+ var __toESMCache_node;
11
+ var __toESMCache_esm;
7
12
  var __toESM = (mod, isNodeMode, target) => {
13
+ var canCache = mod != null && typeof mod === "object";
14
+ if (canCache) {
15
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
16
+ var cached = cache.get(mod);
17
+ if (cached)
18
+ return cached;
19
+ }
8
20
  target = mod != null ? __create(__getProtoOf(mod)) : {};
9
21
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
22
  for (let key of __getOwnPropNames(mod))
11
23
  if (!__hasOwnProp.call(to, key))
12
24
  __defProp(to, key, {
13
- get: () => mod[key],
25
+ get: __accessProp.bind(mod, key),
14
26
  enumerable: true
15
27
  });
28
+ if (canCache)
29
+ cache.set(mod, to);
16
30
  return to;
17
31
  };
18
32
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
19
33
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
20
34
 
21
- // ../../node_modules/yoctocolors-cjs/index.js
35
+ // node_modules/yoctocolors-cjs/index.js
22
36
  var require_yoctocolors_cjs = __commonJS((exports, module) => {
23
37
  var tty = __require("node:tty");
24
38
  var hasColors = tty?.WriteStream?.prototype?.hasColors?.() ?? false;
@@ -92,7 +106,7 @@ var require_yoctocolors_cjs = __commonJS((exports, module) => {
92
106
  module.exports = colors;
93
107
  });
94
108
 
95
- // ../../node_modules/cli-width/index.js
109
+ // node_modules/cli-width/index.js
96
110
  var require_cli_width = __commonJS((exports, module) => {
97
111
  module.exports = cliWidth;
98
112
  function normalizeOpts(options) {
@@ -132,7 +146,7 @@ var require_cli_width = __commonJS((exports, module) => {
132
146
  }
133
147
  });
134
148
 
135
- // ../../node_modules/ansi-regex/index.js
149
+ // node_modules/ansi-regex/index.js
136
150
  var require_ansi_regex = __commonJS((exports, module) => {
137
151
  module.exports = ({ onlyFirst = false } = {}) => {
138
152
  const pattern = [
@@ -143,13 +157,13 @@ var require_ansi_regex = __commonJS((exports, module) => {
143
157
  };
144
158
  });
145
159
 
146
- // ../../node_modules/strip-ansi/index.js
160
+ // node_modules/strip-ansi/index.js
147
161
  var require_strip_ansi = __commonJS((exports, module) => {
148
162
  var ansiRegex = require_ansi_regex();
149
163
  module.exports = (string) => typeof string === "string" ? string.replace(ansiRegex(), "") : string;
150
164
  });
151
165
 
152
- // ../../node_modules/string-width/node_modules/is-fullwidth-code-point/index.js
166
+ // node_modules/is-fullwidth-code-point/index.js
153
167
  var require_is_fullwidth_code_point = __commonJS((exports, module) => {
154
168
  var isFullwidthCodePoint = (codePoint) => {
155
169
  if (Number.isNaN(codePoint)) {
@@ -164,14 +178,14 @@ var require_is_fullwidth_code_point = __commonJS((exports, module) => {
164
178
  module.exports.default = isFullwidthCodePoint;
165
179
  });
166
180
 
167
- // ../../node_modules/string-width/node_modules/emoji-regex/index.js
181
+ // node_modules/emoji-regex/index.js
168
182
  var require_emoji_regex = __commonJS((exports, module) => {
169
183
  module.exports = function() {
170
184
  return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
171
185
  };
172
186
  });
173
187
 
174
- // ../../node_modules/string-width/index.js
188
+ // node_modules/string-width/index.js
175
189
  var require_string_width = __commonJS((exports, module) => {
176
190
  var stripAnsi = require_strip_ansi();
177
191
  var isFullwidthCodePoint = require_is_fullwidth_code_point();
@@ -205,7 +219,7 @@ var require_string_width = __commonJS((exports, module) => {
205
219
  module.exports.default = stringWidth;
206
220
  });
207
221
 
208
- // ../../node_modules/color-name/index.js
222
+ // node_modules/color-name/index.js
209
223
  var require_color_name = __commonJS((exports, module) => {
210
224
  module.exports = {
211
225
  aliceblue: [240, 248, 255],
@@ -359,7 +373,7 @@ var require_color_name = __commonJS((exports, module) => {
359
373
  };
360
374
  });
361
375
 
362
- // ../../node_modules/color-convert/conversions.js
376
+ // node_modules/color-convert/conversions.js
363
377
  var require_conversions = __commonJS((exports, module) => {
364
378
  var cssKeywords = require_color_name();
365
379
  var reverseKeywords = {};
@@ -1028,7 +1042,7 @@ var require_conversions = __commonJS((exports, module) => {
1028
1042
  };
1029
1043
  });
1030
1044
 
1031
- // ../../node_modules/color-convert/route.js
1045
+ // node_modules/color-convert/route.js
1032
1046
  var require_route = __commonJS((exports, module) => {
1033
1047
  var conversions = require_conversions();
1034
1048
  function buildGraph() {
@@ -1094,7 +1108,7 @@ var require_route = __commonJS((exports, module) => {
1094
1108
  };
1095
1109
  });
1096
1110
 
1097
- // ../../node_modules/color-convert/index.js
1111
+ // node_modules/color-convert/index.js
1098
1112
  var require_color_convert = __commonJS((exports, module) => {
1099
1113
  var conversions = require_conversions();
1100
1114
  var route = require_route();
@@ -1153,7 +1167,7 @@ var require_color_convert = __commonJS((exports, module) => {
1153
1167
  module.exports = convert;
1154
1168
  });
1155
1169
 
1156
- // ../../node_modules/ansi-styles/index.js
1170
+ // node_modules/ansi-styles/index.js
1157
1171
  var require_ansi_styles = __commonJS((exports, module) => {
1158
1172
  var wrapAnsi16 = (fn, offset) => (...args) => {
1159
1173
  const code = fn(...args);
@@ -1289,7 +1303,7 @@ var require_ansi_styles = __commonJS((exports, module) => {
1289
1303
  });
1290
1304
  });
1291
1305
 
1292
- // ../../node_modules/@inquirer/core/node_modules/wrap-ansi/index.js
1306
+ // node_modules/wrap-ansi/index.js
1293
1307
  var require_wrap_ansi = __commonJS((exports, module) => {
1294
1308
  var stringWidth = require_string_width();
1295
1309
  var stripAnsi = require_strip_ansi();
@@ -1425,7 +1439,7 @@ var require_wrap_ansi = __commonJS((exports, module) => {
1425
1439
  };
1426
1440
  });
1427
1441
 
1428
- // ../../node_modules/mute-stream/lib/index.js
1442
+ // node_modules/mute-stream/lib/index.js
1429
1443
  var require_lib = __commonJS((exports, module) => {
1430
1444
  var Stream = __require("stream");
1431
1445
 
@@ -1757,6 +1771,7 @@ function localRunnerPayload(options, instanceId, eventType, codexThreadId, conte
1757
1771
  fast: options.fast ?? false,
1758
1772
  sandbox: options.channelSession?.sandbox ?? null,
1759
1773
  approval_policy: options.channelSession?.approvalPolicy ?? null,
1774
+ allow_port_forwarding_by_default: options.channelSession?.allowPortForwardingByDefault ?? null,
1760
1775
  user_id: context.runnerIdentity.actorUserId ?? null,
1761
1776
  ...sourceMessageSeq === undefined ? {} : { source_message_seq: sourceMessageSeq }
1762
1777
  }
@@ -3362,8 +3377,17 @@ function reviewPortForwardCandidate(options) {
3362
3377
  reason: "listener_changed"
3363
3378
  };
3364
3379
  }
3365
- if (options.pendingRequests.some((request) => request.port === options.candidate.port)) {
3366
- return { type: "skip", reason: "already_pending" };
3380
+ const pendingRequest = options.pendingRequests.find((request) => request.port === options.candidate.port);
3381
+ if (pendingRequest !== undefined) {
3382
+ if (sameForwardCandidate(approvedTargetFromRequest(pendingRequest), options.candidate)) {
3383
+ return { type: "skip", reason: "already_pending" };
3384
+ }
3385
+ return {
3386
+ type: "replace_pending",
3387
+ expired: pendingRequest,
3388
+ candidate: options.candidate,
3389
+ reason: "listener_changed"
3390
+ };
3367
3391
  }
3368
3392
  return { type: "prompt", candidate: options.candidate };
3369
3393
  }
@@ -4319,7 +4343,7 @@ async function bindChannelSession(args, state, payloadContext) {
4319
4343
  }
4320
4344
  async function handleChannelSessionControl(args, state, payloadContext, control) {
4321
4345
  if (control.type === "update_session_settings") {
4322
- return updateSessionSettings(args, state, control);
4346
+ return updateSessionSettings(args, state, payloadContext, control);
4323
4347
  }
4324
4348
  if (control.type === "resolve_codex_approval_request") {
4325
4349
  return resolvePendingCodexApprovalRequest(args, state, control);
@@ -4386,7 +4410,7 @@ async function handleChannelSessionControl(args, state, payloadContext, control)
4386
4410
  interruptedQueuedMessages: interrupted.ok ? interrupted.selectedCount : 0
4387
4411
  };
4388
4412
  }
4389
- async function updateSessionSettings(args, state, control) {
4413
+ async function updateSessionSettings(args, state, payloadContext, control) {
4390
4414
  if (state.codexThreadId !== control.threadId) {
4391
4415
  return;
4392
4416
  }
@@ -4410,8 +4434,12 @@ async function updateSessionSettings(args, state, control) {
4410
4434
  reasoning_effort: state.runtimeSettings.reasoningEffort ?? null,
4411
4435
  approval_policy: state.runtimeSettings.approvalPolicy ?? null,
4412
4436
  sandbox: state.runtimeSettings.sandbox ?? null,
4413
- fast: state.runtimeSettings.fast ?? null
4437
+ fast: state.runtimeSettings.fast ?? null,
4438
+ allow_port_forwarding_by_default: state.runtimeSettings.allowPortForwardingByDefault ?? null
4414
4439
  });
4440
+ if (state.runtimeSettings.allowPortForwardingByDefault === true) {
4441
+ await approvePendingPortForwardRequestsByDefault(args, state, payloadContext);
4442
+ }
4415
4443
  await tryResumeCodexThreadForPendingRuntimeSettings(args, state);
4416
4444
  return {
4417
4445
  instanceId: args.instanceId,
@@ -4420,7 +4448,8 @@ async function updateSessionSettings(args, state, control) {
4420
4448
  reasoningEffort: state.runtimeSettings.reasoningEffort ?? null,
4421
4449
  approvalPolicy: state.runtimeSettings.approvalPolicy ?? null,
4422
4450
  sandbox: state.runtimeSettings.sandbox ?? null,
4423
- fast: state.runtimeSettings.fast ?? null
4451
+ fast: state.runtimeSettings.fast ?? null,
4452
+ allowPortForwardingByDefault: state.runtimeSettings.allowPortForwardingByDefault ?? null
4424
4453
  };
4425
4454
  }
4426
4455
  async function resumeCodexThreadForPendingRuntimeSettings(args, state) {
@@ -4570,6 +4599,29 @@ async function resolvePendingPortForwardRequest(args, state, payloadContext, con
4570
4599
  await drainQueuedPortForwardPrompt(args, state, payloadContext);
4571
4600
  return { instanceId: args.instanceId, ok: true };
4572
4601
  }
4602
+ await approvePortForwardRequest(args, state, payloadContext, request, {
4603
+ publishMessageState: true,
4604
+ logEvent: "port_forward.request_approved"
4605
+ });
4606
+ await drainQueuedPortForwardPrompt(args, state, payloadContext);
4607
+ return { instanceId: args.instanceId, ok: true, port: request.port };
4608
+ }
4609
+ async function expirePendingPortForwardRequest(args, state, request, reason) {
4610
+ const failedReason = reason === "listener_exited" ? "port_forward_listener_exited" : "port_forward_listener_changed";
4611
+ state.pendingPortForwardRequests.delete(request.requestId);
4612
+ await publishForwardPortResolvedEvent(args, request, {
4613
+ decision: "expired",
4614
+ reason
4615
+ });
4616
+ await publishMessageStateForPortForwardResult(args, state, request, "failed", failedReason);
4617
+ args.log("port_forward.pending_request_expired", {
4618
+ request_id: request.requestId,
4619
+ port: request.port,
4620
+ pid: request.pid,
4621
+ reason
4622
+ });
4623
+ }
4624
+ async function approvePortForwardRequest(args, state, payloadContext, request, options) {
4573
4625
  state.approvedForwardPorts.add(request.port);
4574
4626
  state.approvedForwardTargets.set(request.port, approvedTargetFromRequest(request));
4575
4627
  const processIdentity = guessCanonicalProcessFromCommand(request.command);
@@ -4584,15 +4636,15 @@ async function resolvePendingPortForwardRequest(args, state, payloadContext, con
4584
4636
  decision: "approve",
4585
4637
  capabilities
4586
4638
  });
4587
- await publishMessageStateForPortForwardResult(args, state, request, "processed");
4639
+ if (options.publishMessageState) {
4640
+ await publishMessageStateForPortForwardResult(args, state, request, "processed");
4641
+ }
4588
4642
  await publishPortForwardReadyMessage(args, state, payloadContext, request);
4589
- args.log("port_forward.request_approved", {
4590
- request_id: control.requestId,
4643
+ args.log(options.logEvent, {
4644
+ request_id: request.requestId,
4591
4645
  port: request.port,
4592
4646
  pid: request.pid
4593
4647
  });
4594
- await drainQueuedPortForwardPrompt(args, state, payloadContext);
4595
- return { instanceId: args.instanceId, ok: true, port: request.port };
4596
4648
  }
4597
4649
  function portForwardControlSenderAllowed(args, payloadContext, control) {
4598
4650
  if (control.actorSlug === undefined && control.actorUserId === undefined) {
@@ -4621,6 +4673,7 @@ async function publishPortForwardPrompt(args, state, payloadContext, candidate)
4621
4673
  dismissedTargets: state.dismissedForwardTargets,
4622
4674
  pendingRequests: Array.from(state.pendingPortForwardRequests.values())
4623
4675
  });
4676
+ const allowByDefault = state.runtimeSettings.allowPortForwardingByDefault === true;
4624
4677
  switch (review.type) {
4625
4678
  case "skip":
4626
4679
  return;
@@ -4628,7 +4681,7 @@ async function publishPortForwardPrompt(args, state, payloadContext, candidate)
4628
4681
  state.approvedForwardTargets.set(review.target.port, review.target);
4629
4682
  return;
4630
4683
  case "revoke_and_prompt":
4631
- if (state.pendingPortForwardRequests.size > 0) {
4684
+ if (state.pendingPortForwardRequests.size > 0 && !allowByDefault) {
4632
4685
  state.queuedPortForwardCandidates.set(candidate.port, candidate);
4633
4686
  args.log("port_forward.request_queued", {
4634
4687
  port: candidate.port,
@@ -4638,8 +4691,32 @@ async function publishPortForwardPrompt(args, state, payloadContext, candidate)
4638
4691
  return;
4639
4692
  }
4640
4693
  await revokeApprovedForwardPort(args, state, review.revoked, review.reason);
4694
+ if (allowByDefault) {
4695
+ await autoApprovePortForwardCandidate(args, state, payloadContext, candidate);
4696
+ return;
4697
+ }
4698
+ break;
4699
+ case "replace_pending":
4700
+ await expirePendingPortForwardRequest(args, state, review.expired, review.reason);
4701
+ if (allowByDefault) {
4702
+ await autoApprovePortForwardCandidate(args, state, payloadContext, review.candidate);
4703
+ return;
4704
+ }
4705
+ if (state.pendingPortForwardRequests.size > 0) {
4706
+ state.queuedPortForwardCandidates.set(review.candidate.port, review.candidate);
4707
+ args.log("port_forward.request_queued", {
4708
+ port: review.candidate.port,
4709
+ pid: review.candidate.pid,
4710
+ pending_count: state.pendingPortForwardRequests.size
4711
+ });
4712
+ return;
4713
+ }
4641
4714
  break;
4642
4715
  case "prompt":
4716
+ if (allowByDefault) {
4717
+ await autoApprovePortForwardCandidate(args, state, payloadContext, candidate);
4718
+ return;
4719
+ }
4643
4720
  if (state.pendingPortForwardRequests.size > 0) {
4644
4721
  state.queuedPortForwardCandidates.set(candidate.port, candidate);
4645
4722
  args.log("port_forward.request_queued", {
@@ -4717,6 +4794,45 @@ async function publishPortForwardPrompt(args, state, payloadContext, candidate)
4717
4794
  pid: candidate.pid
4718
4795
  });
4719
4796
  }
4797
+ async function autoApprovePortForwardCandidate(args, state, payloadContext, candidate) {
4798
+ const sourceSeq = portForwardApprovalSourceSeq(state);
4799
+ if (sourceSeq === undefined) {
4800
+ args.log("port_forward.auto_approval_skipped", {
4801
+ port: candidate.port,
4802
+ pid: candidate.pid,
4803
+ reason: "source_seq_missing"
4804
+ });
4805
+ return;
4806
+ }
4807
+ const request = pendingRequestFromCandidate({
4808
+ requestId: `port-forward-auto-${randomUUID()}`,
4809
+ sourceSeq,
4810
+ candidate
4811
+ });
4812
+ await approvePortForwardRequest(args, state, payloadContext, request, {
4813
+ publishMessageState: false,
4814
+ logEvent: "port_forward.request_auto_approved"
4815
+ });
4816
+ }
4817
+ async function approvePendingPortForwardRequestsByDefault(args, state, payloadContext) {
4818
+ for (const request of Array.from(state.pendingPortForwardRequests.values())) {
4819
+ state.pendingPortForwardRequests.delete(request.requestId);
4820
+ await approvePortForwardRequest(args, state, payloadContext, request, {
4821
+ publishMessageState: true,
4822
+ logEvent: "port_forward.request_auto_approved"
4823
+ });
4824
+ }
4825
+ await drainQueuedPortForwardPromptsByDefault(args, state, payloadContext);
4826
+ }
4827
+ async function drainQueuedPortForwardPromptsByDefault(args, state, payloadContext) {
4828
+ const next = Array.from(state.queuedPortForwardCandidates.values()).sort((left, right) => left.port - right.port)[0];
4829
+ if (next === undefined) {
4830
+ return;
4831
+ }
4832
+ state.queuedPortForwardCandidates.delete(next.port);
4833
+ await publishPortForwardPrompt(args, state, payloadContext, next);
4834
+ await drainQueuedPortForwardPromptsByDefault(args, state, payloadContext);
4835
+ }
4720
4836
  function portForwardApprovalSourceSeq(state) {
4721
4837
  return state.activeProcessingState?.seq ?? state.rootSeq;
4722
4838
  }
@@ -4750,18 +4866,7 @@ async function expireLostPendingPortForwardRequest(args, state, payloadContext,
4750
4866
  if (request === undefined) {
4751
4867
  return;
4752
4868
  }
4753
- state.pendingPortForwardRequests.delete(request.requestId);
4754
- await publishForwardPortResolvedEvent(args, request, {
4755
- decision: "expired",
4756
- reason: "listener_exited"
4757
- });
4758
- await publishMessageStateForPortForwardResult(args, state, request, "failed", "port_forward_listener_exited");
4759
- args.log("port_forward.pending_request_expired", {
4760
- request_id: request.requestId,
4761
- port: request.port,
4762
- pid: request.pid,
4763
- reason: "listener_exited"
4764
- });
4869
+ await expirePendingPortForwardRequest(args, state, request, "listener_exited");
4765
4870
  await drainQueuedPortForwardPrompt(args, state, payloadContext);
4766
4871
  }
4767
4872
  async function publishPortForwardReadyMessage(args, state, payloadContext, request) {
@@ -4995,10 +5100,6 @@ async function handleKandanChatEvent(args, state, runnerIdentity, payloadContext
4995
5100
  actor_user_id: event.actorUserId ?? null,
4996
5101
  reason: "different_thread"
4997
5102
  });
4998
- await publishKandanMessageState(args, event, {
4999
- status: "ignored",
5000
- reason: "different_thread"
5001
- });
5002
5103
  return;
5003
5104
  }
5004
5105
  if (!claimKandanMessage(args, state, event)) {
@@ -5416,48 +5517,15 @@ async function forwardCompletedCodexTurn(args, state, turnId, payloadContext) {
5416
5517
  if (completingLocalTuiTurn && sourceMessageSeqForTurn(state, turnId) === undefined) {
5417
5518
  throw new LogicalProjectionError(`Cannot forward Codex output for local TUI turn ${turnId} before mirroring its human input`);
5418
5519
  }
5419
- for (const message of messages) {
5420
- const sourceMessageSeq = sourceMessageSeqForTurn(state, turnId);
5421
- const rootSeq = state.rootSeq;
5422
- const streamedStructured = resolveStreamingStructuredOutputForCompletedMessage(state, message.itemKey, message.structured);
5423
- if (streamedStructured !== undefined) {
5424
- await editCodexStructuredOutput(args, state, streamedStructured.seq, message.body, message.structured);
5425
- forgetStreamingStructuredOutput(state, message.itemKey, message.structured);
5426
- args.log("kandan.codex_output_forwarded", {
5427
- turn_id: turnId,
5428
- item_key: message.itemKey,
5429
- structured_kind: stringValue(message.structured.kind) ?? null,
5430
- command: stringValue(message.structured.command) ?? null,
5431
- file_paths: fileChangePaths(message.structured)
5432
- });
5433
- continue;
5434
- }
5435
- if (stringValue(message.structured.kind) === "codex_terminal_input" && state.forwardedTerminalInputKeys.has(message.itemKey)) {
5436
- continue;
5437
- }
5438
- const streamed = resolveStreamingAssistantOutputForCompletedMessage(state, turnId, message.itemKey, message.body, message.structured);
5439
- switch (streamed.status) {
5440
- case "none":
5441
- await streamCompletedCodexOutput(args, state, payloadContext, {
5442
- turnId,
5443
- sourceMessageSeq,
5444
- rootSeq,
5445
- message
5446
- });
5447
- break;
5448
- case "matched":
5449
- await editStreamedCodexOutput(args, state, streamed.output.seq, message.itemKey, message.body, "completed");
5450
- forgetStreamingAssistantOutput(state, streamed.output.itemKey);
5451
- break;
5452
- case "ambiguous":
5453
- throw new LogicalProjectionError(`Cannot reconcile completed assistant item ${message.itemKey} for turn ${turnId}; ${streamed.candidateCount} active streamed assistant outputs exist`);
5454
- }
5455
- args.log("kandan.codex_output_forwarded", {
5456
- turn_id: turnId,
5457
- item_key: message.itemKey,
5458
- structured_kind: stringValue(message.structured.kind) ?? null,
5459
- command: stringValue(message.structured.command) ?? null,
5460
- file_paths: fileChangePaths(message.structured)
5520
+ const completedOutputs = completedOutputProjectionsForTurn(state, turnId, messages);
5521
+ const sourceMessageSeq = sourceMessageSeqForTurn(state, turnId);
5522
+ const rootSeq = state.rootSeq;
5523
+ for (const output of completedOutputs) {
5524
+ await postCompletedOutputProjection(args, state, payloadContext, {
5525
+ turnId,
5526
+ sourceMessageSeq,
5527
+ rootSeq,
5528
+ output
5461
5529
  });
5462
5530
  }
5463
5531
  rememberForwardedTurnId(state, turnId);
@@ -5506,6 +5574,202 @@ async function forwardCompletedCodexTurn(args, state, turnId, payloadContext) {
5506
5574
  }
5507
5575
  }
5508
5576
  }
5577
+ function completedOutputProjectionsForTurn(state, turnId, messages) {
5578
+ const snapshotOutputs = messages.flatMap((message, snapshotIndex) => completedSnapshotOutputProjection(state, turnId, message, snapshotIndex));
5579
+ const matchedStructuredKeys = new Set(snapshotOutputs.flatMap((output) => {
5580
+ switch (output.match.kind) {
5581
+ case "structured":
5582
+ return [output.match.matchKey];
5583
+ case "assistant":
5584
+ case "none":
5585
+ return [];
5586
+ }
5587
+ }));
5588
+ const filteredReasoningOutputs = boundedCacheValues(state.streamingReasoningOutputs).filter((output) => output.turnId === turnId && !matchedStructuredKeys.has(structuredOutputMatchKey("codex_reasoning", output.itemKey)));
5589
+ const filteredCommandOutputs = boundedCacheValues(state.streamingCommandOutputs).filter((output) => output.turnId === turnId && !matchedStructuredKeys.has(structuredOutputMatchKey("codex_command_execution", output.itemKey)));
5590
+ const filteredFileChangeOutputs = boundedCacheValues(state.streamingFileChangeOutputs).filter((output) => output.turnId === turnId && !matchedStructuredKeys.has(structuredOutputMatchKey("codex_file_change", output.itemKey)));
5591
+ const cachedOutputs = [
5592
+ ...filteredReasoningOutputs.map((output, index) => ({
5593
+ kind: "cached_reasoning",
5594
+ sortOrder: output.seq,
5595
+ snapshotIndex: messages.length + index,
5596
+ output
5597
+ })),
5598
+ ...filteredCommandOutputs.map((output, index) => ({
5599
+ kind: "cached_command",
5600
+ sortOrder: output.seq,
5601
+ snapshotIndex: messages.length + filteredReasoningOutputs.length + index,
5602
+ output
5603
+ })),
5604
+ ...filteredFileChangeOutputs.map((output, index) => ({
5605
+ kind: "cached_file_change",
5606
+ sortOrder: output.seq,
5607
+ snapshotIndex: messages.length + filteredReasoningOutputs.length + filteredCommandOutputs.length + index,
5608
+ output
5609
+ }))
5610
+ ];
5611
+ const fallbackSortOrderBase = fallbackSnapshotOutputBase([
5612
+ ...snapshotOutputs.flatMap((output) => {
5613
+ switch (output.match.kind) {
5614
+ case "assistant":
5615
+ case "structured":
5616
+ return [output.sortOrder];
5617
+ case "none":
5618
+ return [];
5619
+ }
5620
+ }),
5621
+ ...cachedOutputs.map((output) => output.sortOrder)
5622
+ ]);
5623
+ const orderedSnapshotOutputs = snapshotOutputs.map((output) => {
5624
+ switch (output.match.kind) {
5625
+ case "none":
5626
+ return {
5627
+ ...output,
5628
+ sortOrder: fallbackSnapshotOutputOrder(fallbackSortOrderBase, output.snapshotIndex)
5629
+ };
5630
+ case "assistant":
5631
+ case "structured":
5632
+ return output;
5633
+ }
5634
+ });
5635
+ return [...orderedSnapshotOutputs, ...cachedOutputs].sort(compareCompletedOutputProjection);
5636
+ }
5637
+ function completedSnapshotOutputProjection(state, turnId, message, snapshotIndex) {
5638
+ const streamedStructured = resolveStreamingStructuredOutputForCompletedMessage(state, message.itemKey, message.structured);
5639
+ if (streamedStructured !== undefined) {
5640
+ const structuredKind = stringValue(message.structured.kind) ?? "";
5641
+ return [
5642
+ {
5643
+ kind: "snapshot",
5644
+ sortOrder: streamedStructured.seq,
5645
+ snapshotIndex,
5646
+ message,
5647
+ match: {
5648
+ kind: "structured",
5649
+ itemKey: message.itemKey,
5650
+ structured: message.structured,
5651
+ matchKey: structuredOutputMatchKey(structuredKind, message.itemKey)
5652
+ }
5653
+ }
5654
+ ];
5655
+ }
5656
+ if (stringValue(message.structured.kind) === "codex_terminal_input" && state.forwardedTerminalInputKeys.has(message.itemKey)) {
5657
+ return [];
5658
+ }
5659
+ const streamed = resolveStreamingAssistantOutputForCompletedMessage(state, turnId, message.itemKey, message.body, message.structured);
5660
+ switch (streamed.status) {
5661
+ case "none":
5662
+ return [
5663
+ {
5664
+ kind: "snapshot",
5665
+ sortOrder: snapshotIndex,
5666
+ snapshotIndex,
5667
+ message,
5668
+ match: { kind: "none" }
5669
+ }
5670
+ ];
5671
+ case "matched":
5672
+ return [
5673
+ {
5674
+ kind: "snapshot",
5675
+ sortOrder: streamed.output.seq,
5676
+ snapshotIndex,
5677
+ message,
5678
+ match: { kind: "assistant", itemKey: streamed.output.itemKey }
5679
+ }
5680
+ ];
5681
+ case "ambiguous":
5682
+ throw new LogicalProjectionError(`Cannot reconcile completed assistant item ${message.itemKey} for turn ${turnId}; ${streamed.candidateCount} active streamed assistant outputs exist`);
5683
+ }
5684
+ }
5685
+ async function postCompletedOutputProjection(args, state, payloadContext, params) {
5686
+ switch (params.output.kind) {
5687
+ case "snapshot": {
5688
+ switch (params.output.match.kind) {
5689
+ case "none":
5690
+ await streamCompletedCodexOutput(args, state, payloadContext, {
5691
+ turnId: params.turnId,
5692
+ sourceMessageSeq: params.sourceMessageSeq,
5693
+ rootSeq: params.rootSeq,
5694
+ message: params.output.message
5695
+ });
5696
+ break;
5697
+ case "assistant":
5698
+ await editStreamedCodexOutput(args, state, params.output.sortOrder, params.output.message.itemKey, params.output.message.body, "completed");
5699
+ forgetStreamingAssistantOutput(state, params.output.match.itemKey);
5700
+ break;
5701
+ case "structured":
5702
+ await editCodexStructuredOutput(args, state, params.output.sortOrder, params.output.message.body, params.output.message.structured);
5703
+ forgetStreamingStructuredOutput(state, params.output.match.itemKey, params.output.match.structured);
5704
+ break;
5705
+ }
5706
+ logCompletedCodexOutput(args, params.turnId, params.output.message);
5707
+ break;
5708
+ }
5709
+ case "cached_reasoning": {
5710
+ const output = params.output.output;
5711
+ const message = {
5712
+ itemKey: output.itemKey,
5713
+ body: output.content,
5714
+ structured: codexReasoningStructuredMessage(output.itemKey, output.content, "completed")
5715
+ };
5716
+ await editCodexStructuredOutput(args, state, output.seq, message.body, message.structured);
5717
+ forgetStreamingReasoningOutput(state, output.itemKey);
5718
+ logCompletedCodexOutput(args, params.turnId, message);
5719
+ break;
5720
+ }
5721
+ case "cached_command": {
5722
+ const output = params.output.output;
5723
+ const message = {
5724
+ itemKey: output.itemKey,
5725
+ body: codexCommandOutputBody("command output", output.output),
5726
+ structured: codexCommandExecutionStructuredMessage(output.itemKey, {
5727
+ command: "command output",
5728
+ output: output.output,
5729
+ processId: output.processId,
5730
+ stream: output.stream
5731
+ }, "completed")
5732
+ };
5733
+ await editCodexStructuredOutput(args, state, output.seq, message.body, message.structured);
5734
+ forgetStreamingCommandOutput(state, output.itemKey);
5735
+ logCompletedCodexOutput(args, params.turnId, message);
5736
+ break;
5737
+ }
5738
+ case "cached_file_change": {
5739
+ const output = params.output.output;
5740
+ const message = {
5741
+ itemKey: output.itemKey,
5742
+ body: output.patchText,
5743
+ structured: codexFileChangeStructuredMessage(output.itemKey, output.patchText, "completed", "completed")
5744
+ };
5745
+ await editCodexStructuredOutput(args, state, output.seq, message.body, message.structured);
5746
+ forgetStreamingFileChangeOutput(state, output.itemKey);
5747
+ logCompletedCodexOutput(args, params.turnId, message);
5748
+ break;
5749
+ }
5750
+ }
5751
+ }
5752
+ function logCompletedCodexOutput(args, turnId, message) {
5753
+ args.log("kandan.codex_output_forwarded", {
5754
+ turn_id: turnId,
5755
+ item_key: message.itemKey,
5756
+ structured_kind: stringValue(message.structured.kind) ?? null,
5757
+ command: stringValue(message.structured.command) ?? null,
5758
+ file_paths: fileChangePaths(message.structured)
5759
+ });
5760
+ }
5761
+ function compareCompletedOutputProjection(left, right) {
5762
+ return left.sortOrder === right.sortOrder ? left.snapshotIndex - right.snapshotIndex : left.sortOrder - right.sortOrder;
5763
+ }
5764
+ function fallbackSnapshotOutputBase(sortOrders) {
5765
+ return sortOrders.reduce((max, sortOrder) => Math.max(max, sortOrder), 0) + 1;
5766
+ }
5767
+ function fallbackSnapshotOutputOrder(base, snapshotIndex) {
5768
+ return base + snapshotIndex;
5769
+ }
5770
+ function structuredOutputMatchKey(kind, itemKey) {
5771
+ return `${kind}:${itemKey}`;
5772
+ }
5509
5773
  async function forwardAssistantDeltaPayload(args, state, delta, payloadContext) {
5510
5774
  if (state.kandanThreadId === undefined || state.codexThreadId === undefined) {
5511
5775
  return;
@@ -6846,7 +7110,8 @@ function runtimeSettingsFromOptions(options) {
6846
7110
  reasoningEffort: options.channelSession.reasoningEffort,
6847
7111
  approvalPolicy: codexApprovalPolicySetting(options.channelSession.approvalPolicy, options.channelSession.sandbox),
6848
7112
  sandbox: options.channelSession.sandbox,
6849
- fast: options.fast
7113
+ fast: options.fast,
7114
+ allowPortForwardingByDefault: options.channelSession.allowPortForwardingByDefault
6850
7115
  };
6851
7116
  }
6852
7117
  function mergeRuntimeSettings(current, update) {
@@ -6856,7 +7121,8 @@ function mergeRuntimeSettings(current, update) {
6856
7121
  reasoningEffort: mergeOptionalStringRuntimeSetting(current.reasoningEffort, update, "reasoningEffort"),
6857
7122
  approvalPolicy: mergeOptionalApprovalPolicyRuntimeSetting(current.approvalPolicy, update, sandbox),
6858
7123
  sandbox,
6859
- fast: update.fast ?? current.fast
7124
+ fast: update.fast ?? current.fast,
7125
+ allowPortForwardingByDefault: update.allowPortForwardingByDefault ?? current.allowPortForwardingByDefault
6860
7126
  };
6861
7127
  }
6862
7128
  function mergeOptionalApprovalPolicyRuntimeSetting(current, update, sandbox) {
@@ -6880,7 +7146,8 @@ function runtimeOptionsForSettings(options, settings) {
6880
7146
  model: settings.model,
6881
7147
  reasoningEffort: settings.reasoningEffort,
6882
7148
  approvalPolicy: settings.approvalPolicy,
6883
- sandbox: settings.sandbox
7149
+ sandbox: settings.sandbox,
7150
+ allowPortForwardingByDefault: settings.allowPortForwardingByDefault
6884
7151
  }
6885
7152
  };
6886
7153
  }
@@ -6899,6 +7166,7 @@ async function publishRuntimeSettings(args, state) {
6899
7166
  approvalPolicy: state.runtimeSettings.approvalPolicy ?? null,
6900
7167
  sandbox: state.runtimeSettings.sandbox ?? null,
6901
7168
  fast: state.runtimeSettings.fast ?? null,
7169
+ allowPortForwardingByDefault: state.runtimeSettings.allowPortForwardingByDefault ?? null,
6902
7170
  updated_at: new Date().toISOString()
6903
7171
  });
6904
7172
  }
@@ -8776,7 +9044,7 @@ function kandanHttpBaseUrl(kandanUrl) {
8776
9044
  case "https:":
8777
9045
  break;
8778
9046
  default:
8779
- throw new Error("--linzumi-url must be ws://, wss://, http://, or https://");
9047
+ throw new Error("--api-url must be ws://, wss://, http://, or https://");
8780
9048
  }
8781
9049
  parsed.pathname = "";
8782
9050
  parsed.search = "";
@@ -9414,7 +9682,8 @@ function probeTool(command, cwd) {
9414
9682
  });
9415
9683
  const child = spawn5(command, args, {
9416
9684
  cwd,
9417
- stdio: ["ignore", "pipe", "pipe"]
9685
+ stdio: ["ignore", "pipe", "pipe"],
9686
+ detached: process.platform !== "win32"
9418
9687
  });
9419
9688
  writeCliAuditEvent("process.spawned", {
9420
9689
  command,
@@ -9435,7 +9704,7 @@ function probeTool(command, cwd) {
9435
9704
  resolve5(status);
9436
9705
  };
9437
9706
  const timeout = setTimeout(() => {
9438
- child.kill("SIGKILL");
9707
+ killDependencyProbe(child.pid);
9439
9708
  writeCliAuditEvent("process.exit", {
9440
9709
  command,
9441
9710
  args,
@@ -9485,6 +9754,18 @@ function probeTool(command, cwd) {
9485
9754
  });
9486
9755
  });
9487
9756
  }
9757
+ function killDependencyProbe(pid) {
9758
+ if (pid === undefined) {
9759
+ return;
9760
+ }
9761
+ try {
9762
+ process.kill(process.platform === "win32" ? pid : -pid, "SIGKILL");
9763
+ } catch (_error) {
9764
+ try {
9765
+ process.kill(pid, "SIGKILL");
9766
+ } catch (_nestedError) {}
9767
+ }
9768
+ }
9488
9769
  async function buildRunnerDependencyStatus(args) {
9489
9770
  const [bun, codex, codeServer] = await Promise.all([
9490
9771
  probeTool(process.execPath, args.cwd),
@@ -9617,6 +9898,21 @@ async function connectPhoenixClient(baseUrl, token, socketFactory = (url) => new
9617
9898
  state.rejectReady = reject;
9618
9899
  });
9619
9900
  };
9901
+ const dispatchRejoinEvents = (topic, response) => {
9902
+ if (!topic.startsWith("chat:")) {
9903
+ return;
9904
+ }
9905
+ const events = response.events;
9906
+ if (events === undefined || events === null) {
9907
+ return;
9908
+ }
9909
+ if (!Array.isArray(events)) {
9910
+ throw new Error(`phoenix rejoin returned invalid events for ${topic}`);
9911
+ }
9912
+ events.forEach((backlogEvent) => {
9913
+ eventCallbacks.forEach((callback) => callback(topic, "event", backlogEvent));
9914
+ });
9915
+ };
9620
9916
  const handleMessage = (event) => {
9621
9917
  const frame = decodeFrame(String(event.data));
9622
9918
  const [, ref, topic, name, payload] = frame;
@@ -9630,6 +9926,14 @@ async function connectPhoenixClient(baseUrl, token, socketFactory = (url) => new
9630
9926
  } else if (isNonOkPushReply(payload) && pendingPush.event !== "phx_join") {
9631
9927
  pendingPush.reject(new Error(`phoenix push failed: ${replyErrorMessage(payload)}`));
9632
9928
  } else {
9929
+ if (pendingPush.event === "phx_join" && state.connectionGeneration > 1 && joins.has(topic) && isJoinReply(payload)) {
9930
+ try {
9931
+ dispatchRejoinEvents(topic, payload.response);
9932
+ } catch (error) {
9933
+ pendingPush.reject(error instanceof Error ? error : new Error(String(error)));
9934
+ return;
9935
+ }
9936
+ }
9633
9937
  pendingPush.resolve(payload);
9634
9938
  }
9635
9939
  }
@@ -10152,7 +10456,7 @@ function realpathOrResolved(pathValue) {
10152
10456
  }
10153
10457
 
10154
10458
  // src/version.ts
10155
- var linzumiCliVersion = "0.0.51-beta";
10459
+ var linzumiCliVersion = "0.0.52-beta";
10156
10460
  var linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
10157
10461
 
10158
10462
  // src/runnerLock.ts
@@ -10761,6 +11065,25 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
10761
11065
  }
10762
11066
  revokeEditorForwardPort(review.revoked.port, review.reason);
10763
11067
  break;
11068
+ case "replace_pending":
11069
+ localEditorForwardState.pendingRequests.delete(review.expired.port);
11070
+ pushEditorPortForwardEvent("forward_port_resolved", {
11071
+ instanceId,
11072
+ requestId: review.expired.requestId,
11073
+ source: "local_editor",
11074
+ port: review.expired.port,
11075
+ pid: review.expired.pid,
11076
+ command: review.expired.command,
11077
+ ...review.expired.cwd === undefined ? {} : { cwd: review.expired.cwd },
11078
+ decision: "expired",
11079
+ reason: review.reason,
11080
+ capabilities: capabilitiesPayload()
11081
+ });
11082
+ if (localEditorForwardState.pendingRequests.size > 0) {
11083
+ localEditorForwardState.queuedCandidates.set(review.candidate.port, review.candidate);
11084
+ return;
11085
+ }
11086
+ break;
10764
11087
  case "prompt":
10765
11088
  if (localEditorForwardState.pendingRequests.size > 0) {
10766
11089
  localEditorForwardState.queuedCandidates.set(candidate.port, candidate);
@@ -10917,7 +11240,12 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
10917
11240
  const codex = await connectCodexAppServer(codexUrl);
10918
11241
  cleanup.actions.push(() => codex.close());
10919
11242
  const seq = { value: 0 };
10920
- const codexThreads = options.channelSession === undefined ? await discoverCodexThreads(codex, options.cwd) : [];
11243
+ const codexThreads = options.channelSession === undefined ? await discoverCodexThreads(codex, options.cwd).catch((error) => {
11244
+ log("kandan.codex_threads_startup_discovery_failed", {
11245
+ message: error instanceof Error ? error.message : String(error)
11246
+ });
11247
+ return [];
11248
+ }) : [];
10921
11249
  const discoveredCodexThreads = { value: codexThreads };
10922
11250
  const runtimeDefaults = runnerRuntimeDefaults(options);
10923
11251
  const instancePayload = {
@@ -10932,6 +11260,7 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
10932
11260
  channel: options.channelSession?.channelSlug ?? null,
10933
11261
  model: runtimeDefaults.model ?? null,
10934
11262
  reasoningEffort: runtimeDefaults.reasoningEffort ?? null,
11263
+ allowPortForwardingByDefault: runtimeDefaults.allowPortForwardingByDefault ?? null,
10935
11264
  fast: options.fast ?? false
10936
11265
  };
10937
11266
  await kandan.push(topic, "instance_started", instancePayload);
@@ -11039,7 +11368,8 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
11039
11368
  model: runtimeSettings.model,
11040
11369
  reasoningEffort: runtimeSettings.reasoningEffort,
11041
11370
  sandbox: runtimeSettings.sandbox,
11042
- approvalPolicy: runtimeSettings.approvalPolicy
11371
+ approvalPolicy: runtimeSettings.approvalPolicy,
11372
+ allowPortForwardingByDefault: runtimeSettings.allowPortForwardingByDefault
11043
11373
  }
11044
11374
  },
11045
11375
  log
@@ -11060,6 +11390,7 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
11060
11390
  codexThreads: discoveredCodexThreads.value,
11061
11391
  model: runtimeDefaults.model ?? null,
11062
11392
  reasoningEffort: runtimeDefaults.reasoningEffort ?? null,
11393
+ allowPortForwardingByDefault: runtimeDefaults.allowPortForwardingByDefault ?? null,
11063
11394
  fast: options.fast ?? false,
11064
11395
  capabilities: capabilitiesPayload()
11065
11396
  });
@@ -11350,24 +11681,95 @@ async function closeCleanupStack(cleanup) {
11350
11681
  })();
11351
11682
  return cleanup.closePromise;
11352
11683
  }
11353
- async function discoverCodexThreads(codex, cwd) {
11354
- const response = await codex.request("thread/list", { cwd });
11355
- if ("error" in response) {
11356
- return [];
11684
+ async function discoverCodexThreads(codex, _cwd) {
11685
+ const rowsById = new Map;
11686
+ const archivedModes = [false, true];
11687
+ const sourcePasses = [
11688
+ undefined,
11689
+ [
11690
+ "exec",
11691
+ "appServer",
11692
+ "subAgent",
11693
+ "subAgentReview",
11694
+ "subAgentCompact",
11695
+ "subAgentThreadSpawn",
11696
+ "subAgentOther",
11697
+ "unknown"
11698
+ ]
11699
+ ];
11700
+ for (const archived of archivedModes) {
11701
+ for (const sourceKinds of sourcePasses) {
11702
+ let cursor;
11703
+ while (true) {
11704
+ const response = await codex.request("thread/list", {
11705
+ limit: 50,
11706
+ sortKey: "updated_at",
11707
+ sortDirection: "desc",
11708
+ archived,
11709
+ useStateDbOnly: true,
11710
+ ...cursor === undefined ? {} : { cursor },
11711
+ ...sourceKinds === undefined ? {} : { sourceKinds }
11712
+ });
11713
+ if ("error" in response) {
11714
+ throw new Error(`thread/list failed: ${response.error.message}`);
11715
+ }
11716
+ const result = objectValue(response.result);
11717
+ const data = arrayValue(result?.data)?.filter(isJsonObject) ?? [];
11718
+ for (const thread of data) {
11719
+ const row = codexThreadHistoryRow(thread, archived);
11720
+ const id = stringValue(objectValue(row)?.id);
11721
+ if (id !== undefined && id !== "" && !rowsById.has(id)) {
11722
+ rowsById.set(id, row);
11723
+ }
11724
+ }
11725
+ const nextCursor = stringValue(result?.nextCursor);
11726
+ if (nextCursor === undefined || nextCursor === "" || data.length === 0) {
11727
+ break;
11728
+ }
11729
+ cursor = nextCursor;
11730
+ }
11731
+ }
11357
11732
  }
11358
- const result = objectValue(response.result);
11359
- const data = arrayValue(result?.data);
11360
- return data === undefined ? [] : data.filter(isJsonObject).map((thread) => ({
11733
+ return Array.from(rowsById.values()).sort(compareCodexThreadHistoryRows);
11734
+ }
11735
+ function codexThreadHistoryRow(thread, archived) {
11736
+ const gitInfo = objectValue(thread.gitInfo);
11737
+ const preview = stringValue(thread.preview) ?? "";
11738
+ const name = stringValue(thread.name) ?? "";
11739
+ const title = stringValue(thread.title) ?? (name === "" ? preview : name);
11740
+ const description = stringValue(thread.description) ?? stringValue(thread.summary) ?? preview;
11741
+ return {
11361
11742
  id: stringValue(thread.id) ?? "",
11362
- title: stringValue(thread.title) ?? stringValue(thread.name) ?? stringValue(thread.preview) ?? "",
11363
- description: stringValue(thread.description) ?? stringValue(thread.summary) ?? stringValue(thread.preview) ?? "",
11364
- preview: stringValue(thread.preview) ?? "",
11743
+ title: title ?? "",
11744
+ description: description ?? "",
11745
+ preview: preview.replace(/\s+/g, " ").trim(),
11365
11746
  cwd: stringValue(thread.cwd) ?? "",
11366
11747
  source: stringValue(thread.source) ?? "",
11367
- createdAt: integerValue(thread.createdAt) ?? stringValue(thread.createdAt) ?? null,
11368
- updatedAt: integerValue(thread.updatedAt) ?? null,
11369
- status: objectValue(thread.status) ?? null
11370
- })).filter((thread) => thread.id !== "");
11748
+ createdAt: codexTimestamp(thread.createdAt),
11749
+ updatedAt: codexTimestamp(thread.updatedAt),
11750
+ archived,
11751
+ modelProvider: stringValue(thread.modelProvider) ?? "",
11752
+ cliVersion: stringValue(thread.cliVersion) ?? "",
11753
+ gitBranch: stringValue(gitInfo?.branch) ?? "",
11754
+ gitOriginUrl: stringValue(gitInfo?.originUrl) ?? "",
11755
+ path: stringValue(thread.path) ?? ""
11756
+ };
11757
+ }
11758
+ function codexTimestamp(value) {
11759
+ if (typeof value === "number" && Number.isFinite(value)) {
11760
+ return new Date(value * 1000).toISOString();
11761
+ }
11762
+ return stringValue(value) ?? "";
11763
+ }
11764
+ function compareCodexThreadHistoryRows(left, right) {
11765
+ const leftRow = objectValue(left);
11766
+ const rightRow = objectValue(right);
11767
+ const leftTime = Date.parse(stringValue(leftRow?.createdAt) ?? stringValue(leftRow?.updatedAt) ?? "");
11768
+ const rightTime = Date.parse(stringValue(rightRow?.createdAt) ?? stringValue(rightRow?.updatedAt) ?? "");
11769
+ return safeComparableTime(leftTime) - safeComparableTime(rightTime);
11770
+ }
11771
+ function safeComparableTime(value) {
11772
+ return Number.isFinite(value) ? value : Number.MAX_SAFE_INTEGER;
11371
11773
  }
11372
11774
  function extractStartedThreadId(response) {
11373
11775
  if ("error" in response) {
@@ -11801,6 +12203,10 @@ You MUST NOT ask the Bootstrapper Codex to do implementation work.
11801
12203
  You MUST NOT inspect unrelated repositories or folders.
11802
12204
  You MUST report the exact blocker if a command, preview, editor, or tunnel step
11803
12205
  fails.
12206
+ When several Linzumi Codex sessions work in the same repository, create or use
12207
+ a separate checkout or git worktree for this task before making changes, unless
12208
+ the human explicitly asks you to share the current checkout. Do not overwrite or
12209
+ revert another session's work.
11804
12210
  </rules>
11805
12211
 
11806
12212
  <examples>
@@ -11892,7 +12298,8 @@ function startInstanceRuntimeSettings(options, control) {
11892
12298
  reasoningEffort: control.reasoningEffort ?? defaults.reasoningEffort,
11893
12299
  approvalPolicy: codexApprovalPolicyForRequest(control.approvalPolicy ?? defaults.approvalPolicy, sandbox),
11894
12300
  sandbox,
11895
- fast: control.fast ?? options.fast
12301
+ fast: control.fast ?? options.fast,
12302
+ allowPortForwardingByDefault: control.allowPortForwardingByDefault ?? defaults.allowPortForwardingByDefault
11896
12303
  };
11897
12304
  }
11898
12305
  async function startOwnedCodexAppServer(options) {
@@ -11915,7 +12322,8 @@ function runnerRuntimeDefaults(options) {
11915
12322
  model: defaults?.model ?? session?.model,
11916
12323
  reasoningEffort: defaults?.reasoningEffort ?? session?.reasoningEffort,
11917
12324
  approvalPolicy: codexApprovalPolicySetting(defaults?.approvalPolicy ?? session?.approvalPolicy, sandbox),
11918
- sandbox
12325
+ sandbox,
12326
+ allowPortForwardingByDefault: defaults?.allowPortForwardingByDefault ?? session?.allowPortForwardingByDefault
11919
12327
  };
11920
12328
  }
11921
12329
  function isUpdateRunnerConfigControl(control) {
@@ -13396,7 +13804,7 @@ To kick the agent off:
13396
13804
  3. Paste into the thread. Codex will pick it up and start editing this folder.
13397
13805
  `;
13398
13806
 
13399
- // ../../node_modules/@inquirer/core/dist/esm/lib/key.js
13807
+ // node_modules/@inquirer/core/dist/esm/lib/key.js
13400
13808
  var isUpKey = (key, keybindings = []) => key.name === "up" || keybindings.includes("vim") && key.name === "k" || keybindings.includes("emacs") && key.ctrl && key.name === "p";
13401
13809
  var isDownKey = (key, keybindings = []) => key.name === "down" || keybindings.includes("vim") && key.name === "j" || keybindings.includes("emacs") && key.ctrl && key.name === "n";
13402
13810
  var isSpaceKey = (key) => key.name === "space";
@@ -13404,7 +13812,7 @@ var isBackspaceKey = (key) => key.name === "backspace";
13404
13812
  var isTabKey = (key) => key.name === "tab";
13405
13813
  var isNumberKey = (key) => "1234567890".includes(key.name);
13406
13814
  var isEnterKey = (key) => key.name === "enter" || key.name === "return";
13407
- // ../../node_modules/@inquirer/core/dist/esm/lib/errors.js
13815
+ // node_modules/@inquirer/core/dist/esm/lib/errors.js
13408
13816
  class AbortPromptError extends Error {
13409
13817
  name = "AbortPromptError";
13410
13818
  message = "Prompt was aborted";
@@ -13430,10 +13838,10 @@ class HookError extends Error {
13430
13838
  class ValidationError extends Error {
13431
13839
  name = "ValidationError";
13432
13840
  }
13433
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-state.js
13841
+ // node_modules/@inquirer/core/dist/esm/lib/use-state.js
13434
13842
  import { AsyncResource as AsyncResource2 } from "node:async_hooks";
13435
13843
 
13436
- // ../../node_modules/@inquirer/core/dist/esm/lib/hook-engine.js
13844
+ // node_modules/@inquirer/core/dist/esm/lib/hook-engine.js
13437
13845
  import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
13438
13846
  var hookStorage = new AsyncLocalStorage;
13439
13847
  function createStore(rl) {
@@ -13538,7 +13946,7 @@ var effectScheduler = {
13538
13946
  }
13539
13947
  };
13540
13948
 
13541
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-state.js
13949
+ // node_modules/@inquirer/core/dist/esm/lib/use-state.js
13542
13950
  function useState(defaultValue) {
13543
13951
  return withPointer((pointer) => {
13544
13952
  const setState = AsyncResource2.bind(function setState2(newValue) {
@@ -13556,7 +13964,7 @@ function useState(defaultValue) {
13556
13964
  });
13557
13965
  }
13558
13966
 
13559
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-effect.js
13967
+ // node_modules/@inquirer/core/dist/esm/lib/use-effect.js
13560
13968
  function useEffect(cb, depArray) {
13561
13969
  withPointer((pointer) => {
13562
13970
  const oldDeps = pointer.get();
@@ -13568,10 +13976,10 @@ function useEffect(cb, depArray) {
13568
13976
  });
13569
13977
  }
13570
13978
 
13571
- // ../../node_modules/@inquirer/core/dist/esm/lib/theme.js
13979
+ // node_modules/@inquirer/core/dist/esm/lib/theme.js
13572
13980
  var import_yoctocolors_cjs = __toESM(require_yoctocolors_cjs(), 1);
13573
13981
 
13574
- // ../../node_modules/@inquirer/figures/dist/esm/index.js
13982
+ // node_modules/@inquirer/figures/dist/esm/index.js
13575
13983
  import process2 from "node:process";
13576
13984
  function isUnicodeSupported() {
13577
13985
  if (process2.platform !== "win32") {
@@ -13860,7 +14268,7 @@ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
13860
14268
  var esm_default = figures;
13861
14269
  var replacements = Object.entries(specialMainSymbols);
13862
14270
 
13863
- // ../../node_modules/@inquirer/core/dist/esm/lib/theme.js
14271
+ // node_modules/@inquirer/core/dist/esm/lib/theme.js
13864
14272
  var defaultTheme = {
13865
14273
  prefix: {
13866
14274
  idle: import_yoctocolors_cjs.default.blue("?"),
@@ -13881,7 +14289,7 @@ var defaultTheme = {
13881
14289
  }
13882
14290
  };
13883
14291
 
13884
- // ../../node_modules/@inquirer/core/dist/esm/lib/make-theme.js
14292
+ // node_modules/@inquirer/core/dist/esm/lib/make-theme.js
13885
14293
  function isPlainObject(value) {
13886
14294
  if (typeof value !== "object" || value === null)
13887
14295
  return false;
@@ -13909,7 +14317,7 @@ function makeTheme(...themes) {
13909
14317
  return deepMerge(...themesToMerge);
13910
14318
  }
13911
14319
 
13912
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-prefix.js
14320
+ // node_modules/@inquirer/core/dist/esm/lib/use-prefix.js
13913
14321
  function usePrefix({ status = "idle", theme }) {
13914
14322
  const [showLoader, setShowLoader] = useState(false);
13915
14323
  const [tick, setTick] = useState(0);
@@ -13939,7 +14347,7 @@ function usePrefix({ status = "idle", theme }) {
13939
14347
  const iconName = status === "loading" ? "idle" : status;
13940
14348
  return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
13941
14349
  }
13942
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-memo.js
14350
+ // node_modules/@inquirer/core/dist/esm/lib/use-memo.js
13943
14351
  function useMemo(fn, dependencies) {
13944
14352
  return withPointer((pointer) => {
13945
14353
  const prev = pointer.get();
@@ -13951,11 +14359,11 @@ function useMemo(fn, dependencies) {
13951
14359
  return prev.value;
13952
14360
  });
13953
14361
  }
13954
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-ref.js
14362
+ // node_modules/@inquirer/core/dist/esm/lib/use-ref.js
13955
14363
  function useRef(val) {
13956
14364
  return useState({ current: val })[0];
13957
14365
  }
13958
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-keypress.js
14366
+ // node_modules/@inquirer/core/dist/esm/lib/use-keypress.js
13959
14367
  function useKeypress(userHandler) {
13960
14368
  const signal = useRef(userHandler);
13961
14369
  signal.current = userHandler;
@@ -13973,7 +14381,7 @@ function useKeypress(userHandler) {
13973
14381
  };
13974
14382
  }, []);
13975
14383
  }
13976
- // ../../node_modules/@inquirer/core/dist/esm/lib/utils.js
14384
+ // node_modules/@inquirer/core/dist/esm/lib/utils.js
13977
14385
  var import_cli_width = __toESM(require_cli_width(), 1);
13978
14386
  var import_wrap_ansi = __toESM(require_wrap_ansi(), 1);
13979
14387
  function breakLines(content, width) {
@@ -13986,7 +14394,7 @@ function readlineWidth() {
13986
14394
  return import_cli_width.default({ defaultWidth: 80, output: readline().output });
13987
14395
  }
13988
14396
 
13989
- // ../../node_modules/@inquirer/core/dist/esm/lib/pagination/use-pagination.js
14397
+ // node_modules/@inquirer/core/dist/esm/lib/pagination/use-pagination.js
13990
14398
  function usePointerPosition({ active, renderedItems, pageSize, loop }) {
13991
14399
  const state = useRef({
13992
14400
  lastPointer: active,
@@ -14052,12 +14460,12 @@ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
14052
14460
  return pageBuffer.filter((line) => typeof line === "string").join(`
14053
14461
  `);
14054
14462
  }
14055
- // ../../node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14463
+ // node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14056
14464
  var import_mute_stream = __toESM(require_lib(), 1);
14057
14465
  import * as readline2 from "node:readline";
14058
14466
  import { AsyncResource as AsyncResource3 } from "node:async_hooks";
14059
14467
 
14060
- // ../../node_modules/@inquirer/core/node_modules/signal-exit/dist/mjs/signals.js
14468
+ // node_modules/signal-exit/dist/mjs/signals.js
14061
14469
  var signals = [];
14062
14470
  signals.push("SIGHUP", "SIGINT", "SIGTERM");
14063
14471
  if (process.platform !== "win32") {
@@ -14067,7 +14475,7 @@ if (process.platform === "linux") {
14067
14475
  signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
14068
14476
  }
14069
14477
 
14070
- // ../../node_modules/@inquirer/core/node_modules/signal-exit/dist/mjs/index.js
14478
+ // node_modules/signal-exit/dist/mjs/index.js
14071
14479
  var processOk = (process3) => !!process3 && typeof process3 === "object" && typeof process3.removeListener === "function" && typeof process3.emit === "function" && typeof process3.reallyExit === "function" && typeof process3.listeners === "function" && typeof process3.kill === "function" && typeof process3.pid === "number" && typeof process3.on === "function";
14072
14480
  var kExitEmitter = Symbol.for("signal-exit emitter");
14073
14481
  var global = globalThis;
@@ -14265,10 +14673,10 @@ var {
14265
14673
  unload
14266
14674
  } = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback);
14267
14675
 
14268
- // ../../node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14676
+ // node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14269
14677
  import { stripVTControlCharacters } from "node:util";
14270
14678
 
14271
- // ../../node_modules/@inquirer/ansi/dist/esm/index.js
14679
+ // node_modules/@inquirer/ansi/dist/esm/index.js
14272
14680
  var ESC = "\x1B[";
14273
14681
  var cursorLeft = ESC + "G";
14274
14682
  var cursorHide = ESC + "?25l";
@@ -14284,7 +14692,7 @@ var cursorTo = (x, y) => {
14284
14692
  var eraseLine = ESC + "2K";
14285
14693
  var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
14286
14694
 
14287
- // ../../node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14695
+ // node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14288
14696
  var height = (content) => content.split(`
14289
14697
  `).length;
14290
14698
  var lastLine = (content) => content.split(`
@@ -14349,7 +14757,7 @@ class ScreenManager {
14349
14757
  }
14350
14758
  }
14351
14759
 
14352
- // ../../node_modules/@inquirer/core/dist/esm/lib/promise-polyfill.js
14760
+ // node_modules/@inquirer/core/dist/esm/lib/promise-polyfill.js
14353
14761
  class PromisePolyfill extends Promise {
14354
14762
  static withResolver() {
14355
14763
  let resolve8;
@@ -14362,7 +14770,7 @@ class PromisePolyfill extends Promise {
14362
14770
  }
14363
14771
  }
14364
14772
 
14365
- // ../../node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14773
+ // node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14366
14774
  function getCallSites() {
14367
14775
  const _prepareStackTrace = Error.prepareStackTrace;
14368
14776
  let result = [];
@@ -14448,7 +14856,7 @@ function createPrompt(view) {
14448
14856
  };
14449
14857
  return prompt;
14450
14858
  }
14451
- // ../../node_modules/@inquirer/core/dist/esm/lib/Separator.js
14859
+ // node_modules/@inquirer/core/dist/esm/lib/Separator.js
14452
14860
  var import_yoctocolors_cjs2 = __toESM(require_yoctocolors_cjs(), 1);
14453
14861
  class Separator {
14454
14862
  separator = import_yoctocolors_cjs2.default.dim(Array.from({ length: 15 }).join(esm_default.line));
@@ -14462,7 +14870,7 @@ class Separator {
14462
14870
  return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
14463
14871
  }
14464
14872
  }
14465
- // ../../node_modules/@inquirer/checkbox/dist/esm/index.js
14873
+ // node_modules/@inquirer/checkbox/dist/esm/index.js
14466
14874
  var import_yoctocolors_cjs3 = __toESM(require_yoctocolors_cjs(), 1);
14467
14875
  var checkboxTheme = {
14468
14876
  icon: {
@@ -14649,7 +15057,7 @@ var esm_default2 = createPrompt((config, done) => {
14649
15057
  `).trimEnd();
14650
15058
  return `${lines}${cursorHide}`;
14651
15059
  });
14652
- // ../../node_modules/@inquirer/input/dist/esm/index.js
15060
+ // node_modules/@inquirer/input/dist/esm/index.js
14653
15061
  var inputTheme = {
14654
15062
  validationFailureMode: "keep"
14655
15063
  };
@@ -14733,7 +15141,7 @@ var esm_default3 = createPrompt((config, done) => {
14733
15141
  error
14734
15142
  ];
14735
15143
  });
14736
- // ../../node_modules/@inquirer/select/dist/esm/index.js
15144
+ // node_modules/@inquirer/select/dist/esm/index.js
14737
15145
  var import_yoctocolors_cjs4 = __toESM(require_yoctocolors_cjs(), 1);
14738
15146
  var selectTheme = {
14739
15147
  icon: { cursor: esm_default.pointer },
@@ -14900,28 +15308,19 @@ var esm_default4 = createPrompt((config, done) => {
14900
15308
  // src/signupFlow.ts
14901
15309
  import { spawn as spawn7 } from "node:child_process";
14902
15310
  import {
14903
- closeSync as closeSync2,
14904
15311
  existsSync as existsSync10,
14905
15312
  constants as fsConstants,
14906
- mkdirSync as mkdirSync10,
14907
15313
  mkdtempSync as mkdtempSync3,
14908
- openSync as openSync3,
14909
15314
  readFileSync as readFileSync10,
14910
15315
  readdirSync,
14911
15316
  rmSync as rmSync3,
14912
15317
  statSync,
14913
- watch,
14914
15318
  writeFileSync as writeFileSync8
14915
15319
  } from "node:fs";
14916
15320
  import { access } from "node:fs/promises";
14917
15321
  import { homedir as homedir8, tmpdir as tmpdir2 } from "node:os";
14918
- import { delimiter as delimiter2, dirname as dirname9, join as join12, resolve as resolve8 } from "node:path";
14919
- import {
14920
- argv as processArgv,
14921
- execPath as processExecPath,
14922
- stdin as defaultStdin,
14923
- stdout as defaultStdout
14924
- } from "node:process";
15322
+ import { delimiter as delimiter2, join as join12, resolve as resolve8 } from "node:path";
15323
+ import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
14925
15324
  import { emitKeypressEvents } from "node:readline";
14926
15325
 
14927
15326
  // src/signupServerClient.ts
@@ -15207,11 +15606,6 @@ function booleanValue(record, key) {
15207
15606
  }
15208
15607
 
15209
15608
  // src/signupFlow.ts
15210
- var commanderConnectedMarkers = [
15211
- "Connected to Linzumi",
15212
- "Runner connected:",
15213
- '"event":"runner.instance_started"'
15214
- ];
15215
15609
  var blue = (value) => `\x1B[38;5;75m${value}\x1B[0m`;
15216
15610
  var green = (value) => `\x1B[38;5;114m${value}\x1B[0m`;
15217
15611
  var red = (value) => `\x1B[38;5;203m${value}\x1B[0m`;
@@ -15519,6 +15913,8 @@ async function runSignupFlow(deps = {}) {
15519
15913
  rootSeq: thread.rootSeq,
15520
15914
  threadSeq: thread.threadSeq
15521
15915
  }));
15916
+ const starterProjectPath = missionControl.config.starterProjectPath ?? starterProject.path;
15917
+ const verifiedCodexBin = verifiedCodexBinFromPreflightChecks(state.preflightChecks);
15522
15918
  const storedSignupAuth = writeSignupCompletion({
15523
15919
  email: verifiedAuth.user.primaryEmail ?? state.email ?? verifiedAuth.user.username,
15524
15920
  serviceUrl,
@@ -15530,20 +15926,24 @@ async function runSignupFlow(deps = {}) {
15530
15926
  launchUrl: missionControl.launchUrl,
15531
15927
  allowedCwds: missionControl.config.allowedCwds
15532
15928
  });
15533
- const commanderLaunch = await launchSignupCommanderForCompletedSignup(commanderLauncher, {
15929
+ const commanderLaunch = verifiedCodexBin === undefined ? failedSignupCommanderLaunchForMissingCodex({
15930
+ serviceUrl,
15931
+ workspaceSlug: missionControl.workspace.slug,
15932
+ projectPath: starterProjectPath
15933
+ }) : await launchSignupCommanderForCompletedSignup(commanderLauncher, {
15534
15934
  serviceUrl,
15535
15935
  localRunnerAccessToken: missionControl.localRunnerToken.accessToken,
15536
15936
  localRunnerExpiresInSeconds: missionControl.localRunnerToken.expiresInSeconds,
15537
15937
  workspaceSlug: missionControl.workspace.slug,
15538
- officeChannelSlug: missionControl.channels.office.slug,
15539
- projectPath: missionControl.config.starterProjectPath ?? starterProject.path,
15540
- selectedProjectPaths: missionControl.config.allowedCwds
15938
+ projectPath: starterProjectPath,
15939
+ selectedProjectPaths: missionControl.config.allowedCwds,
15940
+ codexBin: verifiedCodexBin
15541
15941
  });
15542
15942
  const starterTaskLaunches = await startSignupTasksForCommander(signupServerClient, {
15543
15943
  accessToken: verifiedAuth.accessToken,
15544
15944
  missionControl,
15545
15945
  commanderLaunch,
15546
- starterProjectPath: missionControl.config.starterProjectPath ?? starterProject.path,
15946
+ starterProjectPath,
15547
15947
  threads: starterTaskThreads
15548
15948
  });
15549
15949
  state = updateSignupState(state, {
@@ -16022,7 +16422,7 @@ function writeLaunchSummary(output, state) {
16022
16422
  writeBoundedLine(output, `${green("✓")} Local Commander connected this computer to Mission Control (${state.commanderLaunch.runnerId})`);
16023
16423
  break;
16024
16424
  case "failed":
16025
- writeStatusMessage(output, red("x"), `Local Commander could not start automatically: ${state.commanderLaunch.error}`);
16425
+ writeStatusMessage(output, red("x"), `Local Commander could not connect: ${state.commanderLaunch.error}`);
16026
16426
  break;
16027
16427
  }
16028
16428
  }
@@ -16064,48 +16464,17 @@ async function defaultSignupCommanderLauncher(args) {
16064
16464
  accessToken: args.localRunnerAccessToken,
16065
16465
  expiresInSeconds: args.localRunnerExpiresInSeconds
16066
16466
  });
16067
- const scriptPath = processArgv[1];
16068
16467
  const runnerId = signupCommanderRunnerId(args.workspaceSlug);
16069
16468
  const restartCommand = signupConnectRestartCommand(args);
16070
- if (scriptPath === undefined || scriptPath.trim() === "") {
16071
- return {
16072
- status: "failed",
16073
- runnerId,
16074
- restartCommand,
16075
- error: "current CLI entrypoint could not be resolved"
16076
- };
16077
- }
16078
- const logFile = signupCommanderLaunchLogFile(runnerId);
16079
- let stdoutFd;
16080
- let stderrFd;
16081
16469
  try {
16082
- mkdirSync10(dirname9(logFile), { recursive: true });
16083
- stdoutFd = openSync3(logFile, "a");
16084
- stderrFd = openSync3(logFile, "a");
16085
- const child = spawn7(processExecPath, signupCommanderConnectSpawnArgs(args, runnerId, logFile, scriptPath), {
16086
- detached: true,
16087
- stdio: ["ignore", stdoutFd, stderrFd]
16088
- });
16089
- closeSync2(stdoutFd);
16090
- closeSync2(stderrFd);
16091
- stdoutFd = undefined;
16092
- stderrFd = undefined;
16093
- child.unref();
16094
- const connected = await waitForSignupCommanderConnection(logFile, 30000);
16095
- if (!connected) {
16096
- return {
16097
- status: "failed",
16098
- runnerId,
16099
- restartCommand,
16100
- error: `Local Commander did not connect within 30 seconds. Check ${logFile}`
16101
- };
16102
- }
16470
+ const handle = await runLocalCodexRunner(await signupCommanderRunnerOptions(args, runnerId));
16103
16471
  return {
16104
16472
  status: "started",
16105
16473
  runnerId,
16106
16474
  restartCommand,
16107
- logFile,
16108
- ...child.pid === undefined ? {} : { pid: child.pid }
16475
+ pid: process.pid,
16476
+ instanceId: handle.instanceId,
16477
+ codexUrl: handle.codexUrl
16109
16478
  };
16110
16479
  } catch (error) {
16111
16480
  return {
@@ -16114,82 +16483,58 @@ async function defaultSignupCommanderLauncher(args) {
16114
16483
  restartCommand,
16115
16484
  error: error instanceof Error ? error.message : String(error)
16116
16485
  };
16117
- } finally {
16118
- closeFileDescriptor(stdoutFd);
16119
- closeFileDescriptor(stderrFd);
16120
16486
  }
16121
16487
  }
16122
- async function waitForSignupCommanderConnection(logFile, timeoutMs) {
16123
- const deadline = Date.now() + timeoutMs;
16124
- while (Date.now() <= deadline) {
16125
- const log = readTextFile(logFile);
16126
- if (log !== undefined && signupCommanderLogIsConnected(log)) {
16127
- return true;
16128
- }
16129
- await waitForSignupCommanderLogChange(logFile, deadline, () => {
16130
- const updatedLog = readTextFile(logFile);
16131
- return updatedLog !== undefined && signupCommanderLogIsConnected(updatedLog);
16132
- });
16133
- }
16134
- return false;
16135
- }
16136
- function signupCommanderLogIsConnected(log) {
16137
- return commanderConnectedMarkers.some((marker) => log.includes(marker));
16138
- }
16139
- function readTextFile(path) {
16140
- try {
16141
- return readFileSync10(path, "utf8");
16142
- } catch (_error) {
16143
- return;
16144
- }
16145
- }
16146
- function closeFileDescriptor(fd) {
16147
- if (fd === undefined) {
16148
- return;
16149
- }
16150
- try {
16151
- closeSync2(fd);
16152
- } catch (_error) {}
16153
- }
16154
- async function waitForSignupCommanderLogChange(logFile, deadline, ready2) {
16155
- const remaining = Math.max(0, deadline - Date.now());
16156
- await new Promise((resolve9) => {
16157
- let resolved = false;
16158
- let watcher;
16159
- const finish = () => {
16160
- if (resolved) {
16161
- return;
16162
- }
16163
- resolved = true;
16164
- watcher?.close();
16165
- clearTimeout(timer);
16166
- resolve9();
16167
- };
16168
- const timer = setTimeout(finish, remaining);
16169
- try {
16170
- watcher = watch(logFile, finish);
16171
- watcher.on("error", finish);
16172
- if (ready2()) {
16173
- finish();
16174
- }
16175
- } catch (_error) {
16176
- if (ready2()) {
16177
- finish();
16178
- return;
16179
- }
16180
- try {
16181
- watcher = watch(dirname9(logFile), finish);
16182
- watcher.on("error", finish);
16183
- } catch (_nestedError) {}
16184
- }
16185
- });
16186
- }
16187
16488
  function signupCommanderRunnerId(workspaceSlug) {
16188
16489
  return `signup-${workspaceSlug}-commander`;
16189
16490
  }
16190
- function signupCommanderLaunchLogFile(runnerId) {
16191
- const launchId = `${Date.now()}-${process.pid}`;
16192
- return join12(homedir8(), ".linzumi", "commanders", `${runnerId}-${launchId}.log`);
16491
+ function failedSignupCommanderLaunchForMissingCodex(args) {
16492
+ return {
16493
+ status: "failed",
16494
+ runnerId: signupCommanderRunnerId(args.workspaceSlug),
16495
+ restartCommand: signupConnectRestartCommand(args),
16496
+ error: "Codex preflight did not resolve a verified Codex command. Install Codex or fix the Codex CLI on PATH, then rerun signup."
16497
+ };
16498
+ }
16499
+ async function signupCommanderRunnerOptions(args, runnerId) {
16500
+ const trust = kandanTlsTrustFromEnv();
16501
+ const editorRuntime = await resolveEditorRuntime({
16502
+ kandanUrl: args.serviceUrl,
16503
+ token: args.localRunnerAccessToken,
16504
+ fetchImpl: trustedFetch(trust)
16505
+ });
16506
+ const dependencyStatus = await buildRunnerDependencyStatus({
16507
+ cwd: args.projectPath,
16508
+ codexBin: args.codexBin,
16509
+ codeServerBin: editorRuntime.codeServerBin,
16510
+ editorRuntime: editorRuntime.status
16511
+ });
16512
+ assertStartDependencies(dependencyStatus);
16513
+ return {
16514
+ kandanUrl: args.serviceUrl,
16515
+ token: args.localRunnerAccessToken,
16516
+ runnerId,
16517
+ machineId: ensureLocalMachineIdForLinzumiUrl(args.serviceUrl),
16518
+ workspaceSlug: args.workspaceSlug,
16519
+ cwd: args.projectPath,
16520
+ codexBin: args.codexBin,
16521
+ codexUrl: undefined,
16522
+ launchTui: false,
16523
+ fast: false,
16524
+ allowedCwds: Array.from(new Set([args.projectPath, ...args.selectedProjectPaths])),
16525
+ allowedForwardPorts: [],
16526
+ codeServerBin: editorRuntime.codeServerBin,
16527
+ editorRuntime: editorRuntime.runtime,
16528
+ socketFactory: trustedWebSocketFactory(trust),
16529
+ dependencyStatus,
16530
+ runtimeDefaults: {
16531
+ model: undefined,
16532
+ reasoningEffort: undefined,
16533
+ approvalPolicy: undefined,
16534
+ sandbox: undefined
16535
+ },
16536
+ channelSession: undefined
16537
+ };
16193
16538
  }
16194
16539
  function signupConnectRestartCommand(args) {
16195
16540
  return [
@@ -16199,23 +16544,12 @@ function signupConnectRestartCommand(args) {
16199
16544
  "connect",
16200
16545
  "--workspace",
16201
16546
  args.workspaceSlug,
16202
- ...args.serviceUrl === defaultLinzumiHttpUrl ? [] : ["--linzumi-url", args.serviceUrl]
16547
+ ...args.codexBin === undefined ? [] : ["--codex-bin", args.codexBin],
16548
+ "--cwd",
16549
+ args.projectPath,
16550
+ ...args.serviceUrl === defaultLinzumiHttpUrl ? [] : ["--api-url", args.serviceUrl]
16203
16551
  ].map(shellArg).join(" ");
16204
16552
  }
16205
- function signupCommanderConnectSpawnArgs(args, runnerId, logFile, scriptPath) {
16206
- return [
16207
- scriptPath,
16208
- "connect",
16209
- "--linzumi-url",
16210
- args.serviceUrl,
16211
- "--workspace",
16212
- args.workspaceSlug,
16213
- "--runner-id",
16214
- runnerId,
16215
- "--log-file",
16216
- logFile
16217
- ];
16218
- }
16219
16553
  function shellArg(value) {
16220
16554
  if (/^[A-Za-z0-9_./:=@%+-]+$/.test(value)) {
16221
16555
  return value;
@@ -17036,6 +17370,10 @@ function defaultPreflightRuntime() {
17036
17370
  checkBrowserHandoff: async () => true
17037
17371
  };
17038
17372
  }
17373
+ function verifiedCodexBinFromPreflightChecks(checks) {
17374
+ const codex = checks.find((check2) => check2.id === "codex");
17375
+ return codex?.command;
17376
+ }
17039
17377
  function defaultProjectDiscoveryRuntime() {
17040
17378
  const cwd = process.cwd();
17041
17379
  return {
@@ -17162,13 +17500,9 @@ async function resolveSignupCodexCommand(env = process.env, homeDir = homedir8()
17162
17500
  env.LINZUMI_CODEX_BIN
17163
17501
  ]);
17164
17502
  if (override !== undefined) {
17165
- return resolveHomePath(override, homeDir);
17503
+ return resolveCodexCommandOverride(override, homeDir);
17166
17504
  }
17167
- const homeCandidates = [
17168
- join12(homeDir, ".volta", "bin", "codex"),
17169
- join12(homeDir, ".local", "bin", "codex"),
17170
- join12(homeDir, "bin", "codex")
17171
- ];
17505
+ const homeCandidates = homeManagedCodexCandidates(homeDir);
17172
17506
  const homeCodex = await firstExecutablePath(homeCandidates, executableExists);
17173
17507
  if (homeCodex !== undefined) {
17174
17508
  return homeCodex;
@@ -17200,6 +17534,20 @@ function resolveHomePath(path, homeDir) {
17200
17534
  }
17201
17535
  return resolve8(path);
17202
17536
  }
17537
+ function resolveCodexCommandOverride(command, homeDir) {
17538
+ const trimmed = command.trim();
17539
+ return commandLooksPathLike(trimmed) ? resolveHomePath(trimmed, homeDir) : trimmed;
17540
+ }
17541
+ function commandLooksPathLike(command) {
17542
+ return command === "~" || command.startsWith("~/") || command.startsWith("/") || command.startsWith("./") || command.startsWith("../") || command.includes("/") || command.includes("\\");
17543
+ }
17544
+ function homeManagedCodexCandidates(homeDir) {
17545
+ return [
17546
+ join12(homeDir, ".volta", "bin", "codex"),
17547
+ join12(homeDir, ".local", "bin", "codex"),
17548
+ join12(homeDir, "bin", "codex")
17549
+ ];
17550
+ }
17203
17551
  async function firstExecutablePath(paths, executableExists) {
17204
17552
  for (const path of paths) {
17205
17553
  if (await executableExists(path)) {
@@ -17363,19 +17711,51 @@ async function checkGit(runtime) {
17363
17711
  };
17364
17712
  }
17365
17713
  async function checkCodex(runtime) {
17366
- const [pathCodex, voltaCodex] = await Promise.all([
17367
- runtime.probeTool("codex", runtime.cwd),
17368
- runtime.probeTool(join12(runtime.homeDir, ".volta", "bin", "codex"), runtime.cwd)
17369
- ]);
17370
- const codex = pathCodex.available ? pathCodex : voltaCodex;
17371
- const location = pathCodex.available ? "on PATH" : "via Volta";
17714
+ const configuredCodex = process.env.LINZUMI_SIGNUP_CODEX_BIN !== undefined && process.env.LINZUMI_SIGNUP_CODEX_BIN.trim() !== "" ? {
17715
+ value: process.env.LINZUMI_SIGNUP_CODEX_BIN,
17716
+ source: "LINZUMI_SIGNUP_CODEX_BIN"
17717
+ } : process.env.LINZUMI_CODEX_BIN !== undefined && process.env.LINZUMI_CODEX_BIN.trim() !== "" ? {
17718
+ value: process.env.LINZUMI_CODEX_BIN,
17719
+ source: "LINZUMI_CODEX_BIN"
17720
+ } : undefined;
17721
+ const configuredCommand = configuredCodex === undefined ? undefined : resolveCodexCommandOverride(configuredCodex.value, runtime.homeDir);
17722
+ if (configuredCommand !== undefined) {
17723
+ const codex2 = await runtime.probeTool(configuredCommand, runtime.cwd);
17724
+ const location2 = `from ${configuredCodex?.source ?? "configured env"}`;
17725
+ return {
17726
+ id: "codex",
17727
+ title: "Codex CLI",
17728
+ detail: codex2.available ? `${codex2.version ?? "codex found"} ${location2}` : `${configuredCommand} ${location2} did not pass --version`,
17729
+ status: codex2.available ? "pass" : "warn",
17730
+ command: codex2.available ? codex2.command : undefined
17731
+ };
17732
+ }
17733
+ const candidates = ["codex", ...homeManagedCodexCandidates(runtime.homeDir)];
17734
+ const [firstCodex, ...otherCodexes] = await Promise.all(candidates.map((candidate) => runtime.probeTool(candidate, runtime.cwd)));
17735
+ const codex = [firstCodex, ...otherCodexes].find((status) => status.available) ?? firstCodex;
17736
+ const location = codexPreflightLocation(codex.command, runtime.homeDir);
17372
17737
  return {
17373
17738
  id: "codex",
17374
17739
  title: "Codex CLI",
17375
17740
  detail: codex.available ? `${codex.version ?? "codex found"} ${location}` : "codex not found",
17376
- status: codex.available ? "pass" : "warn"
17741
+ status: codex.available ? "pass" : "warn",
17742
+ command: codex.available ? codex.command : undefined
17377
17743
  };
17378
17744
  }
17745
+ function codexPreflightLocation(command, homeDir) {
17746
+ switch (command) {
17747
+ case "codex":
17748
+ return "on PATH";
17749
+ case join12(homeDir, ".volta", "bin", "codex"):
17750
+ return "via Volta";
17751
+ case join12(homeDir, ".local", "bin", "codex"):
17752
+ return "via ~/.local/bin";
17753
+ case join12(homeDir, "bin", "codex"):
17754
+ return "via ~/bin";
17755
+ default:
17756
+ return "from configured path";
17757
+ }
17758
+ }
17379
17759
  async function checkGitEmail(runtime) {
17380
17760
  const email = await runtime.readGitEmail(runtime.cwd);
17381
17761
  return {
@@ -17703,15 +18083,15 @@ function renderPreflightRow(check2, spinnerFrame, columns) {
17703
18083
  // src/commanderDaemon.ts
17704
18084
  import {
17705
18085
  existsSync as existsSync11,
17706
- closeSync as closeSync3,
18086
+ closeSync as closeSync2,
17707
18087
  mkdirSync as mkdirSync11,
17708
- openSync as openSync4,
18088
+ openSync as openSync3,
17709
18089
  readFileSync as readFileSync11,
17710
- watch as watch2,
18090
+ watch,
17711
18091
  writeFileSync as writeFileSync9
17712
18092
  } from "node:fs";
17713
18093
  import { homedir as homedir9 } from "node:os";
17714
- import { dirname as dirname10, join as join13, resolve as resolve9 } from "node:path";
18094
+ import { dirname as dirname9, join as join13, resolve as resolve9 } from "node:path";
17715
18095
  import { execFileSync, spawn as spawn8 } from "node:child_process";
17716
18096
  import { fileURLToPath as fileURLToPath2 } from "node:url";
17717
18097
  var connectedMarkers = ["Connected to Linzumi", "Runner connected:"];
@@ -17744,9 +18124,9 @@ function startCommanderDaemon(options) {
17744
18124
  logFile
17745
18125
  ];
17746
18126
  mkdirSync11(statusDir, { recursive: true });
17747
- mkdirSync11(dirname10(logFile), { recursive: true });
17748
- const out = openSync4(logFile, "a");
17749
- const err = openSync4(logFile, "a");
18127
+ mkdirSync11(dirname9(logFile), { recursive: true });
18128
+ const out = openSync3(logFile, "a");
18129
+ const err = openSync3(logFile, "a");
17750
18130
  writeCliAuditEvent("process.spawn", {
17751
18131
  command: nodeBin,
17752
18132
  args: command,
@@ -17765,8 +18145,8 @@ function startCommanderDaemon(options) {
17765
18145
  pid: child.pid,
17766
18146
  purpose: "commander_daemon.start"
17767
18147
  }, { sessionId: options.runnerId });
17768
- closeSync3(out);
17769
- closeSync3(err);
18148
+ closeSync2(out);
18149
+ closeSync2(err);
17770
18150
  child.unref();
17771
18151
  if (child.pid === undefined) {
17772
18152
  throw new Error("commander daemon did not report a pid");
@@ -17796,7 +18176,7 @@ function commanderDaemonStatus(runnerId, statusDir = commanderStatusDir(), proce
17796
18176
  }
17797
18177
  async function waitForCommanderDaemon(options) {
17798
18178
  const now = options.now ?? (() => Date.now());
17799
- const readTextFile2 = options.readTextFile ?? ((path) => existsSync11(path) ? readFileSync11(path, "utf8") : undefined);
18179
+ const readTextFile = options.readTextFile ?? ((path) => existsSync11(path) ? readFileSync11(path, "utf8") : undefined);
17800
18180
  const statusImpl = options.statusImpl ?? commanderDaemonStatus;
17801
18181
  const deadline = now() + options.timeoutMs;
17802
18182
  while (now() <= deadline) {
@@ -17807,7 +18187,7 @@ async function waitForCommanderDaemon(options) {
17807
18187
  case "stopped":
17808
18188
  return { ok: false, reason: "stopped" };
17809
18189
  case "running": {
17810
- const log = readTextFile2(status.record.logFile);
18190
+ const log = readTextFile(status.record.logFile);
17811
18191
  if (log === undefined) {
17812
18192
  return { ok: false, reason: "timeout" };
17813
18193
  }
@@ -17815,7 +18195,7 @@ async function waitForCommanderDaemon(options) {
17815
18195
  return { ok: true, record: status.record };
17816
18196
  }
17817
18197
  await waitForFileChangeOrTimeout(status.record.logFile, deadline, now, () => {
17818
- const updatedLog = readTextFile2(status.record.logFile);
18198
+ const updatedLog = readTextFile(status.record.logFile);
17819
18199
  return updatedLog !== undefined && commanderLogIsConnected(updatedLog);
17820
18200
  });
17821
18201
  }
@@ -17941,7 +18321,7 @@ async function waitForFileChangeOrTimeout(path, deadline, now, ready2 = () => fa
17941
18321
  };
17942
18322
  const timer = setTimeout(finish, remaining);
17943
18323
  try {
17944
- watcher = watch2(path, finish);
18324
+ watcher = watch(path, finish);
17945
18325
  watcher.on("error", finish);
17946
18326
  if (ready2()) {
17947
18327
  finish();
@@ -17959,8 +18339,7 @@ async function waitForFileChangeOrTimeout(path, deadline, now, ready2 = () => fa
17959
18339
  // src/index.ts
17960
18340
  var flagDefinitions = new Map([
17961
18341
  ["version", { kind: "boolean" }],
17962
- ["linzumi-url", { kind: "value" }],
17963
- ["kandan-url", { kind: "value" }],
18342
+ ["api-url", { kind: "value" }],
17964
18343
  ["token", { kind: "value" }],
17965
18344
  ["runner-id", { kind: "value" }],
17966
18345
  ["cwd", { kind: "value" }],
@@ -17970,7 +18349,6 @@ var flagDefinitions = new Map([
17970
18349
  ["workspace", { kind: "value" }],
17971
18350
  ["channel", { kind: "value" }],
17972
18351
  ["linzumi-thread-id", { kind: "value" }],
17973
- ["kandan-thread-id", { kind: "value" }],
17974
18352
  ["listen-user", { kind: "value" }],
17975
18353
  ["model", { kind: "value" }],
17976
18354
  ["reasoning-effort", { kind: "value" }],
@@ -17989,10 +18367,6 @@ var flagDefinitions = new Map([
17989
18367
  ["oauth-callback-host", { kind: "value" }],
17990
18368
  ["help", { kind: "boolean" }]
17991
18369
  ]);
17992
- var flagAliases = new Map([
17993
- ["kandan-url", "linzumi-url"],
17994
- ["kandan-thread-id", "linzumi-thread-id"]
17995
- ]);
17996
18370
  var helloFlagDefinitions = new Map([
17997
18371
  ["dir", { kind: "value" }],
17998
18372
  ["parent-dir", { kind: "value" }],
@@ -18248,8 +18622,7 @@ function parsePathsCommandArgs(args) {
18248
18622
  case "--help":
18249
18623
  help = true;
18250
18624
  break;
18251
- case "--linzumi-url":
18252
- case "--kandan-url": {
18625
+ case "--api-url": {
18253
18626
  const value = args[index + 1];
18254
18627
  if (value === undefined || value.startsWith("--")) {
18255
18628
  throw new Error(`missing value for ${arg}`);
@@ -18360,7 +18733,7 @@ async function runAuthCommand(args) {
18360
18733
  process.stdout.write(helpText());
18361
18734
  return;
18362
18735
  }
18363
- const kandanUrl = required(values, "linzumi-url");
18736
+ const kandanUrl = required(values, "api-url");
18364
18737
  const target = parseOptionalChannelTarget(values);
18365
18738
  const token = await acquireLocalRunnerTokenDetails({
18366
18739
  kandanUrl,
@@ -18391,7 +18764,7 @@ async function parseStartRunnerArgs(args, deps = {
18391
18764
  process.exit(0);
18392
18765
  }
18393
18766
  rejectStartTargetingFlags(values);
18394
- const kandanUrl = stringValue4(values, "linzumi-url") ?? defaultLinzumiWebSocketUrl;
18767
+ const kandanUrl = stringValue4(values, "api-url") ?? defaultLinzumiWebSocketUrl;
18395
18768
  const requestedCwd = resolveUserPath(cwdArg ?? process.cwd());
18396
18769
  const cwd = assertConfiguredAllowedCwds([requestedCwd])[0] ?? requestedCwd;
18397
18770
  const explicitAllowedCwds = values.has("allowed-cwd") ? assertConfiguredAllowedCwds(parseAllowedCwdList(stringValue4(values, "allowed-cwd"))) : [];
@@ -18509,7 +18882,7 @@ async function parseAgentRunnerArgs(args, deps = {
18509
18882
  approvalPolicy: stringValue4(values, "approval-policy"),
18510
18883
  streamFlushMs: positiveIntegerValue2(values, "stream-flush-ms")
18511
18884
  };
18512
- const kandanUrl = stringValue4(values, "linzumi-url") ?? agentApiUrlToKandanUrl(tokenFile.apiUrl);
18885
+ const kandanUrl = stringValue4(values, "api-url") ?? agentApiUrlToKandanUrl(tokenFile.apiUrl);
18513
18886
  const requestedCwdValue = cwdArg ?? stringValue4(values, "cwd");
18514
18887
  const requestedCwd = resolveUserPath(requestedCwdValue ?? process.cwd());
18515
18888
  const configuredAllowedCwds2 = requestedCwdValue === undefined && !values.has("allowed-cwd") ? readConfiguredAllowedCwdDetailsForLinzumiUrl(kandanUrl) : { allowedCwds: [], missingAllowedCwds: [] };
@@ -18641,7 +19014,7 @@ async function parseRunnerArgs(args, deps = {
18641
19014
  }
18642
19015
  rejectConnectChannelFlags(values);
18643
19016
  const workspaceSlug = stringValue4(values, "workspace");
18644
- const kandanUrl = stringValue4(values, "linzumi-url") ?? defaultLinzumiWebSocketUrl;
19017
+ const kandanUrl = stringValue4(values, "api-url") ?? defaultLinzumiWebSocketUrl;
18645
19018
  const cwd = stringValue4(values, "cwd") ?? process.cwd();
18646
19019
  const cwdAllowedCwds = assertConfiguredAllowedCwds([cwd]);
18647
19020
  const localConfiguredAllowedCwds = values.has("allowed-cwd") ? { allowedCwds: [], missingAllowedCwds: [] } : readConfiguredAllowedCwdDetailsForLinzumiUrl(kandanUrl);
@@ -18699,7 +19072,8 @@ function runnerRuntimeDefaultsFromValues(values) {
18699
19072
  model: stringValue4(values, "model"),
18700
19073
  reasoningEffort: stringValue4(values, "reasoning-effort"),
18701
19074
  approvalPolicy: stringValue4(values, "approval-policy"),
18702
- sandbox: stringValue4(values, "sandbox")
19075
+ sandbox: stringValue4(values, "sandbox"),
19076
+ allowPortForwardingByDefault: undefined
18703
19077
  };
18704
19078
  }
18705
19079
  function strictFlagValues(args, definitions = flagDefinitions) {
@@ -18714,16 +19088,15 @@ function strictFlagValues(args, definitions = flagDefinitions) {
18714
19088
  if (definition === undefined) {
18715
19089
  throw new Error(`invalid flag: --${rawKey}`);
18716
19090
  }
18717
- const key = flagAliases.get(rawKey) ?? rawKey;
18718
19091
  if (definition.kind === "boolean") {
18719
- values.set(key, true);
19092
+ values.set(rawKey, true);
18720
19093
  continue;
18721
19094
  }
18722
19095
  const next = args[index + 1];
18723
19096
  if (next === undefined || next.startsWith("--")) {
18724
19097
  throw new Error(`missing value for --${rawKey}`);
18725
19098
  }
18726
- values.set(key, next);
19099
+ values.set(rawKey, next);
18727
19100
  index += 1;
18728
19101
  }
18729
19102
  return values;
@@ -18905,11 +19278,10 @@ Usage:
18905
19278
  linzumi start <folder> [options]
18906
19279
  linzumi paths list|add|remove [path]
18907
19280
  linzumi connect --workspace <slug> [options]
18908
- linzumi auth --linzumi-url <ws-url> [--workspace <slug> --channel <slug>]
19281
+ linzumi auth --api-url <url> [--workspace <slug> --channel <slug>]
18909
19282
 
18910
19283
  Connection:
18911
- --linzumi-url <ws-url> Linzumi backend URL, default ${defaultLinzumiWebSocketUrl}
18912
- (deprecated alias: --kandan-url)
19284
+ --api-url <url> Linzumi API URL, default ${defaultLinzumiWebSocketUrl}
18913
19285
  --token <jwt> Optional override token. Otherwise ~/.linzumi/auth.json is validated or OAuth opens.
18914
19286
  --auth-file <path> Auth cache path, default ~/.linzumi/auth.json
18915
19287
  --oauth-callback-host <ip> Callback host reachable by your browser
@@ -19022,12 +19394,12 @@ function pathsHelpText() {
19022
19394
  return `Linzumi trusted paths
19023
19395
 
19024
19396
  Usage:
19025
- linzumi paths [--linzumi-url <ws-url>] list
19026
- linzumi paths [--linzumi-url <ws-url>] add <path>
19027
- linzumi paths [--linzumi-url <ws-url>] remove <path>
19397
+ linzumi paths [--api-url <url>] list
19398
+ linzumi paths [--api-url <url>] add <path>
19399
+ linzumi paths [--api-url <url>] remove <path>
19028
19400
 
19029
19401
  Trusted paths are stored in ~/.linzumi/config.json. Production/default paths
19030
- use the root config fields; explicit --linzumi-url paths use a URL-scoped config
19402
+ use the root config fields; explicit --api-url paths use a URL-scoped config
19031
19403
  section so local, staging, and production runners do not share trust state.
19032
19404
  `;
19033
19405
  }
@@ -19044,8 +19416,7 @@ What it does:
19044
19416
  previews, and the browser VS Code editor.
19045
19417
 
19046
19418
  Options:
19047
- --linzumi-url <ws-url> Linzumi backend URL, default ${defaultLinzumiWebSocketUrl}
19048
- (deprecated alias: --kandan-url)
19419
+ --api-url <url> Linzumi API URL, default ${defaultLinzumiWebSocketUrl}
19049
19420
  --token <jwt> Optional scoped local-runner token override
19050
19421
  --auth-file <path> Auth cache path, default ~/.linzumi/auth.json
19051
19422
  --oauth-callback-host <ip> Callback host reachable by your browser
@@ -19085,8 +19456,7 @@ What it does:
19085
19456
 
19086
19457
  Options:
19087
19458
  --agent-token-file <path> Agent token cache, default ~/.linzumi/agent-token.json
19088
- --linzumi-url <ws-url> Linzumi websocket base URL. Defaults deterministically from the stored apiUrl.
19089
- (deprecated alias: --kandan-url)
19459
+ --api-url <url> Linzumi API URL. Defaults deterministically from the stored apiUrl.
19090
19460
  --runner-id <id> Stable Commander id
19091
19461
  --codex-bin <path> Codex executable, default codex
19092
19462
  --code-server-bin <path> Custom development code-server executable. By default Linzumi installs the approved editor runtime.
@@ -19102,7 +19472,7 @@ Options:
19102
19472
  Examples:
19103
19473
  linzumi paths add "$PWD"
19104
19474
  linzumi commander daemon --runner-id hello-world-commander
19105
- linzumi commander ~/code/my-app --linzumi-url ws://127.0.0.1:4162 --runner-id local-qa-commander
19475
+ linzumi commander ~/code/my-app --api-url http://127.0.0.1:4162 --runner-id local-qa-commander
19106
19476
  `;
19107
19477
  }
19108
19478
  function connectGuideText() {