@radnine/storybook-addon-claude 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/manager.js +201 -47
  2. package/package.json +1 -1
package/dist/manager.js CHANGED
@@ -86,16 +86,16 @@ function MarkdownContent({ text }) {
86
86
  }
87
87
 
88
88
  // src/components/MessageList.jsx
89
- function MessageList({ messages }) {
89
+ function MessageList({ messages, isProcessing }) {
90
90
  const bottomRef = useRef(null);
91
91
  useEffect(() => {
92
92
  var _a;
93
93
  (_a = bottomRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
94
- }, [messages]);
94
+ }, [messages, isProcessing]);
95
95
  if (messages.length === 0) {
96
96
  return /* @__PURE__ */ React2.createElement("div", { style: styles.empty }, "No messages yet. Send a message to start chatting with Claude.");
97
97
  }
98
- return /* @__PURE__ */ React2.createElement("div", { style: styles.container }, messages.map((msg) => /* @__PURE__ */ React2.createElement(MessageItem, { key: msg.id, message: msg })), /* @__PURE__ */ React2.createElement("div", { ref: bottomRef }));
98
+ return /* @__PURE__ */ React2.createElement("div", { style: styles.container }, messages.map((msg) => /* @__PURE__ */ React2.createElement(MessageItem, { key: msg.id, message: msg })), isProcessing && /* @__PURE__ */ React2.createElement(TypingIndicator, null), /* @__PURE__ */ React2.createElement("div", { ref: bottomRef }));
99
99
  }
100
100
  function MessageItem({ message }) {
101
101
  switch (message.type) {
@@ -107,6 +107,8 @@ function MessageItem({ message }) {
107
107
  return /* @__PURE__ */ React2.createElement(OutputMessage, { data: message.data, replay: message.replay });
108
108
  case "complete":
109
109
  return /* @__PURE__ */ React2.createElement(CompleteMessage, { message });
110
+ case "cancelled":
111
+ return /* @__PURE__ */ React2.createElement(CancelledMessage, null);
110
112
  case "error":
111
113
  return /* @__PURE__ */ React2.createElement(ErrorMessage, { message });
112
114
  default:
@@ -211,9 +213,20 @@ function GenericOutputMessage({ data, replay }) {
211
213
  function CompleteMessage({ message }) {
212
214
  return /* @__PURE__ */ React2.createElement("div", { style: styles.systemRow }, /* @__PURE__ */ React2.createElement("div", { style: styles.completeBubble }, "Command completed (exit ", message.exitCode ?? "?", ")", message.durationMs != null && ` in ${(message.durationMs / 1e3).toFixed(1)}s`));
213
215
  }
216
+ function CancelledMessage() {
217
+ return /* @__PURE__ */ React2.createElement("div", { style: styles.resultRow }, /* @__PURE__ */ React2.createElement("div", { style: styles.cancelledBubble }, /* @__PURE__ */ React2.createElement("span", { style: styles.resultLabel }, "Cancelled")));
218
+ }
214
219
  function SkillInvocationMessage({ skill }) {
215
220
  return /* @__PURE__ */ React2.createElement("div", { style: styles.skillRow }, /* @__PURE__ */ React2.createElement("div", { style: styles.skillBubble }, /* @__PURE__ */ React2.createElement("span", { style: styles.skillIcon }, skill.icon), /* @__PURE__ */ React2.createElement("span", { style: styles.skillLabel }, "Skill: ", skill.label)));
216
221
  }
222
+ function TypingIndicator() {
223
+ return /* @__PURE__ */ React2.createElement("div", { style: styles.assistantRow }, /* @__PURE__ */ React2.createElement("style", null, `
224
+ @keyframes claude-typing-bounce {
225
+ 0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
226
+ 30% { opacity: 1; transform: translateY(-3px); }
227
+ }
228
+ `), /* @__PURE__ */ React2.createElement("div", { style: styles.typingBubble }, /* @__PURE__ */ React2.createElement("span", { style: styles.typingDot }), /* @__PURE__ */ React2.createElement("span", { style: { ...styles.typingDot, animationDelay: "0.2s" } }), /* @__PURE__ */ React2.createElement("span", { style: { ...styles.typingDot, animationDelay: "0.4s" } })));
229
+ }
217
230
  function ErrorMessage({ message }) {
218
231
  return /* @__PURE__ */ React2.createElement("div", { style: styles.errorRow }, /* @__PURE__ */ React2.createElement("div", { style: styles.errorBubble }, message.code && /* @__PURE__ */ React2.createElement("span", { style: styles.errorCode }, message.code, ": "), message.message || "Unknown error"));
219
232
  }
@@ -398,6 +411,29 @@ var styles = {
398
411
  fontSize: "11px",
399
412
  color: "#777"
400
413
  },
414
+ typingBubble: {
415
+ display: "flex",
416
+ alignItems: "center",
417
+ gap: "4px",
418
+ padding: "10px 14px",
419
+ borderRadius: "12px 12px 12px 2px",
420
+ backgroundColor: "#f0f0f0"
421
+ },
422
+ typingDot: {
423
+ width: "6px",
424
+ height: "6px",
425
+ borderRadius: "50%",
426
+ backgroundColor: "#999",
427
+ animation: "claude-typing-bounce 1.2s infinite"
428
+ },
429
+ cancelledBubble: {
430
+ padding: "6px 12px",
431
+ borderRadius: "8px",
432
+ backgroundColor: "#fff3e0",
433
+ fontSize: "12px",
434
+ color: "#e65100",
435
+ textAlign: "center"
436
+ },
401
437
  genericContent: {
402
438
  margin: 0,
403
439
  padding: "8px",
@@ -451,7 +487,7 @@ var styles = {
451
487
 
452
488
  // src/components/MessageInput.jsx
453
489
  import React3, { useState, useRef as useRef2 } from "react";
454
- function MessageInput({ onSend, disabled, isProcessing, placeholder }) {
490
+ function MessageInput({ onSend, disabled, isProcessing, placeholder, onCancel }) {
455
491
  const [text, setText] = useState("");
456
492
  const textareaRef = useRef2(null);
457
493
  const handleSend = () => {
@@ -464,7 +500,10 @@ function MessageInput({ onSend, disabled, isProcessing, placeholder }) {
464
500
  }
465
501
  };
466
502
  const handleKeyDown = (e) => {
467
- if (e.key === "Enter" && !e.shiftKey) {
503
+ if (e.key === "Escape" && isProcessing && onCancel) {
504
+ e.preventDefault();
505
+ onCancel();
506
+ } else if (e.key === "Enter" && !e.shiftKey) {
468
507
  e.preventDefault();
469
508
  handleSend();
470
509
  }
@@ -475,6 +514,29 @@ function MessageInput({ onSend, disabled, isProcessing, placeholder }) {
475
514
  el.style.height = "auto";
476
515
  el.style.height = Math.min(el.scrollHeight, 120) + "px";
477
516
  };
517
+ if (isProcessing && onCancel) {
518
+ return /* @__PURE__ */ React3.createElement("div", { style: styles2.container }, /* @__PURE__ */ React3.createElement(
519
+ "textarea",
520
+ {
521
+ ref: textareaRef,
522
+ style: styles2.textarea,
523
+ value: text,
524
+ onChange: handleInput,
525
+ onKeyDown: handleKeyDown,
526
+ placeholder: disabled ? "Connect to daemon first..." : placeholder || "Ask Claude...",
527
+ disabled: true,
528
+ rows: 1
529
+ }
530
+ ), /* @__PURE__ */ React3.createElement(
531
+ "button",
532
+ {
533
+ style: styles2.buttonCancel,
534
+ onClick: onCancel,
535
+ title: "Cancel response (Escape)"
536
+ },
537
+ "Cancel"
538
+ ));
539
+ }
478
540
  return /* @__PURE__ */ React3.createElement("div", { style: styles2.container }, /* @__PURE__ */ React3.createElement(
479
541
  "textarea",
480
542
  {
@@ -498,7 +560,7 @@ function MessageInput({ onSend, disabled, isProcessing, placeholder }) {
498
560
  disabled: disabled || !text.trim(),
499
561
  title: "Send message (Enter)"
500
562
  },
501
- isProcessing ? "..." : "Send"
563
+ "Send"
502
564
  ));
503
565
  }
504
566
  var styles2 = {
@@ -537,6 +599,18 @@ var styles2 = {
537
599
  buttonDisabled: {
538
600
  backgroundColor: "#ccc",
539
601
  cursor: "not-allowed"
602
+ },
603
+ buttonCancel: {
604
+ padding: "8px 16px",
605
+ border: "none",
606
+ borderRadius: "8px",
607
+ backgroundColor: "#e53e3e",
608
+ color: "#fff",
609
+ fontSize: "13px",
610
+ fontWeight: 600,
611
+ cursor: "pointer",
612
+ whiteSpace: "nowrap",
613
+ minHeight: "36px"
540
614
  }
541
615
  };
542
616
 
@@ -674,6 +748,7 @@ var WebSocketClient = class {
674
748
  this._host = options.host || DEFAULT_HOST;
675
749
  this._port = options.port || DEFAULT_PORT;
676
750
  this._token = options.token || null;
751
+ this._daemonUrl = options.daemonUrl || null;
677
752
  this._ws = null;
678
753
  this._state = CONNECTION_STATES.DISCONNECTED;
679
754
  this._listeners = /* @__PURE__ */ new Map();
@@ -693,7 +768,7 @@ var WebSocketClient = class {
693
768
  }
694
769
  /**
695
770
  * Register an event listener.
696
- * Events: 'state_change', 'session_activated', 'output', 'complete', 'error', 'pong'
771
+ * Events: 'state_change', 'session_activated', 'output', 'complete', 'error', 'pong', 'cancelled'
697
772
  */
698
773
  on(event, callback) {
699
774
  if (!this._listeners.has(event)) {
@@ -716,7 +791,7 @@ var WebSocketClient = class {
716
791
  this._setState(CONNECTION_STATES.CONNECTING);
717
792
  }
718
793
  const params = this._token ? `?token=${encodeURIComponent(this._token)}` : "";
719
- const url = `ws://${this._host}:${this._port}/${params}`;
794
+ const url = this._buildUrl(params);
720
795
  try {
721
796
  this._ws = new WebSocket(url);
722
797
  } catch (err) {
@@ -768,6 +843,12 @@ var WebSocketClient = class {
768
843
  setToken(token) {
769
844
  this._token = token;
770
845
  }
846
+ /**
847
+ * Update the daemon URL for remote environments.
848
+ */
849
+ setDaemonUrl(url) {
850
+ this._daemonUrl = url;
851
+ }
771
852
  /**
772
853
  * Activate a session. Must be called after connecting.
773
854
  */
@@ -798,6 +879,16 @@ var WebSocketClient = class {
798
879
  sessionId
799
880
  });
800
881
  }
882
+ /**
883
+ * Cancel a command in progress.
884
+ */
885
+ cancelCommand(sessionId, commandId) {
886
+ this._send({
887
+ type: "cancel",
888
+ sessionId,
889
+ commandId
890
+ });
891
+ }
801
892
  /**
802
893
  * Send a query to the daemon.
803
894
  */
@@ -810,6 +901,28 @@ var WebSocketClient = class {
810
901
  // ---------------------------------------------------------------------------
811
902
  // Internal
812
903
  // ---------------------------------------------------------------------------
904
+ /**
905
+ * Build the WebSocket URL. Priority:
906
+ * 1. Explicit `daemonUrl` option (fully custom URL)
907
+ * 2. Auto-detected Codespaces forwarded URL (derived from current hostname)
908
+ * 3. Local `ws://host:port/` fallback
909
+ */
910
+ _buildUrl(params) {
911
+ if (this._daemonUrl) {
912
+ const base = this._daemonUrl.replace(/\/$/, "");
913
+ return `${base}/${params}`;
914
+ }
915
+ if (typeof window !== "undefined" && window.location) {
916
+ const hostname = window.location.hostname;
917
+ const match = hostname.match(/^(.+)-(\d+)(\..*\.app\.github\.dev)$/);
918
+ if (match) {
919
+ const [, prefix, , suffix] = match;
920
+ const daemonHost = `${prefix}-${this._port}${suffix}`;
921
+ return `wss://${daemonHost}/${params}`;
922
+ }
923
+ }
924
+ return `ws://${this._host}:${this._port}/${params}`;
925
+ }
813
926
  _send(msg) {
814
927
  if (this._ws && this._ws.readyState === WebSocket.OPEN) {
815
928
  this._ws.send(JSON.stringify(msg));
@@ -831,6 +944,7 @@ var WebSocketClient = class {
831
944
  case "user_input":
832
945
  case "pong":
833
946
  case "query_result":
947
+ case "cancelled":
834
948
  this._emit(msg.type, msg);
835
949
  break;
836
950
  default:
@@ -922,6 +1036,7 @@ function useClaudeSession(options = {}) {
922
1036
  const clientRef = useRef3(null);
923
1037
  const sessionIdRef = useRef3(sessionId);
924
1038
  sessionIdRef.current = sessionId;
1039
+ const currentCommandIdRef = useRef3(null);
925
1040
  useEffect2(() => {
926
1041
  const client = new WebSocketClient({ host, port, token });
927
1042
  clientRef.current = client;
@@ -980,6 +1095,12 @@ function useClaudeSession(options = {}) {
980
1095
  { type: "error", ...msg, id: crypto.randomUUID(), timestamp: Date.now() }
981
1096
  ]);
982
1097
  setIsProcessing(false);
1098
+ }),
1099
+ client.on("cancelled", (msg) => {
1100
+ if (msg.sessionId !== sessionIdRef.current) return;
1101
+ setMessages((prev) => [...prev, { type: "cancelled", id: crypto.randomUUID(), timestamp: msg.timestamp, sessionId: msg.sessionId }]);
1102
+ setIsProcessing(false);
1103
+ currentCommandIdRef.current = null;
983
1104
  })
984
1105
  ];
985
1106
  return () => {
@@ -1019,7 +1140,9 @@ ${text}` : text;
1019
1140
  }
1020
1141
  ]);
1021
1142
  setIsProcessing(true);
1022
- client.sendCommand(sessionIdRef.current, fullText);
1143
+ const commandId = crypto.randomUUID();
1144
+ currentCommandIdRef.current = commandId;
1145
+ client.sendCommand(sessionIdRef.current, fullText, commandId);
1023
1146
  },
1024
1147
  []
1025
1148
  );
@@ -1061,6 +1184,12 @@ ${text}` : text;
1061
1184
  startSession();
1062
1185
  }
1063
1186
  }, [startSession]);
1187
+ const cancelCommand = useCallback(() => {
1188
+ const client = clientRef.current;
1189
+ const cmdId = currentCommandIdRef.current;
1190
+ if (!client || !client.isConnected || !sessionIdRef.current) return;
1191
+ client.cancelCommand(sessionIdRef.current, cmdId);
1192
+ }, []);
1064
1193
  return {
1065
1194
  connectionState,
1066
1195
  messages,
@@ -1073,44 +1202,42 @@ ${text}` : text;
1073
1202
  setMessages,
1074
1203
  disconnect,
1075
1204
  newChat,
1205
+ cancelCommand,
1076
1206
  isConnected: connectionState === CONNECTION_STATES.CONNECTED,
1077
1207
  client: clientRef.current
1078
1208
  };
1079
1209
  }
1080
1210
 
1081
- // src/useGitContext.js
1211
+ // src/useDaemonQuery.js
1082
1212
  import { useState as useState4, useEffect as useEffect3, useRef as useRef4, useCallback as useCallback2 } from "react";
1083
- function useGitContext(client, connectionState) {
1084
- const [gitData, setGitData] = useState4(null);
1085
- const [loading, setLoading] = useState4(false);
1213
+ function useDaemonQuery(client, connectionState, queryType, pollIntervalMs) {
1214
+ const [data, setData] = useState4(null);
1215
+ const [error, setError] = useState4(null);
1086
1216
  const intervalRef = useRef4(null);
1087
- const unsubRef = useRef4(null);
1088
- const fetchContext = useCallback2(() => {
1217
+ const dataRef = useRef4(null);
1218
+ const fetchQuery = useCallback2(() => {
1089
1219
  if (!client || !client.isConnected) return;
1090
- setLoading(true);
1091
- client.sendQuery("git_context");
1092
- }, [client]);
1220
+ client.sendQuery(queryType);
1221
+ }, [client, queryType]);
1093
1222
  useEffect3(() => {
1094
1223
  if (!client) return;
1095
1224
  const unsub = client.on("query_result", (msg) => {
1096
- if (msg.queryType === "git_context") {
1097
- setGitData(msg.data || null);
1098
- setLoading(false);
1225
+ if (msg.queryType === queryType) {
1226
+ dataRef.current = msg.data || null;
1227
+ setData(msg.data || null);
1228
+ setError(null);
1099
1229
  }
1100
1230
  });
1101
1231
  const unsubErr = client.on("error", (msg) => {
1102
1232
  if (msg.code === "UNKNOWN_TYPE" || msg.code === "UNKNOWN_QUERY") {
1103
- setLoading(false);
1233
+ setError(msg.message || "Unsupported query");
1104
1234
  }
1105
1235
  });
1106
- unsubRef.current = () => {
1236
+ return () => {
1107
1237
  unsub();
1108
1238
  unsubErr();
1109
1239
  };
1110
- return () => {
1111
- if (unsubRef.current) unsubRef.current();
1112
- };
1113
- }, [client]);
1240
+ }, [client, queryType]);
1114
1241
  useEffect3(() => {
1115
1242
  if (connectionState !== CONNECTION_STATES.CONNECTED) {
1116
1243
  if (intervalRef.current) {
@@ -1119,18 +1246,25 @@ function useGitContext(client, connectionState) {
1119
1246
  }
1120
1247
  return;
1121
1248
  }
1122
- fetchContext();
1123
- intervalRef.current = setInterval(fetchContext, 6e4);
1249
+ fetchQuery();
1250
+ intervalRef.current = setInterval(fetchQuery, pollIntervalMs);
1124
1251
  return () => {
1125
1252
  if (intervalRef.current) {
1126
1253
  clearInterval(intervalRef.current);
1127
1254
  intervalRef.current = null;
1128
1255
  }
1129
1256
  };
1130
- }, [connectionState, fetchContext]);
1257
+ }, [connectionState, fetchQuery, pollIntervalMs]);
1258
+ const loading = data === null && dataRef.current === null && error === null;
1259
+ return { data, loading, error };
1260
+ }
1261
+
1262
+ // src/useGitContext.js
1263
+ function useGitContext(client, connectionState) {
1264
+ const { data, loading } = useDaemonQuery(client, connectionState, "git_context", 6e4);
1131
1265
  return {
1132
- branch: (gitData == null ? void 0 : gitData.branch) || null,
1133
- pr: (gitData == null ? void 0 : gitData.pr) || null,
1266
+ branch: (data == null ? void 0 : data.branch) || null,
1267
+ pr: (data == null ? void 0 : data.pr) || null,
1134
1268
  loading
1135
1269
  };
1136
1270
  }
@@ -1202,6 +1336,7 @@ function ClaudePanel({ active }) {
1202
1336
  sendMessage,
1203
1337
  startSession,
1204
1338
  newChat,
1339
+ cancelCommand,
1205
1340
  isConnected,
1206
1341
  client
1207
1342
  } = useClaudeSession({
@@ -1256,12 +1391,13 @@ function ClaudePanel({ active }) {
1256
1391
  "aria-label": "New Chat"
1257
1392
  },
1258
1393
  "New Chat"
1259
- ))), /* @__PURE__ */ React5.createElement(MessageList, { messages }), /* @__PURE__ */ React5.createElement(
1394
+ ))), /* @__PURE__ */ React5.createElement(MessageList, { messages, isProcessing }), /* @__PURE__ */ React5.createElement(
1260
1395
  MessageInput,
1261
1396
  {
1262
1397
  onSend: handleSend,
1263
1398
  disabled: !isConnected,
1264
- isProcessing
1399
+ isProcessing,
1400
+ onCancel: cancelCommand
1265
1401
  }
1266
1402
  ));
1267
1403
  }
@@ -1280,6 +1416,9 @@ function getInitialPort() {
1280
1416
  function getInitialToken() {
1281
1417
  var _a, _b;
1282
1418
  try {
1419
+ if (typeof window !== "undefined" && window.__CLAUDE_DAEMON_TOKEN__) {
1420
+ return window.__CLAUDE_DAEMON_TOKEN__;
1421
+ }
1283
1422
  return typeof process !== "undefined" && ((_a = process.env) == null ? void 0 : _a.STORYBOOK_CLAUDE_DAEMON_TOKEN) || typeof process !== "undefined" && ((_b = process.env) == null ? void 0 : _b.CLAUDE_DAEMON_TOKEN) || null;
1284
1423
  } catch {
1285
1424
  return null;
@@ -1382,7 +1521,7 @@ function SkillsBar({ skills, onTrigger, disabled }) {
1382
1521
  },
1383
1522
  onClick: () => onTrigger(skill),
1384
1523
  disabled,
1385
- title: skill.prompt
1524
+ title: skill.description || skill.prompt
1386
1525
  },
1387
1526
  /* @__PURE__ */ React6.createElement("span", { style: styles5.icon }, skill.icon),
1388
1527
  /* @__PURE__ */ React6.createElement("span", null, skill.label)
@@ -1419,8 +1558,18 @@ var styles5 = {
1419
1558
  }
1420
1559
  };
1421
1560
 
1561
+ // src/useSkillsConfig.js
1562
+ function useSkillsConfig(client, connectionState) {
1563
+ const { data, loading } = useDaemonQuery(client, connectionState, "skills_config", 12e4);
1564
+ return {
1565
+ skills: (data == null ? void 0 : data.skills) || [],
1566
+ source: (data == null ? void 0 : data.source) || "none",
1567
+ loading
1568
+ };
1569
+ }
1570
+
1422
1571
  // src/skills.js
1423
- var STATIC_SKILLS = [
1572
+ var DEFAULT_SKILLS = [
1424
1573
  {
1425
1574
  id: "sync-components",
1426
1575
  label: "Sync Components",
@@ -1456,17 +1605,13 @@ function getPrSkill(pr) {
1456
1605
  prompt: "Create a new pull request for the current branch with a summary of all changes."
1457
1606
  };
1458
1607
  }
1459
- function getGlobalSkills(gitContext) {
1608
+ function getGlobalSkills(gitContext, configSkills) {
1460
1609
  const pr = (gitContext == null ? void 0 : gitContext.pr) || null;
1610
+ const skills = configSkills && configSkills.length > 0 ? configSkills : DEFAULT_SKILLS;
1461
1611
  return [
1462
- STATIC_SKILLS[0],
1463
- // Sync Components
1612
+ skills[0],
1464
1613
  getPrSkill(pr),
1465
- // New PR / Finalize PR
1466
- STATIC_SKILLS[1],
1467
- // Run Tests
1468
- STATIC_SKILLS[2]
1469
- // Audit Stories
1614
+ ...skills.slice(1)
1470
1615
  ];
1471
1616
  }
1472
1617
 
@@ -1490,6 +1635,7 @@ function GlobalPanel() {
1490
1635
  sendMessage,
1491
1636
  startSession,
1492
1637
  setMessages,
1638
+ cancelCommand,
1493
1639
  isConnected,
1494
1640
  client
1495
1641
  } = useClaudeSession({
@@ -1500,7 +1646,11 @@ function GlobalPanel() {
1500
1646
  storageKey: `${ADDON_ID}:globalSessionId`
1501
1647
  });
1502
1648
  const gitContext = useGitContext(client, connectionState);
1503
- const skills = useMemo2(() => getGlobalSkills(gitContext), [gitContext]);
1649
+ const skillsConfig = useSkillsConfig(client, connectionState);
1650
+ const skills = useMemo2(
1651
+ () => getGlobalSkills(gitContext, skillsConfig.skills),
1652
+ [gitContext, skillsConfig.skills]
1653
+ );
1504
1654
  const handleTokenSubmit = useCallback4(
1505
1655
  (newToken, newPort) => {
1506
1656
  setAddonState({ ...addonState, token: newToken, port: newPort || DEFAULT_PORT });
@@ -1554,13 +1704,14 @@ function GlobalPanel() {
1554
1704
  },
1555
1705
  "PR #",
1556
1706
  gitContext.pr.number
1557
- ))), /* @__PURE__ */ React7.createElement("div", { style: styles6.chatArea }, /* @__PURE__ */ React7.createElement(MessageList, { messages }), /* @__PURE__ */ React7.createElement(
1707
+ ))), /* @__PURE__ */ React7.createElement("div", { style: styles6.chatArea }, /* @__PURE__ */ React7.createElement(MessageList, { messages, isProcessing }), /* @__PURE__ */ React7.createElement(
1558
1708
  MessageInput,
1559
1709
  {
1560
1710
  onSend: handleSend,
1561
1711
  disabled: !isConnected,
1562
1712
  isProcessing,
1563
- placeholder: "Ask Claude about your project..."
1713
+ placeholder: "Ask Claude about your project...",
1714
+ onCancel: cancelCommand
1564
1715
  }
1565
1716
  )));
1566
1717
  }
@@ -1579,6 +1730,9 @@ function getInitialPort2() {
1579
1730
  function getInitialToken2() {
1580
1731
  var _a, _b;
1581
1732
  try {
1733
+ if (typeof window !== "undefined" && window.__CLAUDE_DAEMON_TOKEN__) {
1734
+ return window.__CLAUDE_DAEMON_TOKEN__;
1735
+ }
1582
1736
  return typeof process !== "undefined" && ((_a = process.env) == null ? void 0 : _a.STORYBOOK_CLAUDE_DAEMON_TOKEN) || typeof process !== "undefined" && ((_b = process.env) == null ? void 0 : _b.CLAUDE_DAEMON_TOKEN) || null;
1583
1737
  } catch {
1584
1738
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radnine/storybook-addon-claude",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "description": "Storybook addon panel for chatting with Claude via the standalone daemon",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {