@couralabs/claudin 0.1.3 → 0.1.4

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.
Files changed (2) hide show
  1. package/claudin.js +1379 -144
  2. package/package.json +2 -2
package/claudin.js CHANGED
@@ -6161,7 +6161,6 @@ var agentRequestSchemas = [
6161
6161
  answers: record(string2(), string2())
6162
6162
  }),
6163
6163
  object({ type: literal("agent.model.set.requested"), agentSessionId, model: string2() }),
6164
- object({ type: literal("agent.model.cycle.requested"), agentSessionId }),
6165
6164
  object({
6166
6165
  type: literal("agent.permission_mode.set.requested"),
6167
6166
  agentSessionId,
@@ -6175,6 +6174,17 @@ var agentRequestSchemas = [
6175
6174
  object({ type: literal("agent.commands.requested"), agentSessionId }),
6176
6175
  object({ type: literal("agent.models.requested"), agentSessionId }),
6177
6176
  object({ type: literal("agent.mcp.status.requested"), agentSessionId }),
6177
+ object({
6178
+ type: literal("agent.mcp.login.requested"),
6179
+ agentSessionId,
6180
+ serverName: string2()
6181
+ }),
6182
+ object({
6183
+ type: literal("agent.mcp.callback.submitted"),
6184
+ agentSessionId,
6185
+ serverName: string2(),
6186
+ callbackUrl: string2()
6187
+ }),
6178
6188
  object({ type: literal("agent.usage.requested"), agentSessionId }),
6179
6189
  object({ type: literal("agent.rate_limit.requested"), agentSessionId }),
6180
6190
  object({ type: literal("agent.rate_limit.cached.requested") }),
@@ -6217,7 +6227,8 @@ var createSessionState = (sessionId) => ({
6217
6227
  backgroundEditor: null,
6218
6228
  question: null,
6219
6229
  history: null,
6220
- diffViewer: null
6230
+ diffViewer: null,
6231
+ toast: null
6221
6232
  }
6222
6233
  });
6223
6234
 
@@ -6632,7 +6643,7 @@ var applyLoadedBackground = (state, background = TRANSPARENT_BACKGROUND) => ({ .
6632
6643
  var applySavedBackground = (state, color) => appendNotice(closeBackgroundEditor({ ...state, background: color }), "Background color saved");
6633
6644
 
6634
6645
  // packages/events/src/reducers/reduceDiffViewer.ts
6635
- var NO_DIFFS_NOTICE = "No changes in the files this session edited";
6646
+ var NO_DIFFS_NOTICE = "No git changes or session edits to show";
6636
6647
  function openDiffViewer(state, files) {
6637
6648
  if (files.length === 0)
6638
6649
  return appendNotice(state, NO_DIFFS_NOTICE);
@@ -6651,7 +6662,10 @@ var closeDiffViewer = (state) => ({
6651
6662
  });
6652
6663
 
6653
6664
  // packages/events/src/reducers/reduceNotices.ts
6654
- var describeServers = (servers) => servers.length === 0 ? "No MCP servers configured" : `MCP servers: ${servers.map((s) => `${s.name} (${s.status})`).join(", ")}`;
6665
+ var LOGIN_HINT = "needs-auth: sign in with /mcp login <name>";
6666
+ var describeServer = ({ name, status }) => `${name} (${status === "needs-auth" ? LOGIN_HINT.replace("<name>", name) : status})`;
6667
+ var describeServers = (servers) => servers.length === 0 ? "No MCP servers configured" : `MCP servers: ${servers.map(describeServer).join(", ")}`;
6668
+ var describeLoginStarted = (serverName, authUrl) => `Signing in to ${serverName}. If the browser did not open, visit: ${authUrl}`;
6655
6669
  function reduceModelChanged(state, model) {
6656
6670
  const changed = { ...state, model };
6657
6671
  return appendNotice(changed, `Model set to ${readModelLabel(changed)}`);
@@ -6703,6 +6717,13 @@ function moveQuestionCursor(state, delta) {
6703
6717
  return state;
6704
6718
  return withDraft(state, { ...question, cursor: (question.cursor + delta + size) % size });
6705
6719
  }
6720
+ function setQuestionCursor(state, cursor) {
6721
+ const { question } = state.ui;
6722
+ const current = question ? readCurrentQuestion(question) : undefined;
6723
+ if (!question || !current || cursor < 0 || cursor > current.options.length)
6724
+ return state;
6725
+ return withDraft(state, { ...question, cursor });
6726
+ }
6706
6727
  function toggleQuestionPick(state) {
6707
6728
  const { question } = state.ui;
6708
6729
  const current = question ? readCurrentQuestion(question) : undefined;
@@ -6730,6 +6751,14 @@ function changeQuestionCustom(state, text) {
6730
6751
  return question ? withDraft(state, { ...question, custom: text }) : state;
6731
6752
  }
6732
6753
 
6754
+ // packages/events/src/reducers/reduceToast.ts
6755
+ var withToast = (state, toast) => ({
6756
+ ...state,
6757
+ ui: { ...state.ui, toast }
6758
+ });
6759
+ var postToast = (state, toast) => withToast(state, { id: toast.id, text: toast.text });
6760
+ var dismissToast = (state, id) => state.ui.toast?.id === id ? withToast(state, null) : state;
6761
+
6733
6762
  // packages/events/src/reducers/reduceUi.ts
6734
6763
  var FOCUS_ORDER = ["input", "scrollback"];
6735
6764
  function cycleFocus(state, direction) {
@@ -6817,6 +6846,8 @@ function reduceUi(state, event) {
6817
6846
  return adjustBackgroundValue(state, event.delta);
6818
6847
  case "ui.question.moved":
6819
6848
  return moveQuestionCursor(state, event.delta);
6849
+ case "ui.question.cursor.set":
6850
+ return setQuestionCursor(state, event.cursor);
6820
6851
  case "ui.question.toggled":
6821
6852
  return toggleQuestionPick(state);
6822
6853
  case "ui.question.custom.changed":
@@ -6827,6 +6858,10 @@ function reduceUi(state, event) {
6827
6858
  return state;
6828
6859
  case "ui.notice.posted":
6829
6860
  return appendNotice(state, event.text);
6861
+ case "ui.toast.posted":
6862
+ return postToast(state, event);
6863
+ case "ui.toast.dismissed":
6864
+ return dismissToast(state, event.id);
6830
6865
  case "ui.clock.ticked":
6831
6866
  return { ...state, now: event.now };
6832
6867
  }
@@ -6847,7 +6882,8 @@ function restoreSession(state, sessionId, stored, notice) {
6847
6882
  return appendNotice({ ...adoptReplay(state, settled, sessionId), status: "idle", queuedTurns: 0 }, notice);
6848
6883
  }
6849
6884
  var syncSession = (state, sessionId, stored) => appendNotice(adoptReplay(state, replayEvents(sessionId, stored), sessionId), "Attached to the live session");
6850
- function openModelPicker(state, models) {
6885
+ function openModelPicker(state, allModels) {
6886
+ const models = allModels.filter((model) => model.value !== "default");
6851
6887
  const current = models.findIndex((model) => model.value === state.model);
6852
6888
  const picker = { kind: "model", selected: Math.max(current, 0) };
6853
6889
  return { ...state, models, ui: { ...state.ui, picker } };
@@ -6937,6 +6973,8 @@ function reduceSessionState(state, event) {
6937
6973
  return reduceModeChanged(state, event.mode);
6938
6974
  case "agent.mcp.status.received":
6939
6975
  return appendNotice(state, describeServers(event.servers));
6976
+ case "agent.mcp.login.started":
6977
+ return appendNotice(state, describeLoginStarted(event.serverName, event.authUrl));
6940
6978
  case "workspace.info.received":
6941
6979
  return { ...state, cwd: event.cwd, gitBranch: event.gitBranch, gitStats: event.gitStats };
6942
6980
  case "options.loaded":
@@ -7059,6 +7097,11 @@ var agentResponseSchemas = [
7059
7097
  type: literal("agent.mcp.status.received"),
7060
7098
  servers: sdkValue()
7061
7099
  }),
7100
+ object({
7101
+ type: literal("agent.mcp.login.started"),
7102
+ serverName: string2(),
7103
+ authUrl: string2()
7104
+ }),
7062
7105
  object({
7063
7106
  type: literal("agent.usage.received"),
7064
7107
  usage: sdkValue()
@@ -7156,6 +7199,9 @@ var PRIVATE_TYPES = new Set([
7156
7199
  "agent.commands.requested",
7157
7200
  "agent.mcp.status.requested",
7158
7201
  "agent.mcp.status.received",
7202
+ "agent.mcp.login.requested",
7203
+ "agent.mcp.callback.submitted",
7204
+ "agent.mcp.login.started",
7159
7205
  "agent.usage.requested",
7160
7206
  "agent.usage.received",
7161
7207
  "agent.rate_limit.requested",
@@ -7396,12 +7442,41 @@ import {
7396
7442
  getSessionMessages,
7397
7443
  query
7398
7444
  } from "@anthropic-ai/claude-agent-sdk";
7445
+
7446
+ // packages/agent/src/runtime/muteShadowedWarning.ts
7447
+ var SHADOWED_WARNING_CODE = "CLAUDE_SDK_CAN_USE_TOOL_SHADOWED";
7448
+ function readWarningCode(args) {
7449
+ const [first, second] = args;
7450
+ if (typeof first === "object" && first !== null)
7451
+ return first.code;
7452
+ return typeof first === "string" && typeof second === "string" ? second : undefined;
7453
+ }
7454
+ function muteShadowedWarning() {
7455
+ const original = process.emitWarning.bind(process);
7456
+ process.emitWarning = (warning, ...args) => {
7457
+ if (readWarningCode(args) === SHADOWED_WARNING_CODE)
7458
+ return;
7459
+ return original(warning, ...args);
7460
+ };
7461
+ }
7462
+
7463
+ // packages/agent/src/runtime/agentRuntime.ts
7464
+ muteShadowedWarning();
7399
7465
  var sdkRuntime = {
7400
- open: query,
7466
+ open: (params) => query(params),
7401
7467
  getInfo: getSessionInfo,
7402
7468
  getMessages: getSessionMessages,
7403
7469
  fork: forkSession
7404
7470
  };
7471
+ // packages/agent/src/runtime/buildUserMessage.ts
7472
+ var isSlashCommand = (content) => readPromptText(content).trimStart().startsWith("/");
7473
+ var buildUserMessage = (content, priority) => ({
7474
+ type: "user",
7475
+ message: { role: "user", content },
7476
+ parent_tool_use_id: null,
7477
+ priority,
7478
+ client_composed: isSlashCommand(content) ? undefined : true
7479
+ });
7405
7480
  // node_modules/.bun/p-defer@4.0.1/node_modules/p-defer/index.js
7406
7481
  function pDefer() {
7407
7482
  const deferred = {};
@@ -7684,6 +7759,846 @@ function _pushable(getNext, options) {
7684
7759
  };
7685
7760
  return pushable;
7686
7761
  }
7762
+ // packages/agent/src/mcp/waitForMcpLogin.ts
7763
+ var DEFAULT_LOGIN_WAIT = { intervalMs: 2000, timeoutMs: 180000 };
7764
+ async function waitForMcpLogin(fetchStatus, serverName, { intervalMs, timeoutMs } = DEFAULT_LOGIN_WAIT) {
7765
+ const deadline = Date.now() + timeoutMs;
7766
+ let servers = await fetchStatus();
7767
+ while (Date.now() < deadline && isAwaitingLogin(servers, serverName)) {
7768
+ await Bun.sleep(intervalMs);
7769
+ servers = await fetchStatus();
7770
+ }
7771
+ return servers;
7772
+ }
7773
+ var isAwaitingLogin = (servers, serverName) => servers.some((server) => server.name === serverName && server.status === "needs-auth");
7774
+
7775
+ // node_modules/.bun/open@11.0.4/node_modules/open/index.js
7776
+ import process9 from "process";
7777
+ import path2 from "path";
7778
+ import { fileURLToPath } from "url";
7779
+ import childProcess3 from "child_process";
7780
+ import fs5, { constants as fsConstants2 } from "fs/promises";
7781
+
7782
+ // node_modules/.bun/wsl-utils@1.0.1/node_modules/wsl-utils/index.js
7783
+ import path from "path";
7784
+ import { promisify as promisify2 } from "util";
7785
+ import childProcess2 from "child_process";
7786
+ import fs4, { constants as fsConstants } from "fs/promises";
7787
+
7788
+ // node_modules/.bun/is-wsl@3.1.1/node_modules/is-wsl/index.js
7789
+ import process2 from "process";
7790
+ import os from "os";
7791
+ import fs3 from "fs";
7792
+
7793
+ // node_modules/.bun/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
7794
+ import fs2 from "fs";
7795
+
7796
+ // node_modules/.bun/is-docker@3.0.0/node_modules/is-docker/index.js
7797
+ import fs from "fs";
7798
+ var isDockerCached;
7799
+ function hasDockerEnv() {
7800
+ try {
7801
+ fs.statSync("/.dockerenv");
7802
+ return true;
7803
+ } catch {
7804
+ return false;
7805
+ }
7806
+ }
7807
+ function hasDockerCGroup() {
7808
+ try {
7809
+ return fs.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
7810
+ } catch {
7811
+ return false;
7812
+ }
7813
+ }
7814
+ function isDocker() {
7815
+ if (isDockerCached === undefined) {
7816
+ isDockerCached = hasDockerEnv() || hasDockerCGroup();
7817
+ }
7818
+ return isDockerCached;
7819
+ }
7820
+
7821
+ // node_modules/.bun/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
7822
+ var cachedResult;
7823
+ var hasContainerEnv = () => {
7824
+ try {
7825
+ fs2.statSync("/run/.containerenv");
7826
+ return true;
7827
+ } catch {
7828
+ return false;
7829
+ }
7830
+ };
7831
+ function isInsideContainer() {
7832
+ if (cachedResult === undefined) {
7833
+ cachedResult = hasContainerEnv() || isDocker();
7834
+ }
7835
+ return cachedResult;
7836
+ }
7837
+
7838
+ // node_modules/.bun/is-wsl@3.1.1/node_modules/is-wsl/index.js
7839
+ var isWsl = () => {
7840
+ if (process2.platform !== "linux") {
7841
+ return false;
7842
+ }
7843
+ if (os.release().toLowerCase().includes("microsoft")) {
7844
+ if (isInsideContainer()) {
7845
+ return false;
7846
+ }
7847
+ return true;
7848
+ }
7849
+ try {
7850
+ if (fs3.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft")) {
7851
+ return !isInsideContainer();
7852
+ }
7853
+ } catch {}
7854
+ if (fs3.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop") || fs3.existsSync("/run/WSL")) {
7855
+ return !isInsideContainer();
7856
+ }
7857
+ return false;
7858
+ };
7859
+ var is_wsl_default = process2.env.__IS_WSL_TEST__ ? isWsl : isWsl();
7860
+
7861
+ // node_modules/.bun/powershell-utils@0.2.1/node_modules/powershell-utils/index.js
7862
+ import process3 from "process";
7863
+ import { Buffer as Buffer2 } from "buffer";
7864
+ import { promisify } from "util";
7865
+ import childProcess from "child_process";
7866
+ var execFile = promisify(childProcess.execFile);
7867
+ var powerShellPath = () => `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
7868
+ var argumentsPrefix = [
7869
+ "-NoProfile",
7870
+ "-NonInteractive",
7871
+ "-ExecutionPolicy",
7872
+ "Bypass",
7873
+ "-EncodedCommand"
7874
+ ];
7875
+ var encodeCommand = (command) => Buffer2.from(command, "utf16le").toString("base64");
7876
+ var escapeArgument = (value) => `'${String(value).replaceAll(/['\u2018\u2019\u201A\u201B]/g, (match) => match + match)}'`;
7877
+ var createArguments = (command) => [...argumentsPrefix, encodeCommand(command)];
7878
+ var createExecFileOptions = (options) => ({
7879
+ encoding: "utf8",
7880
+ ...options,
7881
+ shell: false
7882
+ });
7883
+ var executePowerShell = async (command, options = {}) => {
7884
+ const {
7885
+ powerShellPath: psPath,
7886
+ ...execFileOptions
7887
+ } = options;
7888
+ return execFile(psPath ?? powerShellPath(), createArguments(command), createExecFileOptions(execFileOptions));
7889
+ };
7890
+ executePowerShell.argumentsPrefix = argumentsPrefix;
7891
+ executePowerShell.encodeCommand = encodeCommand;
7892
+ executePowerShell.escapeArgument = escapeArgument;
7893
+ executePowerShell.createArguments = createArguments;
7894
+
7895
+ // node_modules/.bun/wsl-utils@1.0.1/node_modules/wsl-utils/utilities.js
7896
+ function parseMountPointFromConfig(content) {
7897
+ for (const line of content.split(`
7898
+ `)) {
7899
+ if (/^\s*#/.test(line)) {
7900
+ continue;
7901
+ }
7902
+ const match = /^\s*root\s*=\s*(?<mountPoint>"[^"]*"|'[^']*'|[^#]*)/.exec(line);
7903
+ if (!match) {
7904
+ continue;
7905
+ }
7906
+ return match.groups.mountPoint.trim().replaceAll(/^["']|["']$/g, "");
7907
+ }
7908
+ }
7909
+
7910
+ // node_modules/.bun/wsl-utils@1.0.1/node_modules/wsl-utils/index.js
7911
+ var execFile2 = promisify2(childProcess2.execFile);
7912
+ var wslDrivesMountPoint = (() => {
7913
+ const defaultMountPoint = "/mnt/";
7914
+ let mountPoint;
7915
+ return async function() {
7916
+ if (mountPoint) {
7917
+ return mountPoint;
7918
+ }
7919
+ const configFilePath = "/etc/wsl.conf";
7920
+ let isConfigFileExists = false;
7921
+ try {
7922
+ await fs4.access(configFilePath, fsConstants.F_OK);
7923
+ isConfigFileExists = true;
7924
+ } catch {}
7925
+ if (!isConfigFileExists) {
7926
+ return defaultMountPoint;
7927
+ }
7928
+ const configContent = await fs4.readFile(configFilePath, { encoding: "utf8" });
7929
+ const parsedMountPoint = parseMountPointFromConfig(configContent);
7930
+ if (parsedMountPoint === undefined) {
7931
+ return defaultMountPoint;
7932
+ }
7933
+ mountPoint = parsedMountPoint;
7934
+ mountPoint = mountPoint.endsWith("/") ? mountPoint : `${mountPoint}/`;
7935
+ return mountPoint;
7936
+ };
7937
+ })();
7938
+ var powerShellPathFromWsl = async () => {
7939
+ const mountPoint = await wslDrivesMountPoint();
7940
+ return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
7941
+ };
7942
+ var powerShellPath2 = is_wsl_default ? powerShellPathFromWsl : powerShellPath;
7943
+ var canAccessPowerShellPromise;
7944
+ var canAccessPowerShell = async () => {
7945
+ canAccessPowerShellPromise ??= (async () => {
7946
+ try {
7947
+ const psPath = await powerShellPath2();
7948
+ await fs4.access(psPath, fsConstants.X_OK);
7949
+ return true;
7950
+ } catch {
7951
+ return false;
7952
+ }
7953
+ })();
7954
+ return canAccessPowerShellPromise;
7955
+ };
7956
+ var wslDefaultBrowser = async () => {
7957
+ const psPath = await powerShellPath2();
7958
+ const command = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
7959
+ const { stdout } = await executePowerShell(command, {
7960
+ powerShellPath: psPath,
7961
+ cwd: path.dirname(psPath)
7962
+ });
7963
+ return stdout.trim();
7964
+ };
7965
+ var isUrl = (path2) => /^[a-z]+:\/\//i.test(path2);
7966
+ var convertPath = async (flag, path2) => {
7967
+ const wslpathArguments = path2.startsWith("-") ? [flag, "--", path2] : [flag, path2];
7968
+ try {
7969
+ const { stdout } = await execFile2("wslpath", wslpathArguments, { encoding: "utf8" });
7970
+ return stdout.replace(/\r?\n$/, "") || path2;
7971
+ } catch {
7972
+ return path2;
7973
+ }
7974
+ };
7975
+ var convertWslPathToWindows = async (paths) => {
7976
+ const isBatch = Array.isArray(paths);
7977
+ const pathArray = isBatch ? paths : [paths];
7978
+ const results = await Promise.all(pathArray.map((path2) => isUrl(path2) ? path2 : convertPath("-aw", path2)));
7979
+ return isBatch ? results : results[0];
7980
+ };
7981
+
7982
+ // node_modules/.bun/define-lazy-prop@3.0.0/node_modules/define-lazy-prop/index.js
7983
+ function defineLazyProperty(object, propertyName, valueGetter) {
7984
+ const define = (value) => Object.defineProperty(object, propertyName, { value, enumerable: true, writable: true });
7985
+ Object.defineProperty(object, propertyName, {
7986
+ configurable: true,
7987
+ enumerable: true,
7988
+ get() {
7989
+ const result = valueGetter();
7990
+ define(result);
7991
+ return result;
7992
+ },
7993
+ set(value) {
7994
+ define(value);
7995
+ }
7996
+ });
7997
+ return object;
7998
+ }
7999
+
8000
+ // node_modules/.bun/default-browser@5.5.1/node_modules/default-browser/index.js
8001
+ import { promisify as promisify6 } from "util";
8002
+ import process7 from "process";
8003
+ import { execFile as execFile6 } from "child_process";
8004
+
8005
+ // node_modules/.bun/default-browser-id@5.0.1/node_modules/default-browser-id/index.js
8006
+ import { promisify as promisify3 } from "util";
8007
+ import process4 from "process";
8008
+ import { execFile as execFile3 } from "child_process";
8009
+ var execFileAsync = promisify3(execFile3);
8010
+ async function defaultBrowserId() {
8011
+ if (process4.platform !== "darwin") {
8012
+ throw new Error("macOS only");
8013
+ }
8014
+ const { stdout } = await execFileAsync("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
8015
+ const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
8016
+ const browserId = match?.groups.id ?? "com.apple.Safari";
8017
+ if (browserId === "com.apple.safari") {
8018
+ return "com.apple.Safari";
8019
+ }
8020
+ return browserId;
8021
+ }
8022
+
8023
+ // node_modules/.bun/run-applescript@7.1.0/node_modules/run-applescript/index.js
8024
+ import process5 from "process";
8025
+ import { promisify as promisify4 } from "util";
8026
+ import { execFile as execFile4, execFileSync } from "child_process";
8027
+ var execFileAsync2 = promisify4(execFile4);
8028
+ async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
8029
+ if (process5.platform !== "darwin") {
8030
+ throw new Error("macOS only");
8031
+ }
8032
+ const outputArguments = humanReadableOutput ? [] : ["-ss"];
8033
+ const execOptions = {};
8034
+ if (signal) {
8035
+ execOptions.signal = signal;
8036
+ }
8037
+ const { stdout } = await execFileAsync2("osascript", ["-e", script, outputArguments], execOptions);
8038
+ return stdout.trim();
8039
+ }
8040
+
8041
+ // node_modules/.bun/bundle-name@4.1.1/node_modules/bundle-name/index.js
8042
+ var bundleIdentifierPattern = /^[^\n\r"\\]+$/u;
8043
+ async function bundleName(bundleId) {
8044
+ if (typeof bundleId !== "string") {
8045
+ throw new TypeError("Expected a string bundle identifier");
8046
+ }
8047
+ if (!bundleIdentifierPattern.test(bundleId)) {
8048
+ throw new TypeError(`Invalid bundle identifier: ${JSON.stringify(bundleId)}`);
8049
+ }
8050
+ return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
8051
+ tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
8052
+ }
8053
+
8054
+ // node_modules/.bun/default-browser@5.5.1/node_modules/default-browser/windows.js
8055
+ import process6 from "process";
8056
+ import { promisify as promisify5 } from "util";
8057
+ import { execFile as execFile5 } from "child_process";
8058
+ var execFileAsync3 = promisify5(execFile5);
8059
+ var windowsBrowserProgIds = {
8060
+ MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
8061
+ MSEdgeBHTML: { name: "Edge Beta", id: "com.microsoft.edge.beta" },
8062
+ MSEdgeDHTML: { name: "Edge Dev", id: "com.microsoft.edge.dev" },
8063
+ AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
8064
+ ChromeHTML: { name: "Chrome", id: "com.google.chrome" },
8065
+ ChromeBHTML: { name: "Chrome Beta", id: "com.google.chrome.beta" },
8066
+ ChromeDHTML: { name: "Chrome Dev", id: "com.google.chrome.dev" },
8067
+ ChromiumHTM: { name: "Chromium", id: "org.chromium.Chromium" },
8068
+ BraveHTML: { name: "Brave", id: "com.brave.Browser" },
8069
+ BraveBHTML: { name: "Brave Beta", id: "com.brave.Browser.beta" },
8070
+ BraveDHTML: { name: "Brave Dev", id: "com.brave.Browser.dev" },
8071
+ BraveSSHTM: { name: "Brave Nightly", id: "com.brave.Browser.nightly" },
8072
+ FirefoxURL: { name: "Firefox", id: "org.mozilla.firefox" },
8073
+ OperaStable: { name: "Opera", id: "com.operasoftware.Opera" },
8074
+ VivaldiHTM: { name: "Vivaldi", id: "com.vivaldi.Vivaldi" },
8075
+ "IE.HTTP": { name: "Internet Explorer", id: "com.microsoft.ie" }
8076
+ };
8077
+ var _windowsBrowserProgIdMap = new Map(Object.entries(windowsBrowserProgIds));
8078
+
8079
+ class UnknownBrowserError extends Error {
8080
+ }
8081
+ async function defaultBrowser(_execFileAsync = execFileAsync3) {
8082
+ const regPath = `${process6.env.SYSTEMROOT ?? process6.env.windir ?? "C:\\Windows"}\\System32\\reg.exe`;
8083
+ const { stdout } = await _execFileAsync(regPath, [
8084
+ "QUERY",
8085
+ " HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
8086
+ "/v",
8087
+ "ProgId"
8088
+ ]);
8089
+ const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
8090
+ if (!match) {
8091
+ throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
8092
+ }
8093
+ const { id } = match.groups;
8094
+ const dotIndex = id.lastIndexOf(".");
8095
+ const hyphenIndex = id.lastIndexOf("-");
8096
+ const baseIdByDot = dotIndex === -1 ? undefined : id.slice(0, dotIndex);
8097
+ const baseIdByHyphen = hyphenIndex === -1 ? undefined : id.slice(0, hyphenIndex);
8098
+ return windowsBrowserProgIds[id] ?? windowsBrowserProgIds[baseIdByDot] ?? windowsBrowserProgIds[baseIdByHyphen] ?? { name: id, id };
8099
+ }
8100
+
8101
+ // node_modules/.bun/default-browser@5.5.1/node_modules/default-browser/index.js
8102
+ var execFileAsync4 = promisify6(execFile6);
8103
+ var titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
8104
+ async function defaultBrowser2() {
8105
+ if (process7.platform === "darwin") {
8106
+ const id = await defaultBrowserId();
8107
+ const name = await bundleName(id);
8108
+ return { name, id };
8109
+ }
8110
+ if (process7.platform === "linux") {
8111
+ const { stdout } = await execFileAsync4("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
8112
+ const id = stdout.trim();
8113
+ const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
8114
+ return { name, id };
8115
+ }
8116
+ if (process7.platform === "win32") {
8117
+ return defaultBrowser();
8118
+ }
8119
+ throw new Error("Only macOS, Linux, and Windows are supported");
8120
+ }
8121
+
8122
+ // node_modules/.bun/is-in-ssh@1.0.0/node_modules/is-in-ssh/index.js
8123
+ import process8 from "process";
8124
+ var isInSsh = Boolean(process8.env.SSH_CONNECTION || process8.env.SSH_CLIENT || process8.env.SSH_TTY);
8125
+ var is_in_ssh_default = isInSsh;
8126
+
8127
+ // node_modules/.bun/open@11.0.4/node_modules/open/index.js
8128
+ var fallbackAttemptSymbol = Symbol("fallbackAttempt");
8129
+ var __dirname2 = import.meta.url ? path2.dirname(fileURLToPath(import.meta.url)) : "";
8130
+ var localXdgOpenPath = path2.join(__dirname2, "xdg-open");
8131
+ var { platform, arch } = process9;
8132
+ var tryEachApp = async (apps, opener) => {
8133
+ if (apps.length === 0) {
8134
+ return;
8135
+ }
8136
+ const errors = [];
8137
+ for (const app of apps) {
8138
+ try {
8139
+ return await opener(app);
8140
+ } catch (error) {
8141
+ errors.push(error);
8142
+ }
8143
+ }
8144
+ throw new AggregateError(errors, "Failed to open in all supported apps");
8145
+ };
8146
+ var baseOpen = async (options) => {
8147
+ options = {
8148
+ wait: false,
8149
+ background: false,
8150
+ newInstance: false,
8151
+ allowNonzeroExitCode: false,
8152
+ ...options
8153
+ };
8154
+ const isFallbackAttempt = options[fallbackAttemptSymbol] === true;
8155
+ delete options[fallbackAttemptSymbol];
8156
+ if (Array.isArray(options.app)) {
8157
+ return tryEachApp(options.app, (singleApp) => baseOpen({
8158
+ ...options,
8159
+ app: singleApp,
8160
+ [fallbackAttemptSymbol]: true
8161
+ }));
8162
+ }
8163
+ let { name: app, arguments: appArguments = [] } = options.app ?? {};
8164
+ appArguments = [...appArguments];
8165
+ if (Array.isArray(app)) {
8166
+ return tryEachApp(app, (appName) => baseOpen({
8167
+ ...options,
8168
+ app: {
8169
+ name: appName,
8170
+ arguments: appArguments
8171
+ },
8172
+ [fallbackAttemptSymbol]: true
8173
+ }));
8174
+ }
8175
+ if (app === "browser" || app === "browserPrivate") {
8176
+ const ids = {
8177
+ "com.google.chrome": "chrome",
8178
+ "google-chrome.desktop": "chrome",
8179
+ "com.brave.browser": "brave",
8180
+ "org.mozilla.firefox": "firefox",
8181
+ "firefox.desktop": "firefox",
8182
+ "com.microsoft.msedge": "edge",
8183
+ "com.microsoft.edge": "edge",
8184
+ "com.microsoft.edgemac": "edge",
8185
+ "microsoft-edge.desktop": "edge",
8186
+ "com.apple.safari": "safari"
8187
+ };
8188
+ const flags = {
8189
+ chrome: "--incognito",
8190
+ brave: "--incognito",
8191
+ firefox: "--private-window",
8192
+ edge: "--inPrivate"
8193
+ };
8194
+ let browser;
8195
+ if (is_wsl_default) {
8196
+ const progId = await wslDefaultBrowser();
8197
+ const browserInfo = _windowsBrowserProgIdMap.get(progId);
8198
+ browser = browserInfo ?? {};
8199
+ } else {
8200
+ browser = await defaultBrowser2();
8201
+ }
8202
+ const browserId = browser.id?.toLowerCase();
8203
+ if (Object.hasOwn(ids, browserId)) {
8204
+ const browserName = ids[browserId];
8205
+ if (app === "browserPrivate") {
8206
+ if (browserName === "safari") {
8207
+ throw new Error("Safari doesn't support opening in private mode via command line");
8208
+ }
8209
+ appArguments.push(flags[browserName]);
8210
+ }
8211
+ return baseOpen({
8212
+ ...options,
8213
+ app: {
8214
+ name: apps[browserName],
8215
+ arguments: appArguments
8216
+ }
8217
+ });
8218
+ }
8219
+ throw new Error(`${browser.name} is not supported as a default browser`);
8220
+ }
8221
+ let command;
8222
+ const cliArguments = [];
8223
+ const childProcessOptions = {};
8224
+ let shouldUseWindowsInWsl = false;
8225
+ if (is_wsl_default && !isInsideContainer() && !is_in_ssh_default && !app) {
8226
+ shouldUseWindowsInWsl = await canAccessPowerShell();
8227
+ }
8228
+ if (platform === "darwin") {
8229
+ command = "open";
8230
+ if (options.wait) {
8231
+ cliArguments.push("--wait-apps");
8232
+ }
8233
+ if (options.background) {
8234
+ cliArguments.push("--background");
8235
+ }
8236
+ if (options.newInstance) {
8237
+ cliArguments.push("--new");
8238
+ }
8239
+ if (app) {
8240
+ cliArguments.push("-a", app);
8241
+ }
8242
+ } else if (platform === "win32" || shouldUseWindowsInWsl) {
8243
+ command = await powerShellPath2();
8244
+ cliArguments.push(...executePowerShell.argumentsPrefix);
8245
+ if (!is_wsl_default) {
8246
+ childProcessOptions.windowsVerbatimArguments = true;
8247
+ }
8248
+ if (is_wsl_default && options.target) {
8249
+ options.target = await convertWslPathToWindows(options.target);
8250
+ }
8251
+ const encodedArguments = ["$ProgressPreference = 'SilentlyContinue';", "Start"];
8252
+ if (options.wait) {
8253
+ encodedArguments.push("-Wait");
8254
+ }
8255
+ if (app) {
8256
+ encodedArguments.push(executePowerShell.escapeArgument(app));
8257
+ if (options.target) {
8258
+ appArguments.push(options.target);
8259
+ }
8260
+ } else if (options.target) {
8261
+ encodedArguments.push(executePowerShell.escapeArgument(options.target));
8262
+ }
8263
+ if (appArguments.length > 0) {
8264
+ appArguments = appArguments.map((argument) => executePowerShell.escapeArgument(argument));
8265
+ encodedArguments.push("-ArgumentList", appArguments.join(","));
8266
+ }
8267
+ options.target = executePowerShell.encodeCommand(encodedArguments.join(" "));
8268
+ if (!options.wait) {
8269
+ childProcessOptions.stdio = "ignore";
8270
+ }
8271
+ if (is_wsl_default) {
8272
+ childProcessOptions.cwd = path2.dirname(command);
8273
+ }
8274
+ } else {
8275
+ if (app) {
8276
+ command = app;
8277
+ } else {
8278
+ const isBundled = !__dirname2 || __dirname2 === "/";
8279
+ let exeLocalXdgOpen = false;
8280
+ try {
8281
+ await fs5.access(localXdgOpenPath, fsConstants2.X_OK);
8282
+ exeLocalXdgOpen = true;
8283
+ } catch {}
8284
+ const useSystemXdgOpen = process9.versions.electron ?? (platform === "android" || isBundled || !exeLocalXdgOpen);
8285
+ command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
8286
+ }
8287
+ if (appArguments.length > 0) {
8288
+ cliArguments.push(...appArguments);
8289
+ }
8290
+ if (!options.wait) {
8291
+ childProcessOptions.stdio = "ignore";
8292
+ childProcessOptions.detached = true;
8293
+ }
8294
+ }
8295
+ if (platform === "darwin" && appArguments.length > 0) {
8296
+ cliArguments.push("--args", ...appArguments);
8297
+ }
8298
+ if (options.target) {
8299
+ cliArguments.push(options.target);
8300
+ }
8301
+ const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
8302
+ if (options.wait) {
8303
+ return new Promise((resolve, reject) => {
8304
+ subprocess.once("error", reject);
8305
+ subprocess.once("close", (exitCode) => {
8306
+ if (!options.allowNonzeroExitCode && exitCode !== 0) {
8307
+ reject(new Error(`Exited with code ${exitCode}`));
8308
+ return;
8309
+ }
8310
+ resolve(subprocess);
8311
+ });
8312
+ });
8313
+ }
8314
+ if (isFallbackAttempt || platform === "win32" || shouldUseWindowsInWsl) {
8315
+ return new Promise((resolve, reject) => {
8316
+ subprocess.once("error", reject);
8317
+ subprocess.once("spawn", () => {
8318
+ subprocess.once("close", (exitCode) => {
8319
+ subprocess.off("error", reject);
8320
+ if (isFallbackAttempt && exitCode !== 0) {
8321
+ reject(new Error(`Exited with code ${exitCode}`));
8322
+ return;
8323
+ }
8324
+ subprocess.unref();
8325
+ resolve(subprocess);
8326
+ });
8327
+ });
8328
+ });
8329
+ }
8330
+ subprocess.unref();
8331
+ return new Promise((resolve, reject) => {
8332
+ subprocess.once("error", reject);
8333
+ subprocess.once("spawn", () => {
8334
+ subprocess.off("error", reject);
8335
+ resolve(subprocess);
8336
+ });
8337
+ });
8338
+ };
8339
+ var open2 = (target, options) => {
8340
+ if (typeof target !== "string") {
8341
+ throw new TypeError("Expected a `target`");
8342
+ }
8343
+ return baseOpen({
8344
+ ...options,
8345
+ target
8346
+ });
8347
+ };
8348
+ function detectArchBinary(binary) {
8349
+ if (typeof binary === "string" || Array.isArray(binary)) {
8350
+ return binary;
8351
+ }
8352
+ const { [arch]: archBinary } = binary;
8353
+ if (!archBinary) {
8354
+ throw new Error(`${arch} is not supported`);
8355
+ }
8356
+ return archBinary;
8357
+ }
8358
+ function detectPlatformBinary({ [platform]: platformBinary }, { wsl } = {}) {
8359
+ if (wsl && is_wsl_default) {
8360
+ return detectArchBinary(wsl);
8361
+ }
8362
+ if (!platformBinary) {
8363
+ throw new Error(`${platform} is not supported`);
8364
+ }
8365
+ return detectArchBinary(platformBinary);
8366
+ }
8367
+ var apps = {
8368
+ browser: "browser",
8369
+ browserPrivate: "browserPrivate"
8370
+ };
8371
+ defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
8372
+ darwin: "google chrome",
8373
+ win32: "chrome",
8374
+ linux: ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser"]
8375
+ }, {
8376
+ wsl: {
8377
+ ia32: "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
8378
+ x64: ["/mnt/c/Program Files/Google/Chrome/Application/chrome.exe", "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"]
8379
+ }
8380
+ }));
8381
+ defineLazyProperty(apps, "brave", () => detectPlatformBinary({
8382
+ darwin: "brave browser",
8383
+ win32: "brave",
8384
+ linux: ["brave-browser", "brave"]
8385
+ }, {
8386
+ wsl: {
8387
+ ia32: "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe",
8388
+ x64: ["/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe", "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe"]
8389
+ }
8390
+ }));
8391
+ defineLazyProperty(apps, "firefox", () => detectPlatformBinary({
8392
+ darwin: "firefox",
8393
+ win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
8394
+ linux: "firefox"
8395
+ }, {
8396
+ wsl: "/mnt/c/Program Files/Mozilla Firefox/firefox.exe"
8397
+ }));
8398
+ defineLazyProperty(apps, "edge", () => detectPlatformBinary({
8399
+ darwin: "microsoft edge",
8400
+ win32: "msedge",
8401
+ linux: ["microsoft-edge", "microsoft-edge-dev"]
8402
+ }, {
8403
+ wsl: "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
8404
+ }));
8405
+ defineLazyProperty(apps, "safari", () => detectPlatformBinary({
8406
+ darwin: "Safari"
8407
+ }));
8408
+ var open_default = open2;
8409
+
8410
+ // packages/agent/src/system/openBrowser.ts
8411
+ var openBrowser = (url) => open_default(url).catch(() => {
8412
+ return;
8413
+ });
8414
+
8415
+ // packages/agent/src/permissions/sanitizeText.ts
8416
+ var isControlCode = (code) => code < 32 || code >= 127 && code <= 159;
8417
+ var sanitizeText = (text) => [...String(text ?? "")].map((char) => isControlCode(char.charCodeAt(0)) ? " " : char).join("");
8418
+
8419
+ // packages/agent/src/permissions/elicitationForm.ts
8420
+ var SKIP_LABEL = "Skip";
8421
+ var ACCEPT_LABEL = "Accept";
8422
+ var DECLINE_LABEL = "Decline";
8423
+ var YES_LABEL = "Yes";
8424
+ var NO_LABEL = "No";
8425
+ var isSchema = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
8426
+ var readList = (value) => Array.isArray(value) ? value : [];
8427
+ var toChoice = (entry) => {
8428
+ if (typeof entry === "string")
8429
+ return { value: entry, label: sanitizeText(entry) };
8430
+ if (!isSchema(entry) || typeof entry.const !== "string")
8431
+ return;
8432
+ const label = typeof entry.title === "string" ? entry.title : entry.const;
8433
+ return { value: entry.const, label: sanitizeText(label) };
8434
+ };
8435
+ var readChoices = (field) => {
8436
+ const source = isSchema(field.items) ? field.items : field;
8437
+ const entries = [...readList(source.oneOf), ...readList(source.anyOf), ...readList(source.enum)];
8438
+ return entries.flatMap((entry) => toChoice(entry) ?? []);
8439
+ };
8440
+ var readKind = (field, choices) => {
8441
+ if (field.type === "array")
8442
+ return "multi";
8443
+ if (choices.length > 0)
8444
+ return "choice";
8445
+ if (field.type === "boolean")
8446
+ return "boolean";
8447
+ return field.type === "number" || field.type === "integer" ? "number" : "text";
8448
+ };
8449
+ var readOptions = (kind, choices) => {
8450
+ const labelled = (labels) => labels.map((label) => ({ label, description: "" }));
8451
+ if (kind === "boolean")
8452
+ return labelled([YES_LABEL, NO_LABEL]);
8453
+ return labelled(choices.length > 0 ? choices.map(({ label }) => label) : [SKIP_LABEL]);
8454
+ };
8455
+ var buildQuestionText = (key, field, message) => {
8456
+ const title = sanitizeText(typeof field.title === "string" ? field.title : key);
8457
+ const description = typeof field.description === "string" ? ` (${sanitizeText(field.description)})` : "";
8458
+ return `${message}${title}${description}`;
8459
+ };
8460
+ var buildConfirmForm = (header, message) => ({
8461
+ fields: [],
8462
+ questions: [
8463
+ {
8464
+ header,
8465
+ question: message,
8466
+ options: [
8467
+ { label: ACCEPT_LABEL, description: "" },
8468
+ { label: DECLINE_LABEL, description: "" }
8469
+ ]
8470
+ }
8471
+ ]
8472
+ });
8473
+ function buildElicitationForm(serverName, message, requestedSchema) {
8474
+ const header = sanitizeText(serverName);
8475
+ const properties = isSchema(requestedSchema?.properties) ? requestedSchema.properties : {};
8476
+ const entries = Object.entries(properties).filter((entry) => isSchema(entry[1]));
8477
+ if (entries.length === 0)
8478
+ return buildConfirmForm(header, sanitizeText(message));
8479
+ const fields = [];
8480
+ const questions = [];
8481
+ for (const [key, field] of entries) {
8482
+ const choices = readChoices(field);
8483
+ const kind = readKind(field, choices);
8484
+ const intro = fields.length === 0 ? `${sanitizeText(message)} \u2014 ` : "";
8485
+ const question = buildQuestionText(key, field, intro);
8486
+ fields.push({ key, question, kind, choices });
8487
+ questions.push({
8488
+ header,
8489
+ question,
8490
+ multiSelect: kind === "multi",
8491
+ options: readOptions(kind, choices)
8492
+ });
8493
+ }
8494
+ return { fields, questions };
8495
+ }
8496
+ var readChoiceValue = (choices, label) => choices.find((choice) => choice.label === label)?.value ?? label;
8497
+ var readFieldValue = ({ kind, choices }, answer) => {
8498
+ if (kind === "boolean")
8499
+ return answer === YES_LABEL;
8500
+ if (kind === "number")
8501
+ return Number.isFinite(Number(answer)) ? Number(answer) : undefined;
8502
+ if (kind === "choice")
8503
+ return readChoiceValue(choices, answer);
8504
+ if (kind === "multi")
8505
+ return answer.split(", ").map((label) => readChoiceValue(choices, label));
8506
+ return answer;
8507
+ };
8508
+ function buildElicitationContent(form, answers) {
8509
+ const content = {};
8510
+ for (const field of form.fields) {
8511
+ const answer = answers[field.question]?.trim();
8512
+ if (!answer || answer === SKIP_LABEL)
8513
+ continue;
8514
+ const value = readFieldValue(field, answer);
8515
+ if (value !== undefined)
8516
+ content[field.key] = value;
8517
+ }
8518
+ return content;
8519
+ }
8520
+ var isConfirmAccepted = (form, answers) => form.fields.length > 0 || Object.values(answers).includes(ACCEPT_LABEL);
8521
+
8522
+ // packages/agent/src/permissions/elicitationGate.ts
8523
+ var ELICITATION_PREFIX = "elicitation:";
8524
+ var OPEN_BROWSER_LABEL = "Open in browser";
8525
+ var DECLINED = { action: "decline" };
8526
+ var isWebUrl = (url) => {
8527
+ try {
8528
+ return url !== undefined && /^https?:$/.test(new URL(url).protocol);
8529
+ } catch {
8530
+ return false;
8531
+ }
8532
+ };
8533
+ var buildUrlQuestion = ({ serverName, message, url }) => ({
8534
+ header: sanitizeText(serverName),
8535
+ question: `${sanitizeText(message)} ${sanitizeText(url)}`,
8536
+ options: [
8537
+ { label: OPEN_BROWSER_LABEL, description: "" },
8538
+ { label: "Decline", description: "" }
8539
+ ]
8540
+ });
8541
+
8542
+ class ElicitationGate {
8543
+ agentSessionId;
8544
+ openUrl;
8545
+ pending = new Map;
8546
+ emit = () => {};
8547
+ constructor(agentSessionId, openUrl = openBrowser) {
8548
+ this.agentSessionId = agentSessionId;
8549
+ this.openUrl = openUrl;
8550
+ }
8551
+ listen(emit) {
8552
+ this.emit = emit;
8553
+ }
8554
+ handle = async (request, { signal, requestId }) => {
8555
+ if (request.mode === "url") {
8556
+ if (!isWebUrl(request.url))
8557
+ return DECLINED;
8558
+ return this.open(requestId, signal, [buildUrlQuestion(request)], (answers) => this.acceptUrl(request.url, answers));
8559
+ }
8560
+ const form = buildElicitationForm(request.serverName, request.message, request.requestedSchema);
8561
+ return this.open(requestId, signal, form.questions, (answers) => this.acceptForm(form, answers));
8562
+ };
8563
+ answer(toolUseId, answers) {
8564
+ const pending = this.pending.get(toolUseId);
8565
+ if (!pending)
8566
+ return false;
8567
+ this.pending.delete(toolUseId);
8568
+ const answered = Object.keys(answers).length > 0;
8569
+ pending.settle(answered ? pending.accept(answers) : DECLINED);
8570
+ this.emit({ type: "agent.question.resolved", toolUseId, answered });
8571
+ return true;
8572
+ }
8573
+ rejectAll() {
8574
+ for (const id of [...this.pending.keys()])
8575
+ this.answer(id, {});
8576
+ }
8577
+ acceptUrl(url, answers) {
8578
+ if (!Object.values(answers).includes(OPEN_BROWSER_LABEL))
8579
+ return DECLINED;
8580
+ this.openUrl(url);
8581
+ return { action: "accept" };
8582
+ }
8583
+ acceptForm(form, answers) {
8584
+ if (!isConfirmAccepted(form, answers))
8585
+ return DECLINED;
8586
+ return { action: "accept", content: buildElicitationContent(form, answers) };
8587
+ }
8588
+ open(requestId, signal, questions, accept) {
8589
+ const toolUseId = `${ELICITATION_PREFIX}${requestId}`;
8590
+ return new Promise((settle) => {
8591
+ this.pending.set(toolUseId, { settle, accept });
8592
+ signal.addEventListener("abort", () => this.answer(toolUseId, {}), { once: true });
8593
+ this.emit({
8594
+ type: "agent.question.required",
8595
+ agentSessionId: this.agentSessionId,
8596
+ toolUseId,
8597
+ questions
8598
+ });
8599
+ });
8600
+ }
8601
+ }
7687
8602
 
7688
8603
  // packages/agent/src/permissions/permissionResults.ts
7689
8604
  var allowTool = (input) => ({
@@ -7800,7 +8715,87 @@ var ADHD_SYSTEM_PROMPT = `For the rest of this session, shape every response for
7800
8715
 
7801
8716
  Break these rules only when: the reader asks you to "explain" or "walk through" (go as long as the topic needs, still no preamble/closer); a destructive action is ahead (confirm first; safety beats brevity); you are in a debug spiral (name the assumption that might be wrong, ask one diagnostic question); or the request is genuinely ambiguous (ask one short clarifying question); or the harness's own system prompt requires something these rules ban (the harness wins; keep the shape).`;
7802
8717
 
7803
- // packages/agent/src/profile/agentProfile.ts
8718
+ // packages/agent/src/profile/codeReviewPrompt.ts
8719
+ var CODE_REVIEW_DESCRIPTION = "Reviews code changes since a commit, branch, or tag, or the uncommitted work, against the repo's coding standards and the originating spec. Use it to review a branch, a PR, or work in progress.";
8720
+ var CODE_REVIEW_PROMPT = `You are CodeReview. You review a diff along two separate axes and report them side by side. You are read-only: never edit files.
8721
+
8722
+ - Standards: does the code follow this repo's documented coding standards?
8723
+ - Spec: does the code match what the originating issue or spec asked for?
8724
+
8725
+ A change can pass one axis and fail the other. Never merge or rerank the two.
8726
+
8727
+ ## 1. Pin the fixed point
8728
+
8729
+ Use the commit, branch, tag, or ref you were given. If none was given, review the uncommitted work with \`git diff HEAD\`.
8730
+ Verify the ref with \`git rev-parse <ref>\` and capture the diff once with \`git diff <ref>...HEAD\`, plus \`git log <ref>..HEAD --oneline\`. If the ref is bad or the diff is empty, say so and stop.
8731
+
8732
+ ## 2. Find the spec
8733
+
8734
+ Look in this order:
8735
+ 1. Issue references in commit messages (#123, Closes #45).
8736
+ 2. A path you were given.
8737
+ 3. A spec or issue file under docs/, specs/, or .scratch/ matching the branch name or feature.
8738
+ If there is none, skip the Spec axis and say "no spec available".
8739
+
8740
+ ## 3. Find the standards
8741
+
8742
+ Collect every file that documents how code should be written: CLAUDE.md, CODING_STANDARDS.md, CONTRIBUTING.md, and similar. A documented repo standard always wins over the smell baseline.
8743
+
8744
+ Smell baseline, always a judgement call, never a hard violation (name it "possible <smell>"). Skip anything tooling already enforces.
8745
+ - Mysterious Name: a name that does not reveal what it does or holds.
8746
+ - Duplicated Code: the same logic shape in more than one hunk or file.
8747
+ - Feature Envy: a method that uses another object's data more than its own.
8748
+ - Data Clumps: the same few fields or params always travel together.
8749
+ - Primitive Obsession: a primitive standing in for a domain concept.
8750
+ - Repeated Switches: the same switch or if-cascade on one type recurs.
8751
+ - Shotgun Surgery: one logical change forces scattered edits across many files.
8752
+ - Divergent Change: one file is edited for several unrelated reasons.
8753
+ - Speculative Generality: abstraction or hooks for needs the spec does not have.
8754
+ - Message Chains: long a.b().c().d() navigation callers should not depend on.
8755
+ - Middle Man: a class or function that mostly delegates onward.
8756
+ - Refused Bequest: a subclass that ignores or overrides most of what it inherits.
8757
+
8758
+ ## 4. Report
8759
+
8760
+ Under \`## Standards\`: every place the diff breaks a documented standard (cite the file and rule), then any baseline smell (name it, quote the hunk). Separate hard violations from judgement calls.
8761
+ Under \`## Spec\`: requirements that are missing or partial, behaviour that was not asked for, and requirements that look implemented but wrong. Quote the spec line for each.
8762
+
8763
+ Every finding names its file path and line range as <path>:<from>:<to>. Keep each axis under 400 words.
8764
+ End with one line: findings per axis and the worst issue within each axis. Do not pick a winner across axes.`;
8765
+
8766
+ // packages/agent/src/profile/scoutPrompt.ts
8767
+ var SCOUT_DESCRIPTION = "Scans the codebase for specific information and returns concise, useful findings with file paths and line ranges. Use it before reading or searching many files yourself.";
8768
+ var SCOUT_PROMPT = `You are Scout. You scan the codebase to answer one exploration request. You are read-only: never edit, write, or run state-changing commands.
8769
+
8770
+ 1. Use Glob to find files, Grep to find content, Read to confirm. Read only the lines you need.
8771
+ 2. Answer the request directly. Report only what the request needs.
8772
+ 3. Every finding names its file path and line range as <path>:<from>:<to>, for example src/auth/login.ts:42:58. A single line is <path>:<line>:<line>.
8773
+ 4. Keep it concise: one line per finding, the most relevant first, at most 10 findings.
8774
+ 5. If nothing matches, say so and list what you searched.`;
8775
+
8776
+ // packages/agent/src/profile/subagents.ts
8777
+ var AGENT_SUBAGENTS = {
8778
+ Scout: {
8779
+ description: SCOUT_DESCRIPTION,
8780
+ prompt: SCOUT_PROMPT,
8781
+ tools: ["Glob", "Grep", "Read"],
8782
+ model: "haiku",
8783
+ effort: "medium"
8784
+ },
8785
+ CodeReview: {
8786
+ description: CODE_REVIEW_DESCRIPTION,
8787
+ prompt: CODE_REVIEW_PROMPT,
8788
+ tools: ["Bash", "Glob", "Grep", "Read"],
8789
+ model: "sonnet",
8790
+ effort: "medium"
8791
+ }
8792
+ };
8793
+ var SUBAGENT_GUIDANCE = `Prefer subagents over doing the work yourself. Use *Agent* with:
8794
+ - Scout: to scan the codebase for specific information. It returns file paths and line ranges (<path>:<from>:<to>). Use it before you search or read many files.
8795
+ - CodeReview: to review code changes against the repo's standards and spec.
8796
+ Run independent subagents in parallel.`;
8797
+
8798
+ // packages/agent/src/profile/agentTools.ts
7804
8799
  var AGENT_TOOLS = [
7805
8800
  "Bash",
7806
8801
  "Read",
@@ -7821,9 +8816,48 @@ var AGENT_TOOLS = [
7821
8816
  "Edit",
7822
8817
  "NotebookEdit"
7823
8818
  ];
8819
+ var AGENT_DISALLOWED_TOOLS = [
8820
+ "Agent(Explore)",
8821
+ "Agent(Plan)",
8822
+ "Agent(statusline-setup)"
8823
+ ];
8824
+
8825
+ // packages/agent/src/profile/toolGuidance.ts
8826
+ var TOOL_USAGE = {
8827
+ Bash: "run shell commands; never to read, search, or edit files",
8828
+ Read: "read files",
8829
+ Grep: "search file contents",
8830
+ Glob: "scan files by name pattern",
8831
+ WebSearch: "search the web",
8832
+ WebFetch: "fetch a URL",
8833
+ TaskStop: "stop a running background task",
8834
+ Agent: "delegate work to a subagent",
8835
+ TaskCreate: "create a task",
8836
+ TaskGet: "read one task",
8837
+ TaskList: "list tasks",
8838
+ TaskOutput: "read a background task's output",
8839
+ TaskUpdate: "update a task",
8840
+ TodoWrite: "track the steps of multi-step work",
8841
+ AskUserQuestion: "ask the user",
8842
+ Write: "create new files with content",
8843
+ Edit: "update files",
8844
+ NotebookEdit: "update notebook cells"
8845
+ };
8846
+ var TOOL_GUIDANCE = `Always use the dedicated tool, never a workaround:
8847
+ ${AGENT_TOOLS.map((tool) => `- Use *${tool}* to ${TOOL_USAGE[tool]}`).join(`
8848
+ `)}`;
8849
+
8850
+ // packages/agent/src/profile/agentSystemPrompt.ts
8851
+ var AGENT_SYSTEM_PROMPT = [ADHD_SYSTEM_PROMPT, TOOL_GUIDANCE, SUBAGENT_GUIDANCE].join(`
8852
+
8853
+ `);
8854
+
8855
+ // packages/agent/src/profile/agentProfile.ts
7824
8856
  var AGENT_PROFILE_OPTIONS = {
7825
8857
  tools: AGENT_TOOLS,
7826
- systemPrompt: ADHD_SYSTEM_PROMPT,
8858
+ disallowedTools: AGENT_DISALLOWED_TOOLS,
8859
+ systemPrompt: AGENT_SYSTEM_PROMPT,
8860
+ agents: AGENT_SUBAGENTS,
7827
8861
  enableFileCheckpointing: true,
7828
8862
  extraArgs: { "replay-user-messages": null },
7829
8863
  permissionMode: DEFAULT_PERMISSION_MODE,
@@ -7855,19 +8889,6 @@ var AGENT_PROFILE_OPTIONS = {
7855
8889
  includeHookEvents: true
7856
8890
  };
7857
8891
 
7858
- // packages/agent/src/runtime/buildUserMessage.ts
7859
- var isSlashCommand = (content) => readPromptText(content).trimStart().startsWith("/");
7860
- var buildUserMessage = (content, priority) => ({
7861
- type: "user",
7862
- message: { role: "user", content },
7863
- parent_tool_use_id: null,
7864
- priority,
7865
- client_composed: isSlashCommand(content) ? undefined : true
7866
- });
7867
-
7868
- // packages/agent/src/session/pickNextModel.ts
7869
- var pickNextModel = (models, current) => models[(models.findIndex((model) => model.value === current) + 1) % models.length]?.value;
7870
-
7871
8892
  // packages/agent/src/session/agentSession.ts
7872
8893
  function requireRewind(result) {
7873
8894
  if (!result.canRewind)
@@ -7879,18 +8900,21 @@ class AgentSession {
7879
8900
  baseOptions;
7880
8901
  input = pushable({ objectMode: true });
7881
8902
  gate;
8903
+ elicitations;
7882
8904
  query;
7883
8905
  pendingTurns = 0;
7884
8906
  pumping = false;
7885
8907
  constructor(agentSessionId, baseOptions, runtime) {
7886
8908
  this.baseOptions = baseOptions;
7887
8909
  this.gate = new PermissionGate(agentSessionId);
8910
+ this.elicitations = new ElicitationGate(agentSessionId);
7888
8911
  this.query = runtime.open({
7889
8912
  prompt: this.input,
7890
8913
  options: {
7891
8914
  ...baseOptions,
7892
8915
  ...AGENT_PROFILE_OPTIONS,
7893
- canUseTool: this.gate.canUseTool
8916
+ canUseTool: this.gate.canUseTool,
8917
+ onElicitation: this.elicitations.handle
7894
8918
  }
7895
8919
  });
7896
8920
  }
@@ -7907,35 +8931,30 @@ class AgentSession {
7907
8931
  return;
7908
8932
  this.pumping = true;
7909
8933
  const sink = pushable({ objectMode: true });
7910
- this.gate.listen((event) => sink.push(event));
8934
+ this.listenGates((event) => sink.push(event));
7911
8935
  this.pumpMessages(sink);
7912
8936
  try {
7913
8937
  yield* sink;
7914
8938
  } finally {
7915
8939
  this.pumping = false;
7916
- this.gate.listen(() => {});
8940
+ this.listenGates(() => {});
7917
8941
  }
7918
8942
  }
7919
8943
  answerApproval(toolUseId, decision) {
7920
8944
  this.gate.answerApproval(toolUseId, decision);
7921
8945
  }
7922
8946
  answerQuestion(toolUseId, answers) {
7923
- this.gate.answerQuestion(toolUseId, answers);
8947
+ if (!this.elicitations.answer(toolUseId, answers))
8948
+ this.gate.answerQuestion(toolUseId, answers);
7924
8949
  }
7925
8950
  async cancel() {
7926
- this.gate.rejectAll();
8951
+ this.rejectAllPrompts();
7927
8952
  await this.query.interrupt();
7928
8953
  }
7929
8954
  async setModel(model) {
7930
8955
  await this.query.setModel(model);
7931
8956
  this.baseOptions = { ...this.baseOptions, model };
7932
8957
  }
7933
- async cycleModel() {
7934
- const next = pickNextModel(await this.fetchModels(), this.baseOptions.model);
7935
- if (next)
7936
- await this.setModel(next);
7937
- return next;
7938
- }
7939
8958
  setPermissionMode(mode) {
7940
8959
  return this.query.setPermissionMode(mode);
7941
8960
  }
@@ -7945,6 +8964,27 @@ class AgentSession {
7945
8964
  fetchMcpStatus() {
7946
8965
  return this.query.mcpServerStatus();
7947
8966
  }
8967
+ async startMcpLogin(serverName) {
8968
+ if (typeof this.query.mcpAuthenticate !== "function") {
8969
+ throw new Error("This Claude Agent SDK version does not support MCP login");
8970
+ }
8971
+ const { authUrl } = await this.query.mcpAuthenticate(serverName);
8972
+ if (!authUrl)
8973
+ throw new Error(`MCP server ${serverName} did not offer a login`);
8974
+ if (!/^https?:$/.test(new URL(authUrl).protocol)) {
8975
+ throw new Error(`MCP server ${serverName} offered an unsafe login link`);
8976
+ }
8977
+ return authUrl;
8978
+ }
8979
+ async submitMcpCallback(serverName, callbackUrl) {
8980
+ if (!/^https?:$/.test(new URL(callbackUrl).protocol)) {
8981
+ throw new Error("The callback must be an http(s) link");
8982
+ }
8983
+ await this.query.mcpSubmitOAuthCallbackUrl(serverName, callbackUrl);
8984
+ }
8985
+ awaitMcpLogin(serverName, wait) {
8986
+ return waitForMcpLogin(() => this.fetchMcpStatus(), serverName, wait);
8987
+ }
7948
8988
  fetchModels() {
7949
8989
  return this.query.supportedModels();
7950
8990
  }
@@ -7962,10 +9002,18 @@ class AgentSession {
7962
9002
  });
7963
9003
  }
7964
9004
  close() {
7965
- this.gate.rejectAll();
9005
+ this.rejectAllPrompts();
7966
9006
  this.input.end();
7967
9007
  this.query.close();
7968
9008
  }
9009
+ listenGates(emit) {
9010
+ this.gate.listen(emit);
9011
+ this.elicitations.listen(emit);
9012
+ }
9013
+ rejectAllPrompts() {
9014
+ this.gate.rejectAll();
9015
+ this.elicitations.rejectAll();
9016
+ }
7969
9017
  async pumpMessages(sink) {
7970
9018
  try {
7971
9019
  while (true) {
@@ -8038,13 +9086,13 @@ class AgentSessionManager {
8038
9086
  import { homedir } from "os";
8039
9087
  import { join as join2 } from "path";
8040
9088
  var OPTIONS_PATH = join2(homedir(), ".claudin", "options.json");
8041
- async function readOptions(path) {
9089
+ async function readOptions2(path) {
8042
9090
  const stored = await Bun.file(path).json().catch(() => ({}));
8043
9091
  const parsed = optionsFileSchema.safeParse(stored);
8044
9092
  return parsed.success ? parsed.data : {};
8045
9093
  }
8046
9094
  async function saveBackground(path, background) {
8047
- await Bun.write(path, JSON.stringify({ ...await readOptions(path), background }, null, 2));
9095
+ await Bun.write(path, JSON.stringify({ ...await readOptions2(path), background }, null, 2));
8048
9096
  }
8049
9097
 
8050
9098
  // packages/daemon/src/workspace/resolvePath.ts
@@ -8264,11 +9312,6 @@ var agentHandlers = {
8264
9312
  await agents.requireSession(request.agentSessionId).setModel(request.model);
8265
9313
  yield { type: "agent.model.changed", model: request.model };
8266
9314
  },
8267
- async* "agent.model.cycle.requested"({ agents }, request) {
8268
- const model = await agents.requireSession(request.agentSessionId).cycleModel();
8269
- if (model)
8270
- yield { type: "agent.model.changed", model };
8271
- },
8272
9315
  async* "agent.effort.set.requested"({ agents }, request) {
8273
9316
  await agents.requireSession(request.agentSessionId).setEffort(request.effort);
8274
9317
  yield { type: "agent.effort.changed", effort: request.effort };
@@ -8289,6 +9332,22 @@ var agentHandlers = {
8289
9332
  const servers = await agents.requireSession(request.agentSessionId).fetchMcpStatus();
8290
9333
  yield { type: "agent.mcp.status.received", servers };
8291
9334
  },
9335
+ async* "agent.mcp.login.requested"({ agents }, request) {
9336
+ const { serverName } = request;
9337
+ const session = agents.requireSession(request.agentSessionId);
9338
+ const authUrl = await session.startMcpLogin(serverName);
9339
+ yield { type: "agent.mcp.login.started", serverName, authUrl };
9340
+ await openBrowser(authUrl);
9341
+ const servers = await session.awaitMcpLogin(serverName);
9342
+ yield { type: "agent.mcp.status.received", servers };
9343
+ },
9344
+ async* "agent.mcp.callback.submitted"({ agents }, request) {
9345
+ const { serverName, callbackUrl } = request;
9346
+ const session = agents.requireSession(request.agentSessionId);
9347
+ await session.submitMcpCallback(serverName, callbackUrl);
9348
+ const servers = await session.awaitMcpLogin(serverName, { intervalMs: 500, timeoutMs: 1e4 });
9349
+ yield { type: "agent.mcp.status.received", servers };
9350
+ },
8292
9351
  async* "agent.usage.requested"({ agents }, request) {
8293
9352
  const { session } = await agents.requireSession(request.agentSessionId).fetchUsage();
8294
9353
  yield { type: "agent.usage.received", usage: session };
@@ -8319,7 +9378,7 @@ var agentHandlers = {
8319
9378
  // packages/daemon/src/handlers/optionsHandlers.ts
8320
9379
  var optionsHandlers = {
8321
9380
  async* "options.load.requested"({ optionsPath }) {
8322
- const { background } = await readOptions(optionsPath);
9381
+ const { background } = await readOptions2(optionsPath);
8323
9382
  yield { type: "options.loaded", background };
8324
9383
  },
8325
9384
  async* "options.background.save.requested"({ optionsPath }, request) {
@@ -8360,16 +9419,17 @@ var sessionHandlers = {
8360
9419
  };
8361
9420
 
8362
9421
  // packages/daemon/src/workspace/readFileDiffs.ts
8363
- import { relative } from "path";
9422
+ import { relative, resolve as resolve2 } from "path";
8364
9423
  var isTracked = async (cwd, path) => (await Bun.$`git ls-files --error-unmatch -- ${path}`.cwd(cwd).quiet().nothrow()).exitCode === 0;
8365
9424
  async function readPatch(cwd, path) {
8366
9425
  const command = await isTracked(cwd, path) ? Bun.$`git diff --no-color HEAD -- ${path}` : Bun.$`git diff --no-color --no-index -- /dev/null ${path}`;
8367
9426
  return (await command.cwd(cwd).quiet().nothrow()).text();
8368
9427
  }
8369
9428
  async function readFileDiff(cwd, path) {
8370
- const patch = await readPatch(cwd, path);
9429
+ const absolute = resolve2(cwd, path);
9430
+ const patch = await readPatch(cwd, absolute);
8371
9431
  return {
8372
- path: relative(cwd, path) || path,
9432
+ path: relative(cwd, absolute) || path,
8373
9433
  patch,
8374
9434
  additions: countPatchLines(patch, "+"),
8375
9435
  deletions: countPatchLines(patch, "-")
@@ -8380,6 +9440,17 @@ async function readFileDiffs(cwd, paths) {
8380
9440
  return diffs.filter(({ patch }) => patch.trim() !== "");
8381
9441
  }
8382
9442
 
9443
+ // packages/daemon/src/workspace/readGitChangedPaths.ts
9444
+ var readLines = async (cwd, command) => (await command.cwd(cwd).quiet().nothrow()).text().split(`
9445
+ `).filter(Boolean);
9446
+ async function readGitChangedPaths(cwd) {
9447
+ const [tracked, untracked] = await Promise.all([
9448
+ readLines(cwd, Bun.$`git diff --name-only --relative HEAD`),
9449
+ readLines(cwd, Bun.$`git ls-files --others --exclude-standard`)
9450
+ ]);
9451
+ return [...tracked, ...untracked];
9452
+ }
9453
+
8383
9454
  // node_modules/.bun/fuzzysort@4.0.2/node_modules/fuzzysort/fuzzysort.js
8384
9455
  function single(search, target) {
8385
9456
  if (!search || !target)
@@ -10007,7 +11078,9 @@ var workspaceHandlers = {
10007
11078
  yield { type: "workspace.cwd.changed", cwd, ...await readGitInfo(cwd) };
10008
11079
  },
10009
11080
  async* "workspace.diff.requested"({ cwd }, request) {
10010
- yield { type: "workspace.diff.received", files: await readFileDiffs(cwd, request.paths) };
11081
+ const changed = await readFileDiffs(cwd, await readGitChangedPaths(cwd));
11082
+ const files = changed.length > 0 ? changed : await readFileDiffs(cwd, request.paths);
11083
+ yield { type: "workspace.diff.received", files };
10011
11084
  }
10012
11085
  };
10013
11086
 
@@ -10060,7 +11133,11 @@ async function startDaemon(port = DEFAULT_PORT, context) {
10060
11133
  return server;
10061
11134
  }
10062
11135
  // apps/tui/src/startTui.ts
10063
- import { BoxRenderable as BoxRenderable15, createCliRenderer } from "@opentui/core";
11136
+ import {
11137
+ BoxRenderable as BoxRenderable16,
11138
+ createCliRenderer,
11139
+ createHostClipboard
11140
+ } from "@opentui/core";
10064
11141
 
10065
11142
  // apps/tui/src/components/backgroundPanel.ts
10066
11143
  import { BoxRenderable, StyledText, TextRenderable } from "@opentui/core";
@@ -17552,7 +18629,7 @@ var detectFiletype = (path) => FILETYPES[path.split(".").pop() ?? ""];
17552
18629
 
17553
18630
  // apps/tui/src/format/diffViewerChunks.ts
17554
18631
  import { bold as bold2, dim as dim2, fg as fg2 } from "@opentui/core";
17555
- var VIEWER_TITLE = "Session diffs";
18632
+ var VIEWER_TITLE = "Diffs";
17556
18633
  var VIEWER_HINT = "\u2190/\u2192 file \xB7 \u2191/\u2193 PgUp/PgDn scroll \xB7 Esc close";
17557
18634
  var buildFileChunks = (file, selected) => [
17558
18635
  selected ? bold2(fg2(Theme.fg.primary)(`\u276F ${file.path}`)) : fg2(Theme.fg.secondary)(file.path),
@@ -17802,7 +18879,9 @@ class ListPopover {
17802
18879
  // apps/tui/src/components/promptInput.ts
17803
18880
  import {
17804
18881
  BoxRenderable as BoxRenderable5,
18882
+ decodePasteBytes as decodePasteBytes2,
17805
18883
  SyntaxStyle,
18884
+ stripAnsiSequences,
17806
18885
  TextareaRenderable,
17807
18886
  TextRenderable as TextRenderable5
17808
18887
  } from "@opentui/core";
@@ -17989,6 +19068,10 @@ class PromptInput {
17989
19068
  event.preventDefault();
17990
19069
  this.textarea.insertText(placeholder);
17991
19070
  }
19071
+ insertPasted(content) {
19072
+ const placeholder = planPaste(content, this.attachments);
19073
+ this.textarea.insertText(placeholder ?? stripAnsiSequences(decodePasteBytes2(content.bytes)));
19074
+ }
17992
19075
  clear() {
17993
19076
  this.textarea.setText("");
17994
19077
  this.attachments.reset();
@@ -18823,6 +19906,7 @@ class ApprovalPanel {
18823
19906
  for (const { label, decision, color } of buildButtons()) {
18824
19907
  buttons.add(new TextRenderable9(renderer, {
18825
19908
  content: new StyledText8([bold4(fg9(color)(label))]),
19909
+ selectable: false,
18826
19910
  onMouseDown: () => onDecision(decision)
18827
19911
  }));
18828
19912
  }
@@ -18847,44 +19931,64 @@ import {
18847
19931
  var QUESTION_HINT = "\u2191/\u2193 select \xB7 Space toggle \xB7 Enter confirm \xB7 Esc dismiss";
18848
19932
  var CUSTOM_PLACEHOLDER = "type your own answer";
18849
19933
  var TEXT_CURSOR = "\u258F";
18850
- var buildRowChunks = (draft) => {
18851
- const current = readCurrentQuestion(draft);
18852
- if (!current)
18853
- return [];
18854
- const rows = [
18855
- ...current.options,
18856
- { label: OTHER_LABEL, description: "", custom: true }
19934
+ var buildRowChunks = (draft, multiSelect, { label, description, custom }, index) => {
19935
+ const focused = index === draft.cursor;
19936
+ const checked = custom ? draft.custom.trim() !== "" : draft.picks.includes(label);
19937
+ const marker = multiSelect ? checked ? QUESTION_GLYPHS.checked : QUESTION_GLYPHS.unchecked : "";
19938
+ const prefix = [focused ? QUESTION_GLYPHS.cursor : " ", marker].filter(Boolean).join(" ");
19939
+ const head = fg10(focused ? Theme.accent.brand : Theme.fg.primary)(`${prefix} ${label}`);
19940
+ if (!custom)
19941
+ return [head, fg10(Theme.fg.muted)(` ${description}`)];
19942
+ const typed = draft.custom ? [fg10(Theme.fg.primary)(draft.custom)] : focused ? [] : [fg10(Theme.fg.muted)(CUSTOM_PLACEHOLDER)];
19943
+ return [
19944
+ head,
19945
+ fg10(Theme.fg.muted)(": "),
19946
+ ...typed,
19947
+ ...focused ? [fg10(Theme.accent.brand)(TEXT_CURSOR)] : []
18857
19948
  ];
18858
- return rows.flatMap(({ label, description, custom }, index) => {
18859
- const focused = index === draft.cursor;
18860
- const checked = custom ? draft.custom.trim() !== "" : draft.picks.includes(label);
18861
- const marker = current.multiSelect ? checked ? QUESTION_GLYPHS.checked : QUESTION_GLYPHS.unchecked : "";
18862
- const prefix = [focused ? QUESTION_GLYPHS.cursor : " ", marker].filter(Boolean).join(" ");
18863
- const head = fg10(focused ? Theme.accent.brand : Theme.fg.primary)(`
18864
- ${prefix} ${label}`);
18865
- if (!custom)
18866
- return [head, fg10(Theme.fg.muted)(` ${description}`)];
18867
- const typed = draft.custom ? fg10(Theme.fg.primary)(draft.custom) : fg10(Theme.fg.muted)(CUSTOM_PLACEHOLDER);
18868
- return [
18869
- head,
18870
- fg10(Theme.fg.muted)(": "),
18871
- typed,
18872
- ...focused ? [fg10(Theme.accent.brand)(TEXT_CURSOR)] : []
18873
- ];
18874
- });
19949
+ };
19950
+ var listRows = (draft) => {
19951
+ const current = readCurrentQuestion(draft);
19952
+ return current ? [...current.options, { label: OTHER_LABEL, description: "", custom: true }] : [];
18875
19953
  };
18876
19954
 
18877
19955
  class QuestionPanel {
19956
+ renderer;
19957
+ onSelectRow;
18878
19958
  renderable;
18879
19959
  text;
18880
- constructor(renderer) {
19960
+ rows;
19961
+ hint;
19962
+ rowViews = [];
19963
+ constructor(renderer, onSelectRow) {
19964
+ this.renderer = renderer;
19965
+ this.onSelectRow = onSelectRow;
18881
19966
  this.renderable = new BoxRenderable9(renderer, {
18882
19967
  flexDirection: "column",
18883
19968
  marginTop: 1,
18884
19969
  flexShrink: 0
18885
19970
  });
18886
19971
  this.text = new TextRenderable10(renderer, { content: "" });
19972
+ this.rows = new BoxRenderable9(renderer, { flexDirection: "column" });
19973
+ this.hint = new TextRenderable10(renderer, {
19974
+ content: new StyledText9([dim4(fg10(Theme.fg.muted)(QUESTION_HINT))])
19975
+ });
18887
19976
  this.renderable.add(this.text);
19977
+ this.renderable.add(this.rows);
19978
+ this.renderable.add(this.hint);
19979
+ }
19980
+ readRowView(index) {
19981
+ const existing = this.rowViews[index];
19982
+ if (existing)
19983
+ return existing;
19984
+ const created = new TextRenderable10(this.renderer, {
19985
+ content: "",
19986
+ selectable: false,
19987
+ onMouseDown: () => this.onSelectRow(index)
19988
+ });
19989
+ this.rowViews.push(created);
19990
+ this.rows.add(created);
19991
+ return created;
18888
19992
  }
18889
19993
  update(draft) {
18890
19994
  const current = readCurrentQuestion(draft);
@@ -18893,11 +19997,17 @@ class QuestionPanel {
18893
19997
  const progress = draft.questions.length > 1 ? ` (${draft.index + 1}/${draft.questions.length})` : "";
18894
19998
  this.text.content = new StyledText9([
18895
19999
  bold5(fg10(Theme.status.warning)(`>>> ${current.header}${progress}: `)),
18896
- bold5(fg10(Theme.fg.primary)(current.question)),
18897
- ...buildRowChunks(draft),
18898
- dim4(fg10(Theme.fg.muted)(`
18899
- ${QUESTION_HINT}`))
20000
+ bold5(fg10(Theme.fg.primary)(current.question))
18900
20001
  ]);
20002
+ const rows = listRows(draft);
20003
+ rows.forEach((row, index) => {
20004
+ const view = this.readRowView(index);
20005
+ view.visible = true;
20006
+ view.content = new StyledText9(buildRowChunks(draft, current.multiSelect === true, row, index));
20007
+ });
20008
+ this.rowViews.slice(rows.length).forEach((view) => {
20009
+ view.visible = false;
20010
+ });
18901
20011
  }
18902
20012
  }
18903
20013
 
@@ -18935,15 +20045,25 @@ class ToolCallView {
18935
20045
  onMouseOver: () => this.setHovered(true),
18936
20046
  onMouseOut: () => this.setHovered(false)
18937
20047
  });
18938
- this.title = new TextRenderable11(renderer, { content: "", wrapMode: "none", flexShrink: 1 });
18939
- this.duration = new TextRenderable11(renderer, { content: "", flexShrink: 0, marginLeft: 2 });
20048
+ this.title = new TextRenderable11(renderer, {
20049
+ content: "",
20050
+ wrapMode: "none",
20051
+ flexShrink: 1,
20052
+ selectable: false
20053
+ });
20054
+ this.duration = new TextRenderable11(renderer, {
20055
+ content: "",
20056
+ flexShrink: 0,
20057
+ marginLeft: 2,
20058
+ selectable: false
20059
+ });
18940
20060
  header.add(this.title);
18941
20061
  header.add(this.duration);
18942
20062
  this.body = new BoxRenderable10(renderer, { flexDirection: "column", paddingLeft: 2 });
18943
20063
  this.command = new TextRenderable11(renderer, { content: "", fg: Theme.fg.secondary });
18944
20064
  this.output = new TextRenderable11(renderer, { content: "" });
18945
20065
  this.approval = new ApprovalPanel(renderer, (decision) => hooks.onDecision(decision, this.callId));
18946
- this.question = new QuestionPanel(renderer);
20066
+ this.question = new QuestionPanel(renderer, (index) => hooks.onSelectRow(index));
18947
20067
  this.body.add(this.command);
18948
20068
  this.body.add(this.output);
18949
20069
  this.renderable.add(header);
@@ -19213,8 +20333,8 @@ var buildWindowChunks = (label, window, now) => {
19213
20333
  };
19214
20334
  function buildRateLimitChunks(limits, now) {
19215
20335
  const windows = [
19216
- ["\u2784", limits.fiveHour],
19217
- ["\u277C", limits.sevenDay]
20336
+ ["\uD83E\uDFF5h", limits.fiveHour],
20337
+ ["\uD83E\uDFF7d", limits.sevenDay]
19218
20338
  ];
19219
20339
  return windows.flatMap(([label, window], index) => window ? [
19220
20340
  ...index > 0 ? [fg13(Theme.border.separator)(SEPARATOR)] : [],
@@ -19342,6 +20462,7 @@ class StatusLine {
19342
20462
  content: "",
19343
20463
  wrapMode: "none",
19344
20464
  flexShrink: 0,
20465
+ selectable: false,
19345
20466
  onMouseDown: onStop
19346
20467
  });
19347
20468
  this.renderable.add(this.label);
@@ -19369,6 +20490,44 @@ class StatusLine {
19369
20490
  }
19370
20491
  }
19371
20492
 
20493
+ // apps/tui/src/components/toastView.ts
20494
+ import { BoxRenderable as BoxRenderable15, fg as fg16, StyledText as StyledText14, TextRenderable as TextRenderable15 } from "@opentui/core";
20495
+ var TOAST_ICON = "\u25CF";
20496
+
20497
+ class ToastView {
20498
+ renderable;
20499
+ text;
20500
+ toastId;
20501
+ constructor(renderer) {
20502
+ this.renderable = new BoxRenderable15(renderer, {
20503
+ position: "absolute",
20504
+ top: 1,
20505
+ right: 2,
20506
+ zIndex: 100,
20507
+ paddingLeft: 1,
20508
+ paddingRight: 1,
20509
+ border: true,
20510
+ borderStyle: "rounded",
20511
+ visible: false
20512
+ });
20513
+ this.text = new TextRenderable15(renderer, { content: "", wrapMode: "none", selectable: false });
20514
+ this.renderable.add(this.text);
20515
+ }
20516
+ update({ ui }) {
20517
+ const { toast } = ui;
20518
+ this.renderable.visible = toast !== null;
20519
+ if (!toast || toast.id === this.toastId)
20520
+ return;
20521
+ this.toastId = toast.id;
20522
+ this.renderable.borderColor = Theme.border.focus;
20523
+ this.renderable.backgroundColor = Theme.bg.surface;
20524
+ this.text.content = new StyledText14([
20525
+ fg16(Theme.status.success)(`${TOAST_ICON} `),
20526
+ fg16(Theme.fg.primary)(toast.text)
20527
+ ]);
20528
+ }
20529
+ }
20530
+
19372
20531
  // apps/tui/src/input/agentBusy.ts
19373
20532
  var isStatusBusy = (status) => status !== "idle" && status !== "error";
19374
20533
  var isAgentBusy = (store) => isStatusBusy(store.state.status);
@@ -19410,13 +20569,10 @@ var WORKFLOW_COMMANDS = {
19410
20569
  store.emit({ type: "ui.rewind.picker.opened" });
19411
20570
  }
19412
20571
  },
19413
- "/view-diffs": {
19414
- description: "Review the diffs of files this session edited",
20572
+ "/diffs": {
20573
+ description: "Review git changes, or this session's edits when there are none",
19415
20574
  run(store) {
19416
- const paths = listEditedFiles(store.state);
19417
- if (paths.length === 0)
19418
- return postNotice(store, "This session has not edited any files");
19419
- store.request({ type: "workspace.diff.requested", paths });
20575
+ store.request({ type: "workspace.diff.requested", paths: listEditedFiles(store.state) });
19420
20576
  }
19421
20577
  },
19422
20578
  "/export": {
@@ -19436,13 +20592,30 @@ var WORKFLOW_COMMANDS = {
19436
20592
  };
19437
20593
 
19438
20594
  // apps/tui/src/input/localCommands.ts
19439
- function cycleModel(store) {
19440
- requestAgent(store, { type: "agent.model.cycle.requested" });
20595
+ function openModelPicker2(store) {
20596
+ requestAgent(store, { type: "agent.models.requested" });
19441
20597
  }
19442
20598
  var QUIT_COMMAND = {
19443
20599
  description: "Exit the app (also /exit, /q, /leave)",
19444
20600
  run: (store) => store.emit({ type: "ui.exit.requested" })
19445
20601
  };
20602
+ var MCP_USAGE = "Usage: /mcp | /mcp login <name> | /mcp callback <name> <url>";
20603
+ function runMcpCommand(store, argument) {
20604
+ const [action, serverName, callbackUrl] = argument.trim().split(/\s+/);
20605
+ if (!action)
20606
+ return void requestAgent(store, { type: "agent.mcp.status.requested" });
20607
+ if (action === "login" && serverName) {
20608
+ return void requestAgent(store, { type: "agent.mcp.login.requested", serverName });
20609
+ }
20610
+ if (action === "callback" && serverName && callbackUrl) {
20611
+ return void requestAgent(store, {
20612
+ type: "agent.mcp.callback.submitted",
20613
+ serverName,
20614
+ callbackUrl
20615
+ });
20616
+ }
20617
+ store.emit({ type: "ui.notice.posted", text: MCP_USAGE });
20618
+ }
19446
20619
  var SLASH_ALIASES = {
19447
20620
  "/exit": "/quit",
19448
20621
  "/q": "/quit",
@@ -19468,7 +20641,7 @@ var SLASH_COMMANDS = {
19468
20641
  run(store, model) {
19469
20642
  if (model)
19470
20643
  return void requestAgent(store, { type: "agent.model.set.requested", model });
19471
- requestAgent(store, { type: "agent.models.requested" });
20644
+ openModelPicker2(store);
19472
20645
  }
19473
20646
  },
19474
20647
  "/theme": {
@@ -19522,10 +20695,8 @@ var SLASH_COMMANDS = {
19522
20695
  }
19523
20696
  },
19524
20697
  "/mcp": {
19525
- description: "List MCP servers",
19526
- run(store) {
19527
- requestAgent(store, { type: "agent.mcp.status.requested" });
19528
- }
20698
+ description: "List MCP servers, sign in with /mcp login <name>, or /mcp callback <name> <url>",
20699
+ run: runMcpCommand
19529
20700
  },
19530
20701
  "/clear": {
19531
20702
  description: "Start a fresh session",
@@ -19719,6 +20890,46 @@ function routeAutocompleteKey(key, store, accept) {
19719
20890
  return true;
19720
20891
  }
19721
20892
 
20893
+ // apps/tui/src/prompt/clipboardPaste.ts
20894
+ var PREFERRED_TYPES = ["image/png", "text/plain"];
20895
+ async function readClipboardPaste(clipboard) {
20896
+ const result = await clipboard.read({ preferredTypes: PREFERRED_TYPES });
20897
+ if (result.status !== "read")
20898
+ return;
20899
+ const { mimeType, bytes } = result.representation;
20900
+ if (bytes.length === 0)
20901
+ return;
20902
+ return { bytes, metadata: { mimeType, kind: mimeType.startsWith("text/") ? "text" : "binary" } };
20903
+ }
20904
+
20905
+ // apps/tui/src/input/toastActions.ts
20906
+ var TOAST_DURATION_MS = 2500;
20907
+ function showToast(store, text) {
20908
+ const id = crypto.randomUUID();
20909
+ store.emit({ type: "ui.toast.posted", id, text });
20910
+ setTimeout(() => store.emit({ type: "ui.toast.dismissed", id }), TOAST_DURATION_MS).unref();
20911
+ }
20912
+
20913
+ // apps/tui/src/input/clipboardActions.ts
20914
+ var UNAVAILABLE_NOTICE = "Clipboard unavailable, use your terminal's paste shortcut";
20915
+ var COPIED_TOAST = "Copied to clipboard";
20916
+ var COPY_FAILED_TOAST = "Could not copy to clipboard";
20917
+ async function pasteFromClipboard(store, input, clipboard) {
20918
+ const content = await readClipboardPaste(clipboard);
20919
+ if (content)
20920
+ input.insertPasted(content);
20921
+ else
20922
+ showToast(store, UNAVAILABLE_NOTICE);
20923
+ }
20924
+ async function copySelection(store, renderer, clipboard, selection) {
20925
+ const text = selection.getSelectedText();
20926
+ if (!text)
20927
+ return;
20928
+ const written = (await clipboard.writeText(text)).status === "written";
20929
+ const copied = written || renderer.copyToClipboardOSC52(text);
20930
+ showToast(store, copied ? COPIED_TOAST : COPY_FAILED_TOAST);
20931
+ }
20932
+
19722
20933
  // apps/tui/src/input/slashCommands.ts
19723
20934
  var parseSlashLine = (line) => {
19724
20935
  const [name = "", ...rest] = line.trim().split(/\s+/);
@@ -19898,7 +21109,7 @@ var routeExit = (key, { store, presses, exit }) => {
19898
21109
  return true;
19899
21110
  }
19900
21111
  presses.ctrlCAt = pressedAt;
19901
- store.emit({ type: "ui.notice.posted", text: EXIT_NOTICE });
21112
+ showToast(store, EXIT_NOTICE);
19902
21113
  return true;
19903
21114
  };
19904
21115
  var routeDoubleEscape = (key, { store, presses }) => {
@@ -19926,10 +21137,11 @@ var QUESTION_ACTIONS = {
19926
21137
  return: confirmQuestion,
19927
21138
  escape: dismissQuestion
19928
21139
  };
21140
+ var DELETE_CHARACTER = "\x7F";
19929
21141
  var readTypedText = (key) => {
19930
21142
  if (key.ctrl || key.meta)
19931
21143
  return;
19932
- return key.sequence.length === 1 && key.sequence >= " " ? key.sequence : undefined;
21144
+ return key.sequence.length === 1 && key.sequence >= " " && key.sequence !== DELETE_CHARACTER ? key.sequence : undefined;
19933
21145
  };
19934
21146
  function typeCustomAnswer(key, store) {
19935
21147
  const { question } = store.state.ui;
@@ -20014,10 +21226,10 @@ var routePicker = (key, { store }) => {
20014
21226
  }
20015
21227
  return true;
20016
21228
  };
20017
- var routeModelCycle = (key, { store }) => {
21229
+ var routeModelPicker = (key, { store }) => {
20018
21230
  if (key.name !== "tab" || !key.shift)
20019
21231
  return false;
20020
- cycleModel(store);
21232
+ openModelPicker2(store);
20021
21233
  return true;
20022
21234
  };
20023
21235
  var routeDelivery = (key, { store, submitInput }) => {
@@ -20027,6 +21239,14 @@ var routeDelivery = (key, { store, submitInput }) => {
20027
21239
  submitInput(delivery);
20028
21240
  return true;
20029
21241
  };
21242
+ var routePaste = (key, { store, pasteClipboard }) => {
21243
+ if (key.name !== "v" || !(key.ctrl || key.super))
21244
+ return false;
21245
+ if (store.state.ui.focus !== "input")
21246
+ return false;
21247
+ pasteClipboard();
21248
+ return true;
21249
+ };
20030
21250
  var ROUTES = [
20031
21251
  routeExit,
20032
21252
  routeApproval,
@@ -20034,8 +21254,9 @@ var ROUTES = [
20034
21254
  routeDiffViewer,
20035
21255
  routeBackgroundEditor,
20036
21256
  routePicker,
20037
- routeModelCycle,
21257
+ routeModelPicker,
20038
21258
  routeDelivery,
21259
+ routePaste,
20039
21260
  routeHistorySearch,
20040
21261
  routeCompletion,
20041
21262
  routeDoubleEscape,
@@ -20179,6 +21400,7 @@ class AppStore {
20179
21400
  machine = new EventMachine(createSessionState(""), reduceTimedEvent);
20180
21401
  peerEvents = new WeakSet;
20181
21402
  stopListening;
21403
+ closed = false;
20182
21404
  constructor(client) {
20183
21405
  this.client = client;
20184
21406
  this.stopListening = client.subscribe((event, peer) => this.receive(event, peer));
@@ -20196,7 +21418,8 @@ class AppStore {
20196
21418
  this.client.send(event);
20197
21419
  }
20198
21420
  emit(event) {
20199
- this.machine.send(event);
21421
+ if (!this.closed)
21422
+ this.machine.send(event);
20200
21423
  }
20201
21424
  subscribe(listener) {
20202
21425
  return this.machine.subscribe(() => listener(this.machine.state));
@@ -20208,6 +21431,7 @@ class AppStore {
20208
21431
  });
20209
21432
  }
20210
21433
  close() {
21434
+ this.closed = true;
20211
21435
  this.stopListening();
20212
21436
  this.client.close();
20213
21437
  }
@@ -20239,7 +21463,9 @@ var readShownTheme = ({ theme, ui }) => (ui.picker?.kind === "theme" ? THEME_NAM
20239
21463
  var readShownBackground = ({ background, ui }) => ui.backgroundEditor?.color ?? background;
20240
21464
  async function startTui(client, options = {}) {
20241
21465
  const activeRenderer = options.renderer ?? await createCliRenderer({ exitOnCtrlC: false, useMouse: true });
21466
+ activeRenderer.setTerminalTitle("Claudin");
20242
21467
  const store = new AppStore(client);
21468
+ const clipboard = options.clipboard ?? createHostClipboard();
20243
21469
  let syntaxStyle = createSyntaxStyle(activeRenderer);
20244
21470
  let appliedTheme = readShownTheme(store.state);
20245
21471
  let appliedBackground = readShownBackground(store.state);
@@ -20247,13 +21473,15 @@ async function startTui(client, options = {}) {
20247
21473
  const infoBar = new SessionInfoBar(activeRenderer);
20248
21474
  const popover = new ListPopover(activeRenderer);
20249
21475
  const backgroundPanel = new BackgroundPanel(activeRenderer);
21476
+ const toastView = new ToastView(activeRenderer);
20250
21477
  const statusLine = new StatusLine(activeRenderer, () => cancelTurn(store));
20251
21478
  const scrollback = new ScrollbackView(activeRenderer, {
20252
21479
  syntaxStyle,
20253
21480
  hooks: {
20254
21481
  syntaxStyle,
20255
21482
  onDecision: (decision, id) => answerApproval(store, decision, id),
20256
- onToggle: (callId) => store.emit({ type: "ui.tool.toggled", callId })
21483
+ onToggle: (callId) => store.emit({ type: "ui.tool.toggled", callId }),
21484
+ onSelectRow: (cursor) => store.emit({ type: "ui.question.cursor.set", cursor })
20257
21485
  }
20258
21486
  });
20259
21487
  const diffViewer = new DiffViewerPanel(activeRenderer, syntaxStyle);
@@ -20281,7 +21509,7 @@ async function startTui(client, options = {}) {
20281
21509
  saveDraft(text);
20282
21510
  }
20283
21511
  });
20284
- const root = new BoxRenderable15(activeRenderer, {
21512
+ const root = new BoxRenderable16(activeRenderer, {
20285
21513
  width: "100%",
20286
21514
  height: "100%",
20287
21515
  flexDirection: "column",
@@ -20300,6 +21528,10 @@ async function startTui(client, options = {}) {
20300
21528
  for (const part of parts)
20301
21529
  root.add(part.renderable);
20302
21530
  activeRenderer.root.add(root);
21531
+ activeRenderer.root.add(toastView.renderable);
21532
+ activeRenderer.on("selection", (selection) => {
21533
+ copySelection(store, activeRenderer, clipboard, selection);
21534
+ });
20303
21535
  for (const part of [header, statusLine, popover, backgroundPanel, input, infoBar]) {
20304
21536
  part.renderable.onMouseScroll = ({ scroll }) => {
20305
21537
  if (scroll?.direction === "up")
@@ -20332,6 +21564,7 @@ async function startTui(client, options = {}) {
20332
21564
  syncTheme(state);
20333
21565
  header.update(state);
20334
21566
  statusLine.update(state);
21567
+ toastView.update(state);
20335
21568
  infoBar.update(state);
20336
21569
  scrollback.update(state);
20337
21570
  scrollback.renderable.visible = state.ui.diffViewer === null;
@@ -20370,6 +21603,7 @@ async function startTui(client, options = {}) {
20370
21603
  diffViewer,
20371
21604
  editor,
20372
21605
  acceptCompletion: () => acceptAutocomplete(store, input),
21606
+ pasteClipboard: () => void pasteFromClipboard(store, input, clipboard),
20373
21607
  submitInput,
20374
21608
  exit: () => activeRenderer.destroy()
20375
21609
  };
@@ -20395,6 +21629,7 @@ async function startTui(client, options = {}) {
20395
21629
  clearInterval(rateLimitPoll);
20396
21630
  destroyed = true;
20397
21631
  historySaver.flush();
21632
+ clipboard.dispose();
20398
21633
  options.onExit?.(store.state.sessionId);
20399
21634
  store.close();
20400
21635
  });
@@ -20506,10 +21741,10 @@ function humanReadableArgName(arg) {
20506
21741
 
20507
21742
  // node_modules/.bun/commander@15.0.0/node_modules/commander/lib/command.js
20508
21743
  import { EventEmitter } from "events";
20509
- import childProcess from "child_process";
20510
- import path from "path";
20511
- import fs from "fs";
20512
- import process2 from "process";
21744
+ import childProcess4 from "child_process";
21745
+ import path3 from "path";
21746
+ import fs6 from "fs";
21747
+ import process10 from "process";
20513
21748
  import { stripVTControlCharacters as stripVTControlCharacters2 } from "util";
20514
21749
 
20515
21750
  // node_modules/.bun/commander@15.0.0/node_modules/commander/lib/help.js
@@ -21146,13 +22381,13 @@ class Command extends EventEmitter {
21146
22381
  this._showSuggestionAfterError = true;
21147
22382
  this._savedState = null;
21148
22383
  this._outputConfiguration = {
21149
- writeOut: (str) => process2.stdout.write(str),
21150
- writeErr: (str) => process2.stderr.write(str),
22384
+ writeOut: (str) => process10.stdout.write(str),
22385
+ writeErr: (str) => process10.stderr.write(str),
21151
22386
  outputError: (str, write) => write(str),
21152
- getOutHelpWidth: () => process2.stdout.isTTY ? process2.stdout.columns : undefined,
21153
- getErrHelpWidth: () => process2.stderr.isTTY ? process2.stderr.columns : undefined,
21154
- getOutHasColors: () => useColor() ?? (process2.stdout.isTTY && process2.stdout.hasColors?.()),
21155
- getErrHasColors: () => useColor() ?? (process2.stderr.isTTY && process2.stderr.hasColors?.()),
22387
+ getOutHelpWidth: () => process10.stdout.isTTY ? process10.stdout.columns : undefined,
22388
+ getErrHelpWidth: () => process10.stderr.isTTY ? process10.stderr.columns : undefined,
22389
+ getOutHasColors: () => useColor() ?? (process10.stdout.isTTY && process10.stdout.hasColors?.()),
22390
+ getErrHasColors: () => useColor() ?? (process10.stderr.isTTY && process10.stderr.hasColors?.()),
21156
22391
  stripColor: (str) => stripVTControlCharacters2(str)
21157
22392
  };
21158
22393
  this._hidden = false;
@@ -21360,7 +22595,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
21360
22595
  if (this._exitCallback) {
21361
22596
  this._exitCallback(new CommanderError(exitCode, code, message));
21362
22597
  }
21363
- process2.exit(exitCode);
22598
+ process10.exit(exitCode);
21364
22599
  }
21365
22600
  action(fn) {
21366
22601
  const listener = (args) => {
@@ -21552,16 +22787,16 @@ Expecting one of '${allowedValues.join("', '")}'`);
21552
22787
  }
21553
22788
  parseOptions = parseOptions || {};
21554
22789
  if (argv === undefined && parseOptions.from === undefined) {
21555
- if (process2.versions?.electron) {
22790
+ if (process10.versions?.electron) {
21556
22791
  parseOptions.from = "electron";
21557
22792
  }
21558
- const execArgv = process2.execArgv ?? [];
22793
+ const execArgv = process10.execArgv ?? [];
21559
22794
  if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
21560
22795
  parseOptions.from = "eval";
21561
22796
  }
21562
22797
  }
21563
22798
  if (argv === undefined) {
21564
- argv = process2.argv;
22799
+ argv = process10.argv;
21565
22800
  }
21566
22801
  this.rawArgs = argv.slice();
21567
22802
  let userArgs;
@@ -21572,7 +22807,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
21572
22807
  userArgs = argv.slice(2);
21573
22808
  break;
21574
22809
  case "electron":
21575
- if (process2.defaultApp) {
22810
+ if (process10.defaultApp) {
21576
22811
  this._scriptPath = argv[1];
21577
22812
  userArgs = argv.slice(2);
21578
22813
  } else {
@@ -21638,7 +22873,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
21638
22873
  this.processedArgs = [];
21639
22874
  }
21640
22875
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
21641
- if (fs.existsSync(executableFile))
22876
+ if (fs6.existsSync(executableFile))
21642
22877
  return;
21643
22878
  const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
21644
22879
  const executableMissing = `'${executableFile}' does not exist
@@ -21651,12 +22886,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
21651
22886
  args = args.slice();
21652
22887
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
21653
22888
  function findFile(baseDir, baseName) {
21654
- const localBin = path.resolve(baseDir, baseName);
21655
- if (fs.existsSync(localBin))
22889
+ const localBin = path3.resolve(baseDir, baseName);
22890
+ if (fs6.existsSync(localBin))
21656
22891
  return localBin;
21657
- if (sourceExt.includes(path.extname(baseName)))
22892
+ if (sourceExt.includes(path3.extname(baseName)))
21658
22893
  return;
21659
- const foundExt = sourceExt.find((ext) => fs.existsSync(`${localBin}${ext}`));
22894
+ const foundExt = sourceExt.find((ext) => fs6.existsSync(`${localBin}${ext}`));
21660
22895
  if (foundExt)
21661
22896
  return `${localBin}${foundExt}`;
21662
22897
  return;
@@ -21668,42 +22903,42 @@ Expecting one of '${allowedValues.join("', '")}'`);
21668
22903
  if (this._scriptPath) {
21669
22904
  let resolvedScriptPath;
21670
22905
  try {
21671
- resolvedScriptPath = fs.realpathSync(this._scriptPath);
22906
+ resolvedScriptPath = fs6.realpathSync(this._scriptPath);
21672
22907
  } catch {
21673
22908
  resolvedScriptPath = this._scriptPath;
21674
22909
  }
21675
- executableDir = path.resolve(path.dirname(resolvedScriptPath), executableDir);
22910
+ executableDir = path3.resolve(path3.dirname(resolvedScriptPath), executableDir);
21676
22911
  }
21677
22912
  if (executableDir) {
21678
22913
  let localFile = findFile(executableDir, executableFile);
21679
22914
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
21680
- const legacyName = path.basename(this._scriptPath, path.extname(this._scriptPath));
22915
+ const legacyName = path3.basename(this._scriptPath, path3.extname(this._scriptPath));
21681
22916
  if (legacyName !== this._name) {
21682
22917
  localFile = findFile(executableDir, `${legacyName}-${subcommand._name}`);
21683
22918
  }
21684
22919
  }
21685
22920
  executableFile = localFile || executableFile;
21686
22921
  }
21687
- const launchWithNode = sourceExt.includes(path.extname(executableFile));
22922
+ const launchWithNode = sourceExt.includes(path3.extname(executableFile));
21688
22923
  let proc;
21689
- if (process2.platform !== "win32") {
22924
+ if (process10.platform !== "win32") {
21690
22925
  if (launchWithNode) {
21691
22926
  args.unshift(executableFile);
21692
- args = incrementNodeInspectorPort(process2.execArgv).concat(args);
21693
- proc = childProcess.spawn(process2.argv[0], args, { stdio: "inherit" });
22927
+ args = incrementNodeInspectorPort(process10.execArgv).concat(args);
22928
+ proc = childProcess4.spawn(process10.argv[0], args, { stdio: "inherit" });
21694
22929
  } else {
21695
- proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
22930
+ proc = childProcess4.spawn(executableFile, args, { stdio: "inherit" });
21696
22931
  }
21697
22932
  } else {
21698
22933
  this._checkForMissingExecutable(executableFile, executableDir, subcommand._name);
21699
22934
  args.unshift(executableFile);
21700
- args = incrementNodeInspectorPort(process2.execArgv).concat(args);
21701
- proc = childProcess.spawn(process2.execPath, args, { stdio: "inherit" });
22935
+ args = incrementNodeInspectorPort(process10.execArgv).concat(args);
22936
+ proc = childProcess4.spawn(process10.execPath, args, { stdio: "inherit" });
21702
22937
  }
21703
22938
  if (!proc.killed) {
21704
22939
  const signals = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
21705
22940
  signals.forEach((signal) => {
21706
- process2.on(signal, () => {
22941
+ process10.on(signal, () => {
21707
22942
  if (proc.killed === false && proc.exitCode === null) {
21708
22943
  proc.kill(signal);
21709
22944
  }
@@ -21714,7 +22949,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
21714
22949
  proc.on("close", (code) => {
21715
22950
  code = code ?? 1;
21716
22951
  if (!exitCallback) {
21717
- process2.exit(code);
22952
+ process10.exit(code);
21718
22953
  } else {
21719
22954
  exitCallback(new CommanderError(code, "commander.executeSubCommandAsync", "(close)"));
21720
22955
  }
@@ -21726,7 +22961,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
21726
22961
  throw new Error(`'${executableFile}' not executable`);
21727
22962
  }
21728
22963
  if (!exitCallback) {
21729
- process2.exit(1);
22964
+ process10.exit(1);
21730
22965
  } else {
21731
22966
  const wrappedError = new CommanderError(1, "commander.executeSubCommandAsync", "(error)");
21732
22967
  wrappedError.nestedError = err;
@@ -22075,11 +23310,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
22075
23310
  }
22076
23311
  _parseOptionsEnv() {
22077
23312
  this.options.forEach((option) => {
22078
- if (option.envVar && option.envVar in process2.env) {
23313
+ if (option.envVar && option.envVar in process10.env) {
22079
23314
  const optionKey = option.attributeName();
22080
23315
  if (this.getOptionValue(optionKey) === undefined || ["default", "config", "env"].includes(this.getOptionValueSource(optionKey))) {
22081
23316
  if (option.required || option.optional) {
22082
- this.emit(`optionEnv:${option.name()}`, process2.env[option.envVar]);
23317
+ this.emit(`optionEnv:${option.name()}`, process10.env[option.envVar]);
22083
23318
  } else {
22084
23319
  this.emit(`optionEnv:${option.name()}`);
22085
23320
  }
@@ -22275,13 +23510,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
22275
23510
  cmd.helpGroup(this._defaultCommandGroup);
22276
23511
  }
22277
23512
  nameFromFilename(filename) {
22278
- this._name = path.basename(filename, path.extname(filename));
23513
+ this._name = path3.basename(filename, path3.extname(filename));
22279
23514
  return this;
22280
23515
  }
22281
- executableDir(path2) {
22282
- if (path2 === undefined)
23516
+ executableDir(path) {
23517
+ if (path === undefined)
22283
23518
  return this._executableDir;
22284
- this._executableDir = path2;
23519
+ this._executableDir = path;
22285
23520
  return this;
22286
23521
  }
22287
23522
  helpInformation(contextOptions) {
@@ -22378,7 +23613,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
22378
23613
  }
22379
23614
  help(contextOptions) {
22380
23615
  this.outputHelp(contextOptions);
22381
- let exitCode = Number(process2.exitCode ?? 0);
23616
+ let exitCode = Number(process10.exitCode ?? 0);
22382
23617
  if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
22383
23618
  exitCode = 1;
22384
23619
  }
@@ -22444,9 +23679,9 @@ function incrementNodeInspectorPort(args) {
22444
23679
  });
22445
23680
  }
22446
23681
  function useColor() {
22447
- if (process2.env.NO_COLOR || process2.env.FORCE_COLOR === "0" || process2.env.FORCE_COLOR === "false")
23682
+ if (process10.env.NO_COLOR || process10.env.FORCE_COLOR === "0" || process10.env.FORCE_COLOR === "false")
22448
23683
  return false;
22449
- if (process2.env.FORCE_COLOR || process2.env.CLICOLOR_FORCE !== undefined)
23684
+ if (process10.env.FORCE_COLOR || process10.env.CLICOLOR_FORCE !== undefined)
22450
23685
  return true;
22451
23686
  return;
22452
23687
  }