@linzumi/cli 0.0.50-beta → 0.0.52-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,21 +4,35 @@ var __getProtoOf = Object.getPrototypeOf;
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ function __accessProp(key) {
8
+ return this[key];
9
+ }
10
+ var __toESMCache_node;
11
+ var __toESMCache_esm;
7
12
  var __toESM = (mod, isNodeMode, target) => {
13
+ var canCache = mod != null && typeof mod === "object";
14
+ if (canCache) {
15
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
16
+ var cached = cache.get(mod);
17
+ if (cached)
18
+ return cached;
19
+ }
8
20
  target = mod != null ? __create(__getProtoOf(mod)) : {};
9
21
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
22
  for (let key of __getOwnPropNames(mod))
11
23
  if (!__hasOwnProp.call(to, key))
12
24
  __defProp(to, key, {
13
- get: () => mod[key],
25
+ get: __accessProp.bind(mod, key),
14
26
  enumerable: true
15
27
  });
28
+ if (canCache)
29
+ cache.set(mod, to);
16
30
  return to;
17
31
  };
18
32
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
19
33
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
20
34
 
21
- // ../../node_modules/.bun/yoctocolors-cjs@2.1.3/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/.bun/cli-width@4.1.0/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/.bun/ansi-regex@5.0.1/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/.bun/strip-ansi@6.0.1/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/.bun/is-fullwidth-code-point@3.0.0/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/.bun/emoji-regex@8.0.0/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/.bun/string-width@4.2.3/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/.bun/color-name@1.1.4/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/.bun/color-convert@2.0.1/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/.bun/color-convert@2.0.1/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/.bun/color-convert@2.0.1/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/.bun/ansi-styles@4.3.0/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/.bun/wrap-ansi@6.2.0/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/.bun/mute-stream@2.0.0/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.50-beta";
10459
+ var linzumiCliVersion = "0.0.52-beta";
10156
10460
  var linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
10157
10461
 
10158
10462
  // src/runnerLock.ts
@@ -10761,6 +11065,25 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
10761
11065
  }
10762
11066
  revokeEditorForwardPort(review.revoked.port, review.reason);
10763
11067
  break;
11068
+ case "replace_pending":
11069
+ localEditorForwardState.pendingRequests.delete(review.expired.port);
11070
+ pushEditorPortForwardEvent("forward_port_resolved", {
11071
+ instanceId,
11072
+ requestId: review.expired.requestId,
11073
+ source: "local_editor",
11074
+ port: review.expired.port,
11075
+ pid: review.expired.pid,
11076
+ command: review.expired.command,
11077
+ ...review.expired.cwd === undefined ? {} : { cwd: review.expired.cwd },
11078
+ decision: "expired",
11079
+ reason: review.reason,
11080
+ capabilities: capabilitiesPayload()
11081
+ });
11082
+ if (localEditorForwardState.pendingRequests.size > 0) {
11083
+ localEditorForwardState.queuedCandidates.set(review.candidate.port, review.candidate);
11084
+ return;
11085
+ }
11086
+ break;
10764
11087
  case "prompt":
10765
11088
  if (localEditorForwardState.pendingRequests.size > 0) {
10766
11089
  localEditorForwardState.queuedCandidates.set(candidate.port, candidate);
@@ -10917,7 +11240,12 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
10917
11240
  const codex = await connectCodexAppServer(codexUrl);
10918
11241
  cleanup.actions.push(() => codex.close());
10919
11242
  const seq = { value: 0 };
10920
- const codexThreads = options.channelSession === undefined ? await discoverCodexThreads(codex, options.cwd) : [];
11243
+ const codexThreads = options.channelSession === undefined ? await discoverCodexThreads(codex, options.cwd).catch((error) => {
11244
+ log("kandan.codex_threads_startup_discovery_failed", {
11245
+ message: error instanceof Error ? error.message : String(error)
11246
+ });
11247
+ return [];
11248
+ }) : [];
10921
11249
  const discoveredCodexThreads = { value: codexThreads };
10922
11250
  const runtimeDefaults = runnerRuntimeDefaults(options);
10923
11251
  const instancePayload = {
@@ -10932,6 +11260,7 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
10932
11260
  channel: options.channelSession?.channelSlug ?? null,
10933
11261
  model: runtimeDefaults.model ?? null,
10934
11262
  reasoningEffort: runtimeDefaults.reasoningEffort ?? null,
11263
+ allowPortForwardingByDefault: runtimeDefaults.allowPortForwardingByDefault ?? null,
10935
11264
  fast: options.fast ?? false
10936
11265
  };
10937
11266
  await kandan.push(topic, "instance_started", instancePayload);
@@ -11039,7 +11368,8 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
11039
11368
  model: runtimeSettings.model,
11040
11369
  reasoningEffort: runtimeSettings.reasoningEffort,
11041
11370
  sandbox: runtimeSettings.sandbox,
11042
- approvalPolicy: runtimeSettings.approvalPolicy
11371
+ approvalPolicy: runtimeSettings.approvalPolicy,
11372
+ allowPortForwardingByDefault: runtimeSettings.allowPortForwardingByDefault
11043
11373
  }
11044
11374
  },
11045
11375
  log
@@ -11060,6 +11390,7 @@ async function openLocalCodexRunner(options, log, cleanup, close) {
11060
11390
  codexThreads: discoveredCodexThreads.value,
11061
11391
  model: runtimeDefaults.model ?? null,
11062
11392
  reasoningEffort: runtimeDefaults.reasoningEffort ?? null,
11393
+ allowPortForwardingByDefault: runtimeDefaults.allowPortForwardingByDefault ?? null,
11063
11394
  fast: options.fast ?? false,
11064
11395
  capabilities: capabilitiesPayload()
11065
11396
  });
@@ -11350,23 +11681,95 @@ async function closeCleanupStack(cleanup) {
11350
11681
  })();
11351
11682
  return cleanup.closePromise;
11352
11683
  }
11353
- async function discoverCodexThreads(codex, cwd) {
11354
- const response = await codex.request("thread/list", { cwd });
11355
- if ("error" in response) {
11356
- return [];
11684
+ async function discoverCodexThreads(codex, _cwd) {
11685
+ const rowsById = new Map;
11686
+ const archivedModes = [false, true];
11687
+ const sourcePasses = [
11688
+ undefined,
11689
+ [
11690
+ "exec",
11691
+ "appServer",
11692
+ "subAgent",
11693
+ "subAgentReview",
11694
+ "subAgentCompact",
11695
+ "subAgentThreadSpawn",
11696
+ "subAgentOther",
11697
+ "unknown"
11698
+ ]
11699
+ ];
11700
+ for (const archived of archivedModes) {
11701
+ for (const sourceKinds of sourcePasses) {
11702
+ let cursor;
11703
+ while (true) {
11704
+ const response = await codex.request("thread/list", {
11705
+ limit: 50,
11706
+ sortKey: "updated_at",
11707
+ sortDirection: "desc",
11708
+ archived,
11709
+ useStateDbOnly: true,
11710
+ ...cursor === undefined ? {} : { cursor },
11711
+ ...sourceKinds === undefined ? {} : { sourceKinds }
11712
+ });
11713
+ if ("error" in response) {
11714
+ throw new Error(`thread/list failed: ${response.error.message}`);
11715
+ }
11716
+ const result = objectValue(response.result);
11717
+ const data = arrayValue(result?.data)?.filter(isJsonObject) ?? [];
11718
+ for (const thread of data) {
11719
+ const row = codexThreadHistoryRow(thread, archived);
11720
+ const id = stringValue(objectValue(row)?.id);
11721
+ if (id !== undefined && id !== "" && !rowsById.has(id)) {
11722
+ rowsById.set(id, row);
11723
+ }
11724
+ }
11725
+ const nextCursor = stringValue(result?.nextCursor);
11726
+ if (nextCursor === undefined || nextCursor === "" || data.length === 0) {
11727
+ break;
11728
+ }
11729
+ cursor = nextCursor;
11730
+ }
11731
+ }
11357
11732
  }
11358
- const result = objectValue(response.result);
11359
- const data = arrayValue(result?.data);
11360
- return data === undefined ? [] : data.filter(isJsonObject).map((thread) => ({
11733
+ return Array.from(rowsById.values()).sort(compareCodexThreadHistoryRows);
11734
+ }
11735
+ function codexThreadHistoryRow(thread, archived) {
11736
+ const gitInfo = objectValue(thread.gitInfo);
11737
+ const preview = stringValue(thread.preview) ?? "";
11738
+ const name = stringValue(thread.name) ?? "";
11739
+ const title = stringValue(thread.title) ?? (name === "" ? preview : name);
11740
+ const description = stringValue(thread.description) ?? stringValue(thread.summary) ?? preview;
11741
+ return {
11361
11742
  id: stringValue(thread.id) ?? "",
11362
- title: stringValue(thread.title) ?? stringValue(thread.name) ?? stringValue(thread.preview) ?? "",
11363
- description: stringValue(thread.description) ?? stringValue(thread.summary) ?? stringValue(thread.preview) ?? "",
11364
- preview: stringValue(thread.preview) ?? "",
11743
+ title: title ?? "",
11744
+ description: description ?? "",
11745
+ preview: preview.replace(/\s+/g, " ").trim(),
11365
11746
  cwd: stringValue(thread.cwd) ?? "",
11366
11747
  source: stringValue(thread.source) ?? "",
11367
- updatedAt: integerValue(thread.updatedAt) ?? null,
11368
- status: objectValue(thread.status) ?? null
11369
- })).filter((thread) => thread.id !== "");
11748
+ createdAt: codexTimestamp(thread.createdAt),
11749
+ updatedAt: codexTimestamp(thread.updatedAt),
11750
+ archived,
11751
+ modelProvider: stringValue(thread.modelProvider) ?? "",
11752
+ cliVersion: stringValue(thread.cliVersion) ?? "",
11753
+ gitBranch: stringValue(gitInfo?.branch) ?? "",
11754
+ gitOriginUrl: stringValue(gitInfo?.originUrl) ?? "",
11755
+ path: stringValue(thread.path) ?? ""
11756
+ };
11757
+ }
11758
+ function codexTimestamp(value) {
11759
+ if (typeof value === "number" && Number.isFinite(value)) {
11760
+ return new Date(value * 1000).toISOString();
11761
+ }
11762
+ return stringValue(value) ?? "";
11763
+ }
11764
+ function compareCodexThreadHistoryRows(left, right) {
11765
+ const leftRow = objectValue(left);
11766
+ const rightRow = objectValue(right);
11767
+ const leftTime = Date.parse(stringValue(leftRow?.createdAt) ?? stringValue(leftRow?.updatedAt) ?? "");
11768
+ const rightTime = Date.parse(stringValue(rightRow?.createdAt) ?? stringValue(rightRow?.updatedAt) ?? "");
11769
+ return safeComparableTime(leftTime) - safeComparableTime(rightTime);
11770
+ }
11771
+ function safeComparableTime(value) {
11772
+ return Number.isFinite(value) ? value : Number.MAX_SAFE_INTEGER;
11370
11773
  }
11371
11774
  function extractStartedThreadId(response) {
11372
11775
  if ("error" in response) {
@@ -11747,6 +12150,22 @@ ${args.developerPrompt}
11747
12150
  `;
11748
12151
  const linzumiContext = args.linzumiContext === undefined ? "" : `
11749
12152
  ${formatLinzumiConversationContextForPrompt(args.linzumiContext)}
12153
+ `;
12154
+ const reviewGuidance = `
12155
+ <linzumi_pr_review_guidance>
12156
+ For frontend or other user-visible changes, ask whether the user wants
12157
+ screenshot or screen-recording proof, ideally before/after when that helps
12158
+ review the change. Screen recordings should be WebM or MP4. When the user asks
12159
+ you to open or update a PR, attach or link that proof in the PR when feasible,
12160
+ and state the exact blocker when it is not feasible.
12161
+ </linzumi_pr_review_guidance>
12162
+
12163
+ <linzumi_user_visible_writing_guide>
12164
+ When you write user-visible UI, status, error, or PR-review copy, keep it short,
12165
+ direct, and focused on the user's outcome. Avoid implementation-heavy sentences,
12166
+ stacked clauses, and internal mechanics unless the user explicitly needs that
12167
+ detail.
12168
+ </linzumi_user_visible_writing_guide>
11750
12169
  `;
11751
12170
  return `<context>
11752
12171
  You are a Linzumi Codex session launched by the Linzumi Commander.
@@ -11784,6 +12203,10 @@ You MUST NOT ask the Bootstrapper Codex to do implementation work.
11784
12203
  You MUST NOT inspect unrelated repositories or folders.
11785
12204
  You MUST report the exact blocker if a command, preview, editor, or tunnel step
11786
12205
  fails.
12206
+ When several Linzumi Codex sessions work in the same repository, create or use
12207
+ a separate checkout or git worktree for this task before making changes, unless
12208
+ the human explicitly asks you to share the current checkout. Do not overwrite or
12209
+ revert another session's work.
11787
12210
  </rules>
11788
12211
 
11789
12212
  <examples>
@@ -11791,6 +12214,7 @@ GOOD preview command: npm run dev -- --host 0.0.0.0 --port 8787
11791
12214
  BAD preview command: npm run dev -- --host 127.0.0.1
11792
12215
  </examples>
11793
12216
  ${linzumiContext}
12217
+ ${reviewGuidance}
11794
12218
  ${customPrompt}
11795
12219
  <task_reminder>
11796
12220
  You are the Commander-launched Linzumi Codex session. Do the implementation
@@ -11874,7 +12298,8 @@ function startInstanceRuntimeSettings(options, control) {
11874
12298
  reasoningEffort: control.reasoningEffort ?? defaults.reasoningEffort,
11875
12299
  approvalPolicy: codexApprovalPolicyForRequest(control.approvalPolicy ?? defaults.approvalPolicy, sandbox),
11876
12300
  sandbox,
11877
- fast: control.fast ?? options.fast
12301
+ fast: control.fast ?? options.fast,
12302
+ allowPortForwardingByDefault: control.allowPortForwardingByDefault ?? defaults.allowPortForwardingByDefault
11878
12303
  };
11879
12304
  }
11880
12305
  async function startOwnedCodexAppServer(options) {
@@ -11897,7 +12322,8 @@ function runnerRuntimeDefaults(options) {
11897
12322
  model: defaults?.model ?? session?.model,
11898
12323
  reasoningEffort: defaults?.reasoningEffort ?? session?.reasoningEffort,
11899
12324
  approvalPolicy: codexApprovalPolicySetting(defaults?.approvalPolicy ?? session?.approvalPolicy, sandbox),
11900
- sandbox
12325
+ sandbox,
12326
+ allowPortForwardingByDefault: defaults?.allowPortForwardingByDefault ?? session?.allowPortForwardingByDefault
11901
12327
  };
11902
12328
  }
11903
12329
  function isUpdateRunnerConfigControl(control) {
@@ -13378,7 +13804,7 @@ To kick the agent off:
13378
13804
  3. Paste into the thread. Codex will pick it up and start editing this folder.
13379
13805
  `;
13380
13806
 
13381
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/key.js
13807
+ // node_modules/@inquirer/core/dist/esm/lib/key.js
13382
13808
  var isUpKey = (key, keybindings = []) => key.name === "up" || keybindings.includes("vim") && key.name === "k" || keybindings.includes("emacs") && key.ctrl && key.name === "p";
13383
13809
  var isDownKey = (key, keybindings = []) => key.name === "down" || keybindings.includes("vim") && key.name === "j" || keybindings.includes("emacs") && key.ctrl && key.name === "n";
13384
13810
  var isSpaceKey = (key) => key.name === "space";
@@ -13386,7 +13812,7 @@ var isBackspaceKey = (key) => key.name === "backspace";
13386
13812
  var isTabKey = (key) => key.name === "tab";
13387
13813
  var isNumberKey = (key) => "1234567890".includes(key.name);
13388
13814
  var isEnterKey = (key) => key.name === "enter" || key.name === "return";
13389
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/errors.js
13815
+ // node_modules/@inquirer/core/dist/esm/lib/errors.js
13390
13816
  class AbortPromptError extends Error {
13391
13817
  name = "AbortPromptError";
13392
13818
  message = "Prompt was aborted";
@@ -13412,10 +13838,10 @@ class HookError extends Error {
13412
13838
  class ValidationError extends Error {
13413
13839
  name = "ValidationError";
13414
13840
  }
13415
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/use-state.js
13841
+ // node_modules/@inquirer/core/dist/esm/lib/use-state.js
13416
13842
  import { AsyncResource as AsyncResource2 } from "node:async_hooks";
13417
13843
 
13418
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/hook-engine.js
13844
+ // node_modules/@inquirer/core/dist/esm/lib/hook-engine.js
13419
13845
  import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
13420
13846
  var hookStorage = new AsyncLocalStorage;
13421
13847
  function createStore(rl) {
@@ -13520,7 +13946,7 @@ var effectScheduler = {
13520
13946
  }
13521
13947
  };
13522
13948
 
13523
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/use-state.js
13949
+ // node_modules/@inquirer/core/dist/esm/lib/use-state.js
13524
13950
  function useState(defaultValue) {
13525
13951
  return withPointer((pointer) => {
13526
13952
  const setState = AsyncResource2.bind(function setState2(newValue) {
@@ -13538,7 +13964,7 @@ function useState(defaultValue) {
13538
13964
  });
13539
13965
  }
13540
13966
 
13541
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/use-effect.js
13967
+ // node_modules/@inquirer/core/dist/esm/lib/use-effect.js
13542
13968
  function useEffect(cb, depArray) {
13543
13969
  withPointer((pointer) => {
13544
13970
  const oldDeps = pointer.get();
@@ -13550,10 +13976,10 @@ function useEffect(cb, depArray) {
13550
13976
  });
13551
13977
  }
13552
13978
 
13553
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/theme.js
13979
+ // node_modules/@inquirer/core/dist/esm/lib/theme.js
13554
13980
  var import_yoctocolors_cjs = __toESM(require_yoctocolors_cjs(), 1);
13555
13981
 
13556
- // ../../node_modules/.bun/@inquirer+figures@1.0.15/node_modules/@inquirer/figures/dist/esm/index.js
13982
+ // node_modules/@inquirer/figures/dist/esm/index.js
13557
13983
  import process2 from "node:process";
13558
13984
  function isUnicodeSupported() {
13559
13985
  if (process2.platform !== "win32") {
@@ -13842,7 +14268,7 @@ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
13842
14268
  var esm_default = figures;
13843
14269
  var replacements = Object.entries(specialMainSymbols);
13844
14270
 
13845
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/theme.js
14271
+ // node_modules/@inquirer/core/dist/esm/lib/theme.js
13846
14272
  var defaultTheme = {
13847
14273
  prefix: {
13848
14274
  idle: import_yoctocolors_cjs.default.blue("?"),
@@ -13863,7 +14289,7 @@ var defaultTheme = {
13863
14289
  }
13864
14290
  };
13865
14291
 
13866
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/make-theme.js
14292
+ // node_modules/@inquirer/core/dist/esm/lib/make-theme.js
13867
14293
  function isPlainObject(value) {
13868
14294
  if (typeof value !== "object" || value === null)
13869
14295
  return false;
@@ -13891,7 +14317,7 @@ function makeTheme(...themes) {
13891
14317
  return deepMerge(...themesToMerge);
13892
14318
  }
13893
14319
 
13894
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/use-prefix.js
14320
+ // node_modules/@inquirer/core/dist/esm/lib/use-prefix.js
13895
14321
  function usePrefix({ status = "idle", theme }) {
13896
14322
  const [showLoader, setShowLoader] = useState(false);
13897
14323
  const [tick, setTick] = useState(0);
@@ -13921,7 +14347,7 @@ function usePrefix({ status = "idle", theme }) {
13921
14347
  const iconName = status === "loading" ? "idle" : status;
13922
14348
  return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
13923
14349
  }
13924
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/use-memo.js
14350
+ // node_modules/@inquirer/core/dist/esm/lib/use-memo.js
13925
14351
  function useMemo(fn, dependencies) {
13926
14352
  return withPointer((pointer) => {
13927
14353
  const prev = pointer.get();
@@ -13933,11 +14359,11 @@ function useMemo(fn, dependencies) {
13933
14359
  return prev.value;
13934
14360
  });
13935
14361
  }
13936
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/use-ref.js
14362
+ // node_modules/@inquirer/core/dist/esm/lib/use-ref.js
13937
14363
  function useRef(val) {
13938
14364
  return useState({ current: val })[0];
13939
14365
  }
13940
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/use-keypress.js
14366
+ // node_modules/@inquirer/core/dist/esm/lib/use-keypress.js
13941
14367
  function useKeypress(userHandler) {
13942
14368
  const signal = useRef(userHandler);
13943
14369
  signal.current = userHandler;
@@ -13955,7 +14381,7 @@ function useKeypress(userHandler) {
13955
14381
  };
13956
14382
  }, []);
13957
14383
  }
13958
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/utils.js
14384
+ // node_modules/@inquirer/core/dist/esm/lib/utils.js
13959
14385
  var import_cli_width = __toESM(require_cli_width(), 1);
13960
14386
  var import_wrap_ansi = __toESM(require_wrap_ansi(), 1);
13961
14387
  function breakLines(content, width) {
@@ -13968,7 +14394,7 @@ function readlineWidth() {
13968
14394
  return import_cli_width.default({ defaultWidth: 80, output: readline().output });
13969
14395
  }
13970
14396
 
13971
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/pagination/use-pagination.js
14397
+ // node_modules/@inquirer/core/dist/esm/lib/pagination/use-pagination.js
13972
14398
  function usePointerPosition({ active, renderedItems, pageSize, loop }) {
13973
14399
  const state = useRef({
13974
14400
  lastPointer: active,
@@ -14034,12 +14460,12 @@ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
14034
14460
  return pageBuffer.filter((line) => typeof line === "string").join(`
14035
14461
  `);
14036
14462
  }
14037
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14463
+ // node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14038
14464
  var import_mute_stream = __toESM(require_lib(), 1);
14039
14465
  import * as readline2 from "node:readline";
14040
14466
  import { AsyncResource as AsyncResource3 } from "node:async_hooks";
14041
14467
 
14042
- // ../../node_modules/.bun/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js
14468
+ // node_modules/signal-exit/dist/mjs/signals.js
14043
14469
  var signals = [];
14044
14470
  signals.push("SIGHUP", "SIGINT", "SIGTERM");
14045
14471
  if (process.platform !== "win32") {
@@ -14049,7 +14475,7 @@ if (process.platform === "linux") {
14049
14475
  signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
14050
14476
  }
14051
14477
 
14052
- // ../../node_modules/.bun/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js
14478
+ // node_modules/signal-exit/dist/mjs/index.js
14053
14479
  var processOk = (process3) => !!process3 && typeof process3 === "object" && typeof process3.removeListener === "function" && typeof process3.emit === "function" && typeof process3.reallyExit === "function" && typeof process3.listeners === "function" && typeof process3.kill === "function" && typeof process3.pid === "number" && typeof process3.on === "function";
14054
14480
  var kExitEmitter = Symbol.for("signal-exit emitter");
14055
14481
  var global = globalThis;
@@ -14247,10 +14673,10 @@ var {
14247
14673
  unload
14248
14674
  } = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback);
14249
14675
 
14250
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14676
+ // node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14251
14677
  import { stripVTControlCharacters } from "node:util";
14252
14678
 
14253
- // ../../node_modules/.bun/@inquirer+ansi@1.0.2/node_modules/@inquirer/ansi/dist/esm/index.js
14679
+ // node_modules/@inquirer/ansi/dist/esm/index.js
14254
14680
  var ESC = "\x1B[";
14255
14681
  var cursorLeft = ESC + "G";
14256
14682
  var cursorHide = ESC + "?25l";
@@ -14266,7 +14692,7 @@ var cursorTo = (x, y) => {
14266
14692
  var eraseLine = ESC + "2K";
14267
14693
  var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
14268
14694
 
14269
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14695
+ // node_modules/@inquirer/core/dist/esm/lib/screen-manager.js
14270
14696
  var height = (content) => content.split(`
14271
14697
  `).length;
14272
14698
  var lastLine = (content) => content.split(`
@@ -14331,7 +14757,7 @@ class ScreenManager {
14331
14757
  }
14332
14758
  }
14333
14759
 
14334
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/promise-polyfill.js
14760
+ // node_modules/@inquirer/core/dist/esm/lib/promise-polyfill.js
14335
14761
  class PromisePolyfill extends Promise {
14336
14762
  static withResolver() {
14337
14763
  let resolve8;
@@ -14344,7 +14770,7 @@ class PromisePolyfill extends Promise {
14344
14770
  }
14345
14771
  }
14346
14772
 
14347
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14773
+ // node_modules/@inquirer/core/dist/esm/lib/create-prompt.js
14348
14774
  function getCallSites() {
14349
14775
  const _prepareStackTrace = Error.prepareStackTrace;
14350
14776
  let result = [];
@@ -14430,7 +14856,7 @@ function createPrompt(view) {
14430
14856
  };
14431
14857
  return prompt;
14432
14858
  }
14433
- // ../../node_modules/.bun/@inquirer+core@10.3.2/node_modules/@inquirer/core/dist/esm/lib/Separator.js
14859
+ // node_modules/@inquirer/core/dist/esm/lib/Separator.js
14434
14860
  var import_yoctocolors_cjs2 = __toESM(require_yoctocolors_cjs(), 1);
14435
14861
  class Separator {
14436
14862
  separator = import_yoctocolors_cjs2.default.dim(Array.from({ length: 15 }).join(esm_default.line));
@@ -14444,7 +14870,7 @@ class Separator {
14444
14870
  return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
14445
14871
  }
14446
14872
  }
14447
- // ../../node_modules/.bun/@inquirer+checkbox@4.3.2/node_modules/@inquirer/checkbox/dist/esm/index.js
14873
+ // node_modules/@inquirer/checkbox/dist/esm/index.js
14448
14874
  var import_yoctocolors_cjs3 = __toESM(require_yoctocolors_cjs(), 1);
14449
14875
  var checkboxTheme = {
14450
14876
  icon: {
@@ -14631,7 +15057,7 @@ var esm_default2 = createPrompt((config, done) => {
14631
15057
  `).trimEnd();
14632
15058
  return `${lines}${cursorHide}`;
14633
15059
  });
14634
- // ../../node_modules/.bun/@inquirer+input@4.3.1/node_modules/@inquirer/input/dist/esm/index.js
15060
+ // node_modules/@inquirer/input/dist/esm/index.js
14635
15061
  var inputTheme = {
14636
15062
  validationFailureMode: "keep"
14637
15063
  };
@@ -14715,7 +15141,7 @@ var esm_default3 = createPrompt((config, done) => {
14715
15141
  error
14716
15142
  ];
14717
15143
  });
14718
- // ../../node_modules/.bun/@inquirer+select@4.4.2/node_modules/@inquirer/select/dist/esm/index.js
15144
+ // node_modules/@inquirer/select/dist/esm/index.js
14719
15145
  var import_yoctocolors_cjs4 = __toESM(require_yoctocolors_cjs(), 1);
14720
15146
  var selectTheme = {
14721
15147
  icon: { cursor: esm_default.pointer },
@@ -14884,24 +15310,17 @@ import { spawn as spawn7 } from "node:child_process";
14884
15310
  import {
14885
15311
  existsSync as existsSync10,
14886
15312
  constants as fsConstants,
14887
- mkdirSync as mkdirSync10,
14888
15313
  mkdtempSync as mkdtempSync3,
14889
15314
  readFileSync as readFileSync10,
14890
15315
  readdirSync,
14891
15316
  rmSync as rmSync3,
14892
15317
  statSync,
14893
- watch,
14894
15318
  writeFileSync as writeFileSync8
14895
15319
  } from "node:fs";
14896
15320
  import { access } from "node:fs/promises";
14897
15321
  import { homedir as homedir8, tmpdir as tmpdir2 } from "node:os";
14898
- import { delimiter as delimiter2, dirname as dirname9, join as join12, resolve as resolve8 } from "node:path";
14899
- import {
14900
- argv as processArgv,
14901
- execPath as processExecPath,
14902
- stdin as defaultStdin,
14903
- stdout as defaultStdout
14904
- } from "node:process";
15322
+ import { delimiter as delimiter2, join as join12, resolve as resolve8 } from "node:path";
15323
+ import { stdin as defaultStdin, stdout as defaultStdout } from "node:process";
14905
15324
  import { emitKeypressEvents } from "node:readline";
14906
15325
 
14907
15326
  // src/signupServerClient.ts
@@ -14916,7 +15335,8 @@ function createSignupServerClient(args) {
14916
15335
  method: "POST",
14917
15336
  body: {
14918
15337
  email: request.email,
14919
- mode: request.mode
15338
+ mode: request.mode,
15339
+ selected_tasks: request.selectedTasks ?? []
14920
15340
  },
14921
15341
  render: renderEmailCodeStart
14922
15342
  }),
@@ -15186,11 +15606,6 @@ function booleanValue(record, key) {
15186
15606
  }
15187
15607
 
15188
15608
  // src/signupFlow.ts
15189
- var commanderConnectedMarkers = [
15190
- "Connected to Linzumi",
15191
- "Runner connected:",
15192
- '"event":"runner.instance_started"'
15193
- ];
15194
15609
  var blue = (value) => `\x1B[38;5;75m${value}\x1B[0m`;
15195
15610
  var green = (value) => `\x1B[38;5;114m${value}\x1B[0m`;
15196
15611
  var red = (value) => `\x1B[38;5;203m${value}\x1B[0m`;
@@ -15429,7 +15844,8 @@ async function runSignupFlow(deps = {}) {
15429
15844
  state = updateSignupState(state, { currentStep: "code", email });
15430
15845
  const codeRequest = signupServerClient === undefined ? { type: "sent", request: { pendingId: "mock", email } } : await startEmailCodeForSignup(signupServerClient, {
15431
15846
  email,
15432
- mode: "existing_or_create"
15847
+ mode: "existing_or_create",
15848
+ selectedTasks: selectedTaskTitlesFromState(state)
15433
15849
  });
15434
15850
  if (codeRequest.type === "failed") {
15435
15851
  state = updateSignupState(state, {
@@ -15497,6 +15913,8 @@ async function runSignupFlow(deps = {}) {
15497
15913
  rootSeq: thread.rootSeq,
15498
15914
  threadSeq: thread.threadSeq
15499
15915
  }));
15916
+ const starterProjectPath = missionControl.config.starterProjectPath ?? starterProject.path;
15917
+ const verifiedCodexBin = verifiedCodexBinFromPreflightChecks(state.preflightChecks);
15500
15918
  const storedSignupAuth = writeSignupCompletion({
15501
15919
  email: verifiedAuth.user.primaryEmail ?? state.email ?? verifiedAuth.user.username,
15502
15920
  serviceUrl,
@@ -15508,20 +15926,24 @@ async function runSignupFlow(deps = {}) {
15508
15926
  launchUrl: missionControl.launchUrl,
15509
15927
  allowedCwds: missionControl.config.allowedCwds
15510
15928
  });
15511
- const commanderLaunch = await launchSignupCommanderForCompletedSignup(commanderLauncher, {
15929
+ const commanderLaunch = verifiedCodexBin === undefined ? failedSignupCommanderLaunchForMissingCodex({
15930
+ serviceUrl,
15931
+ workspaceSlug: missionControl.workspace.slug,
15932
+ projectPath: starterProjectPath
15933
+ }) : await launchSignupCommanderForCompletedSignup(commanderLauncher, {
15512
15934
  serviceUrl,
15513
15935
  localRunnerAccessToken: missionControl.localRunnerToken.accessToken,
15514
15936
  localRunnerExpiresInSeconds: missionControl.localRunnerToken.expiresInSeconds,
15515
15937
  workspaceSlug: missionControl.workspace.slug,
15516
- officeChannelSlug: missionControl.channels.office.slug,
15517
- projectPath: missionControl.config.starterProjectPath ?? starterProject.path,
15518
- selectedProjectPaths: missionControl.config.allowedCwds
15938
+ projectPath: starterProjectPath,
15939
+ selectedProjectPaths: missionControl.config.allowedCwds,
15940
+ codexBin: verifiedCodexBin
15519
15941
  });
15520
15942
  const starterTaskLaunches = await startSignupTasksForCommander(signupServerClient, {
15521
15943
  accessToken: verifiedAuth.accessToken,
15522
15944
  missionControl,
15523
15945
  commanderLaunch,
15524
- starterProjectPath: missionControl.config.starterProjectPath ?? starterProject.path,
15946
+ starterProjectPath,
15525
15947
  threads: starterTaskThreads
15526
15948
  });
15527
15949
  state = updateSignupState(state, {
@@ -15839,7 +16261,7 @@ function signupProgressRows(state) {
15839
16261
  checked: selectedTaskTitlesFromState(state).length > 0
15840
16262
  },
15841
16263
  {
15842
- label: "We'll launch you into Mission Control with your work already running",
16264
+ label: "Mission Control will open with your work already running",
15843
16265
  checked: state.currentStep === "launch"
15844
16266
  }
15845
16267
  ];
@@ -15978,7 +16400,7 @@ function writeLaunchSummary(output, state) {
15978
16400
  writeBoundedLine(output, blue(" npx -y @linzumi/cli@latest signup"));
15979
16401
  return;
15980
16402
  }
15981
- writeBoundedLine(output, blue("7) We'll launch you into Mission Control with your work already running"));
16403
+ writeBoundedLine(output, blue("7) Mission Control will open with your work already running"));
15982
16404
  const taskCount = selectedTaskTitlesFromState(state).length;
15983
16405
  writeBoundedLine(output, muted(` Starting ${taskCount} ${taskCount === 1 ? "task" : "tasks"} and saying hello to the Linzumi team...`));
15984
16406
  state.starterTaskLaunches.forEach((launch) => {
@@ -16000,7 +16422,7 @@ function writeLaunchSummary(output, state) {
16000
16422
  writeBoundedLine(output, `${green("✓")} Local Commander connected this computer to Mission Control (${state.commanderLaunch.runnerId})`);
16001
16423
  break;
16002
16424
  case "failed":
16003
- writeStatusMessage(output, red("x"), `Local Commander could not start automatically: ${state.commanderLaunch.error}`);
16425
+ writeStatusMessage(output, red("x"), `Local Commander could not connect: ${state.commanderLaunch.error}`);
16004
16426
  break;
16005
16427
  }
16006
16428
  }
@@ -16042,40 +16464,17 @@ async function defaultSignupCommanderLauncher(args) {
16042
16464
  accessToken: args.localRunnerAccessToken,
16043
16465
  expiresInSeconds: args.localRunnerExpiresInSeconds
16044
16466
  });
16045
- const scriptPath = processArgv[1];
16046
16467
  const runnerId = signupCommanderRunnerId(args.workspaceSlug);
16047
16468
  const restartCommand = signupConnectRestartCommand(args);
16048
- if (scriptPath === undefined || scriptPath.trim() === "") {
16049
- return {
16050
- status: "failed",
16051
- runnerId,
16052
- restartCommand,
16053
- error: "current CLI entrypoint could not be resolved"
16054
- };
16055
- }
16056
- const logFile = signupCommanderLaunchLogFile(runnerId);
16057
16469
  try {
16058
- mkdirSync10(dirname9(logFile), { recursive: true });
16059
- const child = spawn7(processExecPath, signupCommanderConnectSpawnArgs(args, runnerId, logFile, scriptPath), {
16060
- detached: true,
16061
- stdio: "ignore"
16062
- });
16063
- child.unref();
16064
- const connected = await waitForSignupCommanderConnection(logFile, 30000);
16065
- if (!connected) {
16066
- return {
16067
- status: "failed",
16068
- runnerId,
16069
- restartCommand,
16070
- error: `Local Commander did not connect within 30 seconds. Check ${logFile}`
16071
- };
16072
- }
16470
+ const handle = await runLocalCodexRunner(await signupCommanderRunnerOptions(args, runnerId));
16073
16471
  return {
16074
16472
  status: "started",
16075
16473
  runnerId,
16076
16474
  restartCommand,
16077
- logFile,
16078
- ...child.pid === undefined ? {} : { pid: child.pid }
16475
+ pid: process.pid,
16476
+ instanceId: handle.instanceId,
16477
+ codexUrl: handle.codexUrl
16079
16478
  };
16080
16479
  } catch (error) {
16081
16480
  return {
@@ -16086,69 +16485,56 @@ async function defaultSignupCommanderLauncher(args) {
16086
16485
  };
16087
16486
  }
16088
16487
  }
16089
- async function waitForSignupCommanderConnection(logFile, timeoutMs) {
16090
- const deadline = Date.now() + timeoutMs;
16091
- while (Date.now() <= deadline) {
16092
- const log = readTextFile(logFile);
16093
- if (log !== undefined && signupCommanderLogIsConnected(log)) {
16094
- return true;
16095
- }
16096
- await waitForSignupCommanderLogChange(logFile, deadline, () => {
16097
- const updatedLog = readTextFile(logFile);
16098
- return updatedLog !== undefined && signupCommanderLogIsConnected(updatedLog);
16099
- });
16100
- }
16101
- return false;
16102
- }
16103
- function signupCommanderLogIsConnected(log) {
16104
- return commanderConnectedMarkers.some((marker) => log.includes(marker));
16105
- }
16106
- function readTextFile(path) {
16107
- try {
16108
- return readFileSync10(path, "utf8");
16109
- } catch (_error) {
16110
- return;
16111
- }
16112
- }
16113
- async function waitForSignupCommanderLogChange(logFile, deadline, ready2) {
16114
- const remaining = Math.max(0, deadline - Date.now());
16115
- await new Promise((resolve9) => {
16116
- let resolved = false;
16117
- let watcher;
16118
- const finish = () => {
16119
- if (resolved) {
16120
- return;
16121
- }
16122
- resolved = true;
16123
- watcher?.close();
16124
- clearTimeout(timer);
16125
- resolve9();
16126
- };
16127
- const timer = setTimeout(finish, remaining);
16128
- try {
16129
- watcher = watch(logFile, finish);
16130
- watcher.on("error", finish);
16131
- if (ready2()) {
16132
- finish();
16133
- }
16134
- } catch (_error) {
16135
- if (ready2()) {
16136
- finish();
16137
- return;
16138
- }
16139
- try {
16140
- watcher = watch(dirname9(logFile), finish);
16141
- watcher.on("error", finish);
16142
- } catch (_nestedError) {}
16143
- }
16144
- });
16145
- }
16146
16488
  function signupCommanderRunnerId(workspaceSlug) {
16147
16489
  return `signup-${workspaceSlug}-commander`;
16148
16490
  }
16149
- function signupCommanderLaunchLogFile(runnerId) {
16150
- const launchId = `${Date.now()}-${process.pid}`;
16151
- return join12(homedir8(), ".linzumi", "commanders", `${runnerId}-${launchId}.log`);
16491
+ function failedSignupCommanderLaunchForMissingCodex(args) {
16492
+ return {
16493
+ status: "failed",
16494
+ runnerId: signupCommanderRunnerId(args.workspaceSlug),
16495
+ restartCommand: signupConnectRestartCommand(args),
16496
+ error: "Codex preflight did not resolve a verified Codex command. Install Codex or fix the Codex CLI on PATH, then rerun signup."
16497
+ };
16498
+ }
16499
+ async function signupCommanderRunnerOptions(args, runnerId) {
16500
+ const trust = kandanTlsTrustFromEnv();
16501
+ const editorRuntime = await resolveEditorRuntime({
16502
+ kandanUrl: args.serviceUrl,
16503
+ token: args.localRunnerAccessToken,
16504
+ fetchImpl: trustedFetch(trust)
16505
+ });
16506
+ const dependencyStatus = await buildRunnerDependencyStatus({
16507
+ cwd: args.projectPath,
16508
+ codexBin: args.codexBin,
16509
+ codeServerBin: editorRuntime.codeServerBin,
16510
+ editorRuntime: editorRuntime.status
16511
+ });
16512
+ assertStartDependencies(dependencyStatus);
16513
+ return {
16514
+ kandanUrl: args.serviceUrl,
16515
+ token: args.localRunnerAccessToken,
16516
+ runnerId,
16517
+ machineId: ensureLocalMachineIdForLinzumiUrl(args.serviceUrl),
16518
+ workspaceSlug: args.workspaceSlug,
16519
+ cwd: args.projectPath,
16520
+ codexBin: args.codexBin,
16521
+ codexUrl: undefined,
16522
+ launchTui: false,
16523
+ fast: false,
16524
+ allowedCwds: Array.from(new Set([args.projectPath, ...args.selectedProjectPaths])),
16525
+ allowedForwardPorts: [],
16526
+ codeServerBin: editorRuntime.codeServerBin,
16527
+ editorRuntime: editorRuntime.runtime,
16528
+ socketFactory: trustedWebSocketFactory(trust),
16529
+ dependencyStatus,
16530
+ runtimeDefaults: {
16531
+ model: undefined,
16532
+ reasoningEffort: undefined,
16533
+ approvalPolicy: undefined,
16534
+ sandbox: undefined
16535
+ },
16536
+ channelSession: undefined
16537
+ };
16152
16538
  }
16153
16539
  function signupConnectRestartCommand(args) {
16154
16540
  return [
@@ -16158,25 +16544,12 @@ function signupConnectRestartCommand(args) {
16158
16544
  "connect",
16159
16545
  "--workspace",
16160
16546
  args.workspaceSlug,
16161
- ...args.serviceUrl === defaultLinzumiHttpUrl ? [] : ["--linzumi-url", args.serviceUrl]
16547
+ ...args.codexBin === undefined ? [] : ["--codex-bin", args.codexBin],
16548
+ "--cwd",
16549
+ args.projectPath,
16550
+ ...args.serviceUrl === defaultLinzumiHttpUrl ? [] : ["--api-url", args.serviceUrl]
16162
16551
  ].map(shellArg).join(" ");
16163
16552
  }
16164
- function signupCommanderConnectSpawnArgs(args, runnerId, logFile, scriptPath) {
16165
- return [
16166
- scriptPath,
16167
- "connect",
16168
- "--linzumi-url",
16169
- args.serviceUrl,
16170
- "--workspace",
16171
- args.workspaceSlug,
16172
- "--channel",
16173
- args.officeChannelSlug,
16174
- "--runner-id",
16175
- runnerId,
16176
- "--log-file",
16177
- logFile
16178
- ];
16179
- }
16180
16553
  function shellArg(value) {
16181
16554
  if (/^[A-Za-z0-9_./:=@%+-]+$/.test(value)) {
16182
16555
  return value;
@@ -16997,6 +17370,10 @@ function defaultPreflightRuntime() {
16997
17370
  checkBrowserHandoff: async () => true
16998
17371
  };
16999
17372
  }
17373
+ function verifiedCodexBinFromPreflightChecks(checks) {
17374
+ const codex = checks.find((check2) => check2.id === "codex");
17375
+ return codex?.command;
17376
+ }
17000
17377
  function defaultProjectDiscoveryRuntime() {
17001
17378
  const cwd = process.cwd();
17002
17379
  return {
@@ -17123,13 +17500,9 @@ async function resolveSignupCodexCommand(env = process.env, homeDir = homedir8()
17123
17500
  env.LINZUMI_CODEX_BIN
17124
17501
  ]);
17125
17502
  if (override !== undefined) {
17126
- return resolveHomePath(override, homeDir);
17503
+ return resolveCodexCommandOverride(override, homeDir);
17127
17504
  }
17128
- const homeCandidates = [
17129
- join12(homeDir, ".volta", "bin", "codex"),
17130
- join12(homeDir, ".local", "bin", "codex"),
17131
- join12(homeDir, "bin", "codex")
17132
- ];
17505
+ const homeCandidates = homeManagedCodexCandidates(homeDir);
17133
17506
  const homeCodex = await firstExecutablePath(homeCandidates, executableExists);
17134
17507
  if (homeCodex !== undefined) {
17135
17508
  return homeCodex;
@@ -17161,6 +17534,20 @@ function resolveHomePath(path, homeDir) {
17161
17534
  }
17162
17535
  return resolve8(path);
17163
17536
  }
17537
+ function resolveCodexCommandOverride(command, homeDir) {
17538
+ const trimmed = command.trim();
17539
+ return commandLooksPathLike(trimmed) ? resolveHomePath(trimmed, homeDir) : trimmed;
17540
+ }
17541
+ function commandLooksPathLike(command) {
17542
+ return command === "~" || command.startsWith("~/") || command.startsWith("/") || command.startsWith("./") || command.startsWith("../") || command.includes("/") || command.includes("\\");
17543
+ }
17544
+ function homeManagedCodexCandidates(homeDir) {
17545
+ return [
17546
+ join12(homeDir, ".volta", "bin", "codex"),
17547
+ join12(homeDir, ".local", "bin", "codex"),
17548
+ join12(homeDir, "bin", "codex")
17549
+ ];
17550
+ }
17164
17551
  async function firstExecutablePath(paths, executableExists) {
17165
17552
  for (const path of paths) {
17166
17553
  if (await executableExists(path)) {
@@ -17324,19 +17711,51 @@ async function checkGit(runtime) {
17324
17711
  };
17325
17712
  }
17326
17713
  async function checkCodex(runtime) {
17327
- const [pathCodex, voltaCodex] = await Promise.all([
17328
- runtime.probeTool("codex", runtime.cwd),
17329
- runtime.probeTool(join12(runtime.homeDir, ".volta", "bin", "codex"), runtime.cwd)
17330
- ]);
17331
- const codex = pathCodex.available ? pathCodex : voltaCodex;
17332
- const location = pathCodex.available ? "on PATH" : "via Volta";
17714
+ const configuredCodex = process.env.LINZUMI_SIGNUP_CODEX_BIN !== undefined && process.env.LINZUMI_SIGNUP_CODEX_BIN.trim() !== "" ? {
17715
+ value: process.env.LINZUMI_SIGNUP_CODEX_BIN,
17716
+ source: "LINZUMI_SIGNUP_CODEX_BIN"
17717
+ } : process.env.LINZUMI_CODEX_BIN !== undefined && process.env.LINZUMI_CODEX_BIN.trim() !== "" ? {
17718
+ value: process.env.LINZUMI_CODEX_BIN,
17719
+ source: "LINZUMI_CODEX_BIN"
17720
+ } : undefined;
17721
+ const configuredCommand = configuredCodex === undefined ? undefined : resolveCodexCommandOverride(configuredCodex.value, runtime.homeDir);
17722
+ if (configuredCommand !== undefined) {
17723
+ const codex2 = await runtime.probeTool(configuredCommand, runtime.cwd);
17724
+ const location2 = `from ${configuredCodex?.source ?? "configured env"}`;
17725
+ return {
17726
+ id: "codex",
17727
+ title: "Codex CLI",
17728
+ detail: codex2.available ? `${codex2.version ?? "codex found"} ${location2}` : `${configuredCommand} ${location2} did not pass --version`,
17729
+ status: codex2.available ? "pass" : "warn",
17730
+ command: codex2.available ? codex2.command : undefined
17731
+ };
17732
+ }
17733
+ const candidates = ["codex", ...homeManagedCodexCandidates(runtime.homeDir)];
17734
+ const [firstCodex, ...otherCodexes] = await Promise.all(candidates.map((candidate) => runtime.probeTool(candidate, runtime.cwd)));
17735
+ const codex = [firstCodex, ...otherCodexes].find((status) => status.available) ?? firstCodex;
17736
+ const location = codexPreflightLocation(codex.command, runtime.homeDir);
17333
17737
  return {
17334
17738
  id: "codex",
17335
17739
  title: "Codex CLI",
17336
17740
  detail: codex.available ? `${codex.version ?? "codex found"} ${location}` : "codex not found",
17337
- status: codex.available ? "pass" : "warn"
17741
+ status: codex.available ? "pass" : "warn",
17742
+ command: codex.available ? codex.command : undefined
17338
17743
  };
17339
17744
  }
17745
+ function codexPreflightLocation(command, homeDir) {
17746
+ switch (command) {
17747
+ case "codex":
17748
+ return "on PATH";
17749
+ case join12(homeDir, ".volta", "bin", "codex"):
17750
+ return "via Volta";
17751
+ case join12(homeDir, ".local", "bin", "codex"):
17752
+ return "via ~/.local/bin";
17753
+ case join12(homeDir, "bin", "codex"):
17754
+ return "via ~/bin";
17755
+ default:
17756
+ return "from configured path";
17757
+ }
17758
+ }
17340
17759
  async function checkGitEmail(runtime) {
17341
17760
  const email = await runtime.readGitEmail(runtime.cwd);
17342
17761
  return {
@@ -17668,11 +18087,11 @@ import {
17668
18087
  mkdirSync as mkdirSync11,
17669
18088
  openSync as openSync3,
17670
18089
  readFileSync as readFileSync11,
17671
- watch as watch2,
18090
+ watch,
17672
18091
  writeFileSync as writeFileSync9
17673
18092
  } from "node:fs";
17674
18093
  import { homedir as homedir9 } from "node:os";
17675
- import { dirname as dirname10, join as join13, resolve as resolve9 } from "node:path";
18094
+ import { dirname as dirname9, join as join13, resolve as resolve9 } from "node:path";
17676
18095
  import { execFileSync, spawn as spawn8 } from "node:child_process";
17677
18096
  import { fileURLToPath as fileURLToPath2 } from "node:url";
17678
18097
  var connectedMarkers = ["Connected to Linzumi", "Runner connected:"];
@@ -17705,7 +18124,7 @@ function startCommanderDaemon(options) {
17705
18124
  logFile
17706
18125
  ];
17707
18126
  mkdirSync11(statusDir, { recursive: true });
17708
- mkdirSync11(dirname10(logFile), { recursive: true });
18127
+ mkdirSync11(dirname9(logFile), { recursive: true });
17709
18128
  const out = openSync3(logFile, "a");
17710
18129
  const err = openSync3(logFile, "a");
17711
18130
  writeCliAuditEvent("process.spawn", {
@@ -17757,7 +18176,7 @@ function commanderDaemonStatus(runnerId, statusDir = commanderStatusDir(), proce
17757
18176
  }
17758
18177
  async function waitForCommanderDaemon(options) {
17759
18178
  const now = options.now ?? (() => Date.now());
17760
- const readTextFile2 = options.readTextFile ?? ((path) => existsSync11(path) ? readFileSync11(path, "utf8") : undefined);
18179
+ const readTextFile = options.readTextFile ?? ((path) => existsSync11(path) ? readFileSync11(path, "utf8") : undefined);
17761
18180
  const statusImpl = options.statusImpl ?? commanderDaemonStatus;
17762
18181
  const deadline = now() + options.timeoutMs;
17763
18182
  while (now() <= deadline) {
@@ -17768,7 +18187,7 @@ async function waitForCommanderDaemon(options) {
17768
18187
  case "stopped":
17769
18188
  return { ok: false, reason: "stopped" };
17770
18189
  case "running": {
17771
- const log = readTextFile2(status.record.logFile);
18190
+ const log = readTextFile(status.record.logFile);
17772
18191
  if (log === undefined) {
17773
18192
  return { ok: false, reason: "timeout" };
17774
18193
  }
@@ -17776,7 +18195,7 @@ async function waitForCommanderDaemon(options) {
17776
18195
  return { ok: true, record: status.record };
17777
18196
  }
17778
18197
  await waitForFileChangeOrTimeout(status.record.logFile, deadline, now, () => {
17779
- const updatedLog = readTextFile2(status.record.logFile);
18198
+ const updatedLog = readTextFile(status.record.logFile);
17780
18199
  return updatedLog !== undefined && commanderLogIsConnected(updatedLog);
17781
18200
  });
17782
18201
  }
@@ -17902,7 +18321,7 @@ async function waitForFileChangeOrTimeout(path, deadline, now, ready2 = () => fa
17902
18321
  };
17903
18322
  const timer = setTimeout(finish, remaining);
17904
18323
  try {
17905
- watcher = watch2(path, finish);
18324
+ watcher = watch(path, finish);
17906
18325
  watcher.on("error", finish);
17907
18326
  if (ready2()) {
17908
18327
  finish();
@@ -17920,8 +18339,7 @@ async function waitForFileChangeOrTimeout(path, deadline, now, ready2 = () => fa
17920
18339
  // src/index.ts
17921
18340
  var flagDefinitions = new Map([
17922
18341
  ["version", { kind: "boolean" }],
17923
- ["linzumi-url", { kind: "value" }],
17924
- ["kandan-url", { kind: "value" }],
18342
+ ["api-url", { kind: "value" }],
17925
18343
  ["token", { kind: "value" }],
17926
18344
  ["runner-id", { kind: "value" }],
17927
18345
  ["cwd", { kind: "value" }],
@@ -17931,7 +18349,6 @@ var flagDefinitions = new Map([
17931
18349
  ["workspace", { kind: "value" }],
17932
18350
  ["channel", { kind: "value" }],
17933
18351
  ["linzumi-thread-id", { kind: "value" }],
17934
- ["kandan-thread-id", { kind: "value" }],
17935
18352
  ["listen-user", { kind: "value" }],
17936
18353
  ["model", { kind: "value" }],
17937
18354
  ["reasoning-effort", { kind: "value" }],
@@ -17950,10 +18367,6 @@ var flagDefinitions = new Map([
17950
18367
  ["oauth-callback-host", { kind: "value" }],
17951
18368
  ["help", { kind: "boolean" }]
17952
18369
  ]);
17953
- var flagAliases = new Map([
17954
- ["kandan-url", "linzumi-url"],
17955
- ["kandan-thread-id", "linzumi-thread-id"]
17956
- ]);
17957
18370
  var helloFlagDefinitions = new Map([
17958
18371
  ["dir", { kind: "value" }],
17959
18372
  ["parent-dir", { kind: "value" }],
@@ -18209,8 +18622,7 @@ function parsePathsCommandArgs(args) {
18209
18622
  case "--help":
18210
18623
  help = true;
18211
18624
  break;
18212
- case "--linzumi-url":
18213
- case "--kandan-url": {
18625
+ case "--api-url": {
18214
18626
  const value = args[index + 1];
18215
18627
  if (value === undefined || value.startsWith("--")) {
18216
18628
  throw new Error(`missing value for ${arg}`);
@@ -18321,7 +18733,7 @@ async function runAuthCommand(args) {
18321
18733
  process.stdout.write(helpText());
18322
18734
  return;
18323
18735
  }
18324
- const kandanUrl = required(values, "linzumi-url");
18736
+ const kandanUrl = required(values, "api-url");
18325
18737
  const target = parseOptionalChannelTarget(values);
18326
18738
  const token = await acquireLocalRunnerTokenDetails({
18327
18739
  kandanUrl,
@@ -18352,7 +18764,7 @@ async function parseStartRunnerArgs(args, deps = {
18352
18764
  process.exit(0);
18353
18765
  }
18354
18766
  rejectStartTargetingFlags(values);
18355
- const kandanUrl = stringValue4(values, "linzumi-url") ?? defaultLinzumiWebSocketUrl;
18767
+ const kandanUrl = stringValue4(values, "api-url") ?? defaultLinzumiWebSocketUrl;
18356
18768
  const requestedCwd = resolveUserPath(cwdArg ?? process.cwd());
18357
18769
  const cwd = assertConfiguredAllowedCwds([requestedCwd])[0] ?? requestedCwd;
18358
18770
  const explicitAllowedCwds = values.has("allowed-cwd") ? assertConfiguredAllowedCwds(parseAllowedCwdList(stringValue4(values, "allowed-cwd"))) : [];
@@ -18470,7 +18882,7 @@ async function parseAgentRunnerArgs(args, deps = {
18470
18882
  approvalPolicy: stringValue4(values, "approval-policy"),
18471
18883
  streamFlushMs: positiveIntegerValue2(values, "stream-flush-ms")
18472
18884
  };
18473
- const kandanUrl = stringValue4(values, "linzumi-url") ?? agentApiUrlToKandanUrl(tokenFile.apiUrl);
18885
+ const kandanUrl = stringValue4(values, "api-url") ?? agentApiUrlToKandanUrl(tokenFile.apiUrl);
18474
18886
  const requestedCwdValue = cwdArg ?? stringValue4(values, "cwd");
18475
18887
  const requestedCwd = resolveUserPath(requestedCwdValue ?? process.cwd());
18476
18888
  const configuredAllowedCwds2 = requestedCwdValue === undefined && !values.has("allowed-cwd") ? readConfiguredAllowedCwdDetailsForLinzumiUrl(kandanUrl) : { allowedCwds: [], missingAllowedCwds: [] };
@@ -18600,8 +19012,9 @@ async function parseRunnerArgs(args, deps = {
18600
19012
  `);
18601
19013
  process.exit(0);
18602
19014
  }
18603
- const connectTarget = parseConnectTarget(values);
18604
- const kandanUrl = stringValue4(values, "linzumi-url") ?? defaultLinzumiWebSocketUrl;
19015
+ rejectConnectChannelFlags(values);
19016
+ const workspaceSlug = stringValue4(values, "workspace");
19017
+ const kandanUrl = stringValue4(values, "api-url") ?? defaultLinzumiWebSocketUrl;
18605
19018
  const cwd = stringValue4(values, "cwd") ?? process.cwd();
18606
19019
  const cwdAllowedCwds = assertConfiguredAllowedCwds([cwd]);
18607
19020
  const localConfiguredAllowedCwds = values.has("allowed-cwd") ? { allowedCwds: [], missingAllowedCwds: [] } : readConfiguredAllowedCwdDetailsForLinzumiUrl(kandanUrl);
@@ -18612,8 +19025,7 @@ async function parseRunnerArgs(args, deps = {
18612
19025
  const token = await deps.resolveToken({
18613
19026
  kandanUrl,
18614
19027
  explicitToken,
18615
- workspaceSlug: connectTarget?.workspaceSlug,
18616
- channelSlug: connectTarget?.channelSlug,
19028
+ workspaceSlug,
18617
19029
  authFilePath: stringValue4(values, "auth-file"),
18618
19030
  callbackHost: stringValue4(values, "oauth-callback-host"),
18619
19031
  reportRejectedCachedToken: () => {
@@ -18621,7 +19033,6 @@ async function parseRunnerArgs(args, deps = {
18621
19033
  `);
18622
19034
  }
18623
19035
  });
18624
- const channelSession = parseChannelSession(values, token, connectTarget);
18625
19036
  const editorRuntime = await deps.resolveEditorRuntime({
18626
19037
  kandanUrl,
18627
19038
  token,
@@ -18652,9 +19063,8 @@ async function parseRunnerArgs(args, deps = {
18652
19063
  editorRuntime: editorRuntime.runtime,
18653
19064
  socketFactory: trustedWebSocketFactory(kandanTlsTrustFromEnv()),
18654
19065
  dependencyStatus,
18655
- workspaceSlug: connectTarget?.workspaceSlug ?? singleWorkspaceScopeFromAccessToken(token),
18656
- runtimeDefaults: runnerRuntimeDefaultsFromValues(values),
18657
- channelSession
19066
+ workspaceSlug: workspaceSlug ?? singleWorkspaceScopeFromAccessToken(token),
19067
+ runtimeDefaults: runnerRuntimeDefaultsFromValues(values)
18658
19068
  };
18659
19069
  }
18660
19070
  function runnerRuntimeDefaultsFromValues(values) {
@@ -18662,7 +19072,8 @@ function runnerRuntimeDefaultsFromValues(values) {
18662
19072
  model: stringValue4(values, "model"),
18663
19073
  reasoningEffort: stringValue4(values, "reasoning-effort"),
18664
19074
  approvalPolicy: stringValue4(values, "approval-policy"),
18665
- sandbox: stringValue4(values, "sandbox")
19075
+ sandbox: stringValue4(values, "sandbox"),
19076
+ allowPortForwardingByDefault: undefined
18666
19077
  };
18667
19078
  }
18668
19079
  function strictFlagValues(args, definitions = flagDefinitions) {
@@ -18677,16 +19088,15 @@ function strictFlagValues(args, definitions = flagDefinitions) {
18677
19088
  if (definition === undefined) {
18678
19089
  throw new Error(`invalid flag: --${rawKey}`);
18679
19090
  }
18680
- const key = flagAliases.get(rawKey) ?? rawKey;
18681
19091
  if (definition.kind === "boolean") {
18682
- values.set(key, true);
19092
+ values.set(rawKey, true);
18683
19093
  continue;
18684
19094
  }
18685
19095
  const next = args[index + 1];
18686
19096
  if (next === undefined || next.startsWith("--")) {
18687
19097
  throw new Error(`missing value for --${rawKey}`);
18688
19098
  }
18689
- values.set(key, next);
19099
+ values.set(rawKey, next);
18690
19100
  index += 1;
18691
19101
  }
18692
19102
  return values;
@@ -18751,7 +19161,7 @@ function stripDaemonSupervisorFlags(args) {
18751
19161
  function rejectStartTargetingFlags(values) {
18752
19162
  const unsupportedFlags = ["workspace", "channel"].filter((flag) => values.has(flag));
18753
19163
  if (unsupportedFlags.length > 0) {
18754
- throw new Error(`linzumi start chooses its workspace during browser onboarding; remove ${unsupportedFlags.map((flag) => `--${flag}`).join(", ")} or use linzumi connect for an explicit workspace/channel.`);
19164
+ throw new Error(`linzumi start chooses its workspace during browser onboarding; remove ${unsupportedFlags.map((flag) => `--${flag}`).join(", ")} or use linzumi connect --workspace for an explicit workspace.`);
18755
19165
  }
18756
19166
  }
18757
19167
  function resolveUserPath(pathValue) {
@@ -18763,26 +19173,6 @@ function resolveUserPath(pathValue) {
18763
19173
  }
18764
19174
  return resolve10(pathValue);
18765
19175
  }
18766
- function parseChannelSession(values, token, target) {
18767
- if (target === undefined || target.channelSlug === undefined) {
18768
- return;
18769
- }
18770
- const listenUser = stringValue4(values, "listen-user") ?? defaultListenUserFromToken(token);
18771
- return {
18772
- workspaceSlug: target.workspaceSlug,
18773
- channelSlug: target.channelSlug,
18774
- kandanThreadId: stringValue4(values, "linzumi-thread-id"),
18775
- listenUser,
18776
- model: stringValue4(values, "model"),
18777
- reasoningEffort: stringValue4(values, "reasoning-effort"),
18778
- sandbox: stringValue4(values, "sandbox"),
18779
- approvalPolicy: stringValue4(values, "approval-policy"),
18780
- streamFlushMs: positiveIntegerValue2(values, "stream-flush-ms")
18781
- };
18782
- }
18783
- function parseConnectTarget(values) {
18784
- return parseOptionalChannelTarget(values);
18785
- }
18786
19176
  function defaultListenUserFromToken(token) {
18787
19177
  const username = identityFromAccessToken(token).actorUsername;
18788
19178
  if (username !== undefined) {
@@ -18790,6 +19180,17 @@ function defaultListenUserFromToken(token) {
18790
19180
  }
18791
19181
  throw new Error("missing --listen-user and authenticated user is unavailable");
18792
19182
  }
19183
+ function rejectConnectChannelFlags(values) {
19184
+ const unsupportedFlags = [
19185
+ "channel",
19186
+ "linzumi-thread-id",
19187
+ "listen-user"
19188
+ ].filter((flag) => values.has(flag));
19189
+ if (unsupportedFlags.length === 0) {
19190
+ return;
19191
+ }
19192
+ throw new Error(`linzumi connect starts a workspace Commander; remove ${unsupportedFlags.map((flag) => `--${flag}`).join(", ")}.`);
19193
+ }
18793
19194
  function parseOptionalChannelTarget(values) {
18794
19195
  const channel = stringValue4(values, "channel");
18795
19196
  const workspace = stringValue4(values, "workspace");
@@ -18876,22 +19277,17 @@ Usage:
18876
19277
  linzumi commander <folder> [options]
18877
19278
  linzumi start <folder> [options]
18878
19279
  linzumi paths list|add|remove [path]
18879
- linzumi connect --workspace <slug> [--channel <slug>] [options]
18880
- linzumi auth --linzumi-url <ws-url> [--workspace <slug> --channel <slug>]
19280
+ linzumi connect --workspace <slug> [options]
19281
+ linzumi auth --api-url <url> [--workspace <slug> --channel <slug>]
18881
19282
 
18882
19283
  Connection:
18883
- --linzumi-url <ws-url> Linzumi backend URL, default ${defaultLinzumiWebSocketUrl}
18884
- (deprecated alias: --kandan-url)
19284
+ --api-url <url> Linzumi API URL, default ${defaultLinzumiWebSocketUrl}
18885
19285
  --token <jwt> Optional override token. Otherwise ~/.linzumi/auth.json is validated or OAuth opens.
18886
19286
  --auth-file <path> Auth cache path, default ~/.linzumi/auth.json
18887
19287
  --oauth-callback-host <ip> Callback host reachable by your browser
18888
19288
 
18889
- Workspace and optional channel binding:
19289
+ Workspace:
18890
19290
  --workspace <slug> Workspace slug
18891
- --channel <slug|w/c> Optional channel slug, or workspace/channel
18892
- --linzumi-thread-id <uuid> Resume an existing Linzumi thread instead of announcing a new root
18893
- (deprecated alias: --kandan-thread-id)
18894
- --listen-user <user|all> User whose replies are accepted, default authenticated user
18895
19291
 
18896
19292
  Codex:
18897
19293
  --cwd <path> Working directory for Codex, default current directory
@@ -18923,16 +19319,15 @@ Examples:
18923
19319
  linzumi start ~/code/my-app
18924
19320
  linzumi connect --workspace <your-workspace> --launch-tui
18925
19321
  linzumi connect --workspace <your-workspace> --model gpt-5 --reasoning-effort low --fast --launch-tui
18926
- linzumi connect --workspace <your-workspace> --channel <your-channel>
18927
19322
  linzumi auth --workspace <your-workspace> --channel <your-channel>
18928
19323
  linzumi paths add ~/code/my-app
18929
19324
  linzumi paths list
18930
19325
 
18931
19326
  Bad:
18932
- linzumi connect --token not-a-jwt --workspace <your-workspace> --channel <your-channel>
18933
- Missing --listen-user and authenticated user is unavailable.
18934
- linzumi connect --token "$TOKEN" --listen-users sean
18935
- Invalid flag: use --listen-user.
19327
+ linzumi connect --workspace <your-workspace> --channel <your-channel>
19328
+ Invalid: Commanders connect to workspaces, not channels.
19329
+ linzumi connect --token "$TOKEN" --listen-user sean
19330
+ Invalid: Commanders connect to workspaces, not individual channel listeners.
18936
19331
  linzumi connect --workspace <your-workspace> --allowed-cwd /does/not/exist
18937
19332
  Invalid --allowed-cwd: allowed cwd roots must exist locally.
18938
19333
  linzumi connect --workspace <your-workspace> --forward-port vite
@@ -18999,12 +19394,12 @@ function pathsHelpText() {
18999
19394
  return `Linzumi trusted paths
19000
19395
 
19001
19396
  Usage:
19002
- linzumi paths [--linzumi-url <ws-url>] list
19003
- linzumi paths [--linzumi-url <ws-url>] add <path>
19004
- linzumi paths [--linzumi-url <ws-url>] remove <path>
19397
+ linzumi paths [--api-url <url>] list
19398
+ linzumi paths [--api-url <url>] add <path>
19399
+ linzumi paths [--api-url <url>] remove <path>
19005
19400
 
19006
19401
  Trusted paths are stored in ~/.linzumi/config.json. Production/default paths
19007
- use the root config fields; explicit --linzumi-url paths use a URL-scoped config
19402
+ use the root config fields; explicit --api-url paths use a URL-scoped config
19008
19403
  section so local, staging, and production runners do not share trust state.
19009
19404
  `;
19010
19405
  }
@@ -19021,8 +19416,7 @@ What it does:
19021
19416
  previews, and the browser VS Code editor.
19022
19417
 
19023
19418
  Options:
19024
- --linzumi-url <ws-url> Linzumi backend URL, default ${defaultLinzumiWebSocketUrl}
19025
- (deprecated alias: --kandan-url)
19419
+ --api-url <url> Linzumi API URL, default ${defaultLinzumiWebSocketUrl}
19026
19420
  --token <jwt> Optional scoped local-runner token override
19027
19421
  --auth-file <path> Auth cache path, default ~/.linzumi/auth.json
19028
19422
  --oauth-callback-host <ip> Callback host reachable by your browser
@@ -19062,8 +19456,7 @@ What it does:
19062
19456
 
19063
19457
  Options:
19064
19458
  --agent-token-file <path> Agent token cache, default ~/.linzumi/agent-token.json
19065
- --linzumi-url <ws-url> Linzumi websocket base URL. Defaults deterministically from the stored apiUrl.
19066
- (deprecated alias: --kandan-url)
19459
+ --api-url <url> Linzumi API URL. Defaults deterministically from the stored apiUrl.
19067
19460
  --runner-id <id> Stable Commander id
19068
19461
  --codex-bin <path> Codex executable, default codex
19069
19462
  --code-server-bin <path> Custom development code-server executable. By default Linzumi installs the approved editor runtime.
@@ -19079,7 +19472,7 @@ Options:
19079
19472
  Examples:
19080
19473
  linzumi paths add "$PWD"
19081
19474
  linzumi commander daemon --runner-id hello-world-commander
19082
- linzumi commander ~/code/my-app --linzumi-url ws://127.0.0.1:4162 --runner-id local-qa-commander
19475
+ linzumi commander ~/code/my-app --api-url http://127.0.0.1:4162 --runner-id local-qa-commander
19083
19476
  `;
19084
19477
  }
19085
19478
  function connectGuideText() {