@ai-matrx/coding-sessions 0.1.81 → 0.1.85

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.
@@ -34,10 +34,10 @@ __export(react_exports, {
34
34
  module.exports = __toCommonJS(react_exports);
35
35
 
36
36
  // src/react/app.tsx
37
- var import_react6 = require("react");
38
- var import_react7 = require("@ai-matrx/chat/react");
37
+ var import_react8 = require("react");
38
+ var import_react9 = require("@ai-matrx/chat/react");
39
39
  var import_external_store2 = require("@ai-matrx/chat/external-store");
40
- var import_design_system5 = require("@ai-matrx/design-system");
40
+ var import_design_system6 = require("@ai-matrx/design-system");
41
41
  var import_format3 = require("@ai-matrx/kit/format");
42
42
 
43
43
  // src/types.ts
@@ -60,6 +60,21 @@ function formatUntil(until) {
60
60
  if (Number.isNaN(ms)) return until;
61
61
  return new Date(ms).toLocaleString(void 0, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
62
62
  }
63
+ var MODEL_UNAVAILABLE = [
64
+ /model is not supported when using codex/i,
65
+ /\bmodel[\s:'"`][^.\n]{0,80}\b(?:not supported|does not exist|not available|not found)\b/i,
66
+ /\bmodel_not_found\b/i,
67
+ /issue with the selected model/i,
68
+ /may not exist or you may not have access to it/i
69
+ ];
70
+ var MODEL_UNAVAILABLE_LABEL = "Model not available on this account";
71
+ function isModelUnavailable(text) {
72
+ const trimmed = (text ?? "").trim();
73
+ return trimmed !== "" && MODEL_UNAVAILABLE.some((re) => re.test(trimmed));
74
+ }
75
+ function runErrorLabel(text) {
76
+ return isModelUnavailable(text) ? MODEL_UNAVAILABLE_LABEL : text;
77
+ }
63
78
 
64
79
  // src/tool-labels.ts
65
80
  var BUILTIN = {
@@ -471,14 +486,20 @@ var SpinnerIcon = ({ size = 16, className }) => /* @__PURE__ */ (0, import_jsx_r
471
486
  ]
472
487
  }
473
488
  );
474
- function ProviderMark({ provider, size = 18 }) {
489
+ var CLAUDE_MARK = "m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z";
490
+ var OPENAI_MARK = "M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z";
491
+ function ProviderMark({ provider, size = 16 }) {
475
492
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
476
- "span",
493
+ "svg",
477
494
  {
478
495
  className: `cs-provider-mark cs-provider-mark--${provider}`,
479
- style: { width: size, height: size, fontSize: Math.round(size * 0.58) },
496
+ width: size,
497
+ height: size,
498
+ viewBox: "0 0 24 24",
499
+ fill: "currentColor",
480
500
  "aria-hidden": "true",
481
- children: provider === "claude" ? "C" : "X"
501
+ "data-provider-mark": provider,
502
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: provider === "claude" ? CLAUDE_MARK : OPENAI_MARK })
482
503
  }
483
504
  );
484
505
  }
@@ -875,10 +896,217 @@ function ModelPicker(props) {
875
896
  ] });
876
897
  }
877
898
 
878
- // src/react/sidebar.tsx
899
+ // src/react/agent-field.tsx
879
900
  var import_react5 = require("react");
901
+ var import_agents = require("@ai-matrx/agents");
902
+ var import_catalog = require("@ai-matrx/agents/catalog");
903
+ var import_react6 = require("@ai-matrx/agents/catalog/react");
904
+ var import_context = require("@ai-matrx/agents/context");
880
905
  var import_design_system4 = require("@ai-matrx/design-system");
881
906
  var import_jsx_runtime5 = require("react/jsx-runtime");
907
+ var SIGNED_OUT_AGENTS = "Sign in to AI Matrx to use your agents";
908
+ var LATEST = "latest";
909
+ function bridgedClient(transport) {
910
+ const call = (request) => {
911
+ const run = () => transport.call("agentCatalogRpc", request).then((result) => ({
912
+ data: result.data,
913
+ error: result.error ? {
914
+ message: result.error.message,
915
+ ...result.error.code ? { code: result.error.code } : {},
916
+ details: result.error.details ?? null,
917
+ hint: result.error.hint ?? null
918
+ } : null,
919
+ count: result.count ?? null
920
+ }));
921
+ return {
922
+ then: (onOk, onErr) => run().then(onOk, onErr),
923
+ range: (from, to) => call({ ...request, range: [from, to] }),
924
+ order: (column, options) => call({ ...request, order: { column, ascending: options?.ascending !== false } })
925
+ };
926
+ };
927
+ return {
928
+ rpc: (fn, args, options) => call({ fn, ...args ? { args } : {}, ...options?.count ? { count: options.count } : {} })
929
+ };
930
+ }
931
+ function useAgentAccess(transport, open) {
932
+ const [access, setAccess] = (0, import_react5.useState)(null);
933
+ (0, import_react5.useEffect)(() => {
934
+ if (!open) return;
935
+ let alive = true;
936
+ transport.call("agentAccess").then((next) => alive && setAccess(next)).catch(() => alive && setAccess({ signedIn: false, userId: null, organizationId: null, configured: false }));
937
+ return () => {
938
+ alive = false;
939
+ };
940
+ }, [transport, open]);
941
+ return access;
942
+ }
943
+ function useCatalog(transport, userId, onError) {
944
+ const report = (0, import_react5.useRef)(onError);
945
+ report.current = onError;
946
+ return (0, import_react5.useMemo)(() => {
947
+ if (!userId) return null;
948
+ return (0, import_catalog.createAgentCatalog)({
949
+ client: bridgedClient(transport),
950
+ identity: { requireUserId: () => userId, getUserId: () => userId },
951
+ catalogId: `coding-sessions:${userId}`,
952
+ // A failed catalogue read shows at the field, never only in the console.
953
+ errorSink: (event) => {
954
+ console.error(`[coding-sessions] agent catalogue: ${event.code}: ${event.message}`);
955
+ if (event.code === "list_read_failed") report.current("Couldn't load your agents. Reopen to retry.");
956
+ }
957
+ });
958
+ }, [transport, userId]);
959
+ }
960
+ function asRunInputVariables(defs) {
961
+ return defs.flatMap((def) => typeof def.name === "string" ? [def] : []);
962
+ }
963
+ function AgentField(props) {
964
+ const access = useAgentAccess(props.transport, props.open);
965
+ const [details, setDetails] = (0, import_react5.useState)(null);
966
+ const [problem, setProblem] = (0, import_react5.useState)(null);
967
+ const catalog = useCatalog(props.transport, access?.signedIn ? access.userId : null, setProblem);
968
+ const agentId = props.value?.agentId ?? null;
969
+ (0, import_react5.useEffect)(() => {
970
+ setDetails(null);
971
+ setProblem(null);
972
+ if (!agentId) return;
973
+ let alive = true;
974
+ props.transport.call("agentDetails", agentId).then((next) => alive && setDetails(next)).catch((error) => alive && setProblem(error instanceof Error ? error.message : String(error)));
975
+ return () => {
976
+ alive = false;
977
+ };
978
+ }, [agentId, props.transport]);
979
+ const { onDetails } = props;
980
+ (0, import_react5.useEffect)(() => {
981
+ onDetails?.(details);
982
+ }, [details, onDetails]);
983
+ const inputs = (0, import_react5.useMemo)(() => (0, import_agents.deriveRunInputs)(asRunInputVariables(details?.variables ?? []), import_context.humanizeContextKey), [details]);
984
+ if (access === null) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cs-skeleton h-9 rounded-lg" });
985
+ if (!access.signedIn || !catalog) {
986
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[12.5px] text-muted-foreground", children: SIGNED_OUT_AGENTS });
987
+ }
988
+ const setVariable = (name, value) => {
989
+ if (!props.value) return;
990
+ props.onChange({ ...props.value, variables: { ...props.value.variables ?? {}, [name]: value } });
991
+ };
992
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-3", children: [
993
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
994
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react6.AgentCatalogProvider, { catalog, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
995
+ import_react6.AgentListDropdown,
996
+ {
997
+ consumerId: "coding-sessions-new-session",
998
+ activeAgentId: agentId,
999
+ label: details?.name ?? (agentId ? "Loading\u2026" : "None"),
1000
+ onSelect: (id) => props.onChange({ agentId: id, versionId: null, variables: {} })
1001
+ }
1002
+ ) }) }),
1003
+ agentId ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Button, { type: "button", size: "sm", variant: "ghost", onClick: () => props.onChange(null), children: "Remove" }) : null
1004
+ ] }),
1005
+ problem ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[12px] text-destructive", children: problem }) : null,
1006
+ details && props.value ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1007
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
1008
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-[72px] shrink-0 text-[12px] text-muted-foreground", children: "Version" }),
1009
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1010
+ import_design_system4.Select,
1011
+ {
1012
+ value: props.value.versionId ?? LATEST,
1013
+ onValueChange: (next) => props.value && props.onChange({ ...props.value, versionId: next === LATEST ? null : next }),
1014
+ children: [
1015
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectTrigger, { className: "h-8 w-[200px] text-[12.5px]", "aria-label": "Agent version", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectValue, {}) }),
1016
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.SelectContent, { children: [
1017
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectItem, { value: LATEST, children: details.latestVersionNumber !== null ? `Latest (v${details.latestVersionNumber})` : "Latest" }),
1018
+ details.versions.map((v) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.SelectItem, { value: v.id, children: [
1019
+ "v",
1020
+ v.versionNumber
1021
+ ] }, v.id))
1022
+ ] })
1023
+ ]
1024
+ }
1025
+ )
1026
+ ] }),
1027
+ inputs.map((input) => {
1028
+ const raw = props.value?.variables?.[input.name];
1029
+ const value = typeof raw === "string" ? raw : "";
1030
+ const id = `cs-agent-var-${input.name}`;
1031
+ const invalid = props.missing === input.name;
1032
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-1", children: [
1033
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { htmlFor: id, className: "text-[12px] font-medium", children: [
1034
+ input.label,
1035
+ input.required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-muted-foreground", children: " \xB7 required" }) : null
1036
+ ] }),
1037
+ input.options && input.options.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.Select, { value, onValueChange: (next) => setVariable(input.name, next), children: [
1038
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectTrigger, { id, className: "h-8 text-[12.5px]", "aria-invalid": invalid || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectValue, { placeholder: "Choose\u2026" }) }),
1039
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectContent, { children: input.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectItem, { value: option, children: option }, option)) })
1040
+ ] }) : input.variable.customComponent?.type === "textarea" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1041
+ import_design_system4.Textarea,
1042
+ {
1043
+ id,
1044
+ rows: 2,
1045
+ value,
1046
+ onChange: (e) => setVariable(input.name, e.target.value),
1047
+ placeholder: input.hint ?? "",
1048
+ "aria-invalid": invalid || void 0
1049
+ }
1050
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1051
+ import_design_system4.Input,
1052
+ {
1053
+ id,
1054
+ value,
1055
+ onChange: (e) => setVariable(input.name, e.target.value),
1056
+ placeholder: input.hint ?? "",
1057
+ "aria-invalid": invalid || void 0
1058
+ }
1059
+ ),
1060
+ invalid ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[12px] text-destructive", children: "Fill this in to use the agent" }) : null
1061
+ ] }, input.name);
1062
+ })
1063
+ ] }) : null
1064
+ ] });
1065
+ }
1066
+ function missingRequiredVariable(details, selection) {
1067
+ if (!details || !selection) return null;
1068
+ for (const input of (0, import_agents.deriveRunInputs)(asRunInputVariables(details.variables), import_context.humanizeContextKey)) {
1069
+ if (!input.required) continue;
1070
+ const value = selection.variables?.[input.name];
1071
+ if (typeof value !== "string" || !value.trim()) return input.name;
1072
+ }
1073
+ return null;
1074
+ }
1075
+ var PART_LABEL = {
1076
+ instructions: "Instructions",
1077
+ skills: "Skills",
1078
+ tools: "Tools"
1079
+ };
1080
+ function AgentChip({ agent }) {
1081
+ const parts = agent.loaded.map(
1082
+ (part) => part.part === "instructions" ? `${PART_LABEL.instructions} ${part.loaded === 1 ? "\u2713" : "\u2014"}` : `${PART_LABEL[part.part]} ${part.loaded}/${part.total}`
1083
+ );
1084
+ const missing = agent.unavailable.slice(0, 6).map((u) => `${u.name}: ${u.reason}`);
1085
+ const more = agent.unavailable.length > 6 ? [`+${agent.unavailable.length - 6} more`] : [];
1086
+ const complete = agent.loaded.every((part) => part.loaded === part.total);
1087
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1088
+ "span",
1089
+ {
1090
+ className: (0, import_design_system4.cn)("cs-agent-chip", !complete && "cs-agent-chip--partial"),
1091
+ title: missing.length ? [...missing, ...more].join("\n") : "Everything loaded",
1092
+ "data-testid": "cs-agent-chip",
1093
+ children: [
1094
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "font-medium text-foreground", children: [
1095
+ agent.name,
1096
+ agent.versionNumber !== null ? ` v${agent.versionNumber}` : ""
1097
+ ] }),
1098
+ " ",
1099
+ "\xB7 ",
1100
+ parts.join(" \xB7 ")
1101
+ ]
1102
+ }
1103
+ );
1104
+ }
1105
+
1106
+ // src/react/sidebar.tsx
1107
+ var import_react7 = require("react");
1108
+ var import_design_system5 = require("@ai-matrx/design-system");
1109
+ var import_jsx_runtime6 = require("react/jsx-runtime");
882
1110
  function readLocal(key, allowed, fallback) {
883
1111
  try {
884
1112
  const value = localStorage.getItem(key);
@@ -894,23 +1122,23 @@ function writeLocal(key, value) {
894
1122
  }
895
1123
  }
896
1124
  function SectionLabel({ children, action }) {
897
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex h-8 items-center justify-between px-3 pt-3", children: [
898
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-[11px] font-medium uppercase tracking-[0.06em] text-muted-foreground", children }),
1125
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-cs-section-label": true, className: "flex h-8 items-center justify-between px-3 pt-3", children: [
1126
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[12px] font-medium text-muted-foreground", children }),
899
1127
  action
900
1128
  ] });
901
1129
  }
902
1130
  function GroupLabel({ children }) {
903
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "truncate px-4 pb-0.5 pt-2.5 text-[11px] font-medium text-muted-foreground/80", children });
1131
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "truncate px-4 pb-0.5 pt-2.5 text-[12px] font-medium text-muted-foreground", children });
904
1132
  }
905
1133
  function RenameInput(props) {
906
- const [value, setValue] = (0, import_react5.useState)(props.initial);
907
- const done = (0, import_react5.useRef)(false);
1134
+ const [value, setValue] = (0, import_react7.useState)(props.initial);
1135
+ const done = (0, import_react7.useRef)(false);
908
1136
  const finish = (title) => {
909
1137
  if (done.current) return;
910
1138
  done.current = true;
911
1139
  props.onDone(title);
912
1140
  };
913
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1141
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
914
1142
  "input",
915
1143
  {
916
1144
  autoFocus: true,
@@ -927,11 +1155,16 @@ function RenameInput(props) {
927
1155
  }
928
1156
  );
929
1157
  }
1158
+ function entryTarget(entry) {
1159
+ if (entry.kind === "session" && entry.session) return `#s/${entry.session.id}`;
1160
+ if (entry.providerSessionId) return `#d/${entry.provider}/${entry.providerSessionId}`;
1161
+ return "";
1162
+ }
930
1163
  function Row(props) {
931
1164
  const client = useCodingSessionsClient();
932
1165
  const show = useToastShow();
933
- const [renaming, setRenaming] = (0, import_react5.useState)(false);
934
- const [menuOpen, setMenuOpen] = (0, import_react5.useState)(false);
1166
+ const [renaming, setRenaming] = (0, import_react7.useState)(false);
1167
+ const [menuOpen, setMenuOpen] = (0, import_react7.useState)(false);
935
1168
  const { entry } = props;
936
1169
  const rename = (title) => {
937
1170
  setRenaming(false);
@@ -941,14 +1174,20 @@ function Row(props) {
941
1174
  (error) => show(`The new name didn't save: ${error instanceof Error ? error.message : String(error)}`)
942
1175
  );
943
1176
  };
944
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.ContextMenu, { children: [
945
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.ContextMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1177
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.ContextMenu, { children: [
1178
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.ContextMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
946
1179
  "div",
947
1180
  {
948
- className: (0, import_design_system4.cn)("cs-row group", props.active && "cs-row--active", menuOpen && "cs-row--menu"),
1181
+ className: (0, import_design_system5.cn)("cs-row group", props.active && "cs-row--active", menuOpen && "cs-row--menu"),
949
1182
  "data-hidden": entry.hidden || void 0,
1183
+ "data-cs-row": entry.key,
1184
+ "data-cs-target": entryTarget(entry),
1185
+ "data-cs-provider": entry.provider,
1186
+ "data-cs-title": entry.title,
1187
+ "data-cs-live": props.live ? "true" : void 0,
1188
+ "data-cs-active": props.active ? "true" : void 0,
950
1189
  children: [
951
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1190
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
952
1191
  "button",
953
1192
  {
954
1193
  type: "button",
@@ -960,39 +1199,39 @@ function Row(props) {
960
1199
  (${entry.originalTitle})` : entry.title
961
1200
  }
962
1201
  ),
963
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pointer-events-none mt-0.5 shrink-0", children: props.live ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SpinnerIcon, { size: 16, className: "text-primary" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ProviderMark, { provider: entry.provider, size: 16 }) }),
964
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "cs-row__body", children: [
965
- renaming ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pointer-events-auto relative z-10 block", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RenameInput, { initial: entry.title, onDone: rename }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "flex items-center gap-1", children: [
966
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "min-w-0 truncate text-[13px] font-medium leading-5", children: entry.title }),
967
- entry.pinned ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PinIcon, { size: 11, className: "shrink-0 text-muted-foreground", "aria-label": "Pinned" }) : null
1202
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "pointer-events-none mt-0.5 shrink-0", children: props.live ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 16, className: "text-primary" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProviderMark, { provider: entry.provider, size: 16 }) }),
1203
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "cs-row__body", children: [
1204
+ renaming ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "pointer-events-auto relative z-10 block", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RenameInput, { initial: entry.title, onDone: rename }) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-center gap-1", children: [
1205
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "min-w-0 truncate text-[13px] font-medium leading-5", children: entry.title }),
1206
+ entry.pinned ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PinIcon, { size: 11, className: "shrink-0 text-muted-foreground", "aria-label": "Pinned" }) : null
968
1207
  ] }),
969
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "block truncate text-[11.5px] leading-4 text-muted-foreground", children: props.meta }),
970
- props.snippet ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "cs-row__snippet", children: props.snippet }) : null
1208
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "block truncate text-[11.5px] leading-4 text-muted-foreground", children: props.meta }),
1209
+ props.snippet ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "cs-row__snippet", children: props.snippet }) : null
971
1210
  ] }),
972
- renaming ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "cs-row__actions", children: [
1211
+ renaming ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "cs-row__actions", children: [
973
1212
  props.takeover,
974
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [
975
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "cs-icon-button", "aria-label": `More for ${entry.title}`, title: "More", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MoreIcon, { size: 15 }) }) }),
976
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuContent, { align: "start", className: "w-60", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChatMenuItems, { entry, variant: "dropdown", onRename: () => setRenaming(true) }) })
1213
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [
1214
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "cs-icon-button", "aria-label": `More for ${entry.title}`, title: "More", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MoreIcon, { size: 15 }) }) }),
1215
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuContent, { align: "start", className: "w-60", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatMenuItems, { entry, variant: "dropdown", onRename: () => setRenaming(true) }) })
977
1216
  ] })
978
1217
  ] })
979
1218
  ]
980
1219
  }
981
1220
  ) }),
982
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.ContextMenuContent, { className: "w-60", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChatMenuItems, { entry, variant: "context", onRename: () => setRenaming(true) }) })
1221
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.ContextMenuContent, { className: "w-60", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatMenuItems, { entry, variant: "context", onRename: () => setRenaming(true) }) })
983
1222
  ] });
984
1223
  }
985
1224
  function SidebarSkeleton() {
986
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "space-y-1.5 px-3 py-2", "aria-hidden": "true", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cs-skeleton h-9 rounded-lg" }, i)) });
1225
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "space-y-1.5 px-3 py-2", "aria-hidden": "true", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "cs-skeleton h-9 rounded-lg" }, i)) });
987
1226
  }
988
1227
  function Highlight({ text, query }) {
989
1228
  const q = query.trim().toLowerCase();
990
1229
  if (!q) return text;
991
1230
  const at = text.toLowerCase().indexOf(q);
992
1231
  if (at < 0) return text;
993
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1232
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
994
1233
  text.slice(0, at),
995
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("mark", { className: "cs-mark", children: text.slice(at, at + q.length) }),
1234
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("mark", { className: "cs-mark", children: text.slice(at, at + q.length) }),
996
1235
  text.slice(at + q.length)
997
1236
  ] });
998
1237
  }
@@ -1007,10 +1246,10 @@ var EMPTY_SEARCH = {
1007
1246
  };
1008
1247
  function useContentSearch(query) {
1009
1248
  const client = useCodingSessionsClient();
1010
- const [state, setState] = (0, import_react5.useState)(EMPTY_SEARCH);
1011
- const latest = (0, import_react5.useRef)(query);
1249
+ const [state, setState] = (0, import_react7.useState)(EMPTY_SEARCH);
1250
+ const latest = (0, import_react7.useRef)(query);
1012
1251
  latest.current = query;
1013
- const run = (0, import_react5.useCallback)(
1252
+ const run = (0, import_react7.useCallback)(
1014
1253
  async (q, cursor, append) => {
1015
1254
  setState((s) => ({ ...append ? s : EMPTY_SEARCH, query: q, loading: true, error: null }));
1016
1255
  try {
@@ -1032,7 +1271,7 @@ function useContentSearch(query) {
1032
1271
  },
1033
1272
  [client]
1034
1273
  );
1035
- (0, import_react5.useEffect)(() => {
1274
+ (0, import_react7.useEffect)(() => {
1036
1275
  const q = query.trim();
1037
1276
  if (q.length < 2) {
1038
1277
  setState(EMPTY_SEARCH);
@@ -1041,7 +1280,7 @@ function useContentSearch(query) {
1041
1280
  const timer = setTimeout(() => void run(q, 0, false), 350);
1042
1281
  return () => clearTimeout(timer);
1043
1282
  }, [query, run]);
1044
- const more = (0, import_react5.useCallback)(() => {
1283
+ const more = (0, import_react7.useCallback)(() => {
1045
1284
  if (state.nextCursor !== null && !state.loading) void run(state.query, state.nextCursor, true);
1046
1285
  }, [run, state.nextCursor, state.loading, state.query]);
1047
1286
  return [state, more];
@@ -1061,19 +1300,19 @@ function Sidebar(props) {
1061
1300
  const client = useCodingSessionsClient();
1062
1301
  const state = useCodingSessionsState();
1063
1302
  const now = useMinuteClock();
1064
- const [query, setQuery] = (0, import_react5.useState)("");
1303
+ const [query, setQuery] = (0, import_react7.useState)("");
1065
1304
  const [search, searchMore] = useContentSearch(query);
1066
- const [groupMode, setGroupMode] = (0, import_react5.useState)(() => readLocal("coding-sessions.group", ["date", "folder"], "date"));
1067
- const [showHidden, setShowHidden] = (0, import_react5.useState)(false);
1068
- const [takingOver, setTakingOver] = (0, import_react5.useState)(null);
1069
- const [takeoverError, setTakeoverError] = (0, import_react5.useState)(null);
1305
+ const [groupMode, setGroupMode] = (0, import_react7.useState)(() => readLocal("coding-sessions.group", ["date", "folder"], "date"));
1306
+ const [showHidden, setShowHidden] = (0, import_react7.useState)(false);
1307
+ const [takingOver, setTakingOver] = (0, import_react7.useState)(null);
1308
+ const [takeoverError, setTakeoverError] = (0, import_react7.useState)(null);
1070
1309
  const prefs = state.preferences;
1071
1310
  const sessions = state.sessions.data;
1072
1311
  const isLive = (id) => {
1073
1312
  const run = state.runs[id];
1074
1313
  return run !== void 0 && !isTerminalRunStatus(run.status);
1075
1314
  };
1076
- const { ours, others, hiddenCount } = (0, import_react5.useMemo)(() => {
1315
+ const { ours, others, hiddenCount } = (0, import_react7.useMemo)(() => {
1077
1316
  const oursList = sessions.map((s) => sessionEntry(s, prefs));
1078
1317
  const known = new Set(sessions.map((s) => s.providerSessionId).filter(Boolean));
1079
1318
  const othersList = state.discovered.data.filter((d) => !known.has(d.providerSessionId)).map((d) => discoveredEntry(d, prefs));
@@ -1113,8 +1352,8 @@ function Sidebar(props) {
1113
1352
  let meta;
1114
1353
  if (live) meta = `${PROVIDER_LABEL[entry.provider]} is working\u2026`;
1115
1354
  else if (d?.activeElsewhere)
1116
- meta = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "cs-live-elsewhere", children: [
1117
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "cs-live-dot", "aria-hidden": "true" }),
1355
+ meta = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "cs-live-elsewhere", children: [
1356
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "cs-live-dot", "aria-hidden": "true" }),
1118
1357
  "Running in ",
1119
1358
  PROVIDER_LABEL[entry.provider]
1120
1359
  ] });
@@ -1123,8 +1362,8 @@ function Sidebar(props) {
1123
1362
  const where = entry.cwd ? prettyPath2(entry.cwd) : "unknown folder";
1124
1363
  meta = `${status}${entry.kind === "discovered" ? `${PROVIDER_LABEL[entry.provider]} \xB7 ` : ""}${groupMode === "folder" && !extra ? "" : `${where} \xB7 `}${relativeTime(entry.updatedAt, now)}`;
1125
1364
  }
1126
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
1127
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1365
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1366
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1128
1367
  Row,
1129
1368
  {
1130
1369
  entry,
@@ -1133,7 +1372,7 @@ function Sidebar(props) {
1133
1372
  live,
1134
1373
  meta,
1135
1374
  snippet: extra?.snippet,
1136
- takeover: d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1375
+ takeover: d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1137
1376
  "button",
1138
1377
  {
1139
1378
  type: "button",
@@ -1142,18 +1381,18 @@ function Sidebar(props) {
1142
1381
  title: d.activeElsewhere ? d.activeElsewhere.message : "Continue this chat here",
1143
1382
  disabled: takingOver === d.providerSessionId,
1144
1383
  children: [
1145
- takingOver === d.providerSessionId ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SpinnerIcon, { size: 11 }) : null,
1384
+ takingOver === d.providerSessionId ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 11 }) : null,
1146
1385
  "Take over"
1147
1386
  ]
1148
1387
  }
1149
1388
  ) : null
1150
1389
  }
1151
1390
  ),
1152
- takeoverError && d && takeoverError.id === d.providerSessionId ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-4 mb-1 text-[11.5px] text-destructive", children: takeoverError.message }) : null
1391
+ takeoverError && d && takeoverError.id === d.providerSessionId ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-4 mb-1 text-[11.5px] text-destructive", children: takeoverError.message }) : null
1153
1392
  ] }, entry.key);
1154
1393
  };
1155
- const renderGroups = (entries) => groupEntries(entries, groupMode, now).map((group) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { role: "group", "aria-label": group.label, children: [
1156
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GroupLabel, { children: group.label }),
1394
+ const renderGroups = (entries) => groupEntries(entries, groupMode, now).map((group) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "group", "aria-label": group.label, children: [
1395
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(GroupLabel, { children: group.label }),
1157
1396
  group.entries.map((e) => renderEntry(e))
1158
1397
  ] }, group.label));
1159
1398
  const searching = query.trim().length > 0;
@@ -1170,60 +1409,60 @@ function Sidebar(props) {
1170
1409
  props.onFound(hitToDiscovered(hit));
1171
1410
  props.select({ kind: "discovered", provider: hit.provider, id: hit.providerSessionId });
1172
1411
  };
1173
- const searchBody = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1174
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SectionLabel, { children: "Chats" }),
1175
- titleMatches.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "px-4 py-1 text-[12px] text-muted-foreground", children: "No listed chat has that in its name or folder." }) : titleMatches.map((e) => renderEntry(e, { query })),
1176
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SectionLabel, { children: "In conversations" }),
1177
- query.trim().length < 2 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "px-4 py-1 text-[12px] text-muted-foreground", children: "Type at least two letters to search what was said." }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1412
+ const searchBody = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1413
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Chats" }),
1414
+ titleMatches.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] text-muted-foreground", children: "No listed chat has that in its name or folder." }) : titleMatches.map((e) => renderEntry(e, { query })),
1415
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "In conversations" }),
1416
+ query.trim().length < 2 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] text-muted-foreground", children: "Type at least two letters to search what was said." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1178
1417
  contentHits.map((hit) => {
1179
1418
  const known = allByKey.get(chatKey(hit.provider, hit.providerSessionId));
1180
1419
  const entry = known ?? discoveredEntry(hitToDiscovered(hit), prefs);
1181
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { onClickCapture: known ? void 0 : () => props.onFound(hitToDiscovered(hit)), children: renderEntry(entry, {
1420
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { onClickCapture: known ? void 0 : () => props.onFound(hitToDiscovered(hit)), children: renderEntry(entry, {
1182
1421
  query,
1183
- snippet: hit.snippet ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Highlight, { text: hit.snippet, query }) : void 0
1422
+ snippet: hit.snippet ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Highlight, { text: hit.snippet, query }) : void 0
1184
1423
  }) }, `hit:${entry.key}`);
1185
1424
  }),
1186
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "px-4 py-2 text-[11.5px] leading-4 text-muted-foreground", role: "status", "aria-live": "polite", children: search.error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "text-destructive", children: [
1425
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-4 py-2 text-[11.5px] leading-4 text-muted-foreground", role: "status", "aria-live": "polite", children: search.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-destructive", children: [
1187
1426
  "Search stopped: ",
1188
1427
  search.error
1189
- ] }) : search.loading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "inline-flex items-center gap-1.5", children: [
1190
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SpinnerIcon, { size: 12 }),
1428
+ ] }) : search.loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "inline-flex items-center gap-1.5", children: [
1429
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 12 }),
1191
1430
  " Searching your chats\u2026"
1192
- ] }) : search.query ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1431
+ ] }) : search.query ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1193
1432
  contentHits.length === 0 && search.hits.length === 0 ? "Nothing found. " : null,
1194
1433
  search.nextCursor === null ? `Searched all ${search.total.toLocaleString()} chats on this computer.` : `Searched the ${search.scanned.toLocaleString()} most recent of ${search.total.toLocaleString()} chats.`,
1195
- search.nextCursor !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "cs-link ml-1", onClick: searchMore, children: "Search older chats" }) : null
1434
+ search.nextCursor !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "cs-link ml-1", onClick: searchMore, children: "Search older chats" }) : null
1196
1435
  ] }) : null })
1197
1436
  ] })
1198
1437
  ] });
1199
- const listBody = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1200
- pinned.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1201
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SectionLabel, { children: "Pinned" }),
1438
+ const listBody = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1439
+ pinned.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1440
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Pinned" }),
1202
1441
  pinned.map((e) => renderEntry(e))
1203
1442
  ] }) : null,
1204
- running.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1205
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SectionLabel, { children: "Running" }),
1443
+ running.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1444
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Running" }),
1206
1445
  running.map((e) => renderEntry(e))
1207
1446
  ] }) : null,
1208
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SectionLabel, { children: "Recent" }),
1209
- state.sessions.loading && state.sessions.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SidebarSkeleton, {}) : state.sessions.error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "px-4 py-1 text-[12px] text-destructive", children: state.sessions.error }) : recent.length === 0 ? running.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "px-4 py-1 text-[12px] leading-5 text-muted-foreground", children: "Sessions you start or take over here will appear here." }) : null : recent.map((e) => renderEntry(e)),
1210
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1447
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Recent" }),
1448
+ state.sessions.loading && state.sessions.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SidebarSkeleton, {}) : state.sessions.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] text-destructive", children: state.sessions.error }) : recent.length === 0 ? running.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] leading-5 text-muted-foreground", children: "Sessions you start or take over here will appear here." }) : null : recent.map((e) => renderEntry(e)),
1449
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1211
1450
  SectionLabel,
1212
1451
  {
1213
- action: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "flex items-center gap-0.5", children: [
1214
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DropdownMenu, { children: [
1215
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "cs-icon-button cs-icon-button--text", "aria-label": "How to list your other chats", children: groupMode === "date" ? "By date" : "By folder" }) }),
1216
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DropdownMenuContent, { align: "end", className: "w-52", children: [
1217
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuLabel, { children: "Group your other chats" }),
1218
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DropdownMenuRadioGroup, { value: groupMode, onValueChange: (v) => setMode(v), children: [
1219
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuRadioItem, { value: "date", children: "By date" }),
1220
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuRadioItem, { value: "folder", children: "By folder" })
1452
+ action: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-center gap-0.5", children: [
1453
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DropdownMenu, { children: [
1454
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "cs-icon-button cs-icon-button--text", "aria-label": "How to list your other chats", children: groupMode === "date" ? "By date" : "By folder" }) }),
1455
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DropdownMenuContent, { align: "end", className: "w-52", children: [
1456
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuLabel, { children: "Group your other chats" }),
1457
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DropdownMenuRadioGroup, { value: groupMode, onValueChange: (v) => setMode(v), children: [
1458
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuRadioItem, { value: "date", children: "By date" }),
1459
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuRadioItem, { value: "folder", children: "By folder" })
1221
1460
  ] }),
1222
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuSeparator, {}),
1223
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuItem, { onSelect: () => setShowHidden((v) => !v), children: showHidden ? "Leave hidden chats out" : `Show hidden chats${hiddenCount ? ` (${hiddenCount})` : ""}` })
1461
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuSeparator, {}),
1462
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuItem, { onSelect: () => setShowHidden((v) => !v), children: showHidden ? "Leave hidden chats out" : `Show hidden chats${hiddenCount ? ` (${hiddenCount})` : ""}` })
1224
1463
  ] })
1225
1464
  ] }),
1226
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1465
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1227
1466
  "button",
1228
1467
  {
1229
1468
  type: "button",
@@ -1231,17 +1470,17 @@ function Sidebar(props) {
1231
1470
  onClick: () => void client.refreshDiscovered(),
1232
1471
  "aria-label": "Look again for your other chats",
1233
1472
  title: "Look again",
1234
- children: state.discovered.loading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RefreshIcon, { size: 13 })
1473
+ children: state.discovered.loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RefreshIcon, { size: 13 })
1235
1474
  }
1236
1475
  )
1237
1476
  ] }),
1238
1477
  children: "Your other chats"
1239
1478
  }
1240
1479
  ),
1241
- state.discovered.loading && state.discovered.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SidebarSkeleton, {}) : state.discovered.error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "px-4 py-1 text-[12px] text-destructive", children: state.discovered.error }) : otherList.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "px-4 py-1 text-[12px] leading-5 text-muted-foreground", children: others.length > 0 ? "Every chat found here is pinned or hidden." : "No other Claude Code or Codex chats were found on this computer." }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1480
+ state.discovered.loading && state.discovered.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SidebarSkeleton, {}) : state.discovered.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] text-destructive", children: state.discovered.error }) : otherList.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] leading-5 text-muted-foreground", children: others.length > 0 ? "Every chat found here is pinned or hidden." : "No other Claude Code or Codex chats were found on this computer." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1242
1481
  renderGroups(otherList),
1243
- state.discovered.data.length >= state.discoveredLimit ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "px-3 pt-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1244
- import_design_system4.Button,
1482
+ state.discovered.data.length >= state.discoveredLimit ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-3 pt-2", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1483
+ import_design_system5.Button,
1245
1484
  {
1246
1485
  variant: "ghost",
1247
1486
  size: "sm",
@@ -1249,32 +1488,32 @@ function Sidebar(props) {
1249
1488
  onClick: () => void client.showMoreDiscovered(),
1250
1489
  disabled: state.discovered.loading,
1251
1490
  children: [
1252
- state.discovered.loading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SpinnerIcon, { size: 13 }) : null,
1491
+ state.discovered.loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 13 }) : null,
1253
1492
  "Show older chats"
1254
1493
  ]
1255
1494
  }
1256
1495
  ) }) : null
1257
1496
  ] }),
1258
- showHidden ? null : hiddenCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { type: "button", className: "cs-link mx-4 mt-3 text-[11.5px]", onClick: () => setShowHidden(true), children: [
1497
+ showHidden ? null : hiddenCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { type: "button", className: "cs-link mx-4 mt-3 text-[11.5px]", onClick: () => setShowHidden(true), children: [
1259
1498
  hiddenCount,
1260
1499
  " hidden ",
1261
1500
  hiddenCount === 1 ? "chat" : "chats",
1262
1501
  " \u2014 show"
1263
1502
  ] }) : null
1264
1503
  ] });
1265
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1504
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1266
1505
  "aside",
1267
1506
  {
1268
- className: "cs-sidebar flex h-full shrink-0 flex-col border-r border-border bg-muted/30",
1507
+ className: "cs-sidebar flex h-full shrink-0 flex-col border-r border-border bg-sidebar-background",
1269
1508
  style: { width: props.width },
1270
1509
  "aria-label": "Sessions",
1271
1510
  children: [
1272
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between gap-2 px-4 pb-2 pt-3.5", children: [
1273
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
1274
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "cs-app-mark", "aria-hidden": "true" }),
1275
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate text-[14px] font-semibold tracking-[-0.01em]", children: "Coding sessions" })
1511
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between gap-2 px-4 pb-2 pt-3.5", children: [
1512
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
1513
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "cs-app-mark", "aria-hidden": "true" }),
1514
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate text-[14px] font-semibold tracking-[-0.01em]", children: "Coding sessions" })
1276
1515
  ] }),
1277
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1516
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1278
1517
  "button",
1279
1518
  {
1280
1519
  type: "button",
@@ -1282,19 +1521,19 @@ function Sidebar(props) {
1282
1521
  onClick: props.onCollapse,
1283
1522
  "aria-label": "Hide the sidebar (\u2318B)",
1284
1523
  title: "Hide sidebar \u2318B",
1285
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SidebarIcon, { size: 15 })
1524
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SidebarIcon, { size: 15 })
1286
1525
  }
1287
1526
  )
1288
1527
  ] }),
1289
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-1.5 px-3 pb-1", children: [
1290
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.Button, { className: "w-full justify-start gap-2", variant: "outline", size: "sm", onClick: props.onNew, children: [
1291
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PlusIcon, { size: 15 }),
1528
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-1.5 px-3 pb-1", children: [
1529
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.Button, { className: "w-full justify-start gap-2", variant: "outline", size: "sm", onClick: props.onNew, children: [
1530
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PlusIcon, { size: 15 }),
1292
1531
  "New session",
1293
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("kbd", { className: "cs-kbd ml-auto", children: "\u2325\u2318N" })
1532
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("kbd", { className: "cs-kbd ml-auto", children: "\u2325\u2318N" })
1294
1533
  ] }),
1295
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cs-search", children: [
1296
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SearchIcon, { size: 14, className: "cs-search__icon" }),
1297
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1534
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "cs-search", children: [
1535
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SearchIcon, { size: 14, className: "cs-search__icon" }),
1536
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1298
1537
  "input",
1299
1538
  {
1300
1539
  ref: props.searchRef,
@@ -1320,10 +1559,10 @@ function Sidebar(props) {
1320
1559
  className: "cs-search__input"
1321
1560
  }
1322
1561
  ),
1323
- query ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "cs-icon-button cs-search__clear", onClick: () => setQuery(""), "aria-label": "Clear search", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CloseIcon, { size: 13 }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("kbd", { className: "cs-search__kbd", children: "\u2318K" })
1562
+ query ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "cs-icon-button cs-search__clear", onClick: () => setQuery(""), "aria-label": "Clear search", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CloseIcon, { size: 13 }) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("kbd", { className: "cs-search__kbd", children: "\u2318K" })
1324
1563
  ] })
1325
1564
  ] }),
1326
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("nav", { className: "min-h-0 flex-1 overflow-y-auto pb-3", children: searching ? searchBody : listBody }),
1565
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("nav", { className: "min-h-0 flex-1 overflow-y-auto pb-3", children: searching ? searchBody : listBody }),
1327
1566
  props.footer
1328
1567
  ]
1329
1568
  }
@@ -1488,14 +1727,15 @@ function createTranscriptBuilder() {
1488
1727
  }));
1489
1728
  return;
1490
1729
  case "error": {
1491
- const said = current?.message.parts.some((p) => p.type === "error" && p.message.trim() === item.text.trim());
1730
+ const text = runErrorLabel(item.text);
1731
+ const said = current?.message.parts.some((p) => p.type === "error" && p.message.trim() === text.trim());
1492
1732
  if (said) return;
1493
1733
  upsertPart(item.id, () => ({
1494
1734
  type: "error",
1495
1735
  errorType: "provider",
1496
1736
  code: null,
1497
- message: item.text,
1498
- userMessage: item.text,
1737
+ message: text,
1738
+ userMessage: text,
1499
1739
  recoverable: true,
1500
1740
  remedy: null
1501
1741
  }));
@@ -1913,13 +2153,13 @@ function firstInvalidField(errors) {
1913
2153
  }
1914
2154
 
1915
2155
  // src/react/app.tsx
1916
- var import_jsx_runtime6 = require("react/jsx-runtime");
2156
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1917
2157
  function CodingSessionsProvider({ transport, children }) {
1918
- const [client] = (0, import_react6.useState)(() => new CodingSessionsClient(transport));
1919
- (0, import_react6.useEffect)(() => {
2158
+ const [client] = (0, import_react8.useState)(() => new CodingSessionsClient(transport));
2159
+ (0, import_react8.useEffect)(() => {
1920
2160
  if (transport.status().state === "open") void client.refreshAll();
1921
2161
  }, [client, transport]);
1922
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CodingSessionsContext.Provider, { value: client, children });
2162
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CodingSessionsContext.Provider, { value: client, children });
1923
2163
  }
1924
2164
  function readHash() {
1925
2165
  if (typeof location === "undefined") return { kind: "none" };
@@ -1942,8 +2182,8 @@ function readTheme() {
1942
2182
  }
1943
2183
  }
1944
2184
  function useTheme() {
1945
- const [choice, setChoice] = (0, import_react6.useState)(readTheme);
1946
- (0, import_react6.useEffect)(() => {
2185
+ const [choice, setChoice] = (0, import_react8.useState)(readTheme);
2186
+ (0, import_react8.useEffect)(() => {
1947
2187
  const media = typeof window.matchMedia === "function" ? window.matchMedia("(prefers-color-scheme: dark)") : null;
1948
2188
  const apply = () => {
1949
2189
  const dark = choice === "dark" || choice === "system" && media?.matches === true;
@@ -1954,7 +2194,7 @@ function useTheme() {
1954
2194
  media?.addEventListener("change", apply);
1955
2195
  return () => media?.removeEventListener("change", apply);
1956
2196
  }, [choice]);
1957
- const set = (0, import_react6.useCallback)((next) => {
2197
+ const set = (0, import_react8.useCallback)((next) => {
1958
2198
  setChoice(next);
1959
2199
  try {
1960
2200
  localStorage.setItem("coding-sessions.theme", next);
@@ -1973,8 +2213,8 @@ var RUN_LABEL = {
1973
2213
  function RunPill({ run }) {
1974
2214
  if (!run) return null;
1975
2215
  const live = !isTerminalRunStatus(run.status);
1976
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: (0, import_design_system5.cn)("cs-pill", `cs-pill--${run.status}`), children: [
1977
- live ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "cs-pill__dot", "aria-hidden": "true" }) : null,
2216
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: (0, import_design_system6.cn)("cs-pill", `cs-pill--${run.status}`), children: [
2217
+ live ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "cs-pill__dot", "aria-hidden": "true" }) : null,
1978
2218
  RUN_LABEL[run.status]
1979
2219
  ] });
1980
2220
  }
@@ -1982,17 +2222,17 @@ function ConnectionBanner() {
1982
2222
  const { connection } = useCodingSessionsState();
1983
2223
  if (connection.state === "open") return null;
1984
2224
  const closed = connection.state === "closed";
1985
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2225
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1986
2226
  "div",
1987
2227
  {
1988
2228
  role: "status",
1989
- className: (0, import_design_system5.cn)(
2229
+ className: (0, import_design_system6.cn)(
1990
2230
  "flex items-center gap-2 border-b px-4 py-2 text-[13px]",
1991
2231
  closed ? "border-destructive/30 bg-destructive/10 text-destructive" : "border-border bg-muted/60 text-muted-foreground"
1992
2232
  ),
1993
2233
  children: [
1994
- closed ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlertIcon, { size: 15 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 14 }),
1995
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: closed ? connection.reason : "Connecting to the coding sessions host\u2026" })
2234
+ closed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 14 }),
2235
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: closed ? connection.reason : "Connecting to the coding sessions host\u2026" })
1996
2236
  ]
1997
2237
  }
1998
2238
  );
@@ -2002,22 +2242,22 @@ function ProvidersFooter(props) {
2002
2242
  const client = useCodingSessionsClient();
2003
2243
  const next = { system: "light", light: "dark", dark: "system" };
2004
2244
  const themeLabel = { system: "Match system", light: "Light", dark: "Dark" };
2005
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "border-t border-border px-3 py-2.5", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2006
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex min-w-0 flex-1 flex-wrap gap-1.5", children: state.providers.loading && state.providers.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[11.5px] text-muted-foreground", children: "Checking Claude Code and Codex\u2026" }) : state.providers.data.map((p) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2245
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "border-t border-border px-3 py-2.5", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2246
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex min-w-0 flex-1 flex-wrap gap-1.5", children: state.providers.loading && state.providers.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[11.5px] text-muted-foreground", children: "Checking Claude Code and Codex\u2026" }) : state.providers.data.map((p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2007
2247
  "span",
2008
2248
  {
2009
- className: (0, import_design_system5.cn)("cs-provider-chip", p.ready ? "" : "cs-provider-chip--problem"),
2010
- title: p.problem ? `${p.problem} ${p.fix ?? ""}` : `${p.label}${p.plan ? ` \xB7 ${p.plan}` : ""}`,
2249
+ className: (0, import_design_system6.cn)("cs-provider-chip", p.ready ? "" : "cs-provider-chip--problem"),
2250
+ title: p.problem ? `${p.problem} ${p.fix ?? ""}` : [binaryWords(p) ?? p.label, p.plan, newerWords(p)].filter(Boolean).join(" \xB7 "),
2011
2251
  children: [
2012
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProviderMark, { provider: p.provider, size: 13 }),
2252
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProviderMark, { provider: p.provider, size: 13 }),
2013
2253
  p.label,
2014
- p.lastProblem ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "cs-provider-chip__note", children: p.lastProblem.kind === "signed-out" ? "\xB7 sign in again" : `\xB7 limit${formatUntil(p.lastProblem.until) ? ` until ${formatUntil(p.lastProblem.until)}` : ""}` }) : null,
2015
- p.ready ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CheckIcon, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlertIcon, { size: 12 })
2254
+ p.lastProblem ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "cs-provider-chip__note", children: p.lastProblem.kind === "signed-out" ? "\xB7 sign in again" : `\xB7 limit${formatUntil(p.lastProblem.until) ? ` until ${formatUntil(p.lastProblem.until)}` : ""}` }) : null,
2255
+ p.ready ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckIcon, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 12 })
2016
2256
  ]
2017
2257
  },
2018
2258
  p.provider
2019
2259
  )) }),
2020
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2260
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2021
2261
  "button",
2022
2262
  {
2023
2263
  type: "button",
@@ -2025,11 +2265,11 @@ function ProvidersFooter(props) {
2025
2265
  onClick: () => void client.refreshProviders(),
2026
2266
  "aria-label": "Check Claude Code and Codex again",
2027
2267
  title: "Check again",
2028
- children: state.providers.loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RefreshIcon, { size: 13 })
2268
+ children: state.providers.loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RefreshIcon, { size: 13 })
2029
2269
  }
2030
2270
  ),
2031
2271
  props.extra,
2032
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2272
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2033
2273
  "button",
2034
2274
  {
2035
2275
  type: "button",
@@ -2037,14 +2277,14 @@ function ProvidersFooter(props) {
2037
2277
  onClick: () => props.setTheme(next[props.theme]),
2038
2278
  "aria-label": `Theme: ${themeLabel[props.theme]}. Switch to ${themeLabel[next[props.theme]]}.`,
2039
2279
  title: `Theme: ${themeLabel[props.theme]}`,
2040
- children: props.theme === "system" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MonitorIcon, { size: 14 }) : props.theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SunIcon, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MoonIcon, { size: 14 })
2280
+ children: props.theme === "system" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MonitorIcon, { size: 14 }) : props.theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SunIcon, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MoonIcon, { size: 14 })
2041
2281
  }
2042
2282
  )
2043
2283
  ] }) });
2044
2284
  }
2045
2285
  function useNotifier() {
2046
- const show = (0, import_react6.useContext)(ToastContext);
2047
- return (0, import_react6.useMemo)(
2286
+ const show = (0, import_react8.useContext)(ToastContext);
2287
+ return (0, import_react8.useMemo)(
2048
2288
  () => ({
2049
2289
  notify(event) {
2050
2290
  show(event.message);
@@ -2055,8 +2295,8 @@ function useNotifier() {
2055
2295
  }
2056
2296
  function useLiveElsewhere(provider, providerSessionId, initial = null) {
2057
2297
  const client = useCodingSessionsClient();
2058
- const [state, setState] = (0, import_react6.useState)(initial);
2059
- (0, import_react6.useEffect)(() => {
2298
+ const [state, setState] = (0, import_react8.useState)(initial);
2299
+ (0, import_react8.useEffect)(() => {
2060
2300
  if (!provider || !providerSessionId) {
2061
2301
  setState(null);
2062
2302
  return;
@@ -2076,8 +2316,8 @@ function useLiveElsewhere(provider, providerSessionId, initial = null) {
2076
2316
  }
2077
2317
  function useSessionUsage(sessionId, lastRunKey) {
2078
2318
  const client = useCodingSessionsClient();
2079
- const [usage, setUsage] = (0, import_react6.useState)(null);
2080
- (0, import_react6.useEffect)(() => {
2319
+ const [usage, setUsage] = (0, import_react8.useState)(null);
2320
+ (0, import_react8.useEffect)(() => {
2081
2321
  let cancelled = false;
2082
2322
  void client.transport.call("listRuns", sessionId).then((runs) => {
2083
2323
  if (cancelled) return;
@@ -2098,18 +2338,18 @@ function useSessionUsage(sessionId, lastRunKey) {
2098
2338
  return usage;
2099
2339
  }
2100
2340
  function HeaderMenu(props) {
2101
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DropdownMenu, { children: [
2102
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "cs-icon-button", "aria-label": "More for this chat", title: "More", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MoreIcon, { size: 16 }) }) }),
2103
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuContent, { align: "end", className: "w-64", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatMenuItems, { entry: props.entry, variant: "dropdown", onRename: props.onRename }) })
2341
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DropdownMenu, { children: [
2342
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "cs-icon-button", "aria-label": "More for this chat", title: "More", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MoreIcon, { size: 16 }) }) }),
2343
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.DropdownMenuContent, { align: "end", className: "w-64", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChatMenuItems, { entry: props.entry, variant: "dropdown", onRename: props.onRename }) })
2104
2344
  ] });
2105
2345
  }
2106
2346
  function HeaderTitle(props) {
2107
2347
  const client = useCodingSessionsClient();
2108
- const show = (0, import_react6.useContext)(ToastContext);
2109
- const [value, setValue] = (0, import_react6.useState)(props.entry.title);
2110
- (0, import_react6.useEffect)(() => setValue(props.entry.title), [props.entry.title, props.renaming]);
2111
- const inputRef = (0, import_react6.useRef)(null);
2112
- (0, import_react6.useEffect)(() => {
2348
+ const show = (0, import_react8.useContext)(ToastContext);
2349
+ const [value, setValue] = (0, import_react8.useState)(props.entry.title);
2350
+ (0, import_react8.useEffect)(() => setValue(props.entry.title), [props.entry.title, props.renaming]);
2351
+ const inputRef = (0, import_react8.useRef)(null);
2352
+ (0, import_react8.useEffect)(() => {
2113
2353
  if (!props.renaming) return;
2114
2354
  const timer = setTimeout(() => {
2115
2355
  const input = inputRef.current;
@@ -2121,7 +2361,7 @@ function HeaderTitle(props) {
2121
2361
  return () => clearTimeout(timer);
2122
2362
  }, [props.renaming]);
2123
2363
  if (!props.renaming) {
2124
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2364
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2125
2365
  "h1",
2126
2366
  {
2127
2367
  className: "truncate text-[15px] font-semibold leading-5 tracking-[-0.01em]",
@@ -2138,7 +2378,7 @@ function HeaderTitle(props) {
2138
2378
  const next = title === "" || title === props.entry.originalTitle ? null : title;
2139
2379
  client.setPreference(props.entry.key, { title: next }).catch((error) => show(`The new name didn't save: ${error instanceof Error ? error.message : String(error)}`));
2140
2380
  };
2141
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2381
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2142
2382
  "input",
2143
2383
  {
2144
2384
  ref: inputRef,
@@ -2157,15 +2397,22 @@ function HeaderTitle(props) {
2157
2397
  );
2158
2398
  }
2159
2399
  function LongChatNote(props) {
2160
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "mx-auto mt-3 flex items-center gap-2 text-[12px] text-muted-foreground", children: [
2400
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "mx-auto mt-3 flex items-center gap-2 text-[12px] text-muted-foreground", children: [
2161
2401
  "This chat is very long \u2014 showing its most recent part.",
2162
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "cs-link", onClick: props.onEarlier, disabled: props.loading, children: props.loading ? "Reading\u2026" : "Show earlier" })
2402
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "cs-link", onClick: props.onEarlier, disabled: props.loading, children: props.loading ? "Reading\u2026" : "Show earlier" })
2163
2403
  ] });
2164
2404
  }
2405
+ function binaryWords(p) {
2406
+ if (!p.version) return null;
2407
+ return `${p.label} ${p.version}${p.binary ? ` \xB7 ${p.binary.sourceLabel}` : ""}`;
2408
+ }
2409
+ function newerWords(p) {
2410
+ return p.binary?.newer ? `Newer: ${p.binary.newer.version} ${p.binary.newer.sourceLabel}` : null;
2411
+ }
2165
2412
  function SessionView({ session, changesOpen, setChangesOpen }) {
2166
2413
  const client = useCodingSessionsClient();
2167
2414
  const state = useCodingSessionsState();
2168
- const show = (0, import_react6.useContext)(ToastContext);
2415
+ const show = (0, import_react8.useContext)(ToastContext);
2169
2416
  const transcript = useSessionTranscript(session.id);
2170
2417
  const run = state.runs[session.id];
2171
2418
  const live = run !== void 0 && !isTerminalRunStatus(run.status);
@@ -2173,8 +2420,9 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
2173
2420
  const provider = state.providers.data.find((p) => p.provider === session.provider) ?? null;
2174
2421
  const blocked = provider && (!provider.installed || !provider.loggedIn) ? provider : null;
2175
2422
  const limited = !blocked && provider?.lastProblem ? provider : null;
2176
- const [stopping, setStopping] = (0, import_react6.useState)(false);
2177
- const [renaming, setRenaming] = (0, import_react6.useState)(false);
2423
+ const modelRefused = run?.status === "failed" && isModelUnavailable(run.error);
2424
+ const [stopping, setStopping] = (0, import_react8.useState)(false);
2425
+ const [renaming, setRenaming] = (0, import_react8.useState)(false);
2178
2426
  const elsewhere = useLiveElsewhere(
2179
2427
  session.origin === "takeover" && !live ? session.provider : null,
2180
2428
  session.providerSessionId
@@ -2183,7 +2431,7 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
2183
2431
  const messages = transcript.thread.getSnapshot().messages;
2184
2432
  const files = useChangedFiles(messages);
2185
2433
  const usage = useSessionUsage(session.id, `${run?.runId ?? ""}:${run?.status ?? ""}`);
2186
- (0, import_react6.useEffect)(() => {
2434
+ (0, import_react8.useEffect)(() => {
2187
2435
  if (!live) setStopping(false);
2188
2436
  }, [live]);
2189
2437
  const stop = async () => {
@@ -2196,16 +2444,16 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
2196
2444
  };
2197
2445
  const usageWords = usage ? `${(0, import_format3.formatCount)(usage.tokens, { style: "compact" })} tokens${usage.cost !== null ? ` \xB7 ${(0, import_format3.formatUsd)(usage.cost)}` : ""}` : null;
2198
2446
  const usageTitle = usage ? `${(0, import_format3.formatCount)(usage.tokens)} tokens over ${usage.runs} ${usage.runs === 1 ? "message" : "messages"} sent from here.` + (usage.cost !== null ? usage.billing === "subscription" ? ` ${(0, import_format3.formatUsd)(usage.cost)} is what this would cost at API prices \u2014 it's covered by your ${provider?.plan ?? ""} plan.`.replace(" ", " ") : ` Billed ${(0, import_format3.formatUsd)(usage.cost)} to your API key.` : "") : "";
2199
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-w-0 flex-1", children: [
2200
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "flex min-w-0 flex-1 flex-col", "aria-label": entry.title, children: [
2201
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("header", { className: "flex items-center gap-3 border-b border-border px-5 py-2.5", children: [
2202
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProviderMark, { provider: session.provider, size: 22 }),
2203
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "min-w-0 flex-1", children: [
2204
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HeaderTitle, { entry, renaming, setRenaming }),
2205
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-w-0 items-center gap-1 text-[12px] leading-5 text-muted-foreground", children: [
2206
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "shrink-0", children: PROVIDER_LABEL[session.provider] }),
2207
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
2208
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2447
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 flex-1", children: [
2448
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "flex min-w-0 flex-1 flex-col", "aria-label": entry.title, children: [
2449
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("header", { className: "flex flex-wrap items-center gap-2 border-b border-border px-5 pt-2.5 pb-2.5", children: [
2450
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProviderMark, { provider: session.provider, size: 22 }),
2451
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "min-w-0 flex-1 overflow-hidden", children: [
2452
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderTitle, { entry, renaming, setRenaming }),
2453
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 items-center gap-1 text-[12px] leading-5 text-muted-foreground", children: [
2454
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "shrink-0", children: PROVIDER_LABEL[session.provider] }),
2455
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
2456
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2209
2457
  ModelPicker,
2210
2458
  {
2211
2459
  status: provider,
@@ -2213,86 +2461,106 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
2213
2461
  onChange: setOptions
2214
2462
  }
2215
2463
  ),
2216
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
2217
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FolderIcon, { size: 12, className: "shrink-0" }),
2218
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "min-w-[4rem] truncate", title: session.cwd, children: prettyPath2(session.cwd) }),
2219
- usageWords ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "shrink-0", title: usageTitle, children: [
2464
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
2465
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FolderIcon, { size: 12, className: "shrink-0" }),
2466
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "min-w-[4rem] truncate", title: session.cwd, children: prettyPath2(session.cwd) }),
2467
+ usageWords ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "shrink-0", title: usageTitle, children: [
2220
2468
  "\xB7 ",
2221
2469
  usageWords
2222
2470
  ] }) : null
2223
2471
  ] })
2224
2472
  ] }),
2225
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2473
+ session.agent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AgentChip, { agent: session.agent }) : null,
2474
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2226
2475
  "button",
2227
2476
  {
2228
2477
  type: "button",
2229
- className: (0, import_design_system5.cn)("cs-chip-button", changesOpen && "cs-chip-button--on"),
2478
+ className: (0, import_design_system6.cn)("cs-chip-button", changesOpen && "cs-chip-button--on"),
2230
2479
  onClick: () => setChangesOpen(!changesOpen),
2231
2480
  "aria-pressed": changesOpen,
2232
2481
  title: "Files this chat changed",
2233
2482
  children: [
2234
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FileIcon, { size: 13 }),
2483
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FileIcon, { size: 13 }),
2235
2484
  files.length > 0 ? `${files.length} ${files.length === 1 ? "file" : "files"} changed` : "Changes"
2236
2485
  ]
2237
2486
  }
2238
2487
  ),
2239
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RunPill, { run }),
2240
- live ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.Button, { variant: "outline", size: "sm", onClick: () => void stop(), disabled: stopping, className: "gap-1.5", title: "Stop Esc", children: [
2241
- stopping ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StopIcon, { size: 13 }),
2488
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RunPill, { run }),
2489
+ live ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.Button, { variant: "outline", size: "sm", onClick: () => void stop(), disabled: stopping, className: "gap-1.5", title: "Stop Esc", children: [
2490
+ stopping ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StopIcon, { size: 13 }),
2242
2491
  stopping ? "Stopping\u2026" : "Stop"
2243
2492
  ] }) : null,
2244
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HeaderMenu, { entry, onRename: () => setRenaming(true) })
2493
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderMenu, { entry, onRename: () => setRenaming(true) })
2245
2494
  ] }),
2246
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-chat flex min-h-0 flex-1 flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react7.ChatProvider, { thread: transcript.thread, ports: { notifier, toolLabel: friendlyToolName }, children: [
2247
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "min-h-0 flex-1 overflow-hidden", children: transcript.state.loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex h-full items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
2248
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 15 }),
2495
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mx-chat flex min-h-0 flex-1 flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react9.ChatProvider, { thread: transcript.thread, ports: { notifier, toolLabel: friendlyToolName }, children: [
2496
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "min-h-0 flex-1 overflow-hidden", children: transcript.state.loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex h-full items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
2497
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 15 }),
2249
2498
  " Loading the conversation\u2026"
2250
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex h-full flex-col", children: [
2251
- transcript.state.unavailable ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-auto mt-4 max-w-[720px] rounded-lg border border-border bg-muted/50 px-4 py-2.5 text-[13px] text-muted-foreground", children: transcript.state.unavailable }) : null,
2252
- transcript.state.truncated ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2499
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex h-full flex-col", children: [
2500
+ transcript.state.unavailable ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "mx-auto mt-4 max-w-[720px] rounded-lg border border-border bg-muted/50 px-4 py-2.5 text-[13px] text-muted-foreground", children: transcript.state.unavailable }) : null,
2501
+ transcript.state.truncated ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2253
2502
  LongChatNote,
2254
2503
  {
2255
2504
  loading: transcript.state.loadingEarlier === true,
2256
2505
  onEarlier: () => void transcript.loadEarlier()
2257
2506
  }
2258
2507
  ) : null,
2259
- messages.length === 0 && !live ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex flex-1 items-center justify-center text-[13px] text-muted-foreground", children: session.origin === "takeover" ? "You've taken over this chat. Send a message to continue it." : "Nothing here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react7.ChatMessageList, { className: "min-h-0 flex-1", label: `Conversation: ${entry.title}` })
2508
+ messages.length === 0 && !live ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-1 items-center justify-center text-[13px] text-muted-foreground", children: session.origin === "takeover" ? "You've taken over this chat. Send a message to continue it." : "Nothing here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react9.ChatMessageList, { className: "min-h-0 flex-1", label: `Conversation: ${entry.title}` })
2260
2509
  ] }) }),
2261
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-auto w-full max-w-[820px] px-4 pb-4", children: [
2262
- limited ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]", children: [
2263
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
2264
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
2510
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mx-auto w-full max-w-[820px] px-4 pb-4", children: [
2511
+ limited ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]", children: [
2512
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
2513
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
2265
2514
  limited.problem,
2266
2515
  " ",
2267
2516
  limited.fix
2268
2517
  ] })
2269
2518
  ] }) : null,
2270
- blocked ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]", children: [
2271
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
2272
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
2519
+ modelRefused && !blocked ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2520
+ "div",
2521
+ {
2522
+ className: "mb-2 flex items-center gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]",
2523
+ role: "alert",
2524
+ children: [
2525
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "shrink-0 text-warning" }),
2526
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "min-w-0 flex-1 truncate", title: run?.error ?? void 0, children: MODEL_UNAVAILABLE_LABEL }),
2527
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2528
+ ModelPicker,
2529
+ {
2530
+ status: provider,
2531
+ value: { model: session.model, effort: session.effort ?? null },
2532
+ onChange: setOptions
2533
+ }
2534
+ )
2535
+ ]
2536
+ }
2537
+ ) : null,
2538
+ blocked ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]", children: [
2539
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
2540
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
2273
2541
  blocked.problem,
2274
2542
  " ",
2275
2543
  blocked.fix
2276
2544
  ] })
2277
2545
  ] }) : null,
2278
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "cs-activity", role: "status", "aria-live": "polite", "data-idle": live ? void 0 : true, children: live ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2279
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 13 }),
2280
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: run?.status === "starting" ? `Starting ${PROVIDER_LABEL[session.provider]}\u2026` : transcript.activity ?? "Thinking\u2026" }),
2281
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "ml-auto shrink-0 text-[11px] opacity-70", children: "Esc to stop" })
2546
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "cs-activity", role: "status", "aria-live": "polite", "data-idle": live ? void 0 : true, children: live ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2547
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 13 }),
2548
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate", children: run?.status === "starting" ? `Starting ${PROVIDER_LABEL[session.provider]}\u2026` : transcript.activity ?? "Thinking\u2026" }),
2549
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ml-auto shrink-0 text-[11px] opacity-70", children: "Esc to stop" })
2282
2550
  ] }) : null }),
2283
- elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]", children: [
2284
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
2285
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
2551
+ elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]", children: [
2552
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
2553
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
2286
2554
  elsewhere.message,
2287
2555
  " A message sent here would put a second agent on the same chat."
2288
2556
  ] })
2289
2557
  ] }) : null,
2290
- session.queued.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "mb-2 space-y-1.5", "aria-label": "Queued messages", children: session.queued.map((text, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("li", { className: "cs-queued", children: [
2291
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "cs-queued__label", children: "Queued \xB7 sends when this run finishes" }),
2292
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "cs-queued__text", children: text })
2558
+ session.queued.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { className: "mb-2 space-y-1.5", "aria-label": "Queued messages", children: session.queued.map((text, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("li", { className: "cs-queued", children: [
2559
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "cs-queued__label", children: "Queued \xB7 sends when this run finishes" }),
2560
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "cs-queued__text", children: text })
2293
2561
  ] }, `${index}-${text.slice(0, 16)}`)) }) : null,
2294
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2295
- import_react7.ChatComposer,
2562
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2563
+ import_react9.ChatComposer,
2296
2564
  {
2297
2565
  placeholder: `Message ${PROVIDER_LABEL[session.provider]}\u2026`,
2298
2566
  autoFocus: true,
@@ -2302,14 +2570,14 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
2302
2570
  ] })
2303
2571
  ] }) })
2304
2572
  ] }),
2305
- changesOpen ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChangesPanel, { files, cwd: session.cwd, truncated: transcript.state.truncated, onClose: () => setChangesOpen(false) }) : null
2573
+ changesOpen ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChangesPanel, { files, cwd: session.cwd, truncated: transcript.state.truncated, onClose: () => setChangesOpen(false) }) : null
2306
2574
  ] });
2307
2575
  }
2308
2576
  function usePreviewThread(id, onSend) {
2309
- const ref = (0, import_react6.useRef)({ messages: [], listeners: /* @__PURE__ */ new Set() });
2310
- const send = (0, import_react6.useRef)(onSend);
2577
+ const ref = (0, import_react8.useRef)({ messages: [], listeners: /* @__PURE__ */ new Set() });
2578
+ const send = (0, import_react8.useRef)(onSend);
2311
2579
  send.current = onSend;
2312
- const thread = (0, import_react6.useMemo)(
2580
+ const thread = (0, import_react8.useMemo)(
2313
2581
  () => (0, import_external_store2.createExternalThreadSource)({
2314
2582
  getSnapshot: () => ({ messages: ref.current.messages, status: "idle", conversationId: id }),
2315
2583
  subscribe: (listener) => {
@@ -2323,7 +2591,7 @@ function usePreviewThread(id, onSend) {
2323
2591
  }),
2324
2592
  [id]
2325
2593
  );
2326
- const set = (0, import_react6.useCallback)((messages) => {
2594
+ const set = (0, import_react8.useCallback)((messages) => {
2327
2595
  ref.current.messages = messages;
2328
2596
  for (const listener of ref.current.listeners) listener();
2329
2597
  }, []);
@@ -2332,15 +2600,15 @@ function usePreviewThread(id, onSend) {
2332
2600
  function DiscoveredView(props) {
2333
2601
  const client = useCodingSessionsClient();
2334
2602
  const state = useCodingSessionsState();
2335
- const show = (0, import_react6.useContext)(ToastContext);
2603
+ const show = (0, import_react8.useContext)(ToastContext);
2336
2604
  const now = useMinuteClock();
2337
- const [preview, setPreview] = (0, import_react6.useState)({ loading: true, messages: [], unavailable: null, truncated: false });
2338
- const [busy, setBusy] = (0, import_react6.useState)(false);
2339
- const [error, setError] = (0, import_react6.useState)(null);
2340
- const [confirming, setConfirming] = (0, import_react6.useState)(false);
2341
- const [renaming, setRenaming] = (0, import_react6.useState)(false);
2342
- const [maxBytes, setMaxBytes] = (0, import_react6.useState)(void 0);
2343
- const [readingEarlier, setReadingEarlier] = (0, import_react6.useState)(false);
2605
+ const [preview, setPreview] = (0, import_react8.useState)({ loading: true, messages: [], unavailable: null, truncated: false });
2606
+ const [busy, setBusy] = (0, import_react8.useState)(false);
2607
+ const [error, setError] = (0, import_react8.useState)(null);
2608
+ const [confirming, setConfirming] = (0, import_react8.useState)(false);
2609
+ const [renaming, setRenaming] = (0, import_react8.useState)(false);
2610
+ const [maxBytes, setMaxBytes] = (0, import_react8.useState)(void 0);
2611
+ const [readingEarlier, setReadingEarlier] = (0, import_react8.useState)(false);
2344
2612
  const elsewhere = useLiveElsewhere(props.provider, props.id, props.session?.activeElsewhere ?? null);
2345
2613
  const files = useChangedFiles(preview.messages);
2346
2614
  const d = props.session;
@@ -2350,7 +2618,7 @@ function DiscoveredView(props) {
2350
2618
  d?.cwd ? `This chat is read-only until you take it over. Press Take over to continue it here.` : "This chat is read-only here: it doesn't record its folder, so it can't be continued."
2351
2619
  )
2352
2620
  );
2353
- (0, import_react6.useEffect)(() => {
2621
+ (0, import_react8.useEffect)(() => {
2354
2622
  let cancelled = false;
2355
2623
  const read = (first) => client.readPreview(props.provider, props.id, maxBytes).then((next) => {
2356
2624
  if (cancelled) return;
@@ -2389,26 +2657,26 @@ function DiscoveredView(props) {
2389
2657
  setBusy(false);
2390
2658
  }
2391
2659
  };
2392
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-w-0 flex-1", children: [
2393
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "flex min-w-0 flex-1 flex-col", "aria-label": entry.title, children: [
2394
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("header", { className: "flex items-center gap-3 border-b border-border px-5 py-3", children: [
2395
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProviderMark, { provider: props.provider, size: 22 }),
2396
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "min-w-0 flex-1", children: [
2397
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HeaderTitle, { entry, renaming, setRenaming }),
2398
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "flex items-center gap-1.5 truncate text-[12px] leading-4 text-muted-foreground", children: [
2399
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: PROVIDER_LABEL[props.provider] }),
2400
- d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2401
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
2402
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FolderIcon, { size: 12 }),
2403
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", title: d.cwd, children: prettyPath2(d.cwd) })
2660
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 flex-1", children: [
2661
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "flex min-w-0 flex-1 flex-col", "aria-label": entry.title, children: [
2662
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("header", { className: "flex flex-wrap items-center gap-2 border-b border-border px-5 pt-2.5 pb-2.5", children: [
2663
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProviderMark, { provider: props.provider, size: 22 }),
2664
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "min-w-0 flex-1", children: [
2665
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderTitle, { entry, renaming, setRenaming }),
2666
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "flex items-center gap-1.5 truncate text-[12px] leading-4 text-muted-foreground", children: [
2667
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: PROVIDER_LABEL[props.provider] }),
2668
+ d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2669
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
2670
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FolderIcon, { size: 12 }),
2671
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate", title: d.cwd, children: prettyPath2(d.cwd) })
2404
2672
  ] }) : null,
2405
- d ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
2673
+ d ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
2406
2674
  "\xB7 last active ",
2407
2675
  relativeTime(d.updatedAt, now)
2408
2676
  ] }) : null
2409
2677
  ] })
2410
2678
  ] }),
2411
- files.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2679
+ files.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2412
2680
  "button",
2413
2681
  {
2414
2682
  type: "button",
@@ -2417,13 +2685,13 @@ function DiscoveredView(props) {
2417
2685
  "aria-pressed": props.changesOpen,
2418
2686
  title: "Files this chat changed",
2419
2687
  children: [
2420
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FileIcon, { size: 13 }),
2688
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FileIcon, { size: 13 }),
2421
2689
  `${files.length} ${files.length === 1 ? "file" : "files"} changed`
2422
2690
  ]
2423
2691
  }
2424
2692
  ) : null,
2425
- d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2426
- import_design_system5.Button,
2693
+ d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2694
+ import_design_system6.Button,
2427
2695
  {
2428
2696
  size: "sm",
2429
2697
  variant: elsewhere ? "outline" : "default",
@@ -2432,44 +2700,44 @@ function DiscoveredView(props) {
2432
2700
  className: "gap-1.5",
2433
2701
  title: elsewhere ? elsewhere.message : void 0,
2434
2702
  children: [
2435
- busy ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 13 }) : elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlertIcon, { size: 14, className: "text-warning" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HandoffIcon, { size: 14 }),
2703
+ busy ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 13 }) : elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 14, className: "text-warning" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HandoffIcon, { size: 14 }),
2436
2704
  elsewhere ? "Take over anyway\u2026" : "Take over"
2437
2705
  ]
2438
2706
  }
2439
2707
  ) : null,
2440
- d ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HeaderMenu, { entry, onRename: () => setRenaming(true) }) : null
2708
+ d ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderMenu, { entry, onRename: () => setRenaming(true) }) : null
2441
2709
  ] }),
2442
- elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "status", className: "flex items-start gap-2 border-b border-warning/40 bg-warning/10 px-5 py-2.5 text-[13px]", children: [
2443
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
2444
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
2445
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-medium", children: elsewhere.message }),
2710
+ elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "status", className: "flex items-start gap-2 border-b border-warning/40 bg-warning/10 px-5 py-2.5 text-[13px]", children: [
2711
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
2712
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
2713
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-medium", children: elsewhere.message }),
2446
2714
  " Taking it over now would put two agents on the same chat, and they could overwrite each other's work. Finish or stop it there first if you can. This preview follows it as it runs."
2447
2715
  ] })
2448
2716
  ] }) : null,
2449
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.Dialog, { open: confirming, onOpenChange: setConfirming, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogContent, { className: "max-w-[460px]", children: [
2450
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogHeader, { children: [
2451
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogTitle, { children: [
2717
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Dialog, { open: confirming, onOpenChange: setConfirming, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogContent, { className: "max-w-[460px]", children: [
2718
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogHeader, { children: [
2719
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogTitle, { children: [
2452
2720
  "This chat is running right now in ",
2453
2721
  PROVIDER_LABEL[props.provider]
2454
2722
  ] }),
2455
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogDescription, { children: [
2723
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogDescription, { children: [
2456
2724
  elsewhere?.message,
2457
2725
  " If you take it over, two agents will work in the same conversation at once and may overwrite each other's changes."
2458
2726
  ] })
2459
2727
  ] }),
2460
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogFooter, { children: [
2461
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.Button, { variant: "ghost", onClick: () => setConfirming(false), children: "Cancel" }),
2462
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.Button, { variant: "destructive", onClick: () => void takeover(), children: "Take over anyway" })
2728
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogFooter, { children: [
2729
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Button, { variant: "ghost", onClick: () => setConfirming(false), children: "Cancel" }),
2730
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Button, { variant: "destructive", onClick: () => void takeover(), children: "Take over anyway" })
2463
2731
  ] })
2464
2732
  ] }) }),
2465
- error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "border-b border-destructive/30 bg-destructive/10 px-5 py-2 text-[13px] text-destructive", children: error }) : null,
2466
- d && !d.cwd ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "border-b border-border bg-muted/50 px-5 py-2 text-[13px] text-muted-foreground", children: "This chat doesn't record which folder it ran in, so it can't be continued from here." }) : null,
2467
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-chat flex min-h-0 flex-1 flex-col", children: [
2468
- preview.loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
2469
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 15 }),
2733
+ error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "border-b border-destructive/30 bg-destructive/10 px-5 py-2 text-[13px] text-destructive", children: error }) : null,
2734
+ d && !d.cwd ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "border-b border-border bg-muted/50 px-5 py-2 text-[13px] text-muted-foreground", children: "This chat doesn't record which folder it ran in, so it can't be continued from here." }) : null,
2735
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mx-chat flex min-h-0 flex-1 flex-col", children: [
2736
+ preview.loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
2737
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 15 }),
2470
2738
  " Reading this chat\u2026"
2471
- ] }) : preview.unavailable ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex flex-1 items-center justify-center px-6 text-center text-[13px] text-muted-foreground", children: preview.unavailable }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react7.ChatProvider, { thread, ports: { notifier, toolLabel: friendlyToolName }, children: [
2472
- preview.truncated ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2739
+ ] }) : preview.unavailable ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-1 items-center justify-center px-6 text-center text-[13px] text-muted-foreground", children: preview.unavailable }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react9.ChatProvider, { thread, ports: { notifier, toolLabel: friendlyToolName }, children: [
2740
+ preview.truncated ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2473
2741
  LongChatNote,
2474
2742
  {
2475
2743
  loading: readingEarlier,
@@ -2479,14 +2747,14 @@ function DiscoveredView(props) {
2479
2747
  }
2480
2748
  }
2481
2749
  ) : null,
2482
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react7.ChatMessageList, { className: "min-h-0 flex-1", label: "Chat preview" })
2750
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react9.ChatMessageList, { className: "min-h-0 flex-1", label: "Chat preview" })
2483
2751
  ] }),
2484
- d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "border-t border-border bg-muted/30 px-5 py-3 text-center text-[13px] text-muted-foreground", children: [
2752
+ d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "border-t border-border bg-muted/30 px-5 py-3 text-center text-[13px] text-muted-foreground", children: [
2485
2753
  "This chat was started in ",
2486
2754
  PROVIDER_LABEL[props.provider],
2487
2755
  ".",
2488
2756
  " ",
2489
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "font-medium text-foreground underline-offset-4 hover:underline", onClick: requestTakeover, children: "Take it over" }),
2757
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "font-medium text-foreground underline-offset-4 hover:underline", onClick: requestTakeover, children: "Take it over" }),
2490
2758
  " ",
2491
2759
  "to continue it here \u2014 it stays in your ",
2492
2760
  PROVIDER_LABEL[props.provider],
@@ -2494,70 +2762,73 @@ function DiscoveredView(props) {
2494
2762
  ] }) : null
2495
2763
  ] })
2496
2764
  ] }),
2497
- props.changesOpen && files.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChangesPanel, { files, cwd: d?.cwd ?? null, truncated: preview.truncated, onClose: () => props.setChangesOpen(false) }) : null
2765
+ props.changesOpen && files.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChangesPanel, { files, cwd: d?.cwd ?? null, truncated: preview.truncated, onClose: () => props.setChangesOpen(false) }) : null
2498
2766
  ] });
2499
2767
  }
2500
2768
  function ProviderCard(props) {
2501
2769
  const ready = props.status.ready;
2502
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2770
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2503
2771
  "button",
2504
2772
  {
2505
2773
  type: "button",
2506
2774
  onClick: props.onSelect,
2507
2775
  "aria-pressed": props.selected,
2508
- className: (0, import_design_system5.cn)(
2776
+ className: (0, import_design_system6.cn)(
2509
2777
  "flex flex-1 flex-col gap-1.5 rounded-xl border px-3.5 py-3 text-left transition-colors",
2510
2778
  props.selected ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-border hover:bg-accent/50"
2511
2779
  ),
2512
2780
  children: [
2513
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-center gap-2", children: [
2514
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProviderMark, { provider: props.status.provider, size: 18 }),
2515
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[13.5px] font-semibold", children: props.status.label })
2781
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "flex items-center gap-2", children: [
2782
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProviderMark, { provider: props.status.provider, size: 18 }),
2783
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[13.5px] font-semibold", children: props.status.label })
2516
2784
  ] }),
2517
- ready ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-center gap-1 text-[12px] text-success", children: [
2518
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CheckIcon, { size: 13 }),
2785
+ ready ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "flex items-center gap-1 text-[12px] text-success", children: [
2786
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckIcon, { size: 13 }),
2519
2787
  props.status.billing === "subscription" ? `Signed in${props.status.plan ? ` \xB7 ${props.status.plan} plan` : ""}` : "Signed in with an API key (billed per use)"
2520
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-start gap-1 text-[12px] leading-4 text-warning", children: [
2521
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlertIcon, { size: 13, className: "mt-px shrink-0" }),
2788
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "flex items-start gap-1 text-[12px] leading-4 text-warning", children: [
2789
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 13, className: "mt-px shrink-0" }),
2522
2790
  props.status.problem
2523
2791
  ] }),
2524
- props.status.quota.filter((w) => w.usedPercent !== null).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[11.5px] leading-4 text-muted-foreground", children: props.status.quota.filter((w) => w.usedPercent !== null).map((w) => `${w.label}: ${w.usedPercent}% used`).join(" \xB7 ") }) : null
2792
+ props.status.quota.filter((w) => w.usedPercent !== null).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[11.5px] leading-4 text-muted-foreground", children: props.status.quota.filter((w) => w.usedPercent !== null).map((w) => `${w.label}: ${w.usedPercent}% used`).join(" \xB7 ") }) : null
2525
2793
  ]
2526
2794
  }
2527
2795
  );
2528
2796
  }
2529
2797
  function FieldError({ id, children }) {
2530
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { id, role: "alert", className: "flex items-start gap-1.5 text-[12.5px] leading-5 text-destructive", children: [
2531
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlertIcon, { size: 14, className: "mt-0.5 shrink-0" }),
2532
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children })
2798
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { id, role: "alert", className: "flex items-start gap-1.5 text-[12.5px] leading-5 text-destructive", children: [
2799
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 14, className: "mt-0.5 shrink-0" }),
2800
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children })
2533
2801
  ] });
2534
2802
  }
2535
2803
  function NewSessionDialog(props) {
2536
2804
  const client = useCodingSessionsClient();
2537
2805
  const state = useCodingSessionsState();
2538
2806
  const now = useMinuteClock();
2539
- const [provider, setProvider] = (0, import_react6.useState)("claude");
2540
- const [folder, setFolder] = (0, import_react6.useState)("");
2541
- const [choice, setChoice] = (0, import_react6.useState)({ model: null, effort: null });
2542
- const [prompt, setPrompt] = (0, import_react6.useState)("");
2543
- const [errors, setErrors] = (0, import_react6.useState)({});
2544
- const [problem, setProblem] = (0, import_react6.useState)(null);
2545
- const [starting, setStarting] = (0, import_react6.useState)(false);
2546
- const [creating, setCreating] = (0, import_react6.useState)(false);
2547
- const promptRef = (0, import_react6.useRef)(null);
2548
- const folderRef = (0, import_react6.useRef)(null);
2549
- const agentRef = (0, import_react6.useRef)(null);
2550
- (0, import_react6.useEffect)(() => {
2807
+ const [provider, setProvider] = (0, import_react8.useState)("claude");
2808
+ const [folder, setFolder] = (0, import_react8.useState)("");
2809
+ const [choice, setChoice] = (0, import_react8.useState)({ model: null, effort: null });
2810
+ const [prompt, setPrompt] = (0, import_react8.useState)("");
2811
+ const [errors, setErrors] = (0, import_react8.useState)({});
2812
+ const [problem, setProblem] = (0, import_react8.useState)(null);
2813
+ const [starting, setStarting] = (0, import_react8.useState)(false);
2814
+ const [creating, setCreating] = (0, import_react8.useState)(false);
2815
+ const [agent, setAgent] = (0, import_react8.useState)(null);
2816
+ const [agentDetails, setAgentDetails] = (0, import_react8.useState)(null);
2817
+ const [agentMissing, setAgentMissing] = (0, import_react8.useState)(null);
2818
+ const promptRef = (0, import_react8.useRef)(null);
2819
+ const folderRef = (0, import_react8.useRef)(null);
2820
+ const agentRef = (0, import_react8.useRef)(null);
2821
+ (0, import_react8.useEffect)(() => {
2551
2822
  if (!props.open) return;
2552
2823
  setProblem(null);
2553
2824
  setErrors({});
2554
2825
  void client.refreshProviders();
2555
2826
  void client.refreshFolders();
2556
2827
  }, [props.open, client]);
2557
- (0, import_react6.useEffect)(() => {
2828
+ (0, import_react8.useEffect)(() => {
2558
2829
  if (!folder && state.folders.data[0]?.exists) setFolder(state.folders.data[0].path);
2559
2830
  }, [state.folders.data, folder]);
2560
- (0, import_react6.useEffect)(() => {
2831
+ (0, import_react8.useEffect)(() => {
2561
2832
  const ready = state.providers.data.filter((p) => p.ready);
2562
2833
  const current = state.providers.data.find((p) => p.provider === provider);
2563
2834
  if (current && !current.ready && ready[0]) setProvider(ready[0].provider);
@@ -2583,9 +2854,22 @@ function NewSessionDialog(props) {
2583
2854
  focusField(first);
2584
2855
  return;
2585
2856
  }
2857
+ const missing = missingRequiredVariable(agentDetails, agent);
2858
+ setAgentMissing(missing);
2859
+ if (missing) {
2860
+ document.getElementById(`cs-agent-var-${missing}`)?.focus();
2861
+ return;
2862
+ }
2586
2863
  setStarting(true);
2587
2864
  try {
2588
- const result = await client.start({ provider, cwd: folder.trim(), prompt, model: choice.model, effort: choice.effort });
2865
+ const result = await client.start({
2866
+ provider,
2867
+ cwd: folder.trim(),
2868
+ prompt,
2869
+ model: choice.model,
2870
+ effort: choice.effort,
2871
+ ...agent ? { agent } : {}
2872
+ });
2589
2873
  setPrompt("");
2590
2874
  props.onStarted(result.session.id);
2591
2875
  } catch (error) {
@@ -2621,16 +2905,16 @@ function NewSessionDialog(props) {
2621
2905
  if (field === "folder") delete next.createFolder;
2622
2906
  return next;
2623
2907
  });
2624
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogContent, { className: "max-w-[560px]", children: [
2625
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogHeader, { children: [
2626
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DialogTitle, { children: "New coding session" }),
2627
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogDescription, { children: [
2908
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogContent, { className: "max-w-[560px]", children: [
2909
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogHeader, { children: [
2910
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.DialogTitle, { children: "New coding session" }),
2911
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogDescription, { children: [
2628
2912
  "Runs on your own ",
2629
2913
  provider === "claude" ? "Claude" : "ChatGPT",
2630
2914
  " sign-in, in a folder on this computer."
2631
2915
  ] })
2632
2916
  ] }),
2633
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2917
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2634
2918
  "form",
2635
2919
  {
2636
2920
  noValidate: true,
@@ -2640,13 +2924,13 @@ function NewSessionDialog(props) {
2640
2924
  },
2641
2925
  className: "flex min-h-0 flex-col",
2642
2926
  children: [
2643
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "cs-dialog-body space-y-5 py-1 pr-1", children: [
2644
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { className: "space-y-2", ref: agentRef, children: [
2645
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Agent" }),
2646
- state.providers.loading && state.providers.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-2", children: [
2647
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "cs-skeleton h-[68px] flex-1 rounded-xl" }),
2648
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "cs-skeleton h-[68px] flex-1 rounded-xl" })
2649
- ] }) : state.providers.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-[12.5px] text-destructive", children: state.providers.error }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex gap-2", children: state.providers.data.map((p) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2927
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "cs-dialog-body space-y-5 py-1 pr-1", children: [
2928
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "space-y-2", ref: agentRef, children: [
2929
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Agent" }),
2930
+ state.providers.loading && state.providers.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-2", children: [
2931
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "cs-skeleton h-[68px] flex-1 rounded-xl" }),
2932
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "cs-skeleton h-[68px] flex-1 rounded-xl" })
2933
+ ] }) : state.providers.error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-[12.5px] text-destructive", children: state.providers.error }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex gap-2", children: state.providers.data.map((p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2650
2934
  ProviderCard,
2651
2935
  {
2652
2936
  status: p,
@@ -2659,14 +2943,31 @@ function NewSessionDialog(props) {
2659
2943
  },
2660
2944
  p.provider
2661
2945
  )) }),
2662
- errors.agent ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FieldError, { id: "cs-err-agent", children: errors.agent }) : selected && !selected.ready && selected.fix ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "text-[12px] leading-4 text-muted-foreground", children: [
2946
+ errors.agent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldError, { id: "cs-err-agent", children: errors.agent }) : selected && !selected.ready && selected.fix ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "text-[12px] leading-4 text-muted-foreground", children: [
2663
2947
  selected.fix,
2664
2948
  selected.installed && selected.loggedIn ? " You can still try \u2014 the run will say if it's still blocked." : ""
2665
2949
  ] }) : null
2666
2950
  ] }),
2667
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { className: "space-y-2", children: [
2668
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Folder" }),
2669
- state.folders.data.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "max-h-[132px] space-y-0.5 overflow-y-auto rounded-lg border border-border p-1", children: state.folders.data.map((f) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2951
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "space-y-2", children: [
2952
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "AI Matrx agent" }),
2953
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2954
+ AgentField,
2955
+ {
2956
+ transport: client.transport,
2957
+ open: props.open,
2958
+ value: agent,
2959
+ onChange: (next) => {
2960
+ setAgent(next);
2961
+ setAgentMissing(null);
2962
+ },
2963
+ missing: agentMissing,
2964
+ onDetails: setAgentDetails
2965
+ }
2966
+ )
2967
+ ] }),
2968
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "space-y-2", children: [
2969
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Folder" }),
2970
+ state.folders.data.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "max-h-[132px] space-y-0.5 overflow-y-auto rounded-lg border border-border p-1", children: state.folders.data.map((f) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2670
2971
  "button",
2671
2972
  {
2672
2973
  type: "button",
@@ -2676,21 +2977,21 @@ function NewSessionDialog(props) {
2676
2977
  },
2677
2978
  disabled: !f.exists,
2678
2979
  title: f.exists ? f.path : `${f.path} no longer exists`,
2679
- className: (0, import_design_system5.cn)(
2980
+ className: (0, import_design_system6.cn)(
2680
2981
  "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[12.5px]",
2681
2982
  folder === f.path ? "bg-accent text-accent-foreground" : "hover:bg-accent/50",
2682
2983
  !f.exists && "opacity-50"
2683
2984
  ),
2684
2985
  children: [
2685
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FolderIcon, { size: 14, className: "shrink-0 text-muted-foreground" }),
2686
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "min-w-0 flex-1 truncate", children: prettyPath2(f.path) }),
2687
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: f.exists ? relativeTime(f.lastUsedAt, now) : "missing" })
2986
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FolderIcon, { size: 14, className: "shrink-0 text-muted-foreground" }),
2987
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "min-w-0 flex-1 truncate", children: prettyPath2(f.path) }),
2988
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: f.exists ? relativeTime(f.lastUsedAt, now) : "missing" })
2688
2989
  ]
2689
2990
  },
2690
2991
  f.path
2691
- )) }) : state.folders.loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "cs-skeleton h-10 rounded-lg" }) : null,
2692
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2693
- import_design_system5.Input,
2992
+ )) }) : state.folders.loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "cs-skeleton h-10 rounded-lg" }) : null,
2993
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2994
+ import_design_system6.Input,
2694
2995
  {
2695
2996
  ref: folderRef,
2696
2997
  value: folder,
@@ -2705,18 +3006,18 @@ function NewSessionDialog(props) {
2705
3006
  spellCheck: false
2706
3007
  }
2707
3008
  ),
2708
- errors.folder ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1", children: [
2709
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FieldError, { id: "cs-err-folder", children: errors.folder }),
2710
- errors.createFolder ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.Button, { type: "button", size: "sm", variant: "outline", onClick: () => void createFolder(), disabled: creating, className: "gap-1.5", children: [
2711
- creating ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FolderIcon, { size: 13 }),
3009
+ errors.folder ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1", children: [
3010
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldError, { id: "cs-err-folder", children: errors.folder }),
3011
+ errors.createFolder ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.Button, { type: "button", size: "sm", variant: "outline", onClick: () => void createFolder(), disabled: creating, className: "gap-1.5", children: [
3012
+ creating ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FolderIcon, { size: 13 }),
2712
3013
  "Create this folder"
2713
3014
  ] }) : null
2714
3015
  ] }) : null
2715
3016
  ] }),
2716
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { className: "space-y-2", children: [
2717
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "What should it do?" }),
2718
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2719
- import_design_system5.Textarea,
3017
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "space-y-2", children: [
3018
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "What should it do?" }),
3019
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3020
+ import_design_system6.Textarea,
2720
3021
  {
2721
3022
  ref: promptRef,
2722
3023
  value: prompt,
@@ -2737,25 +3038,25 @@ function NewSessionDialog(props) {
2737
3038
  "aria-describedby": errors.prompt ? "cs-err-prompt" : void 0
2738
3039
  }
2739
3040
  ),
2740
- errors.prompt ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FieldError, { id: "cs-err-prompt", children: errors.prompt }) : null
3041
+ errors.prompt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldError, { id: "cs-err-prompt", children: errors.prompt }) : null
2741
3042
  ] }),
2742
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("fieldset", { className: "space-y-2", children: [
2743
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Model and thinking effort" }),
2744
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ModelPicker, { status: selected, value: choice, onChange: setChoice, appearance: "field" }),
2745
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "text-[11.5px] leading-4 text-muted-foreground", children: [
3043
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "space-y-2", children: [
3044
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Model and thinking effort" }),
3045
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ModelPicker, { status: selected, value: choice, onChange: setChoice, appearance: "field" }),
3046
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "text-[11.5px] leading-4 text-muted-foreground", children: [
2746
3047
  "Default is ",
2747
3048
  defaultModelWords(selected),
2748
3049
  ". You can change it later from the chat's header."
2749
3050
  ] })
2750
3051
  ] }),
2751
- problem ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FieldError, { id: "cs-err-start", children: problem }) : null
3052
+ problem ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldError, { id: "cs-err-start", children: problem }) : null
2752
3053
  ] }),
2753
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogFooter, { className: "pt-4", children: [
2754
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.Button, { type: "button", variant: "ghost", onClick: () => props.onOpenChange(false), children: "Cancel" }),
2755
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.Button, { type: "submit", disabled: starting, className: "gap-1.5", children: [
2756
- starting ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 14 }) : null,
3054
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogFooter, { className: "pt-4", children: [
3055
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Button, { type: "button", variant: "ghost", onClick: () => props.onOpenChange(false), children: "Cancel" }),
3056
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.Button, { type: "submit", disabled: starting, className: "gap-1.5", children: [
3057
+ starting ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 14 }) : null,
2757
3058
  starting ? "Starting\u2026" : "Start session",
2758
- !starting ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("kbd", { className: "cs-kbd", children: "\u2318\u21B5" }) : null
3059
+ !starting ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("kbd", { className: "cs-kbd", children: "\u2318\u21B5" }) : null
2759
3060
  ] })
2760
3061
  ] })
2761
3062
  ]
@@ -2765,50 +3066,61 @@ function NewSessionDialog(props) {
2765
3066
  }
2766
3067
  function Home({ onNew }) {
2767
3068
  const state = useCodingSessionsState();
2768
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("section", { className: "flex flex-1 items-center justify-center px-6", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "w-full max-w-[460px] text-center", children: [
2769
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-auto mb-4 flex h-11 w-11 items-center justify-center rounded-2xl bg-primary/10 text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatBubbleIcon, { size: 22 }) }),
2770
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h1", { className: "text-[19px] font-semibold tracking-[-0.015em]", children: "Drive Claude Code and Codex from here" }),
2771
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-auto mt-2 max-w-[400px] text-[13.5px] leading-6 text-muted-foreground", children: "Start a session in any folder, or pick up a chat you began somewhere else. Everything runs on your own subscriptions \u2014 no API keys." }),
2772
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.Button, { className: "mt-5 gap-1.5", onClick: onNew, children: [
2773
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PlusIcon, { size: 15 }),
3069
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("section", { className: "flex flex-1 items-center justify-center px-6", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "w-full max-w-[460px] text-center", children: [
3070
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "mx-auto mb-4 flex h-11 w-11 items-center justify-center rounded-2xl bg-primary/10 text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChatBubbleIcon, { size: 22 }) }),
3071
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { className: "text-[15px] font-semibold leading-5 tracking-[-0.01em]", children: "Drive Claude Code and Codex from here" }),
3072
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "mx-auto mt-2 max-w-[400px] text-[13.5px] leading-6 text-muted-foreground", children: "Start a session in any folder, or pick up a chat you began somewhere else. Everything runs on your own subscriptions \u2014 no API keys." }),
3073
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.Button, { className: "mt-5 gap-1.5", onClick: onNew, children: [
3074
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PlusIcon, { size: 15 }),
2774
3075
  "New session"
2775
3076
  ] }),
2776
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "mt-3 text-[12px] text-muted-foreground", children: [
2777
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("kbd", { className: "cs-kbd", children: "\u2325\u2318N" }),
3077
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "mt-3 text-[12px] text-muted-foreground", children: [
3078
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("kbd", { className: "cs-kbd", children: "\u2325\u2318N" }),
2778
3079
  " new session \xB7 ",
2779
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("kbd", { className: "cs-kbd", children: "\u2318K" }),
3080
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("kbd", { className: "cs-kbd", children: "\u2318K" }),
2780
3081
  " search your chats \xB7",
2781
3082
  " ",
2782
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("kbd", { className: "cs-kbd", children: "\u2318/" }),
3083
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("kbd", { className: "cs-kbd", children: "\u2318/" }),
2783
3084
  " all shortcuts"
2784
3085
  ] }),
2785
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mt-6 space-y-1.5 text-left", children: state.providers.data.map((p) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-start gap-2.5 rounded-lg border border-border px-3 py-2.5", children: [
2786
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProviderMark, { provider: p.provider, size: 18 }),
2787
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "min-w-0 flex-1 text-[12.5px] leading-5", children: [
2788
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-medium", children: p.label }),
2789
- p.ready ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-muted-foreground", children: [
3086
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-6 grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-1.5 text-left", children: state.providers.data.map((p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-[220px] items-start gap-2.5 rounded-lg border border-border px-3 py-2.5", children: [
3087
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProviderMark, { provider: p.provider, size: 16 }),
3088
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "min-w-0 flex-1 text-[12.5px] leading-5", children: [
3089
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-medium", children: p.label }),
3090
+ p.ready ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "text-muted-foreground", children: [
2790
3091
  " ",
2791
3092
  "\u2014 ready",
2792
3093
  p.plan ? ` on your ${p.plan} plan` : "",
2793
- p.billing === "api" ? " (API key, billed per use)" : "",
2794
- p.version ? ` \xB7 version ${p.version}` : ""
2795
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "block text-muted-foreground", children: [
3094
+ p.billing === "api" ? " (API key, billed per use)" : ""
3095
+ ] }) : null,
3096
+ p.installed && p.version ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3097
+ "span",
3098
+ {
3099
+ className: "block text-[11.5px] text-muted-foreground",
3100
+ title: newerWords(p) ?? p.binary?.path ?? void 0,
3101
+ children: [
3102
+ binaryWords(p),
3103
+ p.binary?.newer ? ` \xB7 ${p.binary.newer.version} available` : ""
3104
+ ]
3105
+ }
3106
+ ) : null,
3107
+ p.ready ? null : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "block text-muted-foreground", children: [
2796
3108
  p.problem,
2797
3109
  " ",
2798
3110
  p.fix
2799
3111
  ] })
2800
3112
  ] }),
2801
- p.ready ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CheckIcon, { size: 15, className: "mt-0.5 text-success" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlertIcon, { size: 15, className: "mt-0.5 text-warning" })
3113
+ p.ready ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckIcon, { size: 15, className: "mt-0.5 text-success" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "mt-0.5 text-warning" })
2802
3114
  ] }, p.provider)) })
2803
3115
  ] }) });
2804
3116
  }
2805
3117
  function useToast() {
2806
- const [text, setText] = (0, import_react6.useState)(null);
2807
- const timer = (0, import_react6.useRef)(null);
2808
- (0, import_react6.useEffect)(() => () => {
3118
+ const [text, setText] = (0, import_react8.useState)(null);
3119
+ const timer = (0, import_react8.useRef)(null);
3120
+ (0, import_react8.useEffect)(() => () => {
2809
3121
  if (timer.current) clearTimeout(timer.current);
2810
3122
  }, []);
2811
- const show = (0, import_react6.useCallback)((next) => {
3123
+ const show = (0, import_react8.useCallback)((next) => {
2812
3124
  setText(next);
2813
3125
  if (timer.current) clearTimeout(timer.current);
2814
3126
  timer.current = setTimeout(() => setText(null), 6e3);
@@ -2817,7 +3129,7 @@ function useToast() {
2817
3129
  }
2818
3130
  function Toast({ text }) {
2819
3131
  if (!text) return null;
2820
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { role: "status", className: "cs-toast", children: text });
3132
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { role: "status", className: "cs-toast", children: text });
2821
3133
  }
2822
3134
  var SIDEBAR_DEFAULT = 300;
2823
3135
  var SIDEBAR_MIN = 220;
@@ -2826,7 +3138,7 @@ function clampWidth(n) {
2826
3138
  return Math.round(Math.min(SIDEBAR_MAX, Math.max(SIDEBAR_MIN, n)));
2827
3139
  }
2828
3140
  function useSidebarLayout() {
2829
- const [width, setWidthState] = (0, import_react6.useState)(() => {
3141
+ const [width, setWidthState] = (0, import_react8.useState)(() => {
2830
3142
  try {
2831
3143
  const n = Number(localStorage.getItem("coding-sessions.sidebar-width"));
2832
3144
  return Number.isFinite(n) && n > 0 ? clampWidth(n) : SIDEBAR_DEFAULT;
@@ -2834,14 +3146,14 @@ function useSidebarLayout() {
2834
3146
  return SIDEBAR_DEFAULT;
2835
3147
  }
2836
3148
  });
2837
- const [collapsed, setCollapsedState] = (0, import_react6.useState)(() => {
3149
+ const [collapsed, setCollapsedState] = (0, import_react8.useState)(() => {
2838
3150
  try {
2839
3151
  return localStorage.getItem("coding-sessions.sidebar-collapsed") === "1";
2840
3152
  } catch {
2841
3153
  return false;
2842
3154
  }
2843
3155
  });
2844
- const setWidth = (0, import_react6.useCallback)((n) => {
3156
+ const setWidth = (0, import_react8.useCallback)((n) => {
2845
3157
  const next = clampWidth(n);
2846
3158
  setWidthState(next);
2847
3159
  try {
@@ -2849,7 +3161,7 @@ function useSidebarLayout() {
2849
3161
  } catch {
2850
3162
  }
2851
3163
  }, []);
2852
- const setCollapsed = (0, import_react6.useCallback)((v) => {
3164
+ const setCollapsed = (0, import_react8.useCallback)((v) => {
2853
3165
  setCollapsedState(v);
2854
3166
  try {
2855
3167
  localStorage.setItem("coding-sessions.sidebar-collapsed", v ? "1" : "0");
@@ -2859,8 +3171,8 @@ function useSidebarLayout() {
2859
3171
  return { width, setWidth, collapsed, setCollapsed };
2860
3172
  }
2861
3173
  function Resizer(props) {
2862
- const [dragging, setDragging] = (0, import_react6.useState)(false);
2863
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: (0, import_design_system5.cn)("cs-resizer", dragging && "cs-resizer--dragging"), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3174
+ const [dragging, setDragging] = (0, import_react8.useState)(false);
3175
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: (0, import_design_system6.cn)("cs-resizer", dragging && "cs-resizer--dragging"), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2864
3176
  "button",
2865
3177
  {
2866
3178
  type: "button",
@@ -2908,24 +3220,24 @@ var SHORTCUTS = [
2908
3220
  { keys: "\u2318/", what: "These shortcuts" }
2909
3221
  ];
2910
3222
  function ShortcutsDialog(props) {
2911
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogContent, { className: "max-w-[420px]", children: [
2912
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DialogHeader, { children: [
2913
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DialogTitle, { children: "Keyboard shortcuts" }),
2914
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DialogDescription, { children: "Ctrl works in place of \u2318 on Windows and Linux." })
3223
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogContent, { className: "max-w-[420px]", children: [
3224
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogHeader, { children: [
3225
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.DialogTitle, { children: "Keyboard shortcuts" }),
3226
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.DialogDescription, { children: "Ctrl works in place of \u2318 on Windows and Linux." })
2915
3227
  ] }),
2916
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dl", { className: "divide-y divide-border text-[13px]", children: SHORTCUTS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between gap-4 py-2", children: [
2917
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dt", { className: "text-muted-foreground", children: s.what }),
2918
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("kbd", { className: "rounded border border-border px-1.5 py-0.5 font-sans text-[12px]", children: s.keys }) })
3228
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dl", { className: "divide-y divide-border text-[13px]", children: SHORTCUTS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between gap-4 py-2", children: [
3229
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dt", { className: "text-muted-foreground", children: s.what }),
3230
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("kbd", { className: "rounded border border-border px-1.5 py-0.5 font-sans text-[12px]", children: s.keys }) })
2919
3231
  ] }, s.keys)) })
2920
3232
  ] }) });
2921
3233
  }
2922
3234
  var BASE_TITLE = "Coding sessions";
2923
3235
  function useRunFinishedNotices(openSessionId, show) {
2924
3236
  const client = useCodingSessionsClient();
2925
- const unseen = (0, import_react6.useRef)(0);
2926
- const openRef = (0, import_react6.useRef)(openSessionId);
3237
+ const unseen = (0, import_react8.useRef)(0);
3238
+ const openRef = (0, import_react8.useRef)(openSessionId);
2927
3239
  openRef.current = openSessionId;
2928
- (0, import_react6.useEffect)(() => {
3240
+ (0, import_react8.useEffect)(() => {
2929
3241
  const reset = () => {
2930
3242
  if (document.visibilityState === "visible") {
2931
3243
  unseen.current = 0;
@@ -2941,7 +3253,7 @@ function useRunFinishedNotices(openSessionId, show) {
2941
3253
  unseen.current += 1;
2942
3254
  document.title = `(${unseen.current}) ${BASE_TITLE}`;
2943
3255
  if (typeof Notification !== "undefined" && Notification.permission === "granted") {
2944
- const note = new Notification(sentence, run.error ? { tag: run.runId, body: run.error } : { tag: run.runId });
3256
+ const note = new Notification(sentence, run.error ? { tag: run.runId, body: runErrorLabel(run.error) } : { tag: run.runId });
2945
3257
  note.onclick = () => {
2946
3258
  window.focus();
2947
3259
  location.hash = `#s/${run.sessionId}`;
@@ -2960,9 +3272,9 @@ function useRunFinishedNotices(openSessionId, show) {
2960
3272
  }
2961
3273
  function NotifyToggle() {
2962
3274
  const supported = typeof Notification !== "undefined";
2963
- const [permission, setPermission] = (0, import_react6.useState)(supported ? Notification.permission : "denied");
3275
+ const [permission, setPermission] = (0, import_react8.useState)(supported ? Notification.permission : "denied");
2964
3276
  if (!supported || permission === "granted") return null;
2965
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3277
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2966
3278
  "button",
2967
3279
  {
2968
3280
  type: "button",
@@ -2971,7 +3283,7 @@ function NotifyToggle() {
2971
3283
  "aria-label": permission === "denied" ? "Notifications are blocked for this page in your browser's site settings" : "Notify me when a run finishes",
2972
3284
  title: permission === "denied" ? "Notifications are blocked in your browser's site settings" : "Notify me when a run finishes",
2973
3285
  disabled: permission === "denied",
2974
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BellIcon, { size: 14 })
3286
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BellIcon, { size: 14 })
2975
3287
  }
2976
3288
  );
2977
3289
  }
@@ -2983,20 +3295,20 @@ function isTyping(target) {
2983
3295
  function Shell() {
2984
3296
  const client = useCodingSessionsClient();
2985
3297
  const state = useCodingSessionsState();
2986
- const [selection, setSelection] = (0, import_react6.useState)(readHash);
2987
- const [newOpen, setNewOpen] = (0, import_react6.useState)(false);
2988
- const [shortcutsOpen, setShortcutsOpen] = (0, import_react6.useState)(false);
2989
- const [changesOpen, setChangesOpen] = (0, import_react6.useState)(false);
2990
- const [found, setFound] = (0, import_react6.useState)({});
3298
+ const [selection, setSelection] = (0, import_react8.useState)(readHash);
3299
+ const [newOpen, setNewOpen] = (0, import_react8.useState)(false);
3300
+ const [shortcutsOpen, setShortcutsOpen] = (0, import_react8.useState)(false);
3301
+ const [changesOpen, setChangesOpen] = (0, import_react8.useState)(false);
3302
+ const [found, setFound] = (0, import_react8.useState)({});
2991
3303
  const [theme, setTheme] = useTheme();
2992
3304
  const [toast, showToast] = useToast();
2993
3305
  const layout = useSidebarLayout();
2994
- const searchRef = (0, import_react6.useRef)(null);
2995
- const select = (0, import_react6.useCallback)((next) => {
3306
+ const searchRef = (0, import_react8.useRef)(null);
3307
+ const select = (0, import_react8.useCallback)((next) => {
2996
3308
  setSelection(next);
2997
3309
  writeHash(next);
2998
3310
  }, []);
2999
- (0, import_react6.useEffect)(() => {
3311
+ (0, import_react8.useEffect)(() => {
3000
3312
  const onHash = () => setSelection(readHash());
3001
3313
  window.addEventListener("hashchange", onHash);
3002
3314
  return () => window.removeEventListener("hashchange", onHash);
@@ -3006,14 +3318,14 @@ function Shell() {
3006
3318
  const discovered = selection.kind === "discovered" ? state.discovered.data.find((d) => d.providerSessionId === selection.id) ?? found[`${selection.provider}:${selection.id}`] ?? null : null;
3007
3319
  const run = session ? state.runs[session.id] : void 0;
3008
3320
  const live = run !== void 0 && !isTerminalRunStatus(run.status);
3009
- const order = (0, import_react6.useMemo)(() => {
3321
+ const order = (0, import_react8.useMemo)(() => {
3010
3322
  const known = new Set(state.sessions.data.map((s) => s.providerSessionId).filter(Boolean));
3011
3323
  return [
3012
3324
  ...state.sessions.data.map((s) => ({ kind: "session", id: s.id })),
3013
3325
  ...state.discovered.data.filter((d) => !known.has(d.providerSessionId)).map((d) => ({ kind: "discovered", provider: d.provider, id: d.providerSessionId }))
3014
3326
  ];
3015
3327
  }, [state.sessions.data, state.discovered.data]);
3016
- (0, import_react6.useEffect)(() => {
3328
+ (0, import_react8.useEffect)(() => {
3017
3329
  const onKey = (e) => {
3018
3330
  const mod = e.metaKey || e.ctrlKey;
3019
3331
  const key = e.key.toLowerCase();
@@ -3069,12 +3381,12 @@ function Shell() {
3069
3381
  }, [client, layout, live, run, order, selection, select, showToast]);
3070
3382
  let main;
3071
3383
  if (selection.kind === "session") {
3072
- main = session ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SessionView, { session, changesOpen, setChangesOpen }, session.id) : state.sessions.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
3073
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 15 }),
3384
+ main = session ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SessionView, { session, changesOpen, setChangesOpen }, session.id) : state.sessions.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
3385
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 15 }),
3074
3386
  " Loading\u2026"
3075
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex flex-1 items-center justify-center text-[13px] text-muted-foreground", children: "That session is not in the list anymore." });
3387
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-1 items-center justify-center text-[13px] text-muted-foreground", children: "That session is not in the list anymore." });
3076
3388
  } else if (selection.kind === "discovered") {
3077
- main = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3389
+ main = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3078
3390
  DiscoveredView,
3079
3391
  {
3080
3392
  session: discovered,
@@ -3087,13 +3399,13 @@ function Shell() {
3087
3399
  `${selection.provider}:${selection.id}`
3088
3400
  );
3089
3401
  } else {
3090
- main = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Home, { onNew: () => setNewOpen(true) });
3402
+ main = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Home, { onNew: () => setNewOpen(true) });
3091
3403
  }
3092
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToastContext.Provider, { value: showToast, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "cs-app flex h-full flex-col bg-background text-foreground", children: [
3093
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ConnectionBanner, {}),
3094
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-h-0 flex-1", children: [
3095
- layout.collapsed ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col items-center gap-1 border-r border-border bg-muted/30 px-1.5 py-3", children: [
3096
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3404
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToastContext.Provider, { value: showToast, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "cs-app flex h-full flex-col bg-background text-foreground", children: [
3405
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ConnectionBanner, {}),
3406
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-h-0 flex-1", children: [
3407
+ layout.collapsed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col items-center gap-1 border-r border-border bg-muted/30 px-1.5 py-3", children: [
3408
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3097
3409
  "button",
3098
3410
  {
3099
3411
  type: "button",
@@ -3101,10 +3413,10 @@ function Shell() {
3101
3413
  onClick: () => layout.setCollapsed(false),
3102
3414
  "aria-label": "Show the sidebar (\u2318B)",
3103
3415
  title: "Show sidebar \u2318B",
3104
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SidebarIcon, { size: 15 })
3416
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SidebarIcon, { size: 15 })
3105
3417
  }
3106
3418
  ),
3107
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3419
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3108
3420
  "button",
3109
3421
  {
3110
3422
  type: "button",
@@ -3112,11 +3424,11 @@ function Shell() {
3112
3424
  onClick: () => setNewOpen(true),
3113
3425
  "aria-label": "New session",
3114
3426
  title: "New session \u2325\u2318N",
3115
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PlusIcon, { size: 15 })
3427
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PlusIcon, { size: 15 })
3116
3428
  }
3117
3429
  )
3118
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3119
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3430
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
3431
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3120
3432
  Sidebar,
3121
3433
  {
3122
3434
  selection,
@@ -3126,14 +3438,14 @@ function Shell() {
3126
3438
  width: layout.width,
3127
3439
  searchRef,
3128
3440
  onFound: (d) => setFound((f) => ({ ...f, [`${d.provider}:${d.providerSessionId}`]: d })),
3129
- footer: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3441
+ footer: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3130
3442
  ProvidersFooter,
3131
3443
  {
3132
3444
  theme,
3133
3445
  setTheme,
3134
- extra: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3135
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NotifyToggle, {}),
3136
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3446
+ extra: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
3447
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(NotifyToggle, {}),
3448
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3137
3449
  "button",
3138
3450
  {
3139
3451
  type: "button",
@@ -3141,7 +3453,7 @@ function Shell() {
3141
3453
  onClick: () => setShortcutsOpen(true),
3142
3454
  "aria-label": "Keyboard shortcuts (\u2318/)",
3143
3455
  title: "Keyboard shortcuts \u2318/",
3144
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(KeyboardIcon, { size: 14 })
3456
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(KeyboardIcon, { size: 14 })
3145
3457
  }
3146
3458
  )
3147
3459
  ] })
@@ -3149,11 +3461,11 @@ function Shell() {
3149
3461
  )
3150
3462
  }
3151
3463
  ),
3152
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Resizer, { width: layout.width, setWidth: layout.setWidth })
3464
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Resizer, { width: layout.width, setWidth: layout.setWidth })
3153
3465
  ] }),
3154
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("main", { className: "flex min-w-0 flex-1", children: main })
3466
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("main", { className: "flex min-w-0 flex-1", children: main })
3155
3467
  ] }),
3156
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3468
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3157
3469
  NewSessionDialog,
3158
3470
  {
3159
3471
  open: newOpen,
@@ -3164,11 +3476,11 @@ function Shell() {
3164
3476
  }
3165
3477
  }
3166
3478
  ),
3167
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ShortcutsDialog, { open: shortcutsOpen, onOpenChange: setShortcutsOpen }),
3168
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Toast, { text: toast })
3479
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ShortcutsDialog, { open: shortcutsOpen, onOpenChange: setShortcutsOpen }),
3480
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Toast, { text: toast })
3169
3481
  ] }) });
3170
3482
  }
3171
3483
  function CodingSessionsApp({ transport }) {
3172
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CodingSessionsProvider, { transport, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Shell, {}) });
3484
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CodingSessionsProvider, { transport, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, {}) });
3173
3485
  }
3174
3486
  //# sourceMappingURL=index.cjs.map