copilotoffice 2.0.0 → 2.1.0

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.
@@ -3044,7 +3044,7 @@ var require_main = __commonJS({
3044
3044
  exports2.createMessageConnection = exports2.createServerSocketTransport = exports2.createClientSocketTransport = exports2.createServerPipeTransport = exports2.createClientPipeTransport = exports2.generateRandomPipeName = exports2.StreamMessageWriter = exports2.StreamMessageReader = exports2.SocketMessageWriter = exports2.SocketMessageReader = exports2.PortMessageWriter = exports2.PortMessageReader = exports2.IPCMessageWriter = exports2.IPCMessageReader = void 0;
3045
3045
  var ril_1 = require_ril();
3046
3046
  ril_1.default.install();
3047
- var path4 = require("path");
3047
+ var path5 = require("path");
3048
3048
  var os4 = require("os");
3049
3049
  var crypto_1 = require("crypto");
3050
3050
  var net_1 = require("net");
@@ -3180,9 +3180,9 @@ var require_main = __commonJS({
3180
3180
  }
3181
3181
  let result;
3182
3182
  if (XDG_RUNTIME_DIR) {
3183
- result = path4.join(XDG_RUNTIME_DIR, `vscode-ipc-${randomSuffix}.sock`);
3183
+ result = path5.join(XDG_RUNTIME_DIR, `vscode-ipc-${randomSuffix}.sock`);
3184
3184
  } else {
3185
- result = path4.join(os4.tmpdir(), `vscode-${randomSuffix}.sock`);
3185
+ result = path5.join(os4.tmpdir(), `vscode-${randomSuffix}.sock`);
3186
3186
  }
3187
3187
  const limit = safeIpcPathLengths.get(process.platform);
3188
3188
  if (limit !== void 0 && result.length > limit) {
@@ -5067,10 +5067,10 @@ var init_dist = __esm({
5067
5067
  });
5068
5068
 
5069
5069
  // electron/terminal/server.ts
5070
- var path3 = __toESM(require("path"));
5070
+ var path4 = __toESM(require("path"));
5071
5071
  var os3 = __toESM(require("os"));
5072
- var fs2 = __toESM(require("fs"));
5073
- var crypto2 = __toESM(require("crypto"));
5072
+ var fs3 = __toESM(require("fs"));
5073
+ var crypto3 = __toESM(require("crypto"));
5074
5074
  var import_child_process2 = require("child_process");
5075
5075
 
5076
5076
  // electron/terminal/events-watcher.ts
@@ -5407,14 +5407,7 @@ var CopilotSdkProcess = class {
5407
5407
  this.emitPrompt();
5408
5408
  continue;
5409
5409
  }
5410
- this.promptPending = true;
5411
- this.queuedSend = this.queuedSend.then(async () => {
5412
- await this.session.send({ prompt, mode: "enqueue" });
5413
- }).catch((error) => {
5414
- this.emitData(`\x1B[31m[SDK send failed: ${String(error)}]\x1B[0m\r
5415
- `);
5416
- this.emitPrompt();
5417
- });
5410
+ this.enqueuePrompt(prompt);
5418
5411
  continue;
5419
5412
  }
5420
5413
  if (ch === "\b" || ch === "\x7F") {
@@ -5428,6 +5421,34 @@ var CopilotSdkProcess = class {
5428
5421
  this.emitData(ch);
5429
5422
  }
5430
5423
  }
5424
+ /**
5425
+ * Submit a complete prompt directly to the SDK session, bypassing the
5426
+ * line-editor. Handles multi-line prompts atomically (no premature submit on
5427
+ * embedded newlines) and echoes the prompt so it appears in the terminal as
5428
+ * if typed. This is the robust path used by programmatic drivers (e.g. Teams
5429
+ * remote dispatch) instead of racing keystrokes through `write()`.
5430
+ */
5431
+ submitPrompt(text, label) {
5432
+ if (this.closed) return;
5433
+ const prompt = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim();
5434
+ if (!prompt) return;
5435
+ this.lineBuffer = "";
5436
+ const tag = label ? `\x1B[2;36m[${label}]\x1B[0m ` : "";
5437
+ this.emitData(`${tag}${prompt.replace(/\n/g, "\r\n")}\r
5438
+ `);
5439
+ this.enqueuePrompt(prompt);
5440
+ }
5441
+ /** Queue a prompt for the SDK session, serialized after any in-flight send. */
5442
+ enqueuePrompt(prompt) {
5443
+ this.promptPending = true;
5444
+ this.queuedSend = this.queuedSend.then(async () => {
5445
+ await this.session.send({ prompt, mode: "enqueue" });
5446
+ }).catch((error) => {
5447
+ this.emitData(`\x1B[31m[SDK send failed: ${String(error)}]\x1B[0m\r
5448
+ `);
5449
+ this.emitPrompt();
5450
+ });
5451
+ }
5431
5452
  resize(_cols, _rows) {
5432
5453
  }
5433
5454
  onData(callback) {
@@ -5649,27 +5670,73 @@ function repairDuplicateSessionIds(officeId, data, options = {}) {
5649
5670
  return repaired;
5650
5671
  }
5651
5672
 
5673
+ // electron/terminal/pty-registry.ts
5674
+ var crypto2 = __toESM(require("crypto"));
5675
+ var fs2 = __toESM(require("fs"));
5676
+ var path3 = __toESM(require("path"));
5677
+ var DEFAULT_REGISTRY_FILE = path3.join(process.cwd(), ".data", "pty-pids.json");
5678
+ function readPtyRegistry(file = DEFAULT_REGISTRY_FILE) {
5679
+ try {
5680
+ const raw = fs2.readFileSync(file, "utf8");
5681
+ const parsed = JSON.parse(raw);
5682
+ if (!Array.isArray(parsed)) return [];
5683
+ return parsed.filter(
5684
+ (r) => !!r && typeof r.pid === "number" && Number.isFinite(r.pid)
5685
+ );
5686
+ } catch {
5687
+ return [];
5688
+ }
5689
+ }
5690
+ function writePtyRegistry(records, file = DEFAULT_REGISTRY_FILE) {
5691
+ try {
5692
+ fs2.mkdirSync(path3.dirname(file), { recursive: true });
5693
+ const tmp = `${file}.${process.pid}.${crypto2.randomBytes(4).toString("hex")}.tmp`;
5694
+ fs2.writeFileSync(tmp, JSON.stringify(records, null, 2));
5695
+ fs2.renameSync(tmp, file);
5696
+ } catch {
5697
+ }
5698
+ }
5699
+ function registerPty(record, file = DEFAULT_REGISTRY_FILE) {
5700
+ const records = readPtyRegistry(file).filter((r) => r.pid !== record.pid);
5701
+ records.push(record);
5702
+ writePtyRegistry(records, file);
5703
+ }
5704
+ function unregisterPty(pid, file = DEFAULT_REGISTRY_FILE) {
5705
+ const records = readPtyRegistry(file);
5706
+ const next = records.filter((r) => r.pid !== pid);
5707
+ if (next.length !== records.length) {
5708
+ writePtyRegistry(next, file);
5709
+ }
5710
+ }
5711
+
5652
5712
  // electron/terminal/server.ts
5653
5713
  var ptyProcesses = /* @__PURE__ */ new Map();
5654
5714
  var DEBUG_COLD_START = process.env.COPILOT_OFFICE_DEBUG_COLD_START === "1";
5655
5715
  var agentToTerminal = /* @__PURE__ */ new Map();
5656
5716
  var activeAgentViewers = /* @__PURE__ */ new Set();
5717
+ var agentForwardKeys = /* @__PURE__ */ new Set();
5718
+ var lastPtyDataAt = /* @__PURE__ */ new Map();
5657
5719
  var viewerMaps = { activeAgentViewers, agentToTerminal };
5658
5720
  var agentWatchers = /* @__PURE__ */ new Map();
5659
5721
  var terminalBackend = null;
5660
5722
  var eventSourceFactory = new FileWatcherEventSourceFactory();
5661
5723
  var agentReadyState = /* @__PURE__ */ new Map();
5662
5724
  var agentInTurn = /* @__PURE__ */ new Map();
5725
+ var userMessageSeq = /* @__PURE__ */ new Map();
5726
+ var lastUserMessageText = /* @__PURE__ */ new Map();
5727
+ function normalizePromptText(s) {
5728
+ return s.replace(/\s+/g, " ").trim();
5729
+ }
5663
5730
  var MAX_BUFFER_BYTES = 512 * 1024;
5664
5731
  var agentScrollbackBuffers = /* @__PURE__ */ new Map();
5665
5732
  var agentScrollbackBytes = /* @__PURE__ */ new Map();
5666
- var DATA_DIR = path3.join(process.cwd(), ".data");
5667
- var OLD_SESSION_FILE = path3.join(DATA_DIR, "copilot-office-sessions.json");
5668
- var OFFICES_FILE = path3.join(DATA_DIR, "copilot-offices.json");
5733
+ var DATA_DIR = path4.join(process.cwd(), ".data");
5734
+ var OLD_SESSION_FILE = path4.join(DATA_DIR, "copilot-office-sessions.json");
5735
+ var OFFICES_FILE = path4.join(DATA_DIR, "copilot-offices.json");
5669
5736
  var officeSessions = /* @__PURE__ */ new Map();
5670
5737
  var hasAutoTitled = /* @__PURE__ */ new Set();
5671
5738
  function getSessionFile(officeId) {
5672
- return path3.join(DATA_DIR, `${officeId}.sessions.json`);
5739
+ return path4.join(DATA_DIR, `${officeId}.sessions.json`);
5673
5740
  }
5674
5741
  function getOfficeSession(officeId) {
5675
5742
  let data = officeSessions.get(officeId);
@@ -5707,9 +5774,9 @@ function appendToScrollback(agentId, data) {
5707
5774
  }
5708
5775
  async function loadOfficeSessionFile(officeId) {
5709
5776
  try {
5710
- await fs2.promises.mkdir(DATA_DIR, { recursive: true });
5777
+ await fs3.promises.mkdir(DATA_DIR, { recursive: true });
5711
5778
  const filePath = getSessionFile(officeId);
5712
- const raw = await fs2.promises.readFile(filePath, "utf8").catch(() => null);
5779
+ const raw = await fs3.promises.readFile(filePath, "utf8").catch(() => null);
5713
5780
  const data = getOfficeSession(officeId);
5714
5781
  if (raw) {
5715
5782
  const parsed = JSON.parse(raw);
@@ -5739,27 +5806,27 @@ async function loadOfficeSessionFile(officeId) {
5739
5806
  }
5740
5807
  async function saveOfficeSessionFile(officeId) {
5741
5808
  try {
5742
- await fs2.promises.mkdir(DATA_DIR, { recursive: true });
5809
+ await fs3.promises.mkdir(DATA_DIR, { recursive: true });
5743
5810
  const data = getOfficeSession(officeId);
5744
5811
  const json = {
5745
5812
  current: Object.fromEntries(data.sessionIds),
5746
5813
  history: Object.fromEntries(data.sessionHistory),
5747
5814
  metadata: Object.fromEntries(data.sessionMeta)
5748
5815
  };
5749
- await fs2.promises.writeFile(getSessionFile(officeId), JSON.stringify(json, null, 2));
5816
+ await fs3.promises.writeFile(getSessionFile(officeId), JSON.stringify(json, null, 2));
5750
5817
  } catch (e) {
5751
5818
  console.error(`[TermServer] Failed to save sessions for ${officeId}:`, e);
5752
5819
  }
5753
5820
  }
5754
5821
  async function createEmptySessionFile(officeId) {
5755
- await fs2.promises.mkdir(DATA_DIR, { recursive: true });
5822
+ await fs3.promises.mkdir(DATA_DIR, { recursive: true });
5756
5823
  const filePath = getSessionFile(officeId);
5757
5824
  try {
5758
- await fs2.promises.access(filePath, fs2.constants.F_OK);
5825
+ await fs3.promises.access(filePath, fs3.constants.F_OK);
5759
5826
  await loadOfficeSessionFile(officeId);
5760
5827
  } catch {
5761
5828
  const empty = { current: {}, history: {}, metadata: {} };
5762
- await fs2.promises.writeFile(filePath, JSON.stringify(empty, null, 2));
5829
+ await fs3.promises.writeFile(filePath, JSON.stringify(empty, null, 2));
5763
5830
  getOfficeSession(officeId);
5764
5831
  console.log(`[TermServer] Created empty session file for ${officeId}: ${filePath}`);
5765
5832
  }
@@ -5779,19 +5846,19 @@ async function migrateGlobalSessionFile() {
5779
5846
  try {
5780
5847
  const migratedMarker = OLD_SESSION_FILE + ".migrated";
5781
5848
  try {
5782
- await fs2.promises.access(migratedMarker, fs2.constants.F_OK);
5849
+ await fs3.promises.access(migratedMarker, fs3.constants.F_OK);
5783
5850
  return;
5784
5851
  } catch {
5785
5852
  }
5786
5853
  let oldRaw = null;
5787
5854
  try {
5788
- oldRaw = await fs2.promises.readFile(OLD_SESSION_FILE, "utf8");
5855
+ oldRaw = await fs3.promises.readFile(OLD_SESSION_FILE, "utf8");
5789
5856
  } catch {
5790
5857
  return;
5791
5858
  }
5792
5859
  let firstOfficeId = "office-0";
5793
5860
  try {
5794
- const officesRaw = await fs2.promises.readFile(OFFICES_FILE, "utf8");
5861
+ const officesRaw = await fs3.promises.readFile(OFFICES_FILE, "utf8");
5795
5862
  const officesData = JSON.parse(officesRaw);
5796
5863
  if (Array.isArray(officesData.offices) && officesData.offices.length > 0) {
5797
5864
  firstOfficeId = officesData.offices[0].id || "office-0";
@@ -5800,22 +5867,22 @@ async function migrateGlobalSessionFile() {
5800
5867
  }
5801
5868
  const firstOfficeFile = getSessionFile(firstOfficeId);
5802
5869
  try {
5803
- await fs2.promises.access(firstOfficeFile, fs2.constants.F_OK);
5870
+ await fs3.promises.access(firstOfficeFile, fs3.constants.F_OK);
5804
5871
  } catch {
5805
- await fs2.promises.writeFile(firstOfficeFile, oldRaw);
5872
+ await fs3.promises.writeFile(firstOfficeFile, oldRaw);
5806
5873
  console.log(`[TermServer] Migrated global sessions to ${firstOfficeFile}`);
5807
5874
  }
5808
- await fs2.promises.rename(OLD_SESSION_FILE, migratedMarker);
5875
+ await fs3.promises.rename(OLD_SESSION_FILE, migratedMarker);
5809
5876
  console.log(`[TermServer] Renamed old session file to ${migratedMarker}`);
5810
5877
  } catch (e) {
5811
5878
  console.error("[TermServer] Migration error:", e);
5812
5879
  }
5813
5880
  }
5814
5881
  async function loadAllOfficeSessions() {
5815
- await fs2.promises.mkdir(DATA_DIR, { recursive: true });
5882
+ await fs3.promises.mkdir(DATA_DIR, { recursive: true });
5816
5883
  await migrateGlobalSessionFile();
5817
5884
  try {
5818
- const files = await fs2.promises.readdir(DATA_DIR);
5885
+ const files = await fs3.promises.readdir(DATA_DIR);
5819
5886
  for (const file of files) {
5820
5887
  const match = file.match(/^(.+)\.sessions\.json$/);
5821
5888
  if (match) {
@@ -5833,6 +5900,46 @@ function getTerminalKey(officeId, agentId) {
5833
5900
  if (ptyProcesses.has(ck)) return ck;
5834
5901
  return null;
5835
5902
  }
5903
+ function submitViaKeystrokes(proc, prompt, ck) {
5904
+ const text = prompt.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
5905
+ const safeWrite = (data) => {
5906
+ try {
5907
+ proc.write(data);
5908
+ } catch {
5909
+ }
5910
+ lastPtyDataAt.set(ck, Date.now());
5911
+ };
5912
+ const waitForIdle = (quietMs, capMs) => new Promise((resolve) => {
5913
+ const start = Date.now();
5914
+ const tick = () => {
5915
+ const last = lastPtyDataAt.get(ck) ?? 0;
5916
+ if (Date.now() - last >= quietMs || Date.now() - start >= capMs) resolve();
5917
+ else setTimeout(tick, 50);
5918
+ };
5919
+ tick();
5920
+ });
5921
+ void (async () => {
5922
+ await waitForIdle(300, 3e3);
5923
+ safeWrite("");
5924
+ safeWrite(`\x1B[200~${text}\x1B[201~`);
5925
+ await waitForIdle(250, 2e3);
5926
+ const delay = (ms) => new Promise((r) => setTimeout(r, ms));
5927
+ const want = normalizePromptText(text);
5928
+ const baseline = userMessageSeq.get(ck) ?? 0;
5929
+ const accepted = () => (userMessageSeq.get(ck) ?? 0) > baseline && lastUserMessageText.get(ck) === want;
5930
+ const MAX_ATTEMPTS = 12;
5931
+ const POLL_MS = 500;
5932
+ for (let attempt = 0; attempt < MAX_ATTEMPTS && !accepted(); attempt++) {
5933
+ safeWrite("\r");
5934
+ for (let waited = 0; waited < POLL_MS && !accepted(); waited += 50) {
5935
+ await delay(50);
5936
+ }
5937
+ }
5938
+ if (!accepted()) {
5939
+ console.warn(`[TermServer] submitViaKeystrokes: prompt not confirmed accepted after ${MAX_ATTEMPTS} Enter attempts for ${ck} \u2014 it may not have submitted.`);
5940
+ }
5941
+ })();
5942
+ }
5836
5943
  function killAllPtyProcesses() {
5837
5944
  console.log(`[TermServer] Killing ${ptyProcesses.size} PTY processes`);
5838
5945
  ptyProcesses.forEach((proc) => killPtyProcess(proc));
@@ -5843,7 +5950,10 @@ function killAllPtyProcesses() {
5843
5950
  }
5844
5951
  function killPtyProcess(proc) {
5845
5952
  proc.process.kill();
5953
+ unregisterPty(proc.pid);
5846
5954
  }
5955
+ var yoloEnabled = false;
5956
+ var additionalParams = "";
5847
5957
  var pendingPreseededPrompts = /* @__PURE__ */ new Map();
5848
5958
  async function startTerminalForAgent(officeId, agentId, workingDir, cols, rows, preseededPrompt, launchMode = "copilot") {
5849
5959
  if (process.env.COPILOT_E2E === "1") {
@@ -5865,7 +5975,7 @@ async function startTerminalForAgent(officeId, agentId, workingDir, cols, rows,
5865
5975
  const officeData = getOfficeSession(officeId);
5866
5976
  let sessionId = officeData.sessionIds.get(agentId);
5867
5977
  if (!sessionId) {
5868
- sessionId = crypto2.randomUUID();
5978
+ sessionId = crypto3.randomUUID();
5869
5979
  officeData.sessionIds.set(agentId, sessionId);
5870
5980
  await saveOfficeSessionFile(officeId);
5871
5981
  console.log(`[TermServer] New session GUID for ${ck}: ${sessionId}`);
@@ -5876,9 +5986,9 @@ async function startTerminalForAgent(officeId, agentId, workingDir, cols, rows,
5876
5986
  const shell = os3.platform() === "win32" ? "powershell.exe" : "bash";
5877
5987
  let cwd = process.cwd();
5878
5988
  if (workingDir) {
5879
- const customPath = path3.isAbsolute(workingDir) ? workingDir : path3.join(process.cwd(), workingDir);
5989
+ const customPath = path4.isAbsolute(workingDir) ? workingDir : path4.join(process.cwd(), workingDir);
5880
5990
  try {
5881
- await fs2.promises.access(customPath, fs2.constants.F_OK);
5991
+ await fs3.promises.access(customPath, fs3.constants.F_OK);
5882
5992
  cwd = customPath;
5883
5993
  } catch {
5884
5994
  }
@@ -5906,6 +6016,9 @@ async function startTerminalForAgent(officeId, agentId, workingDir, cols, rows,
5906
6016
  workingDir
5907
6017
  });
5908
6018
  agentToTerminal.set(ck, terminalKey);
6019
+ if (terminalBackend.name === "node-pty") {
6020
+ registerPty({ pid: proc.pid, agentId, sessionId, startedAt: Date.now() });
6021
+ }
5909
6022
  if (!shellOnlyMode) {
5910
6023
  send({ type: "terminal-preload-status", agentId, status: "preloading" });
5911
6024
  }
@@ -5964,8 +6077,16 @@ async function startTerminalForAgent(officeId, agentId, workingDir, cols, rows,
5964
6077
  console.log(`[TermServer] Forwarding turn_start for ${ck}`);
5965
6078
  send({ type: "copilot-turn-start", agentId });
5966
6079
  } else if (event.type === "user.message") {
6080
+ userMessageSeq.set(ck, (userMessageSeq.get(ck) ?? 0) + 1);
6081
+ let rawUserText = "";
6082
+ {
6083
+ const d = event.data ?? {};
6084
+ const raw = d.content || d.message || d.text || d.input || d.prompt || d.body || "";
6085
+ rawUserText = String(raw);
6086
+ lastUserMessageText.set(ck, normalizePromptText(rawUserText));
6087
+ }
5967
6088
  console.log(`[TermServer] Forwarding user_message for ${ck}, data keys: ${JSON.stringify(Object.keys(event.data || {}))}`);
5968
- send({ type: "copilot-user-message", agentId });
6089
+ send({ type: "copilot-user-message", agentId, text: rawUserText });
5969
6090
  const existing = officeData.sessionMeta.get(agentId);
5970
6091
  const existingTitle = typeof existing?.title === "string" ? existing.title.trim() : "";
5971
6092
  if (existingTitle) {
@@ -6000,6 +6121,8 @@ async function startTerminalForAgent(officeId, agentId, workingDir, cols, rows,
6000
6121
  const isFleetCriticalEvent = event.type.startsWith("subagent.") || event.type === "system.notification" || event.type === "tool.execution_start" && event.data?.toolName === "task";
6001
6122
  if (isFleetCriticalEvent || hasActiveViewer2(ck)) {
6002
6123
  send({ type: "copilot-event", agentId, event });
6124
+ } else if (agentForwardKeys.has(ck)) {
6125
+ send({ type: "copilot-event", agentId, event, mainOnly: true });
6003
6126
  } else {
6004
6127
  console.warn(`[TermServer] Dropped copilot-event ${event.type} for ${ck} \u2014 no active viewer (viewers: [${[...activeAgentViewers].join(", ")}])`);
6005
6128
  }
@@ -6017,6 +6140,7 @@ async function startTerminalForAgent(officeId, agentId, workingDir, cols, rows,
6017
6140
  pendingData = "";
6018
6141
  };
6019
6142
  proc.onData((data) => {
6143
+ lastPtyDataAt.set(ck, Date.now());
6020
6144
  appendToScrollback(ck, data);
6021
6145
  if (!shellOnlyMode && terminalBackend?.name === "node-pty" && !hasSignalledReady) {
6022
6146
  const hasLegacyReadyMarker = data.includes("Environment loaded");
@@ -6037,12 +6161,16 @@ async function startTerminalForAgent(officeId, agentId, workingDir, cols, rows,
6037
6161
  });
6038
6162
  proc.onExit(({ exitCode }) => {
6039
6163
  send({ type: "terminal-exit", agentId, exitCode });
6164
+ unregisterPty(proc.pid);
6040
6165
  ptyProcesses.delete(terminalKey);
6041
6166
  activeAgentViewers.delete(ck);
6042
6167
  agentScrollbackBuffers.delete(ck);
6043
6168
  agentScrollbackBytes.delete(ck);
6044
6169
  agentReadyState.delete(ck);
6045
6170
  agentInTurn.delete(ck);
6171
+ lastPtyDataAt.delete(ck);
6172
+ userMessageSeq.delete(ck);
6173
+ lastUserMessageText.delete(ck);
6046
6174
  const w = agentWatchers.get(ck);
6047
6175
  if (w) {
6048
6176
  w.stop();
@@ -6051,8 +6179,10 @@ async function startTerminalForAgent(officeId, agentId, workingDir, cols, rows,
6051
6179
  });
6052
6180
  if (!shellOnlyMode && terminalBackend.name === "node-pty") {
6053
6181
  setTimeout(() => {
6054
- console.log(`[TermServer] Starting copilot --session-id for ${ck}: ${sessionId}`);
6055
- proc.write(`copilot --session-id=${sessionId}\r`);
6182
+ const yoloFlag = yoloEnabled ? " --yolo" : "";
6183
+ const extraParams = additionalParams ? ` ${additionalParams}` : "";
6184
+ console.log(`[TermServer] Starting copilot --session-id for ${ck}: ${sessionId}${yoloEnabled ? " (yolo)" : ""}${additionalParams ? ` (params: ${additionalParams})` : ""}`);
6185
+ proc.write(`copilot --session-id=${sessionId}${yoloFlag}${extraParams}\r`);
6056
6186
  }, 500);
6057
6187
  }
6058
6188
  return { success: true, pid: proc.pid, sessionId };
@@ -6083,12 +6213,47 @@ async function handleMessage(msg) {
6083
6213
  }
6084
6214
  break;
6085
6215
  }
6216
+ case "submit-prompt": {
6217
+ const key = getTerminalKey(msg.officeId, msg.agentId);
6218
+ const proc = key ? ptyProcesses.get(key) : null;
6219
+ if (proc) {
6220
+ agentForwardKeys.add(compositeKey(msg.officeId, msg.agentId));
6221
+ const backendProc = proc.process;
6222
+ if (typeof backendProc.submitPrompt === "function") {
6223
+ backendProc.submitPrompt(msg.prompt, msg.label);
6224
+ } else {
6225
+ submitViaKeystrokes(backendProc, msg.prompt, key);
6226
+ }
6227
+ send({ type: "response", requestId: msg.requestId, result: { success: true } });
6228
+ } else {
6229
+ const ck = compositeKey(msg.officeId, msg.agentId);
6230
+ console.log(`[TermServer] SUBMIT-PROMPT FAILED \u2014 no PTY for ${ck}`);
6231
+ send({ type: "response", requestId: msg.requestId, result: { success: false, error: `No PTY for ${ck}` } });
6232
+ }
6233
+ break;
6234
+ }
6235
+ case "set-agent-forwarding": {
6236
+ const ck = compositeKey(msg.officeId, msg.agentId);
6237
+ if (msg.enabled) agentForwardKeys.add(ck);
6238
+ else agentForwardKeys.delete(ck);
6239
+ break;
6240
+ }
6086
6241
  case "resize": {
6087
6242
  const key = getTerminalKey(msg.officeId, msg.agentId);
6088
6243
  const proc = key ? ptyProcesses.get(key) : null;
6089
6244
  if (proc) proc.process.resize(msg.cols, msg.rows);
6090
6245
  break;
6091
6246
  }
6247
+ case "set-yolo": {
6248
+ yoloEnabled = msg.enabled;
6249
+ console.log(`[TermServer] YOLO mode ${yoloEnabled ? "ENABLED" : "disabled"}`);
6250
+ break;
6251
+ }
6252
+ case "set-additional-params": {
6253
+ additionalParams = (msg.params ?? "").trim();
6254
+ console.log(`[TermServer] Additional params ${additionalParams ? `set: ${additionalParams}` : "cleared"}`);
6255
+ break;
6256
+ }
6092
6257
  case "kill": {
6093
6258
  const ck = compositeKey(msg.officeId, msg.agentId);
6094
6259
  const key = getTerminalKey(msg.officeId, msg.agentId);
@@ -6185,15 +6350,18 @@ async function handleMessage(msg) {
6185
6350
  const ptyProc = termKey ? ptyProcesses.get(termKey) : null;
6186
6351
  let cwd = process.cwd();
6187
6352
  if (ptyProc?.workingDir) {
6188
- const customPath = path3.join(process.cwd(), ptyProc.workingDir);
6353
+ const customPath = path4.join(process.cwd(), ptyProc.workingDir);
6189
6354
  try {
6190
- await fs2.promises.access(customPath, fs2.constants.F_OK);
6355
+ await fs3.promises.access(customPath, fs3.constants.F_OK);
6191
6356
  cwd = customPath;
6192
6357
  } catch {
6193
6358
  }
6194
6359
  }
6195
6360
  try {
6196
- (0, import_child_process2.spawn)("wt", ["-d", cwd, "copilot", "--session-id", sid], { detached: true, stdio: "ignore" }).unref();
6361
+ const wtArgs = ["-d", cwd, "copilot", "--session-id", sid];
6362
+ if (yoloEnabled) wtArgs.push("--yolo");
6363
+ if (additionalParams) wtArgs.push(...additionalParams.split(/\s+/).filter(Boolean));
6364
+ (0, import_child_process2.spawn)("wt", wtArgs, { detached: true, stdio: "ignore" }).unref();
6197
6365
  send({ type: "response", requestId: msg.requestId, result: { success: true } });
6198
6366
  } catch (error) {
6199
6367
  send({ type: "response", requestId: msg.requestId, result: { success: false, error: String(error) } });
@@ -6225,7 +6393,7 @@ async function handleMessage(msg) {
6225
6393
  hasAutoTitled.delete(ck);
6226
6394
  send({ type: "session-meta-updated", agentId: msg.agentId, meta: { title: "" } });
6227
6395
  archiveSessionId(msg.officeId, msg.agentId);
6228
- const newSessionId = crypto2.randomUUID();
6396
+ const newSessionId = crypto3.randomUUID();
6229
6397
  officeDataReset.sessionIds.set(msg.agentId, newSessionId);
6230
6398
  await saveOfficeSessionFile(msg.officeId);
6231
6399
  console.log(`[TermServer] Reset session for ${ck}: new GUID ${newSessionId}`);
@@ -6276,7 +6444,7 @@ async function handleMessage(msg) {
6276
6444
  }
6277
6445
  officeData.sessionMeta.clear();
6278
6446
  for (const agentId of officeData.sessionIds.keys()) {
6279
- officeData.sessionIds.set(agentId, crypto2.randomUUID());
6447
+ officeData.sessionIds.set(agentId, crypto3.randomUUID());
6280
6448
  }
6281
6449
  await saveOfficeSessionFile(officeId);
6282
6450
  console.log(`[TermServer] All sessions reset for ${officeId}`);
@@ -6351,7 +6519,7 @@ async function handleMessage(msg) {
6351
6519
  case "delete-office-session": {
6352
6520
  const filePath = getSessionFile(msg.officeId);
6353
6521
  try {
6354
- await fs2.promises.unlink(filePath);
6522
+ await fs3.promises.unlink(filePath);
6355
6523
  officeSessions.delete(msg.officeId);
6356
6524
  console.log(`[TermServer] Deleted session file for ${msg.officeId}`);
6357
6525
  } catch {