@ai-matrx/coding-sessions 0.1.85 → 0.1.87

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.
@@ -1077,30 +1077,167 @@ var PART_LABEL = {
1077
1077
  skills: "Skills",
1078
1078
  tools: "Tools"
1079
1079
  };
1080
- function AgentChip({ agent }) {
1080
+ function agentChipText(agent) {
1081
1081
  const parts = agent.loaded.map(
1082
1082
  (part) => part.part === "instructions" ? `${PART_LABEL.instructions} ${part.loaded === 1 ? "\u2713" : "\u2014"}` : `${PART_LABEL[part.part]} ${part.loaded}/${part.total}`
1083
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
- ]
1084
+ return `${agent.name}${agent.versionNumber !== null ? ` v${agent.versionNumber}` : ""} \xB7 ${parts.join(" \xB7 ")}`;
1085
+ }
1086
+ function AgentMenu(props) {
1087
+ const { agent } = props;
1088
+ const show = useToastShow();
1089
+ const [open, setOpen] = (0, import_react5.useState)(false);
1090
+ const [choosing, setChoosing] = (0, import_react5.useState)(false);
1091
+ const [latest, setLatest] = (0, import_react5.useState)(null);
1092
+ const [access, setAccess] = (0, import_react5.useState)(null);
1093
+ (0, import_react5.useEffect)(() => {
1094
+ if (!open) return;
1095
+ let alive = true;
1096
+ void props.transport.call("agentAccess").then((next) => alive && setAccess(next)).catch(() => void 0);
1097
+ if (agent) {
1098
+ props.transport.call("agentDetails", agent.agentId).then((d) => {
1099
+ if (alive && d.latestVersionId && d.latestVersionNumber !== null) setLatest({ id: d.latestVersionId, number: d.latestVersionNumber });
1100
+ }).catch(() => void 0);
1102
1101
  }
1103
- );
1102
+ return () => {
1103
+ alive = false;
1104
+ };
1105
+ }, [open, agent, props.transport]);
1106
+ const apply = async (selection, done) => {
1107
+ try {
1108
+ await props.transport.call("setAgent", props.sessionId, selection);
1109
+ show(done);
1110
+ props.onChange();
1111
+ } catch (error) {
1112
+ show(`That didn't change: ${error instanceof Error ? error.message : String(error)}`);
1113
+ }
1114
+ };
1115
+ const behind = agent && latest && agent.versionNumber !== null && latest.number > agent.versionNumber ? latest : null;
1116
+ const complete = agent ? agent.loaded.every((part) => part.loaded === part.total) : true;
1117
+ const signedIn = access?.signedIn ?? false;
1118
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1119
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DropdownMenu, { open, onOpenChange: setOpen, children: [
1120
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1121
+ "button",
1122
+ {
1123
+ type: "button",
1124
+ className: (0, import_design_system4.cn)("cs-agent-chip", agent ? "cs-agent-chip--set" : "cs-agent-chip--none", !complete && "cs-agent-chip--partial"),
1125
+ "data-testid": "cs-agent-chip",
1126
+ "aria-label": agent ? `AI Matrx agent: ${agent.name}` : "Add an AI Matrx agent",
1127
+ children: [
1128
+ agent ? agentChipText(agent) : "No agent",
1129
+ behind ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "cs-agent-chip-dot", "aria-label": "Update available" }) : null,
1130
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronDownIcon, { size: 12, className: "ml-1 inline shrink-0" })
1131
+ ]
1132
+ }
1133
+ ) }),
1134
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DropdownMenuContent, { align: "end", className: "w-[320px]", children: [
1135
+ agent ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1136
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DropdownMenuLabel, { className: "truncate", children: [
1137
+ agent.name,
1138
+ agent.versionNumber !== null ? ` \xB7 v${agent.versionNumber}` : ""
1139
+ ] }),
1140
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cs-agent-parts", children: [
1141
+ agent.blockDue ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[12px] text-muted-foreground", children: "Sent with your next message" }) : null,
1142
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AgentPartList, { title: "Skills", items: agent.skills ?? [] }),
1143
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AgentPartList, { title: "Tools", items: agent.tools ?? [] }),
1144
+ agent.unavailable.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1145
+ AgentPartList,
1146
+ {
1147
+ title: "Not loaded",
1148
+ items: agent.unavailable.map((u) => `${u.name} \u2014 ${u.reason}`)
1149
+ }
1150
+ ) : null
1151
+ ] }),
1152
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuSeparator, {})
1153
+ ] }) : null,
1154
+ signedIn ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1155
+ behind && agent ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1156
+ import_design_system4.DropdownMenuItem,
1157
+ {
1158
+ onSelect: () => void apply(
1159
+ { agentId: agent.agentId, versionId: behind.id, variables: agent.variables ?? {} },
1160
+ `The next message uses ${agent.name} v${behind.number}.`
1161
+ ),
1162
+ children: [
1163
+ "Update to v",
1164
+ behind.number
1165
+ ]
1166
+ }
1167
+ ) : null,
1168
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuItem, { onSelect: () => setChoosing(true), children: agent ? "Change agent\u2026" : "Choose agent\u2026" }),
1169
+ agent ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuItem, { onSelect: () => void apply(null, "The next message runs without an agent."), children: "Remove agent" }) : null
1170
+ ] }) : access ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "px-2 py-1.5 text-[12px] text-muted-foreground", children: SIGNED_OUT_AGENTS }) : null
1171
+ ] })
1172
+ ] }),
1173
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1174
+ ChooseAgentDialog,
1175
+ {
1176
+ transport: props.transport,
1177
+ open: choosing,
1178
+ onOpenChange: setChoosing,
1179
+ title: agent ? "Change agent" : "Choose an agent",
1180
+ action: "Use this agent",
1181
+ onConfirm: (selection) => apply(selection, "The next message uses the new agent.")
1182
+ }
1183
+ )
1184
+ ] });
1185
+ }
1186
+ function AgentPartList({ title, items }) {
1187
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
1188
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "text-[11.5px] font-medium text-muted-foreground", children: [
1189
+ title,
1190
+ " \xB7 ",
1191
+ items.length
1192
+ ] }),
1193
+ items.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "cs-agent-part-list", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { className: "truncate", title: item, children: item }, item)) }) : null
1194
+ ] });
1195
+ }
1196
+ function ChooseAgentDialog(props) {
1197
+ const [value, setValue] = (0, import_react5.useState)(null);
1198
+ const [details, setDetails] = (0, import_react5.useState)(null);
1199
+ const [missing, setMissing] = (0, import_react5.useState)(null);
1200
+ const [busy, setBusy] = (0, import_react5.useState)(false);
1201
+ (0, import_react5.useEffect)(() => {
1202
+ if (props.open) {
1203
+ setValue(null);
1204
+ setMissing(null);
1205
+ }
1206
+ }, [props.open]);
1207
+ const confirm = async () => {
1208
+ if (!value) return;
1209
+ const gap = missingRequiredVariable(details, value);
1210
+ setMissing(gap);
1211
+ if (gap) return;
1212
+ setBusy(true);
1213
+ try {
1214
+ await props.onConfirm(value);
1215
+ props.onOpenChange(false);
1216
+ } finally {
1217
+ setBusy(false);
1218
+ }
1219
+ };
1220
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DialogContent, { className: "max-w-[480px]", children: [
1221
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DialogHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DialogTitle, { children: props.title }) }),
1222
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1223
+ AgentField,
1224
+ {
1225
+ transport: props.transport,
1226
+ open: props.open,
1227
+ value,
1228
+ onChange: (next) => {
1229
+ setValue(next);
1230
+ setMissing(null);
1231
+ },
1232
+ missing,
1233
+ onDetails: setDetails
1234
+ }
1235
+ ),
1236
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DialogFooter, { children: [
1237
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Button, { type: "button", variant: "ghost", onClick: () => props.onOpenChange(false), children: "Cancel" }),
1238
+ value ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Button, { type: "button", disabled: busy, onClick: () => void confirm(), children: props.action }) : null
1239
+ ] })
1240
+ ] }) });
1104
1241
  }
1105
1242
 
1106
1243
  // src/react/sidebar.tsx
@@ -2106,12 +2243,13 @@ var CodingSessionsClient = class {
2106
2243
  start(input) {
2107
2244
  return this.transport.call("start", input);
2108
2245
  }
2109
- takeover(session) {
2246
+ takeover(session, agent) {
2110
2247
  return this.transport.call("takeover", {
2111
2248
  provider: session.provider,
2112
2249
  providerSessionId: session.providerSessionId,
2113
2250
  cwd: session.cwd ?? "",
2114
- title: session.title
2251
+ title: session.title,
2252
+ ...agent ? { agent } : {}
2115
2253
  });
2116
2254
  }
2117
2255
  send(sessionId, prompt) {
@@ -2470,7 +2608,7 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
2470
2608
  ] }) : null
2471
2609
  ] })
2472
2610
  ] }),
2473
- session.agent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AgentChip, { agent: session.agent }) : null,
2611
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AgentMenu, { transport: client.transport, sessionId: session.id, agent: session.agent ?? null, onChange: () => void 0 }),
2474
2612
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2475
2613
  "button",
2476
2614
  {
@@ -2643,13 +2781,14 @@ function DiscoveredView(props) {
2643
2781
  if (elsewhere) setConfirming(true);
2644
2782
  else void takeover();
2645
2783
  };
2646
- const takeover = async () => {
2784
+ const [choosingAgent, setChoosingAgent] = (0, import_react8.useState)(false);
2785
+ const takeover = async (agent) => {
2647
2786
  if (!d) return;
2648
2787
  setConfirming(false);
2649
2788
  setBusy(true);
2650
2789
  setError(null);
2651
2790
  try {
2652
- const taken = await client.takeover(d);
2791
+ const taken = await client.takeover(d, agent);
2653
2792
  props.onTakenOver(taken.id);
2654
2793
  } catch (e) {
2655
2794
  setError(e instanceof Error ? e.message : String(e));
@@ -2705,6 +2844,18 @@ function DiscoveredView(props) {
2705
2844
  ]
2706
2845
  }
2707
2846
  ) : null,
2847
+ d?.cwd && !elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Button, { size: "sm", variant: "outline", onClick: () => setChoosingAgent(true), disabled: busy, children: "Continue with agent\u2026" }) : null,
2848
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2849
+ ChooseAgentDialog,
2850
+ {
2851
+ transport: client.transport,
2852
+ open: choosingAgent,
2853
+ onOpenChange: setChoosingAgent,
2854
+ title: "Continue with an agent",
2855
+ action: "Take over with this agent",
2856
+ onConfirm: (agent) => takeover(agent)
2857
+ }
2858
+ ),
2708
2859
  d ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderMenu, { entry, onRename: () => setRenaming(true) }) : null
2709
2860
  ] }),
2710
2861
  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: [