orion-super-agent-dev 0.1.19 → 0.1.20

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/out/main.js CHANGED
@@ -25517,14 +25517,14 @@ var require_templates = __commonJS({
25517
25517
  }
25518
25518
  return results;
25519
25519
  }
25520
- function buildStyle(chalk5, styles3) {
25520
+ function buildStyle(chalk6, styles3) {
25521
25521
  const enabled = {};
25522
25522
  for (const layer of styles3) {
25523
25523
  for (const style of layer.styles) {
25524
25524
  enabled[style[0]] = layer.inverse ? null : style.slice(1);
25525
25525
  }
25526
25526
  }
25527
- let current2 = chalk5;
25527
+ let current2 = chalk6;
25528
25528
  for (const [styleName, styles4] of Object.entries(enabled)) {
25529
25529
  if (!Array.isArray(styles4)) {
25530
25530
  continue;
@@ -25536,7 +25536,7 @@ var require_templates = __commonJS({
25536
25536
  }
25537
25537
  return current2;
25538
25538
  }
25539
- module2.exports = (chalk5, temporary) => {
25539
+ module2.exports = (chalk6, temporary) => {
25540
25540
  const styles3 = [];
25541
25541
  const chunks = [];
25542
25542
  let chunk = [];
@@ -25546,13 +25546,13 @@ var require_templates = __commonJS({
25546
25546
  } else if (style) {
25547
25547
  const string = chunk.join("");
25548
25548
  chunk = [];
25549
- chunks.push(styles3.length === 0 ? string : buildStyle(chalk5, styles3)(string));
25549
+ chunks.push(styles3.length === 0 ? string : buildStyle(chalk6, styles3)(string));
25550
25550
  styles3.push({ inverse, styles: parseStyle(style) });
25551
25551
  } else if (close) {
25552
25552
  if (styles3.length === 0) {
25553
25553
  throw new Error("Found extraneous } in Chalk template literal");
25554
25554
  }
25555
- chunks.push(buildStyle(chalk5, styles3)(chunk.join("")));
25555
+ chunks.push(buildStyle(chalk6, styles3)(chunk.join("")));
25556
25556
  chunk = [];
25557
25557
  styles3.pop();
25558
25558
  } else {
@@ -25600,16 +25600,16 @@ var require_source = __commonJS({
25600
25600
  }
25601
25601
  };
25602
25602
  var chalkFactory = (options) => {
25603
- const chalk6 = {};
25604
- applyOptions(chalk6, options);
25605
- chalk6.template = (...arguments_2) => chalkTag(chalk6.template, ...arguments_2);
25606
- Object.setPrototypeOf(chalk6, Chalk.prototype);
25607
- Object.setPrototypeOf(chalk6.template, chalk6);
25608
- chalk6.template.constructor = () => {
25603
+ const chalk7 = {};
25604
+ applyOptions(chalk7, options);
25605
+ chalk7.template = (...arguments_2) => chalkTag(chalk7.template, ...arguments_2);
25606
+ Object.setPrototypeOf(chalk7, Chalk.prototype);
25607
+ Object.setPrototypeOf(chalk7.template, chalk7);
25608
+ chalk7.template.constructor = () => {
25609
25609
  throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.");
25610
25610
  };
25611
- chalk6.template.Instance = ChalkClass;
25612
- return chalk6.template;
25611
+ chalk7.template.Instance = ChalkClass;
25612
+ return chalk7.template;
25613
25613
  };
25614
25614
  function Chalk(options) {
25615
25615
  return chalkFactory(options);
@@ -25720,7 +25720,7 @@ var require_source = __commonJS({
25720
25720
  return openAll + string + closeAll;
25721
25721
  };
25722
25722
  var template;
25723
- var chalkTag = (chalk6, ...strings) => {
25723
+ var chalkTag = (chalk7, ...strings) => {
25724
25724
  const [firstString] = strings;
25725
25725
  if (!isArray(firstString) || !isArray(firstString.raw)) {
25726
25726
  return strings.join(" ");
@@ -25736,14 +25736,14 @@ var require_source = __commonJS({
25736
25736
  if (template === void 0) {
25737
25737
  template = require_templates();
25738
25738
  }
25739
- return template(chalk6, parts2.join(""));
25739
+ return template(chalk7, parts2.join(""));
25740
25740
  };
25741
25741
  Object.defineProperties(Chalk.prototype, styles3);
25742
- var chalk5 = Chalk();
25743
- chalk5.supportsColor = stdoutColor;
25744
- chalk5.stderr = Chalk({ level: stderrColor ? stderrColor.level : 0 });
25745
- chalk5.stderr.supportsColor = stderrColor;
25746
- module2.exports = chalk5;
25742
+ var chalk6 = Chalk();
25743
+ chalk6.supportsColor = stdoutColor;
25744
+ chalk6.stderr = Chalk({ level: stderrColor ? stderrColor.level : 0 });
25745
+ chalk6.stderr.supportsColor = stderrColor;
25746
+ module2.exports = chalk6;
25747
25747
  }
25748
25748
  });
25749
25749
 
@@ -29033,6 +29033,36 @@ var require_atomicWrite = __commonJS({
29033
29033
  }
29034
29034
  });
29035
29035
 
29036
+ // ../packages/orion-client-core/dist/duetPlanners.js
29037
+ var require_duetPlanners = __commonJS({
29038
+ "../packages/orion-client-core/dist/duetPlanners.js"(exports2) {
29039
+ "use strict";
29040
+ Object.defineProperty(exports2, "__esModule", { value: true });
29041
+ exports2.DUET_PLANNER_LABELS = exports2.DUET_PLANNER_PROVIDERS = exports2.DUET_PLANNER_DEFAULT = exports2.DUET_EXECUTOR_DEFAULT_ID = exports2.DUET_PLANNER_IDS = void 0;
29042
+ exports2.isDuetPlanner = isDuetPlanner2;
29043
+ exports2.resolveDuetPlanner = resolveDuetPlanner2;
29044
+ exports2.DUET_PLANNER_IDS = ["claude-fable-5", "claude-opus-5"];
29045
+ exports2.DUET_EXECUTOR_DEFAULT_ID = "claude-sonnet-5";
29046
+ exports2.DUET_PLANNER_DEFAULT = "claude-fable-5";
29047
+ exports2.DUET_PLANNER_PROVIDERS = ["claude_code", "anthropic"];
29048
+ exports2.DUET_PLANNER_LABELS = {
29049
+ "claude-fable-5": "Claude Fable 5",
29050
+ "claude-opus-5": "Claude Opus 5"
29051
+ };
29052
+ function isDuetPlanner2(model) {
29053
+ return !!model && exports2.DUET_PLANNER_IDS.includes(model);
29054
+ }
29055
+ function resolveDuetPlanner2(id, models) {
29056
+ for (const provider of exports2.DUET_PLANNER_PROVIDERS) {
29057
+ if (models.some((m2) => m2.id === id && (m2.provider ?? "") === provider)) {
29058
+ return { provider, model: id };
29059
+ }
29060
+ }
29061
+ return { provider: exports2.DUET_PLANNER_PROVIDERS[0], model: id };
29062
+ }
29063
+ }
29064
+ });
29065
+
29036
29066
  // ../packages/orion-client-core/dist/settingsPaths.js
29037
29067
  var require_settingsPaths = __commonJS({
29038
29068
  "../packages/orion-client-core/dist/settingsPaths.js"(exports2) {
@@ -29091,6 +29121,405 @@ var require_settingsPaths = __commonJS({
29091
29121
  }
29092
29122
  });
29093
29123
 
29124
+ // ../packages/orion-client-core/dist/duetMode.js
29125
+ var require_duetMode = __commonJS({
29126
+ "../packages/orion-client-core/dist/duetMode.js"(exports2) {
29127
+ "use strict";
29128
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m2, k, k2) {
29129
+ if (k2 === void 0) k2 = k;
29130
+ var desc = Object.getOwnPropertyDescriptor(m2, k);
29131
+ if (!desc || ("get" in desc ? !m2.__esModule : desc.writable || desc.configurable)) {
29132
+ desc = { enumerable: true, get: function() {
29133
+ return m2[k];
29134
+ } };
29135
+ }
29136
+ Object.defineProperty(o, k2, desc);
29137
+ } : function(o, m2, k, k2) {
29138
+ if (k2 === void 0) k2 = k;
29139
+ o[k2] = m2[k];
29140
+ });
29141
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v2) {
29142
+ Object.defineProperty(o, "default", { enumerable: true, value: v2 });
29143
+ } : function(o, v2) {
29144
+ o["default"] = v2;
29145
+ });
29146
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ function() {
29147
+ var ownKeys = function(o) {
29148
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
29149
+ var ar = [];
29150
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
29151
+ return ar;
29152
+ };
29153
+ return ownKeys(o);
29154
+ };
29155
+ return function(mod2) {
29156
+ if (mod2 && mod2.__esModule) return mod2;
29157
+ var result = {};
29158
+ if (mod2 != null) {
29159
+ for (var k = ownKeys(mod2), i2 = 0; i2 < k.length; i2++) if (k[i2] !== "default") __createBinding(result, mod2, k[i2]);
29160
+ }
29161
+ __setModuleDefault(result, mod2);
29162
+ return result;
29163
+ };
29164
+ }();
29165
+ Object.defineProperty(exports2, "__esModule", { value: true });
29166
+ exports2.DUET_EXECUTOR_INFO = exports2.DUET_EXECUTOR_DEFAULT_LABEL = void 0;
29167
+ exports2.clearDuetExecutorCache = clearDuetExecutorCache;
29168
+ exports2.loadDuetExecutor = loadDuetExecutor2;
29169
+ exports2.setDuetExecutor = setDuetExecutor2;
29170
+ exports2.duetExecutorSource = duetExecutorSource;
29171
+ exports2.duetExecutorWireForSegment = duetExecutorWireForSegment;
29172
+ exports2.prewarmDuetExecutor = prewarmDuetExecutor;
29173
+ var fs14 = __importStar(__require("node:fs/promises"));
29174
+ var os8 = __importStar(__require("node:os"));
29175
+ var path13 = __importStar(__require("node:path"));
29176
+ var atomicWrite_js_1 = require_atomicWrite();
29177
+ var duetPlanners_js_1 = require_duetPlanners();
29178
+ var settingsPaths_js_1 = require_settingsPaths();
29179
+ exports2.DUET_EXECUTOR_DEFAULT_LABEL = "Claude Sonnet 5";
29180
+ exports2.DUET_EXECUTOR_INFO = {
29181
+ /** The choice's snake_case key on the segment body. */
29182
+ wireKey: "duet_executor",
29183
+ label: "Duet executor",
29184
+ description: "Runs the approved plan in Duet mode. Planning stays on the session's model; execution hands off to this one (Claude Sonnet 5 unless changed)."
29185
+ };
29186
+ var MAX_MODEL_LEN = 128;
29187
+ var MAX_PROVIDER_LEN = 64;
29188
+ var MAX_EFFORT_LEN = 24;
29189
+ var MAX_WINDOW = 5e7;
29190
+ function toChoice(raw) {
29191
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw))
29192
+ return null;
29193
+ const value = raw;
29194
+ const model = typeof value.model === "string" ? value.model.trim() : "";
29195
+ if (model === "" || model.length > MAX_MODEL_LEN)
29196
+ return null;
29197
+ const provider = typeof value.provider === "string" ? value.provider.trim() : "";
29198
+ if (provider.length > MAX_PROVIDER_LEN)
29199
+ return null;
29200
+ const rawEffort = typeof value.effort === "string" ? value.effort.trim() : "";
29201
+ if (rawEffort.length > MAX_EFFORT_LEN)
29202
+ return null;
29203
+ const windowRaw = typeof value.contextWindow === "number" ? value.contextWindow : 0;
29204
+ const contextWindow = Number.isInteger(windowRaw) && windowRaw >= 1 && windowRaw <= MAX_WINDOW ? windowRaw : void 0;
29205
+ return {
29206
+ provider,
29207
+ model,
29208
+ ...rawEffort !== "" ? { effort: rawEffort } : {},
29209
+ ...contextWindow !== void 0 ? { contextWindow } : {}
29210
+ };
29211
+ }
29212
+ async function readTier(file) {
29213
+ if (file === null)
29214
+ return null;
29215
+ let parsed;
29216
+ try {
29217
+ parsed = JSON.parse(await fs14.readFile(file, "utf8"));
29218
+ } catch {
29219
+ return null;
29220
+ }
29221
+ return toChoice(parsed?.duetExecutor);
29222
+ }
29223
+ var DUET_EXECUTOR_CACHE_TTL_MS = 5e3;
29224
+ var cache3 = /* @__PURE__ */ new Map();
29225
+ var refreshing = /* @__PURE__ */ new Map();
29226
+ function cacheKeyFor(home, ws) {
29227
+ return `${home}\0${ws ?? ""}`;
29228
+ }
29229
+ function clearDuetExecutorCache() {
29230
+ cache3.clear();
29231
+ refreshing.clear();
29232
+ }
29233
+ async function mergeTiers(home, ws) {
29234
+ let merged = null;
29235
+ for (const tier of ["user", "project", "local"]) {
29236
+ const choice = await readTier((0, settingsPaths_js_1.settingsFilePath)(tier, { homeDir: home, workspaceRoot: ws }));
29237
+ if (choice !== null)
29238
+ merged = choice;
29239
+ }
29240
+ return merged;
29241
+ }
29242
+ async function loadDuetExecutor2(opts = {}) {
29243
+ const home = opts.homeDir ?? os8.homedir();
29244
+ const ws = opts.workspaceRoot ?? null;
29245
+ const cacheKey = cacheKeyFor(home, ws);
29246
+ const hit = cache3.get(cacheKey);
29247
+ const now2 = Date.now();
29248
+ if (hit !== void 0 && now2 - hit.at < DUET_EXECUTOR_CACHE_TTL_MS)
29249
+ return hit.choice;
29250
+ const merged = await mergeTiers(home, ws);
29251
+ cache3.set(cacheKey, { at: now2, choice: merged });
29252
+ return merged;
29253
+ }
29254
+ async function setDuetExecutor2(choice, opts = {}) {
29255
+ const file = (0, settingsPaths_js_1.settingsFilePath)("user", opts);
29256
+ if (file === null)
29257
+ throw new Error("no user settings file");
29258
+ let root2 = {};
29259
+ try {
29260
+ const parsed = JSON.parse(await fs14.readFile(file, "utf8"));
29261
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
29262
+ root2 = parsed;
29263
+ }
29264
+ } catch {
29265
+ }
29266
+ const validated = choice === void 0 ? null : toChoice(choice);
29267
+ if (validated === null)
29268
+ delete root2.duetExecutor;
29269
+ else
29270
+ root2.duetExecutor = validated;
29271
+ await fs14.mkdir(path13.dirname(file), { recursive: true });
29272
+ await (0, atomicWrite_js_1.atomicWriteFile)(file, `${JSON.stringify(root2, null, 2)}
29273
+ `);
29274
+ clearDuetExecutorCache();
29275
+ }
29276
+ async function duetExecutorSource(opts = {}) {
29277
+ const home = opts.homeDir ?? os8.homedir();
29278
+ const ws = opts.workspaceRoot ?? null;
29279
+ let source2 = null;
29280
+ for (const tier of ["user", "project", "local"]) {
29281
+ const choice = await readTier((0, settingsPaths_js_1.settingsFilePath)(tier, { homeDir: home, workspaceRoot: ws }));
29282
+ if (choice !== null)
29283
+ source2 = tier;
29284
+ }
29285
+ return source2;
29286
+ }
29287
+ function revalidate(home, ws, cacheKey) {
29288
+ if (refreshing.has(cacheKey))
29289
+ return;
29290
+ const refresh = (async () => {
29291
+ const merged = await mergeTiers(home, ws);
29292
+ cache3.set(cacheKey, { at: Date.now(), choice: merged });
29293
+ })();
29294
+ refreshing.set(cacheKey, refresh.catch(() => {
29295
+ }).finally(() => {
29296
+ refreshing.delete(cacheKey);
29297
+ }));
29298
+ }
29299
+ function duetExecutorWireForSegment(workspaceRoot) {
29300
+ try {
29301
+ const home = os8.homedir();
29302
+ const ws = workspaceRoot ?? null;
29303
+ const cacheKey = cacheKeyFor(home, ws);
29304
+ const hit = cache3.get(cacheKey);
29305
+ if (hit === void 0 || Date.now() - hit.at >= DUET_EXECUTOR_CACHE_TTL_MS) {
29306
+ revalidate(home, ws, cacheKey);
29307
+ }
29308
+ if (hit === void 0 || hit.choice === null) {
29309
+ return { provider: duetPlanners_js_1.DUET_PLANNER_PROVIDERS[0], model: duetPlanners_js_1.DUET_EXECUTOR_DEFAULT_ID };
29310
+ }
29311
+ return {
29312
+ provider: hit.choice.provider,
29313
+ model: hit.choice.model,
29314
+ // Wire spelling is snake_case, like every other segment-body key.
29315
+ ...hit.choice.effort !== void 0 ? { effort: hit.choice.effort } : {},
29316
+ ...hit.choice.contextWindow !== void 0 ? { context_window: hit.choice.contextWindow } : {}
29317
+ };
29318
+ } catch {
29319
+ return void 0;
29320
+ }
29321
+ }
29322
+ async function prewarmDuetExecutor(workspaceRoot) {
29323
+ try {
29324
+ await loadDuetExecutor2({ workspaceRoot: workspaceRoot ?? null });
29325
+ } catch {
29326
+ }
29327
+ }
29328
+ }
29329
+ });
29330
+
29331
+ // ../packages/orion-client-core/dist/duetPlan.js
29332
+ var require_duetPlan = __commonJS({
29333
+ "../packages/orion-client-core/dist/duetPlan.js"(exports2) {
29334
+ "use strict";
29335
+ Object.defineProperty(exports2, "__esModule", { value: true });
29336
+ exports2.DUET_PLAN_MAX_FAILURES = exports2.DUET_ESCALATION_THRESHOLD = exports2.DUET_REPLAN_CAPABILITY = exports2.DUET_REPLAN_TOOL = exports2.DUET_PLAN_GRANTS = exports2.DUET_PLAN_MAX_VERSION = exports2.DUET_PLAN_MAX_LEN = void 0;
29337
+ exports2.createStandingPlan = createStandingPlan3;
29338
+ exports2.duetPlanWireForSegment = duetPlanWireForSegment;
29339
+ exports2.highRiskRequest = highRiskRequest;
29340
+ exports2.explicitPlanRequest = explicitPlanRequest;
29341
+ exports2.willRouteToExecution = willRouteToExecution2;
29342
+ exports2.invalidateStandingPlan = invalidateStandingPlan2;
29343
+ exports2.duetReplanCommandNote = duetReplanCommandNote2;
29344
+ exports2.duetReplanResult = duetReplanResult2;
29345
+ exports2.duetReplanFollowupPrompt = duetReplanFollowupPrompt2;
29346
+ exports2.recordDuetTurnOutcome = recordDuetTurnOutcome;
29347
+ exports2.foldDuetTurnEnd = foldDuetTurnEnd2;
29348
+ exports2.duetPhaseLine = duetPhaseLine2;
29349
+ exports2.DUET_PLAN_MAX_LEN = 65536;
29350
+ exports2.DUET_PLAN_MAX_VERSION = 1e4;
29351
+ exports2.DUET_PLAN_GRANTS = ["default", "workspace_write"];
29352
+ function createStandingPlan3(plan, previous, grantedPermission = "workspace_write") {
29353
+ const trimmed = plan.trim();
29354
+ if (trimmed === "" || trimmed.length > exports2.DUET_PLAN_MAX_LEN)
29355
+ return null;
29356
+ const version = Math.min((previous?.version ?? 0) + 1, exports2.DUET_PLAN_MAX_VERSION);
29357
+ return {
29358
+ plan: trimmed,
29359
+ version,
29360
+ standing: true,
29361
+ grantedPermission,
29362
+ planningFailures: 0,
29363
+ executorFailures: 0,
29364
+ scopeChanged: false,
29365
+ architectureDecisionRequired: false,
29366
+ userNegativeFeedback: false,
29367
+ escalated: false
29368
+ };
29369
+ }
29370
+ function duetPlanWireForSegment(record) {
29371
+ if (!record?.standing)
29372
+ return void 0;
29373
+ const plan = record.plan.trim();
29374
+ if (plan === "" || plan.length > exports2.DUET_PLAN_MAX_LEN)
29375
+ return void 0;
29376
+ if (record.version < 1 || record.version > exports2.DUET_PLAN_MAX_VERSION)
29377
+ return void 0;
29378
+ if (!exports2.DUET_PLAN_GRANTS.includes(record.grantedPermission))
29379
+ return void 0;
29380
+ return {
29381
+ standing: true,
29382
+ plan,
29383
+ version: record.version,
29384
+ granted_permission: record.grantedPermission,
29385
+ planning_failures: record.planningFailures,
29386
+ executor_failures: record.executorFailures,
29387
+ scope_changed: record.scopeChanged,
29388
+ architecture_decision_required: record.architectureDecisionRequired,
29389
+ user_negative_feedback: record.userNegativeFeedback,
29390
+ escalated: record.escalated
29391
+ };
29392
+ }
29393
+ var EXPLICIT_PLAN_WORDS = [
29394
+ "replan",
29395
+ "re-plan",
29396
+ "redesign",
29397
+ "re-design",
29398
+ "rethink",
29399
+ "re-think",
29400
+ "architect",
29401
+ // The architect-family nouns: a "short architectural change" must replan even under
29402
+ // a valid standing plan (the high-risk list only fires with NO plan).
29403
+ "architecture",
29404
+ "architectural",
29405
+ "new plan",
29406
+ "change the plan",
29407
+ "different approach",
29408
+ // The imperative plan/design shapes (bare "plan"/"design" are everyday words —
29409
+ // "the plan is working", "design doc" — so only request shapes match).
29410
+ "plan this",
29411
+ "plan the",
29412
+ "plan out",
29413
+ "make a plan",
29414
+ "write a plan",
29415
+ "design a",
29416
+ "design the",
29417
+ "design this"
29418
+ ];
29419
+ var HIGH_RISK_WORDS = [
29420
+ "migration",
29421
+ "migrate",
29422
+ "security",
29423
+ "auth",
29424
+ "authentication",
29425
+ "production",
29426
+ "deploy",
29427
+ "deployment",
29428
+ "database",
29429
+ "schema",
29430
+ "architecture",
29431
+ "infrastructure",
29432
+ "rewrite"
29433
+ ];
29434
+ function highRiskRequest(text) {
29435
+ const lower = text.toLowerCase();
29436
+ return HIGH_RISK_WORDS.some((word) => containsWord(lower, word));
29437
+ }
29438
+ function explicitPlanRequest(text) {
29439
+ const lower = text.toLowerCase();
29440
+ if (EXPLICIT_PLAN_WORDS.some((word) => containsWord(lower, word)))
29441
+ return true;
29442
+ const lead = lower.trimStart();
29443
+ return lead.startsWith("plan ") || lead.startsWith("design ");
29444
+ }
29445
+ function containsWord(lower, word) {
29446
+ let start2 = 0;
29447
+ for (; ; ) {
29448
+ const at = lower.indexOf(word, start2);
29449
+ if (at < 0)
29450
+ return false;
29451
+ const end = at + word.length;
29452
+ const beforeOk = at === 0 || !/[a-z0-9]/i.test(lower[at - 1] ?? "");
29453
+ const afterOk = !/[a-z0-9]/i.test(lower[end] ?? "");
29454
+ if (beforeOk && afterOk)
29455
+ return true;
29456
+ start2 = end;
29457
+ }
29458
+ }
29459
+ function willRouteToExecution2(record, text) {
29460
+ if (explicitPlanRequest(text))
29461
+ return false;
29462
+ if (duetPlanWireForSegment(record) === void 0)
29463
+ return !highRiskRequest(text);
29464
+ if (record.scopeChanged || record.architectureDecisionRequired)
29465
+ return false;
29466
+ if (record.planningFailures >= 2)
29467
+ return false;
29468
+ if (record.userNegativeFeedback)
29469
+ return false;
29470
+ return true;
29471
+ }
29472
+ exports2.DUET_REPLAN_TOOL = "request_replan";
29473
+ exports2.DUET_REPLAN_CAPABILITY = "duet_replan";
29474
+ function invalidateStandingPlan2(record) {
29475
+ if (!record?.standing)
29476
+ return record ?? null;
29477
+ return { ...record, scopeChanged: true };
29478
+ }
29479
+ function duetReplanCommandNote2(hadPlan) {
29480
+ return hadPlan ? "Standing plan invalidated \u2014 the next Duet request runs the planner." : 'No standing plan is active \u2014 ask for a plan (e.g. "plan this out") to run the planner.';
29481
+ }
29482
+ function duetReplanResult2(hadPlan) {
29483
+ return hadPlan ? "Standing plan invalidated. The planning model takes over on an automatic follow-up turn as soon as you finish \u2014 summarize where you stopped and why the plan no longer fits, then end the turn." : "No standing plan is active. The planning model takes over on an automatic follow-up turn as soon as you finish \u2014 summarize what this task needs and why, then end the turn.";
29484
+ }
29485
+ function duetReplanFollowupPrompt2(reason) {
29486
+ const trimmed = reason.trim().replace(/\s+/g, " ");
29487
+ const capped = trimmed.length > 500 ? `${trimmed.slice(0, 499)}\u2026` : trimmed;
29488
+ const cause = capped === "" ? "the executor reported the approved plan no longer fits" : `the executor reported the approved plan no longer fits: ${capped}`;
29489
+ return `Re-plan this task \u2014 ${cause}. Review the summary above, investigate what changed, and produce a fresh plan.`;
29490
+ }
29491
+ exports2.DUET_ESCALATION_THRESHOLD = 2;
29492
+ exports2.DUET_PLAN_MAX_FAILURES = 1e3;
29493
+ function recordDuetTurnOutcome(record, outcome) {
29494
+ if (!record?.standing)
29495
+ return record ?? null;
29496
+ if (outcome.ok) {
29497
+ if (!outcome.executionLeg)
29498
+ return record;
29499
+ return { ...record, executorFailures: 0, escalated: false };
29500
+ }
29501
+ if (outcome.executionLeg) {
29502
+ const executorFailures = Math.min(record.executorFailures + 1, exports2.DUET_PLAN_MAX_FAILURES);
29503
+ return {
29504
+ ...record,
29505
+ executorFailures,
29506
+ escalated: executorFailures >= exports2.DUET_ESCALATION_THRESHOLD
29507
+ };
29508
+ }
29509
+ return { ...record, planningFailures: Math.min(record.planningFailures + 1, exports2.DUET_PLAN_MAX_FAILURES) };
29510
+ }
29511
+ function foldDuetTurnEnd2(record, executionLeg, outcome) {
29512
+ if (outcome === "cancelled")
29513
+ return record ?? null;
29514
+ return recordDuetTurnOutcome(record, { executionLeg, ok: outcome === "completed" });
29515
+ }
29516
+ function duetPhaseLine2(phase, opts) {
29517
+ const base = phase === "planning" ? "Planning" : "Executing";
29518
+ return phase === "executing" && opts?.escalated ? `${base} \xB7 escalated` : base;
29519
+ }
29520
+ }
29521
+ });
29522
+
29094
29523
  // ../packages/orion-client-core/dist/interimModels.js
29095
29524
  var require_interimModels = __commonJS({
29096
29525
  "../packages/orion-client-core/dist/interimModels.js"(exports2) {
@@ -31547,6 +31976,8 @@ var require_segmentDriver = __commonJS({
31547
31976
  exports2.runToolBatch = runToolBatch;
31548
31977
  var node_events_1 = __require("node:events");
31549
31978
  var os8 = __importStar(__require("node:os"));
31979
+ var duetMode_js_1 = require_duetMode();
31980
+ var duetPlan_js_1 = require_duetPlan();
31550
31981
  var interimModels_js_1 = require_interimModels();
31551
31982
  var repoIdentity_js_1 = require_repoIdentity();
31552
31983
  var memoryIndex_js_1 = require_memoryIndex();
@@ -31894,6 +32325,12 @@ var require_segmentDriver = __commonJS({
31894
32325
  if (orionResources !== void 0)
31895
32326
  body2.orion_resources = orionResources;
31896
32327
  const interimModels = (0, interimModels_js_1.interimModelsWireForSegment)(start2.routing?.workspaceRoot);
32328
+ const duetExecutor = start2.routing?.mode === "duet" ? (0, duetMode_js_1.duetExecutorWireForSegment)(start2.routing?.workspaceRoot) : void 0;
32329
+ if (duetExecutor !== void 0)
32330
+ body2.duet_executor = duetExecutor;
32331
+ const duetPlan = start2.routing?.mode === "duet" ? (0, duetPlan_js_1.duetPlanWireForSegment)(start2.duetPlan) : void 0;
32332
+ if (duetPlan !== void 0)
32333
+ body2.duet_plan = duetPlan;
31897
32334
  if (interimModels !== void 0)
31898
32335
  body2.interim_models = interimModels;
31899
32336
  const repoIdentity = (0, repoIdentity_js_1.repoIdentityForSegment)(start2.routing?.workspaceRoot);
@@ -36205,7 +36642,7 @@ var require_agentManager = __commonJS({
36205
36642
  worktree = await this.createWorktree(parentSessionId, agentId);
36206
36643
  }
36207
36644
  const model = str(params.model) || resolveModelPreference(def.model, routing.model) || routing.model;
36208
- const readOnly = routing.mode === "plan" || routing.mode === "ask";
36645
+ const readOnly = routing.mode === "plan" || routing.mode === "ask" || routing.mode === "duet";
36209
36646
  const sessionId = await this.transport.startSession({
36210
36647
  provider: routing.provider,
36211
36648
  model,
@@ -49589,8 +50026,9 @@ var require_codebaseIndex = __commonJS({
49589
50026
  "../packages/orion-client-core/dist/codebaseIndex.js"(exports2) {
49590
50027
  "use strict";
49591
50028
  Object.defineProperty(exports2, "__esModule", { value: true });
49592
- exports2.WorkspaceIndexStore = exports2.CONTENT_PROBE_DEADLINE_MS = exports2.DEFAULT_RETRIEVAL_MODE = void 0;
50029
+ exports2.WorkspaceIndexStore = exports2.CONTENT_PROBE_DEADLINE_MS = exports2.RETRIEVAL_TOGGLE_ENABLED = exports2.DEFAULT_RETRIEVAL_MODE = void 0;
49593
50030
  exports2.normalizeRetrievalMode = normalizeRetrievalMode4;
50031
+ exports2.effectiveRetrievalMode = effectiveRetrievalMode;
49594
50032
  var contentChunkIndex_1 = require_contentChunkIndex();
49595
50033
  var linkExpansion_1 = require_linkExpansion();
49596
50034
  var pathIndex_1 = require_pathIndex();
@@ -49737,6 +50175,12 @@ var require_codebaseIndex = __commonJS({
49737
50175
  return value;
49738
50176
  return fallback;
49739
50177
  }
50178
+ exports2.RETRIEVAL_TOGGLE_ENABLED = false;
50179
+ function effectiveRetrievalMode(value) {
50180
+ if (!exports2.RETRIEVAL_TOGGLE_ENABLED)
50181
+ return "enhanced";
50182
+ return normalizeRetrievalMode4(value);
50183
+ }
49740
50184
  exports2.CONTENT_PROBE_DEADLINE_MS = 600;
49741
50185
  async function boundedAll(promises2, deadlineMs) {
49742
50186
  if (promises2.length === 0)
@@ -59842,7 +60286,7 @@ ${notes.join("\n\n")}`;
59842
60286
  });
59843
60287
  this.readState.record(readKey2, meta2, range2);
59844
60288
  const mode2 = readContextMode(params);
59845
- const retrievalMode2 = this.getRetrievalMode(sessionId);
60289
+ const retrievalMode2 = (0, codebaseIndex_1.effectiveRetrievalMode)(this.getRetrievalMode(sessionId));
59846
60290
  this.logRetrievalTool({
59847
60291
  sessionId,
59848
60292
  tool: "read_file",
@@ -59873,7 +60317,7 @@ ${notes.join("\n\n")}`;
59873
60317
  });
59874
60318
  this.readState.record(readKey, meta, range);
59875
60319
  const mode = readContextMode(params);
59876
- const retrievalMode = this.getRetrievalMode(sessionId);
60320
+ const retrievalMode = (0, codebaseIndex_1.effectiveRetrievalMode)(this.getRetrievalMode(sessionId));
59877
60321
  this.logRetrievalTool({
59878
60322
  sessionId,
59879
60323
  tool: "read_file",
@@ -59889,7 +60333,7 @@ ${notes.join("\n\n")}`;
59889
60333
  if (!this.codebaseIndex) {
59890
60334
  return NO_INDEX_GUIDANCE;
59891
60335
  }
59892
- const retrievalMode = this.getRetrievalMode(sessionId);
60336
+ const retrievalMode = (0, codebaseIndex_1.effectiveRetrievalMode)(this.getRetrievalMode(sessionId));
59893
60337
  this.logRetrievalTool({
59894
60338
  sessionId,
59895
60339
  tool: "search_codebase",
@@ -59915,7 +60359,7 @@ ${notes.join("\n\n")}`;
59915
60359
  if (!this.codebaseIndex) {
59916
60360
  return NO_INDEX_GUIDANCE;
59917
60361
  }
59918
- const retrievalMode = this.getRetrievalMode(sessionId);
60362
+ const retrievalMode = (0, codebaseIndex_1.effectiveRetrievalMode)(this.getRetrievalMode(sessionId));
59919
60363
  this.logRetrievalTool({
59920
60364
  sessionId,
59921
60365
  tool: "trace_codebase",
@@ -64306,7 +64750,8 @@ var require_manager = __commonJS({
64306
64750
  return `A work-graph run (${parent.activeRunId}) is already active in this conversation. Use work_run_status to watch it, work_run_amend to change it, or work_run_stop to end it.`;
64307
64751
  }
64308
64752
  const plan = params.plan;
64309
- const readOnly = parent.hooks.chatMode?.() === "plan";
64753
+ const mode = parent.hooks.chatMode?.();
64754
+ const readOnly = mode === "plan" || mode === "duet";
64310
64755
  const result = (0, validate_js_1.validateWorkPlan)(plan, parent.hooks.knownPersonas?.() ?? [], { readOnly });
64311
64756
  if (!result.valid) {
64312
64757
  return `The plan was REJECTED by the validator. Fix these and resubmit:
@@ -67038,6 +67483,9 @@ var require_dist = __commonJS({
67038
67483
  __exportStar(require_segmentDriver(), exports2);
67039
67484
  __exportStar(require_customProviders(), exports2);
67040
67485
  __exportStar(require_interimModels(), exports2);
67486
+ __exportStar(require_duetMode(), exports2);
67487
+ __exportStar(require_duetPlan(), exports2);
67488
+ __exportStar(require_duetPlanners(), exports2);
67041
67489
  __exportStar(require_repoIdentity(), exports2);
67042
67490
  __exportStar(require_customProviderModels(), exports2);
67043
67491
  __exportStar(require_cron(), exports2);
@@ -83690,8 +84138,8 @@ var Box2 = Box_default;
83690
84138
  var ScrollBox2 = ScrollBox_default;
83691
84139
 
83692
84140
  // src/main.tsx
83693
- var import_client_core42 = __toESM(require_dist(), 1);
83694
84141
  var import_client_core43 = __toESM(require_dist(), 1);
84142
+ var import_client_core44 = __toESM(require_dist(), 1);
83695
84143
  import { fileURLToPath as fileURLToPath3 } from "url";
83696
84144
  import * as os7 from "os";
83697
84145
  import { randomUUID as randomUUID3 } from "crypto";
@@ -84057,7 +84505,9 @@ var darkTheme = {
84057
84505
  diffAddBg: "#225c2b",
84058
84506
  diffRemoveBg: "#7a2936",
84059
84507
  autoAccept: "#3fb950",
84060
- planMode: "#38bdf8"
84508
+ planMode: "#38bdf8",
84509
+ duetMode: "#a78bfa",
84510
+ activeChoice: "#a78bfa"
84061
84511
  };
84062
84512
  var lightTheme = {
84063
84513
  name: "orion-light",
@@ -84108,7 +84558,9 @@ var lightTheme = {
84108
84558
  diffAddBg: "#a6f3b0",
84109
84559
  diffRemoveBg: "#ffc9d0",
84110
84560
  autoAccept: "#15803d",
84111
- planMode: "#267f99"
84561
+ planMode: "#267f99",
84562
+ duetMode: "#7c3aed",
84563
+ activeChoice: "#7c3aed"
84112
84564
  };
84113
84565
  var THEMES = {
84114
84566
  "orion-dark": darkTheme,
@@ -86078,13 +86530,28 @@ var ATTACH_MIME = {
86078
86530
  ".webp": "image/webp",
86079
86531
  ".pdf": "application/pdf"
86080
86532
  };
86081
- var MODES = ["code", "plan", "ask"];
86533
+ var MODES = ["code", "plan", "ask", "duet"];
86082
86534
  var PERMS = ["read_only", "default", "workspace_write", "full_access"];
86083
86535
  function applyMode(ctx, mode) {
86084
86536
  const sid = ctx.sessionId();
86085
86537
  if (!sid) return;
86086
86538
  ctx.appStore.setState((s) => ({ ...s, mode }));
86087
86539
  void ctx.bridge.rpc("set_mode", { session_id: sid, mode });
86540
+ if (mode === "duet" && !(0, import_client_core16.isDuetPlanner)(ctx.appStore.getState().model)) {
86541
+ void (async () => {
86542
+ let models = [];
86543
+ try {
86544
+ const res = await ctx.bridge.rpc(
86545
+ "list_models",
86546
+ { provider: "all" }
86547
+ );
86548
+ models = res.models ?? [];
86549
+ } catch {
86550
+ }
86551
+ const planner = (0, import_client_core16.resolveDuetPlanner)(import_client_core16.DUET_PLANNER_DEFAULT, models);
86552
+ await applyModel(ctx, sid, planner.model, planner.provider);
86553
+ })().catch(() => void 0);
86554
+ }
86088
86555
  }
86089
86556
  function applyPermissionMode(ctx, mode) {
86090
86557
  const sid = ctx.sessionId();
@@ -86095,6 +86562,9 @@ function applyPermissionMode(ctx, mode) {
86095
86562
  function cycleModePosture(ctx) {
86096
86563
  const st2 = ctx.appStore.getState();
86097
86564
  if (st2.mode === "plan") {
86565
+ applyMode(ctx, "duet");
86566
+ applyPermissionMode(ctx, "read_only");
86567
+ } else if (st2.mode === "duet") {
86098
86568
  applyMode(ctx, "code");
86099
86569
  applyPermissionMode(ctx, "workspace_write");
86100
86570
  } else if (st2.permissionMode === "full_access") {
@@ -86140,7 +86610,7 @@ async function applyModel(ctx, sid, modelId, provider, label, contextWindow) {
86140
86610
  }
86141
86611
  ctx.print(`Model set to ${lbl}${provider ? ` \xB7 ${providerLabel(provider)}` : ""}`);
86142
86612
  }
86143
- async function openInterimModelPicker(ctx, slot, workspaceRoot) {
86613
+ async function openPlatformModelPicker(ctx, opts) {
86144
86614
  let models = [];
86145
86615
  try {
86146
86616
  const res = await ctx.bridge.rpc("list_models", {
@@ -86149,13 +86619,16 @@ async function openInterimModelPicker(ctx, slot, workspaceRoot) {
86149
86619
  models = res.models ?? [];
86150
86620
  } catch {
86151
86621
  }
86152
- const config = await (0, import_client_core16.loadInterimModels)({ workspaceRoot });
86153
- const active = config[slot.key];
86622
+ const active = opts.active;
86154
86623
  const options = [
86155
86624
  {
86156
- label: import_client_core16.INTERIM_DEFAULT_LABEL,
86157
- value: "__primary",
86158
- hint: active ? "" : "(active)"
86625
+ label: opts.defaultLabel,
86626
+ value: "__default",
86627
+ // "(reset)" when something else is active — the row is an ACTION (go back to
86628
+ // the default), and a bare default label beside a current choice reads like a
86629
+ // status line claiming nothing is selected.
86630
+ hint: active ? "(reset)" : "(active)",
86631
+ accent: active === void 0
86159
86632
  }
86160
86633
  ];
86161
86634
  const providerOf = {};
@@ -86173,37 +86646,49 @@ async function openInterimModelPicker(ctx, slot, workspaceRoot) {
86173
86646
  modelOf[key] = m2.id;
86174
86647
  labelOf[key] = m2.label ?? formatModelName(m2.id);
86175
86648
  const isActive = active !== void 0 && active.model === m2.id && active.provider === prov;
86176
- options.push({ label: m2.label ?? m2.id, value: key, hint: isActive ? "(active)" : m2.id });
86649
+ options.push({ label: m2.label ?? m2.id, value: key, hint: isActive ? "(active)" : m2.id, accent: isActive });
86177
86650
  }
86651
+ const currentLabel = active ? labelOf[`${active.provider}/${active.model}`] ?? formatModelName(active.model) : opts.defaultLabel;
86178
86652
  ctx.appStore.setState((s) => ({
86179
86653
  ...s,
86180
86654
  activeDialog: {
86181
86655
  kind: "select",
86182
- title: `${slot.label} \u2014 select a model`,
86656
+ title: `${opts.title} \xB7 current: ${currentLabel}`,
86183
86657
  options,
86184
86658
  onSelect: (value) => {
86185
86659
  ctx.appStore.setState((s2) => ({ ...s2, activeDialog: null }));
86186
86660
  if (!value) return;
86187
86661
  void (async () => {
86188
- if (value === "__primary") await (0, import_client_core16.setInterimModel)(slot.key, void 0);
86189
- else if (modelOf[value] !== void 0) {
86190
- await (0, import_client_core16.setInterimModel)(slot.key, {
86191
- provider: providerOf[value] ?? "",
86192
- model: modelOf[value]
86193
- });
86194
- } else return;
86195
- ctx.print(
86196
- value === "__primary" ? `${slot.label} reset to the primary active model` : `${slot.label} model set to ${labelOf[value] ?? modelOf[value]}`
86197
- );
86662
+ if (value === "__default") {
86663
+ ctx.print(await opts.save(void 0, opts.defaultLabel));
86664
+ } else if (modelOf[value] !== void 0) {
86665
+ ctx.print(
86666
+ await opts.save(
86667
+ { provider: providerOf[value] ?? "", model: modelOf[value] },
86668
+ labelOf[value] ?? modelOf[value]
86669
+ )
86670
+ );
86671
+ }
86198
86672
  })().catch(
86199
- (e) => ctx.print(
86200
- `Could not save the interim-model choice: ${e instanceof Error ? e.message : String(e)}`
86201
- )
86673
+ (e) => ctx.print(`${opts.saveErrorPrefix}: ${e instanceof Error ? e.message : String(e)}`)
86202
86674
  );
86203
86675
  }
86204
86676
  }
86205
86677
  }));
86206
86678
  }
86679
+ async function openInterimModelPicker(ctx, slot, workspaceRoot) {
86680
+ const config = await (0, import_client_core16.loadInterimModels)({ workspaceRoot });
86681
+ await openPlatformModelPicker(ctx, {
86682
+ title: `${slot.label} \u2014 select a model`,
86683
+ defaultLabel: import_client_core16.INTERIM_DEFAULT_LABEL,
86684
+ active: config[slot.key],
86685
+ save: async (pick, label) => {
86686
+ await (0, import_client_core16.setInterimModel)(slot.key, pick);
86687
+ return pick === void 0 ? `${slot.label} reset to the primary active model` : `${slot.label} model set to ${label}`;
86688
+ },
86689
+ saveErrorPrefix: "Could not save the interim-model choice"
86690
+ });
86691
+ }
86207
86692
  function promptReasoning(ctx, sid, modelLabel, reasoning) {
86208
86693
  const levels = reasoning.levels.filter((l3) => l3 !== "off");
86209
86694
  if (levels.length === 0) return;
@@ -86547,30 +87032,95 @@ function registerBuiltins(registry) {
86547
87032
  if (m2.reasoning && m2.reasoning.levels?.length) reasoningOf[key] = m2.reasoning;
86548
87033
  if (m2.context_window && m2.context_window > 0) windowOf[key] = m2.context_window;
86549
87034
  }
87035
+ const duet = ctx.appStore.getState().mode === "duet";
87036
+ const duetExecutor = duet ? await (0, import_client_core16.loadDuetExecutor)({ workspaceRoot: ctx.config?.workspaceRoot }).catch(() => null) : null;
86550
87037
  const opts = [];
87038
+ if (duet) {
87039
+ const plannerLabel = models.find((m2) => m2.id === current2)?.label ?? import_client_core16.DUET_PLANNER_LABELS[current2] ?? formatModelName(current2);
87040
+ opts.push({ label: "Plan \u2014 ", value: "__sep_plan", separator: true, accentSuffix: plannerLabel });
87041
+ for (const id of import_client_core16.DUET_PLANNER_IDS) {
87042
+ let entry;
87043
+ for (const prov2 of import_client_core16.DUET_PLANNER_PROVIDERS) {
87044
+ entry = models.find((m2) => m2.id === id && (m2.provider ?? "") === prov2);
87045
+ if (entry) break;
87046
+ }
87047
+ const prov = entry?.provider ?? import_client_core16.DUET_PLANNER_PROVIDERS[0];
87048
+ const label = entry?.label ?? import_client_core16.DUET_PLANNER_LABELS[id] ?? formatModelName(id);
87049
+ const key = `${prov}/${id}`;
87050
+ modelOf[`plan|${key}`] = id;
87051
+ providerOf[`plan|${key}`] = prov;
87052
+ labelOf[`plan|${key}`] = label;
87053
+ if (entry?.reasoning?.levels?.length) reasoningOf[`plan|${key}`] = entry.reasoning;
87054
+ if (entry?.context_window) windowOf[`plan|${key}`] = entry.context_window;
87055
+ opts.push({
87056
+ label,
87057
+ value: `plan|${key}`,
87058
+ // Role-tagged: the search filter flattens sections away, and a planner
87059
+ // can also appear in the executor catalog with an identical label —
87060
+ // the hint is what keeps the two rows tellable apart.
87061
+ hint: current2 === id ? "planner (active)" : "planner",
87062
+ accent: current2 === id
87063
+ });
87064
+ }
87065
+ const executorLabel = duetExecutor ? models.find(
87066
+ (m2) => m2.id === duetExecutor.model && ((m2.provider ?? "") === duetExecutor.provider || duetExecutor.provider === "")
87067
+ )?.label ?? duetExecutor.model : import_client_core16.DUET_EXECUTOR_DEFAULT_LABEL;
87068
+ opts.push({ label: "Executor \u2014 ", value: "__sep_exec", separator: true, accentSuffix: executorLabel });
87069
+ opts.push({
87070
+ label: `Default \u2014 ${import_client_core16.DUET_EXECUTOR_DEFAULT_LABEL}`,
87071
+ value: "exec|__default",
87072
+ hint: duetExecutor === null ? "(active)" : "(reset)",
87073
+ accent: duetExecutor === null
87074
+ });
87075
+ }
86551
87076
  let lastProvider;
86552
87077
  for (const m2 of models) {
86553
87078
  const prov = m2.provider ?? currentProvider;
86554
87079
  if (prov !== lastProvider) {
86555
- opts.push({ label: providerLabel(prov), value: `__sep_${prov}`, separator: true });
87080
+ opts.push({
87081
+ label: duet ? ` ${providerLabel(prov)}` : providerLabel(prov),
87082
+ value: `__sep_${prov}`,
87083
+ separator: true
87084
+ });
86556
87085
  lastProvider = prov;
86557
87086
  }
86558
- const active = m2.id === current2 && prov === currentProvider;
87087
+ const active = duet ? !!duetExecutor && duetExecutor.model === m2.id && (duetExecutor.provider === prov || duetExecutor.provider === "") : m2.id === current2 && prov === currentProvider;
86559
87088
  opts.push({
86560
87089
  label: m2.label ?? m2.id,
86561
- value: `${prov}/${m2.id}`,
86562
- hint: active ? "(active)" : m2.id
87090
+ value: duet ? `exec|${prov}/${m2.id}` : `${prov}/${m2.id}`,
87091
+ hint: active ? "(active)" : m2.id,
87092
+ accent: active
86563
87093
  });
86564
87094
  }
86565
87095
  ctx.appStore.setState((s) => ({
86566
87096
  ...s,
86567
87097
  activeDialog: {
86568
87098
  kind: "model",
86569
- title: "Select a model",
87099
+ title: duet ? "Select models \u2014 Plan \xB7 Executor" : "Select a model",
86570
87100
  options: opts,
86571
87101
  onSelect: (v2) => {
86572
87102
  ctx.appStore.setState((s2) => ({ ...s2, activeDialog: null }));
86573
87103
  if (!v2) return;
87104
+ if (v2 === "exec|__default") {
87105
+ void (0, import_client_core16.setDuetExecutor)(void 0).then(
87106
+ () => ctx.print(
87107
+ `Duet executor reset \u2014 approved plans execute on ${import_client_core16.DUET_EXECUTOR_DEFAULT_LABEL} (default)`
87108
+ )
87109
+ ).catch(
87110
+ (e) => ctx.print(`Could not save the Duet executor: ${e instanceof Error ? e.message : String(e)}`)
87111
+ );
87112
+ return;
87113
+ }
87114
+ if (v2.startsWith("exec|")) {
87115
+ const key = v2.slice("exec|".length);
87116
+ const slash = key.indexOf("/");
87117
+ const provider = key.slice(0, slash);
87118
+ const id = key.slice(slash + 1);
87119
+ void (0, import_client_core16.setDuetExecutor)({ provider, model: id }).then(() => ctx.print(`Duet executor set to ${labelOf[key] ?? formatModelName(id)}`)).catch(
87120
+ (e) => ctx.print(`Could not save the Duet executor: ${e instanceof Error ? e.message : String(e)}`)
87121
+ );
87122
+ return;
87123
+ }
86574
87124
  const modelId = modelOf[v2] ?? v2;
86575
87125
  void applyModel(ctx, sid, modelId, providerOf[v2], labelOf[v2], windowOf[v2]).then(() => {
86576
87126
  const r2 = reasoningOf[v2];
@@ -86649,6 +87199,27 @@ function registerBuiltins(registry) {
86649
87199
  }));
86650
87200
  }
86651
87201
  },
87202
+ {
87203
+ kind: "local",
87204
+ name: "duet-executor",
87205
+ aliases: ["executor", "auto-executor"],
87206
+ description: "Choose the model that executes approved plans in Duet mode",
87207
+ keywords: ["model", "auto", "duet", "plan", "execute"],
87208
+ run: async (_args, ctx) => {
87209
+ const workspaceRoot = ctx.config?.workspaceRoot;
87210
+ const active = await (0, import_client_core16.loadDuetExecutor)({ workspaceRoot });
87211
+ await openPlatformModelPicker(ctx, {
87212
+ title: `${import_client_core16.DUET_EXECUTOR_INFO.label} \u2014 select a model`,
87213
+ defaultLabel: import_client_core16.DUET_EXECUTOR_DEFAULT_LABEL,
87214
+ active: active ?? void 0,
87215
+ save: async (pick, label) => {
87216
+ await (0, import_client_core16.setDuetExecutor)(pick);
87217
+ return pick === void 0 ? `Duet executor reset \u2014 approved plans execute on ${import_client_core16.DUET_EXECUTOR_DEFAULT_LABEL} (default)` : `Duet executor set to ${label}`;
87218
+ },
87219
+ saveErrorPrefix: "Could not save the Duet executor"
87220
+ });
87221
+ }
87222
+ },
86652
87223
  {
86653
87224
  kind: "local",
86654
87225
  name: "endpoint",
@@ -86800,17 +87371,17 @@ Use one: /endpoint use <name> [model] \xB7 remove: /endpoint remove <name>`
86800
87371
  {
86801
87372
  kind: "local",
86802
87373
  name: "mode",
86803
- description: "Set mode (code|plan|ask)",
87374
+ description: "Set mode (code|plan|ask|duet)",
86804
87375
  argumentHint: "<mode>",
86805
87376
  run: async (args2, ctx) => {
86806
87377
  const sid = ctx.sessionId();
86807
- const mode = args2.trim();
87378
+ const typed = args2.trim().toLowerCase();
87379
+ const mode = typed === "auto" ? "duet" : typed;
86808
87380
  if (!sid || !MODES.includes(mode)) {
86809
- ctx.print("Usage: /mode code|plan|ask");
87381
+ ctx.print("Usage: /mode code|plan|ask|duet (auto = duet)");
86810
87382
  return;
86811
87383
  }
86812
- await ctx.bridge.rpc("set_mode", { session_id: sid, mode });
86813
- ctx.appStore.setState((s) => ({ ...s, mode }));
87384
+ applyMode(ctx, mode);
86814
87385
  ctx.print(`Mode set to ${mode}`);
86815
87386
  }
86816
87387
  },
@@ -87038,22 +87609,27 @@ Use one: /endpoint use <name> [model] \xB7 remove: /endpoint remove <name>`
87038
87609
  if (requested !== "off") ctx.print(`Index mode: ${requested}`);
87039
87610
  }
87040
87611
  },
87041
- {
87042
- kind: "local",
87043
- name: "retrieval",
87044
- description: "Toggle enhanced retrieval",
87045
- argumentHint: "[default|enhanced|toggle]",
87046
- run: (args2, ctx) => {
87047
- const current2 = (0, import_client_core14.normalizeRetrievalMode)(ctx.appStore.getState().retrievalMode, "default");
87048
- const requested = args2.trim();
87049
- if (!requested || requested.toLowerCase() === "status") {
87050
- return ctx.printInfo(retrievalView(current2));
87051
- }
87052
- const next = parseRetrievalModeArg(requested, current2);
87053
- if (!next) return ctx.print("Usage: /retrieval [default|enhanced|toggle]");
87054
- applyRetrievalMode(ctx, next);
87055
- }
87056
- },
87612
+ // ORION: `/retrieval` is hidden while enhanced retrieval is always on. The
87613
+ // command is kept intact — flipping RETRIEVAL_TOGGLE_ENABLED back to true in
87614
+ // orion-client-core restores it in this list with no other change.
87615
+ ...import_client_core14.RETRIEVAL_TOGGLE_ENABLED ? [
87616
+ {
87617
+ kind: "local",
87618
+ name: "retrieval",
87619
+ description: "Toggle enhanced retrieval",
87620
+ argumentHint: "[default|enhanced|toggle]",
87621
+ run: (args2, ctx) => {
87622
+ const current2 = (0, import_client_core14.normalizeRetrievalMode)(ctx.appStore.getState().retrievalMode, "default");
87623
+ const requested = args2.trim();
87624
+ if (!requested || requested.toLowerCase() === "status") {
87625
+ return ctx.printInfo(retrievalView(current2));
87626
+ }
87627
+ const next = parseRetrievalModeArg(requested, current2);
87628
+ if (!next) return ctx.print("Usage: /retrieval [default|enhanced|toggle]");
87629
+ applyRetrievalMode(ctx, next);
87630
+ }
87631
+ }
87632
+ ] : [],
87057
87633
  {
87058
87634
  kind: "local",
87059
87635
  name: "theme",
@@ -88326,6 +88902,8 @@ function initialAppState(partial) {
88326
88902
  error: null,
88327
88903
  pendingPermissions: [],
88328
88904
  pendingPlanApproval: null,
88905
+ duetExecutionStarted: false,
88906
+ duetPlan: null,
88329
88907
  pendingAskUser: null,
88330
88908
  pendingWorkPlan: null,
88331
88909
  pendingFeedback: null,
@@ -88416,9 +88994,44 @@ function resumedRouting(current2, saved) {
88416
88994
  };
88417
88995
  }
88418
88996
 
88419
- // src/events/renderLane.ts
88997
+ // src/components/messages/duetPhaseNote.ts
88998
+ var import_chalk3 = __toESM(require_source(), 1);
88420
88999
  var import_client_core19 = __toESM(require_dist(), 1);
88421
89000
 
89001
+ // src/components/design-system/GradientText.tsx
89002
+ var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
89003
+ var GRAD_FROM = [183, 148, 246];
89004
+ var GRAD_TO = [230, 218, 252];
89005
+ var hex2 = (v2) => Math.max(0, Math.min(255, Math.round(v2))).toString(16).padStart(2, "0");
89006
+ function gradientAt(t) {
89007
+ const c3 = Math.max(0, Math.min(1, t));
89008
+ return `#${hex2(GRAD_FROM[0] + (GRAD_TO[0] - GRAD_FROM[0]) * c3)}${hex2(
89009
+ GRAD_FROM[1] + (GRAD_TO[1] - GRAD_FROM[1]) * c3
89010
+ )}${hex2(GRAD_FROM[2] + (GRAD_TO[2] - GRAD_FROM[2]) * c3)}`;
89011
+ }
89012
+ function GradientText({
89013
+ text,
89014
+ wrap: wrap2
89015
+ }) {
89016
+ const chars = [...text];
89017
+ const last = Math.max(1, chars.length - 1);
89018
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text2, { wrap: wrap2, children: chars.map((ch, i2) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Text2, { color: gradientAt(i2 / last), children: ch }, i2)) });
89019
+ }
89020
+
89021
+ // src/components/messages/duetPhaseNote.ts
89022
+ function duetPhaseNoteText(phase, opts) {
89023
+ const line = (0, import_client_core19.duetPhaseLine)(phase, opts);
89024
+ const sep4 = line.indexOf(" \xB7 ");
89025
+ const verb = [...sep4 === -1 ? line : line.slice(0, sep4)];
89026
+ const last = Math.max(1, verb.length - 1);
89027
+ const styled = verb.map((ch, i2) => import_chalk3.default.hex(gradientAt(i2 / last))(ch)).join("");
89028
+ const lifted = `\x1B[22m${styled}\x1B[2m`;
89029
+ return sep4 === -1 ? lifted : lifted + line.slice(sep4);
89030
+ }
89031
+
89032
+ // src/events/renderLane.ts
89033
+ var import_client_core20 = __toESM(require_dist(), 1);
89034
+
88422
89035
  // src/services/persistence.ts
88423
89036
  import * as path9 from "path";
88424
89037
  import * as fs10 from "fs";
@@ -88736,12 +89349,12 @@ function renderLane(transcript, app, ev) {
88736
89349
  }
88737
89350
  case "file_modified":
88738
89351
  if (d2.memory === true) {
88739
- const label = d2.memory_tier === "working" ? `Recursive learning \xB7 ${(0, import_client_core19.memorySlug)(String(d2.path ?? ""))}` : `Memory updated \xB7 ${(0, import_client_core19.memorySlug)(String(d2.path ?? ""))}`;
89352
+ const label = d2.memory_tier === "working" ? `Recursive learning \xB7 ${(0, import_client_core20.memorySlug)(String(d2.path ?? ""))}` : `Memory updated \xB7 ${(0, import_client_core20.memorySlug)(String(d2.path ?? ""))}`;
88740
89353
  transcript.setState((s) => appendNote(s, label));
88741
89354
  break;
88742
89355
  }
88743
89356
  if (d2.scratch === true) {
88744
- const label = typeof d2.scratch_path === "string" && d2.scratch_path ? d2.scratch_path : (0, import_client_core19.scratchLabel)(String(d2.path ?? ""));
89357
+ const label = typeof d2.scratch_path === "string" && d2.scratch_path ? d2.scratch_path : (0, import_client_core20.scratchLabel)(String(d2.path ?? ""));
88745
89358
  transcript.setState(
88746
89359
  (s) => appendNote(s, `Scratch \xB7 ${label}`, {
88747
89360
  insertions: typeof d2.insertions === "number" ? d2.insertions : 0,
@@ -88758,7 +89371,7 @@ function renderLane(transcript, app, ev) {
88758
89371
  deletions: typeof d2.deletions === "number" ? d2.deletions : 0,
88759
89372
  deleted: d2.deleted === true,
88760
89373
  affectedFiles: Array.isArray(d2.affected_files) ? d2.affected_files.filter((p) => typeof p === "string") : void 0,
88761
- trust: (0, import_client_core19.parseTrust)(d2.trust)
89374
+ trust: (0, import_client_core20.parseTrust)(d2.trust)
88762
89375
  })
88763
89376
  );
88764
89377
  break;
@@ -88825,7 +89438,7 @@ function renderLane(transcript, app, ev) {
88825
89438
  break;
88826
89439
  }
88827
89440
  case "input_guard": {
88828
- const card = (0, import_client_core19.parseInputGuardEvent)(d2);
89441
+ const card = (0, import_client_core20.parseInputGuardEvent)(d2);
88829
89442
  if (card) transcript.setState((s) => appendInputGuard(s, card));
88830
89443
  break;
88831
89444
  }
@@ -88858,7 +89471,7 @@ function renderLane(transcript, app, ev) {
88858
89471
  break;
88859
89472
  case "compaction_complete": {
88860
89473
  app.setState((s) => s.status === "streaming" ? { ...s, statusText: "thinking\u2026" } : s);
88861
- const compaction = (0, import_client_core19.parseUserCompaction)(d2);
89474
+ const compaction = (0, import_client_core20.parseUserCompaction)(d2);
88862
89475
  if (compaction) transcript.setState((s) => appendCompaction(s, compaction));
88863
89476
  break;
88864
89477
  }
@@ -88916,7 +89529,7 @@ function renderLane(transcript, app, ev) {
88916
89529
  // …and the parked ask future
88917
89530
  }));
88918
89531
  } else {
88919
- const quota = (0, import_client_core19.parseQuotaRefusal)(d2);
89532
+ const quota = (0, import_client_core20.parseQuotaRefusal)(d2);
88920
89533
  transcript.setState(
88921
89534
  (s) => quota ? appendQuota(applyTurnError(s, data), quota) : applyTurnError(s, data)
88922
89535
  );
@@ -88978,7 +89591,7 @@ function isOutOfBandEvent(event) {
88978
89591
  }
88979
89592
 
88980
89593
  // src/state/steerLifecycle.ts
88981
- var import_client_core20 = __toESM(require_dist(), 1);
89594
+ var import_client_core21 = __toESM(require_dist(), 1);
88982
89595
  function drainSteersForSegment(app, transcript) {
88983
89596
  const steers = app.getState().queuedMessages.filter((q2) => q2.kind === "steer");
88984
89597
  if (steers.length === 0) return [];
@@ -89010,7 +89623,7 @@ function settleSteerQueue(deps2) {
89010
89623
  if (deps2.isBusy()) return;
89011
89624
  const leftovers = deps2.app.getState().queuedMessages.filter((q2) => q2.kind === "steer");
89012
89625
  if (leftovers.length === 0) return;
89013
- const prompt = (0, import_client_core20.promoteLeftoverSteers)(leftovers.map((q2) => q2.text));
89626
+ const prompt = (0, import_client_core21.promoteLeftoverSteers)(leftovers.map((q2) => q2.text));
89014
89627
  deps2.app.setState((s) => ({
89015
89628
  ...s,
89016
89629
  queuedMessages: s.queuedMessages.filter((q2) => q2.kind !== "steer")
@@ -89097,7 +89710,7 @@ function makeGoalRunTurn(deps2) {
89097
89710
  }
89098
89711
 
89099
89712
  // src/events/boundaryHandlers.ts
89100
- var import_client_core21 = __toESM(require_dist(), 1);
89713
+ var import_client_core22 = __toESM(require_dist(), 1);
89101
89714
  var import_client_ui_core4 = __toESM(require_dist2(), 1);
89102
89715
  function createBoundaryHandlers(deps2) {
89103
89716
  const {
@@ -89117,7 +89730,7 @@ function createBoundaryHandlers(deps2) {
89117
89730
  onEvent,
89118
89731
  runTool: (req, s, ctx) => executor.run(req, s, ctx),
89119
89732
  onPermission: async (req) => {
89120
- const addDirCandidate = req.reason_code === "outside_working_directories" && typeof req.blocked_path === "string" ? await (0, import_client_core21.directoryForBlockedPath)(req.blocked_path) : void 0;
89733
+ const addDirCandidate = req.reason_code === "outside_working_directories" && typeof req.blocked_path === "string" ? await (0, import_client_core22.directoryForBlockedPath)(req.blocked_path) : void 0;
89121
89734
  if (bridge.isTurboModeEnabledForSession(sid)) {
89122
89735
  if (fullyAutomatic && req.reason_code === "protected_path") {
89123
89736
  return { decision: "deny", auto: true };
@@ -89205,7 +89818,7 @@ function createBoundaryHandlers(deps2) {
89205
89818
  // a human at it. Only a genuinely UNATTENDED run (headless: no UI to draw a card on) gets
89206
89819
  // the standing instruction, because there a card would wait forever.
89207
89820
  onAskUser: (req) => {
89208
- if (unattended) return Promise.resolve((0, import_client_core21.answerAll)(req, import_client_core21.ASK_NO_INTERACTIVE_USER));
89821
+ if (unattended) return Promise.resolve((0, import_client_core22.answerAll)(req, import_client_core22.ASK_NO_INTERACTIVE_USER));
89209
89822
  appStore.setState((s) => ({
89210
89823
  ...s,
89211
89824
  pendingAskUser: { requestId: req.request_id, request: req, sessionId: sid }
@@ -89262,6 +89875,23 @@ function createBoundaryHandlers(deps2) {
89262
89875
  const resolve5 = planResolvers.get(requestId);
89263
89876
  planResolvers.delete(requestId);
89264
89877
  resolve5?.({ decision });
89878
+ if (appStore.getState().mode === "duet") {
89879
+ const approved = decision === "auto" || decision === "manual";
89880
+ const pendingPlanText = appStore.getState().pendingPlanApproval?.plan ?? "";
89881
+ appStore.setState((s) => ({
89882
+ ...s,
89883
+ pendingPlanApproval: null,
89884
+ ...approved ? { duetExecutionStarted: true } : {},
89885
+ // A STANDING grant (auto-accept, human by construction — this resolver IS the
89886
+ // card) mints/refreshes the standing plan: the record routed planning reads on
89887
+ // following turns. Manual approve stays per-turn.
89888
+ ...decision === "auto" ? { duetPlan: (0, import_client_core22.createStandingPlan)(pendingPlanText, s.duetPlan) ?? s.duetPlan } : {}
89889
+ }));
89890
+ if (approved) {
89891
+ deps2.duetExecutingNote?.();
89892
+ }
89893
+ return;
89894
+ }
89265
89895
  if (decision === "auto") {
89266
89896
  appStore.setState((s) => ({
89267
89897
  ...s,
@@ -89297,7 +89927,7 @@ function ringBell(out2 = process.stdout) {
89297
89927
  }
89298
89928
 
89299
89929
  // src/services/loopService.ts
89300
- var import_client_core22 = __toESM(require_dist(), 1);
89930
+ var import_client_core23 = __toESM(require_dist(), 1);
89301
89931
  import { promises as fs11 } from "fs";
89302
89932
  import { dirname as dirname5, join as join9 } from "path";
89303
89933
  function loopSchedulePersistence(path13) {
@@ -89328,18 +89958,18 @@ var LoopService = class {
89328
89958
  started = false;
89329
89959
  constructor(deps2) {
89330
89960
  this.deps = deps2;
89331
- this.approvals = new import_client_core22.LoopApprovalStore(deps2.workspaceRoot);
89332
- this.runs = new import_client_core22.LoopRunStore(deps2.workspaceRoot);
89333
- this.runner = new import_client_core22.LoopRunner({
89961
+ this.approvals = new import_client_core23.LoopApprovalStore(deps2.workspaceRoot);
89962
+ this.runs = new import_client_core23.LoopRunStore(deps2.workspaceRoot);
89963
+ this.runner = new import_client_core23.LoopRunner({
89334
89964
  transport: deps2.transport,
89335
89965
  tools: deps2.tools,
89336
89966
  store: this.runs,
89337
- leases: new import_client_core22.LoopLeaseStore(deps2.workspaceRoot),
89967
+ leases: new import_client_core23.LoopLeaseStore(deps2.workspaceRoot),
89338
89968
  baseRouting: deps2.baseRouting,
89339
- anchorResolver: () => new import_client_core22.FilesystemAnchorResolver(deps2.workspaceRoot),
89969
+ anchorResolver: () => new import_client_core23.FilesystemAnchorResolver(deps2.workspaceRoot),
89340
89970
  notify: deps2.notify
89341
89971
  });
89342
- this.schedule = new import_client_core22.LoopSchedule({
89972
+ this.schedule = new import_client_core23.LoopSchedule({
89343
89973
  persistence: loopSchedulePersistence(deps2.schedulePath),
89344
89974
  onFire: (name2) => void this.fire(name2),
89345
89975
  isBusy: deps2.isBusy
@@ -89361,11 +89991,11 @@ var LoopService = class {
89361
89991
  }
89362
89992
  /** Re-read the declaration files and re-reconcile what is scheduled. */
89363
89993
  async reload() {
89364
- const { decls, issues } = await (0, import_client_core22.loadLoopDecls)(this.deps.workspaceRoot);
89994
+ const { decls, issues } = await (0, import_client_core23.loadLoopDecls)(this.deps.workspaceRoot);
89365
89995
  this.decls = decls;
89366
89996
  this.issues = issues;
89367
89997
  this.approvals.invalidate();
89368
- await this.schedule.syncFromDecls(await (0, import_client_core22.withApprovalStatus)(decls.values(), this.approvals));
89998
+ await this.schedule.syncFromDecls(await (0, import_client_core23.withApprovalStatus)(decls.values(), this.approvals));
89369
89999
  void this.runner.sweepDanglingParks();
89370
90000
  }
89371
90001
  /** Problems found while loading declarations — shown in `/loops` so a typo is visible
@@ -89375,7 +90005,7 @@ var LoopService = class {
89375
90005
  }
89376
90006
  /** Everything `/loops` renders. */
89377
90007
  async rows() {
89378
- const entries = await (0, import_client_core22.withApprovalStatus)(this.decls.values(), this.approvals);
90008
+ const entries = await (0, import_client_core23.withApprovalStatus)(this.decls.values(), this.approvals);
89379
90009
  const nextFire = await this.schedule.nextFireTimes();
89380
90010
  const active = new Set(this.runner.activeRuns().map((r2) => r2.loop));
89381
90011
  const rows = [];
@@ -89515,13 +90145,13 @@ var import_react27 = __toESM(require_react(), 1);
89515
90145
  var import_react23 = __toESM(require_react(), 1);
89516
90146
 
89517
90147
  // src/components/messages/UserText.tsx
89518
- var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
90148
+ var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
89519
90149
  function UserText({
89520
90150
  text,
89521
90151
  pending = false
89522
90152
  }) {
89523
90153
  const theme = useTheme();
89524
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Box2, { marginTop: 1, flexDirection: "row", paddingRight: 1, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Box2, { flexGrow: 1, flexShrink: 1, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
90154
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box2, { marginTop: 1, flexDirection: "row", paddingRight: 1, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box2, { flexGrow: 1, flexShrink: 1, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
89525
90155
  Text2,
89526
90156
  {
89527
90157
  backgroundColor: pending ? void 0 : theme.userBg,
@@ -89538,22 +90168,22 @@ function UserText({
89538
90168
  }
89539
90169
 
89540
90170
  // src/components/messages/UserCommand.tsx
89541
- var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
90171
+ var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
89542
90172
  function UserCommand({ name: name2, args: args2 }) {
89543
90173
  const theme = useTheme();
89544
90174
  const content = `/${[name2, args2].filter(Boolean).join(" ")}`;
89545
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box2, { marginTop: 1, flexDirection: "row", paddingRight: 1, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Box2, { flexGrow: 1, flexShrink: 1, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text2, { backgroundColor: theme.userBg, wrap: "wrap", children: [
89546
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Text2, { color: theme.dim, children: [
90175
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Box2, { marginTop: 1, flexDirection: "row", paddingRight: 1, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Box2, { flexGrow: 1, flexShrink: 1, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Text2, { backgroundColor: theme.userBg, wrap: "wrap", children: [
90176
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Text2, { color: theme.dim, children: [
89547
90177
  glyphs.user,
89548
90178
  " "
89549
90179
  ] }),
89550
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text2, { color: theme.user, children: content })
90180
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text2, { color: theme.user, children: content })
89551
90181
  ] }) }) });
89552
90182
  }
89553
90183
 
89554
90184
  // src/components/markdown/Markdown.tsx
89555
90185
  var import_react19 = __toESM(require_react(), 1);
89556
- var import_chalk4 = __toESM(require_source(), 1);
90186
+ var import_chalk5 = __toESM(require_source(), 1);
89557
90187
  var import_strip_ansi3 = __toESM(require_strip_ansi(), 1);
89558
90188
  var import_string_width2 = __toESM(require_string_width(), 1);
89559
90189
 
@@ -90797,7 +91427,7 @@ var Vt = b.parse;
90797
91427
  var Yt = x.lex;
90798
91428
 
90799
91429
  // src/components/markdown/format.ts
90800
- var import_chalk3 = __toESM(require_source(), 1);
91430
+ var import_chalk4 = __toESM(require_source(), 1);
90801
91431
  var import_strip_ansi2 = __toESM(require_strip_ansi(), 1);
90802
91432
  var import_string_width = __toESM(require_string_width(), 1);
90803
91433
 
@@ -104668,26 +105298,6 @@ function highlightCode(code, lang) {
104668
105298
  return result;
104669
105299
  }
104670
105300
 
104671
- // src/components/design-system/GradientText.tsx
104672
- var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
104673
- var GRAD_FROM = [183, 148, 246];
104674
- var GRAD_TO = [230, 218, 252];
104675
- var hex2 = (v2) => Math.max(0, Math.min(255, Math.round(v2))).toString(16).padStart(2, "0");
104676
- function gradientAt(t) {
104677
- const c3 = Math.max(0, Math.min(1, t));
104678
- return `#${hex2(GRAD_FROM[0] + (GRAD_TO[0] - GRAD_FROM[0]) * c3)}${hex2(
104679
- GRAD_FROM[1] + (GRAD_TO[1] - GRAD_FROM[1]) * c3
104680
- )}${hex2(GRAD_FROM[2] + (GRAD_TO[2] - GRAD_FROM[2]) * c3)}`;
104681
- }
104682
- function GradientText({
104683
- text,
104684
- wrap: wrap2
104685
- }) {
104686
- const chars = [...text];
104687
- const last = Math.max(1, chars.length - 1);
104688
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text2, { wrap: wrap2, children: chars.map((ch, i2) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text2, { color: gradientAt(i2 / last), children: ch }, i2)) });
104689
- }
104690
-
104691
105301
  // src/components/markdown/format.ts
104692
105302
  var EOL = "\n";
104693
105303
  var BLOCKQUOTE_BAR = "\u2502";
@@ -104700,13 +105310,13 @@ function configureMarked() {
104700
105310
  function gradientHeading(text) {
104701
105311
  const chars = [...text];
104702
105312
  const last = Math.max(1, chars.length - 1);
104703
- return chars.map((ch, i2) => import_chalk3.default.hex(gradientAt(i2 / last))(ch)).join("");
105313
+ return chars.map((ch, i2) => import_chalk4.default.hex(gradientAt(i2 / last))(ch)).join("");
104704
105314
  }
104705
105315
  function highlightToAnsi(code, lang, theme) {
104706
105316
  return highlightCode(code, lang).map(
104707
105317
  (spans) => spans.map((s) => {
104708
105318
  const c3 = synColor(theme, s.kind);
104709
- return c3 ? import_chalk3.default.hex(c3)(s.text) : s.text;
105319
+ return c3 ? import_chalk4.default.hex(c3)(s.text) : s.text;
104710
105320
  }).join("")
104711
105321
  ).join(EOL);
104712
105322
  }
@@ -104772,23 +105382,23 @@ function formatToken(token, theme, listDepth = 0, orderedListNumber = null, pare
104772
105382
  switch (token.type) {
104773
105383
  case "blockquote": {
104774
105384
  const inner = kids(token);
104775
- const bar = import_chalk3.default.hex(theme.dim)(BLOCKQUOTE_BAR);
104776
- return inner.split(EOL).map((line) => (0, import_strip_ansi2.default)(line).trim() ? `${bar} ${import_chalk3.default.italic(line)}` : line).join(EOL);
105385
+ const bar = import_chalk4.default.hex(theme.dim)(BLOCKQUOTE_BAR);
105386
+ return inner.split(EOL).map((line) => (0, import_strip_ansi2.default)(line).trim() ? `${bar} ${import_chalk4.default.italic(line)}` : line).join(EOL);
104777
105387
  }
104778
105388
  case "code": {
104779
105389
  const t = token;
104780
105390
  return highlightToAnsi(t.text, t.lang ?? "", theme) + EOL;
104781
105391
  }
104782
105392
  case "codespan":
104783
- return import_chalk3.default.hex(theme.assistant)(token.text);
105393
+ return import_chalk4.default.hex(theme.assistant)(token.text);
104784
105394
  case "em":
104785
- return import_chalk3.default.italic(kids(token, 0, null, parent));
105395
+ return import_chalk4.default.italic(kids(token, 0, null, parent));
104786
105396
  case "strong":
104787
- return import_chalk3.default.bold(kids(token, 0, null, parent));
105397
+ return import_chalk4.default.bold(kids(token, 0, null, parent));
104788
105398
  case "heading": {
104789
105399
  const t = token;
104790
105400
  const grad = gradientHeading((0, import_strip_ansi2.default)(kids(token)));
104791
- const styled = t.depth === 1 ? import_chalk3.default.bold.italic.underline(grad) : import_chalk3.default.bold(grad);
105401
+ const styled = t.depth === 1 ? import_chalk4.default.bold.italic.underline(grad) : import_chalk4.default.bold(grad);
104792
105402
  return styled + EOL + EOL;
104793
105403
  }
104794
105404
  case "hr":
@@ -104798,7 +105408,7 @@ function formatToken(token, theme, listDepth = 0, orderedListNumber = null, pare
104798
105408
  case "link": {
104799
105409
  const t = token;
104800
105410
  if (t.href.startsWith("mailto:")) return t.href.replace(/^mailto:/, "");
104801
- const text = import_chalk3.default.hex(theme.assistant).underline(kids(token, 0, null, token));
105411
+ const text = import_chalk4.default.hex(theme.assistant).underline(kids(token, 0, null, token));
104802
105412
  const plain = (0, import_strip_ansi2.default)(text);
104803
105413
  return plain && plain !== t.href ? hyperlink(t.href, text) : hyperlink(t.href);
104804
105414
  }
@@ -104897,7 +105507,7 @@ function MarkdownTable({ token, width }) {
104897
105507
  borderBottom: false,
104898
105508
  borderRight: last,
104899
105509
  justifyContent: justify(token.align?.[i2], !!bold),
104900
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Text2, { wrap: "wrap", children: bold ? import_chalk4.default.bold(ansi) : ansi })
105510
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Text2, { wrap: "wrap", children: bold ? import_chalk5.default.bold(ansi) : ansi })
104901
105511
  },
104902
105512
  i2
104903
105513
  );
@@ -105615,7 +106225,7 @@ function QuotaWarning({ refusal }) {
105615
106225
 
105616
106226
  // src/components/tools/SubAgentTree.tsx
105617
106227
  var import_react22 = __toESM(require_react(), 1);
105618
- var import_client_core23 = __toESM(require_dist(), 1);
106228
+ var import_client_core24 = __toESM(require_dist(), 1);
105619
106229
  var import_client_ui_core8 = __toESM(require_dist2(), 1);
105620
106230
  var import_jsx_runtime33 = __toESM(require_jsx_runtime(), 1);
105621
106231
  function agentLabel(agent) {
@@ -105627,7 +106237,7 @@ var rowMeta = import_client_ui_core8.subagentRowMeta;
105627
106237
  function rowStatus(agent) {
105628
106238
  if (agent.phase === "finished") {
105629
106239
  if (agent.status === "failed") return "Failed";
105630
- const took = agent.endedAt ? ` (${(0, import_client_core23.formatElapsed)(agent.endedAt - agent.startedAt)})` : "";
106240
+ const took = agent.endedAt ? ` (${(0, import_client_core24.formatElapsed)(agent.endedAt - agent.startedAt)})` : "";
105631
106241
  return `Done${took}`;
105632
106242
  }
105633
106243
  const last = agent.activity?.[agent.activity.length - 1];
@@ -105860,7 +106470,7 @@ function OrionRing() {
105860
106470
 
105861
106471
  // src/services/version.ts
105862
106472
  function tuiVersion() {
105863
- return "0.1.19".length > 0 ? "0.1.19" : null;
106473
+ return "0.1.20".length > 0 ? "0.1.20" : null;
105864
106474
  }
105865
106475
 
105866
106476
  // src/components/layout/WelcomeCard.tsx
@@ -106199,11 +106809,11 @@ function PlanCard({ plan }) {
106199
106809
 
106200
106810
  // src/components/tools/SubAgentCard.tsx
106201
106811
  var import_react29 = __toESM(require_react(), 1);
106202
- var import_client_core24 = __toESM(require_dist(), 1);
106812
+ var import_client_core25 = __toESM(require_dist(), 1);
106203
106813
  var import_client_ui_core10 = __toESM(require_dist2(), 1);
106204
106814
  var import_jsx_runtime42 = __toESM(require_jsx_runtime(), 1);
106205
106815
  function SubAgentCard({ agent, now: now2 }) {
106206
- const elapsed = (0, import_client_core24.formatElapsed)((now2 ?? Date.now()) - agent.startedAt);
106816
+ const elapsed = (0, import_client_core25.formatElapsed)((now2 ?? Date.now()) - agent.startedAt);
106207
106817
  const metrics = [elapsed, (0, import_client_ui_core10.subagentTokenLabel)(agent.contextTokens)].filter(Boolean).join(" \xB7 ");
106208
106818
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(Box2, { flexDirection: "row", children: [
106209
106819
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Box2, { flexShrink: 0, marginRight: 1, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ThemedText, { colorKey: "dim", children: glyphs.subagent }) }),
@@ -106452,7 +107062,7 @@ function Autocomplete({
106452
107062
  }
106453
107063
 
106454
107064
  // src/components/input/ContextSuggestions.tsx
106455
- var import_client_core25 = __toESM(require_dist(), 1);
107065
+ var import_client_core26 = __toESM(require_dist(), 1);
106456
107066
  var import_jsx_runtime44 = __toESM(require_jsx_runtime(), 1);
106457
107067
  var MAX_VISIBLE3 = 12;
106458
107068
  function ContextSuggestions({
@@ -106488,12 +107098,13 @@ function ContextSuggestions({
106488
107098
  ] });
106489
107099
  }
106490
107100
  function mentionPrefix(value, cursor) {
106491
- return (0, import_client_core25.findFileMentionQuery)(value, cursor)?.query ?? null;
107101
+ return (0, import_client_core26.findFileMentionQuery)(value, cursor)?.query ?? null;
106492
107102
  }
106493
107103
 
106494
107104
  // src/services/posture.ts
106495
107105
  function postureOf(mode, permissionMode, fullyAutomatic = false) {
106496
107106
  if (mode === "plan") return { label: `${glyphs.planMode} plan mode`, colorKey: "planMode" };
107107
+ if (mode === "duet") return { label: `${glyphs.planMode} duet mode`, colorKey: "duetMode" };
106497
107108
  if (permissionMode === "full_access" && !fullyAutomatic)
106498
107109
  return { label: `${glyphs.acceptEdits} accept edits`, colorKey: "autoAccept" };
106499
107110
  return { label: "normal", colorKey: "accent" };
@@ -106617,7 +107228,7 @@ function pushEntry(entries, text, limit = HISTORY_LIMIT) {
106617
107228
  }
106618
107229
 
106619
107230
  // src/components/input/PromptInput.tsx
106620
- var import_client_core26 = __toESM(require_dist(), 1);
107231
+ var import_client_core27 = __toESM(require_dist(), 1);
106621
107232
 
106622
107233
  // src/keybindings/match.ts
106623
107234
  function matchKeypress(input, key) {
@@ -107090,7 +107701,7 @@ function PromptInput({
107090
107701
  (0, import_react30.useEffect)(() => () => notifyMenuRef.current?.(false), []);
107091
107702
  (0, import_react30.useEffect)(() => {
107092
107703
  for (const path13 of pickedMentions.current) {
107093
- if (!value.includes(`${import_client_core26.FILE_MENTION_LEADER}${path13}`)) pickedMentions.current.delete(path13);
107704
+ if (!value.includes(`${import_client_core27.FILE_MENTION_LEADER}${path13}`)) pickedMentions.current.delete(path13);
107094
107705
  }
107095
107706
  }, [value]);
107096
107707
  (0, import_react30.useEffect)(() => {
@@ -107122,9 +107733,9 @@ function PromptInput({
107122
107733
  const completeMenu = (idx) => {
107123
107734
  if (menuFiles) {
107124
107735
  const pick = fileSuggestions[Math.min(idx, fileSuggestions.length - 1)];
107125
- const at2 = (0, import_client_core26.findFileMentionQuery)(value, cursor);
107736
+ const at2 = (0, import_client_core27.findFileMentionQuery)(value, cursor);
107126
107737
  if (!at2) return;
107127
- const next = (0, import_client_core26.insertFileMention)(value, at2, pick);
107738
+ const next = (0, import_client_core27.insertFileMention)(value, at2, pick);
107128
107739
  pickedMentions.current.add(pick);
107129
107740
  setValue2(next.text);
107130
107741
  setCursor(next.caret);
@@ -107454,7 +108065,7 @@ function PromptInput({
107454
108065
  ...pasteTokenRanges(value),
107455
108066
  // A picked `@file` is a recognized token too, and wears the same colour — the
107456
108067
  // IDE and the Power App paint theirs the same way.
107457
- ...(0, import_client_core26.scanFileMentionRanges)(value, pickedMentions.current)
108068
+ ...(0, import_client_core27.scanFileMentionRanges)(value, pickedMentions.current)
107458
108069
  ].sort((a, b2) => a.start - b2.start);
107459
108070
  const colored = (text, offset) => tokenRanges.length === 0 ? text : segmentSlice(text, offset, tokenRanges).map(
107460
108071
  (seg2, i2) => seg2.token ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Text2, { color: SLASH_TOKEN_COLOR, children: seg2.text }, `${offset}-${i2}`) : seg2.text
@@ -107610,7 +108221,7 @@ function IndexIndicator({
107610
108221
  }
107611
108222
 
107612
108223
  // src/components/status/StatusBar.tsx
107613
- var import_client_core27 = __toESM(require_dist(), 1);
108224
+ var import_client_core28 = __toESM(require_dist(), 1);
107614
108225
  var import_jsx_runtime48 = __toESM(require_jsx_runtime(), 1);
107615
108226
  var PERM_SHORT = {
107616
108227
  read_only: "read-only",
@@ -107642,6 +108253,7 @@ function StatusBar({
107642
108253
  const nodeFor = (seg2) => {
107643
108254
  switch (seg2) {
107644
108255
  case "model": {
108256
+ if (mode === "duet") return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemedText, { dim: true, children: "Orion Hybrid" });
107645
108257
  const showLvl = reasoning && reasoning.toLowerCase() !== "none";
107646
108258
  const lvl = showLvl ? effortLabel(reasoning) : "";
107647
108259
  return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemedText, { dim: true, children: displayModel(model, modelLabel) + (lvl ? ` ${lvl}` : "") });
@@ -107649,14 +108261,14 @@ function StatusBar({
107649
108261
  case "provider":
107650
108262
  return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemedText, { dim: true, children: providerLabel(provider) });
107651
108263
  case "mode":
107652
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemedText, { dim: true, children: mode.charAt(0).toUpperCase() + mode.slice(1) });
108264
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemedText, { dim: true, children: mode === "duet" ? "Duet" : mode.charAt(0).toUpperCase() + mode.slice(1) });
107653
108265
  case "perm":
107654
108266
  case "permission":
107655
108267
  return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemedText, { dim: true, children: PERM_SHORT[perm] ?? perm });
107656
108268
  case "persona":
107657
108269
  return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemedText, { dim: true, children: persona });
107658
108270
  case "tier":
107659
- return accountTier ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemedText, { dim: true, children: (0, import_client_core27.planLabel)(accountTier) }) : null;
108271
+ return accountTier ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemedText, { dim: true, children: (0, import_client_core28.planLabel)(accountTier) }) : null;
107660
108272
  case "workrun":
107661
108273
  return workRun ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ThemedText, { dim: true, children: `graph ${workRun.phasesDone}/${workRun.phasesTotal}` }) : null;
107662
108274
  case "cost":
@@ -107965,7 +108577,7 @@ function FeedbackPrompt({
107965
108577
  var import_react35 = __toESM(require_react(), 1);
107966
108578
  var import_client_ui_core13 = __toESM(require_dist2(), 1);
107967
108579
  var import_client_ui_core14 = __toESM(require_dist2(), 1);
107968
- var import_client_core28 = __toESM(require_dist(), 1);
108580
+ var import_client_core29 = __toESM(require_dist(), 1);
107969
108581
 
107970
108582
  // src/components/dialogs/SelectList.tsx
107971
108583
  var import_react34 = __toESM(require_react(), 1);
@@ -108047,12 +108659,18 @@ function SelectList({
108047
108659
  view.slice(start2, end).map((o, vi) => {
108048
108660
  const i2 = start2 + vi;
108049
108661
  const ordinal = numbered && !o.separator ? `${selectable.indexOf(i2) + 1}. ` : "";
108050
- return o.separator ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Box2, { marginTop: i2 > start2 ? 1 : 0, children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(ThemedText, { dim: true, bold: true, children: o.label }) }, `sep-${i2}`) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Box2, { flexDirection: "row", marginRight: columns ? 3 : 0, children: i2 === safeIdx ? (
108662
+ return o.separator ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(Box2, { marginTop: i2 > start2 ? 1 : 0, flexDirection: "row", children: [
108663
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(ThemedText, { dim: true, bold: true, children: o.label }),
108664
+ o.accentSuffix ? (
108665
+ // The header's CURRENT value, in the same accent the active row wears.
108666
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(ThemedText, { colorKey: "activeChoice", bold: true, children: o.accentSuffix })
108667
+ ) : null
108668
+ ] }, `sep-${i2}`) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Box2, { flexDirection: "row", marginRight: columns ? 3 : 0, children: i2 === safeIdx ? (
108051
108669
  // Selected row: the slogan's purple→lavender gradient (matches the
108052
108670
  // typing-/ menu); the hint rides the same ramp.
108053
108671
  /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(GradientText, { text: `\u276F ${ordinal}${o.label}${o.hint ? ` ${o.hint}` : ""}` })
108054
108672
  ) : /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_jsx_runtime52.Fragment, { children: [
108055
- /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(ThemedText, { children: [
108673
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(ThemedText, { colorKey: o.accent ? "activeChoice" : void 0, children: [
108056
108674
  " ",
108057
108675
  ordinal,
108058
108676
  o.label
@@ -108215,12 +108833,12 @@ function PermissionPrompt({
108215
108833
  label: "Don't ask again for",
108216
108834
  value: stage.draft,
108217
108835
  error: (() => {
108218
- const verdict = (0, import_client_core28.validateRule)(stage.draft);
108836
+ const verdict = (0, import_client_core29.validateRule)(stage.draft);
108219
108837
  return verdict.ok ? null : verdict.reason;
108220
108838
  })(),
108221
108839
  onChange: (draft) => setStage({ ...stage, draft }),
108222
108840
  onSubmit: () => {
108223
- if (!(0, import_client_core28.validateRule)(stage.draft).ok) return;
108841
+ if (!(0, import_client_core29.validateRule)(stage.draft).ok) return;
108224
108842
  setStage({
108225
108843
  kind: "pick-destination",
108226
108844
  rule: stage.draft,
@@ -108808,7 +109426,7 @@ function EndpointsPanel({
108808
109426
 
108809
109427
  // src/components/dialogs/PermissionRulesPanel.tsx
108810
109428
  var import_react37 = __toESM(require_react(), 1);
108811
- var import_client_core29 = __toESM(require_dist(), 1);
109429
+ var import_client_core30 = __toESM(require_dist(), 1);
108812
109430
  var import_client_ui_core15 = __toESM(require_dist2(), 1);
108813
109431
  var import_jsx_runtime55 = __toESM(require_jsx_runtime(), 1);
108814
109432
  function PermissionRulesPanel({
@@ -108823,7 +109441,7 @@ function PermissionRulesPanel({
108823
109441
  if (stage.kind === "add-rule") {
108824
109442
  if (key.escape) return setStage({ kind: "list" });
108825
109443
  if (key.return) {
108826
- if ((0, import_client_core29.validateRule)(stage.draft).ok) setStage({ kind: "add-behavior", rule: stage.draft });
109444
+ if ((0, import_client_core30.validateRule)(stage.draft).ok) setStage({ kind: "add-behavior", rule: stage.draft });
108827
109445
  return;
108828
109446
  }
108829
109447
  if (key.backspace || key.delete)
@@ -108835,7 +109453,7 @@ function PermissionRulesPanel({
108835
109453
  if (input.toLowerCase() === "a") setStage({ kind: "add-rule", draft: "" });
108836
109454
  });
108837
109455
  if (stage.kind === "add-rule") {
108838
- const verdict = (0, import_client_core29.validateRule)(stage.draft);
109456
+ const verdict = (0, import_client_core30.validateRule)(stage.draft);
108839
109457
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(Box2, { flexDirection: "column", marginTop: 1, children: [
108840
109458
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(ThemedText, { bold: true, children: "Add a permission rule" }),
108841
109459
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(ThemedText, { colorKey: "toolArgs", children: `[ ${stage.draft}\u2588 ]` }),
@@ -108961,7 +109579,7 @@ function PlanApprovalPrompt({
108961
109579
 
108962
109580
  // src/components/dialogs/WorkPlanApprovalPrompt.tsx
108963
109581
  var import_react39 = __toESM(require_react(), 1);
108964
- var import_client_core30 = __toESM(require_dist(), 1);
109582
+ var import_client_core31 = __toESM(require_dist(), 1);
108965
109583
  var import_jsx_runtime57 = __toESM(require_jsx_runtime(), 1);
108966
109584
  function WorkPlanApprovalPrompt({
108967
109585
  pending,
@@ -108982,11 +109600,11 @@ function WorkPlanApprovalPrompt({
108982
109600
  if (c3 === "y") onRespond(requestId, true);
108983
109601
  else if (c3 === "n" || key.escape) onRespond(requestId, false);
108984
109602
  });
108985
- const worktreeCandidates = (0, import_client_core30.planWorktreeCount)(plan);
109603
+ const worktreeCandidates = (0, import_client_core31.planWorktreeCount)(plan);
108986
109604
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Box2, { flexDirection: "column", marginTop: 1, children: [
108987
109605
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Box2, { flexDirection: "row", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ThemedText, { colorKey: "planMode", bold: true, children: "Work graph \u2014 run this plan in the background?" }) }),
108988
109606
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Box2, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ThemedText, { dim: true, children: plan.goal }) }),
108989
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Box2, { flexDirection: "column", marginTop: 1, marginLeft: 2, children: (0, import_client_core30.planFlowLines)(plan).map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ThemedText, { colorKey: "planMode", children: line }, index)) }),
109607
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Box2, { flexDirection: "column", marginTop: 1, marginLeft: 2, children: (0, import_client_core31.planFlowLines)(plan).map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ThemedText, { colorKey: "planMode", children: line }, index)) }),
108990
109608
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Box2, { marginTop: 1, flexDirection: "column", children: plan.phases.map((phase) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PhaseRow, { phase }, phase.id)) }),
108991
109609
  worktreeCandidates > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Box2, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ThemedText, { dim: true, children: `${worktreeCandidates} isolated worktree${worktreeCandidates === 1 ? "" : "s"} will be created; changed ones are kept for review.` }) }),
108992
109610
  /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Box2, { marginTop: 1, flexDirection: "row", children: [
@@ -109002,8 +109620,8 @@ function PhaseRow({ phase }) {
109002
109620
  const heading = phase.title && phase.title !== phase.id ? `${phase.id} \u2014 ${phase.title}` : phase.id;
109003
109621
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Box2, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: [
109004
109622
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ThemedText, { bold: true, children: heading }),
109005
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Box2, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ThemedText, { dim: true, children: (0, import_client_core30.phaseTraits)(phase).join(" \xB7 ") }) }),
109006
- phase.gate && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Box2, { marginLeft: 2, flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ThemedText, { colorKey: "planMode", children: `gate: ${phase.gate.cmd}${(0, import_client_core30.gateRetrySuffix)(phase.gate)}` }) })
109623
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Box2, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ThemedText, { dim: true, children: (0, import_client_core31.phaseTraits)(phase).join(" \xB7 ") }) }),
109624
+ phase.gate && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Box2, { marginLeft: 2, flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ThemedText, { colorKey: "planMode", children: `gate: ${phase.gate.cmd}${(0, import_client_core31.gateRetrySuffix)(phase.gate)}` }) })
109007
109625
  ] });
109008
109626
  }
109009
109627
 
@@ -109163,7 +109781,7 @@ function HooksBrowser({
109163
109781
 
109164
109782
  // src/components/dialogs/PluginManager.tsx
109165
109783
  var import_react41 = __toESM(require_react(), 1);
109166
- var import_client_core31 = __toESM(require_dist(), 1);
109784
+ var import_client_core32 = __toESM(require_dist(), 1);
109167
109785
  var import_jsx_runtime62 = __toESM(require_jsx_runtime(), 1);
109168
109786
  function pluginId(p) {
109169
109787
  return p.id ?? p.name ?? "";
@@ -109238,7 +109856,7 @@ function PluginManager({
109238
109856
  {
109239
109857
  dialog: {
109240
109858
  kind: "confirm",
109241
- title: `${import_client_core31.PLUGIN_TRUST_NOTICE}
109859
+ title: `${import_client_core32.PLUGIN_TRUST_NOTICE}
109242
109860
 
109243
109861
  Install "${view.id}" from "${view.catalog}" (${scope} scope)?`,
109244
109862
  options: [],
@@ -109562,7 +110180,7 @@ function ModalFrame({ children }) {
109562
110180
  }
109563
110181
 
109564
110182
  // src/components/dialogs/UsageMetricsPanel.tsx
109565
- var import_client_core32 = __toESM(require_dist(), 1);
110183
+ var import_client_core33 = __toESM(require_dist(), 1);
109566
110184
  var import_jsx_runtime66 = __toESM(require_jsx_runtime(), 1);
109567
110185
  function compactInt(value) {
109568
110186
  if (value >= 1e6) return `${(value / 1e6).toFixed(1)}m`;
@@ -109577,7 +110195,7 @@ function tokenLine(s) {
109577
110195
  `out ${compactInt(t.output_tokens ?? 0)}`,
109578
110196
  `visible ${compactInt(t.visible_output_tokens ?? 0)}`,
109579
110197
  `reason ${compactInt(t.reasoning_tokens ?? 0)}`,
109580
- `cache ${compactInt((0, import_client_core32.cacheHitTokens)(t))}`,
110198
+ `cache ${compactInt((0, import_client_core33.cacheHitTokens)(t))}`,
109581
110199
  // `read`/`write`, not `hit`: this is the cache READ share. A write-heavy turn reads 0% while
109582
110200
  // still paying the 1.25x-2x write premium, so both rates are shown.
109583
110201
  `read ${Math.round(s.cacheHitPercent)}%`,
@@ -109586,7 +110204,7 @@ function tokenLine(s) {
109586
110204
  ].join(" \xB7 ");
109587
110205
  }
109588
110206
  function topRows(group, limit = 4) {
109589
- return Object.entries(group).sort((a, b2) => (0, import_client_core32.meteredTokens)(b2[1].tokens) - (0, import_client_core32.meteredTokens)(a[1].tokens) || b2[1].calls - a[1].calls).slice(0, limit);
110207
+ return Object.entries(group).sort((a, b2) => (0, import_client_core33.meteredTokens)(b2[1].tokens) - (0, import_client_core33.meteredTokens)(a[1].tokens) || b2[1].calls - a[1].calls).slice(0, limit);
109590
110208
  }
109591
110209
  function topContextRows(group, limit = 5) {
109592
110210
  return Object.entries(group).filter(([, value]) => value > 0).sort((a, b2) => b2[1] - a[1]).slice(0, limit);
@@ -109672,11 +110290,11 @@ function BreakdownRows({
109672
110290
  }) {
109673
110291
  const rows = topRows(group);
109674
110292
  if (rows.length === 0) return null;
109675
- const max = Math.max(...rows.map(([, item]) => (0, import_client_core32.meteredTokens)(item.tokens)), 1);
110293
+ const max = Math.max(...rows.map(([, item]) => (0, import_client_core33.meteredTokens)(item.tokens)), 1);
109676
110294
  return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(Box2, { flexDirection: "column", marginTop: 1, children: [
109677
110295
  /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ThemedText, { bold: true, children: title }),
109678
110296
  rows.map(([key, item], index) => {
109679
- const tokens = (0, import_client_core32.meteredTokens)(item.tokens);
110297
+ const tokens = (0, import_client_core33.meteredTokens)(item.tokens);
109680
110298
  return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(BarRow, { label: key, value: tokens, max, tone: index, children: [
109681
110299
  item.calls,
109682
110300
  " calls \xB7 in ",
@@ -109809,10 +110427,10 @@ function RecentTurns({ rows }) {
109809
110427
  function DailyRows({ summary }) {
109810
110428
  const rows = summary.daily.slice(-5);
109811
110429
  if (rows.length === 0) return null;
109812
- const max = Math.max(...rows.map((day) => (0, import_client_core32.meteredTokens)(day.tokens)), 1);
110430
+ const max = Math.max(...rows.map((day) => (0, import_client_core33.meteredTokens)(day.tokens)), 1);
109813
110431
  return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(Box2, { flexDirection: "column", marginTop: 1, children: [
109814
110432
  /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ThemedText, { bold: true, children: "Daily history" }),
109815
- rows.map((day, index) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(BarRow, { label: day.date, value: (0, import_client_core32.meteredTokens)(day.tokens), max, tone: index, children: [
110433
+ rows.map((day, index) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(BarRow, { label: day.date, value: (0, import_client_core33.meteredTokens)(day.tokens), max, tone: index, children: [
109816
110434
  day.calls,
109817
110435
  " calls \xB7 in ",
109818
110436
  compactInt(day.tokens.input_tokens ?? 0),
@@ -109962,7 +110580,7 @@ function PendingAttachments({ items: all }) {
109962
110580
  }
109963
110581
 
109964
110582
  // src/components/layout/ReplFooter.tsx
109965
- var import_client_core33 = __toESM(require_dist(), 1);
110583
+ var import_client_core34 = __toESM(require_dist(), 1);
109966
110584
  var import_jsx_runtime70 = __toESM(require_jsx_runtime(), 1);
109967
110585
  function ReplFooter({
109968
110586
  appStore,
@@ -110007,7 +110625,7 @@ function ReplFooter({
110007
110625
  const indexPhase = useStoreSelector(appStore, (s) => s.indexPhase);
110008
110626
  const indexBadgeText = useStoreSelector(
110009
110627
  appStore,
110010
- (s) => (0, import_client_core33.formatIndexBadge)({
110628
+ (s) => (0, import_client_core34.formatIndexBadge)({
110011
110629
  mode: s.indexMode,
110012
110630
  phase: s.indexPhase,
110013
110631
  percent: s.indexPercent,
@@ -110199,7 +110817,7 @@ function FullscreenLayout({
110199
110817
 
110200
110818
  // src/components/dialogs/AgentsDashboard.tsx
110201
110819
  var import_react47 = __toESM(require_react(), 1);
110202
- var import_client_core34 = __toESM(require_dist(), 1);
110820
+ var import_client_core35 = __toESM(require_dist(), 1);
110203
110821
  var import_client_ui_core17 = __toESM(require_dist2(), 1);
110204
110822
  var import_strip_ansi4 = __toESM(require_strip_ansi(), 1);
110205
110823
  var import_jsx_runtime72 = __toESM(require_jsx_runtime(), 1);
@@ -110316,11 +110934,11 @@ function AgentsDashboard({
110316
110934
  setEvents((prev) => [...prev, ...fresh]);
110317
110935
  }
110318
110936
  setPollError(null);
110319
- if (!(0, import_client_core34.isTerminal)(job.status)) timer = setTimeout(tick, POLL_MS);
110937
+ if (!(0, import_client_core35.isTerminal)(job.status)) timer = setTimeout(tick, POLL_MS);
110320
110938
  } catch (e) {
110321
110939
  if (cancelled) return;
110322
- setPollError((0, import_client_core34.formatMissionsError)(e));
110323
- if (latest && (0, import_client_core34.isTerminal)(latest.status)) return;
110940
+ setPollError((0, import_client_core35.formatMissionsError)(e));
110941
+ if (latest && (0, import_client_core35.isTerminal)(latest.status)) return;
110324
110942
  timer = setTimeout(tick, POLL_MS);
110325
110943
  }
110326
110944
  };
@@ -110348,7 +110966,7 @@ function AgentsDashboard({
110348
110966
  cancelled = true;
110349
110967
  };
110350
110968
  }, [detailId, branchName]);
110351
- const liveSessionId = detailJob && !(0, import_client_core34.isTerminal)(detailJob.status) && detailJob.session_id ? detailJob.session_id : null;
110969
+ const liveSessionId = detailJob && !(0, import_client_core35.isTerminal)(detailJob.status) && detailJob.session_id ? detailJob.session_id : null;
110352
110970
  (0, import_react47.useEffect)(() => {
110353
110971
  if (!liveSessionId) return;
110354
110972
  liveIdRef.current = 0;
@@ -110357,16 +110975,16 @@ function AgentsDashboard({
110357
110975
  setLiveFrames(0);
110358
110976
  const nextId = () => liveIdRef.current += 1;
110359
110977
  const sub = panelRef.current.watch(liveSessionId, (env3) => {
110360
- if ((0, import_client_core34.desktopFrameOf)(env3) !== null) {
110978
+ if ((0, import_client_core35.desktopFrameOf)(env3) !== null) {
110361
110979
  setLiveFrames((n) => n + 1);
110362
110980
  return;
110363
110981
  }
110364
- const chunk = (0, import_client_core34.terminalChunkOf)(env3);
110982
+ const chunk = (0, import_client_core35.terminalChunkOf)(env3);
110365
110983
  if (chunk !== null) {
110366
- setLiveTerm((tail) => (0, import_client_core34.appendTerminalTail)(tail, (0, import_strip_ansi4.default)(chunk)));
110984
+ setLiveTerm((tail) => (0, import_client_core35.appendTerminalTail)(tail, (0, import_strip_ansi4.default)(chunk)));
110367
110985
  return;
110368
110986
  }
110369
- setLiveItems((prev) => (0, import_client_core34.applyLiveThreadEvent)(prev, env3, nextId));
110987
+ setLiveItems((prev) => (0, import_client_core35.applyLiveThreadEvent)(prev, env3, nextId));
110370
110988
  });
110371
110989
  return () => sub.dispose();
110372
110990
  }, [liveSessionId]);
@@ -110398,7 +111016,7 @@ function AgentsDashboard({
110398
111016
  const runAction = (action) => {
110399
111017
  setBusy(true);
110400
111018
  setError(null);
110401
- void action().catch((e) => setError((0, import_client_core34.formatMissionsError)(e))).finally(() => setBusy(false));
111019
+ void action().catch((e) => setError((0, import_client_core35.formatMissionsError)(e))).finally(() => setBusy(false));
110402
111020
  };
110403
111021
  const submitMessage = (id) => {
110404
111022
  const text = messageText.trim();
@@ -110414,7 +111032,7 @@ function AgentsDashboard({
110414
111032
  setMessaging(false);
110415
111033
  setMessageNote("Follow-up started.");
110416
111034
  setScreen({ kind: "detail", id: created.job_id });
110417
- }).catch((e) => setMessageNote((0, import_client_core34.formatMissionsError)(e))).finally(() => setBusy(false));
111035
+ }).catch((e) => setMessageNote((0, import_client_core35.formatMissionsError)(e))).finally(() => setBusy(false));
110418
111036
  return;
110419
111037
  }
110420
111038
  if (detailJob?.status === "needs_human_input") {
@@ -110424,7 +111042,7 @@ function AgentsDashboard({
110424
111042
  setMessageText("");
110425
111043
  setMessaging(false);
110426
111044
  setMessageNote("Resumed.");
110427
- }).catch((e) => setMessageNote((0, import_client_core34.formatMissionsError)(e))).finally(() => setBusy(false));
111045
+ }).catch((e) => setMessageNote((0, import_client_core35.formatMissionsError)(e))).finally(() => setBusy(false));
110428
111046
  return;
110429
111047
  }
110430
111048
  if (!text) {
@@ -110437,7 +111055,7 @@ function AgentsDashboard({
110437
111055
  setMessageText("");
110438
111056
  setMessaging(false);
110439
111057
  setMessageNote(res.delivered ? "Sent to the agent." : "Queued for the next phase.");
110440
- }).catch((e) => setMessageNote((0, import_client_core34.formatMissionsError)(e))).finally(() => setBusy(false));
111058
+ }).catch((e) => setMessageNote((0, import_client_core35.formatMissionsError)(e))).finally(() => setBusy(false));
110441
111059
  };
110442
111060
  const tokenHost = tokenStatus?.host || "github.com";
110443
111061
  const startConnect = () => {
@@ -110518,7 +111136,7 @@ function AgentsDashboard({
110518
111136
  setTokenInput(false);
110519
111137
  setTokenDraft("");
110520
111138
  setTokenNote("Token saved.");
110521
- }).catch((e) => setTokenNote((0, import_client_core34.formatMissionsError)(e))).finally(() => setTokenBusy(false));
111139
+ }).catch((e) => setTokenNote((0, import_client_core35.formatMissionsError)(e))).finally(() => setTokenBusy(false));
110522
111140
  };
110523
111141
  const submitJiraStep = () => {
110524
111142
  if (!jiraInput) return;
@@ -110547,7 +111165,7 @@ function AgentsDashboard({
110547
111165
  );
110548
111166
  setJiraInput(null);
110549
111167
  setJiraNote("Jira connected \u2014 the launch form's Ticket field is live.");
110550
- }).catch((e) => setJiraNote((0, import_client_core34.formatMissionsError)(e))).finally(() => setJiraBusy(false));
111168
+ }).catch((e) => setJiraNote((0, import_client_core35.formatMissionsError)(e))).finally(() => setJiraBusy(false));
110551
111169
  };
110552
111170
  const removeJira = () => {
110553
111171
  if (jiraBusy) return;
@@ -110556,7 +111174,7 @@ function AgentsDashboard({
110556
111174
  void panel.clearTicketConnection().then(() => {
110557
111175
  setJiraStatus((p) => p ? { ...p, configured: false, base_url: null, hint: null } : p);
110558
111176
  setJiraNote("Jira connection removed.");
110559
- }).catch((e) => setJiraNote((0, import_client_core34.formatMissionsError)(e))).finally(() => setJiraBusy(false));
111177
+ }).catch((e) => setJiraNote((0, import_client_core35.formatMissionsError)(e))).finally(() => setJiraBusy(false));
110560
111178
  };
110561
111179
  const removeToken = () => {
110562
111180
  if (tokenBusy) return;
@@ -110565,7 +111183,7 @@ function AgentsDashboard({
110565
111183
  void panel.clearToken().then(() => {
110566
111184
  setTokenStatus((p) => p ? { ...p, configured: false, hint: null } : p);
110567
111185
  setTokenNote("Token removed.");
110568
- }).catch((e) => setTokenNote((0, import_client_core34.formatMissionsError)(e))).finally(() => setTokenBusy(false));
111186
+ }).catch((e) => setTokenNote((0, import_client_core35.formatMissionsError)(e))).finally(() => setTokenBusy(false));
110569
111187
  };
110570
111188
  const submitLaunch = () => {
110571
111189
  const repo_url = form.repo_url.trim();
@@ -110585,7 +111203,7 @@ function AgentsDashboard({
110585
111203
  setForm(EMPTY_FORM);
110586
111204
  setField(0);
110587
111205
  setScreen({ kind: "list" });
110588
- }).catch((e) => setError((0, import_client_core34.formatMissionsError)(e))).finally(() => setBusy(false));
111206
+ }).catch((e) => setError((0, import_client_core35.formatMissionsError)(e))).finally(() => setBusy(false));
110589
111207
  };
110590
111208
  use_input_default((input, key) => {
110591
111209
  if (busy) return;
@@ -110624,14 +111242,14 @@ function AgentsDashboard({
110624
111242
  return;
110625
111243
  }
110626
111244
  if (key.escape || input === "q") return setScreen({ kind: "list" });
110627
- if (input === "m" && job && (!(0, import_client_core34.isTerminal)(job.status) || job.status === "complete")) {
111245
+ if (input === "m" && job && (!(0, import_client_core35.isTerminal)(job.status) || job.status === "complete")) {
110628
111246
  setMessageNote(null);
110629
111247
  return setMessaging(true);
110630
111248
  }
110631
- if (input === "i" && job && !(0, import_client_core34.isTerminal)(job.status) && job.status !== "needs_human_input") {
111249
+ if (input === "i" && job && !(0, import_client_core35.isTerminal)(job.status) && job.status !== "needs_human_input") {
110632
111250
  return runAction(() => panel.interrupt(screen.id).then(() => void 0));
110633
111251
  }
110634
- if (input === "c" && job && !(0, import_client_core34.isTerminal)(job.status)) {
111252
+ if (input === "c" && job && !(0, import_client_core35.isTerminal)(job.status)) {
110635
111253
  return runAction(() => panel.cancel(screen.id));
110636
111254
  }
110637
111255
  if (input === "r") return runAction(() => panel.refresh().then(() => void 0));
@@ -110704,7 +111322,7 @@ function AgentsDashboard({
110704
111322
  setError(null);
110705
111323
  return setScreen({ kind: "detail", id: here.id });
110706
111324
  }
110707
- if (input === "c" && !(0, import_client_core34.isTerminal)(here.status)) {
111325
+ if (input === "c" && !(0, import_client_core35.isTerminal)(here.status)) {
110708
111326
  return runAction(() => panel.cancel(here.id));
110709
111327
  }
110710
111328
  });
@@ -110731,7 +111349,7 @@ function AgentsDashboard({
110731
111349
  // point. This MUST match the `m`-key gate (which allows complete): if the
110732
111350
  // key opens messaging but the render gate stays !isTerminal, the user types
110733
111351
  // blind and errors never paint.
110734
- live: !!(detailJob && (!(0, import_client_core34.isTerminal)(detailJob.status) || detailJob.status === "complete")),
111352
+ live: !!(detailJob && (!(0, import_client_core35.isTerminal)(detailJob.status) || detailJob.status === "complete")),
110735
111353
  messaging,
110736
111354
  text: messageText,
110737
111355
  note: messageNote,
@@ -110783,10 +111401,10 @@ function footerHint(screen, job, messaging, conn) {
110783
111401
  }
110784
111402
  if (parked) return "m resume \xB7 c cancel \xB7 r refresh \xB7 q back";
110785
111403
  if (job?.status === "complete") return "m follow-up \xB7 r refresh \xB7 q back";
110786
- const steer = job && !(0, import_client_core34.isTerminal)(job.status) ? "m message \xB7 i interrupt \xB7 c cancel \xB7 " : "";
111404
+ const steer = job && !(0, import_client_core35.isTerminal)(job.status) ? "m message \xB7 i interrupt \xB7 c cancel \xB7 " : "";
110787
111405
  return `${steer}r refresh \xB7 q back`;
110788
111406
  }
110789
- const cancel = job && !(0, import_client_core34.isTerminal)(job.status) ? "c cancel \xB7 " : "";
111407
+ const cancel = job && !(0, import_client_core35.isTerminal)(job.status) ? "c cancel \xB7 " : "";
110790
111408
  return `\u2191/\u2193 move \xB7 enter open \xB7 n new \xB7 s connections \xB7 ${cancel}r refresh \xB7 q close`;
110791
111409
  }
110792
111410
  function ConnectionsView({
@@ -110920,7 +111538,7 @@ function JobDetailView({
110920
111538
  composer
110921
111539
  }) {
110922
111540
  if (!job) return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ThemedText, { dim: true, children: "Job not found." });
110923
- const terminal = (0, import_client_core34.isTerminal)(job.status);
111541
+ const terminal = (0, import_client_core35.isTerminal)(job.status);
110924
111542
  return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(Box2, { flexDirection: "column", children: [
110925
111543
  /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ThemedText, { colorKey: "listSelection", bold: true, children: jobTitle(job) }),
110926
111544
  /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(Box2, { flexDirection: "column", marginTop: 1, children: [
@@ -111160,7 +111778,7 @@ function Root({
111160
111778
 
111161
111779
  // src/components/layout/SignInScreen.tsx
111162
111780
  var import_react51 = __toESM(require_react(), 1);
111163
- var import_client_core35 = __toESM(require_dist(), 1);
111781
+ var import_client_core36 = __toESM(require_dist(), 1);
111164
111782
 
111165
111783
  // src/components/layout/splash/Splash.tsx
111166
111784
  var import_react50 = __toESM(require_react(), 1);
@@ -111546,7 +112164,7 @@ function SignInScreen({
111546
112164
  setUrl(null);
111547
112165
  setError(null);
111548
112166
  try {
111549
- await (0, import_client_core35.signInViaBrowser)(
112167
+ await (0, import_client_core36.signInViaBrowser)(
111550
112168
  session,
111551
112169
  { accountsUrl, accountsApiUrl, client: "tui" },
111552
112170
  {
@@ -111655,16 +112273,16 @@ function SignInCard({
111655
112273
  }
111656
112274
 
111657
112275
  // src/services/presenceHost.ts
111658
- var import_client_core36 = __toESM(require_dist(), 1);
112276
+ var import_client_core37 = __toESM(require_dist(), 1);
111659
112277
  function startTuiPresence(opts) {
111660
- const registry = opts.registry ?? new import_client_core36.PresenceRegistry({ clientType: "tui" });
112278
+ const registry = opts.registry ?? new import_client_core37.PresenceRegistry({ clientType: "tui" });
111661
112279
  let currentSid = null;
111662
112280
  let lastStatus = "idle";
111663
112281
  const statusFromApp = (s) => s.pendingPermissions.length > 0 ? "waiting" : s.status === "streaming" ? "busy" : "idle";
111664
112282
  const stampGit = () => {
111665
112283
  if (!opts.workspaceRoot || !currentSid) return;
111666
112284
  const sid = currentSid;
111667
- void (0, import_client_core36.getGitInfo)(opts.workspaceRoot).then((info2) => {
112285
+ void (0, import_client_core37.getGitInfo)(opts.workspaceRoot).then((info2) => {
111668
112286
  if (sid !== currentSid) return;
111669
112287
  registry.updateSession(sid, {
111670
112288
  gitRoot: info2.gitRoot ?? void 0,
@@ -111700,11 +112318,11 @@ function startTuiPresence(opts) {
111700
112318
  ownSessionId: currentSid ?? void 0,
111701
112319
  fresh: true
111702
112320
  });
111703
- return peers.map((p) => `${(0, import_client_core36.describePeer)(p)} \u2014 ${p.session.status}`);
112321
+ return peers.map((p) => `${(0, import_client_core37.describePeer)(p)} \u2014 ${p.session.status}`);
111704
112322
  },
111705
112323
  async liveElsewhere(sessionId) {
111706
112324
  const peer = await registry.isSessionLiveElsewhere(sessionId);
111707
- return peer ? (0, import_client_core36.describePeer)(peer) : null;
112325
+ return peer ? (0, import_client_core37.describePeer)(peer) : null;
111708
112326
  },
111709
112327
  dispose() {
111710
112328
  unsubscribe();
@@ -111714,7 +112332,7 @@ function startTuiPresence(opts) {
111714
112332
  }
111715
112333
 
111716
112334
  // src/services/remoteControlHost.ts
111717
- var import_client_core37 = __toESM(require_dist(), 1);
112335
+ var import_client_core38 = __toESM(require_dist(), 1);
111718
112336
  import os5 from "os";
111719
112337
  var REMOTE_DENIED = /* @__PURE__ */ new Set([
111720
112338
  // Session/process-scoped.
@@ -111764,17 +112382,17 @@ function flattenInfoView(view) {
111764
112382
  function startTuiRemoteControl(opts) {
111765
112383
  let currentSid = null;
111766
112384
  const stateFromApp = (s) => s.pendingPermissions.length > 0 || s.pendingPlanApproval !== null || s.pendingAskUser !== null ? "needs_you" : s.status === "streaming" ? "running" : "idle";
111767
- const requireCurrent = (sessionId) => sessionId === currentSid ? null : (0, import_client_core37.rcRefuse)("unknown_session", "this terminal is on a different session");
112385
+ const requireCurrent = (sessionId) => sessionId === currentSid ? null : (0, import_client_core38.rcRefuse)("unknown_session", "this terminal is on a different session");
111768
112386
  const deliverText = (text, attachments) => {
111769
112387
  if (opts.appStore.getState().status === "streaming") {
111770
112388
  if (attachments !== void 0 && attachments.length > 0) {
111771
- return (0, import_client_core37.rcRefusePhotosMidTurn)();
112389
+ return (0, import_client_core38.rcRefusePhotosMidTurn)();
111772
112390
  }
111773
112391
  opts.verbs.steer(text);
111774
- return import_client_core37.RC_OK;
112392
+ return import_client_core38.RC_OK;
111775
112393
  }
111776
112394
  const sent = attachments !== void 0 && attachments.length > 0 ? opts.verbs.send(text, attachments) : opts.verbs.send(text);
111777
- return sent ? import_client_core37.RC_OK : (0, import_client_core37.rcRefuse)("signed_out", "sign in on this machine first");
112395
+ return sent ? import_client_core38.RC_OK : (0, import_client_core38.rcRefuse)("signed_out", "sign in on this machine first");
111778
112396
  };
111779
112397
  const commandCatalog = () => opts.commands === void 0 ? [] : opts.commands.registry.all().filter((command) => !REMOTE_DENIED.has(command.name)).map((command) => ({
111780
112398
  name: command.name,
@@ -111783,15 +112401,15 @@ function startTuiRemoteControl(opts) {
111783
112401
  }));
111784
112402
  const runRemoteCommand = async (text) => {
111785
112403
  const wired = opts.commands;
111786
- if (wired === void 0) return (0, import_client_core37.rcRefuse)("unsupported", "commands are not wired");
112404
+ if (wired === void 0) return (0, import_client_core38.rcRefuse)("unsupported", "commands are not wired");
111787
112405
  const parsed = wired.registry.parse(text);
111788
- if (parsed === null) return (0, import_client_core37.rcRefuse)("unsupported", "unknown command");
112406
+ if (parsed === null) return (0, import_client_core38.rcRefuse)("unsupported", "unknown command");
111789
112407
  const { command, args: args2 } = parsed;
111790
112408
  if (REMOTE_DENIED.has(command.name)) {
111791
- return (0, import_client_core37.rcRefuse)("unsupported", "this command runs at the terminal only");
112409
+ return (0, import_client_core38.rcRefuse)("unsupported", "this command runs at the terminal only");
111792
112410
  }
111793
112411
  if (REMOTE_ARG_REQUIRED.has(command.name) && args2.trim() === "") {
111794
- return (0, import_client_core37.rcRefuse)(
112412
+ return (0, import_client_core38.rcRefuse)(
111795
112413
  "unsupported",
111796
112414
  `add a value: /${command.name} ${command.argumentHint ?? "<value>"}`
111797
112415
  );
@@ -111817,11 +112435,11 @@ function startTuiRemoteControl(opts) {
111817
112435
  try {
111818
112436
  await command.run(args2, ctx);
111819
112437
  } catch (error) {
111820
- return (0, import_client_core37.rcRefuse)("internal", error instanceof Error ? error.message : String(error));
112438
+ return (0, import_client_core38.rcRefuse)("internal", error instanceof Error ? error.message : String(error));
111821
112439
  }
111822
112440
  return { ok: true, ...lines.length > 0 ? { output: lines.join("\n") } : {} };
111823
112441
  };
111824
- const host = (0, import_client_core37.createRemoteControlHost)({
112442
+ const host = (0, import_client_core38.createRemoteControlHost)({
111825
112443
  clientType: "tui",
111826
112444
  bridge: opts.bridge,
111827
112445
  machineId: os5.hostname(),
@@ -111853,18 +112471,18 @@ function startTuiRemoteControl(opts) {
111853
112471
  const refusal = requireCurrent(sessionId);
111854
112472
  if (refusal) return refusal;
111855
112473
  opts.verbs.deliverAgentMessage(message);
111856
- return import_client_core37.RC_OK;
112474
+ return import_client_core38.RC_OK;
111857
112475
  },
111858
112476
  resolvePermission: (sessionId, requestId, decision) => {
111859
112477
  const refusal = requireCurrent(sessionId);
111860
112478
  if (refusal) return refusal;
111861
- return opts.verbs.resolvePermission(requestId, decision, sessionId) ? import_client_core37.RC_OK : (0, import_client_core37.rcRefuse)("no_pending_permission", "that prompt was already answered");
112479
+ return opts.verbs.resolvePermission(requestId, decision, sessionId) ? import_client_core38.RC_OK : (0, import_client_core38.rcRefuse)("no_pending_permission", "that prompt was already answered");
111862
112480
  },
111863
112481
  interrupt: (sessionId) => {
111864
112482
  const refusal = requireCurrent(sessionId);
111865
112483
  if (refusal) return refusal;
111866
112484
  opts.verbs.interrupt();
111867
- return import_client_core37.RC_OK;
112485
+ return import_client_core38.RC_OK;
111868
112486
  },
111869
112487
  runCommand: (sessionId, text) => {
111870
112488
  const refusal = requireCurrent(sessionId);
@@ -111876,14 +112494,14 @@ function startTuiRemoteControl(opts) {
111876
112494
  if (refusal) return refusal;
111877
112495
  const ok2 = await opts.verbs.setModel(
111878
112496
  model,
111879
- effort === void 0 ? void 0 : (0, import_client_core37.rcEffortToLocal)(effort)
112497
+ effort === void 0 ? void 0 : (0, import_client_core38.rcEffortToLocal)(effort)
111880
112498
  );
111881
- return ok2 ? import_client_core37.RC_OK : (0, import_client_core37.rcRefuse)("internal", "couldn't switch the model");
112499
+ return ok2 ? import_client_core38.RC_OK : (0, import_client_core38.rcRefuse)("internal", "couldn't switch the model");
111882
112500
  },
111883
112501
  setMode: (sessionId, mode) => {
111884
112502
  const refusal = requireCurrent(sessionId);
111885
112503
  if (refusal) return refusal;
111886
- return opts.verbs.setMode(mode) ? import_client_core37.RC_OK : (0, import_client_core37.rcRefuse)("internal", "couldn't switch permissions");
112504
+ return opts.verbs.setMode(mode) ? import_client_core38.RC_OK : (0, import_client_core38.rcRefuse)("internal", "couldn't switch permissions");
111887
112505
  },
111888
112506
  committedMessages: (sessionId) => sessionId === currentSid ? opts.committedMessages() : [],
111889
112507
  // Cards parked before anyone was watching: replayed at the end of an attach
@@ -111894,7 +112512,7 @@ function startTuiRemoteControl(opts) {
111894
112512
  const now2 = Date.now() / 1e3;
111895
112513
  return [
111896
112514
  ...app.pendingPermissions.map(
111897
- (parked) => (0, import_client_core37.parkedPermissionEvent)(
112515
+ (parked) => (0, import_client_core38.parkedPermissionEvent)(
111898
112516
  sessionId,
111899
112517
  {
111900
112518
  requestId: parked.data.request_id,
@@ -111909,7 +112527,7 @@ function startTuiRemoteControl(opts) {
111909
112527
  // The other two parked-decision cards ride the backfill tail the same way —
111910
112528
  // a phone arriving mid-plan (or mid-question) has something to answer.
111911
112529
  ...app.pendingPlanApproval !== null ? [
111912
- (0, import_client_core37.parkedPlanApprovalEvent)(
112530
+ (0, import_client_core38.parkedPlanApprovalEvent)(
111913
112531
  sessionId,
111914
112532
  {
111915
112533
  requestId: app.pendingPlanApproval.requestId,
@@ -111919,7 +112537,7 @@ function startTuiRemoteControl(opts) {
111919
112537
  )
111920
112538
  ] : [],
111921
112539
  ...app.pendingAskUser !== null ? [
111922
- (0, import_client_core37.parkedAskUserEvent)(
112540
+ (0, import_client_core38.parkedAskUserEvent)(
111923
112541
  sessionId,
111924
112542
  {
111925
112543
  requestId: app.pendingAskUser.requestId,
@@ -111933,7 +112551,7 @@ function startTuiRemoteControl(opts) {
111933
112551
  resolvePlanApproval: (sessionId, requestId, approved) => {
111934
112552
  const refusal = requireCurrent(sessionId);
111935
112553
  if (refusal) return refusal;
111936
- return opts.verbs.resolvePlanApproval(requestId, approved, sessionId) ? import_client_core37.RC_OK : (0, import_client_core37.rcRefuse)("no_pending_permission", "that plan was already answered");
112554
+ return opts.verbs.resolvePlanApproval(requestId, approved, sessionId) ? import_client_core38.RC_OK : (0, import_client_core38.rcRefuse)("no_pending_permission", "that plan was already answered");
111937
112555
  },
111938
112556
  answerQuestions: (sessionId, requestId, answers) => {
111939
112557
  const refusal = requireCurrent(sessionId);
@@ -111942,7 +112560,7 @@ function startTuiRemoteControl(opts) {
111942
112560
  requestId,
111943
112561
  answers,
111944
112562
  sessionId
111945
- ) ? import_client_core37.RC_OK : (0, import_client_core37.rcRefuse)("no_pending_permission", "those questions were already answered");
112563
+ ) ? import_client_core38.RC_OK : (0, import_client_core38.rcRefuse)("no_pending_permission", "those questions were already answered");
111946
112564
  }
111947
112565
  }
111948
112566
  });
@@ -111967,7 +112585,7 @@ function startTuiRemoteControl(opts) {
111967
112585
  host.updateSession(currentSid, {
111968
112586
  ...model !== void 0 ? { model } : {},
111969
112587
  mode: app.permissionMode,
111970
- effort: (0, import_client_core37.rcEffortToWire)(app.reasoning)
112588
+ effort: (0, import_client_core38.rcEffortToWire)(app.reasoning)
111971
112589
  });
111972
112590
  }
111973
112591
  const next = stateFromApp(app);
@@ -112001,7 +112619,7 @@ function startTuiRemoteControl(opts) {
112001
112619
  ...app.sessionTitle !== "" ? { title: app.sessionTitle } : {},
112002
112620
  ...lastModel !== void 0 ? { model: lastModel } : {},
112003
112621
  mode: lastMode,
112004
- effort: (0, import_client_core37.rcEffortToWire)(lastEffort)
112622
+ effort: (0, import_client_core38.rcEffortToWire)(lastEffort)
112005
112623
  });
112006
112624
  },
112007
112625
  status: () => host.status(),
@@ -112042,19 +112660,19 @@ function appendHistory(text) {
112042
112660
  }
112043
112661
 
112044
112662
  // src/services/indexer.ts
112045
- var import_client_core39 = __toESM(require_dist(), 1);
112663
+ var import_client_core40 = __toESM(require_dist(), 1);
112046
112664
 
112047
112665
  // src/services/nodeFileSource.ts
112048
- var import_client_core38 = __toESM(require_dist(), 1);
112666
+ var import_client_core39 = __toESM(require_dist(), 1);
112049
112667
 
112050
112668
  // src/services/indexer.ts
112051
112669
  import { fileURLToPath as fileURLToPath2 } from "url";
112052
112670
  import * as fs13 from "fs";
112053
112671
  import * as path11 from "path";
112054
- var INDEX_WATCH_INCLUDE = `**/*.{${import_client_core39.INDEX_FILE_EXTENSIONS.join(",")}}`;
112055
- var EXCLUDE = "{" + [...import_client_core39.IGNORE_DIRS].map((d2) => `**/${d2}/**`).join(",") + "}";
112672
+ var INDEX_WATCH_INCLUDE = `**/*.{${import_client_core40.INDEX_FILE_EXTENSIONS.join(",")}}`;
112673
+ var EXCLUDE = "{" + [...import_client_core40.IGNORE_DIRS].map((d2) => `**/${d2}/**`).join(",") + "}";
112056
112674
  function createIndexer(bridge, workspaceRoot, store, onStatus, onFileEvent, options = {}) {
112057
- const fileSource = new import_client_core38.NodeFileSource(workspaceRoot, {
112675
+ const fileSource = new import_client_core39.NodeFileSource(workspaceRoot, {
112058
112676
  watchInclude: INDEX_WATCH_INCLUDE,
112059
112677
  watchExclude: EXCLUDE
112060
112678
  });
@@ -112070,9 +112688,9 @@ function createIndexer(bridge, workspaceRoot, store, onStatus, onFileEvent, opti
112070
112688
  setFileCount: (n) => onStatus?.("orion.index.files", n)
112071
112689
  };
112072
112690
  const workerScriptPath = options.workerScriptPath ?? bundledIndexWorkerPath();
112073
- const controller = new import_client_core39.IndexModeController({
112074
- initialMode: (0, import_client_core39.normalizeIndexMode)(options.mode, "on"),
112075
- create: (defer) => new import_client_core39.ProcessWorkspaceIndexer({
112691
+ const controller = new import_client_core40.IndexModeController({
112692
+ initialMode: (0, import_client_core40.normalizeIndexMode)(options.mode, "on"),
112693
+ create: (defer) => new import_client_core40.ProcessWorkspaceIndexer({
112076
112694
  getRoot: () => workspaceRoot,
112077
112695
  indexConfig,
112078
112696
  progress,
@@ -112081,7 +112699,7 @@ function createIndexer(bridge, workspaceRoot, store, onStatus, onFileEvent, opti
112081
112699
  rgPath: options.rgPath ?? null,
112082
112700
  deferBuildUntilFirstQuery: defer,
112083
112701
  fallback: {
112084
- indexer: new import_client_core39.WorkspaceIndexer(bridge, fileSource, indexConfig, progress, grammarDir, store),
112702
+ indexer: new import_client_core40.WorkspaceIndexer(bridge, fileSource, indexConfig, progress, grammarDir, store),
112085
112703
  reader: store
112086
112704
  },
112087
112705
  log: (message, error) => {
@@ -112090,7 +112708,7 @@ function createIndexer(bridge, workspaceRoot, store, onStatus, onFileEvent, opti
112090
112708
  }
112091
112709
  })
112092
112710
  });
112093
- const safety = (0, import_client_core39.classifyWorkspaceRootForIndexing)(workspaceRoot);
112711
+ const safety = (0, import_client_core40.classifyWorkspaceRootForIndexing)(workspaceRoot);
112094
112712
  if (!safety.safe) {
112095
112713
  onStatus?.("orion.index.state", "idle");
112096
112714
  onStatus?.("orion.index.percent", 0);
@@ -112229,7 +112847,7 @@ function shouldAutoApprove(fullyAutomatic, configAutoApprove) {
112229
112847
  }
112230
112848
 
112231
112849
  // src/headless/runHeadless.ts
112232
- var import_client_core40 = __toESM(require_dist(), 1);
112850
+ var import_client_core41 = __toESM(require_dist(), 1);
112233
112851
  var import_client_ui_core18 = __toESM(require_dist2(), 1);
112234
112852
  import * as os6 from "os";
112235
112853
  import { randomUUID } from "crypto";
@@ -112274,7 +112892,7 @@ function extractFinalAssistantText(data) {
112274
112892
  }
112275
112893
  async function runGoalLoop(deps2) {
112276
112894
  let turns = 0;
112277
- const runner = new import_client_core40.GoalRunner({
112895
+ const runner = new import_client_core41.GoalRunner({
112278
112896
  // An explicit `--max-turns` overrides; without one this run takes the same default
112279
112897
  // ceiling every other host does. An unattended fleet is the LAST place that should be
112280
112898
  // the only caller running unbounded.
@@ -112292,7 +112910,7 @@ async function runHeadless(flags2) {
112292
112910
  const config = loadConfig();
112293
112911
  if (flags2.workspace) config.workspaceRoot = flags2.workspace;
112294
112912
  const secrets = createSecretStore();
112295
- const session = (0, import_client_core40.createAgentSession)(secrets, config);
112913
+ const session = (0, import_client_core41.createAgentSession)(secrets, config);
112296
112914
  const signedIn = await session.isSignedIn();
112297
112915
  if (!signedIn && !process.env.ORION_AUTH_TOKEN) {
112298
112916
  throw new Error(
@@ -112317,15 +112935,15 @@ async function runHeadless(flags2) {
112317
112935
  reasoning: flags2.reasoning ?? ""
112318
112936
  });
112319
112937
  const authToken = async () => await session.currentAccessToken() ?? process.env.ORION_AUTH_TOKEN ?? null;
112320
- const bridge = new import_client_core40.OrionBridge(
112938
+ const bridge = new import_client_core41.OrionBridge(
112321
112939
  () => config.apiUrl,
112322
112940
  authToken,
112323
- import_client_core40.nodeEmitterFactory,
112941
+ import_client_core41.nodeEmitterFactory,
112324
112942
  () => session.refresh().then(() => true, () => false)
112325
112943
  );
112326
- const brain = (0, import_client_core40.createHostBrain)({
112944
+ const brain = (0, import_client_core41.createHostBrain)({
112327
112945
  topology: config.brainTopology,
112328
- resolveBinary: () => (0, import_client_core40.resolveBrainBinary)({
112946
+ resolveBinary: () => (0, import_client_core41.resolveBrainBinary)({
112329
112947
  configPath: config.brainPath,
112330
112948
  env: process.env,
112331
112949
  bundledCandidates: bundledBrainCandidates()
@@ -112336,19 +112954,19 @@ async function runHeadless(flags2) {
112336
112954
  renewBearer: async () => await session.currentFreshAccessToken() ?? process.env.ORION_AUTH_TOKEN ?? null,
112337
112955
  log: (message, error) => console.error(`[orion-brain] ${message}${error ? `: ${String(error)}` : ""}`)
112338
112956
  });
112339
- const turnTransport = (0, import_client_core40.createTurnTransport)({
112957
+ const turnTransport = (0, import_client_core41.createTurnTransport)({
112340
112958
  mode: config.brain,
112341
112959
  bridge,
112342
- makeLocal: () => new import_client_core40.LocalBrainTransport({
112960
+ makeLocal: () => new import_client_core41.LocalBrainTransport({
112343
112961
  // Proactive freshness for the segment-holding bearer (the interactive TUI's twin).
112344
112962
  authToken: async () => await session.currentFreshAccessToken() ?? process.env.ORION_AUTH_TOKEN ?? null,
112345
112963
  gatewayUrl: () => config.apiUrl,
112346
112964
  connect: () => brain.connect()
112347
112965
  })
112348
112966
  });
112349
- const codebaseIndexFallback = new import_client_core40.WorkspaceIndexStore();
112350
- const ripgrep = new import_client_core40.NodeRipgrepLocator({
112351
- bundledCandidates: () => (0, import_client_core40.vscodeRipgrepCandidates)((specifier) => __require.resolve(specifier))
112967
+ const codebaseIndexFallback = new import_client_core41.WorkspaceIndexStore();
112968
+ const ripgrep = new import_client_core41.NodeRipgrepLocator({
112969
+ bundledCandidates: () => (0, import_client_core41.vscodeRipgrepCandidates)((specifier) => __require.resolve(specifier))
112352
112970
  });
112353
112971
  const indexer = createIndexer(bridge, config.workspaceRoot, codebaseIndexFallback, void 0, void 0, {
112354
112972
  rgPath: ripgrep.locate(),
@@ -112358,13 +112976,13 @@ async function runHeadless(flags2) {
112358
112976
  mode: "on-demand"
112359
112977
  });
112360
112978
  void indexer.start().catch(() => void 0);
112361
- const permissionStore = new import_client_core40.PermissionSettingsStore({ workspaceRoot: config.workspaceRoot });
112979
+ const permissionStore = new import_client_core41.PermissionSettingsStore({ workspaceRoot: config.workspaceRoot });
112362
112980
  await permissionStore.load();
112363
- const executor = new import_client_core40.ToolExecutor(
112981
+ const executor = new import_client_core41.ToolExecutor(
112364
112982
  () => config.workspaceRoot,
112365
112983
  () => appStore.getState().permissionMode,
112366
112984
  secrets,
112367
- new import_client_core40.NullLspProvider(),
112985
+ new import_client_core41.NullLspProvider(),
112368
112986
  ripgrep,
112369
112987
  nullFrameSinkFactory,
112370
112988
  fallbackBrowserConfig,
@@ -112387,7 +113005,7 @@ async function runHeadless(flags2) {
112387
113005
  workspaceRoot: config.workspaceRoot,
112388
113006
  homeDir: os6.homedir()
112389
113007
  });
112390
- const sandboxAvailable = (0, import_client_core40.probeSandboxAvailable)();
113008
+ const sandboxAvailable = (0, import_client_core41.probeSandboxAvailable)();
112391
113009
  await (0, import_client_core8.refreshEndpointRouting)(appStore.getState().provider, {
112392
113010
  workspaceRoot: config.workspaceRoot
112393
113011
  });
@@ -112421,7 +113039,7 @@ async function runHeadless(flags2) {
112421
113039
  const onEvent = (ev) => {
112422
113040
  lastEvent = ev;
112423
113041
  };
112424
- const outcome = await (0, import_client_core40.driveTurn)(
113042
+ const outcome = await (0, import_client_core41.driveTurn)(
112425
113043
  turnTransport,
112426
113044
  {
112427
113045
  sessionId,
@@ -112431,7 +113049,7 @@ async function runHeadless(flags2) {
112431
113049
  routing: routing(),
112432
113050
  clientCapabilities: [],
112433
113051
  drainQueuedInput: () => [],
112434
- getOrionResources: () => (0, import_client_core40.buildOrionSnapshot)(config.workspaceRoot, void 0, sessionId),
113052
+ getOrionResources: () => (0, import_client_core41.buildOrionSnapshot)(config.workspaceRoot, void 0, sessionId),
112435
113053
  getFileHistoryManifest: () => executor.fileHistoryManifest(sessionId)
112436
113054
  },
112437
113055
  {
@@ -112463,7 +113081,7 @@ async function runHeadless(flags2) {
112463
113081
  }
112464
113082
 
112465
113083
  // src/services/feedbackGate.ts
112466
- var import_client_core41 = __toESM(require_dist(), 1);
113084
+ var import_client_core42 = __toESM(require_dist(), 1);
112467
113085
  var import_client_ui_core19 = __toESM(require_dist2(), 1);
112468
113086
  import { randomUUID as randomUUID2 } from "crypto";
112469
113087
  var TuiFeedbackGate = class {
@@ -112513,7 +113131,7 @@ var TuiFeedbackGate = class {
112513
113131
  model: routing.model,
112514
113132
  provider: routing.provider
112515
113133
  });
112516
- void (0, import_client_core41.sendFeedbackImpression)(this.deps.submit, "shown", "tui");
113134
+ void (0, import_client_core42.sendFeedbackImpression)(this.deps.submit, "shown", "tui");
112517
113135
  }
112518
113136
  /** The user rated. Snapshot the transcript SYNCHRONOUSLY (before any await), then
112519
113137
  * scrub + assemble + send off the interactive path. Idempotent per requestId. */
@@ -112536,8 +113154,8 @@ var TuiFeedbackGate = class {
112536
113154
  model: meta.model,
112537
113155
  provider: meta.provider
112538
113156
  });
112539
- const { conversation, truncated } = (0, import_client_core41.scrubFeedbackConversation)(snapshot);
112540
- void (0, import_client_core41.sendFeedbackSubmission)(this.deps.submit, {
113157
+ const { conversation, truncated } = (0, import_client_core42.scrubFeedbackConversation)(snapshot);
113158
+ void (0, import_client_core42.sendFeedbackSubmission)(this.deps.submit, {
112541
113159
  ...body2,
112542
113160
  conversation,
112543
113161
  conversation_truncated: truncated
@@ -112566,7 +113184,7 @@ var TuiFeedbackGate = class {
112566
113184
  now2
112567
113185
  );
112568
113186
  this.safeSave((0, import_client_ui_core19.feedbackScalarsFromState)(state));
112569
- void (0, import_client_core41.sendFeedbackImpression)(this.deps.submit, "dismissed", "tui");
113187
+ void (0, import_client_core42.sendFeedbackImpression)(this.deps.submit, "dismissed", "tui");
112570
113188
  }
112571
113189
  return true;
112572
113190
  }
@@ -112580,7 +113198,7 @@ var TuiFeedbackGate = class {
112580
113198
 
112581
113199
  // src/main.tsx
112582
113200
  var import_jsx_runtime77 = __toESM(require_jsx_runtime(), 1);
112583
- var SANDBOX_AVAILABLE = (0, import_client_core42.probeSandboxAvailable)();
113201
+ var SANDBOX_AVAILABLE = (0, import_client_core43.probeSandboxAvailable)();
112584
113202
  async function main() {
112585
113203
  let headlessFlags = null;
112586
113204
  try {
@@ -112603,6 +113221,17 @@ async function main() {
112603
113221
  let altScreen = { active: false, dispose: () => void 0 };
112604
113222
  const firstRun = ensureConfigFile();
112605
113223
  const config = loadConfig();
113224
+ let pendingDuetReplan = null;
113225
+ const beginDuetPhase = (text) => {
113226
+ const s = appStore.getState();
113227
+ if (s.mode !== "duet") return;
113228
+ const routed = (0, import_client_core44.willRouteToExecution)(s.duetPlan, text);
113229
+ if (routed) appStore.setState((st2) => ({ ...st2, duetExecutionStarted: true }));
113230
+ const escalated = routed && (s.duetPlan?.escalated ?? false);
113231
+ transcriptStore.setState(
113232
+ (st2) => appendNote(st2, duetPhaseNoteText(routed ? "executing" : "planning", { escalated }))
113233
+ );
113234
+ };
112606
113235
  const bindings = loadBindings();
112607
113236
  const flags2 = parseLaunchFlags(process.argv.slice(2));
112608
113237
  const resumeId = flags2.resumeId;
@@ -112632,8 +113261,8 @@ async function main() {
112632
113261
  }
112633
113262
  });
112634
113263
  void (0, import_client_core8.refreshEndpointRouting)(config.provider, { workspaceRoot: config.workspaceRoot });
112635
- void (0, import_client_core43.prewarmInterimModels)(config.workspaceRoot);
112636
- void (0, import_client_core43.prewarmRepoIdentity)(config.workspaceRoot);
113264
+ void (0, import_client_core44.prewarmInterimModels)(config.workspaceRoot);
113265
+ void (0, import_client_core44.prewarmRepoIdentity)(config.workspaceRoot);
112637
113266
  const setSessionTitle = (title) => {
112638
113267
  appStore.setState((s) => s.sessionTitle === title ? s : { ...s, sessionTitle: title });
112639
113268
  };
@@ -112657,8 +113286,8 @@ async function main() {
112657
113286
  }
112658
113287
  });
112659
113288
  const secrets = createSecretStore();
112660
- const session = (0, import_client_core43.createAgentSession)(secrets, config);
112661
- const outcomes = new import_client_core43.OutcomeReporter({
113289
+ const session = (0, import_client_core44.createAgentSession)(secrets, config);
113290
+ const outcomes = new import_client_core44.OutcomeReporter({
112662
113291
  apiBaseUrl: () => config.accountsApiUrl,
112663
113292
  accessToken: () => session.currentAccessToken()
112664
113293
  });
@@ -112710,10 +113339,10 @@ async function main() {
112710
113339
  }
112711
113340
  }
112712
113341
  const authToken = async () => await session.currentAccessToken() ?? process.env.ORION_AUTH_TOKEN ?? null;
112713
- const bridge = new import_client_core42.OrionBridge(
113342
+ const bridge = new import_client_core43.OrionBridge(
112714
113343
  () => config.apiUrl,
112715
113344
  authToken,
112716
- import_client_core43.nodeEmitterFactory,
113345
+ import_client_core44.nodeEmitterFactory,
112717
113346
  // Seamless refresh: a 401 coalesces ONE refresh through the AgentSession (single-flight), so a
112718
113347
  // token cycling mid-chat never logs the user out. `refreshAndSyncGate` also re-syncs the cached
112719
113348
  // gate flag so a definitively-revoked session re-gates the chat cleanly (no stale "signed in").
@@ -112721,9 +113350,9 @@ async function main() {
112721
113350
  );
112722
113351
  let brainInstance;
112723
113352
  const brain = () => {
112724
- brainInstance ??= (0, import_client_core43.createHostBrain)({
113353
+ brainInstance ??= (0, import_client_core44.createHostBrain)({
112725
113354
  topology: config.brainTopology,
112726
- resolveBinary: () => (0, import_client_core43.resolveBrainBinary)({
113355
+ resolveBinary: () => (0, import_client_core44.resolveBrainBinary)({
112727
113356
  configPath: config.brainPath,
112728
113357
  env: process.env,
112729
113358
  bundledCandidates: bundledBrainCandidates()
@@ -112738,10 +113367,10 @@ async function main() {
112738
113367
  });
112739
113368
  return brainInstance;
112740
113369
  };
112741
- const turnTransport = (0, import_client_core43.createTurnTransport)({
113370
+ const turnTransport = (0, import_client_core44.createTurnTransport)({
112742
113371
  mode: config.brain,
112743
113372
  bridge,
112744
- makeLocal: () => new import_client_core43.LocalBrainTransport({
113373
+ makeLocal: () => new import_client_core44.LocalBrainTransport({
112745
113374
  // Proactive freshness: the brain holds this bearer for a whole segment and cannot
112746
113375
  // ride the bridge's reactive 401-refresh — so validate-or-refresh before hand-off.
112747
113376
  authToken: async () => await session.currentFreshAccessToken() ?? process.env.ORION_AUTH_TOKEN ?? null,
@@ -112749,14 +113378,14 @@ async function main() {
112749
113378
  connect: () => brain().connect()
112750
113379
  })
112751
113380
  });
112752
- const codebaseIndexFallback = new import_client_core42.WorkspaceIndexStore();
112753
- const ripgrep = new import_client_core43.NodeRipgrepLocator({
113381
+ const codebaseIndexFallback = new import_client_core43.WorkspaceIndexStore();
113382
+ const ripgrep = new import_client_core44.NodeRipgrepLocator({
112754
113383
  // Bundled-first rg: ships as an optionalDependency of this package, so an
112755
113384
  // `npm i -g` user gets fast search with nothing else installed. Resolved
112756
113385
  // from THIS package's node_modules via require.resolve (nested and hoisted
112757
113386
  // layouts both work); absent (install offline / postinstall failed) → the
112758
113387
  // locator falls through to PATH + well-known paths exactly as before.
112759
- bundledCandidates: () => (0, import_client_core43.vscodeRipgrepCandidates)((specifier) => __require.resolve(specifier))
113388
+ bundledCandidates: () => (0, import_client_core44.vscodeRipgrepCandidates)((specifier) => __require.resolve(specifier))
112760
113389
  });
112761
113390
  const indexer = createIndexer(
112762
113391
  bridge,
@@ -112788,21 +113417,21 @@ async function main() {
112788
113417
  );
112789
113418
  void indexer.start().catch(() => void 0);
112790
113419
  initIndexModeService({ appStore, setMode: (m2) => indexer.setMode(m2) });
112791
- const permissionStore = new import_client_core43.PermissionSettingsStore({ workspaceRoot: config.workspaceRoot });
113420
+ const permissionStore = new import_client_core44.PermissionSettingsStore({ workspaceRoot: config.workspaceRoot });
112792
113421
  await permissionStore.load();
112793
- const executor = new import_client_core42.ToolExecutor(
113422
+ const executor = new import_client_core43.ToolExecutor(
112794
113423
  () => config.workspaceRoot,
112795
113424
  // The session's EFFECTIVE mode — the same turbo⇒full_access law the wire rides
112796
113425
  // (`currentRouting`), never the bare store mode: the executor's membership
112797
113426
  // backstop must agree with the gate that already ruled on each call. Loop-run
112798
113427
  // sessions never enable turbo on the bridge, so they keep the configured mode
112799
113428
  // their own wire rides.
112800
- (sessionId2) => (0, import_client_core43.effectiveWirePermissionMode)(
113429
+ (sessionId2) => (0, import_client_core44.effectiveWirePermissionMode)(
112801
113430
  sessionId2 !== void 0 && bridge.isTurboModeEnabledForSession(sessionId2),
112802
113431
  appStore.getState().permissionMode
112803
113432
  ),
112804
113433
  secrets,
112805
- new import_client_core43.NullLspProvider(),
113434
+ new import_client_core44.NullLspProvider(),
112806
113435
  ripgrep,
112807
113436
  nullFrameSinkFactory,
112808
113437
  fallbackBrowserConfig,
@@ -112925,11 +113554,11 @@ async function main() {
112925
113554
  }
112926
113555
  renderLane(transcriptStore, appStore, ev);
112927
113556
  if (ev.event === "usage_recorded") {
112928
- (0, import_client_core42.recordTurnMetrics)({
113557
+ (0, import_client_core43.recordTurnMetrics)({
112929
113558
  app: "tui",
112930
113559
  sessionId,
112931
113560
  workspaceRoot: currentRouting().workspaceRoot,
112932
- turn: (0, import_client_core42.turnMetricsFromUsageRecorded)(ev.data ?? {})
113561
+ turn: (0, import_client_core43.turnMetricsFromUsageRecorded)(ev.data ?? {})
112933
113562
  });
112934
113563
  }
112935
113564
  if (ev.event === "file_modified") {
@@ -112953,7 +113582,7 @@ async function main() {
112953
113582
  sessionSub = bridge.onSessionEvent(sid, onSessionStreamEvent);
112954
113583
  };
112955
113584
  let goalRunner = null;
112956
- const cronController = new import_client_core43.CronController({
113585
+ const cronController = new import_client_core44.CronController({
112957
113586
  submitTurn: (prompt) => sendTurn(prompt, "\u27F3 scheduled", void 0, "system"),
112958
113587
  isBusy: () => appStore.getState().status === "streaming",
112959
113588
  persistence: fileCronPersistence(config.workspaceRoot)
@@ -113134,6 +113763,17 @@ async function main() {
113134
113763
  );
113135
113764
  }
113136
113765
  });
113766
+ registry.register({
113767
+ name: "replan",
113768
+ description: "Duet: invalidate the standing plan (the next request runs the planner)",
113769
+ argumentHint: "",
113770
+ kind: "local",
113771
+ run: (_args, ctx) => {
113772
+ const flagged = (0, import_client_core44.invalidateStandingPlan)(ctx.appStore.getState().duetPlan);
113773
+ if (flagged) ctx.appStore.setState((s) => ({ ...s, duetPlan: flagged }));
113774
+ ctx.print((0, import_client_core44.duetReplanCommandNote)(flagged !== null));
113775
+ }
113776
+ });
113137
113777
  const getCompletions = (input) => {
113138
113778
  if (input.startsWith("/")) skillSlash.ensureFresh();
113139
113779
  return registry.complete(input).map((c3) => ({
@@ -113149,8 +113789,8 @@ async function main() {
113149
113789
  const anywhere = new Set(
113150
113790
  registry.all().filter((c3) => c3.source === "skill").map((c3) => c3.name)
113151
113791
  );
113152
- const ranges = (0, import_client_core43.scanSlashTokenRanges)(v2, anywhere);
113153
- const lead = (0, import_client_core43.matchSlashToken)(v2);
113792
+ const ranges = (0, import_client_core44.scanSlashTokenRanges)(v2, anywhere);
113793
+ const lead = (0, import_client_core44.matchSlashToken)(v2);
113154
113794
  if (lead && !anywhere.has(lead.name) && registry.get(lead.name)) {
113155
113795
  const start2 = v2.indexOf("/");
113156
113796
  ranges.unshift({ start: start2, end: start2 + lead.name.length + 1 });
@@ -113159,7 +113799,7 @@ async function main() {
113159
113799
  return ranges;
113160
113800
  };
113161
113801
  let fileEntries = [];
113162
- void new import_client_core38.NodeFileSource(config.workspaceRoot).findFiles("**/*", "{**/node_modules/**,**/.git/**,**/dist/**,**/build/**}", 5e3).then((abs) => {
113802
+ void new import_client_core39.NodeFileSource(config.workspaceRoot).findFiles("**/*", "{**/node_modules/**,**/.git/**,**/dist/**,**/build/**}", 5e3).then((abs) => {
113163
113803
  fileEntries = withDirectories(
113164
113804
  abs.map((p) => path12.relative(config.workspaceRoot, p).split(path12.sep).join("/"))
113165
113805
  );
@@ -113186,7 +113826,7 @@ async function main() {
113186
113826
  if (turn && streaming && !turn.cancelRequested && turn.phase === "stream") {
113187
113827
  turn.cancelRequested = true;
113188
113828
  outcomes.report({ kind: "cancel_context", kept_edits: turn.hadEdits });
113189
- turn.disposeFallback = (0, import_client_core43.armGracefulCancel)({
113829
+ turn.disposeFallback = (0, import_client_core44.armGracefulCancel)({
113190
113830
  controller: turn.abort,
113191
113831
  sendCancel: () => turnTransport.cancelTurn(turn.sessionId)
113192
113832
  });
@@ -113214,6 +113854,9 @@ async function main() {
113214
113854
  });
113215
113855
  };
113216
113856
  const boundary = createBoundaryHandlers({
113857
+ duetExecutingNote: () => {
113858
+ transcriptStore.setState((s) => appendNote(s, duetPhaseNoteText("executing")));
113859
+ },
113217
113860
  bridge,
113218
113861
  executor,
113219
113862
  appStore,
@@ -113242,7 +113885,7 @@ async function main() {
113242
113885
  };
113243
113886
  const heldAgentReports = [];
113244
113887
  let inboundPeerHop = null;
113245
- const agentManager = new import_client_core43.AgentManager((0, import_client_core43.brainAwareAgentTransport)(bridge, turnTransport), executor, async () => {
113888
+ const agentManager = new import_client_core44.AgentManager((0, import_client_core44.brainAwareAgentTransport)(bridge, turnTransport), executor, async () => {
113246
113889
  const result = await bridge.rpc("list_personas", {});
113247
113890
  return result.personas ?? [];
113248
113891
  });
@@ -113252,8 +113895,8 @@ async function main() {
113252
113895
  agentManager.attachOutcomeSink((outcome) => {
113253
113896
  oVaultSessions.for(outcome.parentSessionId, currentRouting().workspaceRoot)?.recordSiblingOutcome(outcome);
113254
113897
  });
113255
- void (0, import_client_core43.loadAgentDefs)(config.workspaceRoot).then((defs) => agentManager.prime(defs));
113256
- const workGraphManager = new import_client_core43.WorkGraphManager({ agents: agentManager, tools: executor });
113898
+ void (0, import_client_core44.loadAgentDefs)(config.workspaceRoot).then((defs) => agentManager.prime(defs));
113899
+ const workGraphManager = new import_client_core44.WorkGraphManager({ agents: agentManager, tools: executor });
113257
113900
  workGraphManager.registerTools(executor);
113258
113901
  const workPlanApproval = new WorkPlanApprovalBridge();
113259
113902
  function rejectPendingWorkPlan() {
@@ -113276,7 +113919,7 @@ async function main() {
113276
113919
  workRunTicker = setInterval(() => {
113277
113920
  const record = liveRunRecord;
113278
113921
  if (!record) return stopWorkRunTicker();
113279
- const view = (0, import_client_core43.buildRunGraphView)(record, agentManager.agentsFor(sessionId), Date.now(), tuiFlowBudget());
113922
+ const view = (0, import_client_core44.buildRunGraphView)(record, agentManager.agentsFor(sessionId), Date.now(), tuiFlowBudget());
113280
113923
  appStore.setState(
113281
113924
  (s) => s.workRun ? { ...s, workRun: { ...s.workRun, view } } : s
113282
113925
  );
@@ -113287,8 +113930,10 @@ async function main() {
113287
113930
  workGraphManager.attachParent(sid, {
113288
113931
  workspaceRoot: () => currentRouting().workspaceRoot ?? config.workspaceRoot,
113289
113932
  knownPersonas: () => agentManager.knownTypes(),
113290
- // Plan mode switches submit to the read-only doctrine (inert graphs, no approval card).
113291
- chatMode: () => currentRouting().mode,
113933
+ // Plan mode switches submit to the read-only doctrine (inert graphs, no approval
113934
+ // card). LEG mode: duet's planning leg is the same read-only doctrine, and its
113935
+ // execution leg is not (mirrors the IDE/Power App).
113936
+ chatMode: () => legMode(),
113292
113937
  requestApproval: (plan) => workPlanApproval.request(
113293
113938
  plan,
113294
113939
  (pending) => appStore.setState((s) => ({ ...s, pendingWorkPlan: pending }))
@@ -113300,11 +113945,11 @@ async function main() {
113300
113945
  const status = appStore.getState().status;
113301
113946
  if (status !== "idle" && status !== "error") return;
113302
113947
  if (heldAgentReports.length === 0) return;
113303
- sendTurn(import_client_core43.SUBAGENT_WAKE_PROMPT, void 0, void 0, "system");
113948
+ sendTurn(import_client_core44.SUBAGENT_WAKE_PROMPT, void 0, void 0, "system");
113304
113949
  },
113305
113950
  onRunUpdate: (record) => {
113306
113951
  liveRunRecord = record;
113307
- const view = (0, import_client_core43.buildRunGraphView)(record, agentManager.agentsFor(sessionId), Date.now(), tuiFlowBudget());
113952
+ const view = (0, import_client_core44.buildRunGraphView)(record, agentManager.agentsFor(sessionId), Date.now(), tuiFlowBudget());
113308
113953
  if (view.live) {
113309
113954
  startWorkRunTicker();
113310
113955
  appStore.setState((s) => ({
@@ -113343,9 +113988,12 @@ async function main() {
113343
113988
  attachWorkGraphParent(sessionId);
113344
113989
  const attachAgentParent = (sid) => {
113345
113990
  agentManager.attachParent(sid, {
113346
- routing: () => currentRouting(),
113991
+ // LEG mode overrides the session's raw mode for the spawn capture: a duet parent's
113992
+ // children are read-only planners during the planning leg and ordinary coders during
113993
+ // execution — never "duet" agents themselves (mirrors the IDE/Power App).
113994
+ routing: () => ({ ...currentRouting(), mode: legMode() }),
113347
113995
  clientCapabilities: () => [
113348
- ...(0, import_client_core42.platformCapabilities)(),
113996
+ ...(0, import_client_core43.platformCapabilities)(),
113349
113997
  ...appStore.getState().subagentsEnabled ? ["subagents"] : []
113350
113998
  ],
113351
113999
  transcript: () => transcriptStore.getState().messages,
@@ -113354,7 +114002,7 @@ async function main() {
113354
114002
  const status = appStore.getState().status;
113355
114003
  if (status !== "idle" && status !== "error") return;
113356
114004
  if (heldAgentReports.length === 0) return;
113357
- sendTurn(import_client_core43.SUBAGENT_WAKE_PROMPT, void 0, void 0, "system");
114005
+ sendTurn(import_client_core44.SUBAGENT_WAKE_PROMPT, void 0, void 0, "system");
113358
114006
  },
113359
114007
  onLifecycle: (ev) => onRenderEvent({
113360
114008
  event: "agent_lifecycle",
@@ -113390,7 +114038,7 @@ async function main() {
113390
114038
  timestamp: Date.now(),
113391
114039
  data
113392
114040
  }),
113393
- getOrionResources: () => (0, import_client_core42.buildOrionSnapshot)(config.workspaceRoot, void 0, sid),
114041
+ getOrionResources: () => (0, import_client_core43.buildOrionSnapshot)(config.workspaceRoot, void 0, sid),
113394
114042
  // Full-dose source for review-persona children (lesson dosing) — the same
113395
114043
  // attention payload the parent turn itself ships.
113396
114044
  oVaultAttention: () => {
@@ -113418,6 +114066,11 @@ async function main() {
113418
114066
  attachWorkGraphParent(newSid);
113419
114067
  };
113420
114068
  attachAgentParent(sessionId);
114069
+ const legMode = () => {
114070
+ const a = appStore.getState();
114071
+ if (a.mode !== "duet") return a.mode;
114072
+ return a.duetExecutionStarted ? "code" : "plan";
114073
+ };
113421
114074
  const currentRouting = () => {
113422
114075
  const a = appStore.getState();
113423
114076
  const custom = (0, import_client_core8.endpointRoutingFor)(a.provider);
@@ -113430,7 +114083,7 @@ async function main() {
113430
114083
  // the /turbo-toggle vs --fully-automatic gap: the flag already overrides the
113431
114084
  // store mode at launch (launchPermissionMode); the toggle now buys the same
113432
114085
  // backend posture, so no ask is ever born and batch-mates stop deferring.
113433
- permissionMode: (0, import_client_core43.effectiveWirePermissionMode)(
114086
+ permissionMode: (0, import_client_core44.effectiveWirePermissionMode)(
113434
114087
  bridge.isTurboModeEnabledForSession(sessionId),
113435
114088
  a.permissionMode
113436
114089
  ),
@@ -113450,8 +114103,8 @@ async function main() {
113450
114103
  sandboxAvailable: SANDBOX_AVAILABLE
113451
114104
  };
113452
114105
  };
113453
- const oVaultSessions = new import_client_core42.OVaultSessions(() => process.env.ORION_OVAULT_CAPTURE !== "0");
113454
- oVaultSessions.syncRunner = new import_client_core42.OVaultSyncRunner({
114106
+ const oVaultSessions = new import_client_core43.OVaultSessions(() => process.env.ORION_OVAULT_CAPTURE !== "0");
114107
+ oVaultSessions.syncRunner = new import_client_core43.OVaultSyncRunner({
113455
114108
  auth: {
113456
114109
  apiBaseUrl: () => config.accountsApiUrl,
113457
114110
  accessToken: () => session.currentAccessToken(),
@@ -113509,7 +114162,7 @@ async function main() {
113509
114162
  return;
113510
114163
  }
113511
114164
  }
113512
- if (lastTurnComplete?.sessionId === sid && Date.now() - lastTurnComplete.at < import_client_core43.REPHRASE_WINDOW_MS) {
114165
+ if (lastTurnComplete?.sessionId === sid && Date.now() - lastTurnComplete.at < import_client_core44.REPHRASE_WINDOW_MS) {
113513
114166
  outcomes.report({ kind: "rephrase" });
113514
114167
  }
113515
114168
  triggerSecurityCapabilitiesRefresh(bridge, appStore);
@@ -113527,10 +114180,11 @@ async function main() {
113527
114180
  };
113528
114181
  try {
113529
114182
  const peerAgents = await presence.registry.peersForWire(sid).catch(() => []);
113530
- const outcome = await (0, import_client_core42.driveTurn)(
114183
+ const outcome = await (0, import_client_core43.driveTurn)(
113531
114184
  turnTransport,
113532
114185
  {
113533
114186
  sessionId: sid,
114187
+ duetPlan: appStore.getState().mode === "duet" ? appStore.getState().duetPlan : null,
113534
114188
  ...start2.skill ? { skill: start2.skill } : { text: start2.text ?? "" },
113535
114189
  ...start2.attachments && start2.attachments.length > 0 ? { attachments: start2.attachments } : {},
113536
114190
  // Replay the COMMITTED transcript (the pre-submit snapshot — NOT the live
@@ -113548,10 +114202,13 @@ async function main() {
113548
114202
  // `workgraph` rides the same switch as the fan-out family: a work graph IS a
113549
114203
  // fan-out (its phases are sub-agents), so turning sub-agents off must hide both.
113550
114204
  clientCapabilities: [
113551
- ...(0, import_client_core42.platformCapabilities)(),
114205
+ ...(0, import_client_core43.platformCapabilities)(),
113552
114206
  ...appStore.getState().subagentsEnabled ? ["scheduling", "subagents", "workgraph"] : ["scheduling"],
113553
114207
  // This terminal can RECEIVE a peer message, so it may also address them.
113554
- "agent_messaging"
114208
+ "agent_messaging",
114209
+ // This host owns a standing-plan record and can clear it, so Duet's
114210
+ // `request_replan` may be offered (further leg-gated backend-side).
114211
+ import_client_core44.DUET_REPLAN_CAPABILITY
113555
114212
  ],
113556
114213
  extraBody: {
113557
114214
  ...appStore.getState().subagentsEnabled ? agentManager.parentExtraBody() : {},
@@ -113568,7 +114225,7 @@ async function main() {
113568
114225
  // Ship the `.orion` snapshot so the backend's begin-turn loaders read
113569
114226
  // config / sub-agent defs / skills / hooks / memory / plugins from the
113570
114227
  // body — no live client-read channel in the stateless segment model.
113571
- getOrionResources: () => (0, import_client_core42.buildOrionSnapshot)(currentRouting().workspaceRoot, void 0, sid),
114228
+ getOrionResources: () => (0, import_client_core43.buildOrionSnapshot)(currentRouting().workspaceRoot, void 0, sid),
113572
114229
  getFileHistoryManifest: () => executor.fileHistoryManifest(sid),
113573
114230
  // Lesson-recall anchors: the TUI has no editor attention, so recently-touched
113574
114231
  // paths from the capture observer are the attention set.
@@ -113578,7 +114235,7 @@ async function main() {
113578
114235
  return { active: null, open: [], touched, related: executor.oVaultRelatedPaths?.(touched) ?? [] };
113579
114236
  }
113580
114237
  },
113581
- (0, import_client_core42.withOVault)(
114238
+ (0, import_client_core43.withOVault)(
113582
114239
  {
113583
114240
  ...boundary.makeHandlers(sid, ac.signal, onEvent),
113584
114241
  // Stops the driver from POSTING the next segment when the user cancelled at a
@@ -113590,7 +114247,7 @@ async function main() {
113590
114247
  onToolResult: (payload) => {
113591
114248
  if (payload.terminal_savings) {
113592
114249
  terminalSavings.push(payload.terminal_savings);
113593
- (0, import_client_core42.recordTurnMetrics)({
114250
+ (0, import_client_core43.recordTurnMetrics)({
113594
114251
  app: "tui",
113595
114252
  sessionId: sid,
113596
114253
  workspaceRoot: currentRouting().workspaceRoot,
@@ -113624,12 +114281,12 @@ async function main() {
113624
114281
  settleOutcome = "completed";
113625
114282
  lastTurnComplete = { sessionId: sid, at: Date.now() };
113626
114283
  const data = outcome.event.data ?? {};
113627
- endSettle = { kind: "complete", finalText: (0, import_client_core43.finalAssistantTextFromWire)(data.messages) };
113628
- (0, import_client_core42.recordTurnMetrics)({
114284
+ endSettle = { kind: "complete", finalText: (0, import_client_core44.finalAssistantTextFromWire)(data.messages) };
114285
+ (0, import_client_core43.recordTurnMetrics)({
113629
114286
  app: "tui",
113630
114287
  sessionId: sid,
113631
114288
  workspaceRoot: currentRouting().workspaceRoot,
113632
- turn: (0, import_client_core42.turnMetricsFromComplete)(data),
114289
+ turn: (0, import_client_core43.turnMetricsFromComplete)(data),
113633
114290
  terminalSavings
113634
114291
  });
113635
114292
  void oVaultSessions.reflectorFor(sid, currentRouting().workspaceRoot, bridge)?.run("turn_complete").finally(
@@ -113673,12 +114330,26 @@ async function main() {
113673
114330
  } finally {
113674
114331
  turn.disposeFallback?.();
113675
114332
  if (currentTurn === turn) {
114333
+ const st2 = appStore.getState();
114334
+ if (st2.duetPlan && st2.mode === "duet") {
114335
+ const folded = (0, import_client_core44.foldDuetTurnEnd)(st2.duetPlan, st2.duetExecutionStarted, settleOutcome);
114336
+ appStore.setState((s2) => ({ ...s2, duetPlan: folded }));
114337
+ }
113676
114338
  settleSteerQueue({
113677
114339
  app: appStore,
113678
114340
  isBusy: () => currentTurn !== null || goalRunner !== null,
113679
114341
  send: sendTurn,
113680
114342
  runCommand: routeInput
113681
114343
  });
114344
+ const replanReason = pendingDuetReplan;
114345
+ pendingDuetReplan = null;
114346
+ if (replanReason !== null && settleOutcome === "completed" && appStore.getState().mode === "duet") {
114347
+ setTimeout(() => {
114348
+ sendTurn((0, import_client_core44.duetReplanFollowupPrompt)(replanReason), void 0, void 0, "system", {
114349
+ ifBusy: "decline"
114350
+ });
114351
+ }, 0);
114352
+ }
113682
114353
  }
113683
114354
  if (currentTurn === turn) currentTurn = null;
113684
114355
  fireTurnEnd();
@@ -113718,6 +114389,8 @@ async function main() {
113718
114389
  status: "streaming",
113719
114390
  statusText: "thinking\u2026",
113720
114391
  error: null,
114392
+ duetExecutionStarted: false,
114393
+ // a fresh turn plans again — the leg record is per-turn
113721
114394
  // A REMOTE send brought its own photos — the local user's pasted ones belong to
113722
114395
  // whatever they are still typing and must survive it. Only a local send consumes
113723
114396
  // them (it just did, via prunePastedImages above).
@@ -113730,6 +114403,7 @@ async function main() {
113730
114403
  // the last await ended; still-running children keep their rows.
113731
114404
  subAgents: s.subAgents.filter((a) => a.phase !== "finished")
113732
114405
  }));
114406
+ beginDuetPhase(text);
113733
114407
  void runTurn({ text, attachments, origin, onTurnEnd: opts?.onTurnEnd }, snapshot);
113734
114408
  return "started";
113735
114409
  };
@@ -113753,6 +114427,8 @@ async function main() {
113753
114427
  status: "streaming",
113754
114428
  statusText: "running skill\u2026",
113755
114429
  error: null,
114430
+ duetExecutionStarted: false,
114431
+ // a fresh turn plans again — the leg record is per-turn
113756
114432
  turnOutputTokens: 0,
113757
114433
  // reset the live meter before turn_started arrives
113758
114434
  scrollBack: 0,
@@ -113760,14 +114436,21 @@ async function main() {
113760
114436
  // Sweep SETTLED fleet rows (matches sendTurn) — a skill turn is a turn.
113761
114437
  subAgents: s.subAgents.filter((a) => a.phase !== "finished")
113762
114438
  }));
114439
+ beginDuetPhase("");
113763
114440
  void runTurn({ skill: { name: name2, args: args2 } }, snapshot);
113764
114441
  };
113765
114442
  cronController.start();
113766
114443
  executor.registerHostTool("schedule_task", makeScheduleTaskHandler(cronController));
114444
+ executor.registerHostTool(import_client_core44.DUET_REPLAN_TOOL, async (params) => {
114445
+ const flagged = (0, import_client_core44.invalidateStandingPlan)(appStore.getState().duetPlan);
114446
+ if (flagged) appStore.setState((s) => ({ ...s, duetPlan: flagged }));
114447
+ pendingDuetReplan = typeof params.reason === "string" ? params.reason : "";
114448
+ return (0, import_client_core44.duetReplanResult)(flagged !== null);
114449
+ });
113767
114450
  const loopService = new LoopService({
113768
114451
  workspaceRoot: config.workspaceRoot,
113769
- schedulePath: loopSchedulePathFor((0, import_client_core43.runsRootFor)("loops", config.workspaceRoot)),
113770
- transport: (0, import_client_core43.brainAwareAgentTransport)(bridge, turnTransport),
114452
+ schedulePath: loopSchedulePathFor((0, import_client_core44.runsRootFor)("loops", config.workspaceRoot)),
114453
+ transport: (0, import_client_core44.brainAwareAgentTransport)(bridge, turnTransport),
113771
114454
  tools: executor,
113772
114455
  // The CONFIGURED mode rides here deliberately, not the turbo-effective one
113773
114456
  // (currentRouting applies the turbo→full_access law): a loop is standing
@@ -113814,12 +114497,12 @@ async function main() {
113814
114497
  }));
113815
114498
  return;
113816
114499
  }
113817
- const runner = new import_client_core43.GoalRunner({ runTurn: runGoalTurn });
114500
+ const runner = new import_client_core44.GoalRunner({ runTurn: runGoalTurn });
113818
114501
  goalRunner = runner;
113819
114502
  transcriptStore.setState((s) => appendNote(s, `Goal started \u2014 working until complete: ${goal}`));
113820
114503
  void runner.run(goal).then((reason) => {
113821
114504
  if (goalRunner === runner) goalRunner = null;
113822
- transcriptStore.setState((s) => appendNote(s, (0, import_client_core43.describeGoalEnd)(reason)));
114505
+ transcriptStore.setState((s) => appendNote(s, (0, import_client_core44.describeGoalEnd)(reason)));
113823
114506
  settleSteerQueue({
113824
114507
  app: appStore,
113825
114508
  isBusy: () => currentTurn !== null || goalRunner !== null,
@@ -113859,10 +114542,10 @@ async function main() {
113859
114542
  steer: (text) => enqueueMachineSteer(text),
113860
114543
  deliverAgentMessage: (message) => {
113861
114544
  inboundPeerHop = Math.max(inboundPeerHop ?? 0, message.hop);
113862
- heldAgentReports.push((0, import_client_core43.formatAgentMessage)(message));
114545
+ heldAgentReports.push((0, import_client_core44.formatAgentMessage)(message));
113863
114546
  const status = appStore.getState().status;
113864
114547
  if (status !== "idle" && status !== "error") return;
113865
- sendTurn((0, import_client_core43.peerMessageWakePrompt)(message), void 0, void 0, "system");
114548
+ sendTurn((0, import_client_core44.peerMessageWakePrompt)(message), void 0, void 0, "system");
113866
114549
  },
113867
114550
  resolvePermission: (requestId, decision, sid) => {
113868
114551
  const pending = appStore.getState().pendingPermissions.some((p) => p.data.request_id === requestId);
@@ -114025,25 +114708,25 @@ async function main() {
114025
114708
  defaultApiUrl: config.apiUrl,
114026
114709
  entries,
114027
114710
  add: async (entry) => {
114028
- await (0, import_client_core43.saveCustomProvider)(entry, "user", opts);
114029
- (0, import_client_core43.clearEndpointCatalog)(entry.baseUrl);
114030
- panel(await (0, import_client_core43.loadCustomProviders)(opts));
114711
+ await (0, import_client_core44.saveCustomProvider)(entry, "user", opts);
114712
+ (0, import_client_core44.clearEndpointCatalog)(entry.baseUrl);
114713
+ panel(await (0, import_client_core44.loadCustomProviders)(opts));
114031
114714
  },
114032
114715
  remove: async (name2) => {
114033
114716
  for (const tier of ["user", "project", "local"]) {
114034
- if (await (0, import_client_core43.removeCustomProvider)(name2, tier, opts)) break;
114717
+ if (await (0, import_client_core44.removeCustomProvider)(name2, tier, opts)) break;
114035
114718
  }
114036
114719
  (0, import_client_core8.clearEndpointRouting)();
114037
- (0, import_client_core43.clearEndpointCatalog)();
114038
- panel(await (0, import_client_core43.loadCustomProviders)(opts));
114720
+ (0, import_client_core44.clearEndpointCatalog)();
114721
+ panel(await (0, import_client_core44.loadCustomProviders)(opts));
114039
114722
  },
114040
- probe: (baseUrl, apiKey) => (0, import_client_core43.probeModels)(baseUrl, apiKey),
114723
+ probe: (baseUrl, apiKey) => (0, import_client_core44.probeModels)(baseUrl, apiKey),
114041
114724
  // A saved endpoint's models come from the CACHED catalog — opening one costs no
114042
114725
  // network, so limits stay editable long after the endpoint was added.
114043
114726
  modelsOf: (entry) => (0, import_client_core8.endpointModelViews)(entry),
114044
114727
  updateModels: async (name2, update) => {
114045
114728
  await (0, import_client_core8.updateCustomProviderModels)(name2, update, "user", opts);
114046
- panel(await (0, import_client_core43.loadCustomProviders)(opts));
114729
+ panel(await (0, import_client_core44.loadCustomProviders)(opts));
114047
114730
  },
114048
114731
  use: async (name2, model) => {
114049
114732
  const provider = `custom:${name2}`;
@@ -114061,7 +114744,7 @@ async function main() {
114061
114744
  }
114062
114745
  }
114063
114746
  }));
114064
- void (0, import_client_core43.loadCustomProviders)(opts).then(panel);
114747
+ void (0, import_client_core44.loadCustomProviders)(opts).then(panel);
114065
114748
  }
114066
114749
  };
114067
114750
  const routeInput = (text) => routeChatInput(text, {
@@ -114070,7 +114753,7 @@ async function main() {
114070
114753
  addMemory: (note) => void addMemoryLine(note),
114071
114754
  resolveCommand: async (line) => {
114072
114755
  let parsed = registry.parse(line);
114073
- if (!parsed && (0, import_client_core43.matchSlashToken)(line)) {
114756
+ if (!parsed && (0, import_client_core44.matchSlashToken)(line)) {
114074
114757
  await skillSlash.refresh().catch(() => void 0);
114075
114758
  parsed = registry.parse(line);
114076
114759
  }