shortcutxl 0.3.73 → 0.3.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Changelog
2
2
 
3
- ## [0.3.73]
3
+ ## [0.3.74]
4
4
 
5
5
  - **Native desktop app** - Run `shortcut app` for a multi-session desktop experience with tools, approvals, subagents, attachments, skills, themes, and account controls.
6
6
 
@@ -3,5 +3,6 @@
3
3
  * but cannot spawn other clones.
4
4
  */
5
5
  import type { AgentDefinition } from '../../agent-definition.js';
6
+ export declare const CLONE_AGENT_TOOL_NAMES: readonly ["bash", "write", "execute_code", "task", "take_screenshot", "get_tool_info", "execute_tool", "mcp"];
6
7
  export declare const cloneAgent: AgentDefinition;
7
8
  //# sourceMappingURL=agent.d.ts.map
@@ -2,13 +2,22 @@
2
2
  * Clone subagent — a full copy of the action agent that can spawn leaf subagents
3
3
  * but cannot spawn other clones.
4
4
  */
5
- import { REFRESH_CONTEXT } from '../../../tool-names.js';
6
- import { ACTION_AGENT_TOOL_NAMES } from '../../modes/action/agent.js';
5
+ import { BASH, EXECUTE_CODE, EXECUTE_TOOL, GET_TOOL_INFO, MCP_TOOL_NAMES, TAKE_SCREENSHOT, TASK, WRITE } from '../../../tool-names.js';
7
6
  import { buildActionPrompt } from '../../modes/action/prompt.js';
8
7
  import { DEFAULT_SUBAGENT_MODEL, DEFAULT_SUBAGENT_TIMEOUT_SECONDS } from '../defaults.js';
9
8
  const NAME = 'clone';
10
9
  const DESCRIPTION = `\
11
10
  A write-capable clone of the main agent with the same tools, including the ability to spawn subagents. Useful for parallelization and delegation of tasks.`;
11
+ export const CLONE_AGENT_TOOL_NAMES = [
12
+ BASH,
13
+ WRITE,
14
+ EXECUTE_CODE,
15
+ TASK,
16
+ TAKE_SCREENSHOT,
17
+ GET_TOOL_INFO,
18
+ EXECUTE_TOOL,
19
+ ...MCP_TOOL_NAMES
20
+ ];
12
21
  const SUBAGENT_OUTPUT_DISCIPLINE = `\
13
22
  ======================
14
23
  SUBAGENT OUTPUT
@@ -20,7 +29,7 @@ export const cloneAgent = {
20
29
  get systemPrompt() {
21
30
  return `${buildActionPrompt()}\n\n${SUBAGENT_OUTPUT_DISCIPLINE}`;
22
31
  },
23
- tools: ACTION_AGENT_TOOL_NAMES.filter((toolName) => toolName !== REFRESH_CONTEXT),
32
+ tools: [...CLONE_AGENT_TOOL_NAMES],
24
33
  excludeSubagents: ['clone'],
25
34
  model: DEFAULT_SUBAGENT_MODEL,
26
35
  thinkingLevel: 'medium',
@@ -5,7 +5,7 @@
5
5
  * catalog, even after test resets.
6
6
  */
7
7
  export type { AgentDefinition } from '../agent-definition.js';
8
- export { cloneAgent } from './clone/agent.js';
8
+ export { CLONE_AGENT_TOOL_NAMES, cloneAgent } from './clone/agent.js';
9
9
  export { DEFAULT_SUBAGENT_MODEL, DEFAULT_SUBAGENT_TIMEOUT_SECONDS, TASK_MODEL_CHOICES } from './defaults.js';
10
10
  export { documentReaderAgent } from './document-reader/agent.js';
11
11
  export { verificationAgent } from './verification/agent.js';
@@ -4,7 +4,7 @@
4
4
  * Built-in agents are registered eagerly so callers always see a stable
5
5
  * catalog, even after test resets.
6
6
  */
7
- export { cloneAgent } from './clone/agent.js';
7
+ export { CLONE_AGENT_TOOL_NAMES, cloneAgent } from './clone/agent.js';
8
8
  export { DEFAULT_SUBAGENT_MODEL, DEFAULT_SUBAGENT_TIMEOUT_SECONDS, TASK_MODEL_CHOICES } from './defaults.js';
9
9
  export { documentReaderAgent } from './document-reader/agent.js';
10
10
  export { verificationAgent } from './verification/agent.js';
package/dist/cli.js CHANGED
@@ -372010,16 +372010,25 @@ var init_defaults = __esm({
372010
372010
  });
372011
372011
 
372012
372012
  // src/app/subagents/clone/agent.ts
372013
- var NAME, DESCRIPTION6, SUBAGENT_OUTPUT_DISCIPLINE, cloneAgent;
372013
+ var NAME, DESCRIPTION6, CLONE_AGENT_TOOL_NAMES, SUBAGENT_OUTPUT_DISCIPLINE, cloneAgent;
372014
372014
  var init_agent6 = __esm({
372015
372015
  "src/app/subagents/clone/agent.ts"() {
372016
372016
  "use strict";
372017
372017
  init_tool_names();
372018
- init_agent();
372019
372018
  init_prompt();
372020
372019
  init_defaults();
372021
372020
  NAME = "clone";
372022
372021
  DESCRIPTION6 = `A write-capable clone of the main agent with the same tools, including the ability to spawn subagents. Useful for parallelization and delegation of tasks.`;
372022
+ CLONE_AGENT_TOOL_NAMES = [
372023
+ BASH,
372024
+ WRITE,
372025
+ EXECUTE_CODE,
372026
+ TASK,
372027
+ TAKE_SCREENSHOT,
372028
+ GET_TOOL_INFO,
372029
+ EXECUTE_TOOL,
372030
+ ...MCP_TOOL_NAMES
372031
+ ];
372023
372032
  SUBAGENT_OUTPUT_DISCIPLINE = `======================
372024
372033
  SUBAGENT OUTPUT
372025
372034
  ======================
@@ -372032,7 +372041,7 @@ Be concise and clear. Keep reports clear, succinct, and structured when possible
372032
372041
 
372033
372042
  ${SUBAGENT_OUTPUT_DISCIPLINE}`;
372034
372043
  },
372035
- tools: ACTION_AGENT_TOOL_NAMES.filter((toolName) => toolName !== REFRESH_CONTEXT),
372044
+ tools: [...CLONE_AGENT_TOOL_NAMES],
372036
372045
  excludeSubagents: ["clone"],
372037
372046
  model: DEFAULT_SUBAGENT_MODEL,
372038
372047
  thinkingLevel: "medium",
@@ -5,5 +5,6 @@
5
5
  * can spawn leaf subagents, but cannot recursively spawn another clone.
6
6
  */
7
7
  import { type AgentDefinition } from '../agent-definition.js';
8
+ export declare const CLONE_TOOL_NAMES: readonly ["get_tool_info", "execute_tool", "execute_code", "bash_command", "take_screenshot", "mcp", "task"];
8
9
  export declare const cloneSubagent: AgentDefinition;
9
10
  //# sourceMappingURL=clone.d.ts.map
@@ -9,11 +9,19 @@ import { AGENT_PHILOSOPHY, COMMUNICATION, DATA_FORMATTING, TASK_EXECUTION, WRITI
9
9
  import { buildSubagentApiReferenceSection } from '../../../../utils/api-reference.js';
10
10
  import { buildActionModeMainSection } from '../../../prompt/modes/action.js';
11
11
  import { API_HIERARCHY_SECTION, SANDBOX_FILESYSTEM, getPlatformIdentity } from '../../../prompt/sections.js';
12
- import { ACTION_TOOL_NAMES } from '../../action-tool-names.js';
13
- import { REFRESH_CONTEXT } from '../../tool-names.js';
12
+ import { BASH_COMMAND, EXECUTE_CODE, EXECUTE_TOOL, GET_TOOL_INFO, MCP, TAKE_SCREENSHOT, TASK } from '../../tool-names.js';
14
13
  import { DEFAULT_TASK_SUBAGENT_MODEL_ID, DEFAULT_TASK_SUBAGENT_TIMEOUT_SECONDS } from '../agent-definition.js';
15
14
  const DESCRIPTION = `\
16
15
  A write-capable clone of the main agent with the same tools, including the ability to spawn subagents. Useful for parallelization and delegation of tasks.`;
16
+ export const CLONE_TOOL_NAMES = [
17
+ GET_TOOL_INFO,
18
+ EXECUTE_TOOL,
19
+ EXECUTE_CODE,
20
+ BASH_COMMAND,
21
+ TAKE_SCREENSHOT,
22
+ MCP,
23
+ TASK
24
+ ];
17
25
  const SUBAGENT_OUTPUT_SECTION = `\
18
26
  ======================
19
27
  SUBAGENT OUTPUT
@@ -40,7 +48,7 @@ export const cloneSubagent = {
40
48
  name: 'clone',
41
49
  description: DESCRIPTION,
42
50
  systemPrompt: buildSystemPrompt,
43
- tools: ACTION_TOOL_NAMES.filter((toolName) => toolName !== REFRESH_CONTEXT),
51
+ tools: [...CLONE_TOOL_NAMES],
44
52
  model: DEFAULT_TASK_SUBAGENT_MODEL_ID,
45
53
  thinkingLevel: RUNTIME_THINKING_LEVEL.Medium,
46
54
  timeoutSeconds: DEFAULT_TASK_SUBAGENT_TIMEOUT_SECONDS,
@@ -4,5 +4,5 @@
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "main": "main/index.js",
7
- "version": "0.3.73"
7
+ "version": "0.3.74"
8
8
  }
@@ -25602,6 +25602,7 @@ function indexToolResults(messages) {
25602
25602
  }
25603
25603
  return results;
25604
25604
  }
25605
+ const MAX_COLLAPSED_LINES = 2;
25605
25606
  function record(value) {
25606
25607
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
25607
25608
  }
@@ -25655,6 +25656,13 @@ function line(text2, tone = "output") {
25655
25656
  function splitLines(text2, tone = "output") {
25656
25657
  return text2.replace(/\t/g, " ").split("\n").map((value) => line(value, tone));
25657
25658
  }
25659
+ function compactOutputLine(text2) {
25660
+ return compact(text2, 180);
25661
+ }
25662
+ function capCollapsedLines(lines) {
25663
+ if (lines.length <= MAX_COLLAPSED_LINES) return lines;
25664
+ return [lines[0], lines.at(-1)];
25665
+ }
25658
25666
  function titleText(parts) {
25659
25667
  return parts.map((value) => value.text).join("");
25660
25668
  }
@@ -25694,9 +25702,13 @@ function bashPresentation(args, output, details, isError) {
25694
25702
  if (suffix) expandedHeader.push(part(suffix, "dim"));
25695
25703
  const rawLines = output.trim() ? output.trim().split("\n") : [];
25696
25704
  const outputTone = isError ? "error" : "output";
25697
- const preview = rawLines.slice(-2).map((value, index2) => line(`${index2 === 0 ? "⎿ " : " "}${value}`, outputTone));
25698
- const hidden = Math.max(0, rawLines.length - 2);
25699
- if (hidden > 0) preview.push(line(` … +${hidden} lines`, "dim"));
25705
+ const lastOutput = rawLines.at(-1);
25706
+ const preview = lastOutput ? [
25707
+ line(
25708
+ `⎿ ${compactOutputLine(lastOutput)}${rawLines.length > 1 ? ` · ${rawLines.length} lines` : ""}`,
25709
+ outputTone
25710
+ )
25711
+ ] : [];
25700
25712
  preview.push(...warningLines(details));
25701
25713
  const expanded = rawLines.map(
25702
25714
  (value, index2) => line(`${index2 === 0 ? "⎿ " : " "}${value}`, outputTone)
@@ -25719,37 +25731,36 @@ function fileHeader(name2, args) {
25719
25731
  }
25720
25732
  return [part(name2, "title", true), part(" "), part(path2, "accent")];
25721
25733
  }
25722
- function filePresentation(name2, args, output, details, isError) {
25734
+ function filePresentation(name2, args, output, details, isError, running) {
25723
25735
  const header = fileHeader(name2, args);
25724
25736
  if (name2 === "read") {
25725
25737
  if (!output) return { header, collapsedLines: [], expandedLines: [] };
25726
25738
  const lines = output.replace(/\t/g, " ").split("\n");
25727
- const preview = lines.slice(-2).map((value) => line(value));
25728
- const skipped = Math.max(0, lines.length - 2);
25729
- if (skipped > 0) preview.push(line(`... +${skipped} lines`, "dim"));
25730
25739
  return {
25731
25740
  header,
25732
- collapsedLines: preview,
25741
+ collapsedLines: [
25742
+ line(`Read ${lines.length} ${lines.length === 1 ? "line" : "lines"}`, "dim")
25743
+ ],
25733
25744
  expandedLines: lines.map((value) => line(value))
25734
25745
  };
25735
25746
  }
25736
25747
  if (name2 === "write") {
25737
25748
  const content2 = stringArg(args, "content");
25749
+ const hasContent = typeof args.content === "string";
25738
25750
  const contentLines = content2 ? content2.replace(/\t/g, " ").split("\n") : [];
25739
- const collapsedLines = contentLines.slice(0, 10).map((value) => line(value));
25740
- if (contentLines.length > 10) {
25741
- collapsedLines.push(
25742
- line(`... (${contentLines.length - 10} more lines, ${contentLines.length} total)`, "dim")
25743
- );
25744
- }
25745
25751
  const expandedLines2 = contentLines.map((value) => line(value));
25746
25752
  if (isError && output) {
25747
- collapsedLines.push(...splitLines(output, "error"));
25748
25753
  expandedLines2.push(...splitLines(output, "error"));
25749
25754
  }
25755
+ const collapsedLines = isError ? [line(`Write failed: ${compactOutputLine(output || "Unknown error")}`, "error")] : hasContent ? [
25756
+ line(
25757
+ contentLines.length === 0 ? `${running ? "Writing" : "Wrote"} empty file` : `${running ? "Writing" : "Wrote"} ${contentLines.length} ${contentLines.length === 1 ? "line" : "lines"}`,
25758
+ "dim"
25759
+ )
25760
+ ] : [];
25750
25761
  return {
25751
25762
  header,
25752
- collapsedLines: contentLines.length ? [line(""), ...collapsedLines] : collapsedLines,
25763
+ collapsedLines,
25753
25764
  expandedLines: contentLines.length ? [line(""), ...expandedLines2] : expandedLines2
25754
25765
  };
25755
25766
  }
@@ -25803,10 +25814,8 @@ function searchWarnings(name2, details) {
25803
25814
  function searchPresentation(name2, args, output, details) {
25804
25815
  const header = searchHeader(name2, args);
25805
25816
  const lines = output.trim() ? output.trim().split("\n").map((value) => line(value)) : [];
25806
- const max = name2 === "grep" ? 0 : 20;
25807
- const preview = lines.slice(0, max);
25808
- if (lines.length > max && max > 0)
25809
- preview.push(line(`... (${lines.length - max} more lines)`, "dim"));
25817
+ const noun = name2 === "ls" ? lines.length === 1 ? "entry" : "entries" : name2 === "find" ? lines.length === 1 ? "result" : "results" : lines.length === 1 ? "match" : "matches";
25818
+ const preview = lines.length ? [line(`${lines.length} ${noun}`, "dim")] : [];
25810
25819
  preview.push(...searchWarnings(name2, details));
25811
25820
  return {
25812
25821
  header,
@@ -25923,11 +25932,18 @@ function goalPresentation(args, output, details, isError) {
25923
25932
  function genericPresentation(name2, args, output) {
25924
25933
  const header = [part(name2, "title", true)];
25925
25934
  const argsText = Object.keys(args).length ? safeJson(args, true) : "";
25926
- const lines = [
25935
+ const expandedLines = [
25927
25936
  ...argsText ? [line(""), ...splitLines(argsText)] : [],
25928
25937
  ...output ? splitLines(output) : []
25929
25938
  ];
25930
- return { header, collapsedLines: lines, expandedLines: lines };
25939
+ const outputPreview = output.split("\n").map((value) => value.trim()).find(Boolean);
25940
+ const argumentPreview = primaryToolArgument(args, name2);
25941
+ const preview = outputPreview || argumentPreview;
25942
+ return {
25943
+ header,
25944
+ collapsedLines: preview ? [line(` ${compactOutputLine(preview)}`, "dim")] : [],
25945
+ expandedLines
25946
+ };
25931
25947
  }
25932
25948
  function humanizeToolName(value) {
25933
25949
  return value.replace(/[_-]+/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase()).trim();
@@ -25972,7 +25988,7 @@ function buildToolDisplay({
25972
25988
  case "read":
25973
25989
  case "write":
25974
25990
  case "edit":
25975
- presentation = filePresentation(name2, args, output, details, isError);
25991
+ presentation = filePresentation(name2, args, output, details, isError, running);
25976
25992
  break;
25977
25993
  case "ls":
25978
25994
  case "find":
@@ -26124,6 +26140,7 @@ function buildToolDisplay({
26124
26140
  isError,
26125
26141
  title: titleText(presentation.header),
26126
26142
  ...presentation,
26143
+ collapsedLines: capCollapsedLines(presentation.collapsedLines),
26127
26144
  images: messageImages(result)
26128
26145
  };
26129
26146
  }
@@ -26406,13 +26423,27 @@ function EmptyConversation({
26406
26423
  ] })
26407
26424
  ] });
26408
26425
  }
26409
- function payloadPreview(payload) {
26410
- return payload && typeof payload === "object" ? JSON.stringify(payload, null, 2) : String(payload ?? "");
26426
+ function payloadRecord(payload) {
26427
+ return payload !== null && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
26428
+ }
26429
+ function payloadText(payload, key) {
26430
+ const value = payload[key];
26431
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
26411
26432
  }
26412
- function payloadDescription(payload) {
26413
- if (!payload || typeof payload !== "object" || !("description" in payload)) return void 0;
26414
- const description = payload.description;
26415
- return typeof description === "string" && description.trim() ? description.trim() : void 0;
26433
+ function approvalDetails(rawPayload) {
26434
+ const payload = payloadRecord(rawPayload);
26435
+ const details = ["description", "reason", "summary", "path", "command", "query", "documentPath"].map((key) => payloadText(payload, key)).filter((detail) => Boolean(detail));
26436
+ for (const key of ["highRiskOperations", "operations"]) {
26437
+ const operations = payload[key];
26438
+ if (!Array.isArray(operations)) continue;
26439
+ for (const operation of operations) {
26440
+ const values = payloadRecord(operation);
26441
+ const label2 = payloadText(values, "label");
26442
+ const reason = payloadText(values, "reason");
26443
+ if (reason) details.push(`${label2 ? `${label2}: ` : ""}${reason}`);
26444
+ }
26445
+ }
26446
+ return [...new Set(details)];
26416
26447
  }
26417
26448
  function InteractionPanel({
26418
26449
  interaction,
@@ -26422,13 +26453,13 @@ function InteractionPanel({
26422
26453
  const [input, setInput] = reactExports.useState("");
26423
26454
  if (interaction.kind === "approval") {
26424
26455
  const request = interaction.approval.request;
26425
- const description = payloadDescription(request.payload);
26456
+ const details = approvalDetails(request.payload);
26426
26457
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "interaction-panel approval-panel", children: [
26427
26458
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "interaction-heading", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
26428
26459
  /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: request.title }),
26429
26460
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: request.kind })
26430
26461
  ] }) }),
26431
- description ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "interaction-description", children: description }) : /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "interaction-preview", children: payloadPreview(request.payload) }),
26462
+ details.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "interaction-details", children: details.map((detail) => /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "interaction-detail", children: detail }, detail)) }),
26432
26463
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "interaction-actions", children: request.choices.map((choice, index2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
26433
26464
  "button",
26434
26465
  {
@@ -27989,6 +28020,8 @@ function useAgentHost() {
27989
28020
  const [restartKey, setRestartKey] = reactExports.useState(0);
27990
28021
  const hostIdRef = reactExports.useRef(void 0);
27991
28022
  const hostsRef = reactExports.useRef(state.hosts);
28023
+ const hostRuntimeArgsRef = reactExports.useRef(/* @__PURE__ */ new Map());
28024
+ const startHostRef = reactExports.useRef(void 0);
27992
28025
  hostsRef.current = state.hosts;
27993
28026
  const activeView = state.activeHostId ? state.hosts[state.activeHostId] : void 0;
27994
28027
  const connection = state.status === "ready" && state.activeHostId && activeView ? { status: "ready", hostId: state.activeHostId, view: activeView } : state.status === "failed" ? { status: "failed", message: state.message ?? "Agent runtime stopped" } : { status: "starting" };
@@ -28001,6 +28034,7 @@ function useAgentHost() {
28001
28034
  if (!active) return;
28002
28035
  if ("termination" in payload) {
28003
28036
  hostIds.delete(payload.hostId);
28037
+ hostRuntimeArgsRef.current.delete(payload.hostId);
28004
28038
  if (hostIdRef.current === payload.hostId) {
28005
28039
  hostIdRef.current = [...hostIds].at(-1);
28006
28040
  }
@@ -28022,25 +28056,34 @@ function useAgentHost() {
28022
28056
  return;
28023
28057
  }
28024
28058
  hostIds.add(result.hostId);
28059
+ hostRuntimeArgsRef.current.set(result.hostId, [...runtimeArgs ?? []]);
28025
28060
  hostIdRef.current = result.hostId;
28026
28061
  dispatch({ type: "ready", ...result });
28027
28062
  } catch (error) {
28028
28063
  if (active && requestGeneration === generation) {
28029
28064
  dispatch({ type: "failed", message: String(error) });
28030
28065
  }
28066
+ throw error;
28031
28067
  }
28032
28068
  };
28069
+ startHostRef.current = start;
28033
28070
  const unsubscribeWorkspace = window.shortcut.agent.onOpenWorkspace(({ cwd: cwd2, runtimeArgs }) => {
28034
- void start(cwd2, runtimeArgs);
28071
+ void start(cwd2, runtimeArgs).catch(() => {
28072
+ });
28073
+ });
28074
+ void start().catch(() => {
28035
28075
  });
28036
- void start();
28037
28076
  return () => {
28038
28077
  active = false;
28039
28078
  generation += 1;
28040
28079
  unsubscribe();
28041
28080
  unsubscribeWorkspace();
28081
+ if (startHostRef.current === start) startHostRef.current = void 0;
28042
28082
  hostIdRef.current = void 0;
28043
- for (const hostId of hostIds) void window.shortcut.agent.stop({ hostId });
28083
+ for (const hostId of hostIds) {
28084
+ hostRuntimeArgsRef.current.delete(hostId);
28085
+ void window.shortcut.agent.stop({ hostId });
28086
+ }
28044
28087
  hostIds.clear();
28045
28088
  };
28046
28089
  }, [restartKey]);
@@ -28072,6 +28115,13 @@ function useAgentHost() {
28072
28115
  [request]
28073
28116
  );
28074
28117
  const newSession = reactExports.useCallback(async () => {
28118
+ const hostId = hostIdRef.current;
28119
+ const startHost = startHostRef.current;
28120
+ const currentView = hostId ? hostsRef.current[hostId] : void 0;
28121
+ if (!hostId || !startHost || !currentView) throw new Error("Agent runtime is not ready");
28122
+ await startHost(currentView.snapshot.session.cwd, hostRuntimeArgsRef.current.get(hostId) ?? []);
28123
+ }, []);
28124
+ const replaceSession = reactExports.useCallback(async () => {
28075
28125
  const result = await request({ type: "new_session" });
28076
28126
  if (!result.cancelled) await refreshSnapshot();
28077
28127
  }, [refreshSnapshot, request]);
@@ -28242,6 +28292,7 @@ function useAgentHost() {
28242
28292
  abort,
28243
28293
  respondToInteraction,
28244
28294
  newSession,
28295
+ replaceSession,
28245
28296
  listSessions,
28246
28297
  deleteSession,
28247
28298
  switchSession,
@@ -28350,7 +28401,7 @@ function App({ initialThemeId: initialThemeId2 }) {
28350
28401
  const newestNotice = view?.notices.at(-1);
28351
28402
  const latestNotice = newestNotice?.id === dismissedNoticeId ? void 0 : newestNotice;
28352
28403
  const activeInteraction = view?.pendingInteractions[0];
28353
- const canStartNewChat = Boolean(ready && !view?.snapshot.isStreaming);
28404
+ const canStartNewChat = Boolean(ready);
28354
28405
  const liveSessions = agent.hosts.map(({ hostId, view: hostView }) => ({
28355
28406
  hostId,
28356
28407
  sessionId: hostView.snapshot.session.id,
@@ -28374,7 +28425,7 @@ function App({ initialThemeId: initialThemeId2 }) {
28374
28425
  return run(async () => {
28375
28426
  const activePath = view.snapshot.session.path;
28376
28427
  if (activePath && paths.includes(activePath)) {
28377
- await agent.newSession();
28428
+ await agent.replaceSession();
28378
28429
  await agent.deleteSession(activePath);
28379
28430
  }
28380
28431
  for (const path2 of paths) {
@@ -772,13 +772,13 @@ button:not(:disabled):active {
772
772
  gap: 16px;
773
773
  }
774
774
 
775
- .runtime-dashboard > section > header h2,
776
- .command-reference > header h2 {
777
- font-family: var(--font-terminal);
778
- font-size: var(--terminal-text-size);
779
- font-weight: 700;
780
- letter-spacing: 0.06em;
781
- text-transform: uppercase;
775
+ .runtime-dashboard > section > header h2,
776
+ .command-reference > header h2 {
777
+ font-family: var(--font-terminal);
778
+ font-size: var(--terminal-text-size);
779
+ font-weight: 700;
780
+ letter-spacing: 0.06em;
781
+ text-transform: uppercase;
782
782
  }
783
783
 
784
784
  .runtime-dashboard h2 {
@@ -807,12 +807,12 @@ button:not(:disabled):active {
807
807
  padding: 0 8px;
808
808
  border: 0;
809
809
  border-bottom: 1px solid var(--line);
810
- border-radius: 0;
811
- color: var(--quiet);
812
- background: transparent;
813
- font-size: var(--terminal-text-size);
814
- text-align: left;
815
- }
810
+ border-radius: 0;
811
+ color: var(--quiet);
812
+ background: transparent;
813
+ font-size: var(--terminal-text-size);
814
+ text-align: left;
815
+ }
816
816
 
817
817
  .environment-list > button,
818
818
  .command-reference button {
@@ -821,12 +821,12 @@ button:not(:disabled):active {
821
821
 
822
822
  .environment-list code,
823
823
  .command-reference code {
824
- width: 88px;
825
- flex: 0 0 88px;
826
- color: var(--ink-soft);
827
- font-size: inherit;
828
- font-weight: 620;
829
- }
824
+ width: 88px;
825
+ flex: 0 0 88px;
826
+ color: var(--ink-soft);
827
+ font-size: inherit;
828
+ font-weight: 620;
829
+ }
830
830
 
831
831
  .environment-list span,
832
832
  .command-reference button span {
@@ -1817,6 +1817,7 @@ button:not(:disabled):active {
1817
1817
  }
1818
1818
 
1819
1819
  .interaction-panel {
1820
+ min-width: 0;
1820
1821
  padding: 14px;
1821
1822
  border: 1px solid var(--line-strong);
1822
1823
  border-bottom: 0;
@@ -1832,9 +1833,15 @@ button:not(:disabled):active {
1832
1833
 
1833
1834
  .interaction-heading > div {
1834
1835
  display: grid;
1836
+ min-width: 0;
1835
1837
  gap: 2px;
1836
1838
  }
1837
1839
 
1840
+ .interaction-heading strong,
1841
+ .interaction-panel > p {
1842
+ overflow-wrap: anywhere;
1843
+ }
1844
+
1838
1845
  .interaction-heading strong {
1839
1846
  color: var(--ink-soft);
1840
1847
  font-size: 0.75rem;
@@ -1846,19 +1853,22 @@ button:not(:disabled):active {
1846
1853
  font-size: 0.625rem;
1847
1854
  }
1848
1855
 
1849
- .interaction-preview {
1850
- margin: 12px 0;
1851
- padding: 10px;
1852
- border: 1px solid var(--interaction-line);
1853
- background: var(--surface);
1854
- }
1855
-
1856
- .interaction-panel .interaction-description {
1857
- margin: 12px 0;
1858
- color: var(--ink-soft);
1859
- font-size: var(--terminal-footer-size);
1860
- line-height: 1.5;
1861
- }
1856
+ .interaction-details {
1857
+ display: grid;
1858
+ min-width: 0;
1859
+ margin: 12px 0;
1860
+ gap: 6px;
1861
+ }
1862
+
1863
+ .interaction-panel .interaction-detail {
1864
+ min-width: 0;
1865
+ margin: 0;
1866
+ color: var(--ink-soft);
1867
+ font-size: var(--terminal-footer-size);
1868
+ line-height: 1.5;
1869
+ overflow-wrap: anywhere;
1870
+ white-space: pre-wrap;
1871
+ }
1862
1872
 
1863
1873
  .interaction-actions {
1864
1874
  justify-content: flex-end;
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Shortcut CLI</title>
7
- <script type="module" crossorigin src="./assets/index-upOaS1d7.js"></script>
8
- <link rel="stylesheet" crossorigin href="./assets/index-m6aeCx-5.css">
7
+ <script type="module" crossorigin src="./assets/index-Fluj0X8h.js"></script>
8
+ <link rel="stylesheet" crossorigin href="./assets/index-OhGE0UY4.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shortcutxl",
3
- "version": "0.3.73",
3
+ "version": "0.3.74",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
Binary file