@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.
- package/CHANGELOG.md +24 -0
- package/dist/engine/index.cjs +724 -139
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +4 -1
- package/dist/engine/index.d.ts +4 -1
- package/dist/engine/index.js +717 -132
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/worker.js +14 -2
- package/dist/engine/worker.js.map +1 -1
- package/dist/{index-RYOb-YZT.d.cts → index-DEPwyr2j.d.cts} +148 -0
- package/dist/{index-RYOb-YZT.d.ts → index-DEPwyr2j.d.ts} +148 -0
- package/dist/index.cjs +21 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +105 -1
- package/dist/index.d.ts +105 -1
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +722 -410
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +105 -7
- package/dist/react/index.d.ts +105 -7
- package/dist/react/index.js +730 -405
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +792 -155
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +4 -1
- package/dist/server/index.d.ts +4 -1
- package/dist/server/index.js +783 -146
- package/dist/server/index.js.map +1 -1
- package/dist/ui/assets/index-DSWoryQZ.js +72 -0
- package/dist/ui/assets/index-Gp2bMDtx.css +2 -0
- package/dist/ui/index.html +2 -2
- package/package.json +4 -2
- package/dist/ui/assets/index-B3Ic2ziA.js +0 -69
- package/dist/ui/assets/index-BAkpc01s.css +0 -2
package/dist/react/index.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
import {
|
|
5
5
|
useCallback as useCallback2,
|
|
6
6
|
useContext as useContext3,
|
|
7
|
-
useEffect as
|
|
8
|
-
useMemo as
|
|
9
|
-
useRef as
|
|
10
|
-
useState as
|
|
7
|
+
useEffect as useEffect4,
|
|
8
|
+
useMemo as useMemo4,
|
|
9
|
+
useRef as useRef3,
|
|
10
|
+
useState as useState6
|
|
11
11
|
} from "react";
|
|
12
12
|
import {
|
|
13
13
|
ChatComposer,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "@ai-matrx/chat/react";
|
|
17
17
|
import { createExternalThreadSource as createExternalThreadSource2 } from "@ai-matrx/chat/external-store";
|
|
18
18
|
import {
|
|
19
|
-
Button as
|
|
19
|
+
Button as Button3,
|
|
20
20
|
Dialog,
|
|
21
21
|
DropdownMenu as DropdownMenu2,
|
|
22
22
|
DropdownMenuContent as DropdownMenuContent2,
|
|
@@ -26,9 +26,9 @@ import {
|
|
|
26
26
|
DialogFooter,
|
|
27
27
|
DialogHeader,
|
|
28
28
|
DialogTitle,
|
|
29
|
-
Input,
|
|
30
|
-
Textarea,
|
|
31
|
-
cn as
|
|
29
|
+
Input as Input2,
|
|
30
|
+
Textarea as Textarea2,
|
|
31
|
+
cn as cn5
|
|
32
32
|
} from "@ai-matrx/design-system";
|
|
33
33
|
import { formatCount, formatUsd } from "@ai-matrx/kit/format";
|
|
34
34
|
|
|
@@ -52,6 +52,21 @@ function formatUntil(until) {
|
|
|
52
52
|
if (Number.isNaN(ms)) return until;
|
|
53
53
|
return new Date(ms).toLocaleString(void 0, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
|
|
54
54
|
}
|
|
55
|
+
var MODEL_UNAVAILABLE = [
|
|
56
|
+
/model is not supported when using codex/i,
|
|
57
|
+
/\bmodel[\s:'"`][^.\n]{0,80}\b(?:not supported|does not exist|not available|not found)\b/i,
|
|
58
|
+
/\bmodel_not_found\b/i,
|
|
59
|
+
/issue with the selected model/i,
|
|
60
|
+
/may not exist or you may not have access to it/i
|
|
61
|
+
];
|
|
62
|
+
var MODEL_UNAVAILABLE_LABEL = "Model not available on this account";
|
|
63
|
+
function isModelUnavailable(text) {
|
|
64
|
+
const trimmed = (text ?? "").trim();
|
|
65
|
+
return trimmed !== "" && MODEL_UNAVAILABLE.some((re) => re.test(trimmed));
|
|
66
|
+
}
|
|
67
|
+
function runErrorLabel(text) {
|
|
68
|
+
return isModelUnavailable(text) ? MODEL_UNAVAILABLE_LABEL : text;
|
|
69
|
+
}
|
|
55
70
|
|
|
56
71
|
// src/tool-labels.ts
|
|
57
72
|
var BUILTIN = {
|
|
@@ -474,14 +489,20 @@ var SpinnerIcon = ({ size = 16, className }) => /* @__PURE__ */ jsxs(
|
|
|
474
489
|
]
|
|
475
490
|
}
|
|
476
491
|
);
|
|
477
|
-
|
|
492
|
+
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";
|
|
493
|
+
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";
|
|
494
|
+
function ProviderMark({ provider, size = 16 }) {
|
|
478
495
|
return /* @__PURE__ */ jsx(
|
|
479
|
-
"
|
|
496
|
+
"svg",
|
|
480
497
|
{
|
|
481
498
|
className: `cs-provider-mark cs-provider-mark--${provider}`,
|
|
482
|
-
|
|
499
|
+
width: size,
|
|
500
|
+
height: size,
|
|
501
|
+
viewBox: "0 0 24 24",
|
|
502
|
+
fill: "currentColor",
|
|
483
503
|
"aria-hidden": "true",
|
|
484
|
-
|
|
504
|
+
"data-provider-mark": provider,
|
|
505
|
+
children: /* @__PURE__ */ jsx("path", { d: provider === "claude" ? CLAUDE_MARK : OPENAI_MARK })
|
|
485
506
|
}
|
|
486
507
|
);
|
|
487
508
|
}
|
|
@@ -878,10 +899,230 @@ function ModelPicker(props) {
|
|
|
878
899
|
] });
|
|
879
900
|
}
|
|
880
901
|
|
|
881
|
-
// src/react/
|
|
882
|
-
import {
|
|
902
|
+
// src/react/agent-field.tsx
|
|
903
|
+
import { useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState4 } from "react";
|
|
904
|
+
import { deriveRunInputs } from "@ai-matrx/agents";
|
|
905
|
+
import {
|
|
906
|
+
createAgentCatalog
|
|
907
|
+
} from "@ai-matrx/agents/catalog";
|
|
908
|
+
import { AgentCatalogProvider, AgentListDropdown } from "@ai-matrx/agents/catalog/react";
|
|
909
|
+
import { humanizeContextKey } from "@ai-matrx/agents/context";
|
|
883
910
|
import {
|
|
884
911
|
Button,
|
|
912
|
+
Input,
|
|
913
|
+
Select,
|
|
914
|
+
SelectContent,
|
|
915
|
+
SelectItem,
|
|
916
|
+
SelectTrigger,
|
|
917
|
+
SelectValue,
|
|
918
|
+
Textarea,
|
|
919
|
+
TooltipProvider,
|
|
920
|
+
cn as cn3
|
|
921
|
+
} from "@ai-matrx/design-system";
|
|
922
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
923
|
+
var SIGNED_OUT_AGENTS = "Sign in to AI Matrx to use your agents";
|
|
924
|
+
var LATEST = "latest";
|
|
925
|
+
function bridgedClient(transport) {
|
|
926
|
+
const call = (request) => {
|
|
927
|
+
const run = () => transport.call("agentCatalogRpc", request).then((result) => ({
|
|
928
|
+
data: result.data,
|
|
929
|
+
error: result.error ? {
|
|
930
|
+
message: result.error.message,
|
|
931
|
+
...result.error.code ? { code: result.error.code } : {},
|
|
932
|
+
details: result.error.details ?? null,
|
|
933
|
+
hint: result.error.hint ?? null
|
|
934
|
+
} : null,
|
|
935
|
+
count: result.count ?? null
|
|
936
|
+
}));
|
|
937
|
+
return {
|
|
938
|
+
then: (onOk, onErr) => run().then(onOk, onErr),
|
|
939
|
+
range: (from, to) => call({ ...request, range: [from, to] }),
|
|
940
|
+
order: (column, options) => call({ ...request, order: { column, ascending: options?.ascending !== false } })
|
|
941
|
+
};
|
|
942
|
+
};
|
|
943
|
+
return {
|
|
944
|
+
rpc: (fn, args, options) => call({ fn, ...args ? { args } : {}, ...options?.count ? { count: options.count } : {} })
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
function useAgentAccess(transport, open) {
|
|
948
|
+
const [access, setAccess] = useState4(null);
|
|
949
|
+
useEffect2(() => {
|
|
950
|
+
if (!open) return;
|
|
951
|
+
let alive = true;
|
|
952
|
+
transport.call("agentAccess").then((next) => alive && setAccess(next)).catch(() => alive && setAccess({ signedIn: false, userId: null, organizationId: null, configured: false }));
|
|
953
|
+
return () => {
|
|
954
|
+
alive = false;
|
|
955
|
+
};
|
|
956
|
+
}, [transport, open]);
|
|
957
|
+
return access;
|
|
958
|
+
}
|
|
959
|
+
function useCatalog(transport, userId, onError) {
|
|
960
|
+
const report = useRef(onError);
|
|
961
|
+
report.current = onError;
|
|
962
|
+
return useMemo2(() => {
|
|
963
|
+
if (!userId) return null;
|
|
964
|
+
return createAgentCatalog({
|
|
965
|
+
client: bridgedClient(transport),
|
|
966
|
+
identity: { requireUserId: () => userId, getUserId: () => userId },
|
|
967
|
+
catalogId: `coding-sessions:${userId}`,
|
|
968
|
+
// A failed catalogue read shows at the field, never only in the console.
|
|
969
|
+
errorSink: (event) => {
|
|
970
|
+
console.error(`[coding-sessions] agent catalogue: ${event.code}: ${event.message}`);
|
|
971
|
+
if (event.code === "list_read_failed") report.current("Couldn't load your agents. Reopen to retry.");
|
|
972
|
+
}
|
|
973
|
+
});
|
|
974
|
+
}, [transport, userId]);
|
|
975
|
+
}
|
|
976
|
+
function asRunInputVariables(defs) {
|
|
977
|
+
return defs.flatMap((def) => typeof def.name === "string" ? [def] : []);
|
|
978
|
+
}
|
|
979
|
+
function AgentField(props) {
|
|
980
|
+
const access = useAgentAccess(props.transport, props.open);
|
|
981
|
+
const [details, setDetails] = useState4(null);
|
|
982
|
+
const [problem, setProblem] = useState4(null);
|
|
983
|
+
const catalog = useCatalog(props.transport, access?.signedIn ? access.userId : null, setProblem);
|
|
984
|
+
const agentId = props.value?.agentId ?? null;
|
|
985
|
+
useEffect2(() => {
|
|
986
|
+
setDetails(null);
|
|
987
|
+
setProblem(null);
|
|
988
|
+
if (!agentId) return;
|
|
989
|
+
let alive = true;
|
|
990
|
+
props.transport.call("agentDetails", agentId).then((next) => alive && setDetails(next)).catch((error) => alive && setProblem(error instanceof Error ? error.message : String(error)));
|
|
991
|
+
return () => {
|
|
992
|
+
alive = false;
|
|
993
|
+
};
|
|
994
|
+
}, [agentId, props.transport]);
|
|
995
|
+
const { onDetails } = props;
|
|
996
|
+
useEffect2(() => {
|
|
997
|
+
onDetails?.(details);
|
|
998
|
+
}, [details, onDetails]);
|
|
999
|
+
const inputs = useMemo2(() => deriveRunInputs(asRunInputVariables(details?.variables ?? []), humanizeContextKey), [details]);
|
|
1000
|
+
if (access === null) return /* @__PURE__ */ jsx5("div", { className: "cs-skeleton h-9 rounded-lg" });
|
|
1001
|
+
if (!access.signedIn || !catalog) {
|
|
1002
|
+
return /* @__PURE__ */ jsx5("p", { className: "text-[12.5px] text-muted-foreground", children: SIGNED_OUT_AGENTS });
|
|
1003
|
+
}
|
|
1004
|
+
const setVariable = (name, value) => {
|
|
1005
|
+
if (!props.value) return;
|
|
1006
|
+
props.onChange({ ...props.value, variables: { ...props.value.variables ?? {}, [name]: value } });
|
|
1007
|
+
};
|
|
1008
|
+
return /* @__PURE__ */ jsxs5("div", { className: "space-y-3", children: [
|
|
1009
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
1010
|
+
/* @__PURE__ */ jsx5(TooltipProvider, { children: /* @__PURE__ */ jsx5(AgentCatalogProvider, { catalog, children: /* @__PURE__ */ jsx5(
|
|
1011
|
+
AgentListDropdown,
|
|
1012
|
+
{
|
|
1013
|
+
consumerId: "coding-sessions-new-session",
|
|
1014
|
+
activeAgentId: agentId,
|
|
1015
|
+
label: details?.name ?? (agentId ? "Loading\u2026" : "None"),
|
|
1016
|
+
onSelect: (id) => props.onChange({ agentId: id, versionId: null, variables: {} })
|
|
1017
|
+
}
|
|
1018
|
+
) }) }),
|
|
1019
|
+
agentId ? /* @__PURE__ */ jsx5(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => props.onChange(null), children: "Remove" }) : null
|
|
1020
|
+
] }),
|
|
1021
|
+
problem ? /* @__PURE__ */ jsx5("p", { className: "text-[12px] text-destructive", children: problem }) : null,
|
|
1022
|
+
details && props.value ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1023
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
1024
|
+
/* @__PURE__ */ jsx5("span", { className: "w-[72px] shrink-0 text-[12px] text-muted-foreground", children: "Version" }),
|
|
1025
|
+
/* @__PURE__ */ jsxs5(
|
|
1026
|
+
Select,
|
|
1027
|
+
{
|
|
1028
|
+
value: props.value.versionId ?? LATEST,
|
|
1029
|
+
onValueChange: (next) => props.value && props.onChange({ ...props.value, versionId: next === LATEST ? null : next }),
|
|
1030
|
+
children: [
|
|
1031
|
+
/* @__PURE__ */ jsx5(SelectTrigger, { className: "h-8 w-[200px] text-[12.5px]", "aria-label": "Agent version", children: /* @__PURE__ */ jsx5(SelectValue, {}) }),
|
|
1032
|
+
/* @__PURE__ */ jsxs5(SelectContent, { children: [
|
|
1033
|
+
/* @__PURE__ */ jsx5(SelectItem, { value: LATEST, children: details.latestVersionNumber !== null ? `Latest (v${details.latestVersionNumber})` : "Latest" }),
|
|
1034
|
+
details.versions.map((v) => /* @__PURE__ */ jsxs5(SelectItem, { value: v.id, children: [
|
|
1035
|
+
"v",
|
|
1036
|
+
v.versionNumber
|
|
1037
|
+
] }, v.id))
|
|
1038
|
+
] })
|
|
1039
|
+
]
|
|
1040
|
+
}
|
|
1041
|
+
)
|
|
1042
|
+
] }),
|
|
1043
|
+
inputs.map((input) => {
|
|
1044
|
+
const raw = props.value?.variables?.[input.name];
|
|
1045
|
+
const value = typeof raw === "string" ? raw : "";
|
|
1046
|
+
const id = `cs-agent-var-${input.name}`;
|
|
1047
|
+
const invalid = props.missing === input.name;
|
|
1048
|
+
return /* @__PURE__ */ jsxs5("div", { className: "space-y-1", children: [
|
|
1049
|
+
/* @__PURE__ */ jsxs5("label", { htmlFor: id, className: "text-[12px] font-medium", children: [
|
|
1050
|
+
input.label,
|
|
1051
|
+
input.required ? /* @__PURE__ */ jsx5("span", { className: "text-muted-foreground", children: " \xB7 required" }) : null
|
|
1052
|
+
] }),
|
|
1053
|
+
input.options && input.options.length > 0 ? /* @__PURE__ */ jsxs5(Select, { value, onValueChange: (next) => setVariable(input.name, next), children: [
|
|
1054
|
+
/* @__PURE__ */ jsx5(SelectTrigger, { id, className: "h-8 text-[12.5px]", "aria-invalid": invalid || void 0, children: /* @__PURE__ */ jsx5(SelectValue, { placeholder: "Choose\u2026" }) }),
|
|
1055
|
+
/* @__PURE__ */ jsx5(SelectContent, { children: input.options.map((option) => /* @__PURE__ */ jsx5(SelectItem, { value: option, children: option }, option)) })
|
|
1056
|
+
] }) : input.variable.customComponent?.type === "textarea" ? /* @__PURE__ */ jsx5(
|
|
1057
|
+
Textarea,
|
|
1058
|
+
{
|
|
1059
|
+
id,
|
|
1060
|
+
rows: 2,
|
|
1061
|
+
value,
|
|
1062
|
+
onChange: (e) => setVariable(input.name, e.target.value),
|
|
1063
|
+
placeholder: input.hint ?? "",
|
|
1064
|
+
"aria-invalid": invalid || void 0
|
|
1065
|
+
}
|
|
1066
|
+
) : /* @__PURE__ */ jsx5(
|
|
1067
|
+
Input,
|
|
1068
|
+
{
|
|
1069
|
+
id,
|
|
1070
|
+
value,
|
|
1071
|
+
onChange: (e) => setVariable(input.name, e.target.value),
|
|
1072
|
+
placeholder: input.hint ?? "",
|
|
1073
|
+
"aria-invalid": invalid || void 0
|
|
1074
|
+
}
|
|
1075
|
+
),
|
|
1076
|
+
invalid ? /* @__PURE__ */ jsx5("p", { className: "text-[12px] text-destructive", children: "Fill this in to use the agent" }) : null
|
|
1077
|
+
] }, input.name);
|
|
1078
|
+
})
|
|
1079
|
+
] }) : null
|
|
1080
|
+
] });
|
|
1081
|
+
}
|
|
1082
|
+
function missingRequiredVariable(details, selection) {
|
|
1083
|
+
if (!details || !selection) return null;
|
|
1084
|
+
for (const input of deriveRunInputs(asRunInputVariables(details.variables), humanizeContextKey)) {
|
|
1085
|
+
if (!input.required) continue;
|
|
1086
|
+
const value = selection.variables?.[input.name];
|
|
1087
|
+
if (typeof value !== "string" || !value.trim()) return input.name;
|
|
1088
|
+
}
|
|
1089
|
+
return null;
|
|
1090
|
+
}
|
|
1091
|
+
var PART_LABEL = {
|
|
1092
|
+
instructions: "Instructions",
|
|
1093
|
+
skills: "Skills",
|
|
1094
|
+
tools: "Tools"
|
|
1095
|
+
};
|
|
1096
|
+
function AgentChip({ agent }) {
|
|
1097
|
+
const parts = agent.loaded.map(
|
|
1098
|
+
(part) => part.part === "instructions" ? `${PART_LABEL.instructions} ${part.loaded === 1 ? "\u2713" : "\u2014"}` : `${PART_LABEL[part.part]} ${part.loaded}/${part.total}`
|
|
1099
|
+
);
|
|
1100
|
+
const missing = agent.unavailable.slice(0, 6).map((u) => `${u.name}: ${u.reason}`);
|
|
1101
|
+
const more = agent.unavailable.length > 6 ? [`+${agent.unavailable.length - 6} more`] : [];
|
|
1102
|
+
const complete = agent.loaded.every((part) => part.loaded === part.total);
|
|
1103
|
+
return /* @__PURE__ */ jsxs5(
|
|
1104
|
+
"span",
|
|
1105
|
+
{
|
|
1106
|
+
className: cn3("cs-agent-chip", !complete && "cs-agent-chip--partial"),
|
|
1107
|
+
title: missing.length ? [...missing, ...more].join("\n") : "Everything loaded",
|
|
1108
|
+
"data-testid": "cs-agent-chip",
|
|
1109
|
+
children: [
|
|
1110
|
+
/* @__PURE__ */ jsxs5("span", { className: "font-medium text-foreground", children: [
|
|
1111
|
+
agent.name,
|
|
1112
|
+
agent.versionNumber !== null ? ` v${agent.versionNumber}` : ""
|
|
1113
|
+
] }),
|
|
1114
|
+
" ",
|
|
1115
|
+
"\xB7 ",
|
|
1116
|
+
parts.join(" \xB7 ")
|
|
1117
|
+
]
|
|
1118
|
+
}
|
|
1119
|
+
);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
// src/react/sidebar.tsx
|
|
1123
|
+
import { useCallback, useEffect as useEffect3, useMemo as useMemo3, useRef as useRef2, useState as useState5 } from "react";
|
|
1124
|
+
import {
|
|
1125
|
+
Button as Button2,
|
|
885
1126
|
ContextMenu,
|
|
886
1127
|
ContextMenuContent,
|
|
887
1128
|
ContextMenuTrigger,
|
|
@@ -893,9 +1134,9 @@ import {
|
|
|
893
1134
|
DropdownMenuRadioItem,
|
|
894
1135
|
DropdownMenuSeparator as DropdownMenuSeparator2,
|
|
895
1136
|
DropdownMenuTrigger,
|
|
896
|
-
cn as
|
|
1137
|
+
cn as cn4
|
|
897
1138
|
} from "@ai-matrx/design-system";
|
|
898
|
-
import { Fragment as
|
|
1139
|
+
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
899
1140
|
function readLocal(key, allowed, fallback) {
|
|
900
1141
|
try {
|
|
901
1142
|
const value = localStorage.getItem(key);
|
|
@@ -911,23 +1152,23 @@ function writeLocal(key, value) {
|
|
|
911
1152
|
}
|
|
912
1153
|
}
|
|
913
1154
|
function SectionLabel({ children, action }) {
|
|
914
|
-
return /* @__PURE__ */
|
|
915
|
-
/* @__PURE__ */
|
|
1155
|
+
return /* @__PURE__ */ jsxs6("div", { "data-cs-section-label": true, className: "flex h-8 items-center justify-between px-3 pt-3", children: [
|
|
1156
|
+
/* @__PURE__ */ jsx6("span", { className: "text-[12px] font-medium text-muted-foreground", children }),
|
|
916
1157
|
action
|
|
917
1158
|
] });
|
|
918
1159
|
}
|
|
919
1160
|
function GroupLabel({ children }) {
|
|
920
|
-
return /* @__PURE__ */
|
|
1161
|
+
return /* @__PURE__ */ jsx6("div", { className: "truncate px-4 pb-0.5 pt-2.5 text-[12px] font-medium text-muted-foreground", children });
|
|
921
1162
|
}
|
|
922
1163
|
function RenameInput(props) {
|
|
923
|
-
const [value, setValue] =
|
|
924
|
-
const done =
|
|
1164
|
+
const [value, setValue] = useState5(props.initial);
|
|
1165
|
+
const done = useRef2(false);
|
|
925
1166
|
const finish = (title) => {
|
|
926
1167
|
if (done.current) return;
|
|
927
1168
|
done.current = true;
|
|
928
1169
|
props.onDone(title);
|
|
929
1170
|
};
|
|
930
|
-
return /* @__PURE__ */
|
|
1171
|
+
return /* @__PURE__ */ jsx6(
|
|
931
1172
|
"input",
|
|
932
1173
|
{
|
|
933
1174
|
autoFocus: true,
|
|
@@ -944,11 +1185,16 @@ function RenameInput(props) {
|
|
|
944
1185
|
}
|
|
945
1186
|
);
|
|
946
1187
|
}
|
|
1188
|
+
function entryTarget(entry) {
|
|
1189
|
+
if (entry.kind === "session" && entry.session) return `#s/${entry.session.id}`;
|
|
1190
|
+
if (entry.providerSessionId) return `#d/${entry.provider}/${entry.providerSessionId}`;
|
|
1191
|
+
return "";
|
|
1192
|
+
}
|
|
947
1193
|
function Row(props) {
|
|
948
1194
|
const client = useCodingSessionsClient();
|
|
949
1195
|
const show = useToastShow();
|
|
950
|
-
const [renaming, setRenaming] =
|
|
951
|
-
const [menuOpen, setMenuOpen] =
|
|
1196
|
+
const [renaming, setRenaming] = useState5(false);
|
|
1197
|
+
const [menuOpen, setMenuOpen] = useState5(false);
|
|
952
1198
|
const { entry } = props;
|
|
953
1199
|
const rename = (title) => {
|
|
954
1200
|
setRenaming(false);
|
|
@@ -958,14 +1204,20 @@ function Row(props) {
|
|
|
958
1204
|
(error) => show(`The new name didn't save: ${error instanceof Error ? error.message : String(error)}`)
|
|
959
1205
|
);
|
|
960
1206
|
};
|
|
961
|
-
return /* @__PURE__ */
|
|
962
|
-
/* @__PURE__ */
|
|
1207
|
+
return /* @__PURE__ */ jsxs6(ContextMenu, { children: [
|
|
1208
|
+
/* @__PURE__ */ jsx6(ContextMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs6(
|
|
963
1209
|
"div",
|
|
964
1210
|
{
|
|
965
|
-
className:
|
|
1211
|
+
className: cn4("cs-row group", props.active && "cs-row--active", menuOpen && "cs-row--menu"),
|
|
966
1212
|
"data-hidden": entry.hidden || void 0,
|
|
1213
|
+
"data-cs-row": entry.key,
|
|
1214
|
+
"data-cs-target": entryTarget(entry),
|
|
1215
|
+
"data-cs-provider": entry.provider,
|
|
1216
|
+
"data-cs-title": entry.title,
|
|
1217
|
+
"data-cs-live": props.live ? "true" : void 0,
|
|
1218
|
+
"data-cs-active": props.active ? "true" : void 0,
|
|
967
1219
|
children: [
|
|
968
|
-
/* @__PURE__ */
|
|
1220
|
+
/* @__PURE__ */ jsx6(
|
|
969
1221
|
"button",
|
|
970
1222
|
{
|
|
971
1223
|
type: "button",
|
|
@@ -977,39 +1229,39 @@ function Row(props) {
|
|
|
977
1229
|
(${entry.originalTitle})` : entry.title
|
|
978
1230
|
}
|
|
979
1231
|
),
|
|
980
|
-
/* @__PURE__ */
|
|
981
|
-
/* @__PURE__ */
|
|
982
|
-
renaming ? /* @__PURE__ */
|
|
983
|
-
/* @__PURE__ */
|
|
984
|
-
entry.pinned ? /* @__PURE__ */
|
|
1232
|
+
/* @__PURE__ */ jsx6("span", { className: "pointer-events-none mt-0.5 shrink-0", children: props.live ? /* @__PURE__ */ jsx6(SpinnerIcon, { size: 16, className: "text-primary" }) : /* @__PURE__ */ jsx6(ProviderMark, { provider: entry.provider, size: 16 }) }),
|
|
1233
|
+
/* @__PURE__ */ jsxs6("span", { className: "cs-row__body", children: [
|
|
1234
|
+
renaming ? /* @__PURE__ */ jsx6("span", { className: "pointer-events-auto relative z-10 block", children: /* @__PURE__ */ jsx6(RenameInput, { initial: entry.title, onDone: rename }) }) : /* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-1", children: [
|
|
1235
|
+
/* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate text-[13px] font-medium leading-5", children: entry.title }),
|
|
1236
|
+
entry.pinned ? /* @__PURE__ */ jsx6(PinIcon, { size: 11, className: "shrink-0 text-muted-foreground", "aria-label": "Pinned" }) : null
|
|
985
1237
|
] }),
|
|
986
|
-
/* @__PURE__ */
|
|
987
|
-
props.snippet ? /* @__PURE__ */
|
|
1238
|
+
/* @__PURE__ */ jsx6("span", { className: "block truncate text-[11.5px] leading-4 text-muted-foreground", children: props.meta }),
|
|
1239
|
+
props.snippet ? /* @__PURE__ */ jsx6("span", { className: "cs-row__snippet", children: props.snippet }) : null
|
|
988
1240
|
] }),
|
|
989
|
-
renaming ? null : /* @__PURE__ */
|
|
1241
|
+
renaming ? null : /* @__PURE__ */ jsxs6("span", { className: "cs-row__actions", children: [
|
|
990
1242
|
props.takeover,
|
|
991
|
-
/* @__PURE__ */
|
|
992
|
-
/* @__PURE__ */
|
|
993
|
-
/* @__PURE__ */
|
|
1243
|
+
/* @__PURE__ */ jsxs6(DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [
|
|
1244
|
+
/* @__PURE__ */ jsx6(DropdownMenuTrigger, { 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 }) }) }),
|
|
1245
|
+
/* @__PURE__ */ jsx6(DropdownMenuContent, { align: "start", className: "w-60", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ jsx6(ChatMenuItems, { entry, variant: "dropdown", onRename: () => setRenaming(true) }) })
|
|
994
1246
|
] })
|
|
995
1247
|
] })
|
|
996
1248
|
]
|
|
997
1249
|
}
|
|
998
1250
|
) }),
|
|
999
|
-
/* @__PURE__ */
|
|
1251
|
+
/* @__PURE__ */ jsx6(ContextMenuContent, { className: "w-60", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ jsx6(ChatMenuItems, { entry, variant: "context", onRename: () => setRenaming(true) }) })
|
|
1000
1252
|
] });
|
|
1001
1253
|
}
|
|
1002
1254
|
function SidebarSkeleton() {
|
|
1003
|
-
return /* @__PURE__ */
|
|
1255
|
+
return /* @__PURE__ */ jsx6("div", { className: "space-y-1.5 px-3 py-2", "aria-hidden": "true", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx6("div", { className: "cs-skeleton h-9 rounded-lg" }, i)) });
|
|
1004
1256
|
}
|
|
1005
1257
|
function Highlight({ text, query }) {
|
|
1006
1258
|
const q = query.trim().toLowerCase();
|
|
1007
1259
|
if (!q) return text;
|
|
1008
1260
|
const at = text.toLowerCase().indexOf(q);
|
|
1009
1261
|
if (at < 0) return text;
|
|
1010
|
-
return /* @__PURE__ */
|
|
1262
|
+
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1011
1263
|
text.slice(0, at),
|
|
1012
|
-
/* @__PURE__ */
|
|
1264
|
+
/* @__PURE__ */ jsx6("mark", { className: "cs-mark", children: text.slice(at, at + q.length) }),
|
|
1013
1265
|
text.slice(at + q.length)
|
|
1014
1266
|
] });
|
|
1015
1267
|
}
|
|
@@ -1024,8 +1276,8 @@ var EMPTY_SEARCH = {
|
|
|
1024
1276
|
};
|
|
1025
1277
|
function useContentSearch(query) {
|
|
1026
1278
|
const client = useCodingSessionsClient();
|
|
1027
|
-
const [state, setState] =
|
|
1028
|
-
const latest =
|
|
1279
|
+
const [state, setState] = useState5(EMPTY_SEARCH);
|
|
1280
|
+
const latest = useRef2(query);
|
|
1029
1281
|
latest.current = query;
|
|
1030
1282
|
const run = useCallback(
|
|
1031
1283
|
async (q, cursor, append) => {
|
|
@@ -1049,7 +1301,7 @@ function useContentSearch(query) {
|
|
|
1049
1301
|
},
|
|
1050
1302
|
[client]
|
|
1051
1303
|
);
|
|
1052
|
-
|
|
1304
|
+
useEffect3(() => {
|
|
1053
1305
|
const q = query.trim();
|
|
1054
1306
|
if (q.length < 2) {
|
|
1055
1307
|
setState(EMPTY_SEARCH);
|
|
@@ -1078,19 +1330,19 @@ function Sidebar(props) {
|
|
|
1078
1330
|
const client = useCodingSessionsClient();
|
|
1079
1331
|
const state = useCodingSessionsState();
|
|
1080
1332
|
const now = useMinuteClock();
|
|
1081
|
-
const [query, setQuery] =
|
|
1333
|
+
const [query, setQuery] = useState5("");
|
|
1082
1334
|
const [search, searchMore] = useContentSearch(query);
|
|
1083
|
-
const [groupMode, setGroupMode] =
|
|
1084
|
-
const [showHidden, setShowHidden] =
|
|
1085
|
-
const [takingOver, setTakingOver] =
|
|
1086
|
-
const [takeoverError, setTakeoverError] =
|
|
1335
|
+
const [groupMode, setGroupMode] = useState5(() => readLocal("coding-sessions.group", ["date", "folder"], "date"));
|
|
1336
|
+
const [showHidden, setShowHidden] = useState5(false);
|
|
1337
|
+
const [takingOver, setTakingOver] = useState5(null);
|
|
1338
|
+
const [takeoverError, setTakeoverError] = useState5(null);
|
|
1087
1339
|
const prefs = state.preferences;
|
|
1088
1340
|
const sessions = state.sessions.data;
|
|
1089
1341
|
const isLive = (id) => {
|
|
1090
1342
|
const run = state.runs[id];
|
|
1091
1343
|
return run !== void 0 && !isTerminalRunStatus(run.status);
|
|
1092
1344
|
};
|
|
1093
|
-
const { ours, others, hiddenCount } =
|
|
1345
|
+
const { ours, others, hiddenCount } = useMemo3(() => {
|
|
1094
1346
|
const oursList = sessions.map((s) => sessionEntry(s, prefs));
|
|
1095
1347
|
const known = new Set(sessions.map((s) => s.providerSessionId).filter(Boolean));
|
|
1096
1348
|
const othersList = state.discovered.data.filter((d) => !known.has(d.providerSessionId)).map((d) => discoveredEntry(d, prefs));
|
|
@@ -1130,8 +1382,8 @@ function Sidebar(props) {
|
|
|
1130
1382
|
let meta;
|
|
1131
1383
|
if (live) meta = `${PROVIDER_LABEL[entry.provider]} is working\u2026`;
|
|
1132
1384
|
else if (d?.activeElsewhere)
|
|
1133
|
-
meta = /* @__PURE__ */
|
|
1134
|
-
/* @__PURE__ */
|
|
1385
|
+
meta = /* @__PURE__ */ jsxs6("span", { className: "cs-live-elsewhere", children: [
|
|
1386
|
+
/* @__PURE__ */ jsx6("span", { className: "cs-live-dot", "aria-hidden": "true" }),
|
|
1135
1387
|
"Running in ",
|
|
1136
1388
|
PROVIDER_LABEL[entry.provider]
|
|
1137
1389
|
] });
|
|
@@ -1140,8 +1392,8 @@ function Sidebar(props) {
|
|
|
1140
1392
|
const where = entry.cwd ? prettyPath2(entry.cwd) : "unknown folder";
|
|
1141
1393
|
meta = `${status}${entry.kind === "discovered" ? `${PROVIDER_LABEL[entry.provider]} \xB7 ` : ""}${groupMode === "folder" && !extra ? "" : `${where} \xB7 `}${relativeTime(entry.updatedAt, now)}`;
|
|
1142
1394
|
}
|
|
1143
|
-
return /* @__PURE__ */
|
|
1144
|
-
/* @__PURE__ */
|
|
1395
|
+
return /* @__PURE__ */ jsxs6("div", { children: [
|
|
1396
|
+
/* @__PURE__ */ jsx6(
|
|
1145
1397
|
Row,
|
|
1146
1398
|
{
|
|
1147
1399
|
entry,
|
|
@@ -1150,7 +1402,7 @@ function Sidebar(props) {
|
|
|
1150
1402
|
live,
|
|
1151
1403
|
meta,
|
|
1152
1404
|
snippet: extra?.snippet,
|
|
1153
|
-
takeover: d?.cwd ? /* @__PURE__ */
|
|
1405
|
+
takeover: d?.cwd ? /* @__PURE__ */ jsxs6(
|
|
1154
1406
|
"button",
|
|
1155
1407
|
{
|
|
1156
1408
|
type: "button",
|
|
@@ -1159,18 +1411,18 @@ function Sidebar(props) {
|
|
|
1159
1411
|
title: d.activeElsewhere ? d.activeElsewhere.message : "Continue this chat here",
|
|
1160
1412
|
disabled: takingOver === d.providerSessionId,
|
|
1161
1413
|
children: [
|
|
1162
|
-
takingOver === d.providerSessionId ? /* @__PURE__ */
|
|
1414
|
+
takingOver === d.providerSessionId ? /* @__PURE__ */ jsx6(SpinnerIcon, { size: 11 }) : null,
|
|
1163
1415
|
"Take over"
|
|
1164
1416
|
]
|
|
1165
1417
|
}
|
|
1166
1418
|
) : null
|
|
1167
1419
|
}
|
|
1168
1420
|
),
|
|
1169
|
-
takeoverError && d && takeoverError.id === d.providerSessionId ? /* @__PURE__ */
|
|
1421
|
+
takeoverError && d && takeoverError.id === d.providerSessionId ? /* @__PURE__ */ jsx6("p", { className: "mx-4 mb-1 text-[11.5px] text-destructive", children: takeoverError.message }) : null
|
|
1170
1422
|
] }, entry.key);
|
|
1171
1423
|
};
|
|
1172
|
-
const renderGroups = (entries) => groupEntries(entries, groupMode, now).map((group) => /* @__PURE__ */
|
|
1173
|
-
/* @__PURE__ */
|
|
1424
|
+
const renderGroups = (entries) => groupEntries(entries, groupMode, now).map((group) => /* @__PURE__ */ jsxs6("div", { role: "group", "aria-label": group.label, children: [
|
|
1425
|
+
/* @__PURE__ */ jsx6(GroupLabel, { children: group.label }),
|
|
1174
1426
|
group.entries.map((e) => renderEntry(e))
|
|
1175
1427
|
] }, group.label));
|
|
1176
1428
|
const searching = query.trim().length > 0;
|
|
@@ -1187,60 +1439,60 @@ function Sidebar(props) {
|
|
|
1187
1439
|
props.onFound(hitToDiscovered(hit));
|
|
1188
1440
|
props.select({ kind: "discovered", provider: hit.provider, id: hit.providerSessionId });
|
|
1189
1441
|
};
|
|
1190
|
-
const searchBody = /* @__PURE__ */
|
|
1191
|
-
/* @__PURE__ */
|
|
1192
|
-
titleMatches.length === 0 ? /* @__PURE__ */
|
|
1193
|
-
/* @__PURE__ */
|
|
1194
|
-
query.trim().length < 2 ? /* @__PURE__ */
|
|
1442
|
+
const searchBody = /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1443
|
+
/* @__PURE__ */ jsx6(SectionLabel, { children: "Chats" }),
|
|
1444
|
+
titleMatches.length === 0 ? /* @__PURE__ */ jsx6("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 })),
|
|
1445
|
+
/* @__PURE__ */ jsx6(SectionLabel, { children: "In conversations" }),
|
|
1446
|
+
query.trim().length < 2 ? /* @__PURE__ */ jsx6("p", { className: "px-4 py-1 text-[12px] text-muted-foreground", children: "Type at least two letters to search what was said." }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1195
1447
|
contentHits.map((hit) => {
|
|
1196
1448
|
const known = allByKey.get(chatKey(hit.provider, hit.providerSessionId));
|
|
1197
1449
|
const entry = known ?? discoveredEntry(hitToDiscovered(hit), prefs);
|
|
1198
|
-
return /* @__PURE__ */
|
|
1450
|
+
return /* @__PURE__ */ jsx6("div", { onClickCapture: known ? void 0 : () => props.onFound(hitToDiscovered(hit)), children: renderEntry(entry, {
|
|
1199
1451
|
query,
|
|
1200
|
-
snippet: hit.snippet ? /* @__PURE__ */
|
|
1452
|
+
snippet: hit.snippet ? /* @__PURE__ */ jsx6(Highlight, { text: hit.snippet, query }) : void 0
|
|
1201
1453
|
}) }, `hit:${entry.key}`);
|
|
1202
1454
|
}),
|
|
1203
|
-
/* @__PURE__ */
|
|
1455
|
+
/* @__PURE__ */ jsx6("div", { className: "px-4 py-2 text-[11.5px] leading-4 text-muted-foreground", role: "status", "aria-live": "polite", children: search.error ? /* @__PURE__ */ jsxs6("span", { className: "text-destructive", children: [
|
|
1204
1456
|
"Search stopped: ",
|
|
1205
1457
|
search.error
|
|
1206
|
-
] }) : search.loading ? /* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
1458
|
+
] }) : search.loading ? /* @__PURE__ */ jsxs6("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
1459
|
+
/* @__PURE__ */ jsx6(SpinnerIcon, { size: 12 }),
|
|
1208
1460
|
" Searching your chats\u2026"
|
|
1209
|
-
] }) : search.query ? /* @__PURE__ */
|
|
1461
|
+
] }) : search.query ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1210
1462
|
contentHits.length === 0 && search.hits.length === 0 ? "Nothing found. " : null,
|
|
1211
1463
|
search.nextCursor === null ? `Searched all ${search.total.toLocaleString()} chats on this computer.` : `Searched the ${search.scanned.toLocaleString()} most recent of ${search.total.toLocaleString()} chats.`,
|
|
1212
|
-
search.nextCursor !== null ? /* @__PURE__ */
|
|
1464
|
+
search.nextCursor !== null ? /* @__PURE__ */ jsx6("button", { type: "button", className: "cs-link ml-1", onClick: searchMore, children: "Search older chats" }) : null
|
|
1213
1465
|
] }) : null })
|
|
1214
1466
|
] })
|
|
1215
1467
|
] });
|
|
1216
|
-
const listBody = /* @__PURE__ */
|
|
1217
|
-
pinned.length > 0 ? /* @__PURE__ */
|
|
1218
|
-
/* @__PURE__ */
|
|
1468
|
+
const listBody = /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1469
|
+
pinned.length > 0 ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1470
|
+
/* @__PURE__ */ jsx6(SectionLabel, { children: "Pinned" }),
|
|
1219
1471
|
pinned.map((e) => renderEntry(e))
|
|
1220
1472
|
] }) : null,
|
|
1221
|
-
running.length > 0 ? /* @__PURE__ */
|
|
1222
|
-
/* @__PURE__ */
|
|
1473
|
+
running.length > 0 ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1474
|
+
/* @__PURE__ */ jsx6(SectionLabel, { children: "Running" }),
|
|
1223
1475
|
running.map((e) => renderEntry(e))
|
|
1224
1476
|
] }) : null,
|
|
1225
|
-
/* @__PURE__ */
|
|
1226
|
-
state.sessions.loading && state.sessions.loadedAt === null ? /* @__PURE__ */
|
|
1227
|
-
/* @__PURE__ */
|
|
1477
|
+
/* @__PURE__ */ jsx6(SectionLabel, { children: "Recent" }),
|
|
1478
|
+
state.sessions.loading && state.sessions.loadedAt === null ? /* @__PURE__ */ jsx6(SidebarSkeleton, {}) : state.sessions.error ? /* @__PURE__ */ jsx6("p", { className: "px-4 py-1 text-[12px] text-destructive", children: state.sessions.error }) : recent.length === 0 ? running.length === 0 ? /* @__PURE__ */ jsx6("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)),
|
|
1479
|
+
/* @__PURE__ */ jsx6(
|
|
1228
1480
|
SectionLabel,
|
|
1229
1481
|
{
|
|
1230
|
-
action: /* @__PURE__ */
|
|
1231
|
-
/* @__PURE__ */
|
|
1232
|
-
/* @__PURE__ */
|
|
1233
|
-
/* @__PURE__ */
|
|
1234
|
-
/* @__PURE__ */
|
|
1235
|
-
/* @__PURE__ */
|
|
1236
|
-
/* @__PURE__ */
|
|
1237
|
-
/* @__PURE__ */
|
|
1482
|
+
action: /* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-0.5", children: [
|
|
1483
|
+
/* @__PURE__ */ jsxs6(DropdownMenu, { children: [
|
|
1484
|
+
/* @__PURE__ */ jsx6(DropdownMenuTrigger, { 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" }) }),
|
|
1485
|
+
/* @__PURE__ */ jsxs6(DropdownMenuContent, { align: "end", className: "w-52", children: [
|
|
1486
|
+
/* @__PURE__ */ jsx6(DropdownMenuLabel, { children: "Group your other chats" }),
|
|
1487
|
+
/* @__PURE__ */ jsxs6(DropdownMenuRadioGroup, { value: groupMode, onValueChange: (v) => setMode(v), children: [
|
|
1488
|
+
/* @__PURE__ */ jsx6(DropdownMenuRadioItem, { value: "date", children: "By date" }),
|
|
1489
|
+
/* @__PURE__ */ jsx6(DropdownMenuRadioItem, { value: "folder", children: "By folder" })
|
|
1238
1490
|
] }),
|
|
1239
|
-
/* @__PURE__ */
|
|
1240
|
-
/* @__PURE__ */
|
|
1491
|
+
/* @__PURE__ */ jsx6(DropdownMenuSeparator2, {}),
|
|
1492
|
+
/* @__PURE__ */ jsx6(DropdownMenuItem2, { onSelect: () => setShowHidden((v) => !v), children: showHidden ? "Leave hidden chats out" : `Show hidden chats${hiddenCount ? ` (${hiddenCount})` : ""}` })
|
|
1241
1493
|
] })
|
|
1242
1494
|
] }),
|
|
1243
|
-
/* @__PURE__ */
|
|
1495
|
+
/* @__PURE__ */ jsx6(
|
|
1244
1496
|
"button",
|
|
1245
1497
|
{
|
|
1246
1498
|
type: "button",
|
|
@@ -1248,17 +1500,17 @@ function Sidebar(props) {
|
|
|
1248
1500
|
onClick: () => void client.refreshDiscovered(),
|
|
1249
1501
|
"aria-label": "Look again for your other chats",
|
|
1250
1502
|
title: "Look again",
|
|
1251
|
-
children: state.discovered.loading ? /* @__PURE__ */
|
|
1503
|
+
children: state.discovered.loading ? /* @__PURE__ */ jsx6(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ jsx6(RefreshIcon, { size: 13 })
|
|
1252
1504
|
}
|
|
1253
1505
|
)
|
|
1254
1506
|
] }),
|
|
1255
1507
|
children: "Your other chats"
|
|
1256
1508
|
}
|
|
1257
1509
|
),
|
|
1258
|
-
state.discovered.loading && state.discovered.loadedAt === null ? /* @__PURE__ */
|
|
1510
|
+
state.discovered.loading && state.discovered.loadedAt === null ? /* @__PURE__ */ jsx6(SidebarSkeleton, {}) : state.discovered.error ? /* @__PURE__ */ jsx6("p", { className: "px-4 py-1 text-[12px] text-destructive", children: state.discovered.error }) : otherList.length === 0 ? /* @__PURE__ */ jsx6("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__ */ jsxs6(Fragment4, { children: [
|
|
1259
1511
|
renderGroups(otherList),
|
|
1260
|
-
state.discovered.data.length >= state.discoveredLimit ? /* @__PURE__ */
|
|
1261
|
-
|
|
1512
|
+
state.discovered.data.length >= state.discoveredLimit ? /* @__PURE__ */ jsx6("div", { className: "px-3 pt-2", children: /* @__PURE__ */ jsxs6(
|
|
1513
|
+
Button2,
|
|
1262
1514
|
{
|
|
1263
1515
|
variant: "ghost",
|
|
1264
1516
|
size: "sm",
|
|
@@ -1266,32 +1518,32 @@ function Sidebar(props) {
|
|
|
1266
1518
|
onClick: () => void client.showMoreDiscovered(),
|
|
1267
1519
|
disabled: state.discovered.loading,
|
|
1268
1520
|
children: [
|
|
1269
|
-
state.discovered.loading ? /* @__PURE__ */
|
|
1521
|
+
state.discovered.loading ? /* @__PURE__ */ jsx6(SpinnerIcon, { size: 13 }) : null,
|
|
1270
1522
|
"Show older chats"
|
|
1271
1523
|
]
|
|
1272
1524
|
}
|
|
1273
1525
|
) }) : null
|
|
1274
1526
|
] }),
|
|
1275
|
-
showHidden ? null : hiddenCount > 0 ? /* @__PURE__ */
|
|
1527
|
+
showHidden ? null : hiddenCount > 0 ? /* @__PURE__ */ jsxs6("button", { type: "button", className: "cs-link mx-4 mt-3 text-[11.5px]", onClick: () => setShowHidden(true), children: [
|
|
1276
1528
|
hiddenCount,
|
|
1277
1529
|
" hidden ",
|
|
1278
1530
|
hiddenCount === 1 ? "chat" : "chats",
|
|
1279
1531
|
" \u2014 show"
|
|
1280
1532
|
] }) : null
|
|
1281
1533
|
] });
|
|
1282
|
-
return /* @__PURE__ */
|
|
1534
|
+
return /* @__PURE__ */ jsxs6(
|
|
1283
1535
|
"aside",
|
|
1284
1536
|
{
|
|
1285
|
-
className: "cs-sidebar flex h-full shrink-0 flex-col border-r border-border bg-
|
|
1537
|
+
className: "cs-sidebar flex h-full shrink-0 flex-col border-r border-border bg-sidebar-background",
|
|
1286
1538
|
style: { width: props.width },
|
|
1287
1539
|
"aria-label": "Sessions",
|
|
1288
1540
|
children: [
|
|
1289
|
-
/* @__PURE__ */
|
|
1290
|
-
/* @__PURE__ */
|
|
1291
|
-
/* @__PURE__ */
|
|
1292
|
-
/* @__PURE__ */
|
|
1541
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2 px-4 pb-2 pt-3.5", children: [
|
|
1542
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
1543
|
+
/* @__PURE__ */ jsx6("span", { className: "cs-app-mark", "aria-hidden": "true" }),
|
|
1544
|
+
/* @__PURE__ */ jsx6("span", { className: "truncate text-[14px] font-semibold tracking-[-0.01em]", children: "Coding sessions" })
|
|
1293
1545
|
] }),
|
|
1294
|
-
/* @__PURE__ */
|
|
1546
|
+
/* @__PURE__ */ jsx6(
|
|
1295
1547
|
"button",
|
|
1296
1548
|
{
|
|
1297
1549
|
type: "button",
|
|
@@ -1299,19 +1551,19 @@ function Sidebar(props) {
|
|
|
1299
1551
|
onClick: props.onCollapse,
|
|
1300
1552
|
"aria-label": "Hide the sidebar (\u2318B)",
|
|
1301
1553
|
title: "Hide sidebar \u2318B",
|
|
1302
|
-
children: /* @__PURE__ */
|
|
1554
|
+
children: /* @__PURE__ */ jsx6(SidebarIcon, { size: 15 })
|
|
1303
1555
|
}
|
|
1304
1556
|
)
|
|
1305
1557
|
] }),
|
|
1306
|
-
/* @__PURE__ */
|
|
1307
|
-
/* @__PURE__ */
|
|
1308
|
-
/* @__PURE__ */
|
|
1558
|
+
/* @__PURE__ */ jsxs6("div", { className: "space-y-1.5 px-3 pb-1", children: [
|
|
1559
|
+
/* @__PURE__ */ jsxs6(Button2, { className: "w-full justify-start gap-2", variant: "outline", size: "sm", onClick: props.onNew, children: [
|
|
1560
|
+
/* @__PURE__ */ jsx6(PlusIcon, { size: 15 }),
|
|
1309
1561
|
"New session",
|
|
1310
|
-
/* @__PURE__ */
|
|
1562
|
+
/* @__PURE__ */ jsx6("kbd", { className: "cs-kbd ml-auto", children: "\u2325\u2318N" })
|
|
1311
1563
|
] }),
|
|
1312
|
-
/* @__PURE__ */
|
|
1313
|
-
/* @__PURE__ */
|
|
1314
|
-
/* @__PURE__ */
|
|
1564
|
+
/* @__PURE__ */ jsxs6("div", { className: "cs-search", children: [
|
|
1565
|
+
/* @__PURE__ */ jsx6(SearchIcon, { size: 14, className: "cs-search__icon" }),
|
|
1566
|
+
/* @__PURE__ */ jsx6(
|
|
1315
1567
|
"input",
|
|
1316
1568
|
{
|
|
1317
1569
|
ref: props.searchRef,
|
|
@@ -1337,10 +1589,10 @@ function Sidebar(props) {
|
|
|
1337
1589
|
className: "cs-search__input"
|
|
1338
1590
|
}
|
|
1339
1591
|
),
|
|
1340
|
-
query ? /* @__PURE__ */
|
|
1592
|
+
query ? /* @__PURE__ */ jsx6("button", { type: "button", className: "cs-icon-button cs-search__clear", onClick: () => setQuery(""), "aria-label": "Clear search", children: /* @__PURE__ */ jsx6(CloseIcon, { size: 13 }) }) : /* @__PURE__ */ jsx6("kbd", { className: "cs-search__kbd", children: "\u2318K" })
|
|
1341
1593
|
] })
|
|
1342
1594
|
] }),
|
|
1343
|
-
/* @__PURE__ */
|
|
1595
|
+
/* @__PURE__ */ jsx6("nav", { className: "min-h-0 flex-1 overflow-y-auto pb-3", children: searching ? searchBody : listBody }),
|
|
1344
1596
|
props.footer
|
|
1345
1597
|
]
|
|
1346
1598
|
}
|
|
@@ -1507,14 +1759,15 @@ function createTranscriptBuilder() {
|
|
|
1507
1759
|
}));
|
|
1508
1760
|
return;
|
|
1509
1761
|
case "error": {
|
|
1510
|
-
const
|
|
1762
|
+
const text = runErrorLabel(item.text);
|
|
1763
|
+
const said = current?.message.parts.some((p) => p.type === "error" && p.message.trim() === text.trim());
|
|
1511
1764
|
if (said) return;
|
|
1512
1765
|
upsertPart(item.id, () => ({
|
|
1513
1766
|
type: "error",
|
|
1514
1767
|
errorType: "provider",
|
|
1515
1768
|
code: null,
|
|
1516
|
-
message:
|
|
1517
|
-
userMessage:
|
|
1769
|
+
message: text,
|
|
1770
|
+
userMessage: text,
|
|
1518
1771
|
recoverable: true,
|
|
1519
1772
|
remedy: null
|
|
1520
1773
|
}));
|
|
@@ -1932,13 +2185,13 @@ function firstInvalidField(errors) {
|
|
|
1932
2185
|
}
|
|
1933
2186
|
|
|
1934
2187
|
// src/react/app.tsx
|
|
1935
|
-
import { Fragment as
|
|
2188
|
+
import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1936
2189
|
function CodingSessionsProvider({ transport, children }) {
|
|
1937
|
-
const [client] =
|
|
1938
|
-
|
|
2190
|
+
const [client] = useState6(() => new CodingSessionsClient(transport));
|
|
2191
|
+
useEffect4(() => {
|
|
1939
2192
|
if (transport.status().state === "open") void client.refreshAll();
|
|
1940
2193
|
}, [client, transport]);
|
|
1941
|
-
return /* @__PURE__ */
|
|
2194
|
+
return /* @__PURE__ */ jsx7(CodingSessionsContext.Provider, { value: client, children });
|
|
1942
2195
|
}
|
|
1943
2196
|
function readHash() {
|
|
1944
2197
|
if (typeof location === "undefined") return { kind: "none" };
|
|
@@ -1961,8 +2214,8 @@ function readTheme() {
|
|
|
1961
2214
|
}
|
|
1962
2215
|
}
|
|
1963
2216
|
function useTheme() {
|
|
1964
|
-
const [choice, setChoice] =
|
|
1965
|
-
|
|
2217
|
+
const [choice, setChoice] = useState6(readTheme);
|
|
2218
|
+
useEffect4(() => {
|
|
1966
2219
|
const media = typeof window.matchMedia === "function" ? window.matchMedia("(prefers-color-scheme: dark)") : null;
|
|
1967
2220
|
const apply = () => {
|
|
1968
2221
|
const dark = choice === "dark" || choice === "system" && media?.matches === true;
|
|
@@ -1992,8 +2245,8 @@ var RUN_LABEL = {
|
|
|
1992
2245
|
function RunPill({ run }) {
|
|
1993
2246
|
if (!run) return null;
|
|
1994
2247
|
const live = !isTerminalRunStatus(run.status);
|
|
1995
|
-
return /* @__PURE__ */
|
|
1996
|
-
live ? /* @__PURE__ */
|
|
2248
|
+
return /* @__PURE__ */ jsxs7("span", { className: cn5("cs-pill", `cs-pill--${run.status}`), children: [
|
|
2249
|
+
live ? /* @__PURE__ */ jsx7("span", { className: "cs-pill__dot", "aria-hidden": "true" }) : null,
|
|
1997
2250
|
RUN_LABEL[run.status]
|
|
1998
2251
|
] });
|
|
1999
2252
|
}
|
|
@@ -2001,17 +2254,17 @@ function ConnectionBanner() {
|
|
|
2001
2254
|
const { connection } = useCodingSessionsState();
|
|
2002
2255
|
if (connection.state === "open") return null;
|
|
2003
2256
|
const closed = connection.state === "closed";
|
|
2004
|
-
return /* @__PURE__ */
|
|
2257
|
+
return /* @__PURE__ */ jsxs7(
|
|
2005
2258
|
"div",
|
|
2006
2259
|
{
|
|
2007
2260
|
role: "status",
|
|
2008
|
-
className:
|
|
2261
|
+
className: cn5(
|
|
2009
2262
|
"flex items-center gap-2 border-b px-4 py-2 text-[13px]",
|
|
2010
2263
|
closed ? "border-destructive/30 bg-destructive/10 text-destructive" : "border-border bg-muted/60 text-muted-foreground"
|
|
2011
2264
|
),
|
|
2012
2265
|
children: [
|
|
2013
|
-
closed ? /* @__PURE__ */
|
|
2014
|
-
/* @__PURE__ */
|
|
2266
|
+
closed ? /* @__PURE__ */ jsx7(AlertIcon, { size: 15 }) : /* @__PURE__ */ jsx7(SpinnerIcon, { size: 14 }),
|
|
2267
|
+
/* @__PURE__ */ jsx7("span", { children: closed ? connection.reason : "Connecting to the coding sessions host\u2026" })
|
|
2015
2268
|
]
|
|
2016
2269
|
}
|
|
2017
2270
|
);
|
|
@@ -2021,22 +2274,22 @@ function ProvidersFooter(props) {
|
|
|
2021
2274
|
const client = useCodingSessionsClient();
|
|
2022
2275
|
const next = { system: "light", light: "dark", dark: "system" };
|
|
2023
2276
|
const themeLabel = { system: "Match system", light: "Light", dark: "Dark" };
|
|
2024
|
-
return /* @__PURE__ */
|
|
2025
|
-
/* @__PURE__ */
|
|
2277
|
+
return /* @__PURE__ */ jsx7("div", { className: "border-t border-border px-3 py-2.5", children: /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1.5", children: [
|
|
2278
|
+
/* @__PURE__ */ jsx7("div", { className: "flex min-w-0 flex-1 flex-wrap gap-1.5", children: state.providers.loading && state.providers.loadedAt === null ? /* @__PURE__ */ jsx7("span", { className: "text-[11.5px] text-muted-foreground", children: "Checking Claude Code and Codex\u2026" }) : state.providers.data.map((p) => /* @__PURE__ */ jsxs7(
|
|
2026
2279
|
"span",
|
|
2027
2280
|
{
|
|
2028
|
-
className:
|
|
2029
|
-
title: p.problem ? `${p.problem} ${p.fix ?? ""}` :
|
|
2281
|
+
className: cn5("cs-provider-chip", p.ready ? "" : "cs-provider-chip--problem"),
|
|
2282
|
+
title: p.problem ? `${p.problem} ${p.fix ?? ""}` : [binaryWords(p) ?? p.label, p.plan, newerWords(p)].filter(Boolean).join(" \xB7 "),
|
|
2030
2283
|
children: [
|
|
2031
|
-
/* @__PURE__ */
|
|
2284
|
+
/* @__PURE__ */ jsx7(ProviderMark, { provider: p.provider, size: 13 }),
|
|
2032
2285
|
p.label,
|
|
2033
|
-
p.lastProblem ? /* @__PURE__ */
|
|
2034
|
-
p.ready ? /* @__PURE__ */
|
|
2286
|
+
p.lastProblem ? /* @__PURE__ */ jsx7("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,
|
|
2287
|
+
p.ready ? /* @__PURE__ */ jsx7(CheckIcon, { size: 12 }) : /* @__PURE__ */ jsx7(AlertIcon, { size: 12 })
|
|
2035
2288
|
]
|
|
2036
2289
|
},
|
|
2037
2290
|
p.provider
|
|
2038
2291
|
)) }),
|
|
2039
|
-
/* @__PURE__ */
|
|
2292
|
+
/* @__PURE__ */ jsx7(
|
|
2040
2293
|
"button",
|
|
2041
2294
|
{
|
|
2042
2295
|
type: "button",
|
|
@@ -2044,11 +2297,11 @@ function ProvidersFooter(props) {
|
|
|
2044
2297
|
onClick: () => void client.refreshProviders(),
|
|
2045
2298
|
"aria-label": "Check Claude Code and Codex again",
|
|
2046
2299
|
title: "Check again",
|
|
2047
|
-
children: state.providers.loading ? /* @__PURE__ */
|
|
2300
|
+
children: state.providers.loading ? /* @__PURE__ */ jsx7(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ jsx7(RefreshIcon, { size: 13 })
|
|
2048
2301
|
}
|
|
2049
2302
|
),
|
|
2050
2303
|
props.extra,
|
|
2051
|
-
/* @__PURE__ */
|
|
2304
|
+
/* @__PURE__ */ jsx7(
|
|
2052
2305
|
"button",
|
|
2053
2306
|
{
|
|
2054
2307
|
type: "button",
|
|
@@ -2056,14 +2309,14 @@ function ProvidersFooter(props) {
|
|
|
2056
2309
|
onClick: () => props.setTheme(next[props.theme]),
|
|
2057
2310
|
"aria-label": `Theme: ${themeLabel[props.theme]}. Switch to ${themeLabel[next[props.theme]]}.`,
|
|
2058
2311
|
title: `Theme: ${themeLabel[props.theme]}`,
|
|
2059
|
-
children: props.theme === "system" ? /* @__PURE__ */
|
|
2312
|
+
children: props.theme === "system" ? /* @__PURE__ */ jsx7(MonitorIcon, { size: 14 }) : props.theme === "light" ? /* @__PURE__ */ jsx7(SunIcon, { size: 14 }) : /* @__PURE__ */ jsx7(MoonIcon, { size: 14 })
|
|
2060
2313
|
}
|
|
2061
2314
|
)
|
|
2062
2315
|
] }) });
|
|
2063
2316
|
}
|
|
2064
2317
|
function useNotifier() {
|
|
2065
2318
|
const show = useContext3(ToastContext);
|
|
2066
|
-
return
|
|
2319
|
+
return useMemo4(
|
|
2067
2320
|
() => ({
|
|
2068
2321
|
notify(event) {
|
|
2069
2322
|
show(event.message);
|
|
@@ -2074,8 +2327,8 @@ function useNotifier() {
|
|
|
2074
2327
|
}
|
|
2075
2328
|
function useLiveElsewhere(provider, providerSessionId, initial = null) {
|
|
2076
2329
|
const client = useCodingSessionsClient();
|
|
2077
|
-
const [state, setState] =
|
|
2078
|
-
|
|
2330
|
+
const [state, setState] = useState6(initial);
|
|
2331
|
+
useEffect4(() => {
|
|
2079
2332
|
if (!provider || !providerSessionId) {
|
|
2080
2333
|
setState(null);
|
|
2081
2334
|
return;
|
|
@@ -2095,8 +2348,8 @@ function useLiveElsewhere(provider, providerSessionId, initial = null) {
|
|
|
2095
2348
|
}
|
|
2096
2349
|
function useSessionUsage(sessionId, lastRunKey) {
|
|
2097
2350
|
const client = useCodingSessionsClient();
|
|
2098
|
-
const [usage, setUsage] =
|
|
2099
|
-
|
|
2351
|
+
const [usage, setUsage] = useState6(null);
|
|
2352
|
+
useEffect4(() => {
|
|
2100
2353
|
let cancelled = false;
|
|
2101
2354
|
void client.transport.call("listRuns", sessionId).then((runs) => {
|
|
2102
2355
|
if (cancelled) return;
|
|
@@ -2117,18 +2370,18 @@ function useSessionUsage(sessionId, lastRunKey) {
|
|
|
2117
2370
|
return usage;
|
|
2118
2371
|
}
|
|
2119
2372
|
function HeaderMenu(props) {
|
|
2120
|
-
return /* @__PURE__ */
|
|
2121
|
-
/* @__PURE__ */
|
|
2122
|
-
/* @__PURE__ */
|
|
2373
|
+
return /* @__PURE__ */ jsxs7(DropdownMenu2, { children: [
|
|
2374
|
+
/* @__PURE__ */ jsx7(DropdownMenuTrigger2, { 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 }) }) }),
|
|
2375
|
+
/* @__PURE__ */ jsx7(DropdownMenuContent2, { align: "end", className: "w-64", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ jsx7(ChatMenuItems, { entry: props.entry, variant: "dropdown", onRename: props.onRename }) })
|
|
2123
2376
|
] });
|
|
2124
2377
|
}
|
|
2125
2378
|
function HeaderTitle(props) {
|
|
2126
2379
|
const client = useCodingSessionsClient();
|
|
2127
2380
|
const show = useContext3(ToastContext);
|
|
2128
|
-
const [value, setValue] =
|
|
2129
|
-
|
|
2130
|
-
const inputRef =
|
|
2131
|
-
|
|
2381
|
+
const [value, setValue] = useState6(props.entry.title);
|
|
2382
|
+
useEffect4(() => setValue(props.entry.title), [props.entry.title, props.renaming]);
|
|
2383
|
+
const inputRef = useRef3(null);
|
|
2384
|
+
useEffect4(() => {
|
|
2132
2385
|
if (!props.renaming) return;
|
|
2133
2386
|
const timer = setTimeout(() => {
|
|
2134
2387
|
const input = inputRef.current;
|
|
@@ -2140,7 +2393,7 @@ function HeaderTitle(props) {
|
|
|
2140
2393
|
return () => clearTimeout(timer);
|
|
2141
2394
|
}, [props.renaming]);
|
|
2142
2395
|
if (!props.renaming) {
|
|
2143
|
-
return /* @__PURE__ */
|
|
2396
|
+
return /* @__PURE__ */ jsx7(
|
|
2144
2397
|
"h1",
|
|
2145
2398
|
{
|
|
2146
2399
|
className: "truncate text-[15px] font-semibold leading-5 tracking-[-0.01em]",
|
|
@@ -2157,7 +2410,7 @@ function HeaderTitle(props) {
|
|
|
2157
2410
|
const next = title === "" || title === props.entry.originalTitle ? null : title;
|
|
2158
2411
|
client.setPreference(props.entry.key, { title: next }).catch((error) => show(`The new name didn't save: ${error instanceof Error ? error.message : String(error)}`));
|
|
2159
2412
|
};
|
|
2160
|
-
return /* @__PURE__ */
|
|
2413
|
+
return /* @__PURE__ */ jsx7(
|
|
2161
2414
|
"input",
|
|
2162
2415
|
{
|
|
2163
2416
|
ref: inputRef,
|
|
@@ -2176,11 +2429,18 @@ function HeaderTitle(props) {
|
|
|
2176
2429
|
);
|
|
2177
2430
|
}
|
|
2178
2431
|
function LongChatNote(props) {
|
|
2179
|
-
return /* @__PURE__ */
|
|
2432
|
+
return /* @__PURE__ */ jsxs7("p", { className: "mx-auto mt-3 flex items-center gap-2 text-[12px] text-muted-foreground", children: [
|
|
2180
2433
|
"This chat is very long \u2014 showing its most recent part.",
|
|
2181
|
-
/* @__PURE__ */
|
|
2434
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: "cs-link", onClick: props.onEarlier, disabled: props.loading, children: props.loading ? "Reading\u2026" : "Show earlier" })
|
|
2182
2435
|
] });
|
|
2183
2436
|
}
|
|
2437
|
+
function binaryWords(p) {
|
|
2438
|
+
if (!p.version) return null;
|
|
2439
|
+
return `${p.label} ${p.version}${p.binary ? ` \xB7 ${p.binary.sourceLabel}` : ""}`;
|
|
2440
|
+
}
|
|
2441
|
+
function newerWords(p) {
|
|
2442
|
+
return p.binary?.newer ? `Newer: ${p.binary.newer.version} ${p.binary.newer.sourceLabel}` : null;
|
|
2443
|
+
}
|
|
2184
2444
|
function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
2185
2445
|
const client = useCodingSessionsClient();
|
|
2186
2446
|
const state = useCodingSessionsState();
|
|
@@ -2192,8 +2452,9 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2192
2452
|
const provider = state.providers.data.find((p) => p.provider === session.provider) ?? null;
|
|
2193
2453
|
const blocked = provider && (!provider.installed || !provider.loggedIn) ? provider : null;
|
|
2194
2454
|
const limited = !blocked && provider?.lastProblem ? provider : null;
|
|
2195
|
-
const
|
|
2196
|
-
const [
|
|
2455
|
+
const modelRefused = run?.status === "failed" && isModelUnavailable(run.error);
|
|
2456
|
+
const [stopping, setStopping] = useState6(false);
|
|
2457
|
+
const [renaming, setRenaming] = useState6(false);
|
|
2197
2458
|
const elsewhere = useLiveElsewhere(
|
|
2198
2459
|
session.origin === "takeover" && !live ? session.provider : null,
|
|
2199
2460
|
session.providerSessionId
|
|
@@ -2202,7 +2463,7 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2202
2463
|
const messages = transcript.thread.getSnapshot().messages;
|
|
2203
2464
|
const files = useChangedFiles(messages);
|
|
2204
2465
|
const usage = useSessionUsage(session.id, `${run?.runId ?? ""}:${run?.status ?? ""}`);
|
|
2205
|
-
|
|
2466
|
+
useEffect4(() => {
|
|
2206
2467
|
if (!live) setStopping(false);
|
|
2207
2468
|
}, [live]);
|
|
2208
2469
|
const stop = async () => {
|
|
@@ -2215,16 +2476,16 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2215
2476
|
};
|
|
2216
2477
|
const usageWords = usage ? `${formatCount(usage.tokens, { style: "compact" })} tokens${usage.cost !== null ? ` \xB7 ${formatUsd(usage.cost)}` : ""}` : null;
|
|
2217
2478
|
const usageTitle = usage ? `${formatCount(usage.tokens)} tokens over ${usage.runs} ${usage.runs === 1 ? "message" : "messages"} sent from here.` + (usage.cost !== null ? usage.billing === "subscription" ? ` ${formatUsd(usage.cost)} is what this would cost at API prices \u2014 it's covered by your ${provider?.plan ?? ""} plan.`.replace(" ", " ") : ` Billed ${formatUsd(usage.cost)} to your API key.` : "") : "";
|
|
2218
|
-
return /* @__PURE__ */
|
|
2219
|
-
/* @__PURE__ */
|
|
2220
|
-
/* @__PURE__ */
|
|
2221
|
-
/* @__PURE__ */
|
|
2222
|
-
/* @__PURE__ */
|
|
2223
|
-
/* @__PURE__ */
|
|
2224
|
-
/* @__PURE__ */
|
|
2225
|
-
/* @__PURE__ */
|
|
2226
|
-
/* @__PURE__ */
|
|
2227
|
-
/* @__PURE__ */
|
|
2479
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1", children: [
|
|
2480
|
+
/* @__PURE__ */ jsxs7("section", { className: "flex min-w-0 flex-1 flex-col", "aria-label": entry.title, children: [
|
|
2481
|
+
/* @__PURE__ */ jsxs7("header", { className: "flex flex-wrap items-center gap-2 border-b border-border px-5 pt-2.5 pb-2.5", children: [
|
|
2482
|
+
/* @__PURE__ */ jsx7(ProviderMark, { provider: session.provider, size: 22 }),
|
|
2483
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1 overflow-hidden", children: [
|
|
2484
|
+
/* @__PURE__ */ jsx7(HeaderTitle, { entry, renaming, setRenaming }),
|
|
2485
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 items-center gap-1 text-[12px] leading-5 text-muted-foreground", children: [
|
|
2486
|
+
/* @__PURE__ */ jsx7("span", { className: "shrink-0", children: PROVIDER_LABEL[session.provider] }),
|
|
2487
|
+
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
2488
|
+
/* @__PURE__ */ jsx7(
|
|
2228
2489
|
ModelPicker,
|
|
2229
2490
|
{
|
|
2230
2491
|
status: provider,
|
|
@@ -2232,85 +2493,105 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2232
2493
|
onChange: setOptions
|
|
2233
2494
|
}
|
|
2234
2495
|
),
|
|
2235
|
-
/* @__PURE__ */
|
|
2236
|
-
/* @__PURE__ */
|
|
2237
|
-
/* @__PURE__ */
|
|
2238
|
-
usageWords ? /* @__PURE__ */
|
|
2496
|
+
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
2497
|
+
/* @__PURE__ */ jsx7(FolderIcon, { size: 12, className: "shrink-0" }),
|
|
2498
|
+
/* @__PURE__ */ jsx7("span", { className: "min-w-[4rem] truncate", title: session.cwd, children: prettyPath2(session.cwd) }),
|
|
2499
|
+
usageWords ? /* @__PURE__ */ jsxs7("span", { className: "shrink-0", title: usageTitle, children: [
|
|
2239
2500
|
"\xB7 ",
|
|
2240
2501
|
usageWords
|
|
2241
2502
|
] }) : null
|
|
2242
2503
|
] })
|
|
2243
2504
|
] }),
|
|
2244
|
-
/* @__PURE__ */
|
|
2505
|
+
session.agent ? /* @__PURE__ */ jsx7(AgentChip, { agent: session.agent }) : null,
|
|
2506
|
+
/* @__PURE__ */ jsxs7(
|
|
2245
2507
|
"button",
|
|
2246
2508
|
{
|
|
2247
2509
|
type: "button",
|
|
2248
|
-
className:
|
|
2510
|
+
className: cn5("cs-chip-button", changesOpen && "cs-chip-button--on"),
|
|
2249
2511
|
onClick: () => setChangesOpen(!changesOpen),
|
|
2250
2512
|
"aria-pressed": changesOpen,
|
|
2251
2513
|
title: "Files this chat changed",
|
|
2252
2514
|
children: [
|
|
2253
|
-
/* @__PURE__ */
|
|
2515
|
+
/* @__PURE__ */ jsx7(FileIcon, { size: 13 }),
|
|
2254
2516
|
files.length > 0 ? `${files.length} ${files.length === 1 ? "file" : "files"} changed` : "Changes"
|
|
2255
2517
|
]
|
|
2256
2518
|
}
|
|
2257
2519
|
),
|
|
2258
|
-
/* @__PURE__ */
|
|
2259
|
-
live ? /* @__PURE__ */
|
|
2260
|
-
stopping ? /* @__PURE__ */
|
|
2520
|
+
/* @__PURE__ */ jsx7(RunPill, { run }),
|
|
2521
|
+
live ? /* @__PURE__ */ jsxs7(Button3, { variant: "outline", size: "sm", onClick: () => void stop(), disabled: stopping, className: "gap-1.5", title: "Stop Esc", children: [
|
|
2522
|
+
stopping ? /* @__PURE__ */ jsx7(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ jsx7(StopIcon, { size: 13 }),
|
|
2261
2523
|
stopping ? "Stopping\u2026" : "Stop"
|
|
2262
2524
|
] }) : null,
|
|
2263
|
-
/* @__PURE__ */
|
|
2525
|
+
/* @__PURE__ */ jsx7(HeaderMenu, { entry, onRename: () => setRenaming(true) })
|
|
2264
2526
|
] }),
|
|
2265
|
-
/* @__PURE__ */
|
|
2266
|
-
/* @__PURE__ */
|
|
2267
|
-
/* @__PURE__ */
|
|
2527
|
+
/* @__PURE__ */ jsx7("div", { className: "mx-chat flex min-h-0 flex-1 flex-col", children: /* @__PURE__ */ jsxs7(ChatProvider, { thread: transcript.thread, ports: { notifier, toolLabel: friendlyToolName }, children: [
|
|
2528
|
+
/* @__PURE__ */ jsx7("div", { className: "min-h-0 flex-1 overflow-hidden", children: transcript.state.loading ? /* @__PURE__ */ jsxs7("div", { className: "flex h-full items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
|
|
2529
|
+
/* @__PURE__ */ jsx7(SpinnerIcon, { size: 15 }),
|
|
2268
2530
|
" Loading the conversation\u2026"
|
|
2269
|
-
] }) : /* @__PURE__ */
|
|
2270
|
-
transcript.state.unavailable ? /* @__PURE__ */
|
|
2271
|
-
transcript.state.truncated ? /* @__PURE__ */
|
|
2531
|
+
] }) : /* @__PURE__ */ jsxs7("div", { className: "flex h-full flex-col", children: [
|
|
2532
|
+
transcript.state.unavailable ? /* @__PURE__ */ jsx7("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,
|
|
2533
|
+
transcript.state.truncated ? /* @__PURE__ */ jsx7(
|
|
2272
2534
|
LongChatNote,
|
|
2273
2535
|
{
|
|
2274
2536
|
loading: transcript.state.loadingEarlier === true,
|
|
2275
2537
|
onEarlier: () => void transcript.loadEarlier()
|
|
2276
2538
|
}
|
|
2277
2539
|
) : null,
|
|
2278
|
-
messages.length === 0 && !live ? /* @__PURE__ */
|
|
2540
|
+
messages.length === 0 && !live ? /* @__PURE__ */ jsx7("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__ */ jsx7(ChatMessageList, { className: "min-h-0 flex-1", label: `Conversation: ${entry.title}` })
|
|
2279
2541
|
] }) }),
|
|
2280
|
-
/* @__PURE__ */
|
|
2281
|
-
limited ? /* @__PURE__ */
|
|
2282
|
-
/* @__PURE__ */
|
|
2283
|
-
/* @__PURE__ */
|
|
2542
|
+
/* @__PURE__ */ jsxs7("div", { className: "mx-auto w-full max-w-[820px] px-4 pb-4", children: [
|
|
2543
|
+
limited ? /* @__PURE__ */ jsxs7("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: [
|
|
2544
|
+
/* @__PURE__ */ jsx7(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
|
|
2545
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2284
2546
|
limited.problem,
|
|
2285
2547
|
" ",
|
|
2286
2548
|
limited.fix
|
|
2287
2549
|
] })
|
|
2288
2550
|
] }) : null,
|
|
2289
|
-
blocked ? /* @__PURE__ */
|
|
2290
|
-
|
|
2291
|
-
|
|
2551
|
+
modelRefused && !blocked ? /* @__PURE__ */ jsxs7(
|
|
2552
|
+
"div",
|
|
2553
|
+
{
|
|
2554
|
+
className: "mb-2 flex items-center gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]",
|
|
2555
|
+
role: "alert",
|
|
2556
|
+
children: [
|
|
2557
|
+
/* @__PURE__ */ jsx7(AlertIcon, { size: 15, className: "shrink-0 text-warning" }),
|
|
2558
|
+
/* @__PURE__ */ jsx7("span", { className: "min-w-0 flex-1 truncate", title: run?.error ?? void 0, children: MODEL_UNAVAILABLE_LABEL }),
|
|
2559
|
+
/* @__PURE__ */ jsx7(
|
|
2560
|
+
ModelPicker,
|
|
2561
|
+
{
|
|
2562
|
+
status: provider,
|
|
2563
|
+
value: { model: session.model, effort: session.effort ?? null },
|
|
2564
|
+
onChange: setOptions
|
|
2565
|
+
}
|
|
2566
|
+
)
|
|
2567
|
+
]
|
|
2568
|
+
}
|
|
2569
|
+
) : null,
|
|
2570
|
+
blocked ? /* @__PURE__ */ jsxs7("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: [
|
|
2571
|
+
/* @__PURE__ */ jsx7(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
|
|
2572
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2292
2573
|
blocked.problem,
|
|
2293
2574
|
" ",
|
|
2294
2575
|
blocked.fix
|
|
2295
2576
|
] })
|
|
2296
2577
|
] }) : null,
|
|
2297
|
-
/* @__PURE__ */
|
|
2298
|
-
/* @__PURE__ */
|
|
2299
|
-
/* @__PURE__ */
|
|
2300
|
-
/* @__PURE__ */
|
|
2578
|
+
/* @__PURE__ */ jsx7("div", { className: "cs-activity", role: "status", "aria-live": "polite", "data-idle": live ? void 0 : true, children: live ? /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
2579
|
+
/* @__PURE__ */ jsx7(SpinnerIcon, { size: 13 }),
|
|
2580
|
+
/* @__PURE__ */ jsx7("span", { className: "truncate", children: run?.status === "starting" ? `Starting ${PROVIDER_LABEL[session.provider]}\u2026` : transcript.activity ?? "Thinking\u2026" }),
|
|
2581
|
+
/* @__PURE__ */ jsx7("span", { className: "ml-auto shrink-0 text-[11px] opacity-70", children: "Esc to stop" })
|
|
2301
2582
|
] }) : null }),
|
|
2302
|
-
elsewhere ? /* @__PURE__ */
|
|
2303
|
-
/* @__PURE__ */
|
|
2304
|
-
/* @__PURE__ */
|
|
2583
|
+
elsewhere ? /* @__PURE__ */ jsxs7("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: [
|
|
2584
|
+
/* @__PURE__ */ jsx7(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
|
|
2585
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2305
2586
|
elsewhere.message,
|
|
2306
2587
|
" A message sent here would put a second agent on the same chat."
|
|
2307
2588
|
] })
|
|
2308
2589
|
] }) : null,
|
|
2309
|
-
session.queued.length > 0 ? /* @__PURE__ */
|
|
2310
|
-
/* @__PURE__ */
|
|
2311
|
-
/* @__PURE__ */
|
|
2590
|
+
session.queued.length > 0 ? /* @__PURE__ */ jsx7("ul", { className: "mb-2 space-y-1.5", "aria-label": "Queued messages", children: session.queued.map((text, index) => /* @__PURE__ */ jsxs7("li", { className: "cs-queued", children: [
|
|
2591
|
+
/* @__PURE__ */ jsx7("span", { className: "cs-queued__label", children: "Queued \xB7 sends when this run finishes" }),
|
|
2592
|
+
/* @__PURE__ */ jsx7("span", { className: "cs-queued__text", children: text })
|
|
2312
2593
|
] }, `${index}-${text.slice(0, 16)}`)) }) : null,
|
|
2313
|
-
/* @__PURE__ */
|
|
2594
|
+
/* @__PURE__ */ jsx7(
|
|
2314
2595
|
ChatComposer,
|
|
2315
2596
|
{
|
|
2316
2597
|
placeholder: `Message ${PROVIDER_LABEL[session.provider]}\u2026`,
|
|
@@ -2321,14 +2602,14 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2321
2602
|
] })
|
|
2322
2603
|
] }) })
|
|
2323
2604
|
] }),
|
|
2324
|
-
changesOpen ? /* @__PURE__ */
|
|
2605
|
+
changesOpen ? /* @__PURE__ */ jsx7(ChangesPanel, { files, cwd: session.cwd, truncated: transcript.state.truncated, onClose: () => setChangesOpen(false) }) : null
|
|
2325
2606
|
] });
|
|
2326
2607
|
}
|
|
2327
2608
|
function usePreviewThread(id, onSend) {
|
|
2328
|
-
const ref =
|
|
2329
|
-
const send =
|
|
2609
|
+
const ref = useRef3({ messages: [], listeners: /* @__PURE__ */ new Set() });
|
|
2610
|
+
const send = useRef3(onSend);
|
|
2330
2611
|
send.current = onSend;
|
|
2331
|
-
const thread =
|
|
2612
|
+
const thread = useMemo4(
|
|
2332
2613
|
() => createExternalThreadSource2({
|
|
2333
2614
|
getSnapshot: () => ({ messages: ref.current.messages, status: "idle", conversationId: id }),
|
|
2334
2615
|
subscribe: (listener) => {
|
|
@@ -2353,13 +2634,13 @@ function DiscoveredView(props) {
|
|
|
2353
2634
|
const state = useCodingSessionsState();
|
|
2354
2635
|
const show = useContext3(ToastContext);
|
|
2355
2636
|
const now = useMinuteClock();
|
|
2356
|
-
const [preview, setPreview] =
|
|
2357
|
-
const [busy, setBusy] =
|
|
2358
|
-
const [error, setError] =
|
|
2359
|
-
const [confirming, setConfirming] =
|
|
2360
|
-
const [renaming, setRenaming] =
|
|
2361
|
-
const [maxBytes, setMaxBytes] =
|
|
2362
|
-
const [readingEarlier, setReadingEarlier] =
|
|
2637
|
+
const [preview, setPreview] = useState6({ loading: true, messages: [], unavailable: null, truncated: false });
|
|
2638
|
+
const [busy, setBusy] = useState6(false);
|
|
2639
|
+
const [error, setError] = useState6(null);
|
|
2640
|
+
const [confirming, setConfirming] = useState6(false);
|
|
2641
|
+
const [renaming, setRenaming] = useState6(false);
|
|
2642
|
+
const [maxBytes, setMaxBytes] = useState6(void 0);
|
|
2643
|
+
const [readingEarlier, setReadingEarlier] = useState6(false);
|
|
2363
2644
|
const elsewhere = useLiveElsewhere(props.provider, props.id, props.session?.activeElsewhere ?? null);
|
|
2364
2645
|
const files = useChangedFiles(preview.messages);
|
|
2365
2646
|
const d = props.session;
|
|
@@ -2369,7 +2650,7 @@ function DiscoveredView(props) {
|
|
|
2369
2650
|
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."
|
|
2370
2651
|
)
|
|
2371
2652
|
);
|
|
2372
|
-
|
|
2653
|
+
useEffect4(() => {
|
|
2373
2654
|
let cancelled = false;
|
|
2374
2655
|
const read = (first) => client.readPreview(props.provider, props.id, maxBytes).then((next) => {
|
|
2375
2656
|
if (cancelled) return;
|
|
@@ -2408,26 +2689,26 @@ function DiscoveredView(props) {
|
|
|
2408
2689
|
setBusy(false);
|
|
2409
2690
|
}
|
|
2410
2691
|
};
|
|
2411
|
-
return /* @__PURE__ */
|
|
2412
|
-
/* @__PURE__ */
|
|
2413
|
-
/* @__PURE__ */
|
|
2414
|
-
/* @__PURE__ */
|
|
2415
|
-
/* @__PURE__ */
|
|
2416
|
-
/* @__PURE__ */
|
|
2417
|
-
/* @__PURE__ */
|
|
2418
|
-
/* @__PURE__ */
|
|
2419
|
-
d?.cwd ? /* @__PURE__ */
|
|
2420
|
-
/* @__PURE__ */
|
|
2421
|
-
/* @__PURE__ */
|
|
2422
|
-
/* @__PURE__ */
|
|
2692
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1", children: [
|
|
2693
|
+
/* @__PURE__ */ jsxs7("section", { className: "flex min-w-0 flex-1 flex-col", "aria-label": entry.title, children: [
|
|
2694
|
+
/* @__PURE__ */ jsxs7("header", { className: "flex flex-wrap items-center gap-2 border-b border-border px-5 pt-2.5 pb-2.5", children: [
|
|
2695
|
+
/* @__PURE__ */ jsx7(ProviderMark, { provider: props.provider, size: 22 }),
|
|
2696
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
|
|
2697
|
+
/* @__PURE__ */ jsx7(HeaderTitle, { entry, renaming, setRenaming }),
|
|
2698
|
+
/* @__PURE__ */ jsxs7("p", { className: "flex items-center gap-1.5 truncate text-[12px] leading-4 text-muted-foreground", children: [
|
|
2699
|
+
/* @__PURE__ */ jsx7("span", { children: PROVIDER_LABEL[props.provider] }),
|
|
2700
|
+
d?.cwd ? /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
2701
|
+
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
2702
|
+
/* @__PURE__ */ jsx7(FolderIcon, { size: 12 }),
|
|
2703
|
+
/* @__PURE__ */ jsx7("span", { className: "truncate", title: d.cwd, children: prettyPath2(d.cwd) })
|
|
2423
2704
|
] }) : null,
|
|
2424
|
-
d ? /* @__PURE__ */
|
|
2705
|
+
d ? /* @__PURE__ */ jsxs7("span", { children: [
|
|
2425
2706
|
"\xB7 last active ",
|
|
2426
2707
|
relativeTime(d.updatedAt, now)
|
|
2427
2708
|
] }) : null
|
|
2428
2709
|
] })
|
|
2429
2710
|
] }),
|
|
2430
|
-
files.length > 0 ? /* @__PURE__ */
|
|
2711
|
+
files.length > 0 ? /* @__PURE__ */ jsxs7(
|
|
2431
2712
|
"button",
|
|
2432
2713
|
{
|
|
2433
2714
|
type: "button",
|
|
@@ -2436,13 +2717,13 @@ function DiscoveredView(props) {
|
|
|
2436
2717
|
"aria-pressed": props.changesOpen,
|
|
2437
2718
|
title: "Files this chat changed",
|
|
2438
2719
|
children: [
|
|
2439
|
-
/* @__PURE__ */
|
|
2720
|
+
/* @__PURE__ */ jsx7(FileIcon, { size: 13 }),
|
|
2440
2721
|
`${files.length} ${files.length === 1 ? "file" : "files"} changed`
|
|
2441
2722
|
]
|
|
2442
2723
|
}
|
|
2443
2724
|
) : null,
|
|
2444
|
-
d?.cwd ? /* @__PURE__ */
|
|
2445
|
-
|
|
2725
|
+
d?.cwd ? /* @__PURE__ */ jsxs7(
|
|
2726
|
+
Button3,
|
|
2446
2727
|
{
|
|
2447
2728
|
size: "sm",
|
|
2448
2729
|
variant: elsewhere ? "outline" : "default",
|
|
@@ -2451,44 +2732,44 @@ function DiscoveredView(props) {
|
|
|
2451
2732
|
className: "gap-1.5",
|
|
2452
2733
|
title: elsewhere ? elsewhere.message : void 0,
|
|
2453
2734
|
children: [
|
|
2454
|
-
busy ? /* @__PURE__ */
|
|
2735
|
+
busy ? /* @__PURE__ */ jsx7(SpinnerIcon, { size: 13 }) : elsewhere ? /* @__PURE__ */ jsx7(AlertIcon, { size: 14, className: "text-warning" }) : /* @__PURE__ */ jsx7(HandoffIcon, { size: 14 }),
|
|
2455
2736
|
elsewhere ? "Take over anyway\u2026" : "Take over"
|
|
2456
2737
|
]
|
|
2457
2738
|
}
|
|
2458
2739
|
) : null,
|
|
2459
|
-
d ? /* @__PURE__ */
|
|
2740
|
+
d ? /* @__PURE__ */ jsx7(HeaderMenu, { entry, onRename: () => setRenaming(true) }) : null
|
|
2460
2741
|
] }),
|
|
2461
|
-
elsewhere ? /* @__PURE__ */
|
|
2462
|
-
/* @__PURE__ */
|
|
2463
|
-
/* @__PURE__ */
|
|
2464
|
-
/* @__PURE__ */
|
|
2742
|
+
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: [
|
|
2743
|
+
/* @__PURE__ */ jsx7(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
|
|
2744
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2745
|
+
/* @__PURE__ */ jsx7("span", { className: "font-medium", children: elsewhere.message }),
|
|
2465
2746
|
" 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."
|
|
2466
2747
|
] })
|
|
2467
2748
|
] }) : null,
|
|
2468
|
-
/* @__PURE__ */
|
|
2469
|
-
/* @__PURE__ */
|
|
2470
|
-
/* @__PURE__ */
|
|
2749
|
+
/* @__PURE__ */ jsx7(Dialog, { open: confirming, onOpenChange: setConfirming, children: /* @__PURE__ */ jsxs7(DialogContent, { className: "max-w-[460px]", children: [
|
|
2750
|
+
/* @__PURE__ */ jsxs7(DialogHeader, { children: [
|
|
2751
|
+
/* @__PURE__ */ jsxs7(DialogTitle, { children: [
|
|
2471
2752
|
"This chat is running right now in ",
|
|
2472
2753
|
PROVIDER_LABEL[props.provider]
|
|
2473
2754
|
] }),
|
|
2474
|
-
/* @__PURE__ */
|
|
2755
|
+
/* @__PURE__ */ jsxs7(DialogDescription, { children: [
|
|
2475
2756
|
elsewhere?.message,
|
|
2476
2757
|
" If you take it over, two agents will work in the same conversation at once and may overwrite each other's changes."
|
|
2477
2758
|
] })
|
|
2478
2759
|
] }),
|
|
2479
|
-
/* @__PURE__ */
|
|
2480
|
-
/* @__PURE__ */
|
|
2481
|
-
/* @__PURE__ */
|
|
2760
|
+
/* @__PURE__ */ jsxs7(DialogFooter, { children: [
|
|
2761
|
+
/* @__PURE__ */ jsx7(Button3, { variant: "ghost", onClick: () => setConfirming(false), children: "Cancel" }),
|
|
2762
|
+
/* @__PURE__ */ jsx7(Button3, { variant: "destructive", onClick: () => void takeover(), children: "Take over anyway" })
|
|
2482
2763
|
] })
|
|
2483
2764
|
] }) }),
|
|
2484
|
-
error ? /* @__PURE__ */
|
|
2485
|
-
d && !d.cwd ? /* @__PURE__ */
|
|
2486
|
-
/* @__PURE__ */
|
|
2487
|
-
preview.loading ? /* @__PURE__ */
|
|
2488
|
-
/* @__PURE__ */
|
|
2765
|
+
error ? /* @__PURE__ */ jsx7("p", { className: "border-b border-destructive/30 bg-destructive/10 px-5 py-2 text-[13px] text-destructive", children: error }) : null,
|
|
2766
|
+
d && !d.cwd ? /* @__PURE__ */ jsx7("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,
|
|
2767
|
+
/* @__PURE__ */ jsxs7("div", { className: "mx-chat flex min-h-0 flex-1 flex-col", children: [
|
|
2768
|
+
preview.loading ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
|
|
2769
|
+
/* @__PURE__ */ jsx7(SpinnerIcon, { size: 15 }),
|
|
2489
2770
|
" Reading this chat\u2026"
|
|
2490
|
-
] }) : preview.unavailable ? /* @__PURE__ */
|
|
2491
|
-
preview.truncated ? /* @__PURE__ */
|
|
2771
|
+
] }) : preview.unavailable ? /* @__PURE__ */ jsx7("div", { className: "flex flex-1 items-center justify-center px-6 text-center text-[13px] text-muted-foreground", children: preview.unavailable }) : /* @__PURE__ */ jsxs7(ChatProvider, { thread, ports: { notifier, toolLabel: friendlyToolName }, children: [
|
|
2772
|
+
preview.truncated ? /* @__PURE__ */ jsx7(
|
|
2492
2773
|
LongChatNote,
|
|
2493
2774
|
{
|
|
2494
2775
|
loading: readingEarlier,
|
|
@@ -2498,14 +2779,14 @@ function DiscoveredView(props) {
|
|
|
2498
2779
|
}
|
|
2499
2780
|
}
|
|
2500
2781
|
) : null,
|
|
2501
|
-
/* @__PURE__ */
|
|
2782
|
+
/* @__PURE__ */ jsx7(ChatMessageList, { className: "min-h-0 flex-1", label: "Chat preview" })
|
|
2502
2783
|
] }),
|
|
2503
|
-
d?.cwd ? /* @__PURE__ */
|
|
2784
|
+
d?.cwd ? /* @__PURE__ */ jsxs7("div", { className: "border-t border-border bg-muted/30 px-5 py-3 text-center text-[13px] text-muted-foreground", children: [
|
|
2504
2785
|
"This chat was started in ",
|
|
2505
2786
|
PROVIDER_LABEL[props.provider],
|
|
2506
2787
|
".",
|
|
2507
2788
|
" ",
|
|
2508
|
-
/* @__PURE__ */
|
|
2789
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: "font-medium text-foreground underline-offset-4 hover:underline", onClick: requestTakeover, children: "Take it over" }),
|
|
2509
2790
|
" ",
|
|
2510
2791
|
"to continue it here \u2014 it stays in your ",
|
|
2511
2792
|
PROVIDER_LABEL[props.provider],
|
|
@@ -2513,70 +2794,73 @@ function DiscoveredView(props) {
|
|
|
2513
2794
|
] }) : null
|
|
2514
2795
|
] })
|
|
2515
2796
|
] }),
|
|
2516
|
-
props.changesOpen && files.length > 0 ? /* @__PURE__ */
|
|
2797
|
+
props.changesOpen && files.length > 0 ? /* @__PURE__ */ jsx7(ChangesPanel, { files, cwd: d?.cwd ?? null, truncated: preview.truncated, onClose: () => props.setChangesOpen(false) }) : null
|
|
2517
2798
|
] });
|
|
2518
2799
|
}
|
|
2519
2800
|
function ProviderCard(props) {
|
|
2520
2801
|
const ready = props.status.ready;
|
|
2521
|
-
return /* @__PURE__ */
|
|
2802
|
+
return /* @__PURE__ */ jsxs7(
|
|
2522
2803
|
"button",
|
|
2523
2804
|
{
|
|
2524
2805
|
type: "button",
|
|
2525
2806
|
onClick: props.onSelect,
|
|
2526
2807
|
"aria-pressed": props.selected,
|
|
2527
|
-
className:
|
|
2808
|
+
className: cn5(
|
|
2528
2809
|
"flex flex-1 flex-col gap-1.5 rounded-xl border px-3.5 py-3 text-left transition-colors",
|
|
2529
2810
|
props.selected ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-border hover:bg-accent/50"
|
|
2530
2811
|
),
|
|
2531
2812
|
children: [
|
|
2532
|
-
/* @__PURE__ */
|
|
2533
|
-
/* @__PURE__ */
|
|
2534
|
-
/* @__PURE__ */
|
|
2813
|
+
/* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-2", children: [
|
|
2814
|
+
/* @__PURE__ */ jsx7(ProviderMark, { provider: props.status.provider, size: 18 }),
|
|
2815
|
+
/* @__PURE__ */ jsx7("span", { className: "text-[13.5px] font-semibold", children: props.status.label })
|
|
2535
2816
|
] }),
|
|
2536
|
-
ready ? /* @__PURE__ */
|
|
2537
|
-
/* @__PURE__ */
|
|
2817
|
+
ready ? /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-1 text-[12px] text-success", children: [
|
|
2818
|
+
/* @__PURE__ */ jsx7(CheckIcon, { size: 13 }),
|
|
2538
2819
|
props.status.billing === "subscription" ? `Signed in${props.status.plan ? ` \xB7 ${props.status.plan} plan` : ""}` : "Signed in with an API key (billed per use)"
|
|
2539
|
-
] }) : /* @__PURE__ */
|
|
2540
|
-
/* @__PURE__ */
|
|
2820
|
+
] }) : /* @__PURE__ */ jsxs7("span", { className: "flex items-start gap-1 text-[12px] leading-4 text-warning", children: [
|
|
2821
|
+
/* @__PURE__ */ jsx7(AlertIcon, { size: 13, className: "mt-px shrink-0" }),
|
|
2541
2822
|
props.status.problem
|
|
2542
2823
|
] }),
|
|
2543
|
-
props.status.quota.filter((w) => w.usedPercent !== null).length > 0 ? /* @__PURE__ */
|
|
2824
|
+
props.status.quota.filter((w) => w.usedPercent !== null).length > 0 ? /* @__PURE__ */ jsx7("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
|
|
2544
2825
|
]
|
|
2545
2826
|
}
|
|
2546
2827
|
);
|
|
2547
2828
|
}
|
|
2548
2829
|
function FieldError({ id, children }) {
|
|
2549
|
-
return /* @__PURE__ */
|
|
2550
|
-
/* @__PURE__ */
|
|
2551
|
-
/* @__PURE__ */
|
|
2830
|
+
return /* @__PURE__ */ jsxs7("p", { id, role: "alert", className: "flex items-start gap-1.5 text-[12.5px] leading-5 text-destructive", children: [
|
|
2831
|
+
/* @__PURE__ */ jsx7(AlertIcon, { size: 14, className: "mt-0.5 shrink-0" }),
|
|
2832
|
+
/* @__PURE__ */ jsx7("span", { children })
|
|
2552
2833
|
] });
|
|
2553
2834
|
}
|
|
2554
2835
|
function NewSessionDialog(props) {
|
|
2555
2836
|
const client = useCodingSessionsClient();
|
|
2556
2837
|
const state = useCodingSessionsState();
|
|
2557
2838
|
const now = useMinuteClock();
|
|
2558
|
-
const [provider, setProvider] =
|
|
2559
|
-
const [folder, setFolder] =
|
|
2560
|
-
const [choice, setChoice] =
|
|
2561
|
-
const [prompt, setPrompt] =
|
|
2562
|
-
const [errors, setErrors] =
|
|
2563
|
-
const [problem, setProblem] =
|
|
2564
|
-
const [starting, setStarting] =
|
|
2565
|
-
const [creating, setCreating] =
|
|
2566
|
-
const
|
|
2567
|
-
const
|
|
2568
|
-
const
|
|
2569
|
-
|
|
2839
|
+
const [provider, setProvider] = useState6("claude");
|
|
2840
|
+
const [folder, setFolder] = useState6("");
|
|
2841
|
+
const [choice, setChoice] = useState6({ model: null, effort: null });
|
|
2842
|
+
const [prompt, setPrompt] = useState6("");
|
|
2843
|
+
const [errors, setErrors] = useState6({});
|
|
2844
|
+
const [problem, setProblem] = useState6(null);
|
|
2845
|
+
const [starting, setStarting] = useState6(false);
|
|
2846
|
+
const [creating, setCreating] = useState6(false);
|
|
2847
|
+
const [agent, setAgent] = useState6(null);
|
|
2848
|
+
const [agentDetails, setAgentDetails] = useState6(null);
|
|
2849
|
+
const [agentMissing, setAgentMissing] = useState6(null);
|
|
2850
|
+
const promptRef = useRef3(null);
|
|
2851
|
+
const folderRef = useRef3(null);
|
|
2852
|
+
const agentRef = useRef3(null);
|
|
2853
|
+
useEffect4(() => {
|
|
2570
2854
|
if (!props.open) return;
|
|
2571
2855
|
setProblem(null);
|
|
2572
2856
|
setErrors({});
|
|
2573
2857
|
void client.refreshProviders();
|
|
2574
2858
|
void client.refreshFolders();
|
|
2575
2859
|
}, [props.open, client]);
|
|
2576
|
-
|
|
2860
|
+
useEffect4(() => {
|
|
2577
2861
|
if (!folder && state.folders.data[0]?.exists) setFolder(state.folders.data[0].path);
|
|
2578
2862
|
}, [state.folders.data, folder]);
|
|
2579
|
-
|
|
2863
|
+
useEffect4(() => {
|
|
2580
2864
|
const ready = state.providers.data.filter((p) => p.ready);
|
|
2581
2865
|
const current = state.providers.data.find((p) => p.provider === provider);
|
|
2582
2866
|
if (current && !current.ready && ready[0]) setProvider(ready[0].provider);
|
|
@@ -2602,9 +2886,22 @@ function NewSessionDialog(props) {
|
|
|
2602
2886
|
focusField(first);
|
|
2603
2887
|
return;
|
|
2604
2888
|
}
|
|
2889
|
+
const missing = missingRequiredVariable(agentDetails, agent);
|
|
2890
|
+
setAgentMissing(missing);
|
|
2891
|
+
if (missing) {
|
|
2892
|
+
document.getElementById(`cs-agent-var-${missing}`)?.focus();
|
|
2893
|
+
return;
|
|
2894
|
+
}
|
|
2605
2895
|
setStarting(true);
|
|
2606
2896
|
try {
|
|
2607
|
-
const result = await client.start({
|
|
2897
|
+
const result = await client.start({
|
|
2898
|
+
provider,
|
|
2899
|
+
cwd: folder.trim(),
|
|
2900
|
+
prompt,
|
|
2901
|
+
model: choice.model,
|
|
2902
|
+
effort: choice.effort,
|
|
2903
|
+
...agent ? { agent } : {}
|
|
2904
|
+
});
|
|
2608
2905
|
setPrompt("");
|
|
2609
2906
|
props.onStarted(result.session.id);
|
|
2610
2907
|
} catch (error) {
|
|
@@ -2640,16 +2937,16 @@ function NewSessionDialog(props) {
|
|
|
2640
2937
|
if (field === "folder") delete next.createFolder;
|
|
2641
2938
|
return next;
|
|
2642
2939
|
});
|
|
2643
|
-
return /* @__PURE__ */
|
|
2644
|
-
/* @__PURE__ */
|
|
2645
|
-
/* @__PURE__ */
|
|
2646
|
-
/* @__PURE__ */
|
|
2940
|
+
return /* @__PURE__ */ jsx7(Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ jsxs7(DialogContent, { className: "max-w-[560px]", children: [
|
|
2941
|
+
/* @__PURE__ */ jsxs7(DialogHeader, { children: [
|
|
2942
|
+
/* @__PURE__ */ jsx7(DialogTitle, { children: "New coding session" }),
|
|
2943
|
+
/* @__PURE__ */ jsxs7(DialogDescription, { children: [
|
|
2647
2944
|
"Runs on your own ",
|
|
2648
2945
|
provider === "claude" ? "Claude" : "ChatGPT",
|
|
2649
2946
|
" sign-in, in a folder on this computer."
|
|
2650
2947
|
] })
|
|
2651
2948
|
] }),
|
|
2652
|
-
/* @__PURE__ */
|
|
2949
|
+
/* @__PURE__ */ jsxs7(
|
|
2653
2950
|
"form",
|
|
2654
2951
|
{
|
|
2655
2952
|
noValidate: true,
|
|
@@ -2659,13 +2956,13 @@ function NewSessionDialog(props) {
|
|
|
2659
2956
|
},
|
|
2660
2957
|
className: "flex min-h-0 flex-col",
|
|
2661
2958
|
children: [
|
|
2662
|
-
/* @__PURE__ */
|
|
2663
|
-
/* @__PURE__ */
|
|
2664
|
-
/* @__PURE__ */
|
|
2665
|
-
state.providers.loading && state.providers.loadedAt === null ? /* @__PURE__ */
|
|
2666
|
-
/* @__PURE__ */
|
|
2667
|
-
/* @__PURE__ */
|
|
2668
|
-
] }) : state.providers.error ? /* @__PURE__ */
|
|
2959
|
+
/* @__PURE__ */ jsxs7("div", { className: "cs-dialog-body space-y-5 py-1 pr-1", children: [
|
|
2960
|
+
/* @__PURE__ */ jsxs7("fieldset", { className: "space-y-2", ref: agentRef, children: [
|
|
2961
|
+
/* @__PURE__ */ jsx7("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Agent" }),
|
|
2962
|
+
state.providers.loading && state.providers.loadedAt === null ? /* @__PURE__ */ jsxs7("div", { className: "flex gap-2", children: [
|
|
2963
|
+
/* @__PURE__ */ jsx7("div", { className: "cs-skeleton h-[68px] flex-1 rounded-xl" }),
|
|
2964
|
+
/* @__PURE__ */ jsx7("div", { className: "cs-skeleton h-[68px] flex-1 rounded-xl" })
|
|
2965
|
+
] }) : state.providers.error ? /* @__PURE__ */ jsx7("p", { className: "text-[12.5px] text-destructive", children: state.providers.error }) : /* @__PURE__ */ jsx7("div", { className: "flex gap-2", children: state.providers.data.map((p) => /* @__PURE__ */ jsx7(
|
|
2669
2966
|
ProviderCard,
|
|
2670
2967
|
{
|
|
2671
2968
|
status: p,
|
|
@@ -2678,14 +2975,31 @@ function NewSessionDialog(props) {
|
|
|
2678
2975
|
},
|
|
2679
2976
|
p.provider
|
|
2680
2977
|
)) }),
|
|
2681
|
-
errors.agent ? /* @__PURE__ */
|
|
2978
|
+
errors.agent ? /* @__PURE__ */ jsx7(FieldError, { id: "cs-err-agent", children: errors.agent }) : selected && !selected.ready && selected.fix ? /* @__PURE__ */ jsxs7("p", { className: "text-[12px] leading-4 text-muted-foreground", children: [
|
|
2682
2979
|
selected.fix,
|
|
2683
2980
|
selected.installed && selected.loggedIn ? " You can still try \u2014 the run will say if it's still blocked." : ""
|
|
2684
2981
|
] }) : null
|
|
2685
2982
|
] }),
|
|
2686
|
-
/* @__PURE__ */
|
|
2687
|
-
/* @__PURE__ */
|
|
2688
|
-
|
|
2983
|
+
/* @__PURE__ */ jsxs7("fieldset", { className: "space-y-2", children: [
|
|
2984
|
+
/* @__PURE__ */ jsx7("legend", { className: "mb-2 text-[12.5px] font-medium", children: "AI Matrx agent" }),
|
|
2985
|
+
/* @__PURE__ */ jsx7(
|
|
2986
|
+
AgentField,
|
|
2987
|
+
{
|
|
2988
|
+
transport: client.transport,
|
|
2989
|
+
open: props.open,
|
|
2990
|
+
value: agent,
|
|
2991
|
+
onChange: (next) => {
|
|
2992
|
+
setAgent(next);
|
|
2993
|
+
setAgentMissing(null);
|
|
2994
|
+
},
|
|
2995
|
+
missing: agentMissing,
|
|
2996
|
+
onDetails: setAgentDetails
|
|
2997
|
+
}
|
|
2998
|
+
)
|
|
2999
|
+
] }),
|
|
3000
|
+
/* @__PURE__ */ jsxs7("fieldset", { className: "space-y-2", children: [
|
|
3001
|
+
/* @__PURE__ */ jsx7("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Folder" }),
|
|
3002
|
+
state.folders.data.length > 0 ? /* @__PURE__ */ jsx7("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__ */ jsxs7(
|
|
2689
3003
|
"button",
|
|
2690
3004
|
{
|
|
2691
3005
|
type: "button",
|
|
@@ -2695,21 +3009,21 @@ function NewSessionDialog(props) {
|
|
|
2695
3009
|
},
|
|
2696
3010
|
disabled: !f.exists,
|
|
2697
3011
|
title: f.exists ? f.path : `${f.path} no longer exists`,
|
|
2698
|
-
className:
|
|
3012
|
+
className: cn5(
|
|
2699
3013
|
"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[12.5px]",
|
|
2700
3014
|
folder === f.path ? "bg-accent text-accent-foreground" : "hover:bg-accent/50",
|
|
2701
3015
|
!f.exists && "opacity-50"
|
|
2702
3016
|
),
|
|
2703
3017
|
children: [
|
|
2704
|
-
/* @__PURE__ */
|
|
2705
|
-
/* @__PURE__ */
|
|
2706
|
-
/* @__PURE__ */
|
|
3018
|
+
/* @__PURE__ */ jsx7(FolderIcon, { size: 14, className: "shrink-0 text-muted-foreground" }),
|
|
3019
|
+
/* @__PURE__ */ jsx7("span", { className: "min-w-0 flex-1 truncate", children: prettyPath2(f.path) }),
|
|
3020
|
+
/* @__PURE__ */ jsx7("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: f.exists ? relativeTime(f.lastUsedAt, now) : "missing" })
|
|
2707
3021
|
]
|
|
2708
3022
|
},
|
|
2709
3023
|
f.path
|
|
2710
|
-
)) }) : state.folders.loading ? /* @__PURE__ */
|
|
2711
|
-
/* @__PURE__ */
|
|
2712
|
-
|
|
3024
|
+
)) }) : state.folders.loading ? /* @__PURE__ */ jsx7("div", { className: "cs-skeleton h-10 rounded-lg" }) : null,
|
|
3025
|
+
/* @__PURE__ */ jsx7(
|
|
3026
|
+
Input2,
|
|
2713
3027
|
{
|
|
2714
3028
|
ref: folderRef,
|
|
2715
3029
|
value: folder,
|
|
@@ -2724,18 +3038,18 @@ function NewSessionDialog(props) {
|
|
|
2724
3038
|
spellCheck: false
|
|
2725
3039
|
}
|
|
2726
3040
|
),
|
|
2727
|
-
errors.folder ? /* @__PURE__ */
|
|
2728
|
-
/* @__PURE__ */
|
|
2729
|
-
errors.createFolder ? /* @__PURE__ */
|
|
2730
|
-
creating ? /* @__PURE__ */
|
|
3041
|
+
errors.folder ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1", children: [
|
|
3042
|
+
/* @__PURE__ */ jsx7(FieldError, { id: "cs-err-folder", children: errors.folder }),
|
|
3043
|
+
errors.createFolder ? /* @__PURE__ */ jsxs7(Button3, { type: "button", size: "sm", variant: "outline", onClick: () => void createFolder(), disabled: creating, className: "gap-1.5", children: [
|
|
3044
|
+
creating ? /* @__PURE__ */ jsx7(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ jsx7(FolderIcon, { size: 13 }),
|
|
2731
3045
|
"Create this folder"
|
|
2732
3046
|
] }) : null
|
|
2733
3047
|
] }) : null
|
|
2734
3048
|
] }),
|
|
2735
|
-
/* @__PURE__ */
|
|
2736
|
-
/* @__PURE__ */
|
|
2737
|
-
/* @__PURE__ */
|
|
2738
|
-
|
|
3049
|
+
/* @__PURE__ */ jsxs7("fieldset", { className: "space-y-2", children: [
|
|
3050
|
+
/* @__PURE__ */ jsx7("legend", { className: "mb-2 text-[12.5px] font-medium", children: "What should it do?" }),
|
|
3051
|
+
/* @__PURE__ */ jsx7(
|
|
3052
|
+
Textarea2,
|
|
2739
3053
|
{
|
|
2740
3054
|
ref: promptRef,
|
|
2741
3055
|
value: prompt,
|
|
@@ -2756,25 +3070,25 @@ function NewSessionDialog(props) {
|
|
|
2756
3070
|
"aria-describedby": errors.prompt ? "cs-err-prompt" : void 0
|
|
2757
3071
|
}
|
|
2758
3072
|
),
|
|
2759
|
-
errors.prompt ? /* @__PURE__ */
|
|
3073
|
+
errors.prompt ? /* @__PURE__ */ jsx7(FieldError, { id: "cs-err-prompt", children: errors.prompt }) : null
|
|
2760
3074
|
] }),
|
|
2761
|
-
/* @__PURE__ */
|
|
2762
|
-
/* @__PURE__ */
|
|
2763
|
-
/* @__PURE__ */
|
|
2764
|
-
/* @__PURE__ */
|
|
3075
|
+
/* @__PURE__ */ jsxs7("fieldset", { className: "space-y-2", children: [
|
|
3076
|
+
/* @__PURE__ */ jsx7("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Model and thinking effort" }),
|
|
3077
|
+
/* @__PURE__ */ jsx7(ModelPicker, { status: selected, value: choice, onChange: setChoice, appearance: "field" }),
|
|
3078
|
+
/* @__PURE__ */ jsxs7("p", { className: "text-[11.5px] leading-4 text-muted-foreground", children: [
|
|
2765
3079
|
"Default is ",
|
|
2766
3080
|
defaultModelWords(selected),
|
|
2767
3081
|
". You can change it later from the chat's header."
|
|
2768
3082
|
] })
|
|
2769
3083
|
] }),
|
|
2770
|
-
problem ? /* @__PURE__ */
|
|
3084
|
+
problem ? /* @__PURE__ */ jsx7(FieldError, { id: "cs-err-start", children: problem }) : null
|
|
2771
3085
|
] }),
|
|
2772
|
-
/* @__PURE__ */
|
|
2773
|
-
/* @__PURE__ */
|
|
2774
|
-
/* @__PURE__ */
|
|
2775
|
-
starting ? /* @__PURE__ */
|
|
3086
|
+
/* @__PURE__ */ jsxs7(DialogFooter, { className: "pt-4", children: [
|
|
3087
|
+
/* @__PURE__ */ jsx7(Button3, { type: "button", variant: "ghost", onClick: () => props.onOpenChange(false), children: "Cancel" }),
|
|
3088
|
+
/* @__PURE__ */ jsxs7(Button3, { type: "submit", disabled: starting, className: "gap-1.5", children: [
|
|
3089
|
+
starting ? /* @__PURE__ */ jsx7(SpinnerIcon, { size: 14 }) : null,
|
|
2776
3090
|
starting ? "Starting\u2026" : "Start session",
|
|
2777
|
-
!starting ? /* @__PURE__ */
|
|
3091
|
+
!starting ? /* @__PURE__ */ jsx7("kbd", { className: "cs-kbd", children: "\u2318\u21B5" }) : null
|
|
2778
3092
|
] })
|
|
2779
3093
|
] })
|
|
2780
3094
|
]
|
|
@@ -2784,47 +3098,58 @@ function NewSessionDialog(props) {
|
|
|
2784
3098
|
}
|
|
2785
3099
|
function Home({ onNew }) {
|
|
2786
3100
|
const state = useCodingSessionsState();
|
|
2787
|
-
return /* @__PURE__ */
|
|
2788
|
-
/* @__PURE__ */
|
|
2789
|
-
/* @__PURE__ */
|
|
2790
|
-
/* @__PURE__ */
|
|
2791
|
-
/* @__PURE__ */
|
|
2792
|
-
/* @__PURE__ */
|
|
3101
|
+
return /* @__PURE__ */ jsx7("section", { className: "flex flex-1 items-center justify-center px-6", children: /* @__PURE__ */ jsxs7("div", { className: "w-full max-w-[460px] text-center", children: [
|
|
3102
|
+
/* @__PURE__ */ jsx7("span", { className: "mx-auto mb-4 flex h-11 w-11 items-center justify-center rounded-2xl bg-primary/10 text-primary", children: /* @__PURE__ */ jsx7(ChatBubbleIcon, { size: 22 }) }),
|
|
3103
|
+
/* @__PURE__ */ jsx7("h1", { className: "text-[15px] font-semibold leading-5 tracking-[-0.01em]", children: "Drive Claude Code and Codex from here" }),
|
|
3104
|
+
/* @__PURE__ */ jsx7("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." }),
|
|
3105
|
+
/* @__PURE__ */ jsxs7(Button3, { className: "mt-5 gap-1.5", onClick: onNew, children: [
|
|
3106
|
+
/* @__PURE__ */ jsx7(PlusIcon, { size: 15 }),
|
|
2793
3107
|
"New session"
|
|
2794
3108
|
] }),
|
|
2795
|
-
/* @__PURE__ */
|
|
2796
|
-
/* @__PURE__ */
|
|
3109
|
+
/* @__PURE__ */ jsxs7("p", { className: "mt-3 text-[12px] text-muted-foreground", children: [
|
|
3110
|
+
/* @__PURE__ */ jsx7("kbd", { className: "cs-kbd", children: "\u2325\u2318N" }),
|
|
2797
3111
|
" new session \xB7 ",
|
|
2798
|
-
/* @__PURE__ */
|
|
3112
|
+
/* @__PURE__ */ jsx7("kbd", { className: "cs-kbd", children: "\u2318K" }),
|
|
2799
3113
|
" search your chats \xB7",
|
|
2800
3114
|
" ",
|
|
2801
|
-
/* @__PURE__ */
|
|
3115
|
+
/* @__PURE__ */ jsx7("kbd", { className: "cs-kbd", children: "\u2318/" }),
|
|
2802
3116
|
" all shortcuts"
|
|
2803
3117
|
] }),
|
|
2804
|
-
/* @__PURE__ */
|
|
2805
|
-
/* @__PURE__ */
|
|
2806
|
-
/* @__PURE__ */
|
|
2807
|
-
/* @__PURE__ */
|
|
2808
|
-
p.ready ? /* @__PURE__ */
|
|
3118
|
+
/* @__PURE__ */ jsx7("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__ */ jsxs7("div", { className: "flex min-w-[220px] items-start gap-2.5 rounded-lg border border-border px-3 py-2.5", children: [
|
|
3119
|
+
/* @__PURE__ */ jsx7(ProviderMark, { provider: p.provider, size: 16 }),
|
|
3120
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1 text-[12.5px] leading-5", children: [
|
|
3121
|
+
/* @__PURE__ */ jsx7("span", { className: "font-medium", children: p.label }),
|
|
3122
|
+
p.ready ? /* @__PURE__ */ jsxs7("span", { className: "text-muted-foreground", children: [
|
|
2809
3123
|
" ",
|
|
2810
3124
|
"\u2014 ready",
|
|
2811
3125
|
p.plan ? ` on your ${p.plan} plan` : "",
|
|
2812
|
-
p.billing === "api" ? " (API key, billed per use)" : ""
|
|
2813
|
-
|
|
2814
|
-
|
|
3126
|
+
p.billing === "api" ? " (API key, billed per use)" : ""
|
|
3127
|
+
] }) : null,
|
|
3128
|
+
p.installed && p.version ? /* @__PURE__ */ jsxs7(
|
|
3129
|
+
"span",
|
|
3130
|
+
{
|
|
3131
|
+
className: "block text-[11.5px] text-muted-foreground",
|
|
3132
|
+
title: newerWords(p) ?? p.binary?.path ?? void 0,
|
|
3133
|
+
children: [
|
|
3134
|
+
binaryWords(p),
|
|
3135
|
+
p.binary?.newer ? ` \xB7 ${p.binary.newer.version} available` : ""
|
|
3136
|
+
]
|
|
3137
|
+
}
|
|
3138
|
+
) : null,
|
|
3139
|
+
p.ready ? null : /* @__PURE__ */ jsxs7("span", { className: "block text-muted-foreground", children: [
|
|
2815
3140
|
p.problem,
|
|
2816
3141
|
" ",
|
|
2817
3142
|
p.fix
|
|
2818
3143
|
] })
|
|
2819
3144
|
] }),
|
|
2820
|
-
p.ready ? /* @__PURE__ */
|
|
3145
|
+
p.ready ? /* @__PURE__ */ jsx7(CheckIcon, { size: 15, className: "mt-0.5 text-success" }) : /* @__PURE__ */ jsx7(AlertIcon, { size: 15, className: "mt-0.5 text-warning" })
|
|
2821
3146
|
] }, p.provider)) })
|
|
2822
3147
|
] }) });
|
|
2823
3148
|
}
|
|
2824
3149
|
function useToast() {
|
|
2825
|
-
const [text, setText] =
|
|
2826
|
-
const timer =
|
|
2827
|
-
|
|
3150
|
+
const [text, setText] = useState6(null);
|
|
3151
|
+
const timer = useRef3(null);
|
|
3152
|
+
useEffect4(() => () => {
|
|
2828
3153
|
if (timer.current) clearTimeout(timer.current);
|
|
2829
3154
|
}, []);
|
|
2830
3155
|
const show = useCallback2((next) => {
|
|
@@ -2836,7 +3161,7 @@ function useToast() {
|
|
|
2836
3161
|
}
|
|
2837
3162
|
function Toast({ text }) {
|
|
2838
3163
|
if (!text) return null;
|
|
2839
|
-
return /* @__PURE__ */
|
|
3164
|
+
return /* @__PURE__ */ jsx7("div", { role: "status", className: "cs-toast", children: text });
|
|
2840
3165
|
}
|
|
2841
3166
|
var SIDEBAR_DEFAULT = 300;
|
|
2842
3167
|
var SIDEBAR_MIN = 220;
|
|
@@ -2845,7 +3170,7 @@ function clampWidth(n) {
|
|
|
2845
3170
|
return Math.round(Math.min(SIDEBAR_MAX, Math.max(SIDEBAR_MIN, n)));
|
|
2846
3171
|
}
|
|
2847
3172
|
function useSidebarLayout() {
|
|
2848
|
-
const [width, setWidthState] =
|
|
3173
|
+
const [width, setWidthState] = useState6(() => {
|
|
2849
3174
|
try {
|
|
2850
3175
|
const n = Number(localStorage.getItem("coding-sessions.sidebar-width"));
|
|
2851
3176
|
return Number.isFinite(n) && n > 0 ? clampWidth(n) : SIDEBAR_DEFAULT;
|
|
@@ -2853,7 +3178,7 @@ function useSidebarLayout() {
|
|
|
2853
3178
|
return SIDEBAR_DEFAULT;
|
|
2854
3179
|
}
|
|
2855
3180
|
});
|
|
2856
|
-
const [collapsed, setCollapsedState] =
|
|
3181
|
+
const [collapsed, setCollapsedState] = useState6(() => {
|
|
2857
3182
|
try {
|
|
2858
3183
|
return localStorage.getItem("coding-sessions.sidebar-collapsed") === "1";
|
|
2859
3184
|
} catch {
|
|
@@ -2878,8 +3203,8 @@ function useSidebarLayout() {
|
|
|
2878
3203
|
return { width, setWidth, collapsed, setCollapsed };
|
|
2879
3204
|
}
|
|
2880
3205
|
function Resizer(props) {
|
|
2881
|
-
const [dragging, setDragging] =
|
|
2882
|
-
return /* @__PURE__ */
|
|
3206
|
+
const [dragging, setDragging] = useState6(false);
|
|
3207
|
+
return /* @__PURE__ */ jsx7("div", { className: cn5("cs-resizer", dragging && "cs-resizer--dragging"), children: /* @__PURE__ */ jsx7(
|
|
2883
3208
|
"button",
|
|
2884
3209
|
{
|
|
2885
3210
|
type: "button",
|
|
@@ -2927,24 +3252,24 @@ var SHORTCUTS = [
|
|
|
2927
3252
|
{ keys: "\u2318/", what: "These shortcuts" }
|
|
2928
3253
|
];
|
|
2929
3254
|
function ShortcutsDialog(props) {
|
|
2930
|
-
return /* @__PURE__ */
|
|
2931
|
-
/* @__PURE__ */
|
|
2932
|
-
/* @__PURE__ */
|
|
2933
|
-
/* @__PURE__ */
|
|
3255
|
+
return /* @__PURE__ */ jsx7(Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ jsxs7(DialogContent, { className: "max-w-[420px]", children: [
|
|
3256
|
+
/* @__PURE__ */ jsxs7(DialogHeader, { children: [
|
|
3257
|
+
/* @__PURE__ */ jsx7(DialogTitle, { children: "Keyboard shortcuts" }),
|
|
3258
|
+
/* @__PURE__ */ jsx7(DialogDescription, { children: "Ctrl works in place of \u2318 on Windows and Linux." })
|
|
2934
3259
|
] }),
|
|
2935
|
-
/* @__PURE__ */
|
|
2936
|
-
/* @__PURE__ */
|
|
2937
|
-
/* @__PURE__ */
|
|
3260
|
+
/* @__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: [
|
|
3261
|
+
/* @__PURE__ */ jsx7("dt", { className: "text-muted-foreground", children: s.what }),
|
|
3262
|
+
/* @__PURE__ */ jsx7("dd", { children: /* @__PURE__ */ jsx7("kbd", { className: "rounded border border-border px-1.5 py-0.5 font-sans text-[12px]", children: s.keys }) })
|
|
2938
3263
|
] }, s.keys)) })
|
|
2939
3264
|
] }) });
|
|
2940
3265
|
}
|
|
2941
3266
|
var BASE_TITLE = "Coding sessions";
|
|
2942
3267
|
function useRunFinishedNotices(openSessionId, show) {
|
|
2943
3268
|
const client = useCodingSessionsClient();
|
|
2944
|
-
const unseen =
|
|
2945
|
-
const openRef =
|
|
3269
|
+
const unseen = useRef3(0);
|
|
3270
|
+
const openRef = useRef3(openSessionId);
|
|
2946
3271
|
openRef.current = openSessionId;
|
|
2947
|
-
|
|
3272
|
+
useEffect4(() => {
|
|
2948
3273
|
const reset = () => {
|
|
2949
3274
|
if (document.visibilityState === "visible") {
|
|
2950
3275
|
unseen.current = 0;
|
|
@@ -2960,7 +3285,7 @@ function useRunFinishedNotices(openSessionId, show) {
|
|
|
2960
3285
|
unseen.current += 1;
|
|
2961
3286
|
document.title = `(${unseen.current}) ${BASE_TITLE}`;
|
|
2962
3287
|
if (typeof Notification !== "undefined" && Notification.permission === "granted") {
|
|
2963
|
-
const note = new Notification(sentence, run.error ? { tag: run.runId, body: run.error } : { tag: run.runId });
|
|
3288
|
+
const note = new Notification(sentence, run.error ? { tag: run.runId, body: runErrorLabel(run.error) } : { tag: run.runId });
|
|
2964
3289
|
note.onclick = () => {
|
|
2965
3290
|
window.focus();
|
|
2966
3291
|
location.hash = `#s/${run.sessionId}`;
|
|
@@ -2979,9 +3304,9 @@ function useRunFinishedNotices(openSessionId, show) {
|
|
|
2979
3304
|
}
|
|
2980
3305
|
function NotifyToggle() {
|
|
2981
3306
|
const supported = typeof Notification !== "undefined";
|
|
2982
|
-
const [permission, setPermission] =
|
|
3307
|
+
const [permission, setPermission] = useState6(supported ? Notification.permission : "denied");
|
|
2983
3308
|
if (!supported || permission === "granted") return null;
|
|
2984
|
-
return /* @__PURE__ */
|
|
3309
|
+
return /* @__PURE__ */ jsx7(
|
|
2985
3310
|
"button",
|
|
2986
3311
|
{
|
|
2987
3312
|
type: "button",
|
|
@@ -2990,7 +3315,7 @@ function NotifyToggle() {
|
|
|
2990
3315
|
"aria-label": permission === "denied" ? "Notifications are blocked for this page in your browser's site settings" : "Notify me when a run finishes",
|
|
2991
3316
|
title: permission === "denied" ? "Notifications are blocked in your browser's site settings" : "Notify me when a run finishes",
|
|
2992
3317
|
disabled: permission === "denied",
|
|
2993
|
-
children: /* @__PURE__ */
|
|
3318
|
+
children: /* @__PURE__ */ jsx7(BellIcon, { size: 14 })
|
|
2994
3319
|
}
|
|
2995
3320
|
);
|
|
2996
3321
|
}
|
|
@@ -3002,20 +3327,20 @@ function isTyping(target) {
|
|
|
3002
3327
|
function Shell() {
|
|
3003
3328
|
const client = useCodingSessionsClient();
|
|
3004
3329
|
const state = useCodingSessionsState();
|
|
3005
|
-
const [selection, setSelection] =
|
|
3006
|
-
const [newOpen, setNewOpen] =
|
|
3007
|
-
const [shortcutsOpen, setShortcutsOpen] =
|
|
3008
|
-
const [changesOpen, setChangesOpen] =
|
|
3009
|
-
const [found, setFound] =
|
|
3330
|
+
const [selection, setSelection] = useState6(readHash);
|
|
3331
|
+
const [newOpen, setNewOpen] = useState6(false);
|
|
3332
|
+
const [shortcutsOpen, setShortcutsOpen] = useState6(false);
|
|
3333
|
+
const [changesOpen, setChangesOpen] = useState6(false);
|
|
3334
|
+
const [found, setFound] = useState6({});
|
|
3010
3335
|
const [theme, setTheme] = useTheme();
|
|
3011
3336
|
const [toast, showToast] = useToast();
|
|
3012
3337
|
const layout = useSidebarLayout();
|
|
3013
|
-
const searchRef =
|
|
3338
|
+
const searchRef = useRef3(null);
|
|
3014
3339
|
const select = useCallback2((next) => {
|
|
3015
3340
|
setSelection(next);
|
|
3016
3341
|
writeHash(next);
|
|
3017
3342
|
}, []);
|
|
3018
|
-
|
|
3343
|
+
useEffect4(() => {
|
|
3019
3344
|
const onHash = () => setSelection(readHash());
|
|
3020
3345
|
window.addEventListener("hashchange", onHash);
|
|
3021
3346
|
return () => window.removeEventListener("hashchange", onHash);
|
|
@@ -3025,14 +3350,14 @@ function Shell() {
|
|
|
3025
3350
|
const discovered = selection.kind === "discovered" ? state.discovered.data.find((d) => d.providerSessionId === selection.id) ?? found[`${selection.provider}:${selection.id}`] ?? null : null;
|
|
3026
3351
|
const run = session ? state.runs[session.id] : void 0;
|
|
3027
3352
|
const live = run !== void 0 && !isTerminalRunStatus(run.status);
|
|
3028
|
-
const order =
|
|
3353
|
+
const order = useMemo4(() => {
|
|
3029
3354
|
const known = new Set(state.sessions.data.map((s) => s.providerSessionId).filter(Boolean));
|
|
3030
3355
|
return [
|
|
3031
3356
|
...state.sessions.data.map((s) => ({ kind: "session", id: s.id })),
|
|
3032
3357
|
...state.discovered.data.filter((d) => !known.has(d.providerSessionId)).map((d) => ({ kind: "discovered", provider: d.provider, id: d.providerSessionId }))
|
|
3033
3358
|
];
|
|
3034
3359
|
}, [state.sessions.data, state.discovered.data]);
|
|
3035
|
-
|
|
3360
|
+
useEffect4(() => {
|
|
3036
3361
|
const onKey = (e) => {
|
|
3037
3362
|
const mod = e.metaKey || e.ctrlKey;
|
|
3038
3363
|
const key = e.key.toLowerCase();
|
|
@@ -3088,12 +3413,12 @@ function Shell() {
|
|
|
3088
3413
|
}, [client, layout, live, run, order, selection, select, showToast]);
|
|
3089
3414
|
let main;
|
|
3090
3415
|
if (selection.kind === "session") {
|
|
3091
|
-
main = session ? /* @__PURE__ */
|
|
3092
|
-
/* @__PURE__ */
|
|
3416
|
+
main = session ? /* @__PURE__ */ jsx7(SessionView, { session, changesOpen, setChangesOpen }, session.id) : state.sessions.loadedAt === null ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
|
|
3417
|
+
/* @__PURE__ */ jsx7(SpinnerIcon, { size: 15 }),
|
|
3093
3418
|
" Loading\u2026"
|
|
3094
|
-
] }) : /* @__PURE__ */
|
|
3419
|
+
] }) : /* @__PURE__ */ jsx7("div", { className: "flex flex-1 items-center justify-center text-[13px] text-muted-foreground", children: "That session is not in the list anymore." });
|
|
3095
3420
|
} else if (selection.kind === "discovered") {
|
|
3096
|
-
main = /* @__PURE__ */
|
|
3421
|
+
main = /* @__PURE__ */ jsx7(
|
|
3097
3422
|
DiscoveredView,
|
|
3098
3423
|
{
|
|
3099
3424
|
session: discovered,
|
|
@@ -3106,13 +3431,13 @@ function Shell() {
|
|
|
3106
3431
|
`${selection.provider}:${selection.id}`
|
|
3107
3432
|
);
|
|
3108
3433
|
} else {
|
|
3109
|
-
main = /* @__PURE__ */
|
|
3434
|
+
main = /* @__PURE__ */ jsx7(Home, { onNew: () => setNewOpen(true) });
|
|
3110
3435
|
}
|
|
3111
|
-
return /* @__PURE__ */
|
|
3112
|
-
/* @__PURE__ */
|
|
3113
|
-
/* @__PURE__ */
|
|
3114
|
-
layout.collapsed ? /* @__PURE__ */
|
|
3115
|
-
/* @__PURE__ */
|
|
3436
|
+
return /* @__PURE__ */ jsx7(ToastContext.Provider, { value: showToast, children: /* @__PURE__ */ jsxs7("div", { className: "cs-app flex h-full flex-col bg-background text-foreground", children: [
|
|
3437
|
+
/* @__PURE__ */ jsx7(ConnectionBanner, {}),
|
|
3438
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex min-h-0 flex-1", children: [
|
|
3439
|
+
layout.collapsed ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-col items-center gap-1 border-r border-border bg-muted/30 px-1.5 py-3", children: [
|
|
3440
|
+
/* @__PURE__ */ jsx7(
|
|
3116
3441
|
"button",
|
|
3117
3442
|
{
|
|
3118
3443
|
type: "button",
|
|
@@ -3120,10 +3445,10 @@ function Shell() {
|
|
|
3120
3445
|
onClick: () => layout.setCollapsed(false),
|
|
3121
3446
|
"aria-label": "Show the sidebar (\u2318B)",
|
|
3122
3447
|
title: "Show sidebar \u2318B",
|
|
3123
|
-
children: /* @__PURE__ */
|
|
3448
|
+
children: /* @__PURE__ */ jsx7(SidebarIcon, { size: 15 })
|
|
3124
3449
|
}
|
|
3125
3450
|
),
|
|
3126
|
-
/* @__PURE__ */
|
|
3451
|
+
/* @__PURE__ */ jsx7(
|
|
3127
3452
|
"button",
|
|
3128
3453
|
{
|
|
3129
3454
|
type: "button",
|
|
@@ -3131,11 +3456,11 @@ function Shell() {
|
|
|
3131
3456
|
onClick: () => setNewOpen(true),
|
|
3132
3457
|
"aria-label": "New session",
|
|
3133
3458
|
title: "New session \u2325\u2318N",
|
|
3134
|
-
children: /* @__PURE__ */
|
|
3459
|
+
children: /* @__PURE__ */ jsx7(PlusIcon, { size: 15 })
|
|
3135
3460
|
}
|
|
3136
3461
|
)
|
|
3137
|
-
] }) : /* @__PURE__ */
|
|
3138
|
-
/* @__PURE__ */
|
|
3462
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
3463
|
+
/* @__PURE__ */ jsx7(
|
|
3139
3464
|
Sidebar,
|
|
3140
3465
|
{
|
|
3141
3466
|
selection,
|
|
@@ -3145,14 +3470,14 @@ function Shell() {
|
|
|
3145
3470
|
width: layout.width,
|
|
3146
3471
|
searchRef,
|
|
3147
3472
|
onFound: (d) => setFound((f) => ({ ...f, [`${d.provider}:${d.providerSessionId}`]: d })),
|
|
3148
|
-
footer: /* @__PURE__ */
|
|
3473
|
+
footer: /* @__PURE__ */ jsx7(
|
|
3149
3474
|
ProvidersFooter,
|
|
3150
3475
|
{
|
|
3151
3476
|
theme,
|
|
3152
3477
|
setTheme,
|
|
3153
|
-
extra: /* @__PURE__ */
|
|
3154
|
-
/* @__PURE__ */
|
|
3155
|
-
/* @__PURE__ */
|
|
3478
|
+
extra: /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
3479
|
+
/* @__PURE__ */ jsx7(NotifyToggle, {}),
|
|
3480
|
+
/* @__PURE__ */ jsx7(
|
|
3156
3481
|
"button",
|
|
3157
3482
|
{
|
|
3158
3483
|
type: "button",
|
|
@@ -3160,7 +3485,7 @@ function Shell() {
|
|
|
3160
3485
|
onClick: () => setShortcutsOpen(true),
|
|
3161
3486
|
"aria-label": "Keyboard shortcuts (\u2318/)",
|
|
3162
3487
|
title: "Keyboard shortcuts \u2318/",
|
|
3163
|
-
children: /* @__PURE__ */
|
|
3488
|
+
children: /* @__PURE__ */ jsx7(KeyboardIcon, { size: 14 })
|
|
3164
3489
|
}
|
|
3165
3490
|
)
|
|
3166
3491
|
] })
|
|
@@ -3168,11 +3493,11 @@ function Shell() {
|
|
|
3168
3493
|
)
|
|
3169
3494
|
}
|
|
3170
3495
|
),
|
|
3171
|
-
/* @__PURE__ */
|
|
3496
|
+
/* @__PURE__ */ jsx7(Resizer, { width: layout.width, setWidth: layout.setWidth })
|
|
3172
3497
|
] }),
|
|
3173
|
-
/* @__PURE__ */
|
|
3498
|
+
/* @__PURE__ */ jsx7("main", { className: "flex min-w-0 flex-1", children: main })
|
|
3174
3499
|
] }),
|
|
3175
|
-
/* @__PURE__ */
|
|
3500
|
+
/* @__PURE__ */ jsx7(
|
|
3176
3501
|
NewSessionDialog,
|
|
3177
3502
|
{
|
|
3178
3503
|
open: newOpen,
|
|
@@ -3183,12 +3508,12 @@ function Shell() {
|
|
|
3183
3508
|
}
|
|
3184
3509
|
}
|
|
3185
3510
|
),
|
|
3186
|
-
/* @__PURE__ */
|
|
3187
|
-
/* @__PURE__ */
|
|
3511
|
+
/* @__PURE__ */ jsx7(ShortcutsDialog, { open: shortcutsOpen, onOpenChange: setShortcutsOpen }),
|
|
3512
|
+
/* @__PURE__ */ jsx7(Toast, { text: toast })
|
|
3188
3513
|
] }) });
|
|
3189
3514
|
}
|
|
3190
3515
|
function CodingSessionsApp({ transport }) {
|
|
3191
|
-
return /* @__PURE__ */
|
|
3516
|
+
return /* @__PURE__ */ jsx7(CodingSessionsProvider, { transport, children: /* @__PURE__ */ jsx7(Shell, {}) });
|
|
3192
3517
|
}
|
|
3193
3518
|
export {
|
|
3194
3519
|
CodingSessionsApp,
|