@ai-matrx/coding-sessions 0.1.85 → 0.1.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/engine/index.cjs +165 -44
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +1 -1
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.js +164 -45
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/worker.js +5 -3
- package/dist/engine/worker.js.map +1 -1
- package/dist/{index-DEPwyr2j.d.cts → index-aavbdzSo.d.cts} +35 -5
- package/dist/{index-DEPwyr2j.d.ts → index-aavbdzSo.d.ts} +35 -5
- package/dist/index.cjs +16 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +176 -25
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +27 -2
- package/dist/react/index.d.ts +27 -2
- package/dist/react/index.js +224 -62
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +163 -45
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +2 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +164 -46
- package/dist/server/index.js.map +1 -1
- package/dist/ui/assets/{index-DSWoryQZ.js → index-XIcCZr8A.js} +1 -2
- package/dist/ui/assets/index-eqe0sxR4.css +2 -0
- package/dist/ui/index.html +2 -2
- package/package.json +3 -3
- package/dist/ui/assets/index-Gp2bMDtx.css +0 -2
package/dist/react/index.d.cts
CHANGED
|
@@ -196,6 +196,8 @@ interface CodingSession {
|
|
|
196
196
|
queued: string[];
|
|
197
197
|
/** The AI Matrx agent loaded into every run of this session, when one was picked. */
|
|
198
198
|
agent?: SessionAgent | null | undefined;
|
|
199
|
+
/** Codex must be told, in the next prompt, that an earlier agent no longer applies. */
|
|
200
|
+
agentRemovedDue?: boolean | undefined;
|
|
199
201
|
}
|
|
200
202
|
/**
|
|
201
203
|
* One normalized transcript item — the same shape from Claude and Codex, from
|
|
@@ -309,6 +311,19 @@ interface SessionAgent {
|
|
|
309
311
|
name: string;
|
|
310
312
|
reason: string;
|
|
311
313
|
}[];
|
|
314
|
+
/** The skills it carries (labels) and the tools it serves (names) — the agent's own set. */
|
|
315
|
+
skills?: string[] | undefined;
|
|
316
|
+
tools?: string[] | undefined;
|
|
317
|
+
/** The person's variable values, kept so "Update to vN" can reuse them. */
|
|
318
|
+
variables?: Record<string, JsonValue> | undefined;
|
|
319
|
+
/**
|
|
320
|
+
* The CLI must be TOLD in the next prompt (a delimited block): a Codex
|
|
321
|
+
* takeover or agent switch (Codex ignores developer_instructions on resume),
|
|
322
|
+
* or a Codex compaction that dropped the block. Cleared once delivered.
|
|
323
|
+
*/
|
|
324
|
+
blockDue?: boolean | undefined;
|
|
325
|
+
/** When the block (or native instructions) last reached the CLI. */
|
|
326
|
+
deliveredAt?: string | null | undefined;
|
|
312
327
|
}
|
|
313
328
|
/** Whether this host can reach AI Matrx as a signed-in person. */
|
|
314
329
|
interface AgentAccess {
|
|
@@ -339,12 +354,13 @@ interface AgentCatalogRpcResult {
|
|
|
339
354
|
} | null;
|
|
340
355
|
count?: number | null;
|
|
341
356
|
}
|
|
342
|
-
/** What
|
|
357
|
+
/** What a picker needs about one agent — the LIGHT read (no skills, no tools). */
|
|
343
358
|
interface AgentDetails {
|
|
344
359
|
agentId: string;
|
|
345
360
|
name: string;
|
|
346
361
|
/** Variable declarations as authored (camelCase). */
|
|
347
362
|
variables: Record<string, JsonValue>[];
|
|
363
|
+
/** Newest first. */
|
|
348
364
|
versions: {
|
|
349
365
|
id: string;
|
|
350
366
|
versionNumber: number;
|
|
@@ -352,12 +368,15 @@ interface AgentDetails {
|
|
|
352
368
|
}[];
|
|
353
369
|
/** The version "Latest" resolves to right now. */
|
|
354
370
|
latestVersionNumber: number | null;
|
|
371
|
+
latestVersionId: string | null;
|
|
355
372
|
}
|
|
356
373
|
interface TakeoverInput {
|
|
357
374
|
provider: CodingProvider;
|
|
358
375
|
providerSessionId: string;
|
|
359
376
|
cwd: string;
|
|
360
377
|
title?: string | undefined;
|
|
378
|
+
/** Continue the chat WITH an AI Matrx agent ("Continue with agent"). */
|
|
379
|
+
agent?: AgentSelection | null | undefined;
|
|
361
380
|
}
|
|
362
381
|
interface SendResult {
|
|
363
382
|
session: CodingSession;
|
|
@@ -434,6 +453,12 @@ interface CodingSessionsApi {
|
|
|
434
453
|
agentCatalogRpc(request: AgentCatalogRpcRequest): Promise<AgentCatalogRpcResult>;
|
|
435
454
|
/** An agent's variables and saved versions, for the New session form. */
|
|
436
455
|
agentDetails(agentId: string): Promise<AgentDetails>;
|
|
456
|
+
/**
|
|
457
|
+
* Load a different agent into a session from its next message on (or
|
|
458
|
+
* remove it, with `null`). Claude reads it every turn; Codex is told in the
|
|
459
|
+
* next prompt.
|
|
460
|
+
*/
|
|
461
|
+
setAgent(sessionId: string, agent: AgentSelection | null): Promise<CodingSession>;
|
|
437
462
|
}
|
|
438
463
|
type RawTranscript = {
|
|
439
464
|
available: true;
|
|
@@ -588,7 +613,7 @@ declare class CodingSessionsClient {
|
|
|
588
613
|
transcript(sessionId: string): SessionTranscript;
|
|
589
614
|
readPreview(provider: CodingProvider, providerSessionId: string, maxBytes?: number): Promise<PreviewState>;
|
|
590
615
|
start(input: StartInput): Promise<SendResult>;
|
|
591
|
-
takeover(session: DiscoveredSession): Promise<CodingSession>;
|
|
616
|
+
takeover(session: DiscoveredSession, agent?: AgentSelection | null): Promise<CodingSession>;
|
|
592
617
|
send(sessionId: string, prompt: string): Promise<SendResult>;
|
|
593
618
|
stop(runId: string): Promise<RunRecord | null>;
|
|
594
619
|
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -196,6 +196,8 @@ interface CodingSession {
|
|
|
196
196
|
queued: string[];
|
|
197
197
|
/** The AI Matrx agent loaded into every run of this session, when one was picked. */
|
|
198
198
|
agent?: SessionAgent | null | undefined;
|
|
199
|
+
/** Codex must be told, in the next prompt, that an earlier agent no longer applies. */
|
|
200
|
+
agentRemovedDue?: boolean | undefined;
|
|
199
201
|
}
|
|
200
202
|
/**
|
|
201
203
|
* One normalized transcript item — the same shape from Claude and Codex, from
|
|
@@ -309,6 +311,19 @@ interface SessionAgent {
|
|
|
309
311
|
name: string;
|
|
310
312
|
reason: string;
|
|
311
313
|
}[];
|
|
314
|
+
/** The skills it carries (labels) and the tools it serves (names) — the agent's own set. */
|
|
315
|
+
skills?: string[] | undefined;
|
|
316
|
+
tools?: string[] | undefined;
|
|
317
|
+
/** The person's variable values, kept so "Update to vN" can reuse them. */
|
|
318
|
+
variables?: Record<string, JsonValue> | undefined;
|
|
319
|
+
/**
|
|
320
|
+
* The CLI must be TOLD in the next prompt (a delimited block): a Codex
|
|
321
|
+
* takeover or agent switch (Codex ignores developer_instructions on resume),
|
|
322
|
+
* or a Codex compaction that dropped the block. Cleared once delivered.
|
|
323
|
+
*/
|
|
324
|
+
blockDue?: boolean | undefined;
|
|
325
|
+
/** When the block (or native instructions) last reached the CLI. */
|
|
326
|
+
deliveredAt?: string | null | undefined;
|
|
312
327
|
}
|
|
313
328
|
/** Whether this host can reach AI Matrx as a signed-in person. */
|
|
314
329
|
interface AgentAccess {
|
|
@@ -339,12 +354,13 @@ interface AgentCatalogRpcResult {
|
|
|
339
354
|
} | null;
|
|
340
355
|
count?: number | null;
|
|
341
356
|
}
|
|
342
|
-
/** What
|
|
357
|
+
/** What a picker needs about one agent — the LIGHT read (no skills, no tools). */
|
|
343
358
|
interface AgentDetails {
|
|
344
359
|
agentId: string;
|
|
345
360
|
name: string;
|
|
346
361
|
/** Variable declarations as authored (camelCase). */
|
|
347
362
|
variables: Record<string, JsonValue>[];
|
|
363
|
+
/** Newest first. */
|
|
348
364
|
versions: {
|
|
349
365
|
id: string;
|
|
350
366
|
versionNumber: number;
|
|
@@ -352,12 +368,15 @@ interface AgentDetails {
|
|
|
352
368
|
}[];
|
|
353
369
|
/** The version "Latest" resolves to right now. */
|
|
354
370
|
latestVersionNumber: number | null;
|
|
371
|
+
latestVersionId: string | null;
|
|
355
372
|
}
|
|
356
373
|
interface TakeoverInput {
|
|
357
374
|
provider: CodingProvider;
|
|
358
375
|
providerSessionId: string;
|
|
359
376
|
cwd: string;
|
|
360
377
|
title?: string | undefined;
|
|
378
|
+
/** Continue the chat WITH an AI Matrx agent ("Continue with agent"). */
|
|
379
|
+
agent?: AgentSelection | null | undefined;
|
|
361
380
|
}
|
|
362
381
|
interface SendResult {
|
|
363
382
|
session: CodingSession;
|
|
@@ -434,6 +453,12 @@ interface CodingSessionsApi {
|
|
|
434
453
|
agentCatalogRpc(request: AgentCatalogRpcRequest): Promise<AgentCatalogRpcResult>;
|
|
435
454
|
/** An agent's variables and saved versions, for the New session form. */
|
|
436
455
|
agentDetails(agentId: string): Promise<AgentDetails>;
|
|
456
|
+
/**
|
|
457
|
+
* Load a different agent into a session from its next message on (or
|
|
458
|
+
* remove it, with `null`). Claude reads it every turn; Codex is told in the
|
|
459
|
+
* next prompt.
|
|
460
|
+
*/
|
|
461
|
+
setAgent(sessionId: string, agent: AgentSelection | null): Promise<CodingSession>;
|
|
437
462
|
}
|
|
438
463
|
type RawTranscript = {
|
|
439
464
|
available: true;
|
|
@@ -588,7 +613,7 @@ declare class CodingSessionsClient {
|
|
|
588
613
|
transcript(sessionId: string): SessionTranscript;
|
|
589
614
|
readPreview(provider: CodingProvider, providerSessionId: string, maxBytes?: number): Promise<PreviewState>;
|
|
590
615
|
start(input: StartInput): Promise<SendResult>;
|
|
591
|
-
takeover(session: DiscoveredSession): Promise<CodingSession>;
|
|
616
|
+
takeover(session: DiscoveredSession, agent?: AgentSelection | null): Promise<CodingSession>;
|
|
592
617
|
send(sessionId: string, prompt: string): Promise<SendResult>;
|
|
593
618
|
stop(runId: string): Promise<RunRecord | null>;
|
|
594
619
|
}
|
package/dist/react/index.js
CHANGED
|
@@ -17,15 +17,15 @@ import {
|
|
|
17
17
|
import { createExternalThreadSource as createExternalThreadSource2 } from "@ai-matrx/chat/external-store";
|
|
18
18
|
import {
|
|
19
19
|
Button as Button3,
|
|
20
|
-
Dialog,
|
|
21
|
-
DropdownMenu as
|
|
22
|
-
DropdownMenuContent as
|
|
23
|
-
DropdownMenuTrigger as
|
|
24
|
-
DialogContent,
|
|
20
|
+
Dialog as Dialog2,
|
|
21
|
+
DropdownMenu as DropdownMenu3,
|
|
22
|
+
DropdownMenuContent as DropdownMenuContent3,
|
|
23
|
+
DropdownMenuTrigger as DropdownMenuTrigger3,
|
|
24
|
+
DialogContent as DialogContent2,
|
|
25
25
|
DialogDescription,
|
|
26
|
-
DialogFooter,
|
|
27
|
-
DialogHeader,
|
|
28
|
-
DialogTitle,
|
|
26
|
+
DialogFooter as DialogFooter2,
|
|
27
|
+
DialogHeader as DialogHeader2,
|
|
28
|
+
DialogTitle as DialogTitle2,
|
|
29
29
|
Input as Input2,
|
|
30
30
|
Textarea as Textarea2,
|
|
31
31
|
cn as cn5
|
|
@@ -909,6 +909,17 @@ import { AgentCatalogProvider, AgentListDropdown } from "@ai-matrx/agents/catalo
|
|
|
909
909
|
import { humanizeContextKey } from "@ai-matrx/agents/context";
|
|
910
910
|
import {
|
|
911
911
|
Button,
|
|
912
|
+
Dialog,
|
|
913
|
+
DialogContent,
|
|
914
|
+
DialogFooter,
|
|
915
|
+
DialogHeader,
|
|
916
|
+
DialogTitle,
|
|
917
|
+
DropdownMenu,
|
|
918
|
+
DropdownMenuContent,
|
|
919
|
+
DropdownMenuItem as DropdownMenuItem2,
|
|
920
|
+
DropdownMenuLabel,
|
|
921
|
+
DropdownMenuSeparator as DropdownMenuSeparator2,
|
|
922
|
+
DropdownMenuTrigger,
|
|
912
923
|
Input,
|
|
913
924
|
Select,
|
|
914
925
|
SelectContent,
|
|
@@ -1093,30 +1104,167 @@ var PART_LABEL = {
|
|
|
1093
1104
|
skills: "Skills",
|
|
1094
1105
|
tools: "Tools"
|
|
1095
1106
|
};
|
|
1096
|
-
function
|
|
1107
|
+
function agentChipText(agent) {
|
|
1097
1108
|
const parts = agent.loaded.map(
|
|
1098
1109
|
(part) => part.part === "instructions" ? `${PART_LABEL.instructions} ${part.loaded === 1 ? "\u2713" : "\u2014"}` : `${PART_LABEL[part.part]} ${part.loaded}/${part.total}`
|
|
1099
1110
|
);
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
]
|
|
1111
|
+
return `${agent.name}${agent.versionNumber !== null ? ` v${agent.versionNumber}` : ""} \xB7 ${parts.join(" \xB7 ")}`;
|
|
1112
|
+
}
|
|
1113
|
+
function AgentMenu(props) {
|
|
1114
|
+
const { agent } = props;
|
|
1115
|
+
const show = useToastShow();
|
|
1116
|
+
const [open, setOpen] = useState4(false);
|
|
1117
|
+
const [choosing, setChoosing] = useState4(false);
|
|
1118
|
+
const [latest, setLatest] = useState4(null);
|
|
1119
|
+
const [access, setAccess] = useState4(null);
|
|
1120
|
+
useEffect2(() => {
|
|
1121
|
+
if (!open) return;
|
|
1122
|
+
let alive = true;
|
|
1123
|
+
void props.transport.call("agentAccess").then((next) => alive && setAccess(next)).catch(() => void 0);
|
|
1124
|
+
if (agent) {
|
|
1125
|
+
props.transport.call("agentDetails", agent.agentId).then((d) => {
|
|
1126
|
+
if (alive && d.latestVersionId && d.latestVersionNumber !== null) setLatest({ id: d.latestVersionId, number: d.latestVersionNumber });
|
|
1127
|
+
}).catch(() => void 0);
|
|
1118
1128
|
}
|
|
1119
|
-
|
|
1129
|
+
return () => {
|
|
1130
|
+
alive = false;
|
|
1131
|
+
};
|
|
1132
|
+
}, [open, agent, props.transport]);
|
|
1133
|
+
const apply = async (selection, done) => {
|
|
1134
|
+
try {
|
|
1135
|
+
await props.transport.call("setAgent", props.sessionId, selection);
|
|
1136
|
+
show(done);
|
|
1137
|
+
props.onChange();
|
|
1138
|
+
} catch (error) {
|
|
1139
|
+
show(`That didn't change: ${error instanceof Error ? error.message : String(error)}`);
|
|
1140
|
+
}
|
|
1141
|
+
};
|
|
1142
|
+
const behind = agent && latest && agent.versionNumber !== null && latest.number > agent.versionNumber ? latest : null;
|
|
1143
|
+
const complete = agent ? agent.loaded.every((part) => part.loaded === part.total) : true;
|
|
1144
|
+
const signedIn = access?.signedIn ?? false;
|
|
1145
|
+
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1146
|
+
/* @__PURE__ */ jsxs5(DropdownMenu, { open, onOpenChange: setOpen, children: [
|
|
1147
|
+
/* @__PURE__ */ jsx5(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs5(
|
|
1148
|
+
"button",
|
|
1149
|
+
{
|
|
1150
|
+
type: "button",
|
|
1151
|
+
className: cn3("cs-agent-chip", agent ? "cs-agent-chip--set" : "cs-agent-chip--none", !complete && "cs-agent-chip--partial"),
|
|
1152
|
+
"data-testid": "cs-agent-chip",
|
|
1153
|
+
"aria-label": agent ? `AI Matrx agent: ${agent.name}` : "Add an AI Matrx agent",
|
|
1154
|
+
children: [
|
|
1155
|
+
agent ? agentChipText(agent) : "No agent",
|
|
1156
|
+
behind ? /* @__PURE__ */ jsx5("span", { className: "cs-agent-chip-dot", "aria-label": "Update available" }) : null,
|
|
1157
|
+
/* @__PURE__ */ jsx5(ChevronDownIcon, { size: 12, className: "ml-1 inline shrink-0" })
|
|
1158
|
+
]
|
|
1159
|
+
}
|
|
1160
|
+
) }),
|
|
1161
|
+
/* @__PURE__ */ jsxs5(DropdownMenuContent, { align: "end", className: "w-[320px]", children: [
|
|
1162
|
+
agent ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1163
|
+
/* @__PURE__ */ jsxs5(DropdownMenuLabel, { className: "truncate", children: [
|
|
1164
|
+
agent.name,
|
|
1165
|
+
agent.versionNumber !== null ? ` \xB7 v${agent.versionNumber}` : ""
|
|
1166
|
+
] }),
|
|
1167
|
+
/* @__PURE__ */ jsxs5("div", { className: "cs-agent-parts", children: [
|
|
1168
|
+
agent.blockDue ? /* @__PURE__ */ jsx5("p", { className: "text-[12px] text-muted-foreground", children: "Sent with your next message" }) : null,
|
|
1169
|
+
/* @__PURE__ */ jsx5(AgentPartList, { title: "Skills", items: agent.skills ?? [] }),
|
|
1170
|
+
/* @__PURE__ */ jsx5(AgentPartList, { title: "Tools", items: agent.tools ?? [] }),
|
|
1171
|
+
agent.unavailable.length > 0 ? /* @__PURE__ */ jsx5(
|
|
1172
|
+
AgentPartList,
|
|
1173
|
+
{
|
|
1174
|
+
title: "Not loaded",
|
|
1175
|
+
items: agent.unavailable.map((u) => `${u.name} \u2014 ${u.reason}`)
|
|
1176
|
+
}
|
|
1177
|
+
) : null
|
|
1178
|
+
] }),
|
|
1179
|
+
/* @__PURE__ */ jsx5(DropdownMenuSeparator2, {})
|
|
1180
|
+
] }) : null,
|
|
1181
|
+
signedIn ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1182
|
+
behind && agent ? /* @__PURE__ */ jsxs5(
|
|
1183
|
+
DropdownMenuItem2,
|
|
1184
|
+
{
|
|
1185
|
+
onSelect: () => void apply(
|
|
1186
|
+
{ agentId: agent.agentId, versionId: behind.id, variables: agent.variables ?? {} },
|
|
1187
|
+
`The next message uses ${agent.name} v${behind.number}.`
|
|
1188
|
+
),
|
|
1189
|
+
children: [
|
|
1190
|
+
"Update to v",
|
|
1191
|
+
behind.number
|
|
1192
|
+
]
|
|
1193
|
+
}
|
|
1194
|
+
) : null,
|
|
1195
|
+
/* @__PURE__ */ jsx5(DropdownMenuItem2, { onSelect: () => setChoosing(true), children: agent ? "Change agent\u2026" : "Choose agent\u2026" }),
|
|
1196
|
+
agent ? /* @__PURE__ */ jsx5(DropdownMenuItem2, { onSelect: () => void apply(null, "The next message runs without an agent."), children: "Remove agent" }) : null
|
|
1197
|
+
] }) : access ? /* @__PURE__ */ jsx5("p", { className: "px-2 py-1.5 text-[12px] text-muted-foreground", children: SIGNED_OUT_AGENTS }) : null
|
|
1198
|
+
] })
|
|
1199
|
+
] }),
|
|
1200
|
+
/* @__PURE__ */ jsx5(
|
|
1201
|
+
ChooseAgentDialog,
|
|
1202
|
+
{
|
|
1203
|
+
transport: props.transport,
|
|
1204
|
+
open: choosing,
|
|
1205
|
+
onOpenChange: setChoosing,
|
|
1206
|
+
title: agent ? "Change agent" : "Choose an agent",
|
|
1207
|
+
action: "Use this agent",
|
|
1208
|
+
onConfirm: (selection) => apply(selection, "The next message uses the new agent.")
|
|
1209
|
+
}
|
|
1210
|
+
)
|
|
1211
|
+
] });
|
|
1212
|
+
}
|
|
1213
|
+
function AgentPartList({ title, items }) {
|
|
1214
|
+
return /* @__PURE__ */ jsxs5("div", { children: [
|
|
1215
|
+
/* @__PURE__ */ jsxs5("p", { className: "text-[11.5px] font-medium text-muted-foreground", children: [
|
|
1216
|
+
title,
|
|
1217
|
+
" \xB7 ",
|
|
1218
|
+
items.length
|
|
1219
|
+
] }),
|
|
1220
|
+
items.length > 0 ? /* @__PURE__ */ jsx5("ul", { className: "cs-agent-part-list", children: items.map((item) => /* @__PURE__ */ jsx5("li", { className: "truncate", title: item, children: item }, item)) }) : null
|
|
1221
|
+
] });
|
|
1222
|
+
}
|
|
1223
|
+
function ChooseAgentDialog(props) {
|
|
1224
|
+
const [value, setValue] = useState4(null);
|
|
1225
|
+
const [details, setDetails] = useState4(null);
|
|
1226
|
+
const [missing, setMissing] = useState4(null);
|
|
1227
|
+
const [busy, setBusy] = useState4(false);
|
|
1228
|
+
useEffect2(() => {
|
|
1229
|
+
if (props.open) {
|
|
1230
|
+
setValue(null);
|
|
1231
|
+
setMissing(null);
|
|
1232
|
+
}
|
|
1233
|
+
}, [props.open]);
|
|
1234
|
+
const confirm = async () => {
|
|
1235
|
+
if (!value) return;
|
|
1236
|
+
const gap = missingRequiredVariable(details, value);
|
|
1237
|
+
setMissing(gap);
|
|
1238
|
+
if (gap) return;
|
|
1239
|
+
setBusy(true);
|
|
1240
|
+
try {
|
|
1241
|
+
await props.onConfirm(value);
|
|
1242
|
+
props.onOpenChange(false);
|
|
1243
|
+
} finally {
|
|
1244
|
+
setBusy(false);
|
|
1245
|
+
}
|
|
1246
|
+
};
|
|
1247
|
+
return /* @__PURE__ */ jsx5(Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ jsxs5(DialogContent, { className: "max-w-[480px]", children: [
|
|
1248
|
+
/* @__PURE__ */ jsx5(DialogHeader, { children: /* @__PURE__ */ jsx5(DialogTitle, { children: props.title }) }),
|
|
1249
|
+
/* @__PURE__ */ jsx5(
|
|
1250
|
+
AgentField,
|
|
1251
|
+
{
|
|
1252
|
+
transport: props.transport,
|
|
1253
|
+
open: props.open,
|
|
1254
|
+
value,
|
|
1255
|
+
onChange: (next) => {
|
|
1256
|
+
setValue(next);
|
|
1257
|
+
setMissing(null);
|
|
1258
|
+
},
|
|
1259
|
+
missing,
|
|
1260
|
+
onDetails: setDetails
|
|
1261
|
+
}
|
|
1262
|
+
),
|
|
1263
|
+
/* @__PURE__ */ jsxs5(DialogFooter, { children: [
|
|
1264
|
+
/* @__PURE__ */ jsx5(Button, { type: "button", variant: "ghost", onClick: () => props.onOpenChange(false), children: "Cancel" }),
|
|
1265
|
+
/* @__PURE__ */ jsx5(Button, { type: "button", disabled: !value || busy, onClick: () => void confirm(), children: props.action })
|
|
1266
|
+
] })
|
|
1267
|
+
] }) });
|
|
1120
1268
|
}
|
|
1121
1269
|
|
|
1122
1270
|
// src/react/sidebar.tsx
|
|
@@ -1126,14 +1274,14 @@ import {
|
|
|
1126
1274
|
ContextMenu,
|
|
1127
1275
|
ContextMenuContent,
|
|
1128
1276
|
ContextMenuTrigger,
|
|
1129
|
-
DropdownMenu,
|
|
1130
|
-
DropdownMenuContent,
|
|
1131
|
-
DropdownMenuItem as
|
|
1132
|
-
DropdownMenuLabel,
|
|
1277
|
+
DropdownMenu as DropdownMenu2,
|
|
1278
|
+
DropdownMenuContent as DropdownMenuContent2,
|
|
1279
|
+
DropdownMenuItem as DropdownMenuItem3,
|
|
1280
|
+
DropdownMenuLabel as DropdownMenuLabel2,
|
|
1133
1281
|
DropdownMenuRadioGroup,
|
|
1134
1282
|
DropdownMenuRadioItem,
|
|
1135
|
-
DropdownMenuSeparator as
|
|
1136
|
-
DropdownMenuTrigger,
|
|
1283
|
+
DropdownMenuSeparator as DropdownMenuSeparator3,
|
|
1284
|
+
DropdownMenuTrigger as DropdownMenuTrigger2,
|
|
1137
1285
|
cn as cn4
|
|
1138
1286
|
} from "@ai-matrx/design-system";
|
|
1139
1287
|
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
@@ -1240,9 +1388,9 @@ function Row(props) {
|
|
|
1240
1388
|
] }),
|
|
1241
1389
|
renaming ? null : /* @__PURE__ */ jsxs6("span", { className: "cs-row__actions", children: [
|
|
1242
1390
|
props.takeover,
|
|
1243
|
-
/* @__PURE__ */ jsxs6(
|
|
1244
|
-
/* @__PURE__ */ jsx6(
|
|
1245
|
-
/* @__PURE__ */ jsx6(
|
|
1391
|
+
/* @__PURE__ */ jsxs6(DropdownMenu2, { open: menuOpen, onOpenChange: setMenuOpen, children: [
|
|
1392
|
+
/* @__PURE__ */ jsx6(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsx6("button", { type: "button", className: "cs-icon-button", "aria-label": `More for ${entry.title}`, title: "More", children: /* @__PURE__ */ jsx6(MoreIcon, { size: 15 }) }) }),
|
|
1393
|
+
/* @__PURE__ */ jsx6(DropdownMenuContent2, { align: "start", className: "w-60", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ jsx6(ChatMenuItems, { entry, variant: "dropdown", onRename: () => setRenaming(true) }) })
|
|
1246
1394
|
] })
|
|
1247
1395
|
] })
|
|
1248
1396
|
]
|
|
@@ -1480,16 +1628,16 @@ function Sidebar(props) {
|
|
|
1480
1628
|
SectionLabel,
|
|
1481
1629
|
{
|
|
1482
1630
|
action: /* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-0.5", children: [
|
|
1483
|
-
/* @__PURE__ */ jsxs6(
|
|
1484
|
-
/* @__PURE__ */ jsx6(
|
|
1485
|
-
/* @__PURE__ */ jsxs6(
|
|
1486
|
-
/* @__PURE__ */ jsx6(
|
|
1631
|
+
/* @__PURE__ */ jsxs6(DropdownMenu2, { children: [
|
|
1632
|
+
/* @__PURE__ */ jsx6(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsx6("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" }) }),
|
|
1633
|
+
/* @__PURE__ */ jsxs6(DropdownMenuContent2, { align: "end", className: "w-52", children: [
|
|
1634
|
+
/* @__PURE__ */ jsx6(DropdownMenuLabel2, { children: "Group your other chats" }),
|
|
1487
1635
|
/* @__PURE__ */ jsxs6(DropdownMenuRadioGroup, { value: groupMode, onValueChange: (v) => setMode(v), children: [
|
|
1488
1636
|
/* @__PURE__ */ jsx6(DropdownMenuRadioItem, { value: "date", children: "By date" }),
|
|
1489
1637
|
/* @__PURE__ */ jsx6(DropdownMenuRadioItem, { value: "folder", children: "By folder" })
|
|
1490
1638
|
] }),
|
|
1491
|
-
/* @__PURE__ */ jsx6(
|
|
1492
|
-
/* @__PURE__ */ jsx6(
|
|
1639
|
+
/* @__PURE__ */ jsx6(DropdownMenuSeparator3, {}),
|
|
1640
|
+
/* @__PURE__ */ jsx6(DropdownMenuItem3, { onSelect: () => setShowHidden((v) => !v), children: showHidden ? "Leave hidden chats out" : `Show hidden chats${hiddenCount ? ` (${hiddenCount})` : ""}` })
|
|
1493
1641
|
] })
|
|
1494
1642
|
] }),
|
|
1495
1643
|
/* @__PURE__ */ jsx6(
|
|
@@ -2138,12 +2286,13 @@ var CodingSessionsClient = class {
|
|
|
2138
2286
|
start(input) {
|
|
2139
2287
|
return this.transport.call("start", input);
|
|
2140
2288
|
}
|
|
2141
|
-
takeover(session) {
|
|
2289
|
+
takeover(session, agent) {
|
|
2142
2290
|
return this.transport.call("takeover", {
|
|
2143
2291
|
provider: session.provider,
|
|
2144
2292
|
providerSessionId: session.providerSessionId,
|
|
2145
2293
|
cwd: session.cwd ?? "",
|
|
2146
|
-
title: session.title
|
|
2294
|
+
title: session.title,
|
|
2295
|
+
...agent ? { agent } : {}
|
|
2147
2296
|
});
|
|
2148
2297
|
}
|
|
2149
2298
|
send(sessionId, prompt) {
|
|
@@ -2370,9 +2519,9 @@ function useSessionUsage(sessionId, lastRunKey) {
|
|
|
2370
2519
|
return usage;
|
|
2371
2520
|
}
|
|
2372
2521
|
function HeaderMenu(props) {
|
|
2373
|
-
return /* @__PURE__ */ jsxs7(
|
|
2374
|
-
/* @__PURE__ */ jsx7(
|
|
2375
|
-
/* @__PURE__ */ jsx7(
|
|
2522
|
+
return /* @__PURE__ */ jsxs7(DropdownMenu3, { children: [
|
|
2523
|
+
/* @__PURE__ */ jsx7(DropdownMenuTrigger3, { asChild: true, children: /* @__PURE__ */ jsx7("button", { type: "button", className: "cs-icon-button", "aria-label": "More for this chat", title: "More", children: /* @__PURE__ */ jsx7(MoreIcon, { size: 16 }) }) }),
|
|
2524
|
+
/* @__PURE__ */ jsx7(DropdownMenuContent3, { align: "end", className: "w-64", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ jsx7(ChatMenuItems, { entry: props.entry, variant: "dropdown", onRename: props.onRename }) })
|
|
2376
2525
|
] });
|
|
2377
2526
|
}
|
|
2378
2527
|
function HeaderTitle(props) {
|
|
@@ -2502,7 +2651,7 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2502
2651
|
] }) : null
|
|
2503
2652
|
] })
|
|
2504
2653
|
] }),
|
|
2505
|
-
|
|
2654
|
+
/* @__PURE__ */ jsx7(AgentMenu, { transport: client.transport, sessionId: session.id, agent: session.agent ?? null, onChange: () => void 0 }),
|
|
2506
2655
|
/* @__PURE__ */ jsxs7(
|
|
2507
2656
|
"button",
|
|
2508
2657
|
{
|
|
@@ -2675,13 +2824,14 @@ function DiscoveredView(props) {
|
|
|
2675
2824
|
if (elsewhere) setConfirming(true);
|
|
2676
2825
|
else void takeover();
|
|
2677
2826
|
};
|
|
2678
|
-
const
|
|
2827
|
+
const [choosingAgent, setChoosingAgent] = useState6(false);
|
|
2828
|
+
const takeover = async (agent) => {
|
|
2679
2829
|
if (!d) return;
|
|
2680
2830
|
setConfirming(false);
|
|
2681
2831
|
setBusy(true);
|
|
2682
2832
|
setError(null);
|
|
2683
2833
|
try {
|
|
2684
|
-
const taken = await client.takeover(d);
|
|
2834
|
+
const taken = await client.takeover(d, agent);
|
|
2685
2835
|
props.onTakenOver(taken.id);
|
|
2686
2836
|
} catch (e) {
|
|
2687
2837
|
setError(e instanceof Error ? e.message : String(e));
|
|
@@ -2737,6 +2887,18 @@ function DiscoveredView(props) {
|
|
|
2737
2887
|
]
|
|
2738
2888
|
}
|
|
2739
2889
|
) : null,
|
|
2890
|
+
d?.cwd && !elsewhere ? /* @__PURE__ */ jsx7(Button3, { size: "sm", variant: "outline", onClick: () => setChoosingAgent(true), disabled: busy, children: "Continue with agent\u2026" }) : null,
|
|
2891
|
+
/* @__PURE__ */ jsx7(
|
|
2892
|
+
ChooseAgentDialog,
|
|
2893
|
+
{
|
|
2894
|
+
transport: client.transport,
|
|
2895
|
+
open: choosingAgent,
|
|
2896
|
+
onOpenChange: setChoosingAgent,
|
|
2897
|
+
title: "Continue with an agent",
|
|
2898
|
+
action: "Take over with this agent",
|
|
2899
|
+
onConfirm: (agent) => takeover(agent)
|
|
2900
|
+
}
|
|
2901
|
+
),
|
|
2740
2902
|
d ? /* @__PURE__ */ jsx7(HeaderMenu, { entry, onRename: () => setRenaming(true) }) : null
|
|
2741
2903
|
] }),
|
|
2742
2904
|
elsewhere ? /* @__PURE__ */ jsxs7("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: [
|
|
@@ -2746,9 +2908,9 @@ function DiscoveredView(props) {
|
|
|
2746
2908
|
" 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."
|
|
2747
2909
|
] })
|
|
2748
2910
|
] }) : null,
|
|
2749
|
-
/* @__PURE__ */ jsx7(
|
|
2750
|
-
/* @__PURE__ */ jsxs7(
|
|
2751
|
-
/* @__PURE__ */ jsxs7(
|
|
2911
|
+
/* @__PURE__ */ jsx7(Dialog2, { open: confirming, onOpenChange: setConfirming, children: /* @__PURE__ */ jsxs7(DialogContent2, { className: "max-w-[460px]", children: [
|
|
2912
|
+
/* @__PURE__ */ jsxs7(DialogHeader2, { children: [
|
|
2913
|
+
/* @__PURE__ */ jsxs7(DialogTitle2, { children: [
|
|
2752
2914
|
"This chat is running right now in ",
|
|
2753
2915
|
PROVIDER_LABEL[props.provider]
|
|
2754
2916
|
] }),
|
|
@@ -2757,7 +2919,7 @@ function DiscoveredView(props) {
|
|
|
2757
2919
|
" If you take it over, two agents will work in the same conversation at once and may overwrite each other's changes."
|
|
2758
2920
|
] })
|
|
2759
2921
|
] }),
|
|
2760
|
-
/* @__PURE__ */ jsxs7(
|
|
2922
|
+
/* @__PURE__ */ jsxs7(DialogFooter2, { children: [
|
|
2761
2923
|
/* @__PURE__ */ jsx7(Button3, { variant: "ghost", onClick: () => setConfirming(false), children: "Cancel" }),
|
|
2762
2924
|
/* @__PURE__ */ jsx7(Button3, { variant: "destructive", onClick: () => void takeover(), children: "Take over anyway" })
|
|
2763
2925
|
] })
|
|
@@ -2937,9 +3099,9 @@ function NewSessionDialog(props) {
|
|
|
2937
3099
|
if (field === "folder") delete next.createFolder;
|
|
2938
3100
|
return next;
|
|
2939
3101
|
});
|
|
2940
|
-
return /* @__PURE__ */ jsx7(
|
|
2941
|
-
/* @__PURE__ */ jsxs7(
|
|
2942
|
-
/* @__PURE__ */ jsx7(
|
|
3102
|
+
return /* @__PURE__ */ jsx7(Dialog2, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ jsxs7(DialogContent2, { className: "max-w-[560px]", children: [
|
|
3103
|
+
/* @__PURE__ */ jsxs7(DialogHeader2, { children: [
|
|
3104
|
+
/* @__PURE__ */ jsx7(DialogTitle2, { children: "New coding session" }),
|
|
2943
3105
|
/* @__PURE__ */ jsxs7(DialogDescription, { children: [
|
|
2944
3106
|
"Runs on your own ",
|
|
2945
3107
|
provider === "claude" ? "Claude" : "ChatGPT",
|
|
@@ -3083,7 +3245,7 @@ function NewSessionDialog(props) {
|
|
|
3083
3245
|
] }),
|
|
3084
3246
|
problem ? /* @__PURE__ */ jsx7(FieldError, { id: "cs-err-start", children: problem }) : null
|
|
3085
3247
|
] }),
|
|
3086
|
-
/* @__PURE__ */ jsxs7(
|
|
3248
|
+
/* @__PURE__ */ jsxs7(DialogFooter2, { className: "pt-4", children: [
|
|
3087
3249
|
/* @__PURE__ */ jsx7(Button3, { type: "button", variant: "ghost", onClick: () => props.onOpenChange(false), children: "Cancel" }),
|
|
3088
3250
|
/* @__PURE__ */ jsxs7(Button3, { type: "submit", disabled: starting, className: "gap-1.5", children: [
|
|
3089
3251
|
starting ? /* @__PURE__ */ jsx7(SpinnerIcon, { size: 14 }) : null,
|
|
@@ -3252,9 +3414,9 @@ var SHORTCUTS = [
|
|
|
3252
3414
|
{ keys: "\u2318/", what: "These shortcuts" }
|
|
3253
3415
|
];
|
|
3254
3416
|
function ShortcutsDialog(props) {
|
|
3255
|
-
return /* @__PURE__ */ jsx7(
|
|
3256
|
-
/* @__PURE__ */ jsxs7(
|
|
3257
|
-
/* @__PURE__ */ jsx7(
|
|
3417
|
+
return /* @__PURE__ */ jsx7(Dialog2, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ jsxs7(DialogContent2, { className: "max-w-[420px]", children: [
|
|
3418
|
+
/* @__PURE__ */ jsxs7(DialogHeader2, { children: [
|
|
3419
|
+
/* @__PURE__ */ jsx7(DialogTitle2, { children: "Keyboard shortcuts" }),
|
|
3258
3420
|
/* @__PURE__ */ jsx7(DialogDescription, { children: "Ctrl works in place of \u2318 on Windows and Linux." })
|
|
3259
3421
|
] }),
|
|
3260
3422
|
/* @__PURE__ */ jsx7("dl", { className: "divide-y divide-border text-[13px]", children: SHORTCUTS.map((s) => /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-4 py-2", children: [
|