@linzumi/cli 0.0.51-beta → 0.0.53-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.53-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,8 +11240,7 @@ 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) : [];
10921
- const discoveredCodexThreads = { value: codexThreads };
11243
+ const discoveredCodexThreads = { value: [] };
10922
11244
  const runtimeDefaults = runnerRuntimeDefaults(options);
10923
11245
  const instancePayload = {
10924
11246
  instanceId,
@@ -10927,11 +11249,12 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
10927
11249
  tuiLaunched: options.launchTui,
10928
11250
  cwd: options.cwd,
10929
11251
  hostname: runnerHost,
10930
- codexThreads,
11252
+ codexThreads: discoveredCodexThreads.value,
10931
11253
  workspace: runnerWorkspaceSlug(options) ?? null,
10932
11254
  channel: options.channelSession?.channelSlug ?? null,
10933
11255
  model: runtimeDefaults.model ?? null,
10934
11256
  reasoningEffort: runtimeDefaults.reasoningEffort ?? null,
11257
+ allowPortForwardingByDefault: runtimeDefaults.allowPortForwardingByDefault ?? null,
10935
11258
  fast: options.fast ?? false
10936
11259
  };
10937
11260
  await kandan.push(topic, "instance_started", instancePayload);
@@ -11039,7 +11362,8 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
11039
11362
  model: runtimeSettings.model,
11040
11363
  reasoningEffort: runtimeSettings.reasoningEffort,
11041
11364
  sandbox: runtimeSettings.sandbox,
11042
- approvalPolicy: runtimeSettings.approvalPolicy
11365
+ approvalPolicy: runtimeSettings.approvalPolicy,
11366
+ allowPortForwardingByDefault: runtimeSettings.allowPortForwardingByDefault
11043
11367
  }
11044
11368
  },
11045
11369
  log
@@ -11060,6 +11384,7 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
11060
11384
  codexThreads: discoveredCodexThreads.value,
11061
11385
  model: runtimeDefaults.model ?? null,
11062
11386
  reasoningEffort: runtimeDefaults.reasoningEffort ?? null,
11387
+ allowPortForwardingByDefault: runtimeDefaults.allowPortForwardingByDefault ?? null,
11063
11388
  fast: options.fast ?? false,
11064
11389
  capabilities: capabilitiesPayload()
11065
11390
  });
@@ -11068,19 +11393,11 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
11068
11393
  message: error instanceof Error ? error.message : String(error)
11069
11394
  });
11070
11395
  });
11071
- const refreshDiscoveredCodexThreads = () => discoverCodexThreads(codex, options.cwd).then((threads) => {
11072
- discoveredCodexThreads.value = threads;
11073
- return kandan.push(topic, "heartbeat", heartbeatPayload());
11074
- }).catch((error) => {
11075
- log("kandan.codex_threads_refresh_failed", {
11076
- message: error instanceof Error ? error.message : String(error)
11077
- });
11078
- });
11079
11396
  const heartbeatInterval = setInterval(() => {
11080
- channelSession === undefined ? refreshDiscoveredCodexThreads() : pushHeartbeat();
11397
+ pushHeartbeat();
11081
11398
  }, 15000);
11082
11399
  cleanup.actions.push(() => clearInterval(heartbeatInterval));
11083
- kandan.onReconnect(() => (channelSession === undefined ? refreshDiscoveredCodexThreads() : pushHeartbeat()).then(() => {
11400
+ kandan.onReconnect(() => pushHeartbeat().then(() => {
11084
11401
  return;
11085
11402
  }));
11086
11403
  pushHeartbeat();
@@ -11350,25 +11667,6 @@ async function closeCleanupStack(cleanup) {
11350
11667
  })();
11351
11668
  return cleanup.closePromise;
11352
11669
  }
11353
- async function discoverCodexThreads(codex, cwd) {
11354
- const response = await codex.request("thread/list", { cwd });
11355
- if ("error" in response) {
11356
- return [];
11357
- }
11358
- const result = objectValue(response.result);
11359
- const data = arrayValue(result?.data);
11360
- return data === undefined ? [] : data.filter(isJsonObject).map((thread) => ({
11361
- 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) ?? "",
11365
- cwd: stringValue(thread.cwd) ?? "",
11366
- 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 !== "");
11371
- }
11372
11670
  function extractStartedThreadId(response) {
11373
11671
  if ("error" in response) {
11374
11672
  throw new Error(`thread/start failed: ${response.error.message}`);
@@ -11801,6 +12099,10 @@ You MUST NOT ask the Bootstrapper Codex to do implementation work.
11801
12099
  You MUST NOT inspect unrelated repositories or folders.
11802
12100
  You MUST report the exact blocker if a command, preview, editor, or tunnel step
11803
12101
  fails.
12102
+ When several Linzumi Codex sessions work in the same repository, create or use
12103
+ a separate checkout or git worktree for this task before making changes, unless
12104
+ the human explicitly asks you to share the current checkout. Do not overwrite or
12105
+ revert another session's work.
11804
12106
  </rules>
11805
12107
 
11806
12108
  <examples>
@@ -11892,7 +12194,8 @@ function startInstanceRuntimeSettings(options, control) {
11892
12194
  reasoningEffort: control.reasoningEffort ?? defaults.reasoningEffort,
11893
12195
  approvalPolicy: codexApprovalPolicyForRequest(control.approvalPolicy ?? defaults.approvalPolicy, sandbox),
11894
12196
  sandbox,
11895
- fast: control.fast ?? options.fast
12197
+ fast: control.fast ?? options.fast,
12198
+ allowPortForwardingByDefault: control.allowPortForwardingByDefault ?? defaults.allowPortForwardingByDefault
11896
12199
  };
11897
12200
  }
11898
12201
  async function startOwnedCodexAppServer(options) {
@@ -11915,7 +12218,8 @@ function runnerRuntimeDefaults(options) {
11915
12218
  model: defaults?.model ?? session?.model,
11916
12219
  reasoningEffort: defaults?.reasoningEffort ?? session?.reasoningEffort,
11917
12220
  approvalPolicy: codexApprovalPolicySetting(defaults?.approvalPolicy ?? session?.approvalPolicy, sandbox),
11918
- sandbox
12221
+ sandbox,
12222
+ allowPortForwardingByDefault: defaults?.allowPortForwardingByDefault ?? session?.allowPortForwardingByDefault
11919
12223
  };
11920
12224
  }
11921
12225
  function isUpdateRunnerConfigControl(control) {
@@ -13396,7 +13700,7 @@ To kick the agent off:
13396
13700
  3. Paste into the thread. Codex will pick it up and start editing this folder.
13397
13701
  `;
13398
13702
 
13399
- // ../../node_modules/@inquirer/core/dist/esm/lib/key.js
13703
+ // node_modules/@inquirer/core/dist/esm/lib/key.js
13400
13704
  var isUpKey = (key, keybindings = []) => key.name === "up" || keybindings.includes("vim") && key.name === "k" || keybindings.includes("emacs") && key.ctrl && key.name === "p";
13401
13705
  var isDownKey = (key, keybindings = []) => key.name === "down" || keybindings.includes("vim") && key.name === "j" || keybindings.includes("emacs") && key.ctrl && key.name === "n";
13402
13706
  var isSpaceKey = (key) => key.name === "space";
@@ -13404,7 +13708,7 @@ var isBackspaceKey = (key) => key.name === "backspace";
13404
13708
  var isTabKey = (key) => key.name === "tab";
13405
13709
  var isNumberKey = (key) => "1234567890".includes(key.name);
13406
13710
  var isEnterKey = (key) => key.name === "enter" || key.name === "return";
13407
- // ../../node_modules/@inquirer/core/dist/esm/lib/errors.js
13711
+ // node_modules/@inquirer/core/dist/esm/lib/errors.js
13408
13712
  class AbortPromptError extends Error {
13409
13713
  name = "AbortPromptError";
13410
13714
  message = "Prompt was aborted";
@@ -13430,10 +13734,10 @@ class HookError extends Error {
13430
13734
  class ValidationError extends Error {
13431
13735
  name = "ValidationError";
13432
13736
  }
13433
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-state.js
13737
+ // node_modules/@inquirer/core/dist/esm/lib/use-state.js
13434
13738
  import { AsyncResource as AsyncResource2 } from "node:async_hooks";
13435
13739
 
13436
- // ../../node_modules/@inquirer/core/dist/esm/lib/hook-engine.js
13740
+ // node_modules/@inquirer/core/dist/esm/lib/hook-engine.js
13437
13741
  import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
13438
13742
  var hookStorage = new AsyncLocalStorage;
13439
13743
  function createStore(rl) {
@@ -13538,7 +13842,7 @@ var effectScheduler = {
13538
13842
  }
13539
13843
  };
13540
13844
 
13541
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-state.js
13845
+ // node_modules/@inquirer/core/dist/esm/lib/use-state.js
13542
13846
  function useState(defaultValue) {
13543
13847
  return withPointer((pointer) => {
13544
13848
  const setState = AsyncResource2.bind(function setState2(newValue) {
@@ -13556,7 +13860,7 @@ function useState(defaultValue) {
13556
13860
  });
13557
13861
  }
13558
13862
 
13559
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-effect.js
13863
+ // node_modules/@inquirer/core/dist/esm/lib/use-effect.js
13560
13864
  function useEffect(cb, depArray) {
13561
13865
  withPointer((pointer) => {
13562
13866
  const oldDeps = pointer.get();
@@ -13568,10 +13872,10 @@ function useEffect(cb, depArray) {
13568
13872
  });
13569
13873
  }
13570
13874
 
13571
- // ../../node_modules/@inquirer/core/dist/esm/lib/theme.js
13875
+ // node_modules/@inquirer/core/dist/esm/lib/theme.js
13572
13876
  var import_yoctocolors_cjs = __toESM(require_yoctocolors_cjs(), 1);
13573
13877
 
13574
- // ../../node_modules/@inquirer/figures/dist/esm/index.js
13878
+ // node_modules/@inquirer/figures/dist/esm/index.js
13575
13879
  import process2 from "node:process";
13576
13880
  function isUnicodeSupported() {
13577
13881
  if (process2.platform !== "win32") {
@@ -13860,7 +14164,7 @@ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
13860
14164
  var esm_default = figures;
13861
14165
  var replacements = Object.entries(specialMainSymbols);
13862
14166
 
13863
- // ../../node_modules/@inquirer/core/dist/esm/lib/theme.js
14167
+ // node_modules/@inquirer/core/dist/esm/lib/theme.js
13864
14168
  var defaultTheme = {
13865
14169
  prefix: {
13866
14170
  idle: import_yoctocolors_cjs.default.blue("?"),
@@ -13881,7 +14185,7 @@ var defaultTheme = {
13881
14185
  }
13882
14186
  };
13883
14187
 
13884
- // ../../node_modules/@inquirer/core/dist/esm/lib/make-theme.js
14188
+ // node_modules/@inquirer/core/dist/esm/lib/make-theme.js
13885
14189
  function isPlainObject(value) {
13886
14190
  if (typeof value !== "object" || value === null)
13887
14191
  return false;
@@ -13909,7 +14213,7 @@ function makeTheme(...themes) {
13909
14213
  return deepMerge(...themesToMerge);
13910
14214
  }
13911
14215
 
13912
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-prefix.js
14216
+ // node_modules/@inquirer/core/dist/esm/lib/use-prefix.js
13913
14217
  function usePrefix({ status = "idle", theme }) {
13914
14218
  const [showLoader, setShowLoader] = useState(false);
13915
14219
  const [tick, setTick] = useState(0);
@@ -13939,7 +14243,7 @@ function usePrefix({ status = "idle", theme }) {
13939
14243
  const iconName = status === "loading" ? "idle" : status;
13940
14244
  return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
13941
14245
  }
13942
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-memo.js
14246
+ // node_modules/@inquirer/core/dist/esm/lib/use-memo.js
13943
14247
  function useMemo(fn, dependencies) {
13944
14248
  return withPointer((pointer) => {
13945
14249
  const prev = pointer.get();
@@ -13951,11 +14255,11 @@ function useMemo(fn, dependencies) {
13951
14255
  return prev.value;
13952
14256
  });
13953
14257
  }
13954
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-ref.js
14258
+ // node_modules/@inquirer/core/dist/esm/lib/use-ref.js
13955
14259
  function useRef(val) {
13956
14260
  return useState({ current: val })[0];
13957
14261
  }
13958
- // ../../node_modules/@inquirer/core/dist/esm/lib/use-keypress.js
14262
+ // node_modules/@inquirer/core/dist/esm/lib/use-keypress.js
13959
14263
  function useKeypress(userHandler) {
13960
14264
  const signal = useRef(userHandler);
13961
14265
  signal.current = userHandler;
@@ -13973,7 +14277,7 @@ function useKeypress(userHandler) {
13973
14277
  };
13974
14278
  }, []);
13975
14279
  }
13976
- // ../../node_modules/@inquirer/core/dist/esm/lib/utils.js
14280
+ // node_modules/@inquirer/core/dist/esm/lib/utils.js
13977
14281
  var import_cli_width = __toESM(require_cli_width(), 1);
13978
14282
  var import_wrap_ansi = __toESM(require_wrap_ansi(), 1);
13979
14283
  function breakLines(content, width) {
@@ -13986,7 +14290,7 @@ function readlineWidth() {
13986
14290
  return import_cli_width.default({ defaultWidth: 80, output: readline().output });
13987
14291
  }
13988
14292
 
13989
- // ../../node_modules/@inquirer/core/dist/esm/lib/pagination/use-pagination.js
14293
+ // node_modules/@inquirer/core/dist/esm/lib/pagination/use-pagination.js
13990
14294
  function usePointerPosition({ active, renderedItems, pageSize, loop }) {
13991
14295
  const state = useRef({
13992
14296
  lastPointer: active,
@@ -14052,12 +14356,12 @@ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
14052
14356
  return pageBuffer.filter((line) => typeof line === "string").join(`
14053
14357
  `);
14054
14358
  }
14055
- // ../../node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14359
+ // node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14056
14360
  var import_mute_stream = __toESM(require_lib(), 1);
14057
14361
  import * as readline2 from "node:readline";
14058
14362
  import { AsyncResource as AsyncResource3 } from "node:async_hooks";
14059
14363
 
14060
- // ../../node_modules/@inquirer/core/node_modules/signal-exit/dist/mjs/signals.js
14364
+ // node_modules/signal-exit/dist/mjs/signals.js
14061
14365
  var signals = [];
14062
14366
  signals.push("SIGHUP", "SIGINT", "SIGTERM");
14063
14367
  if (process.platform !== "win32") {
@@ -14067,7 +14371,7 @@ if (process.platform === "linux") {
14067
14371
  signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
14068
14372
  }
14069
14373
 
14070
- // ../../node_modules/@inquirer/core/node_modules/signal-exit/dist/mjs/index.js
14374
+ // node_modules/signal-exit/dist/mjs/index.js
14071
14375
  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
14376
  var kExitEmitter = Symbol.for("signal-exit emitter");
14073
14377
  var global = globalThis;
@@ -14265,10 +14569,10 @@ var {
14265
14569
  unload
14266
14570
  } = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback);
14267
14571
 
14268
- // ../../node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14572
+ // node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14269
14573
  import { stripVTControlCharacters } from "node:util";
14270
14574
 
14271
- // ../../node_modules/@inquirer/ansi/dist/esm/index.js
14575
+ // node_modules/@inquirer/ansi/dist/esm/index.js
14272
14576
  var ESC = "\x1B[";
14273
14577
  var cursorLeft = ESC + "G";
14274
14578
  var cursorHide = ESC + "?25l";
@@ -14284,7 +14588,7 @@ var cursorTo = (x, y) => {
14284
14588
  var eraseLine = ESC + "2K";
14285
14589
  var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
14286
14590
 
14287
- // ../../node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14591
+ // node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14288
14592
  var height = (content) => content.split(`
14289
14593
  `).length;
14290
14594
  var lastLine = (content) => content.split(`
@@ -14349,7 +14653,7 @@ class ScreenManager {
14349
14653
  }
14350
14654
  }
14351
14655
 
14352
- // ../../node_modules/@inquirer/core/dist/esm/lib/promise-polyfill.js
14656
+ // node_modules/@inquirer/core/dist/esm/lib/promise-polyfill.js
14353
14657
  class PromisePolyfill extends Promise {
14354
14658
  static withResolver() {
14355
14659
  let resolve8;
@@ -14362,7 +14666,7 @@ class PromisePolyfill extends Promise {
14362
14666
  }
14363
14667
  }
14364
14668
 
14365
- // ../../node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14669
+ // node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14366
14670
  function getCallSites() {
14367
14671
  const _prepareStackTrace = Error.prepareStackTrace;
14368
14672
  let result = [];
@@ -14448,7 +14752,7 @@ function createPrompt(view) {
14448
14752
  };
14449
14753
  return prompt;
14450
14754
  }
14451
- // ../../node_modules/@inquirer/core/dist/esm/lib/Separator.js
14755
+ // node_modules/@inquirer/core/dist/esm/lib/Separator.js
14452
14756
  var import_yoctocolors_cjs2 = __toESM(require_yoctocolors_cjs(), 1);
14453
14757
  class Separator {
14454
14758
  separator = import_yoctocolors_cjs2.default.dim(Array.from({ length: 15 }).join(esm_default.line));
@@ -14462,7 +14766,7 @@ class Separator {
14462
14766
  return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
14463
14767
  }
14464
14768
  }
14465
- // ../../node_modules/@inquirer/checkbox/dist/esm/index.js
14769
+ // node_modules/@inquirer/checkbox/dist/esm/index.js
14466
14770
  var import_yoctocolors_cjs3 = __toESM(require_yoctocolors_cjs(), 1);
14467
14771
  var checkboxTheme = {
14468
14772
  icon: {
@@ -14649,7 +14953,7 @@ var esm_default2 = createPrompt((config, done) => {
14649
14953
  `).trimEnd();
14650
14954
  return `${lines}${cursorHide}`;
14651
14955
  });
14652
- // ../../node_modules/@inquirer/input/dist/esm/index.js
14956
+ // node_modules/@inquirer/input/dist/esm/index.js
14653
14957
  var inputTheme = {
14654
14958
  validationFailureMode: "keep"
14655
14959
  };
@@ -14733,7 +15037,7 @@ var esm_default3 = createPrompt((config, done) => {
14733
15037
  error
14734
15038
  ];
14735
15039
  });
14736
- // ../../node_modules/@inquirer/select/dist/esm/index.js
15040
+ // node_modules/@inquirer/select/dist/esm/index.js
14737
15041
  var import_yoctocolors_cjs4 = __toESM(require_yoctocolors_cjs(), 1);
14738
15042
  var selectTheme = {
14739
15043
  icon: { cursor: esm_default.pointer },
@@ -14900,28 +15204,19 @@ var esm_default4 = createPrompt((config, done) => {
14900
15204
  // src/signupFlow.ts
14901
15205
  import { spawn as spawn7 } from "node:child_process";
14902
15206
  import {
14903
- closeSync as closeSync2,
14904
15207
  existsSync as existsSync10,
14905
15208
  constants as fsConstants,
14906
- mkdirSync as mkdirSync10,
14907
15209
  mkdtempSync as mkdtempSync3,
14908
- openSync as openSync3,
14909
15210
  readFileSync as readFileSync10,
14910
15211
  readdirSync,
14911
15212
  rmSync as rmSync3,
14912
15213
  statSync,
14913
- watch,
14914
15214
  writeFileSync as writeFileSync8
14915
15215
  } from "node:fs";
14916
15216
  import { access } from "node:fs/promises";
14917
15217
  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";
15218
+ import { delimiter as delimiter2, join as join12, resolve as resolve8 } from "node:path";
15219
+ import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
14925
15220
  import { emitKeypressEvents } from "node:readline";
14926
15221
 
14927
15222
  // src/signupServerClient.ts
@@ -15207,11 +15502,6 @@ function booleanValue(record, key) {
15207
15502
  }
15208
15503
 
15209
15504
  // src/signupFlow.ts
15210
- var commanderConnectedMarkers = [
15211
- "Connected to Linzumi",
15212
- "Runner connected:",
15213
- '"event":"runner.instance_started"'
15214
- ];
15215
15505
  var blue = (value) => `\x1B[38;5;75m${value}\x1B[0m`;
15216
15506
  var green = (value) => `\x1B[38;5;114m${value}\x1B[0m`;
15217
15507
  var red = (value) => `\x1B[38;5;203m${value}\x1B[0m`;
@@ -15519,6 +15809,8 @@ async function runSignupFlow(deps = {}) {
15519
15809
  rootSeq: thread.rootSeq,
15520
15810
  threadSeq: thread.threadSeq
15521
15811
  }));
15812
+ const starterProjectPath = missionControl.config.starterProjectPath ?? starterProject.path;
15813
+ const verifiedCodexBin = verifiedCodexBinFromPreflightChecks(state.preflightChecks);
15522
15814
  const storedSignupAuth = writeSignupCompletion({
15523
15815
  email: verifiedAuth.user.primaryEmail ?? state.email ?? verifiedAuth.user.username,
15524
15816
  serviceUrl,
@@ -15530,20 +15822,24 @@ async function runSignupFlow(deps = {}) {
15530
15822
  launchUrl: missionControl.launchUrl,
15531
15823
  allowedCwds: missionControl.config.allowedCwds
15532
15824
  });
15533
- const commanderLaunch = await launchSignupCommanderForCompletedSignup(commanderLauncher, {
15825
+ const commanderLaunch = verifiedCodexBin === undefined ? failedSignupCommanderLaunchForMissingCodex({
15826
+ serviceUrl,
15827
+ workspaceSlug: missionControl.workspace.slug,
15828
+ projectPath: starterProjectPath
15829
+ }) : await launchSignupCommanderForCompletedSignup(commanderLauncher, {
15534
15830
  serviceUrl,
15535
15831
  localRunnerAccessToken: missionControl.localRunnerToken.accessToken,
15536
15832
  localRunnerExpiresInSeconds: missionControl.localRunnerToken.expiresInSeconds,
15537
15833
  workspaceSlug: missionControl.workspace.slug,
15538
- officeChannelSlug: missionControl.channels.office.slug,
15539
- projectPath: missionControl.config.starterProjectPath ?? starterProject.path,
15540
- selectedProjectPaths: missionControl.config.allowedCwds
15834
+ projectPath: starterProjectPath,
15835
+ selectedProjectPaths: missionControl.config.allowedCwds,
15836
+ codexBin: verifiedCodexBin
15541
15837
  });
15542
15838
  const starterTaskLaunches = await startSignupTasksForCommander(signupServerClient, {
15543
15839
  accessToken: verifiedAuth.accessToken,
15544
15840
  missionControl,
15545
15841
  commanderLaunch,
15546
- starterProjectPath: missionControl.config.starterProjectPath ?? starterProject.path,
15842
+ starterProjectPath,
15547
15843
  threads: starterTaskThreads
15548
15844
  });
15549
15845
  state = updateSignupState(state, {
@@ -16022,7 +16318,7 @@ function writeLaunchSummary(output, state) {
16022
16318
  writeBoundedLine(output, `${green("✓")} Local Commander connected this computer to Mission Control (${state.commanderLaunch.runnerId})`);
16023
16319
  break;
16024
16320
  case "failed":
16025
- writeStatusMessage(output, red("x"), `Local Commander could not start automatically: ${state.commanderLaunch.error}`);
16321
+ writeStatusMessage(output, red("x"), `Local Commander could not connect: ${state.commanderLaunch.error}`);
16026
16322
  break;
16027
16323
  }
16028
16324
  }
@@ -16064,48 +16360,17 @@ async function defaultSignupCommanderLauncher(args) {
16064
16360
  accessToken: args.localRunnerAccessToken,
16065
16361
  expiresInSeconds: args.localRunnerExpiresInSeconds
16066
16362
  });
16067
- const scriptPath = processArgv[1];
16068
16363
  const runnerId = signupCommanderRunnerId(args.workspaceSlug);
16069
16364
  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
16365
  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
- }
16366
+ const handle = await runLocalCodexRunner(await signupCommanderRunnerOptions(args, runnerId));
16103
16367
  return {
16104
16368
  status: "started",
16105
16369
  runnerId,
16106
16370
  restartCommand,
16107
- logFile,
16108
- ...child.pid === undefined ? {} : { pid: child.pid }
16371
+ pid: process.pid,
16372
+ instanceId: handle.instanceId,
16373
+ codexUrl: handle.codexUrl
16109
16374
  };
16110
16375
  } catch (error) {
16111
16376
  return {
@@ -16114,82 +16379,58 @@ async function defaultSignupCommanderLauncher(args) {
16114
16379
  restartCommand,
16115
16380
  error: error instanceof Error ? error.message : String(error)
16116
16381
  };
16117
- } finally {
16118
- closeFileDescriptor(stdoutFd);
16119
- closeFileDescriptor(stderrFd);
16120
- }
16121
- }
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
16382
  }
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
16383
  }
16187
16384
  function signupCommanderRunnerId(workspaceSlug) {
16188
16385
  return `signup-${workspaceSlug}-commander`;
16189
16386
  }
16190
- function signupCommanderLaunchLogFile(runnerId) {
16191
- const launchId = `${Date.now()}-${process.pid}`;
16192
- return join12(homedir8(), ".linzumi", "commanders", `${runnerId}-${launchId}.log`);
16387
+ function failedSignupCommanderLaunchForMissingCodex(args) {
16388
+ return {
16389
+ status: "failed",
16390
+ runnerId: signupCommanderRunnerId(args.workspaceSlug),
16391
+ restartCommand: signupConnectRestartCommand(args),
16392
+ error: "Codex preflight did not resolve a verified Codex command. Install Codex or fix the Codex CLI on PATH, then rerun signup."
16393
+ };
16394
+ }
16395
+ async function signupCommanderRunnerOptions(args, runnerId) {
16396
+ const trust = kandanTlsTrustFromEnv();
16397
+ const editorRuntime = await resolveEditorRuntime({
16398
+ kandanUrl: args.serviceUrl,
16399
+ token: args.localRunnerAccessToken,
16400
+ fetchImpl: trustedFetch(trust)
16401
+ });
16402
+ const dependencyStatus = await buildRunnerDependencyStatus({
16403
+ cwd: args.projectPath,
16404
+ codexBin: args.codexBin,
16405
+ codeServerBin: editorRuntime.codeServerBin,
16406
+ editorRuntime: editorRuntime.status
16407
+ });
16408
+ assertStartDependencies(dependencyStatus);
16409
+ return {
16410
+ kandanUrl: args.serviceUrl,
16411
+ token: args.localRunnerAccessToken,
16412
+ runnerId,
16413
+ machineId: ensureLocalMachineIdForLinzumiUrl(args.serviceUrl),
16414
+ workspaceSlug: args.workspaceSlug,
16415
+ cwd: args.projectPath,
16416
+ codexBin: args.codexBin,
16417
+ codexUrl: undefined,
16418
+ launchTui: false,
16419
+ fast: false,
16420
+ allowedCwds: Array.from(new Set([args.projectPath, ...args.selectedProjectPaths])),
16421
+ allowedForwardPorts: [],
16422
+ codeServerBin: editorRuntime.codeServerBin,
16423
+ editorRuntime: editorRuntime.runtime,
16424
+ socketFactory: trustedWebSocketFactory(trust),
16425
+ dependencyStatus,
16426
+ runtimeDefaults: {
16427
+ model: undefined,
16428
+ reasoningEffort: undefined,
16429
+ approvalPolicy: undefined,
16430
+ sandbox: undefined
16431
+ },
16432
+ channelSession: undefined
16433
+ };
16193
16434
  }
16194
16435
  function signupConnectRestartCommand(args) {
16195
16436
  return [
@@ -16199,23 +16440,12 @@ function signupConnectRestartCommand(args) {
16199
16440
  "connect",
16200
16441
  "--workspace",
16201
16442
  args.workspaceSlug,
16202
- ...args.serviceUrl === defaultLinzumiHttpUrl ? [] : ["--linzumi-url", args.serviceUrl]
16443
+ ...args.codexBin === undefined ? [] : ["--codex-bin", args.codexBin],
16444
+ "--cwd",
16445
+ args.projectPath,
16446
+ ...args.serviceUrl === defaultLinzumiHttpUrl ? [] : ["--api-url", args.serviceUrl]
16203
16447
  ].map(shellArg).join(" ");
16204
16448
  }
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
16449
  function shellArg(value) {
16220
16450
  if (/^[A-Za-z0-9_./:=@%+-]+$/.test(value)) {
16221
16451
  return value;
@@ -17036,6 +17266,10 @@ function defaultPreflightRuntime() {
17036
17266
  checkBrowserHandoff: async () => true
17037
17267
  };
17038
17268
  }
17269
+ function verifiedCodexBinFromPreflightChecks(checks) {
17270
+ const codex = checks.find((check2) => check2.id === "codex");
17271
+ return codex?.command;
17272
+ }
17039
17273
  function defaultProjectDiscoveryRuntime() {
17040
17274
  const cwd = process.cwd();
17041
17275
  return {
@@ -17162,13 +17396,9 @@ async function resolveSignupCodexCommand(env = process.env, homeDir = homedir8()
17162
17396
  env.LINZUMI_CODEX_BIN
17163
17397
  ]);
17164
17398
  if (override !== undefined) {
17165
- return resolveHomePath(override, homeDir);
17399
+ return resolveCodexCommandOverride(override, homeDir);
17166
17400
  }
17167
- const homeCandidates = [
17168
- join12(homeDir, ".volta", "bin", "codex"),
17169
- join12(homeDir, ".local", "bin", "codex"),
17170
- join12(homeDir, "bin", "codex")
17171
- ];
17401
+ const homeCandidates = homeManagedCodexCandidates(homeDir);
17172
17402
  const homeCodex = await firstExecutablePath(homeCandidates, executableExists);
17173
17403
  if (homeCodex !== undefined) {
17174
17404
  return homeCodex;
@@ -17200,6 +17430,20 @@ function resolveHomePath(path, homeDir) {
17200
17430
  }
17201
17431
  return resolve8(path);
17202
17432
  }
17433
+ function resolveCodexCommandOverride(command, homeDir) {
17434
+ const trimmed = command.trim();
17435
+ return commandLooksPathLike(trimmed) ? resolveHomePath(trimmed, homeDir) : trimmed;
17436
+ }
17437
+ function commandLooksPathLike(command) {
17438
+ return command === "~" || command.startsWith("~/") || command.startsWith("/") || command.startsWith("./") || command.startsWith("../") || command.includes("/") || command.includes("\\");
17439
+ }
17440
+ function homeManagedCodexCandidates(homeDir) {
17441
+ return [
17442
+ join12(homeDir, ".volta", "bin", "codex"),
17443
+ join12(homeDir, ".local", "bin", "codex"),
17444
+ join12(homeDir, "bin", "codex")
17445
+ ];
17446
+ }
17203
17447
  async function firstExecutablePath(paths, executableExists) {
17204
17448
  for (const path of paths) {
17205
17449
  if (await executableExists(path)) {
@@ -17363,19 +17607,51 @@ async function checkGit(runtime) {
17363
17607
  };
17364
17608
  }
17365
17609
  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";
17610
+ const configuredCodex = process.env.LINZUMI_SIGNUP_CODEX_BIN !== undefined && process.env.LINZUMI_SIGNUP_CODEX_BIN.trim() !== "" ? {
17611
+ value: process.env.LINZUMI_SIGNUP_CODEX_BIN,
17612
+ source: "LINZUMI_SIGNUP_CODEX_BIN"
17613
+ } : process.env.LINZUMI_CODEX_BIN !== undefined && process.env.LINZUMI_CODEX_BIN.trim() !== "" ? {
17614
+ value: process.env.LINZUMI_CODEX_BIN,
17615
+ source: "LINZUMI_CODEX_BIN"
17616
+ } : undefined;
17617
+ const configuredCommand = configuredCodex === undefined ? undefined : resolveCodexCommandOverride(configuredCodex.value, runtime.homeDir);
17618
+ if (configuredCommand !== undefined) {
17619
+ const codex2 = await runtime.probeTool(configuredCommand, runtime.cwd);
17620
+ const location2 = `from ${configuredCodex?.source ?? "configured env"}`;
17621
+ return {
17622
+ id: "codex",
17623
+ title: "Codex CLI",
17624
+ detail: codex2.available ? `${codex2.version ?? "codex found"} ${location2}` : `${configuredCommand} ${location2} did not pass --version`,
17625
+ status: codex2.available ? "pass" : "warn",
17626
+ command: codex2.available ? codex2.command : undefined
17627
+ };
17628
+ }
17629
+ const candidates = ["codex", ...homeManagedCodexCandidates(runtime.homeDir)];
17630
+ const [firstCodex, ...otherCodexes] = await Promise.all(candidates.map((candidate) => runtime.probeTool(candidate, runtime.cwd)));
17631
+ const codex = [firstCodex, ...otherCodexes].find((status) => status.available) ?? firstCodex;
17632
+ const location = codexPreflightLocation(codex.command, runtime.homeDir);
17372
17633
  return {
17373
17634
  id: "codex",
17374
17635
  title: "Codex CLI",
17375
17636
  detail: codex.available ? `${codex.version ?? "codex found"} ${location}` : "codex not found",
17376
- status: codex.available ? "pass" : "warn"
17637
+ status: codex.available ? "pass" : "warn",
17638
+ command: codex.available ? codex.command : undefined
17377
17639
  };
17378
17640
  }
17641
+ function codexPreflightLocation(command, homeDir) {
17642
+ switch (command) {
17643
+ case "codex":
17644
+ return "on PATH";
17645
+ case join12(homeDir, ".volta", "bin", "codex"):
17646
+ return "via Volta";
17647
+ case join12(homeDir, ".local", "bin", "codex"):
17648
+ return "via ~/.local/bin";
17649
+ case join12(homeDir, "bin", "codex"):
17650
+ return "via ~/bin";
17651
+ default:
17652
+ return "from configured path";
17653
+ }
17654
+ }
17379
17655
  async function checkGitEmail(runtime) {
17380
17656
  const email = await runtime.readGitEmail(runtime.cwd);
17381
17657
  return {
@@ -17703,15 +17979,15 @@ function renderPreflightRow(check2, spinnerFrame, columns) {
17703
17979
  // src/commanderDaemon.ts
17704
17980
  import {
17705
17981
  existsSync as existsSync11,
17706
- closeSync as closeSync3,
17982
+ closeSync as closeSync2,
17707
17983
  mkdirSync as mkdirSync11,
17708
- openSync as openSync4,
17984
+ openSync as openSync3,
17709
17985
  readFileSync as readFileSync11,
17710
- watch as watch2,
17986
+ watch,
17711
17987
  writeFileSync as writeFileSync9
17712
17988
  } from "node:fs";
17713
17989
  import { homedir as homedir9 } from "node:os";
17714
- import { dirname as dirname10, join as join13, resolve as resolve9 } from "node:path";
17990
+ import { dirname as dirname9, join as join13, resolve as resolve9 } from "node:path";
17715
17991
  import { execFileSync, spawn as spawn8 } from "node:child_process";
17716
17992
  import { fileURLToPath as fileURLToPath2 } from "node:url";
17717
17993
  var connectedMarkers = ["Connected to Linzumi", "Runner connected:"];
@@ -17744,9 +18020,9 @@ function startCommanderDaemon(options) {
17744
18020
  logFile
17745
18021
  ];
17746
18022
  mkdirSync11(statusDir, { recursive: true });
17747
- mkdirSync11(dirname10(logFile), { recursive: true });
17748
- const out = openSync4(logFile, "a");
17749
- const err = openSync4(logFile, "a");
18023
+ mkdirSync11(dirname9(logFile), { recursive: true });
18024
+ const out = openSync3(logFile, "a");
18025
+ const err = openSync3(logFile, "a");
17750
18026
  writeCliAuditEvent("process.spawn", {
17751
18027
  command: nodeBin,
17752
18028
  args: command,
@@ -17765,8 +18041,8 @@ function startCommanderDaemon(options) {
17765
18041
  pid: child.pid,
17766
18042
  purpose: "commander_daemon.start"
17767
18043
  }, { sessionId: options.runnerId });
17768
- closeSync3(out);
17769
- closeSync3(err);
18044
+ closeSync2(out);
18045
+ closeSync2(err);
17770
18046
  child.unref();
17771
18047
  if (child.pid === undefined) {
17772
18048
  throw new Error("commander daemon did not report a pid");
@@ -17796,7 +18072,7 @@ function commanderDaemonStatus(runnerId, statusDir = commanderStatusDir(), proce
17796
18072
  }
17797
18073
  async function waitForCommanderDaemon(options) {
17798
18074
  const now = options.now ?? (() => Date.now());
17799
- const readTextFile2 = options.readTextFile ?? ((path) => existsSync11(path) ? readFileSync11(path, "utf8") : undefined);
18075
+ const readTextFile = options.readTextFile ?? ((path) => existsSync11(path) ? readFileSync11(path, "utf8") : undefined);
17800
18076
  const statusImpl = options.statusImpl ?? commanderDaemonStatus;
17801
18077
  const deadline = now() + options.timeoutMs;
17802
18078
  while (now() <= deadline) {
@@ -17807,7 +18083,7 @@ async function waitForCommanderDaemon(options) {
17807
18083
  case "stopped":
17808
18084
  return { ok: false, reason: "stopped" };
17809
18085
  case "running": {
17810
- const log = readTextFile2(status.record.logFile);
18086
+ const log = readTextFile(status.record.logFile);
17811
18087
  if (log === undefined) {
17812
18088
  return { ok: false, reason: "timeout" };
17813
18089
  }
@@ -17815,7 +18091,7 @@ async function waitForCommanderDaemon(options) {
17815
18091
  return { ok: true, record: status.record };
17816
18092
  }
17817
18093
  await waitForFileChangeOrTimeout(status.record.logFile, deadline, now, () => {
17818
- const updatedLog = readTextFile2(status.record.logFile);
18094
+ const updatedLog = readTextFile(status.record.logFile);
17819
18095
  return updatedLog !== undefined && commanderLogIsConnected(updatedLog);
17820
18096
  });
17821
18097
  }
@@ -17941,7 +18217,7 @@ async function waitForFileChangeOrTimeout(path, deadline, now, ready2 = () => fa
17941
18217
  };
17942
18218
  const timer = setTimeout(finish, remaining);
17943
18219
  try {
17944
- watcher = watch2(path, finish);
18220
+ watcher = watch(path, finish);
17945
18221
  watcher.on("error", finish);
17946
18222
  if (ready2()) {
17947
18223
  finish();
@@ -17959,8 +18235,8 @@ async function waitForFileChangeOrTimeout(path, deadline, now, ready2 = () => fa
17959
18235
  // src/index.ts
17960
18236
  var flagDefinitions = new Map([
17961
18237
  ["version", { kind: "boolean" }],
18238
+ ["api-url", { kind: "value" }],
17962
18239
  ["linzumi-url", { kind: "value" }],
17963
- ["kandan-url", { kind: "value" }],
17964
18240
  ["token", { kind: "value" }],
17965
18241
  ["runner-id", { kind: "value" }],
17966
18242
  ["cwd", { kind: "value" }],
@@ -17970,12 +18246,12 @@ var flagDefinitions = new Map([
17970
18246
  ["workspace", { kind: "value" }],
17971
18247
  ["channel", { kind: "value" }],
17972
18248
  ["linzumi-thread-id", { kind: "value" }],
17973
- ["kandan-thread-id", { kind: "value" }],
17974
18249
  ["listen-user", { kind: "value" }],
17975
18250
  ["model", { kind: "value" }],
17976
18251
  ["reasoning-effort", { kind: "value" }],
17977
18252
  ["sandbox", { kind: "value" }],
17978
18253
  ["approval-policy", { kind: "value" }],
18254
+ ["allow-port-forwarding-by-default", { kind: "boolean" }],
17979
18255
  ["stream-flush-ms", { kind: "value" }],
17980
18256
  ["allowed-cwd", { kind: "value" }],
17981
18257
  ["forward-port", { kind: "value" }],
@@ -17989,10 +18265,6 @@ var flagDefinitions = new Map([
17989
18265
  ["oauth-callback-host", { kind: "value" }],
17990
18266
  ["help", { kind: "boolean" }]
17991
18267
  ]);
17992
- var flagAliases = new Map([
17993
- ["kandan-url", "linzumi-url"],
17994
- ["kandan-thread-id", "linzumi-thread-id"]
17995
- ]);
17996
18268
  var helloFlagDefinitions = new Map([
17997
18269
  ["dir", { kind: "value" }],
17998
18270
  ["parent-dir", { kind: "value" }],
@@ -18248,8 +18520,7 @@ function parsePathsCommandArgs(args) {
18248
18520
  case "--help":
18249
18521
  help = true;
18250
18522
  break;
18251
- case "--linzumi-url":
18252
- case "--kandan-url": {
18523
+ case "--api-url": {
18253
18524
  const value = args[index + 1];
18254
18525
  if (value === undefined || value.startsWith("--")) {
18255
18526
  throw new Error(`missing value for ${arg}`);
@@ -18360,7 +18631,7 @@ async function runAuthCommand(args) {
18360
18631
  process.stdout.write(helpText());
18361
18632
  return;
18362
18633
  }
18363
- const kandanUrl = required(values, "linzumi-url");
18634
+ const kandanUrl = requiredKandanUrl(values);
18364
18635
  const target = parseOptionalChannelTarget(values);
18365
18636
  const token = await acquireLocalRunnerTokenDetails({
18366
18637
  kandanUrl,
@@ -18391,7 +18662,7 @@ async function parseStartRunnerArgs(args, deps = {
18391
18662
  process.exit(0);
18392
18663
  }
18393
18664
  rejectStartTargetingFlags(values);
18394
- const kandanUrl = stringValue4(values, "linzumi-url") ?? defaultLinzumiWebSocketUrl;
18665
+ const kandanUrl = kandanUrlValue(values) ?? defaultLinzumiWebSocketUrl;
18395
18666
  const requestedCwd = resolveUserPath(cwdArg ?? process.cwd());
18396
18667
  const cwd = assertConfiguredAllowedCwds([requestedCwd])[0] ?? requestedCwd;
18397
18668
  const explicitAllowedCwds = values.has("allowed-cwd") ? assertConfiguredAllowedCwds(parseAllowedCwdList(stringValue4(values, "allowed-cwd"))) : [];
@@ -18475,6 +18746,7 @@ async function parseStartRunnerArgs(args, deps = {
18475
18746
  reasoningEffort: stringValue4(values, "reasoning-effort"),
18476
18747
  sandbox: stringValue4(values, "sandbox"),
18477
18748
  approvalPolicy: stringValue4(values, "approval-policy"),
18749
+ allowPortForwardingByDefault: booleanFlagValue(values, "allow-port-forwarding-by-default"),
18478
18750
  streamFlushMs: positiveIntegerValue2(values, "stream-flush-ms")
18479
18751
  }
18480
18752
  };
@@ -18507,9 +18779,10 @@ async function parseAgentRunnerArgs(args, deps = {
18507
18779
  reasoningEffort: stringValue4(values, "reasoning-effort"),
18508
18780
  sandbox: stringValue4(values, "sandbox"),
18509
18781
  approvalPolicy: stringValue4(values, "approval-policy"),
18782
+ allowPortForwardingByDefault: booleanFlagValue(values, "allow-port-forwarding-by-default"),
18510
18783
  streamFlushMs: positiveIntegerValue2(values, "stream-flush-ms")
18511
18784
  };
18512
- const kandanUrl = stringValue4(values, "linzumi-url") ?? agentApiUrlToKandanUrl(tokenFile.apiUrl);
18785
+ const kandanUrl = kandanUrlValue(values) ?? agentApiUrlToKandanUrl(tokenFile.apiUrl);
18513
18786
  const requestedCwdValue = cwdArg ?? stringValue4(values, "cwd");
18514
18787
  const requestedCwd = resolveUserPath(requestedCwdValue ?? process.cwd());
18515
18788
  const configuredAllowedCwds2 = requestedCwdValue === undefined && !values.has("allowed-cwd") ? readConfiguredAllowedCwdDetailsForLinzumiUrl(kandanUrl) : { allowedCwds: [], missingAllowedCwds: [] };
@@ -18641,7 +18914,7 @@ async function parseRunnerArgs(args, deps = {
18641
18914
  }
18642
18915
  rejectConnectChannelFlags(values);
18643
18916
  const workspaceSlug = stringValue4(values, "workspace");
18644
- const kandanUrl = stringValue4(values, "linzumi-url") ?? defaultLinzumiWebSocketUrl;
18917
+ const kandanUrl = kandanUrlValue(values) ?? defaultLinzumiWebSocketUrl;
18645
18918
  const cwd = stringValue4(values, "cwd") ?? process.cwd();
18646
18919
  const cwdAllowedCwds = assertConfiguredAllowedCwds([cwd]);
18647
18920
  const localConfiguredAllowedCwds = values.has("allowed-cwd") ? { allowedCwds: [], missingAllowedCwds: [] } : readConfiguredAllowedCwdDetailsForLinzumiUrl(kandanUrl);
@@ -18699,9 +18972,28 @@ function runnerRuntimeDefaultsFromValues(values) {
18699
18972
  model: stringValue4(values, "model"),
18700
18973
  reasoningEffort: stringValue4(values, "reasoning-effort"),
18701
18974
  approvalPolicy: stringValue4(values, "approval-policy"),
18702
- sandbox: stringValue4(values, "sandbox")
18975
+ sandbox: stringValue4(values, "sandbox"),
18976
+ allowPortForwardingByDefault: booleanFlagValue(values, "allow-port-forwarding-by-default")
18703
18977
  };
18704
18978
  }
18979
+ function kandanUrlValue(values) {
18980
+ const apiUrl = stringValue4(values, "api-url");
18981
+ const linzumiUrl = stringValue4(values, "linzumi-url");
18982
+ if (apiUrl !== undefined && linzumiUrl !== undefined && apiUrl !== linzumiUrl) {
18983
+ throw new Error("use only one of --api-url or --linzumi-url");
18984
+ }
18985
+ return apiUrl ?? linzumiUrl;
18986
+ }
18987
+ function requiredKandanUrl(values) {
18988
+ const value = kandanUrlValue(values);
18989
+ if (value === undefined) {
18990
+ throw new Error("missing required flag: --api-url or --linzumi-url");
18991
+ }
18992
+ return value;
18993
+ }
18994
+ function booleanFlagValue(values, key) {
18995
+ return values.get(key) === true ? true : undefined;
18996
+ }
18705
18997
  function strictFlagValues(args, definitions = flagDefinitions) {
18706
18998
  const values = new Map;
18707
18999
  for (let index = 0;index < args.length; index += 1) {
@@ -18714,16 +19006,15 @@ function strictFlagValues(args, definitions = flagDefinitions) {
18714
19006
  if (definition === undefined) {
18715
19007
  throw new Error(`invalid flag: --${rawKey}`);
18716
19008
  }
18717
- const key = flagAliases.get(rawKey) ?? rawKey;
18718
19009
  if (definition.kind === "boolean") {
18719
- values.set(key, true);
19010
+ values.set(rawKey, true);
18720
19011
  continue;
18721
19012
  }
18722
19013
  const next = args[index + 1];
18723
19014
  if (next === undefined || next.startsWith("--")) {
18724
19015
  throw new Error(`missing value for --${rawKey}`);
18725
19016
  }
18726
- values.set(key, next);
19017
+ values.set(rawKey, next);
18727
19018
  index += 1;
18728
19019
  }
18729
19020
  return values;
@@ -18905,11 +19196,11 @@ Usage:
18905
19196
  linzumi start <folder> [options]
18906
19197
  linzumi paths list|add|remove [path]
18907
19198
  linzumi connect --workspace <slug> [options]
18908
- linzumi auth --linzumi-url <ws-url> [--workspace <slug> --channel <slug>]
19199
+ linzumi auth --api-url <url> [--workspace <slug> --channel <slug>]
18909
19200
 
18910
19201
  Connection:
18911
- --linzumi-url <ws-url> Linzumi backend URL, default ${defaultLinzumiWebSocketUrl}
18912
- (deprecated alias: --kandan-url)
19202
+ --api-url <url> Linzumi API URL, default ${defaultLinzumiWebSocketUrl}
19203
+ --linzumi-url <url> Alias for --api-url
18913
19204
  --token <jwt> Optional override token. Otherwise ~/.linzumi/auth.json is validated or OAuth opens.
18914
19205
  --auth-file <path> Auth cache path, default ~/.linzumi/auth.json
18915
19206
  --oauth-callback-host <ip> Callback host reachable by your browser
@@ -18926,6 +19217,8 @@ Codex:
18926
19217
  --reasoning-effort <value> Reasoning effort requested for Codex and shown in Linzumi
18927
19218
  --sandbox <value> Sandbox metadata shown in Linzumi
18928
19219
  --approval-policy <value> Approval-policy metadata shown in Linzumi
19220
+ --allow-port-forwarding-by-default
19221
+ Auto-approve detected port-forward candidates for started sessions
18929
19222
  --stream-flush-ms <ms> Batch live Codex deltas before Linzumi persistence, default 150
18930
19223
  --fast Mark this runner as low-latency/fast in the availability message
18931
19224
  --log-file <path> JSONL event log path, default <cwd>/.linzumi-runner.log
@@ -19022,12 +19315,12 @@ function pathsHelpText() {
19022
19315
  return `Linzumi trusted paths
19023
19316
 
19024
19317
  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>
19318
+ linzumi paths [--api-url <url>] list
19319
+ linzumi paths [--api-url <url>] add <path>
19320
+ linzumi paths [--api-url <url>] remove <path>
19028
19321
 
19029
19322
  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
19323
+ use the root config fields; explicit --api-url paths use a URL-scoped config
19031
19324
  section so local, staging, and production runners do not share trust state.
19032
19325
  `;
19033
19326
  }
@@ -19044,8 +19337,7 @@ What it does:
19044
19337
  previews, and the browser VS Code editor.
19045
19338
 
19046
19339
  Options:
19047
- --linzumi-url <ws-url> Linzumi backend URL, default ${defaultLinzumiWebSocketUrl}
19048
- (deprecated alias: --kandan-url)
19340
+ --api-url <url> Linzumi API URL, default ${defaultLinzumiWebSocketUrl}
19049
19341
  --token <jwt> Optional scoped local-runner token override
19050
19342
  --auth-file <path> Auth cache path, default ~/.linzumi/auth.json
19051
19343
  --oauth-callback-host <ip> Callback host reachable by your browser
@@ -19085,8 +19377,7 @@ What it does:
19085
19377
 
19086
19378
  Options:
19087
19379
  --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)
19380
+ --api-url <url> Linzumi API URL. Defaults deterministically from the stored apiUrl.
19090
19381
  --runner-id <id> Stable Commander id
19091
19382
  --codex-bin <path> Codex executable, default codex
19092
19383
  --code-server-bin <path> Custom development code-server executable. By default Linzumi installs the approved editor runtime.
@@ -19102,7 +19393,7 @@ Options:
19102
19393
  Examples:
19103
19394
  linzumi paths add "$PWD"
19104
19395
  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
19396
+ linzumi commander ~/code/my-app --api-url http://127.0.0.1:4162 --runner-id local-qa-commander
19106
19397
  `;
19107
19398
  }
19108
19399
  function connectGuideText() {