@cydm/pie 2.7.12 → 2.7.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -29,10 +29,7 @@ import {
29
29
  migrateConfigFromAgentDir,
30
30
  setYoloGrantListener,
31
31
  truncateHeadTail
32
- } from "./chunks/chunk-YI3CSQGD.js";
33
- import {
34
- resolveCliProjectRoot
35
- } from "./chunks/chunk-WLFOBECN.js";
32
+ } from "./chunks/chunk-FOE2AW4L.js";
36
33
  import {
37
34
  AGENTS_CONTEXT_FILE_NAME,
38
35
  AgentSessionController,
@@ -94,8 +91,8 @@ import {
94
91
  shouldPreserveExecutionStateForUserText,
95
92
  supersedeExecutionState,
96
93
  verifyPreparedCompactionCommit
97
- } from "./chunks/chunk-AFPRX5XI.js";
98
- import "./chunks/chunk-2NBUFVUQ.js";
94
+ } from "./chunks/chunk-VPTLDLI6.js";
95
+ import "./chunks/chunk-5YU6MU2N.js";
99
96
  import {
100
97
  Deref,
101
98
  Errors,
@@ -118,7 +115,13 @@ import {
118
115
  sortToolModelCandidatesByCapability,
119
116
  streamSimple,
120
117
  type_exports
121
- } from "./chunks/chunk-EN47TIBG.js";
118
+ } from "./chunks/chunk-N4252GH3.js";
119
+ import {
120
+ readImageFormat
121
+ } from "./chunks/chunk-F7EBZTZO.js";
122
+ import {
123
+ resolveCliProjectRoot
124
+ } from "./chunks/chunk-WLFOBECN.js";
122
125
  import {
123
126
  IsArray,
124
127
  IsBigInt,
@@ -52611,18 +52614,18 @@ function validateRemoteModel(profileId, model) {
52611
52614
  validateWebSearchCapability(model.webSearch, `Remote profile "${profileId}" model "${model.id}" webSearch`);
52612
52615
  validateFileCapabilities(model.fileCapabilities, `Remote profile "${profileId}" model "${model.id}" fileCapabilities`);
52613
52616
  }
52614
- function assertHeadersShape(headers, label) {
52615
- if (headers === void 0) return;
52616
- if (!isPlainRecord(headers)) throw new Error(`${label} headers must be an object`);
52617
- for (const [name, value] of Object.entries(headers)) {
52617
+ function assertHeadersShape(headers2, label) {
52618
+ if (headers2 === void 0) return;
52619
+ if (!isPlainRecord(headers2)) throw new Error(`${label} headers must be an object`);
52620
+ for (const [name, value] of Object.entries(headers2)) {
52618
52621
  if (!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name)) throw new Error(`${label} header name ${name || "(empty)"} is invalid`);
52619
52622
  if (typeof value !== "string") throw new Error(`${label} header ${name} must be a string`);
52620
52623
  if (/[\0-\x08\x0A-\x1F\x7F]/.test(value)) throw new Error(`${label} header ${name} contains an invalid control character`);
52621
52624
  }
52622
52625
  }
52623
- function assertRemoteHeadersSafe(headers, label) {
52624
- assertHeadersShape(headers, label);
52625
- for (const name of Object.keys(headers || {})) {
52626
+ function assertRemoteHeadersSafe(headers2, label) {
52627
+ assertHeadersShape(headers2, label);
52628
+ for (const name of Object.keys(headers2 || {})) {
52626
52629
  if (/(?:authorization|cookie|api[-_]?key|token|secret|credential)/i.test(name)) {
52627
52630
  throw new Error(`${label} must not provide credential-bearing header ${name}`);
52628
52631
  }
@@ -53252,10 +53255,10 @@ var ModelRegistry = class {
53252
53255
  let payload = cached?.payload;
53253
53256
  let response;
53254
53257
  try {
53255
- const headers = { Authorization: `Bearer ${apiKey}` };
53256
- if (cached?.etag) headers["If-None-Match"] = cached.etag;
53258
+ const headers2 = { Authorization: `Bearer ${apiKey}` };
53259
+ if (cached?.etag) headers2["If-None-Match"] = cached.etag;
53257
53260
  response = await fetch(url, {
53258
- headers,
53261
+ headers: headers2,
53259
53262
  redirect: "manual",
53260
53263
  signal: AbortSignal.timeout(3e3)
53261
53264
  });
@@ -56533,6 +56536,15 @@ function createExtensionContext(extension, cwd, uiContext, abortFn, isIdleFn, ha
56533
56536
  sendUserMessage(content) {
56534
56537
  actions?.sendUserMessage(content);
56535
56538
  },
56539
+ ...actions?.attachLocalFile ? {
56540
+ attachLocalFile: (path34, displayName) => actions.attachLocalFile(path34, displayName)
56541
+ } : {},
56542
+ ...actions?.beginUserInput ? {
56543
+ beginUserInput: (isCurrent) => actions.beginUserInput(isCurrent)
56544
+ } : {},
56545
+ ...actions?.attachLocalFileAndSubmit ? {
56546
+ attachLocalFileAndSubmit: (path34, displayName, submitText) => actions.attachLocalFileAndSubmit(path34, displayName, submitText)
56547
+ } : {},
56536
56548
  setPlanMode(enabled, options) {
56537
56549
  actions?.setPlanMode(enabled, options);
56538
56550
  },
@@ -63659,10 +63671,37 @@ var Spacer = class {
63659
63671
 
63660
63672
  // ../../packages/tui/src/stdin-buffer.ts
63661
63673
  import { EventEmitter } from "events";
63674
+
63675
+ // ../../packages/tui/src/clipboard-framing.ts
63676
+ var headers = [
63677
+ { kind: "osc", prefix: "\x1B]5522" },
63678
+ { kind: "csi", prefix: "\x1B[?5522" }
63679
+ ];
63680
+ function clipboardFrameEnd(data, kind) {
63681
+ const match = kind === "osc" ? /\x07|\x1b\\/.exec(data) : /[\x40-\x7e]/.exec(data);
63682
+ return match ? match.index + match[0].length : void 0;
63683
+ }
63684
+ function classifyClipboardFragment(data, pending = false) {
63685
+ if (!data) return void 0;
63686
+ for (const { kind, prefix } of headers) {
63687
+ if (prefix.startsWith(data)) {
63688
+ const ambiguous = data === "\x1B" || data === "\x1B[";
63689
+ if (!ambiguous || pending) return { kind, valid: false };
63690
+ } else if (data.startsWith(prefix)) {
63691
+ const end = clipboardFrameEnd(data.slice(2), kind);
63692
+ const length = end === void 0 ? void 0 : end + 2;
63693
+ const frame = length === void 0 ? data : data.slice(0, length);
63694
+ const valid = kind === "osc" ? frame.startsWith(`${prefix};`) : /^\x1b\[\?5522;[0-4]\$y$/.test(frame);
63695
+ return { kind, length, valid };
63696
+ }
63697
+ }
63698
+ return void 0;
63699
+ }
63700
+
63701
+ // ../../packages/tui/src/stdin-buffer.ts
63662
63702
  var ESC = "\x1B";
63663
63703
  var BRACKETED_PASTE_START = "\x1B[200~";
63664
63704
  var BRACKETED_PASTE_END = "\x1B[201~";
63665
- var OSC_5522_PREFIX = "\x1B]5522;";
63666
63705
  var OSC_5522_MAX_FRAME = 70 * 1024 * 1024;
63667
63706
  function isCompleteSequence(data) {
63668
63707
  if (!data.startsWith(ESC)) {
@@ -63750,16 +63789,29 @@ function isCompleteApcSequence(data) {
63750
63789
  }
63751
63790
  return "incomplete";
63752
63791
  }
63753
- function extractCompleteSequences(buffer, maxClipboardFrame = OSC_5522_MAX_FRAME) {
63792
+ function extractCompleteSequences(buffer, maxClipboardFrame = OSC_5522_MAX_FRAME, pending = false) {
63754
63793
  const sequences = [];
63755
63794
  let pos = 0;
63756
63795
  while (pos < buffer.length) {
63757
63796
  const remaining = buffer.slice(pos);
63797
+ const clipboard = classifyClipboardFragment(remaining, pending);
63798
+ if (clipboard) {
63799
+ if (clipboard.length === void 0) return { sequences, remainder: remaining };
63800
+ if (clipboard.valid && clipboard.length <= Math.min(maxClipboardFrame, clipboard.kind === "csi" ? 64 : Infinity)) {
63801
+ sequences.push(remaining.slice(0, clipboard.length));
63802
+ }
63803
+ pos += clipboard.length;
63804
+ continue;
63805
+ }
63806
+ if (remaining.startsWith(BRACKETED_PASTE_START)) {
63807
+ sequences.push(BRACKETED_PASTE_START);
63808
+ return { sequences, remainder: remaining.slice(BRACKETED_PASTE_START.length) };
63809
+ }
63758
63810
  if (remaining.startsWith(`${ESC}]`)) {
63759
63811
  const end = /\x07|\x1b\\/.exec(remaining);
63760
63812
  if (!end) return { sequences, remainder: remaining };
63761
63813
  const length = end.index + end[0].length;
63762
- if (!remaining.startsWith(OSC_5522_PREFIX) || length <= maxClipboardFrame) sequences.push(remaining.slice(0, length));
63814
+ sequences.push(remaining.slice(0, length));
63763
63815
  pos += length;
63764
63816
  continue;
63765
63817
  }
@@ -63796,7 +63848,8 @@ var StdinBuffer = class extends EventEmitter {
63796
63848
  timeoutMs;
63797
63849
  pasteMode = false;
63798
63850
  pasteBuffer = "";
63799
- discardingClipboard = false;
63851
+ discardingClipboard;
63852
+ clipboardStarted = 0;
63800
63853
  discardEsc = false;
63801
63854
  options;
63802
63855
  constructor(options = {}) {
@@ -63825,19 +63878,26 @@ var StdinBuffer = class extends EventEmitter {
63825
63878
  return;
63826
63879
  }
63827
63880
  if (this.discardingClipboard) {
63828
- const discarded = (this.discardEsc ? ESC : "") + str2;
63829
- const end = /\x07|\x1b\\/.exec(discarded);
63830
- if (!end) {
63831
- this.discardEsc = discarded.endsWith(ESC);
63832
- this.timeout = setTimeout(() => {
63833
- this.discardingClipboard = false;
63834
- this.discardEsc = false;
63835
- }, this.options.clipboardFrameTimeout ?? 1e3);
63836
- return;
63881
+ const kind = this.discardingClipboard;
63882
+ const heldEscape = this.discardEsc;
63883
+ const discarded = (heldEscape ? ESC : "") + str2;
63884
+ const end = clipboardFrameEnd(discarded, kind);
63885
+ const escape = discarded.indexOf(ESC, heldEscape && str2.startsWith(ESC) ? 1 : 0);
63886
+ const resync = escape >= 0 && escape + 1 < discarded.length && (end === void 0 || escape < end - 1) && !(kind === "osc" && end !== void 0 && escape === end - 2 && discarded.startsWith(`${ESC}\\`, escape));
63887
+ if (resync) {
63888
+ this.discardingClipboard = void 0;
63889
+ this.discardEsc = false;
63890
+ str2 = discarded.slice(escape);
63891
+ } else {
63892
+ if (!end) {
63893
+ this.discardEsc = discarded.endsWith(ESC);
63894
+ this.scheduleDiscardRecovery();
63895
+ return;
63896
+ }
63897
+ this.discardingClipboard = void 0;
63898
+ this.discardEsc = false;
63899
+ str2 = discarded.slice(end);
63837
63900
  }
63838
- this.discardingClipboard = false;
63839
- this.discardEsc = false;
63840
- str2 = discarded.slice(end.index + end[0].length);
63841
63901
  }
63842
63902
  this.buffer += str2;
63843
63903
  if (this.pasteMode) {
@@ -63856,16 +63916,13 @@ var StdinBuffer = class extends EventEmitter {
63856
63916
  }
63857
63917
  return;
63858
63918
  }
63859
- const startIndex = this.buffer.indexOf(BRACKETED_PASTE_START);
63860
- if (startIndex !== -1) {
63861
- if (startIndex > 0) {
63862
- const beforePaste = this.buffer.slice(0, startIndex);
63863
- const result2 = extractCompleteSequences(beforePaste);
63864
- for (const sequence of result2.sequences) {
63865
- this.emit("data", sequence);
63866
- }
63867
- }
63868
- this.buffer = this.buffer.slice(startIndex + BRACKETED_PASTE_START.length);
63919
+ const result = extractCompleteSequences(this.buffer, this.options.clipboardMaxFrame, this.options.clipboardResponsePending?.());
63920
+ if (result.remainder.length < this.buffer.length) this.clipboardStarted = 0;
63921
+ this.buffer = result.remainder;
63922
+ for (const sequence of result.sequences) {
63923
+ if (sequence !== BRACKETED_PASTE_START) this.emit("data", sequence);
63924
+ }
63925
+ if (result.sequences.at(-1) === BRACKETED_PASTE_START) {
63869
63926
  this.pasteMode = true;
63870
63927
  this.pasteBuffer = this.buffer;
63871
63928
  this.buffer = "";
@@ -63882,40 +63939,29 @@ var StdinBuffer = class extends EventEmitter {
63882
63939
  }
63883
63940
  return;
63884
63941
  }
63885
- const result = extractCompleteSequences(this.buffer, this.options.clipboardMaxFrame);
63886
- this.buffer = result.remainder;
63887
- for (const sequence of result.sequences) {
63888
- this.emit("data", sequence);
63889
- }
63890
63942
  if (this.buffer.length > 0) {
63891
- const heldFor5522 = this.buffer.startsWith(OSC_5522_PREFIX) || this.buffer.length >= 2 && OSC_5522_PREFIX.startsWith(this.buffer) || this.buffer === ESC && this.options.clipboardResponsePending?.();
63892
- if (heldFor5522 && this.buffer.length <= (this.options.clipboardMaxFrame ?? OSC_5522_MAX_FRAME)) {
63943
+ const fragment = classifyClipboardFragment(this.buffer, this.options.clipboardResponsePending?.());
63944
+ if (fragment) {
63945
+ this.clipboardStarted ||= Date.now();
63946
+ const limit = Math.min(this.options.clipboardMaxFrame ?? OSC_5522_MAX_FRAME, fragment.kind === "csi" ? 64 : Infinity);
63947
+ if (this.buffer.length > limit) {
63948
+ this.discardClipboard(fragment.kind);
63949
+ return;
63950
+ }
63951
+ const deadline = Math.min(
63952
+ this.options.clipboardFrameTimeout ?? 1e3,
63953
+ (this.options.clipboardFrameMaxDuration ?? 1e4) - (Date.now() - this.clipboardStarted)
63954
+ );
63893
63955
  this.timeout = setTimeout(() => {
63894
- const ambiguousEscape = this.buffer === ESC;
63895
- this.discardEsc = this.buffer.endsWith(ESC);
63896
- this.buffer = "";
63897
- if (ambiguousEscape) {
63956
+ if (this.buffer === ESC) {
63957
+ this.buffer = "";
63958
+ this.clipboardStarted = 0;
63898
63959
  this.emit("data", ESC);
63899
- return;
63900
- }
63901
- this.discardingClipboard = true;
63902
- this.timeout = setTimeout(() => {
63903
- this.discardingClipboard = false;
63904
- this.discardEsc = false;
63905
- }, this.options.clipboardFrameTimeout ?? 1e3);
63906
- }, this.options.clipboardFrameTimeout ?? 1e3);
63907
- return;
63908
- }
63909
- if (heldFor5522) {
63910
- this.discardEsc = this.buffer.endsWith(ESC);
63911
- this.buffer = "";
63912
- this.discardingClipboard = true;
63913
- this.timeout = setTimeout(() => {
63914
- this.discardingClipboard = false;
63915
- this.discardEsc = false;
63916
- }, this.options.clipboardFrameTimeout ?? 1e3);
63960
+ } else this.discardClipboard(fragment.kind);
63961
+ }, Math.max(0, deadline));
63917
63962
  return;
63918
63963
  }
63964
+ this.clipboardStarted = 0;
63919
63965
  this.timeout = setTimeout(() => {
63920
63966
  const flushed = this.flush();
63921
63967
  for (const sequence of flushed) {
@@ -63924,6 +63970,19 @@ var StdinBuffer = class extends EventEmitter {
63924
63970
  }, this.timeoutMs);
63925
63971
  }
63926
63972
  }
63973
+ scheduleDiscardRecovery() {
63974
+ this.timeout = setTimeout(() => {
63975
+ this.discardingClipboard = void 0;
63976
+ this.discardEsc = false;
63977
+ }, this.options.clipboardFrameTimeout ?? 1e3);
63978
+ }
63979
+ discardClipboard(kind) {
63980
+ this.discardEsc = this.buffer.endsWith(ESC);
63981
+ this.buffer = "";
63982
+ this.clipboardStarted = 0;
63983
+ this.discardingClipboard = kind;
63984
+ this.scheduleDiscardRecovery();
63985
+ }
63927
63986
  flush() {
63928
63987
  if (this.timeout) {
63929
63988
  clearTimeout(this.timeout);
@@ -63932,7 +63991,13 @@ var StdinBuffer = class extends EventEmitter {
63932
63991
  if (this.buffer.length === 0) {
63933
63992
  return [];
63934
63993
  }
63935
- const sequences = this.buffer.startsWith(OSC_5522_PREFIX) || this.buffer.length >= 2 && OSC_5522_PREFIX.startsWith(this.buffer) ? [] : [this.buffer];
63994
+ const fragment = classifyClipboardFragment(this.buffer, this.options.clipboardResponsePending?.());
63995
+ if (fragment && this.buffer !== ESC) {
63996
+ this.discardClipboard(fragment.kind);
63997
+ return [];
63998
+ }
63999
+ const sequences = [this.buffer];
64000
+ this.clipboardStarted = 0;
63936
64001
  this.buffer = "";
63937
64002
  return sequences;
63938
64003
  }
@@ -63944,7 +64009,8 @@ var StdinBuffer = class extends EventEmitter {
63944
64009
  this.buffer = "";
63945
64010
  this.pasteMode = false;
63946
64011
  this.pasteBuffer = "";
63947
- this.discardingClipboard = false;
64012
+ this.clipboardStarted = 0;
64013
+ this.discardingClipboard = void 0;
63948
64014
  this.discardEsc = false;
63949
64015
  }
63950
64016
  getBuffer() {
@@ -63960,6 +64026,7 @@ import * as fs11 from "node:fs";
63960
64026
  import koffi from "koffi";
63961
64027
 
63962
64028
  // ../../packages/tui/src/osc-5522.ts
64029
+ import { randomBytes as randomBytes2 } from "node:crypto";
63963
64030
  var OSC = "\x1B]";
63964
64031
  var ST = "\x1B\\";
63965
64032
  var READ_TIMEOUT_MS = 8e3;
@@ -64016,13 +64083,14 @@ var Osc5522Client = class {
64016
64083
  return true;
64017
64084
  }
64018
64085
  const packet = parseOsc5522Packet(data);
64019
- if (!packet) return false;
64086
+ if (!packet) return data.startsWith(`${OSC}5522;`);
64020
64087
  const fields = parseMetadata(packet.metadata);
64021
64088
  const type = fields.get("type") ?? "";
64022
- if (!type.startsWith("read")) return false;
64089
+ if (!type.startsWith("read")) return true;
64023
64090
  const status = fields.get("status");
64024
64091
  const session = this.session;
64025
64092
  if (!session) return true;
64093
+ if (fields.get("id") !== session.id) return true;
64026
64094
  if (status === void 0) {
64027
64095
  this.finishFor(session, { ok: false, kind: "malformed", message: `OSC 5522 read packet without status: ${packet.metadata}` });
64028
64096
  return true;
@@ -64105,6 +64173,7 @@ var Osc5522Client = class {
64105
64173
  return { ok: false, kind: "busy", message: "Another OSC 5522 read is already in flight." };
64106
64174
  }
64107
64175
  const session = {
64176
+ id: `pie-${randomBytes2(8).toString("hex")}`,
64108
64177
  resolve: void 0,
64109
64178
  timer: void 0,
64110
64179
  chunks: [],
@@ -64124,7 +64193,7 @@ var Osc5522Client = class {
64124
64193
  }
64125
64194
  if (this.session !== session) return promise;
64126
64195
  const mimeList = Buffer.from("image/png image/jpeg").toString("base64");
64127
- this.write(`${OSC}5522;type=read;${mimeList}${ST}`);
64196
+ this.write(`${OSC}5522;id=${session.id}:type=read;${mimeList}${ST}`);
64128
64197
  return promise;
64129
64198
  }
64130
64199
  /** Finish only if `session` is still the live session (identity-bound). */
@@ -64580,6 +64649,15 @@ var ExtensionRunner = class {
64580
64649
  setActiveTools: (toolNames) => this.actions.setActiveTools(toolNames),
64581
64650
  getActiveTools: () => this.actions.getActiveTools(),
64582
64651
  sendUserMessage: (content) => this.actions.sendUserMessage(content),
64652
+ ...this.actions.attachLocalFile ? {
64653
+ attachLocalFile: (path34, displayName) => this.actions.attachLocalFile(path34, displayName)
64654
+ } : {},
64655
+ ...this.actions.beginUserInput ? {
64656
+ beginUserInput: (isCurrent) => this.actions.beginUserInput(isCurrent)
64657
+ } : {},
64658
+ ...this.actions.attachLocalFileAndSubmit ? {
64659
+ attachLocalFileAndSubmit: (path34, displayName, submitText) => this.actions.attachLocalFileAndSubmit(path34, displayName, submitText)
64660
+ } : {},
64583
64661
  setPlanMode: (enabled, options) => this.actions.setPlanMode(enabled, options),
64584
64662
  setExecutionReminder: (text) => this.actions.setExecutionReminder(text),
64585
64663
  getExecutionState: () => this.actions.getExecutionState(),
@@ -68103,6 +68181,20 @@ var FileCache = class _FileCache {
68103
68181
  getByHash(hash) {
68104
68182
  return this.index.files[hash];
68105
68183
  }
68184
+ /** Repair historical image MIME labels using the cached bytes. Content
68185
+ * deduplication must not keep an old .png-derived label when the same
68186
+ * Feishu JPEG is staged again with the corrected .jpg name. The hash,
68187
+ * bytes and platform upload records stay unchanged. */
68188
+ refreshImageMimeType(hash) {
68189
+ const entry = this.index.files[hash];
68190
+ if (!entry || !entry.mimeType.startsWith("image/")) return;
68191
+ const localPath = this.getLocalPath(hash);
68192
+ if (!localPath) return;
68193
+ const detected = readImageFormat(localPath);
68194
+ if (detected.ext === ".bin" || detected.mime === entry.mimeType) return;
68195
+ entry.mimeType = detected.mime;
68196
+ this.saveIndex();
68197
+ }
68106
68198
  getByFileId(fileId, platform2) {
68107
68199
  for (const entry of Object.values(this.index.files)) {
68108
68200
  const platformRecord = entry.platforms[platform2];
@@ -69206,6 +69298,7 @@ var FileManager = class {
69206
69298
  if (!cached) {
69207
69299
  await this.fileCache.storeFile(resolvedPath, sourceName, mimeType);
69208
69300
  }
69301
+ this.fileCache.refreshImageMimeType(hash);
69209
69302
  this.fileCache.rememberPathHint(resolvedPath, hash, sourceName);
69210
69303
  this.invalidateDirectoryListingCacheForPath(resolvedPath);
69211
69304
  const entry = this.fileCache.getByHash(hash);
@@ -70296,12 +70389,21 @@ var YoloGrantTracker = class {
70296
70389
  isActive(now = Date.now()) {
70297
70390
  return this.untilMs > now;
70298
70391
  }
70392
+ remainingMs(now = Date.now()) {
70393
+ return Math.max(0, this.untilMs - now);
70394
+ }
70299
70395
  award(grantMs, now = Date.now()) {
70300
70396
  this.untilMs = now + Math.max(0, grantMs);
70301
70397
  }
70302
70398
  expire() {
70303
70399
  this.untilMs = 0;
70304
70400
  }
70401
+ /** Revoke the active grant and report whether revocation changed live state. */
70402
+ revoke() {
70403
+ const wasActive = this.isActive();
70404
+ this.expire();
70405
+ return wasActive;
70406
+ }
70305
70407
  /** Expiry timestamp (0 when no grant is held); useful for display. */
70306
70408
  get until() {
70307
70409
  return this.untilMs;
@@ -76576,7 +76678,9 @@ async function handleCalmCommand(host, args) {
76576
76678
  async function handleYoloCommand(host, args) {
76577
76679
  const mode = (args || "").trim().toLowerCase();
76578
76680
  if (mode === "status") {
76579
- host.showStatus(`YOLO mode is ${host.yoloMode ? "on" : "off"}`);
76681
+ const persistent = `YOLO mode is ${host.yoloMode ? "on" : "off"}`;
76682
+ const grantRemaining = host.getYoloGrantRemainingMs();
76683
+ host.showStatus(grantRemaining > 0 ? `${persistent}; temporary high-risk shell grant active for ${Math.max(1, Math.ceil(grantRemaining / 6e4))} more min` : persistent);
76580
76684
  return;
76581
76685
  }
76582
76686
  if (mode && !["on", "off", "enable", "enabled", "disable", "disabled", "true", "false", "1", "0"].includes(mode)) {
@@ -76584,9 +76688,10 @@ async function handleYoloCommand(host, args) {
76584
76688
  return;
76585
76689
  }
76586
76690
  const nextYoloMode = mode ? ["on", "enable", "enabled", "true", "1"].includes(mode) : !host.yoloMode;
76691
+ const revokedGrant = nextYoloMode ? false : host.revokeYoloGrant();
76587
76692
  if (host.yoloMode === nextYoloMode) {
76588
76693
  host.footer.setState({ yoloMode: host.yoloMode });
76589
- host.showStatus(`YOLO mode already ${host.yoloMode ? "on" : "off"}`);
76694
+ host.showStatus(`YOLO mode already ${host.yoloMode ? "on" : "off"}${revokedGrant ? "; temporary grant revoked" : ""}`);
76590
76695
  return;
76591
76696
  }
76592
76697
  host.yoloMode = nextYoloMode;
@@ -76604,6 +76709,7 @@ async function handleYoloCommand(host, args) {
76604
76709
  host.chatContainer.addChild(new Spacer(1));
76605
76710
  host.chatContainer.addChild(new Text(theme.fg("accent", "\u2713 YOLO mode disabled"), 1, 0));
76606
76711
  host.chatContainer.addChild(new Text(theme.fg("dim", " Sandbox directory restrictions restored."), 1, 0));
76712
+ if (revokedGrant) host.chatContainer.addChild(new Text(theme.fg("dim", " Temporary high-risk shell grant revoked."), 1, 0));
76607
76713
  host.chatContainer.addChild(new Spacer(1));
76608
76714
  }
76609
76715
  host.ui.requestRender();
@@ -78819,7 +78925,23 @@ var MentionHandler = class {
78819
78925
  * behave identically.
78820
78926
  */
78821
78927
  async attachLocalFile(path34, displayName, pendingMention, isCurrent) {
78822
- await this.attachFileFromPath(path34, { sourceName: displayName, queryToken: pendingMention, isCurrent });
78928
+ return this.attachFileFromPath(path34, { sourceName: displayName, queryToken: pendingMention, isCurrent });
78929
+ }
78930
+ /** Prepare a message-owned mention without reading or mutating the editor.
78931
+ * Errors propagate to the caller; no caption-only submission on failure. */
78932
+ async prepareLocalFile(filePath, displayName, isCurrent = () => true) {
78933
+ if (!isCurrent()) return void 0;
78934
+ const sourceName = displayName ?? path28.basename(filePath);
78935
+ const result = await this.prepareFile(filePath, sourceName);
78936
+ if (!isCurrent() || !result.success) return void 0;
78937
+ return this.formatMention(result.name, result.fileId);
78938
+ }
78939
+ prepareFile(filePath, sourceName, onProgress) {
78940
+ const mimeType = FileCache.getMimeType(filePath);
78941
+ const isMedia = mimeType.startsWith("image/") || mimeType.startsWith("video/");
78942
+ if (!isMedia || !this.fileManager.hasAdapter()) return this.fileManager.stageLocal(filePath, { sourceName });
78943
+ if (mimeType.startsWith("video/")) return this.fileManager.uploadVideo(filePath, { sourceName, onProgress });
78944
+ return this.fileManager.uploadPic(filePath, { sourceName, onProgress });
78823
78945
  }
78824
78946
  /** Reserve a real queue-replaceable token before asynchronous clipboard IO. */
78825
78947
  beginPendingAttachment(name) {
@@ -78872,29 +78994,22 @@ var MentionHandler = class {
78872
78994
  this.formatUploadProgress(sourceName, progress, stage)
78873
78995
  );
78874
78996
  };
78875
- const result = shouldStageLocally ? await this.fileManager.stageLocal(path34, { sourceName }) : mimeType.startsWith("video/") ? await this.fileManager.uploadVideo(path34, {
78876
- sourceName,
78877
- onProgress
78878
- }) : mimeType.startsWith("image/") ? await this.fileManager.uploadPic(path34, {
78879
- sourceName,
78880
- onProgress
78881
- }) : await this.fileManager.upload(path34, {
78882
- sourceName,
78883
- onProgress
78884
- });
78885
- if (options.isCurrent && !options.isCurrent()) return;
78997
+ const result = await this.prepareFile(path34, sourceName, onProgress);
78998
+ if (options.isCurrent && !options.isCurrent()) return false;
78886
78999
  if (result.success) {
78887
79000
  const mention = this.formatMention(result.name, result.fileId);
78888
79001
  this.onInsertMention(mention, pendingMention);
78889
79002
  this.clearPendingStatus(pendingStatusKey);
78890
79003
  this.onStatus?.(shouldStageLocally ? `Added local file ${result.name}` : `Added ${result.name}`);
79004
+ return true;
78891
79005
  } else {
78892
79006
  this.onInsertMention("", pendingMention);
78893
79007
  this.clearPendingStatus(pendingStatusKey);
78894
79008
  this.onError?.("File upload failed. Please try again.");
79009
+ return false;
78895
79010
  }
78896
79011
  } catch (err) {
78897
- if (options.isCurrent && !options.isCurrent()) return;
79012
+ if (options.isCurrent && !options.isCurrent()) return false;
78898
79013
  this.onInsertMention("", pendingMention);
78899
79014
  this.clearPendingStatus(pendingStatusKey);
78900
79015
  const errorMessage5 = err instanceof Error ? err.message : String(err);
@@ -78909,6 +79024,7 @@ var MentionHandler = class {
78909
79024
  } else {
78910
79025
  this.onError?.(`Upload failed: ${errorMessage5}`);
78911
79026
  }
79027
+ return false;
78912
79028
  } finally {
78913
79029
  this.clearPendingStatus(pendingStatusKey);
78914
79030
  this.pendingUploadCount = Math.max(0, this.pendingUploadCount - 1);
@@ -79596,6 +79712,9 @@ async function selectMentionOption(host, option) {
79596
79712
  }
79597
79713
 
79598
79714
  // src/input/interactive-keybindings.ts
79715
+ function mainEditorOwnsInput(host) {
79716
+ return host.editor.focused === true && host.editorContainer.children.includes(host.editor) && !host.ui.hasOverlay() && !host.mentionPickerComponent;
79717
+ }
79599
79718
  function setupInteractiveKeybindings(host) {
79600
79719
  host.ui.addInputListener((data) => {
79601
79720
  if (isKeyRelease(data)) {
@@ -79653,7 +79772,7 @@ function setupInteractiveKeybindings(host) {
79653
79772
  host.handleInterrupt();
79654
79773
  return { consume: true };
79655
79774
  }
79656
- if (!host.mentionPickerComponent && host.keybindings.matches(data, "pasteImage")) {
79775
+ if (host.keybindings.matches(data, "pasteImage") && mainEditorOwnsInput(host)) {
79657
79776
  host.handlePasteImage();
79658
79777
  return { consume: true };
79659
79778
  }
@@ -79673,14 +79792,22 @@ function setupInteractiveKeybindings(host) {
79673
79792
  host.handleFollowUp();
79674
79793
  return { consume: true };
79675
79794
  }
79795
+ const shortcuts = host.getExtensionShortcuts?.();
79796
+ if (shortcuts && shortcuts.size > 0 && mainEditorOwnsInput(host)) {
79797
+ for (const shortcut of shortcuts.values()) {
79798
+ if (matchesKey(data, shortcut.key)) {
79799
+ void shortcut.handler();
79800
+ return { consume: true };
79801
+ }
79802
+ }
79803
+ }
79676
79804
  return { consume: false };
79677
79805
  });
79678
79806
  }
79679
79807
 
79680
79808
  // src/clipboard/read-clipboard-image.ts
79681
79809
  import { spawn as spawn2 } from "node:child_process";
79682
- import { randomBytes as randomBytes2 } from "node:crypto";
79683
- import { existsSync as existsSync18, readFileSync as readFileSync17, statSync as statSync12, unlinkSync as unlinkSync8, writeFileSync as writeFileSync12 } from "node:fs";
79810
+ import { chmodSync as chmodSync2, closeSync as closeSync4, existsSync as existsSync18, fchmodSync, mkdtempSync, openSync as openSync4, readFileSync as readFileSync17, rmdirSync, statSync as statSync12, unlinkSync as unlinkSync8, writeFileSync as writeFileSync12 } from "node:fs";
79684
79811
  import { tmpdir } from "node:os";
79685
79812
  import { join as join20 } from "node:path";
79686
79813
  var MAX_IMAGE_BYTES = 50 * 1024 * 1024;
@@ -79746,14 +79873,67 @@ function defaultSpawnFn(file, args, spawnImpl = spawn2, maxBytes = MAX_IMAGE_BYT
79746
79873
  });
79747
79874
  });
79748
79875
  }
79749
- function defaultMkTempPath(ext) {
79750
- return join20(tmpdir(), `pie-clipboard-${randomBytes2(6).toString("hex")}${ext}`);
79751
- }
79876
+ var TempImageResources = class {
79877
+ constructor(injectedPath) {
79878
+ this.injectedPath = injectedPath;
79879
+ }
79880
+ injectedPath;
79881
+ directory;
79882
+ files = /* @__PURE__ */ new Set();
79883
+ create = (ext) => {
79884
+ if (!this.injectedPath && !this.directory) {
79885
+ this.directory = mkdtempSync(join20(tmpdir(), "pie-clipboard-"));
79886
+ if (process.platform !== "win32") chmodSync2(this.directory, 448);
79887
+ }
79888
+ const path34 = this.injectedPath ? this.injectedPath(ext) : join20(this.directory, `image${ext}`);
79889
+ const fd = openSync4(path34, "wx", 384);
79890
+ this.files.add(path34);
79891
+ try {
79892
+ if (process.platform !== "win32") fchmodSync(fd, 384);
79893
+ } finally {
79894
+ closeSync4(fd);
79895
+ }
79896
+ return path34;
79897
+ };
79898
+ cleanup = () => {
79899
+ for (const path34 of this.files) {
79900
+ try {
79901
+ unlinkSync8(path34);
79902
+ this.files.delete(path34);
79903
+ } catch (err) {
79904
+ if (err.code === "ENOENT") this.files.delete(path34);
79905
+ }
79906
+ }
79907
+ if (this.directory) {
79908
+ try {
79909
+ rmdirSync(this.directory);
79910
+ this.directory = void 0;
79911
+ } catch (err) {
79912
+ if (err.code === "ENOENT") this.directory = void 0;
79913
+ }
79914
+ }
79915
+ };
79916
+ };
79752
79917
  async function readClipboardImage(deps = {}) {
79753
79918
  const platform2 = deps.platform ?? process.platform;
79754
79919
  const env = deps.env ?? process.env;
79755
79920
  const spawnImpl = deps.spawnImpl ?? defaultSpawnFn;
79756
- const mkTempPath = deps.mkTempPath ?? defaultMkTempPath;
79921
+ const resources = new TempImageResources(deps.mkTempPath);
79922
+ let retained = false;
79923
+ try {
79924
+ const result = await readPlatformClipboard(platform2, env, spawnImpl, resources.create);
79925
+ if (result.ok === true) {
79926
+ retained = true;
79927
+ return { ...result, cleanup: resources.cleanup };
79928
+ }
79929
+ return result;
79930
+ } catch (err) {
79931
+ return { ok: false, kind: "failed", message: `Failed to read clipboard image: ${errorMessage4(err)}` };
79932
+ } finally {
79933
+ if (!retained) resources.cleanup();
79934
+ }
79935
+ }
79936
+ async function readPlatformClipboard(platform2, env, spawnImpl, mkTempPath) {
79757
79937
  switch (platform2) {
79758
79938
  case "darwin":
79759
79939
  return readMacClipboard(spawnImpl, mkTempPath);
@@ -79936,15 +80116,14 @@ function writeImageBytes(bytes, declaredMime, mkTempPath) {
79936
80116
  const mimeType = detectMimeFromMagic(bytes) ?? declaredMime;
79937
80117
  const targetPath = mkTempPath(extensionForMime(mimeType));
79938
80118
  try {
79939
- writeFileSync12(targetPath, bytes);
80119
+ writeFileSync12(targetPath, bytes, { flag: "r+", mode: 384 });
79940
80120
  } catch (err) {
79941
80121
  return { ok: false, kind: "failed", message: `Failed to write temp image: ${errorMessage4(err)}` };
79942
80122
  }
79943
80123
  return {
79944
80124
  ok: true,
79945
80125
  path: targetPath,
79946
- mimeType,
79947
- cleanup: makeCleanup(targetPath)
80126
+ mimeType
79948
80127
  };
79949
80128
  }
79950
80129
  function finalizeTempImage(path34, mimeType) {
@@ -79955,11 +80134,9 @@ function finalizeTempImage(path34, mimeType) {
79955
80134
  }
79956
80135
  const size = statSync12(path34).size;
79957
80136
  if (size === 0) {
79958
- makeCleanup(path34)();
79959
80137
  return { ok: false, kind: "no-image", message: "Clipboard does not contain an image." };
79960
80138
  }
79961
80139
  if (size > MAX_IMAGE_BYTES) {
79962
- makeCleanup(path34)();
79963
80140
  return { ok: false, kind: "too-large", message: `Clipboard image is too large (${formatBytes2(size)}).` };
79964
80141
  }
79965
80142
  bytes = readFileSync17(path34);
@@ -79968,10 +80145,9 @@ function finalizeTempImage(path34, mimeType) {
79968
80145
  }
79969
80146
  const detected = detectMimeFromMagic(bytes);
79970
80147
  if (!detected) {
79971
- makeCleanup(path34)();
79972
80148
  return { ok: false, kind: "no-image", message: "Clipboard does not contain a supported image (PNG/JPEG)." };
79973
80149
  }
79974
- return { ok: true, path: path34, mimeType: detected, cleanup: makeCleanup(path34) };
80150
+ return { ok: true, path: path34, mimeType: detected };
79975
80151
  }
79976
80152
  function detectMimeFromMagic(bytes) {
79977
80153
  if (bytes.length >= 8 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
@@ -79982,14 +80158,6 @@ function detectMimeFromMagic(bytes) {
79982
80158
  }
79983
80159
  return void 0;
79984
80160
  }
79985
- function makeCleanup(path34) {
79986
- return () => {
79987
- try {
79988
- unlinkSync8(path34);
79989
- } catch {
79990
- }
79991
- };
79992
- }
79993
80161
  function spawnFailure(outcome, tool) {
79994
80162
  if (outcome.error === "too-large") {
79995
80163
  return { ok: false, kind: "too-large", message: "Clipboard image is too large." };
@@ -80019,7 +80187,7 @@ function formatBytes2(bytes) {
80019
80187
  }
80020
80188
 
80021
80189
  // src/input/image-paste.ts
80022
- import { mkdtempSync, writeFileSync as writeFileSync13, rmSync as rmSync3 } from "node:fs";
80190
+ import { mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync13, rmSync as rmSync3 } from "node:fs";
80023
80191
  import { tmpdir as tmpdir2 } from "node:os";
80024
80192
  import { join as join21 } from "node:path";
80025
80193
  var pastingHosts = /* @__PURE__ */ new WeakSet();
@@ -80046,7 +80214,7 @@ function terminalResultToClipboardResult(result) {
80046
80214
  const ext = result.mimeType === "image/jpeg" ? ".jpg" : ".png";
80047
80215
  let dir;
80048
80216
  try {
80049
- dir = mkdtempSync(join21(tmpdir2(), "pie-osc5522-"));
80217
+ dir = mkdtempSync2(join21(tmpdir2(), "pie-osc5522-"));
80050
80218
  const path34 = join21(dir, formatPastedImageName(/* @__PURE__ */ new Date(), ext));
80051
80219
  writeFileSync13(path34, result.bytes);
80052
80220
  return {
@@ -81726,6 +81894,11 @@ function createInteractiveAgentSessionController(host) {
81726
81894
  lastShownCompactionError = null;
81727
81895
  host.setControllerBusy(false);
81728
81896
  } else if (event.type === "turn_cancelled") {
81897
+ host.emitExtensionEvent({
81898
+ type: "turn:cancelled",
81899
+ turnIndex: host._semanticTurnIndex,
81900
+ reason: event.reason
81901
+ });
81729
81902
  const outcome = host.executionState.abort();
81730
81903
  host.logDebug("execution:turn_cancelled", {
81731
81904
  turnIndex: host._semanticTurnIndex,
@@ -82634,6 +82807,51 @@ function summarizeToolNames(tools) {
82634
82807
  return tools.map((tool) => tool.name).join(", ");
82635
82808
  }
82636
82809
 
82810
+ // src/extensions/user-input-scope.ts
82811
+ function beginUserInput(host, extensionIsCurrent = () => true) {
82812
+ const session = host.sessionManager.getActiveSession();
82813
+ const controller = host.agentSessionController;
82814
+ const runner = host.extensionRunner;
82815
+ const handler = host.attachmentMentionHandler?.();
82816
+ if (!session || !controller || !runner || !handler) return void 0;
82817
+ let retired = false;
82818
+ let used = false;
82819
+ const unsubscribe = controller.subscribe((event) => {
82820
+ if (event.type === "session_invalidated") retired = true;
82821
+ });
82822
+ const dispose = runner.trackUnregisterHandle(() => {
82823
+ retired = true;
82824
+ unsubscribe();
82825
+ });
82826
+ const isCurrent = () => !retired && host.sessionManager.getActiveSession() === session && host.agentSessionController === controller && host.extensionRunner === runner && host.attachmentMentionHandler?.() === handler && extensionIsCurrent();
82827
+ return {
82828
+ isCurrent,
82829
+ dispose,
82830
+ async submit(text, files = []) {
82831
+ if (used || !isCurrent() || !text.trim() && !files.length) return false;
82832
+ used = true;
82833
+ try {
82834
+ const mentions = [];
82835
+ for (const file of files) {
82836
+ if (!isCurrent()) return false;
82837
+ const mention = await handler.prepareLocalFile(file.path, file.displayName, isCurrent);
82838
+ if (!mention || !isCurrent()) return false;
82839
+ mentions.push(mention.trim());
82840
+ }
82841
+ let content = [text.trim(), ...mentions].filter(Boolean).join("\n");
82842
+ const decision = await runner.emitTerminalInput({ type: "terminal:input", text: content });
82843
+ if (!isCurrent() || decision.action === "consume") return false;
82844
+ if (decision.action === "transform") content = decision.text.trim();
82845
+ if (!content || mentions.some((mention) => !content.includes(mention))) return false;
82846
+ host.queueMessage(content, "followUp", { clearEditor: false, deliverWhileStreaming: false });
82847
+ return true;
82848
+ } catch {
82849
+ return false;
82850
+ }
82851
+ }
82852
+ };
82853
+ }
82854
+
82637
82855
  // src/extensions/interactive-extension-loader.ts
82638
82856
  async function loadInteractiveExtensions(host) {
82639
82857
  const extensionActions = {
@@ -82655,6 +82873,21 @@ async function loadInteractiveExtensions(host) {
82655
82873
  void host.editor.onSubmit(content);
82656
82874
  }
82657
82875
  },
82876
+ attachLocalFile: async (path34, displayName) => {
82877
+ const handler = host.attachmentMentionHandler?.();
82878
+ if (!handler) return false;
82879
+ return handler.attachLocalFile(path34, displayName);
82880
+ },
82881
+ beginUserInput: (isCurrent) => beginUserInput(host, isCurrent),
82882
+ attachLocalFileAndSubmit: async (path34, displayName, submitText) => {
82883
+ const scope = beginUserInput(host);
82884
+ if (!scope) return false;
82885
+ try {
82886
+ return await scope.submit(submitText, [{ path: path34, displayName }]);
82887
+ } finally {
82888
+ scope.dispose();
82889
+ }
82890
+ },
82658
82891
  setPlanMode: (enabled, options) => {
82659
82892
  const shouldEmitTransition = host.planModeEnabled !== enabled || options?.forcePromptInjection;
82660
82893
  if (shouldEmitTransition) {
@@ -83026,6 +83259,12 @@ var InteractiveMode = class {
83026
83259
  get controllerSetupHost() {
83027
83260
  return this;
83028
83261
  }
83262
+ getYoloGrantRemainingMs() {
83263
+ return this.yoloGrant.remainingMs();
83264
+ }
83265
+ revokeYoloGrant() {
83266
+ return this.yoloGrant.revoke();
83267
+ }
83029
83268
  getPolicyContext = () => ({
83030
83269
  mode: this.planModeEnabled ? "plan" : "normal",
83031
83270
  yoloMode: this.yoloMode || this.yoloGrant.isActive(),
@@ -83183,7 +83422,7 @@ var InteractiveMode = class {
83183
83422
  async init() {
83184
83423
  const activeSession = this.sessionManager.getActiveSession();
83185
83424
  this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
83186
- const { Agent } = await import("./chunks/src-XDNJ3PHL.js");
83425
+ const { Agent } = await import("./chunks/src-4PG3KZUS.js");
83187
83426
  this.agent = new Agent({
83188
83427
  initialState: {
83189
83428
  systemPrompt: this.buildSystemPrompt(),
@@ -83550,9 +83789,41 @@ var InteractiveMode = class {
83550
83789
  return interactiveCommands.some((cmd) => commandPath.startsWith(cmd));
83551
83790
  }
83552
83791
  toggleToolsExpansion() {
83792
+ if (this.calmMode) {
83793
+ this.setCalmMode(false);
83794
+ if (this.toolOutputExpanded) toggleToolsExpansion(this.uiHelperHost);
83795
+ this.options.settingsManager.setToolOutputExpanded(this.toolOutputExpanded);
83796
+ return;
83797
+ }
83798
+ if (this.toolOutputExpanded) {
83799
+ this.setCalmMode(true);
83800
+ return;
83801
+ }
83553
83802
  toggleToolsExpansion(this.uiHelperHost);
83554
83803
  this.options.settingsManager.setToolOutputExpanded(this.toolOutputExpanded);
83555
83804
  }
83805
+ /** Aggregated extension shortcut registrations for the keybinding
83806
+ * dispatcher (duck-typed onto InteractiveKeybindingsHost). Handlers are
83807
+ * bound to the extension runner context here. */
83808
+ getExtensionShortcuts() {
83809
+ const merged = /* @__PURE__ */ new Map();
83810
+ for (const extension of this.extensions) {
83811
+ for (const [key, shortcut] of extension.shortcuts) {
83812
+ if (merged.has(key)) continue;
83813
+ const context = this.extensionRunner?.createContext();
83814
+ merged.set(key, {
83815
+ key,
83816
+ handler: () => shortcut.handler(context)
83817
+ });
83818
+ }
83819
+ }
83820
+ return merged;
83821
+ }
83822
+ /** Live mention handler for extension-driven attachments (duck-typed onto
83823
+ * InteractiveExtensionLoaderHost); undefined while attachments init. */
83824
+ attachmentMentionHandler() {
83825
+ return this.mentionHandler;
83826
+ }
83556
83827
  showSelector(create) {
83557
83828
  return showSelector(this.uiHelperHost, create);
83558
83829
  }
@@ -84075,7 +84346,7 @@ async function runPrintMode(params) {
84075
84346
  `);
84076
84347
  console.log("Assistant: ");
84077
84348
  }
84078
- const { Agent: AgentClass } = await import("./chunks/src-XDNJ3PHL.js");
84349
+ const { Agent: AgentClass } = await import("./chunks/src-4PG3KZUS.js");
84079
84350
  let agent;
84080
84351
  const printModeExtensions = await loadPrintModeExtensions({
84081
84352
  cwd: runtime.cwd,
@@ -84375,7 +84646,6 @@ function parseInput(line) {
84375
84646
  };
84376
84647
  }
84377
84648
  if (parsed.type === "sidechat.request" && typeof parsed.requestId === "string" && typeof parsed.prompt === "string") {
84378
- if (parsed.hostContext !== void 0 && !isHostContextBlock(parsed.hostContext)) return null;
84379
84649
  return {
84380
84650
  type: "sidechat.request",
84381
84651
  sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
@@ -84385,7 +84655,6 @@ function parseInput(line) {
84385
84655
  };
84386
84656
  }
84387
84657
  if ((parsed.type === "turn.request" || parsed.type === "turn.input") && typeof parsed.turnId === "string" && typeof parsed.prompt === "string") {
84388
- if (parsed.hostContext !== void 0 && !isHostContextBlock(parsed.hostContext)) return null;
84389
84658
  const streamingBehavior = parsed.streamingBehavior;
84390
84659
  if (streamingBehavior !== void 0 && streamingBehavior !== "steer" && streamingBehavior !== "followUp") {
84391
84660
  return null;
@@ -84923,6 +85192,11 @@ async function runJsonEventsMode(params) {
84923
85192
  }
84924
85193
  const startedAt = Date.now();
84925
85194
  if (params.mockResponse !== void 0) {
85195
+ const hostContextFailure = validateIntakeHostContext(message);
85196
+ if (hostContextFailure) {
85197
+ writeSidechatFailure(message, hostContextFailure.message, hostContextFailure.code);
85198
+ return;
85199
+ }
84926
85200
  writeEvent({ type: "sidechat.started", sessionId, requestId });
84927
85201
  const event = {
84928
85202
  type: "sidechat.completed",
@@ -84967,7 +85241,7 @@ async function runJsonEventsMode(params) {
84967
85241
  const sideTrace = trace;
84968
85242
  const sideApiKey = runtime.apiKey;
84969
85243
  const snapshot = structuredClone(parent.state.messages);
84970
- const { Agent: AgentClass } = await import("./chunks/src-XDNJ3PHL.js");
85244
+ const { Agent: AgentClass } = await import("./chunks/src-4PG3KZUS.js");
84971
85245
  const sideAgent = new AgentClass({
84972
85246
  initialState: {
84973
85247
  systemPrompt: parent.state.systemPrompt,
@@ -85331,7 +85605,7 @@ async function runJsonEventsMode(params) {
85331
85605
  if (runtime.initialModel.unconfigured || controller) {
85332
85606
  return;
85333
85607
  }
85334
- const { Agent: AgentClass } = await import("./chunks/src-XDNJ3PHL.js");
85608
+ const { Agent: AgentClass } = await import("./chunks/src-4PG3KZUS.js");
85335
85609
  if (runtimeClosing) return;
85336
85610
  const compositionRegistry = createCliHostEnvelopeRegistry();
85337
85611
  const jsonModeExtensions = await loadJsonModeExtensions({ runtime, envelopeRegistry: compositionRegistry, getAgent: () => agent });
@@ -85523,7 +85797,7 @@ async function runJsonEventsMode(params) {
85523
85797
  return message.hostContext ? [message.hostContext, { type: "text", text: message.prompt }] : [{ type: "text", text: message.prompt }];
85524
85798
  }
85525
85799
  function validateIntakeHostContext(message) {
85526
- return message.hostContext ? intakeHostContextFailure(message.hostContext, envelopeRegistry) : void 0;
85800
+ return message.hostContext !== void 0 ? intakeHostContextFailure(message.hostContext, envelopeRegistry) : void 0;
85527
85801
  }
85528
85802
  async function runTurn(message) {
85529
85803
  if (isSessionMismatch(message)) {
@@ -85731,7 +86005,8 @@ async function runJsonEventsMode(params) {
85731
86005
  sessionId,
85732
86006
  turnId: message.turnId,
85733
86007
  error: failure.message,
85734
- hostContextKinds: cliHostEnvelopeKinds(envelopeRegistry)
86008
+ code: failure.code,
86009
+ ...failure.code === "host_context_unknown_projector" ? { hostContextKinds: cliHostEnvelopeKinds(envelopeRegistry) } : {}
85735
86010
  });
85736
86011
  return;
85737
86012
  }
@@ -86018,7 +86293,7 @@ async function runWithJsonEventsConsoleIsolation(fn) {
86018
86293
  }
86019
86294
  async function createCliTestStreamFnFromEnv() {
86020
86295
  if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
86021
- return (await import("./chunks/test-stream-LUUGOJMP.js")).createTestStreamFnFromSequenceEnv();
86296
+ return (await import("./chunks/test-stream-OTKTTZ72.js")).createTestStreamFnFromSequenceEnv();
86022
86297
  }
86023
86298
  function resolveJsonEventsDetailFlag() {
86024
86299
  for (let index = 0; index < process.argv.length; index += 1) {