@ai-matrx/coding-sessions 0.1.83 → 0.1.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/engine/index.cjs +656 -126
- 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 +654 -126
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/worker.js +7 -5
- package/dist/engine/worker.js.map +1 -1
- package/dist/{index-DQ0teQvw.d.cts → index-aavbdzSo.d.cts} +161 -1
- package/dist/{index-DQ0teQvw.d.ts → index-aavbdzSo.d.ts} +161 -1
- package/dist/index.cjs +16 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +112 -1
- package/dist/index.d.ts +112 -1
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +821 -412
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +113 -8
- package/dist/react/index.d.ts +113 -8
- package/dist/react/index.js +851 -418
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +720 -141
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +5 -1
- package/dist/server/index.d.ts +5 -1
- package/dist/server/index.js +719 -140
- package/dist/server/index.js.map +1 -1
- package/dist/ui/assets/index-XIcCZr8A.js +71 -0
- package/dist/ui/assets/index-eqe0sxR4.css +2 -0
- package/dist/ui/index.html +2 -2
- package/package.json +3 -1
- package/dist/ui/assets/index-C-_1qjy9.css +0 -2
- package/dist/ui/assets/index-CmFgFvLa.js +0 -69
package/dist/react/index.cjs
CHANGED
|
@@ -34,10 +34,10 @@ __export(react_exports, {
|
|
|
34
34
|
module.exports = __toCommonJS(react_exports);
|
|
35
35
|
|
|
36
36
|
// src/react/app.tsx
|
|
37
|
-
var
|
|
38
|
-
var
|
|
37
|
+
var import_react8 = require("react");
|
|
38
|
+
var import_react9 = require("@ai-matrx/chat/react");
|
|
39
39
|
var import_external_store2 = require("@ai-matrx/chat/external-store");
|
|
40
|
-
var
|
|
40
|
+
var import_design_system6 = require("@ai-matrx/design-system");
|
|
41
41
|
var import_format3 = require("@ai-matrx/kit/format");
|
|
42
42
|
|
|
43
43
|
// src/types.ts
|
|
@@ -486,14 +486,20 @@ var SpinnerIcon = ({ size = 16, className }) => /* @__PURE__ */ (0, import_jsx_r
|
|
|
486
486
|
]
|
|
487
487
|
}
|
|
488
488
|
);
|
|
489
|
-
|
|
489
|
+
var CLAUDE_MARK = "m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z";
|
|
490
|
+
var OPENAI_MARK = "M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z";
|
|
491
|
+
function ProviderMark({ provider, size = 16 }) {
|
|
490
492
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
491
|
-
"
|
|
493
|
+
"svg",
|
|
492
494
|
{
|
|
493
495
|
className: `cs-provider-mark cs-provider-mark--${provider}`,
|
|
494
|
-
|
|
496
|
+
width: size,
|
|
497
|
+
height: size,
|
|
498
|
+
viewBox: "0 0 24 24",
|
|
499
|
+
fill: "currentColor",
|
|
495
500
|
"aria-hidden": "true",
|
|
496
|
-
|
|
501
|
+
"data-provider-mark": provider,
|
|
502
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: provider === "claude" ? CLAUDE_MARK : OPENAI_MARK })
|
|
497
503
|
}
|
|
498
504
|
);
|
|
499
505
|
}
|
|
@@ -890,10 +896,354 @@ function ModelPicker(props) {
|
|
|
890
896
|
] });
|
|
891
897
|
}
|
|
892
898
|
|
|
893
|
-
// src/react/
|
|
899
|
+
// src/react/agent-field.tsx
|
|
894
900
|
var import_react5 = require("react");
|
|
901
|
+
var import_agents = require("@ai-matrx/agents");
|
|
902
|
+
var import_catalog = require("@ai-matrx/agents/catalog");
|
|
903
|
+
var import_react6 = require("@ai-matrx/agents/catalog/react");
|
|
904
|
+
var import_context = require("@ai-matrx/agents/context");
|
|
895
905
|
var import_design_system4 = require("@ai-matrx/design-system");
|
|
896
906
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
907
|
+
var SIGNED_OUT_AGENTS = "Sign in to AI Matrx to use your agents";
|
|
908
|
+
var LATEST = "latest";
|
|
909
|
+
function bridgedClient(transport) {
|
|
910
|
+
const call = (request) => {
|
|
911
|
+
const run = () => transport.call("agentCatalogRpc", request).then((result) => ({
|
|
912
|
+
data: result.data,
|
|
913
|
+
error: result.error ? {
|
|
914
|
+
message: result.error.message,
|
|
915
|
+
...result.error.code ? { code: result.error.code } : {},
|
|
916
|
+
details: result.error.details ?? null,
|
|
917
|
+
hint: result.error.hint ?? null
|
|
918
|
+
} : null,
|
|
919
|
+
count: result.count ?? null
|
|
920
|
+
}));
|
|
921
|
+
return {
|
|
922
|
+
then: (onOk, onErr) => run().then(onOk, onErr),
|
|
923
|
+
range: (from, to) => call({ ...request, range: [from, to] }),
|
|
924
|
+
order: (column, options) => call({ ...request, order: { column, ascending: options?.ascending !== false } })
|
|
925
|
+
};
|
|
926
|
+
};
|
|
927
|
+
return {
|
|
928
|
+
rpc: (fn, args, options) => call({ fn, ...args ? { args } : {}, ...options?.count ? { count: options.count } : {} })
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
function useAgentAccess(transport, open) {
|
|
932
|
+
const [access, setAccess] = (0, import_react5.useState)(null);
|
|
933
|
+
(0, import_react5.useEffect)(() => {
|
|
934
|
+
if (!open) return;
|
|
935
|
+
let alive = true;
|
|
936
|
+
transport.call("agentAccess").then((next) => alive && setAccess(next)).catch(() => alive && setAccess({ signedIn: false, userId: null, organizationId: null, configured: false }));
|
|
937
|
+
return () => {
|
|
938
|
+
alive = false;
|
|
939
|
+
};
|
|
940
|
+
}, [transport, open]);
|
|
941
|
+
return access;
|
|
942
|
+
}
|
|
943
|
+
function useCatalog(transport, userId, onError) {
|
|
944
|
+
const report = (0, import_react5.useRef)(onError);
|
|
945
|
+
report.current = onError;
|
|
946
|
+
return (0, import_react5.useMemo)(() => {
|
|
947
|
+
if (!userId) return null;
|
|
948
|
+
return (0, import_catalog.createAgentCatalog)({
|
|
949
|
+
client: bridgedClient(transport),
|
|
950
|
+
identity: { requireUserId: () => userId, getUserId: () => userId },
|
|
951
|
+
catalogId: `coding-sessions:${userId}`,
|
|
952
|
+
// A failed catalogue read shows at the field, never only in the console.
|
|
953
|
+
errorSink: (event) => {
|
|
954
|
+
console.error(`[coding-sessions] agent catalogue: ${event.code}: ${event.message}`);
|
|
955
|
+
if (event.code === "list_read_failed") report.current("Couldn't load your agents. Reopen to retry.");
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
}, [transport, userId]);
|
|
959
|
+
}
|
|
960
|
+
function asRunInputVariables(defs) {
|
|
961
|
+
return defs.flatMap((def) => typeof def.name === "string" ? [def] : []);
|
|
962
|
+
}
|
|
963
|
+
function AgentField(props) {
|
|
964
|
+
const access = useAgentAccess(props.transport, props.open);
|
|
965
|
+
const [details, setDetails] = (0, import_react5.useState)(null);
|
|
966
|
+
const [problem, setProblem] = (0, import_react5.useState)(null);
|
|
967
|
+
const catalog = useCatalog(props.transport, access?.signedIn ? access.userId : null, setProblem);
|
|
968
|
+
const agentId = props.value?.agentId ?? null;
|
|
969
|
+
(0, import_react5.useEffect)(() => {
|
|
970
|
+
setDetails(null);
|
|
971
|
+
setProblem(null);
|
|
972
|
+
if (!agentId) return;
|
|
973
|
+
let alive = true;
|
|
974
|
+
props.transport.call("agentDetails", agentId).then((next) => alive && setDetails(next)).catch((error) => alive && setProblem(error instanceof Error ? error.message : String(error)));
|
|
975
|
+
return () => {
|
|
976
|
+
alive = false;
|
|
977
|
+
};
|
|
978
|
+
}, [agentId, props.transport]);
|
|
979
|
+
const { onDetails } = props;
|
|
980
|
+
(0, import_react5.useEffect)(() => {
|
|
981
|
+
onDetails?.(details);
|
|
982
|
+
}, [details, onDetails]);
|
|
983
|
+
const inputs = (0, import_react5.useMemo)(() => (0, import_agents.deriveRunInputs)(asRunInputVariables(details?.variables ?? []), import_context.humanizeContextKey), [details]);
|
|
984
|
+
if (access === null) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cs-skeleton h-9 rounded-lg" });
|
|
985
|
+
if (!access.signedIn || !catalog) {
|
|
986
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[12.5px] text-muted-foreground", children: SIGNED_OUT_AGENTS });
|
|
987
|
+
}
|
|
988
|
+
const setVariable = (name, value) => {
|
|
989
|
+
if (!props.value) return;
|
|
990
|
+
props.onChange({ ...props.value, variables: { ...props.value.variables ?? {}, [name]: value } });
|
|
991
|
+
};
|
|
992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-3", children: [
|
|
993
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
994
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react6.AgentCatalogProvider, { catalog, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
995
|
+
import_react6.AgentListDropdown,
|
|
996
|
+
{
|
|
997
|
+
consumerId: "coding-sessions-new-session",
|
|
998
|
+
activeAgentId: agentId,
|
|
999
|
+
label: details?.name ?? (agentId ? "Loading\u2026" : "None"),
|
|
1000
|
+
onSelect: (id) => props.onChange({ agentId: id, versionId: null, variables: {} })
|
|
1001
|
+
}
|
|
1002
|
+
) }) }),
|
|
1003
|
+
agentId ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Button, { type: "button", size: "sm", variant: "ghost", onClick: () => props.onChange(null), children: "Remove" }) : null
|
|
1004
|
+
] }),
|
|
1005
|
+
problem ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[12px] text-destructive", children: problem }) : null,
|
|
1006
|
+
details && props.value ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1007
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1008
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-[72px] shrink-0 text-[12px] text-muted-foreground", children: "Version" }),
|
|
1009
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1010
|
+
import_design_system4.Select,
|
|
1011
|
+
{
|
|
1012
|
+
value: props.value.versionId ?? LATEST,
|
|
1013
|
+
onValueChange: (next) => props.value && props.onChange({ ...props.value, versionId: next === LATEST ? null : next }),
|
|
1014
|
+
children: [
|
|
1015
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectTrigger, { className: "h-8 w-[200px] text-[12.5px]", "aria-label": "Agent version", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectValue, {}) }),
|
|
1016
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.SelectContent, { children: [
|
|
1017
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectItem, { value: LATEST, children: details.latestVersionNumber !== null ? `Latest (v${details.latestVersionNumber})` : "Latest" }),
|
|
1018
|
+
details.versions.map((v) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.SelectItem, { value: v.id, children: [
|
|
1019
|
+
"v",
|
|
1020
|
+
v.versionNumber
|
|
1021
|
+
] }, v.id))
|
|
1022
|
+
] })
|
|
1023
|
+
]
|
|
1024
|
+
}
|
|
1025
|
+
)
|
|
1026
|
+
] }),
|
|
1027
|
+
inputs.map((input) => {
|
|
1028
|
+
const raw = props.value?.variables?.[input.name];
|
|
1029
|
+
const value = typeof raw === "string" ? raw : "";
|
|
1030
|
+
const id = `cs-agent-var-${input.name}`;
|
|
1031
|
+
const invalid = props.missing === input.name;
|
|
1032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-1", children: [
|
|
1033
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { htmlFor: id, className: "text-[12px] font-medium", children: [
|
|
1034
|
+
input.label,
|
|
1035
|
+
input.required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-muted-foreground", children: " \xB7 required" }) : null
|
|
1036
|
+
] }),
|
|
1037
|
+
input.options && input.options.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.Select, { value, onValueChange: (next) => setVariable(input.name, next), children: [
|
|
1038
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectTrigger, { id, className: "h-8 text-[12.5px]", "aria-invalid": invalid || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectValue, { placeholder: "Choose\u2026" }) }),
|
|
1039
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectContent, { children: input.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.SelectItem, { value: option, children: option }, option)) })
|
|
1040
|
+
] }) : input.variable.customComponent?.type === "textarea" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1041
|
+
import_design_system4.Textarea,
|
|
1042
|
+
{
|
|
1043
|
+
id,
|
|
1044
|
+
rows: 2,
|
|
1045
|
+
value,
|
|
1046
|
+
onChange: (e) => setVariable(input.name, e.target.value),
|
|
1047
|
+
placeholder: input.hint ?? "",
|
|
1048
|
+
"aria-invalid": invalid || void 0
|
|
1049
|
+
}
|
|
1050
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1051
|
+
import_design_system4.Input,
|
|
1052
|
+
{
|
|
1053
|
+
id,
|
|
1054
|
+
value,
|
|
1055
|
+
onChange: (e) => setVariable(input.name, e.target.value),
|
|
1056
|
+
placeholder: input.hint ?? "",
|
|
1057
|
+
"aria-invalid": invalid || void 0
|
|
1058
|
+
}
|
|
1059
|
+
),
|
|
1060
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[12px] text-destructive", children: "Fill this in to use the agent" }) : null
|
|
1061
|
+
] }, input.name);
|
|
1062
|
+
})
|
|
1063
|
+
] }) : null
|
|
1064
|
+
] });
|
|
1065
|
+
}
|
|
1066
|
+
function missingRequiredVariable(details, selection) {
|
|
1067
|
+
if (!details || !selection) return null;
|
|
1068
|
+
for (const input of (0, import_agents.deriveRunInputs)(asRunInputVariables(details.variables), import_context.humanizeContextKey)) {
|
|
1069
|
+
if (!input.required) continue;
|
|
1070
|
+
const value = selection.variables?.[input.name];
|
|
1071
|
+
if (typeof value !== "string" || !value.trim()) return input.name;
|
|
1072
|
+
}
|
|
1073
|
+
return null;
|
|
1074
|
+
}
|
|
1075
|
+
var PART_LABEL = {
|
|
1076
|
+
instructions: "Instructions",
|
|
1077
|
+
skills: "Skills",
|
|
1078
|
+
tools: "Tools"
|
|
1079
|
+
};
|
|
1080
|
+
function agentChipText(agent) {
|
|
1081
|
+
const parts = agent.loaded.map(
|
|
1082
|
+
(part) => part.part === "instructions" ? `${PART_LABEL.instructions} ${part.loaded === 1 ? "\u2713" : "\u2014"}` : `${PART_LABEL[part.part]} ${part.loaded}/${part.total}`
|
|
1083
|
+
);
|
|
1084
|
+
return `${agent.name}${agent.versionNumber !== null ? ` v${agent.versionNumber}` : ""} \xB7 ${parts.join(" \xB7 ")}`;
|
|
1085
|
+
}
|
|
1086
|
+
function AgentMenu(props) {
|
|
1087
|
+
const { agent } = props;
|
|
1088
|
+
const show = useToastShow();
|
|
1089
|
+
const [open, setOpen] = (0, import_react5.useState)(false);
|
|
1090
|
+
const [choosing, setChoosing] = (0, import_react5.useState)(false);
|
|
1091
|
+
const [latest, setLatest] = (0, import_react5.useState)(null);
|
|
1092
|
+
const [access, setAccess] = (0, import_react5.useState)(null);
|
|
1093
|
+
(0, import_react5.useEffect)(() => {
|
|
1094
|
+
if (!open) return;
|
|
1095
|
+
let alive = true;
|
|
1096
|
+
void props.transport.call("agentAccess").then((next) => alive && setAccess(next)).catch(() => void 0);
|
|
1097
|
+
if (agent) {
|
|
1098
|
+
props.transport.call("agentDetails", agent.agentId).then((d) => {
|
|
1099
|
+
if (alive && d.latestVersionId && d.latestVersionNumber !== null) setLatest({ id: d.latestVersionId, number: d.latestVersionNumber });
|
|
1100
|
+
}).catch(() => void 0);
|
|
1101
|
+
}
|
|
1102
|
+
return () => {
|
|
1103
|
+
alive = false;
|
|
1104
|
+
};
|
|
1105
|
+
}, [open, agent, props.transport]);
|
|
1106
|
+
const apply = async (selection, done) => {
|
|
1107
|
+
try {
|
|
1108
|
+
await props.transport.call("setAgent", props.sessionId, selection);
|
|
1109
|
+
show(done);
|
|
1110
|
+
props.onChange();
|
|
1111
|
+
} catch (error) {
|
|
1112
|
+
show(`That didn't change: ${error instanceof Error ? error.message : String(error)}`);
|
|
1113
|
+
}
|
|
1114
|
+
};
|
|
1115
|
+
const behind = agent && latest && agent.versionNumber !== null && latest.number > agent.versionNumber ? latest : null;
|
|
1116
|
+
const complete = agent ? agent.loaded.every((part) => part.loaded === part.total) : true;
|
|
1117
|
+
const signedIn = access?.signedIn ?? false;
|
|
1118
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1119
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DropdownMenu, { open, onOpenChange: setOpen, children: [
|
|
1120
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1121
|
+
"button",
|
|
1122
|
+
{
|
|
1123
|
+
type: "button",
|
|
1124
|
+
className: (0, import_design_system4.cn)("cs-agent-chip", agent ? "cs-agent-chip--set" : "cs-agent-chip--none", !complete && "cs-agent-chip--partial"),
|
|
1125
|
+
"data-testid": "cs-agent-chip",
|
|
1126
|
+
"aria-label": agent ? `AI Matrx agent: ${agent.name}` : "Add an AI Matrx agent",
|
|
1127
|
+
children: [
|
|
1128
|
+
agent ? agentChipText(agent) : "No agent",
|
|
1129
|
+
behind ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "cs-agent-chip-dot", "aria-label": "Update available" }) : null,
|
|
1130
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronDownIcon, { size: 12, className: "ml-1 inline shrink-0" })
|
|
1131
|
+
]
|
|
1132
|
+
}
|
|
1133
|
+
) }),
|
|
1134
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DropdownMenuContent, { align: "end", className: "w-[320px]", children: [
|
|
1135
|
+
agent ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1136
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DropdownMenuLabel, { className: "truncate", children: [
|
|
1137
|
+
agent.name,
|
|
1138
|
+
agent.versionNumber !== null ? ` \xB7 v${agent.versionNumber}` : ""
|
|
1139
|
+
] }),
|
|
1140
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cs-agent-parts", children: [
|
|
1141
|
+
agent.blockDue ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[12px] text-muted-foreground", children: "Sent with your next message" }) : null,
|
|
1142
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AgentPartList, { title: "Skills", items: agent.skills ?? [] }),
|
|
1143
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AgentPartList, { title: "Tools", items: agent.tools ?? [] }),
|
|
1144
|
+
agent.unavailable.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1145
|
+
AgentPartList,
|
|
1146
|
+
{
|
|
1147
|
+
title: "Not loaded",
|
|
1148
|
+
items: agent.unavailable.map((u) => `${u.name} \u2014 ${u.reason}`)
|
|
1149
|
+
}
|
|
1150
|
+
) : null
|
|
1151
|
+
] }),
|
|
1152
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuSeparator, {})
|
|
1153
|
+
] }) : null,
|
|
1154
|
+
signedIn ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1155
|
+
behind && agent ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1156
|
+
import_design_system4.DropdownMenuItem,
|
|
1157
|
+
{
|
|
1158
|
+
onSelect: () => void apply(
|
|
1159
|
+
{ agentId: agent.agentId, versionId: behind.id, variables: agent.variables ?? {} },
|
|
1160
|
+
`The next message uses ${agent.name} v${behind.number}.`
|
|
1161
|
+
),
|
|
1162
|
+
children: [
|
|
1163
|
+
"Update to v",
|
|
1164
|
+
behind.number
|
|
1165
|
+
]
|
|
1166
|
+
}
|
|
1167
|
+
) : null,
|
|
1168
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuItem, { onSelect: () => setChoosing(true), children: agent ? "Change agent\u2026" : "Choose agent\u2026" }),
|
|
1169
|
+
agent ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DropdownMenuItem, { onSelect: () => void apply(null, "The next message runs without an agent."), children: "Remove agent" }) : null
|
|
1170
|
+
] }) : access ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "px-2 py-1.5 text-[12px] text-muted-foreground", children: SIGNED_OUT_AGENTS }) : null
|
|
1171
|
+
] })
|
|
1172
|
+
] }),
|
|
1173
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1174
|
+
ChooseAgentDialog,
|
|
1175
|
+
{
|
|
1176
|
+
transport: props.transport,
|
|
1177
|
+
open: choosing,
|
|
1178
|
+
onOpenChange: setChoosing,
|
|
1179
|
+
title: agent ? "Change agent" : "Choose an agent",
|
|
1180
|
+
action: "Use this agent",
|
|
1181
|
+
onConfirm: (selection) => apply(selection, "The next message uses the new agent.")
|
|
1182
|
+
}
|
|
1183
|
+
)
|
|
1184
|
+
] });
|
|
1185
|
+
}
|
|
1186
|
+
function AgentPartList({ title, items }) {
|
|
1187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1188
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "text-[11.5px] font-medium text-muted-foreground", children: [
|
|
1189
|
+
title,
|
|
1190
|
+
" \xB7 ",
|
|
1191
|
+
items.length
|
|
1192
|
+
] }),
|
|
1193
|
+
items.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "cs-agent-part-list", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { className: "truncate", title: item, children: item }, item)) }) : null
|
|
1194
|
+
] });
|
|
1195
|
+
}
|
|
1196
|
+
function ChooseAgentDialog(props) {
|
|
1197
|
+
const [value, setValue] = (0, import_react5.useState)(null);
|
|
1198
|
+
const [details, setDetails] = (0, import_react5.useState)(null);
|
|
1199
|
+
const [missing, setMissing] = (0, import_react5.useState)(null);
|
|
1200
|
+
const [busy, setBusy] = (0, import_react5.useState)(false);
|
|
1201
|
+
(0, import_react5.useEffect)(() => {
|
|
1202
|
+
if (props.open) {
|
|
1203
|
+
setValue(null);
|
|
1204
|
+
setMissing(null);
|
|
1205
|
+
}
|
|
1206
|
+
}, [props.open]);
|
|
1207
|
+
const confirm = async () => {
|
|
1208
|
+
if (!value) return;
|
|
1209
|
+
const gap = missingRequiredVariable(details, value);
|
|
1210
|
+
setMissing(gap);
|
|
1211
|
+
if (gap) return;
|
|
1212
|
+
setBusy(true);
|
|
1213
|
+
try {
|
|
1214
|
+
await props.onConfirm(value);
|
|
1215
|
+
props.onOpenChange(false);
|
|
1216
|
+
} finally {
|
|
1217
|
+
setBusy(false);
|
|
1218
|
+
}
|
|
1219
|
+
};
|
|
1220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DialogContent, { className: "max-w-[480px]", children: [
|
|
1221
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DialogHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.DialogTitle, { children: props.title }) }),
|
|
1222
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1223
|
+
AgentField,
|
|
1224
|
+
{
|
|
1225
|
+
transport: props.transport,
|
|
1226
|
+
open: props.open,
|
|
1227
|
+
value,
|
|
1228
|
+
onChange: (next) => {
|
|
1229
|
+
setValue(next);
|
|
1230
|
+
setMissing(null);
|
|
1231
|
+
},
|
|
1232
|
+
missing,
|
|
1233
|
+
onDetails: setDetails
|
|
1234
|
+
}
|
|
1235
|
+
),
|
|
1236
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system4.DialogFooter, { children: [
|
|
1237
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Button, { type: "button", variant: "ghost", onClick: () => props.onOpenChange(false), children: "Cancel" }),
|
|
1238
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system4.Button, { type: "button", disabled: !value || busy, onClick: () => void confirm(), children: props.action })
|
|
1239
|
+
] })
|
|
1240
|
+
] }) });
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
// src/react/sidebar.tsx
|
|
1244
|
+
var import_react7 = require("react");
|
|
1245
|
+
var import_design_system5 = require("@ai-matrx/design-system");
|
|
1246
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
897
1247
|
function readLocal(key, allowed, fallback) {
|
|
898
1248
|
try {
|
|
899
1249
|
const value = localStorage.getItem(key);
|
|
@@ -909,23 +1259,23 @@ function writeLocal(key, value) {
|
|
|
909
1259
|
}
|
|
910
1260
|
}
|
|
911
1261
|
function SectionLabel({ children, action }) {
|
|
912
|
-
return /* @__PURE__ */ (0,
|
|
913
|
-
/* @__PURE__ */ (0,
|
|
1262
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-cs-section-label": true, className: "flex h-8 items-center justify-between px-3 pt-3", children: [
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[12px] font-medium text-muted-foreground", children }),
|
|
914
1264
|
action
|
|
915
1265
|
] });
|
|
916
1266
|
}
|
|
917
1267
|
function GroupLabel({ children }) {
|
|
918
|
-
return /* @__PURE__ */ (0,
|
|
1268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "truncate px-4 pb-0.5 pt-2.5 text-[12px] font-medium text-muted-foreground", children });
|
|
919
1269
|
}
|
|
920
1270
|
function RenameInput(props) {
|
|
921
|
-
const [value, setValue] = (0,
|
|
922
|
-
const done = (0,
|
|
1271
|
+
const [value, setValue] = (0, import_react7.useState)(props.initial);
|
|
1272
|
+
const done = (0, import_react7.useRef)(false);
|
|
923
1273
|
const finish = (title) => {
|
|
924
1274
|
if (done.current) return;
|
|
925
1275
|
done.current = true;
|
|
926
1276
|
props.onDone(title);
|
|
927
1277
|
};
|
|
928
|
-
return /* @__PURE__ */ (0,
|
|
1278
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
929
1279
|
"input",
|
|
930
1280
|
{
|
|
931
1281
|
autoFocus: true,
|
|
@@ -942,11 +1292,16 @@ function RenameInput(props) {
|
|
|
942
1292
|
}
|
|
943
1293
|
);
|
|
944
1294
|
}
|
|
1295
|
+
function entryTarget(entry) {
|
|
1296
|
+
if (entry.kind === "session" && entry.session) return `#s/${entry.session.id}`;
|
|
1297
|
+
if (entry.providerSessionId) return `#d/${entry.provider}/${entry.providerSessionId}`;
|
|
1298
|
+
return "";
|
|
1299
|
+
}
|
|
945
1300
|
function Row(props) {
|
|
946
1301
|
const client = useCodingSessionsClient();
|
|
947
1302
|
const show = useToastShow();
|
|
948
|
-
const [renaming, setRenaming] = (0,
|
|
949
|
-
const [menuOpen, setMenuOpen] = (0,
|
|
1303
|
+
const [renaming, setRenaming] = (0, import_react7.useState)(false);
|
|
1304
|
+
const [menuOpen, setMenuOpen] = (0, import_react7.useState)(false);
|
|
950
1305
|
const { entry } = props;
|
|
951
1306
|
const rename = (title) => {
|
|
952
1307
|
setRenaming(false);
|
|
@@ -956,14 +1311,20 @@ function Row(props) {
|
|
|
956
1311
|
(error) => show(`The new name didn't save: ${error instanceof Error ? error.message : String(error)}`)
|
|
957
1312
|
);
|
|
958
1313
|
};
|
|
959
|
-
return /* @__PURE__ */ (0,
|
|
960
|
-
/* @__PURE__ */ (0,
|
|
1314
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.ContextMenu, { children: [
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.ContextMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
961
1316
|
"div",
|
|
962
1317
|
{
|
|
963
|
-
className: (0,
|
|
1318
|
+
className: (0, import_design_system5.cn)("cs-row group", props.active && "cs-row--active", menuOpen && "cs-row--menu"),
|
|
964
1319
|
"data-hidden": entry.hidden || void 0,
|
|
1320
|
+
"data-cs-row": entry.key,
|
|
1321
|
+
"data-cs-target": entryTarget(entry),
|
|
1322
|
+
"data-cs-provider": entry.provider,
|
|
1323
|
+
"data-cs-title": entry.title,
|
|
1324
|
+
"data-cs-live": props.live ? "true" : void 0,
|
|
1325
|
+
"data-cs-active": props.active ? "true" : void 0,
|
|
965
1326
|
children: [
|
|
966
|
-
/* @__PURE__ */ (0,
|
|
1327
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
967
1328
|
"button",
|
|
968
1329
|
{
|
|
969
1330
|
type: "button",
|
|
@@ -975,39 +1336,39 @@ function Row(props) {
|
|
|
975
1336
|
(${entry.originalTitle})` : entry.title
|
|
976
1337
|
}
|
|
977
1338
|
),
|
|
978
|
-
/* @__PURE__ */ (0,
|
|
979
|
-
/* @__PURE__ */ (0,
|
|
980
|
-
renaming ? /* @__PURE__ */ (0,
|
|
981
|
-
/* @__PURE__ */ (0,
|
|
982
|
-
entry.pinned ? /* @__PURE__ */ (0,
|
|
1339
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "pointer-events-none mt-0.5 shrink-0", children: props.live ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 16, className: "text-primary" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProviderMark, { provider: entry.provider, size: 16 }) }),
|
|
1340
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "cs-row__body", children: [
|
|
1341
|
+
renaming ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "pointer-events-auto relative z-10 block", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RenameInput, { initial: entry.title, onDone: rename }) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-center gap-1", children: [
|
|
1342
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "min-w-0 truncate text-[13px] font-medium leading-5", children: entry.title }),
|
|
1343
|
+
entry.pinned ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PinIcon, { size: 11, className: "shrink-0 text-muted-foreground", "aria-label": "Pinned" }) : null
|
|
983
1344
|
] }),
|
|
984
|
-
/* @__PURE__ */ (0,
|
|
985
|
-
props.snippet ? /* @__PURE__ */ (0,
|
|
1345
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "block truncate text-[11.5px] leading-4 text-muted-foreground", children: props.meta }),
|
|
1346
|
+
props.snippet ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "cs-row__snippet", children: props.snippet }) : null
|
|
986
1347
|
] }),
|
|
987
|
-
renaming ? null : /* @__PURE__ */ (0,
|
|
1348
|
+
renaming ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "cs-row__actions", children: [
|
|
988
1349
|
props.takeover,
|
|
989
|
-
/* @__PURE__ */ (0,
|
|
990
|
-
/* @__PURE__ */ (0,
|
|
991
|
-
/* @__PURE__ */ (0,
|
|
1350
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [
|
|
1351
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "cs-icon-button", "aria-label": `More for ${entry.title}`, title: "More", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MoreIcon, { size: 15 }) }) }),
|
|
1352
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuContent, { align: "start", className: "w-60", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatMenuItems, { entry, variant: "dropdown", onRename: () => setRenaming(true) }) })
|
|
992
1353
|
] })
|
|
993
1354
|
] })
|
|
994
1355
|
]
|
|
995
1356
|
}
|
|
996
1357
|
) }),
|
|
997
|
-
/* @__PURE__ */ (0,
|
|
1358
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.ContextMenuContent, { className: "w-60", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatMenuItems, { entry, variant: "context", onRename: () => setRenaming(true) }) })
|
|
998
1359
|
] });
|
|
999
1360
|
}
|
|
1000
1361
|
function SidebarSkeleton() {
|
|
1001
|
-
return /* @__PURE__ */ (0,
|
|
1362
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "space-y-1.5 px-3 py-2", "aria-hidden": "true", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "cs-skeleton h-9 rounded-lg" }, i)) });
|
|
1002
1363
|
}
|
|
1003
1364
|
function Highlight({ text, query }) {
|
|
1004
1365
|
const q = query.trim().toLowerCase();
|
|
1005
1366
|
if (!q) return text;
|
|
1006
1367
|
const at = text.toLowerCase().indexOf(q);
|
|
1007
1368
|
if (at < 0) return text;
|
|
1008
|
-
return /* @__PURE__ */ (0,
|
|
1369
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1009
1370
|
text.slice(0, at),
|
|
1010
|
-
/* @__PURE__ */ (0,
|
|
1371
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("mark", { className: "cs-mark", children: text.slice(at, at + q.length) }),
|
|
1011
1372
|
text.slice(at + q.length)
|
|
1012
1373
|
] });
|
|
1013
1374
|
}
|
|
@@ -1022,10 +1383,10 @@ var EMPTY_SEARCH = {
|
|
|
1022
1383
|
};
|
|
1023
1384
|
function useContentSearch(query) {
|
|
1024
1385
|
const client = useCodingSessionsClient();
|
|
1025
|
-
const [state, setState] = (0,
|
|
1026
|
-
const latest = (0,
|
|
1386
|
+
const [state, setState] = (0, import_react7.useState)(EMPTY_SEARCH);
|
|
1387
|
+
const latest = (0, import_react7.useRef)(query);
|
|
1027
1388
|
latest.current = query;
|
|
1028
|
-
const run = (0,
|
|
1389
|
+
const run = (0, import_react7.useCallback)(
|
|
1029
1390
|
async (q, cursor, append) => {
|
|
1030
1391
|
setState((s) => ({ ...append ? s : EMPTY_SEARCH, query: q, loading: true, error: null }));
|
|
1031
1392
|
try {
|
|
@@ -1047,7 +1408,7 @@ function useContentSearch(query) {
|
|
|
1047
1408
|
},
|
|
1048
1409
|
[client]
|
|
1049
1410
|
);
|
|
1050
|
-
(0,
|
|
1411
|
+
(0, import_react7.useEffect)(() => {
|
|
1051
1412
|
const q = query.trim();
|
|
1052
1413
|
if (q.length < 2) {
|
|
1053
1414
|
setState(EMPTY_SEARCH);
|
|
@@ -1056,7 +1417,7 @@ function useContentSearch(query) {
|
|
|
1056
1417
|
const timer = setTimeout(() => void run(q, 0, false), 350);
|
|
1057
1418
|
return () => clearTimeout(timer);
|
|
1058
1419
|
}, [query, run]);
|
|
1059
|
-
const more = (0,
|
|
1420
|
+
const more = (0, import_react7.useCallback)(() => {
|
|
1060
1421
|
if (state.nextCursor !== null && !state.loading) void run(state.query, state.nextCursor, true);
|
|
1061
1422
|
}, [run, state.nextCursor, state.loading, state.query]);
|
|
1062
1423
|
return [state, more];
|
|
@@ -1076,19 +1437,19 @@ function Sidebar(props) {
|
|
|
1076
1437
|
const client = useCodingSessionsClient();
|
|
1077
1438
|
const state = useCodingSessionsState();
|
|
1078
1439
|
const now = useMinuteClock();
|
|
1079
|
-
const [query, setQuery] = (0,
|
|
1440
|
+
const [query, setQuery] = (0, import_react7.useState)("");
|
|
1080
1441
|
const [search, searchMore] = useContentSearch(query);
|
|
1081
|
-
const [groupMode, setGroupMode] = (0,
|
|
1082
|
-
const [showHidden, setShowHidden] = (0,
|
|
1083
|
-
const [takingOver, setTakingOver] = (0,
|
|
1084
|
-
const [takeoverError, setTakeoverError] = (0,
|
|
1442
|
+
const [groupMode, setGroupMode] = (0, import_react7.useState)(() => readLocal("coding-sessions.group", ["date", "folder"], "date"));
|
|
1443
|
+
const [showHidden, setShowHidden] = (0, import_react7.useState)(false);
|
|
1444
|
+
const [takingOver, setTakingOver] = (0, import_react7.useState)(null);
|
|
1445
|
+
const [takeoverError, setTakeoverError] = (0, import_react7.useState)(null);
|
|
1085
1446
|
const prefs = state.preferences;
|
|
1086
1447
|
const sessions = state.sessions.data;
|
|
1087
1448
|
const isLive = (id) => {
|
|
1088
1449
|
const run = state.runs[id];
|
|
1089
1450
|
return run !== void 0 && !isTerminalRunStatus(run.status);
|
|
1090
1451
|
};
|
|
1091
|
-
const { ours, others, hiddenCount } = (0,
|
|
1452
|
+
const { ours, others, hiddenCount } = (0, import_react7.useMemo)(() => {
|
|
1092
1453
|
const oursList = sessions.map((s) => sessionEntry(s, prefs));
|
|
1093
1454
|
const known = new Set(sessions.map((s) => s.providerSessionId).filter(Boolean));
|
|
1094
1455
|
const othersList = state.discovered.data.filter((d) => !known.has(d.providerSessionId)).map((d) => discoveredEntry(d, prefs));
|
|
@@ -1128,8 +1489,8 @@ function Sidebar(props) {
|
|
|
1128
1489
|
let meta;
|
|
1129
1490
|
if (live) meta = `${PROVIDER_LABEL[entry.provider]} is working\u2026`;
|
|
1130
1491
|
else if (d?.activeElsewhere)
|
|
1131
|
-
meta = /* @__PURE__ */ (0,
|
|
1132
|
-
/* @__PURE__ */ (0,
|
|
1492
|
+
meta = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "cs-live-elsewhere", children: [
|
|
1493
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "cs-live-dot", "aria-hidden": "true" }),
|
|
1133
1494
|
"Running in ",
|
|
1134
1495
|
PROVIDER_LABEL[entry.provider]
|
|
1135
1496
|
] });
|
|
@@ -1138,8 +1499,8 @@ function Sidebar(props) {
|
|
|
1138
1499
|
const where = entry.cwd ? prettyPath2(entry.cwd) : "unknown folder";
|
|
1139
1500
|
meta = `${status}${entry.kind === "discovered" ? `${PROVIDER_LABEL[entry.provider]} \xB7 ` : ""}${groupMode === "folder" && !extra ? "" : `${where} \xB7 `}${relativeTime(entry.updatedAt, now)}`;
|
|
1140
1501
|
}
|
|
1141
|
-
return /* @__PURE__ */ (0,
|
|
1142
|
-
/* @__PURE__ */ (0,
|
|
1502
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
1503
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1143
1504
|
Row,
|
|
1144
1505
|
{
|
|
1145
1506
|
entry,
|
|
@@ -1148,7 +1509,7 @@ function Sidebar(props) {
|
|
|
1148
1509
|
live,
|
|
1149
1510
|
meta,
|
|
1150
1511
|
snippet: extra?.snippet,
|
|
1151
|
-
takeover: d?.cwd ? /* @__PURE__ */ (0,
|
|
1512
|
+
takeover: d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1152
1513
|
"button",
|
|
1153
1514
|
{
|
|
1154
1515
|
type: "button",
|
|
@@ -1157,18 +1518,18 @@ function Sidebar(props) {
|
|
|
1157
1518
|
title: d.activeElsewhere ? d.activeElsewhere.message : "Continue this chat here",
|
|
1158
1519
|
disabled: takingOver === d.providerSessionId,
|
|
1159
1520
|
children: [
|
|
1160
|
-
takingOver === d.providerSessionId ? /* @__PURE__ */ (0,
|
|
1521
|
+
takingOver === d.providerSessionId ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 11 }) : null,
|
|
1161
1522
|
"Take over"
|
|
1162
1523
|
]
|
|
1163
1524
|
}
|
|
1164
1525
|
) : null
|
|
1165
1526
|
}
|
|
1166
1527
|
),
|
|
1167
|
-
takeoverError && d && takeoverError.id === d.providerSessionId ? /* @__PURE__ */ (0,
|
|
1528
|
+
takeoverError && d && takeoverError.id === d.providerSessionId ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-4 mb-1 text-[11.5px] text-destructive", children: takeoverError.message }) : null
|
|
1168
1529
|
] }, entry.key);
|
|
1169
1530
|
};
|
|
1170
|
-
const renderGroups = (entries) => groupEntries(entries, groupMode, now).map((group) => /* @__PURE__ */ (0,
|
|
1171
|
-
/* @__PURE__ */ (0,
|
|
1531
|
+
const renderGroups = (entries) => groupEntries(entries, groupMode, now).map((group) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "group", "aria-label": group.label, children: [
|
|
1532
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(GroupLabel, { children: group.label }),
|
|
1172
1533
|
group.entries.map((e) => renderEntry(e))
|
|
1173
1534
|
] }, group.label));
|
|
1174
1535
|
const searching = query.trim().length > 0;
|
|
@@ -1185,60 +1546,60 @@ function Sidebar(props) {
|
|
|
1185
1546
|
props.onFound(hitToDiscovered(hit));
|
|
1186
1547
|
props.select({ kind: "discovered", provider: hit.provider, id: hit.providerSessionId });
|
|
1187
1548
|
};
|
|
1188
|
-
const searchBody = /* @__PURE__ */ (0,
|
|
1189
|
-
/* @__PURE__ */ (0,
|
|
1190
|
-
titleMatches.length === 0 ? /* @__PURE__ */ (0,
|
|
1191
|
-
/* @__PURE__ */ (0,
|
|
1192
|
-
query.trim().length < 2 ? /* @__PURE__ */ (0,
|
|
1549
|
+
const searchBody = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1550
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Chats" }),
|
|
1551
|
+
titleMatches.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] text-muted-foreground", children: "No listed chat has that in its name or folder." }) : titleMatches.map((e) => renderEntry(e, { query })),
|
|
1552
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "In conversations" }),
|
|
1553
|
+
query.trim().length < 2 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] text-muted-foreground", children: "Type at least two letters to search what was said." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1193
1554
|
contentHits.map((hit) => {
|
|
1194
1555
|
const known = allByKey.get(chatKey(hit.provider, hit.providerSessionId));
|
|
1195
1556
|
const entry = known ?? discoveredEntry(hitToDiscovered(hit), prefs);
|
|
1196
|
-
return /* @__PURE__ */ (0,
|
|
1557
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { onClickCapture: known ? void 0 : () => props.onFound(hitToDiscovered(hit)), children: renderEntry(entry, {
|
|
1197
1558
|
query,
|
|
1198
|
-
snippet: hit.snippet ? /* @__PURE__ */ (0,
|
|
1559
|
+
snippet: hit.snippet ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Highlight, { text: hit.snippet, query }) : void 0
|
|
1199
1560
|
}) }, `hit:${entry.key}`);
|
|
1200
1561
|
}),
|
|
1201
|
-
/* @__PURE__ */ (0,
|
|
1562
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-4 py-2 text-[11.5px] leading-4 text-muted-foreground", role: "status", "aria-live": "polite", children: search.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-destructive", children: [
|
|
1202
1563
|
"Search stopped: ",
|
|
1203
1564
|
search.error
|
|
1204
|
-
] }) : search.loading ? /* @__PURE__ */ (0,
|
|
1205
|
-
/* @__PURE__ */ (0,
|
|
1565
|
+
] }) : search.loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
1566
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 12 }),
|
|
1206
1567
|
" Searching your chats\u2026"
|
|
1207
|
-
] }) : search.query ? /* @__PURE__ */ (0,
|
|
1568
|
+
] }) : search.query ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1208
1569
|
contentHits.length === 0 && search.hits.length === 0 ? "Nothing found. " : null,
|
|
1209
1570
|
search.nextCursor === null ? `Searched all ${search.total.toLocaleString()} chats on this computer.` : `Searched the ${search.scanned.toLocaleString()} most recent of ${search.total.toLocaleString()} chats.`,
|
|
1210
|
-
search.nextCursor !== null ? /* @__PURE__ */ (0,
|
|
1571
|
+
search.nextCursor !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "cs-link ml-1", onClick: searchMore, children: "Search older chats" }) : null
|
|
1211
1572
|
] }) : null })
|
|
1212
1573
|
] })
|
|
1213
1574
|
] });
|
|
1214
|
-
const listBody = /* @__PURE__ */ (0,
|
|
1215
|
-
pinned.length > 0 ? /* @__PURE__ */ (0,
|
|
1216
|
-
/* @__PURE__ */ (0,
|
|
1575
|
+
const listBody = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1576
|
+
pinned.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1577
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Pinned" }),
|
|
1217
1578
|
pinned.map((e) => renderEntry(e))
|
|
1218
1579
|
] }) : null,
|
|
1219
|
-
running.length > 0 ? /* @__PURE__ */ (0,
|
|
1220
|
-
/* @__PURE__ */ (0,
|
|
1580
|
+
running.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1581
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Running" }),
|
|
1221
1582
|
running.map((e) => renderEntry(e))
|
|
1222
1583
|
] }) : null,
|
|
1223
|
-
/* @__PURE__ */ (0,
|
|
1224
|
-
state.sessions.loading && state.sessions.loadedAt === null ? /* @__PURE__ */ (0,
|
|
1225
|
-
/* @__PURE__ */ (0,
|
|
1584
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Recent" }),
|
|
1585
|
+
state.sessions.loading && state.sessions.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SidebarSkeleton, {}) : state.sessions.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] text-destructive", children: state.sessions.error }) : recent.length === 0 ? running.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] leading-5 text-muted-foreground", children: "Sessions you start or take over here will appear here." }) : null : recent.map((e) => renderEntry(e)),
|
|
1586
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1226
1587
|
SectionLabel,
|
|
1227
1588
|
{
|
|
1228
|
-
action: /* @__PURE__ */ (0,
|
|
1229
|
-
/* @__PURE__ */ (0,
|
|
1230
|
-
/* @__PURE__ */ (0,
|
|
1231
|
-
/* @__PURE__ */ (0,
|
|
1232
|
-
/* @__PURE__ */ (0,
|
|
1233
|
-
/* @__PURE__ */ (0,
|
|
1234
|
-
/* @__PURE__ */ (0,
|
|
1235
|
-
/* @__PURE__ */ (0,
|
|
1589
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-center gap-0.5", children: [
|
|
1590
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DropdownMenu, { children: [
|
|
1591
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "cs-icon-button cs-icon-button--text", "aria-label": "How to list your other chats", children: groupMode === "date" ? "By date" : "By folder" }) }),
|
|
1592
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DropdownMenuContent, { align: "end", className: "w-52", children: [
|
|
1593
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuLabel, { children: "Group your other chats" }),
|
|
1594
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.DropdownMenuRadioGroup, { value: groupMode, onValueChange: (v) => setMode(v), children: [
|
|
1595
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuRadioItem, { value: "date", children: "By date" }),
|
|
1596
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuRadioItem, { value: "folder", children: "By folder" })
|
|
1236
1597
|
] }),
|
|
1237
|
-
/* @__PURE__ */ (0,
|
|
1238
|
-
/* @__PURE__ */ (0,
|
|
1598
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuSeparator, {}),
|
|
1599
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system5.DropdownMenuItem, { onSelect: () => setShowHidden((v) => !v), children: showHidden ? "Leave hidden chats out" : `Show hidden chats${hiddenCount ? ` (${hiddenCount})` : ""}` })
|
|
1239
1600
|
] })
|
|
1240
1601
|
] }),
|
|
1241
|
-
/* @__PURE__ */ (0,
|
|
1602
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1242
1603
|
"button",
|
|
1243
1604
|
{
|
|
1244
1605
|
type: "button",
|
|
@@ -1246,17 +1607,17 @@ function Sidebar(props) {
|
|
|
1246
1607
|
onClick: () => void client.refreshDiscovered(),
|
|
1247
1608
|
"aria-label": "Look again for your other chats",
|
|
1248
1609
|
title: "Look again",
|
|
1249
|
-
children: state.discovered.loading ? /* @__PURE__ */ (0,
|
|
1610
|
+
children: state.discovered.loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RefreshIcon, { size: 13 })
|
|
1250
1611
|
}
|
|
1251
1612
|
)
|
|
1252
1613
|
] }),
|
|
1253
1614
|
children: "Your other chats"
|
|
1254
1615
|
}
|
|
1255
1616
|
),
|
|
1256
|
-
state.discovered.loading && state.discovered.loadedAt === null ? /* @__PURE__ */ (0,
|
|
1617
|
+
state.discovered.loading && state.discovered.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SidebarSkeleton, {}) : state.discovered.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] text-destructive", children: state.discovered.error }) : otherList.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "px-4 py-1 text-[12px] leading-5 text-muted-foreground", children: others.length > 0 ? "Every chat found here is pinned or hidden." : "No other Claude Code or Codex chats were found on this computer." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1257
1618
|
renderGroups(otherList),
|
|
1258
|
-
state.discovered.data.length >= state.discoveredLimit ? /* @__PURE__ */ (0,
|
|
1259
|
-
|
|
1619
|
+
state.discovered.data.length >= state.discoveredLimit ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-3 pt-2", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1620
|
+
import_design_system5.Button,
|
|
1260
1621
|
{
|
|
1261
1622
|
variant: "ghost",
|
|
1262
1623
|
size: "sm",
|
|
@@ -1264,32 +1625,32 @@ function Sidebar(props) {
|
|
|
1264
1625
|
onClick: () => void client.showMoreDiscovered(),
|
|
1265
1626
|
disabled: state.discovered.loading,
|
|
1266
1627
|
children: [
|
|
1267
|
-
state.discovered.loading ? /* @__PURE__ */ (0,
|
|
1628
|
+
state.discovered.loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SpinnerIcon, { size: 13 }) : null,
|
|
1268
1629
|
"Show older chats"
|
|
1269
1630
|
]
|
|
1270
1631
|
}
|
|
1271
1632
|
) }) : null
|
|
1272
1633
|
] }),
|
|
1273
|
-
showHidden ? null : hiddenCount > 0 ? /* @__PURE__ */ (0,
|
|
1634
|
+
showHidden ? null : hiddenCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { type: "button", className: "cs-link mx-4 mt-3 text-[11.5px]", onClick: () => setShowHidden(true), children: [
|
|
1274
1635
|
hiddenCount,
|
|
1275
1636
|
" hidden ",
|
|
1276
1637
|
hiddenCount === 1 ? "chat" : "chats",
|
|
1277
1638
|
" \u2014 show"
|
|
1278
1639
|
] }) : null
|
|
1279
1640
|
] });
|
|
1280
|
-
return /* @__PURE__ */ (0,
|
|
1641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1281
1642
|
"aside",
|
|
1282
1643
|
{
|
|
1283
|
-
className: "cs-sidebar flex h-full shrink-0 flex-col border-r border-border bg-
|
|
1644
|
+
className: "cs-sidebar flex h-full shrink-0 flex-col border-r border-border bg-sidebar-background",
|
|
1284
1645
|
style: { width: props.width },
|
|
1285
1646
|
"aria-label": "Sessions",
|
|
1286
1647
|
children: [
|
|
1287
|
-
/* @__PURE__ */ (0,
|
|
1288
|
-
/* @__PURE__ */ (0,
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1648
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between gap-2 px-4 pb-2 pt-3.5", children: [
|
|
1649
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
1650
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "cs-app-mark", "aria-hidden": "true" }),
|
|
1651
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate text-[14px] font-semibold tracking-[-0.01em]", children: "Coding sessions" })
|
|
1291
1652
|
] }),
|
|
1292
|
-
/* @__PURE__ */ (0,
|
|
1653
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1293
1654
|
"button",
|
|
1294
1655
|
{
|
|
1295
1656
|
type: "button",
|
|
@@ -1297,19 +1658,19 @@ function Sidebar(props) {
|
|
|
1297
1658
|
onClick: props.onCollapse,
|
|
1298
1659
|
"aria-label": "Hide the sidebar (\u2318B)",
|
|
1299
1660
|
title: "Hide sidebar \u2318B",
|
|
1300
|
-
children: /* @__PURE__ */ (0,
|
|
1661
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SidebarIcon, { size: 15 })
|
|
1301
1662
|
}
|
|
1302
1663
|
)
|
|
1303
1664
|
] }),
|
|
1304
|
-
/* @__PURE__ */ (0,
|
|
1305
|
-
/* @__PURE__ */ (0,
|
|
1306
|
-
/* @__PURE__ */ (0,
|
|
1665
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-1.5 px-3 pb-1", children: [
|
|
1666
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system5.Button, { className: "w-full justify-start gap-2", variant: "outline", size: "sm", onClick: props.onNew, children: [
|
|
1667
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PlusIcon, { size: 15 }),
|
|
1307
1668
|
"New session",
|
|
1308
|
-
/* @__PURE__ */ (0,
|
|
1669
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("kbd", { className: "cs-kbd ml-auto", children: "\u2325\u2318N" })
|
|
1309
1670
|
] }),
|
|
1310
|
-
/* @__PURE__ */ (0,
|
|
1311
|
-
/* @__PURE__ */ (0,
|
|
1312
|
-
/* @__PURE__ */ (0,
|
|
1671
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "cs-search", children: [
|
|
1672
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SearchIcon, { size: 14, className: "cs-search__icon" }),
|
|
1673
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1313
1674
|
"input",
|
|
1314
1675
|
{
|
|
1315
1676
|
ref: props.searchRef,
|
|
@@ -1335,10 +1696,10 @@ function Sidebar(props) {
|
|
|
1335
1696
|
className: "cs-search__input"
|
|
1336
1697
|
}
|
|
1337
1698
|
),
|
|
1338
|
-
query ? /* @__PURE__ */ (0,
|
|
1699
|
+
query ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "cs-icon-button cs-search__clear", onClick: () => setQuery(""), "aria-label": "Clear search", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CloseIcon, { size: 13 }) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("kbd", { className: "cs-search__kbd", children: "\u2318K" })
|
|
1339
1700
|
] })
|
|
1340
1701
|
] }),
|
|
1341
|
-
/* @__PURE__ */ (0,
|
|
1702
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("nav", { className: "min-h-0 flex-1 overflow-y-auto pb-3", children: searching ? searchBody : listBody }),
|
|
1342
1703
|
props.footer
|
|
1343
1704
|
]
|
|
1344
1705
|
}
|
|
@@ -1882,12 +2243,13 @@ var CodingSessionsClient = class {
|
|
|
1882
2243
|
start(input) {
|
|
1883
2244
|
return this.transport.call("start", input);
|
|
1884
2245
|
}
|
|
1885
|
-
takeover(session) {
|
|
2246
|
+
takeover(session, agent) {
|
|
1886
2247
|
return this.transport.call("takeover", {
|
|
1887
2248
|
provider: session.provider,
|
|
1888
2249
|
providerSessionId: session.providerSessionId,
|
|
1889
2250
|
cwd: session.cwd ?? "",
|
|
1890
|
-
title: session.title
|
|
2251
|
+
title: session.title,
|
|
2252
|
+
...agent ? { agent } : {}
|
|
1891
2253
|
});
|
|
1892
2254
|
}
|
|
1893
2255
|
send(sessionId, prompt) {
|
|
@@ -1929,13 +2291,13 @@ function firstInvalidField(errors) {
|
|
|
1929
2291
|
}
|
|
1930
2292
|
|
|
1931
2293
|
// src/react/app.tsx
|
|
1932
|
-
var
|
|
2294
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1933
2295
|
function CodingSessionsProvider({ transport, children }) {
|
|
1934
|
-
const [client] = (0,
|
|
1935
|
-
(0,
|
|
2296
|
+
const [client] = (0, import_react8.useState)(() => new CodingSessionsClient(transport));
|
|
2297
|
+
(0, import_react8.useEffect)(() => {
|
|
1936
2298
|
if (transport.status().state === "open") void client.refreshAll();
|
|
1937
2299
|
}, [client, transport]);
|
|
1938
|
-
return /* @__PURE__ */ (0,
|
|
2300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CodingSessionsContext.Provider, { value: client, children });
|
|
1939
2301
|
}
|
|
1940
2302
|
function readHash() {
|
|
1941
2303
|
if (typeof location === "undefined") return { kind: "none" };
|
|
@@ -1958,8 +2320,8 @@ function readTheme() {
|
|
|
1958
2320
|
}
|
|
1959
2321
|
}
|
|
1960
2322
|
function useTheme() {
|
|
1961
|
-
const [choice, setChoice] = (0,
|
|
1962
|
-
(0,
|
|
2323
|
+
const [choice, setChoice] = (0, import_react8.useState)(readTheme);
|
|
2324
|
+
(0, import_react8.useEffect)(() => {
|
|
1963
2325
|
const media = typeof window.matchMedia === "function" ? window.matchMedia("(prefers-color-scheme: dark)") : null;
|
|
1964
2326
|
const apply = () => {
|
|
1965
2327
|
const dark = choice === "dark" || choice === "system" && media?.matches === true;
|
|
@@ -1970,7 +2332,7 @@ function useTheme() {
|
|
|
1970
2332
|
media?.addEventListener("change", apply);
|
|
1971
2333
|
return () => media?.removeEventListener("change", apply);
|
|
1972
2334
|
}, [choice]);
|
|
1973
|
-
const set = (0,
|
|
2335
|
+
const set = (0, import_react8.useCallback)((next) => {
|
|
1974
2336
|
setChoice(next);
|
|
1975
2337
|
try {
|
|
1976
2338
|
localStorage.setItem("coding-sessions.theme", next);
|
|
@@ -1989,8 +2351,8 @@ var RUN_LABEL = {
|
|
|
1989
2351
|
function RunPill({ run }) {
|
|
1990
2352
|
if (!run) return null;
|
|
1991
2353
|
const live = !isTerminalRunStatus(run.status);
|
|
1992
|
-
return /* @__PURE__ */ (0,
|
|
1993
|
-
live ? /* @__PURE__ */ (0,
|
|
2354
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: (0, import_design_system6.cn)("cs-pill", `cs-pill--${run.status}`), children: [
|
|
2355
|
+
live ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "cs-pill__dot", "aria-hidden": "true" }) : null,
|
|
1994
2356
|
RUN_LABEL[run.status]
|
|
1995
2357
|
] });
|
|
1996
2358
|
}
|
|
@@ -1998,17 +2360,17 @@ function ConnectionBanner() {
|
|
|
1998
2360
|
const { connection } = useCodingSessionsState();
|
|
1999
2361
|
if (connection.state === "open") return null;
|
|
2000
2362
|
const closed = connection.state === "closed";
|
|
2001
|
-
return /* @__PURE__ */ (0,
|
|
2363
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2002
2364
|
"div",
|
|
2003
2365
|
{
|
|
2004
2366
|
role: "status",
|
|
2005
|
-
className: (0,
|
|
2367
|
+
className: (0, import_design_system6.cn)(
|
|
2006
2368
|
"flex items-center gap-2 border-b px-4 py-2 text-[13px]",
|
|
2007
2369
|
closed ? "border-destructive/30 bg-destructive/10 text-destructive" : "border-border bg-muted/60 text-muted-foreground"
|
|
2008
2370
|
),
|
|
2009
2371
|
children: [
|
|
2010
|
-
closed ? /* @__PURE__ */ (0,
|
|
2011
|
-
/* @__PURE__ */ (0,
|
|
2372
|
+
closed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 14 }),
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: closed ? connection.reason : "Connecting to the coding sessions host\u2026" })
|
|
2012
2374
|
]
|
|
2013
2375
|
}
|
|
2014
2376
|
);
|
|
@@ -2018,22 +2380,22 @@ function ProvidersFooter(props) {
|
|
|
2018
2380
|
const client = useCodingSessionsClient();
|
|
2019
2381
|
const next = { system: "light", light: "dark", dark: "system" };
|
|
2020
2382
|
const themeLabel = { system: "Match system", light: "Light", dark: "Dark" };
|
|
2021
|
-
return /* @__PURE__ */ (0,
|
|
2022
|
-
/* @__PURE__ */ (0,
|
|
2383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "border-t border-border px-3 py-2.5", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
2384
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex min-w-0 flex-1 flex-wrap gap-1.5", children: state.providers.loading && state.providers.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[11.5px] text-muted-foreground", children: "Checking Claude Code and Codex\u2026" }) : state.providers.data.map((p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2023
2385
|
"span",
|
|
2024
2386
|
{
|
|
2025
|
-
className: (0,
|
|
2387
|
+
className: (0, import_design_system6.cn)("cs-provider-chip", p.ready ? "" : "cs-provider-chip--problem"),
|
|
2026
2388
|
title: p.problem ? `${p.problem} ${p.fix ?? ""}` : [binaryWords(p) ?? p.label, p.plan, newerWords(p)].filter(Boolean).join(" \xB7 "),
|
|
2027
2389
|
children: [
|
|
2028
|
-
/* @__PURE__ */ (0,
|
|
2390
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProviderMark, { provider: p.provider, size: 13 }),
|
|
2029
2391
|
p.label,
|
|
2030
|
-
p.lastProblem ? /* @__PURE__ */ (0,
|
|
2031
|
-
p.ready ? /* @__PURE__ */ (0,
|
|
2392
|
+
p.lastProblem ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "cs-provider-chip__note", children: p.lastProblem.kind === "signed-out" ? "\xB7 sign in again" : `\xB7 limit${formatUntil(p.lastProblem.until) ? ` until ${formatUntil(p.lastProblem.until)}` : ""}` }) : null,
|
|
2393
|
+
p.ready ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckIcon, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 12 })
|
|
2032
2394
|
]
|
|
2033
2395
|
},
|
|
2034
2396
|
p.provider
|
|
2035
2397
|
)) }),
|
|
2036
|
-
/* @__PURE__ */ (0,
|
|
2398
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2037
2399
|
"button",
|
|
2038
2400
|
{
|
|
2039
2401
|
type: "button",
|
|
@@ -2041,11 +2403,11 @@ function ProvidersFooter(props) {
|
|
|
2041
2403
|
onClick: () => void client.refreshProviders(),
|
|
2042
2404
|
"aria-label": "Check Claude Code and Codex again",
|
|
2043
2405
|
title: "Check again",
|
|
2044
|
-
children: state.providers.loading ? /* @__PURE__ */ (0,
|
|
2406
|
+
children: state.providers.loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RefreshIcon, { size: 13 })
|
|
2045
2407
|
}
|
|
2046
2408
|
),
|
|
2047
2409
|
props.extra,
|
|
2048
|
-
/* @__PURE__ */ (0,
|
|
2410
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2049
2411
|
"button",
|
|
2050
2412
|
{
|
|
2051
2413
|
type: "button",
|
|
@@ -2053,14 +2415,14 @@ function ProvidersFooter(props) {
|
|
|
2053
2415
|
onClick: () => props.setTheme(next[props.theme]),
|
|
2054
2416
|
"aria-label": `Theme: ${themeLabel[props.theme]}. Switch to ${themeLabel[next[props.theme]]}.`,
|
|
2055
2417
|
title: `Theme: ${themeLabel[props.theme]}`,
|
|
2056
|
-
children: props.theme === "system" ? /* @__PURE__ */ (0,
|
|
2418
|
+
children: props.theme === "system" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MonitorIcon, { size: 14 }) : props.theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SunIcon, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MoonIcon, { size: 14 })
|
|
2057
2419
|
}
|
|
2058
2420
|
)
|
|
2059
2421
|
] }) });
|
|
2060
2422
|
}
|
|
2061
2423
|
function useNotifier() {
|
|
2062
|
-
const show = (0,
|
|
2063
|
-
return (0,
|
|
2424
|
+
const show = (0, import_react8.useContext)(ToastContext);
|
|
2425
|
+
return (0, import_react8.useMemo)(
|
|
2064
2426
|
() => ({
|
|
2065
2427
|
notify(event) {
|
|
2066
2428
|
show(event.message);
|
|
@@ -2071,8 +2433,8 @@ function useNotifier() {
|
|
|
2071
2433
|
}
|
|
2072
2434
|
function useLiveElsewhere(provider, providerSessionId, initial = null) {
|
|
2073
2435
|
const client = useCodingSessionsClient();
|
|
2074
|
-
const [state, setState] = (0,
|
|
2075
|
-
(0,
|
|
2436
|
+
const [state, setState] = (0, import_react8.useState)(initial);
|
|
2437
|
+
(0, import_react8.useEffect)(() => {
|
|
2076
2438
|
if (!provider || !providerSessionId) {
|
|
2077
2439
|
setState(null);
|
|
2078
2440
|
return;
|
|
@@ -2092,8 +2454,8 @@ function useLiveElsewhere(provider, providerSessionId, initial = null) {
|
|
|
2092
2454
|
}
|
|
2093
2455
|
function useSessionUsage(sessionId, lastRunKey) {
|
|
2094
2456
|
const client = useCodingSessionsClient();
|
|
2095
|
-
const [usage, setUsage] = (0,
|
|
2096
|
-
(0,
|
|
2457
|
+
const [usage, setUsage] = (0, import_react8.useState)(null);
|
|
2458
|
+
(0, import_react8.useEffect)(() => {
|
|
2097
2459
|
let cancelled = false;
|
|
2098
2460
|
void client.transport.call("listRuns", sessionId).then((runs) => {
|
|
2099
2461
|
if (cancelled) return;
|
|
@@ -2114,18 +2476,18 @@ function useSessionUsage(sessionId, lastRunKey) {
|
|
|
2114
2476
|
return usage;
|
|
2115
2477
|
}
|
|
2116
2478
|
function HeaderMenu(props) {
|
|
2117
|
-
return /* @__PURE__ */ (0,
|
|
2118
|
-
/* @__PURE__ */ (0,
|
|
2119
|
-
/* @__PURE__ */ (0,
|
|
2479
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DropdownMenu, { children: [
|
|
2480
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "cs-icon-button", "aria-label": "More for this chat", title: "More", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MoreIcon, { size: 16 }) }) }),
|
|
2481
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.DropdownMenuContent, { align: "end", className: "w-64", onCloseAutoFocus: (e) => e.preventDefault(), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChatMenuItems, { entry: props.entry, variant: "dropdown", onRename: props.onRename }) })
|
|
2120
2482
|
] });
|
|
2121
2483
|
}
|
|
2122
2484
|
function HeaderTitle(props) {
|
|
2123
2485
|
const client = useCodingSessionsClient();
|
|
2124
|
-
const show = (0,
|
|
2125
|
-
const [value, setValue] = (0,
|
|
2126
|
-
(0,
|
|
2127
|
-
const inputRef = (0,
|
|
2128
|
-
(0,
|
|
2486
|
+
const show = (0, import_react8.useContext)(ToastContext);
|
|
2487
|
+
const [value, setValue] = (0, import_react8.useState)(props.entry.title);
|
|
2488
|
+
(0, import_react8.useEffect)(() => setValue(props.entry.title), [props.entry.title, props.renaming]);
|
|
2489
|
+
const inputRef = (0, import_react8.useRef)(null);
|
|
2490
|
+
(0, import_react8.useEffect)(() => {
|
|
2129
2491
|
if (!props.renaming) return;
|
|
2130
2492
|
const timer = setTimeout(() => {
|
|
2131
2493
|
const input = inputRef.current;
|
|
@@ -2137,7 +2499,7 @@ function HeaderTitle(props) {
|
|
|
2137
2499
|
return () => clearTimeout(timer);
|
|
2138
2500
|
}, [props.renaming]);
|
|
2139
2501
|
if (!props.renaming) {
|
|
2140
|
-
return /* @__PURE__ */ (0,
|
|
2502
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2141
2503
|
"h1",
|
|
2142
2504
|
{
|
|
2143
2505
|
className: "truncate text-[15px] font-semibold leading-5 tracking-[-0.01em]",
|
|
@@ -2154,7 +2516,7 @@ function HeaderTitle(props) {
|
|
|
2154
2516
|
const next = title === "" || title === props.entry.originalTitle ? null : title;
|
|
2155
2517
|
client.setPreference(props.entry.key, { title: next }).catch((error) => show(`The new name didn't save: ${error instanceof Error ? error.message : String(error)}`));
|
|
2156
2518
|
};
|
|
2157
|
-
return /* @__PURE__ */ (0,
|
|
2519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2158
2520
|
"input",
|
|
2159
2521
|
{
|
|
2160
2522
|
ref: inputRef,
|
|
@@ -2173,9 +2535,9 @@ function HeaderTitle(props) {
|
|
|
2173
2535
|
);
|
|
2174
2536
|
}
|
|
2175
2537
|
function LongChatNote(props) {
|
|
2176
|
-
return /* @__PURE__ */ (0,
|
|
2538
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "mx-auto mt-3 flex items-center gap-2 text-[12px] text-muted-foreground", children: [
|
|
2177
2539
|
"This chat is very long \u2014 showing its most recent part.",
|
|
2178
|
-
/* @__PURE__ */ (0,
|
|
2540
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "cs-link", onClick: props.onEarlier, disabled: props.loading, children: props.loading ? "Reading\u2026" : "Show earlier" })
|
|
2179
2541
|
] });
|
|
2180
2542
|
}
|
|
2181
2543
|
function binaryWords(p) {
|
|
@@ -2188,7 +2550,7 @@ function newerWords(p) {
|
|
|
2188
2550
|
function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
2189
2551
|
const client = useCodingSessionsClient();
|
|
2190
2552
|
const state = useCodingSessionsState();
|
|
2191
|
-
const show = (0,
|
|
2553
|
+
const show = (0, import_react8.useContext)(ToastContext);
|
|
2192
2554
|
const transcript = useSessionTranscript(session.id);
|
|
2193
2555
|
const run = state.runs[session.id];
|
|
2194
2556
|
const live = run !== void 0 && !isTerminalRunStatus(run.status);
|
|
@@ -2197,8 +2559,8 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2197
2559
|
const blocked = provider && (!provider.installed || !provider.loggedIn) ? provider : null;
|
|
2198
2560
|
const limited = !blocked && provider?.lastProblem ? provider : null;
|
|
2199
2561
|
const modelRefused = run?.status === "failed" && isModelUnavailable(run.error);
|
|
2200
|
-
const [stopping, setStopping] = (0,
|
|
2201
|
-
const [renaming, setRenaming] = (0,
|
|
2562
|
+
const [stopping, setStopping] = (0, import_react8.useState)(false);
|
|
2563
|
+
const [renaming, setRenaming] = (0, import_react8.useState)(false);
|
|
2202
2564
|
const elsewhere = useLiveElsewhere(
|
|
2203
2565
|
session.origin === "takeover" && !live ? session.provider : null,
|
|
2204
2566
|
session.providerSessionId
|
|
@@ -2207,7 +2569,7 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2207
2569
|
const messages = transcript.thread.getSnapshot().messages;
|
|
2208
2570
|
const files = useChangedFiles(messages);
|
|
2209
2571
|
const usage = useSessionUsage(session.id, `${run?.runId ?? ""}:${run?.status ?? ""}`);
|
|
2210
|
-
(0,
|
|
2572
|
+
(0, import_react8.useEffect)(() => {
|
|
2211
2573
|
if (!live) setStopping(false);
|
|
2212
2574
|
}, [live]);
|
|
2213
2575
|
const stop = async () => {
|
|
@@ -2220,16 +2582,16 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2220
2582
|
};
|
|
2221
2583
|
const usageWords = usage ? `${(0, import_format3.formatCount)(usage.tokens, { style: "compact" })} tokens${usage.cost !== null ? ` \xB7 ${(0, import_format3.formatUsd)(usage.cost)}` : ""}` : null;
|
|
2222
2584
|
const usageTitle = usage ? `${(0, import_format3.formatCount)(usage.tokens)} tokens over ${usage.runs} ${usage.runs === 1 ? "message" : "messages"} sent from here.` + (usage.cost !== null ? usage.billing === "subscription" ? ` ${(0, import_format3.formatUsd)(usage.cost)} is what this would cost at API prices \u2014 it's covered by your ${provider?.plan ?? ""} plan.`.replace(" ", " ") : ` Billed ${(0, import_format3.formatUsd)(usage.cost)} to your API key.` : "") : "";
|
|
2223
|
-
return /* @__PURE__ */ (0,
|
|
2224
|
-
/* @__PURE__ */ (0,
|
|
2225
|
-
/* @__PURE__ */ (0,
|
|
2226
|
-
/* @__PURE__ */ (0,
|
|
2227
|
-
/* @__PURE__ */ (0,
|
|
2228
|
-
/* @__PURE__ */ (0,
|
|
2229
|
-
/* @__PURE__ */ (0,
|
|
2230
|
-
/* @__PURE__ */ (0,
|
|
2231
|
-
/* @__PURE__ */ (0,
|
|
2232
|
-
/* @__PURE__ */ (0,
|
|
2585
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 flex-1", children: [
|
|
2586
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "flex min-w-0 flex-1 flex-col", "aria-label": entry.title, children: [
|
|
2587
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("header", { className: "flex flex-wrap items-center gap-2 border-b border-border px-5 pt-2.5 pb-2.5", children: [
|
|
2588
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProviderMark, { provider: session.provider, size: 22 }),
|
|
2589
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "min-w-0 flex-1 overflow-hidden", children: [
|
|
2590
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderTitle, { entry, renaming, setRenaming }),
|
|
2591
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 items-center gap-1 text-[12px] leading-5 text-muted-foreground", children: [
|
|
2592
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "shrink-0", children: PROVIDER_LABEL[session.provider] }),
|
|
2593
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
2594
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2233
2595
|
ModelPicker,
|
|
2234
2596
|
{
|
|
2235
2597
|
status: provider,
|
|
@@ -2237,69 +2599,70 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2237
2599
|
onChange: setOptions
|
|
2238
2600
|
}
|
|
2239
2601
|
),
|
|
2240
|
-
/* @__PURE__ */ (0,
|
|
2241
|
-
/* @__PURE__ */ (0,
|
|
2242
|
-
/* @__PURE__ */ (0,
|
|
2243
|
-
usageWords ? /* @__PURE__ */ (0,
|
|
2602
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
2603
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FolderIcon, { size: 12, className: "shrink-0" }),
|
|
2604
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "min-w-[4rem] truncate", title: session.cwd, children: prettyPath2(session.cwd) }),
|
|
2605
|
+
usageWords ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "shrink-0", title: usageTitle, children: [
|
|
2244
2606
|
"\xB7 ",
|
|
2245
2607
|
usageWords
|
|
2246
2608
|
] }) : null
|
|
2247
2609
|
] })
|
|
2248
2610
|
] }),
|
|
2249
|
-
/* @__PURE__ */ (0,
|
|
2611
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AgentMenu, { transport: client.transport, sessionId: session.id, agent: session.agent ?? null, onChange: () => void 0 }),
|
|
2612
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2250
2613
|
"button",
|
|
2251
2614
|
{
|
|
2252
2615
|
type: "button",
|
|
2253
|
-
className: (0,
|
|
2616
|
+
className: (0, import_design_system6.cn)("cs-chip-button", changesOpen && "cs-chip-button--on"),
|
|
2254
2617
|
onClick: () => setChangesOpen(!changesOpen),
|
|
2255
2618
|
"aria-pressed": changesOpen,
|
|
2256
2619
|
title: "Files this chat changed",
|
|
2257
2620
|
children: [
|
|
2258
|
-
/* @__PURE__ */ (0,
|
|
2621
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FileIcon, { size: 13 }),
|
|
2259
2622
|
files.length > 0 ? `${files.length} ${files.length === 1 ? "file" : "files"} changed` : "Changes"
|
|
2260
2623
|
]
|
|
2261
2624
|
}
|
|
2262
2625
|
),
|
|
2263
|
-
/* @__PURE__ */ (0,
|
|
2264
|
-
live ? /* @__PURE__ */ (0,
|
|
2265
|
-
stopping ? /* @__PURE__ */ (0,
|
|
2626
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RunPill, { run }),
|
|
2627
|
+
live ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.Button, { variant: "outline", size: "sm", onClick: () => void stop(), disabled: stopping, className: "gap-1.5", title: "Stop Esc", children: [
|
|
2628
|
+
stopping ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StopIcon, { size: 13 }),
|
|
2266
2629
|
stopping ? "Stopping\u2026" : "Stop"
|
|
2267
2630
|
] }) : null,
|
|
2268
|
-
/* @__PURE__ */ (0,
|
|
2631
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderMenu, { entry, onRename: () => setRenaming(true) })
|
|
2269
2632
|
] }),
|
|
2270
|
-
/* @__PURE__ */ (0,
|
|
2271
|
-
/* @__PURE__ */ (0,
|
|
2272
|
-
/* @__PURE__ */ (0,
|
|
2633
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mx-chat flex min-h-0 flex-1 flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react9.ChatProvider, { thread: transcript.thread, ports: { notifier, toolLabel: friendlyToolName }, children: [
|
|
2634
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "min-h-0 flex-1 overflow-hidden", children: transcript.state.loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex h-full items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
|
|
2635
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 15 }),
|
|
2273
2636
|
" Loading the conversation\u2026"
|
|
2274
|
-
] }) : /* @__PURE__ */ (0,
|
|
2275
|
-
transcript.state.unavailable ? /* @__PURE__ */ (0,
|
|
2276
|
-
transcript.state.truncated ? /* @__PURE__ */ (0,
|
|
2637
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex h-full flex-col", children: [
|
|
2638
|
+
transcript.state.unavailable ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "mx-auto mt-4 max-w-[720px] rounded-lg border border-border bg-muted/50 px-4 py-2.5 text-[13px] text-muted-foreground", children: transcript.state.unavailable }) : null,
|
|
2639
|
+
transcript.state.truncated ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2277
2640
|
LongChatNote,
|
|
2278
2641
|
{
|
|
2279
2642
|
loading: transcript.state.loadingEarlier === true,
|
|
2280
2643
|
onEarlier: () => void transcript.loadEarlier()
|
|
2281
2644
|
}
|
|
2282
2645
|
) : null,
|
|
2283
|
-
messages.length === 0 && !live ? /* @__PURE__ */ (0,
|
|
2646
|
+
messages.length === 0 && !live ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-1 items-center justify-center text-[13px] text-muted-foreground", children: session.origin === "takeover" ? "You've taken over this chat. Send a message to continue it." : "Nothing here yet." }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react9.ChatMessageList, { className: "min-h-0 flex-1", label: `Conversation: ${entry.title}` })
|
|
2284
2647
|
] }) }),
|
|
2285
|
-
/* @__PURE__ */ (0,
|
|
2286
|
-
limited ? /* @__PURE__ */ (0,
|
|
2287
|
-
/* @__PURE__ */ (0,
|
|
2288
|
-
/* @__PURE__ */ (0,
|
|
2648
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mx-auto w-full max-w-[820px] px-4 pb-4", children: [
|
|
2649
|
+
limited ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]", children: [
|
|
2650
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
|
|
2651
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
2289
2652
|
limited.problem,
|
|
2290
2653
|
" ",
|
|
2291
2654
|
limited.fix
|
|
2292
2655
|
] })
|
|
2293
2656
|
] }) : null,
|
|
2294
|
-
modelRefused && !blocked ? /* @__PURE__ */ (0,
|
|
2657
|
+
modelRefused && !blocked ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2295
2658
|
"div",
|
|
2296
2659
|
{
|
|
2297
2660
|
className: "mb-2 flex items-center gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]",
|
|
2298
2661
|
role: "alert",
|
|
2299
2662
|
children: [
|
|
2300
|
-
/* @__PURE__ */ (0,
|
|
2301
|
-
/* @__PURE__ */ (0,
|
|
2302
|
-
/* @__PURE__ */ (0,
|
|
2663
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "shrink-0 text-warning" }),
|
|
2664
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "min-w-0 flex-1 truncate", title: run?.error ?? void 0, children: MODEL_UNAVAILABLE_LABEL }),
|
|
2665
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2303
2666
|
ModelPicker,
|
|
2304
2667
|
{
|
|
2305
2668
|
status: provider,
|
|
@@ -2310,32 +2673,32 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2310
2673
|
]
|
|
2311
2674
|
}
|
|
2312
2675
|
) : null,
|
|
2313
|
-
blocked ? /* @__PURE__ */ (0,
|
|
2314
|
-
/* @__PURE__ */ (0,
|
|
2315
|
-
/* @__PURE__ */ (0,
|
|
2676
|
+
blocked ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]", children: [
|
|
2677
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
|
|
2678
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
2316
2679
|
blocked.problem,
|
|
2317
2680
|
" ",
|
|
2318
2681
|
blocked.fix
|
|
2319
2682
|
] })
|
|
2320
2683
|
] }) : null,
|
|
2321
|
-
/* @__PURE__ */ (0,
|
|
2322
|
-
/* @__PURE__ */ (0,
|
|
2323
|
-
/* @__PURE__ */ (0,
|
|
2324
|
-
/* @__PURE__ */ (0,
|
|
2684
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "cs-activity", role: "status", "aria-live": "polite", "data-idle": live ? void 0 : true, children: live ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2685
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 13 }),
|
|
2686
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate", children: run?.status === "starting" ? `Starting ${PROVIDER_LABEL[session.provider]}\u2026` : transcript.activity ?? "Thinking\u2026" }),
|
|
2687
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ml-auto shrink-0 text-[11px] opacity-70", children: "Esc to stop" })
|
|
2325
2688
|
] }) : null }),
|
|
2326
|
-
elsewhere ? /* @__PURE__ */ (0,
|
|
2327
|
-
/* @__PURE__ */ (0,
|
|
2328
|
-
/* @__PURE__ */ (0,
|
|
2689
|
+
elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mb-2 flex items-start gap-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-[12.5px]", children: [
|
|
2690
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
|
|
2691
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
2329
2692
|
elsewhere.message,
|
|
2330
2693
|
" A message sent here would put a second agent on the same chat."
|
|
2331
2694
|
] })
|
|
2332
2695
|
] }) : null,
|
|
2333
|
-
session.queued.length > 0 ? /* @__PURE__ */ (0,
|
|
2334
|
-
/* @__PURE__ */ (0,
|
|
2335
|
-
/* @__PURE__ */ (0,
|
|
2696
|
+
session.queued.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { className: "mb-2 space-y-1.5", "aria-label": "Queued messages", children: session.queued.map((text, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("li", { className: "cs-queued", children: [
|
|
2697
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "cs-queued__label", children: "Queued \xB7 sends when this run finishes" }),
|
|
2698
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "cs-queued__text", children: text })
|
|
2336
2699
|
] }, `${index}-${text.slice(0, 16)}`)) }) : null,
|
|
2337
|
-
/* @__PURE__ */ (0,
|
|
2338
|
-
|
|
2700
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2701
|
+
import_react9.ChatComposer,
|
|
2339
2702
|
{
|
|
2340
2703
|
placeholder: `Message ${PROVIDER_LABEL[session.provider]}\u2026`,
|
|
2341
2704
|
autoFocus: true,
|
|
@@ -2345,14 +2708,14 @@ function SessionView({ session, changesOpen, setChangesOpen }) {
|
|
|
2345
2708
|
] })
|
|
2346
2709
|
] }) })
|
|
2347
2710
|
] }),
|
|
2348
|
-
changesOpen ? /* @__PURE__ */ (0,
|
|
2711
|
+
changesOpen ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChangesPanel, { files, cwd: session.cwd, truncated: transcript.state.truncated, onClose: () => setChangesOpen(false) }) : null
|
|
2349
2712
|
] });
|
|
2350
2713
|
}
|
|
2351
2714
|
function usePreviewThread(id, onSend) {
|
|
2352
|
-
const ref = (0,
|
|
2353
|
-
const send = (0,
|
|
2715
|
+
const ref = (0, import_react8.useRef)({ messages: [], listeners: /* @__PURE__ */ new Set() });
|
|
2716
|
+
const send = (0, import_react8.useRef)(onSend);
|
|
2354
2717
|
send.current = onSend;
|
|
2355
|
-
const thread = (0,
|
|
2718
|
+
const thread = (0, import_react8.useMemo)(
|
|
2356
2719
|
() => (0, import_external_store2.createExternalThreadSource)({
|
|
2357
2720
|
getSnapshot: () => ({ messages: ref.current.messages, status: "idle", conversationId: id }),
|
|
2358
2721
|
subscribe: (listener) => {
|
|
@@ -2366,7 +2729,7 @@ function usePreviewThread(id, onSend) {
|
|
|
2366
2729
|
}),
|
|
2367
2730
|
[id]
|
|
2368
2731
|
);
|
|
2369
|
-
const set = (0,
|
|
2732
|
+
const set = (0, import_react8.useCallback)((messages) => {
|
|
2370
2733
|
ref.current.messages = messages;
|
|
2371
2734
|
for (const listener of ref.current.listeners) listener();
|
|
2372
2735
|
}, []);
|
|
@@ -2375,15 +2738,15 @@ function usePreviewThread(id, onSend) {
|
|
|
2375
2738
|
function DiscoveredView(props) {
|
|
2376
2739
|
const client = useCodingSessionsClient();
|
|
2377
2740
|
const state = useCodingSessionsState();
|
|
2378
|
-
const show = (0,
|
|
2741
|
+
const show = (0, import_react8.useContext)(ToastContext);
|
|
2379
2742
|
const now = useMinuteClock();
|
|
2380
|
-
const [preview, setPreview] = (0,
|
|
2381
|
-
const [busy, setBusy] = (0,
|
|
2382
|
-
const [error, setError] = (0,
|
|
2383
|
-
const [confirming, setConfirming] = (0,
|
|
2384
|
-
const [renaming, setRenaming] = (0,
|
|
2385
|
-
const [maxBytes, setMaxBytes] = (0,
|
|
2386
|
-
const [readingEarlier, setReadingEarlier] = (0,
|
|
2743
|
+
const [preview, setPreview] = (0, import_react8.useState)({ loading: true, messages: [], unavailable: null, truncated: false });
|
|
2744
|
+
const [busy, setBusy] = (0, import_react8.useState)(false);
|
|
2745
|
+
const [error, setError] = (0, import_react8.useState)(null);
|
|
2746
|
+
const [confirming, setConfirming] = (0, import_react8.useState)(false);
|
|
2747
|
+
const [renaming, setRenaming] = (0, import_react8.useState)(false);
|
|
2748
|
+
const [maxBytes, setMaxBytes] = (0, import_react8.useState)(void 0);
|
|
2749
|
+
const [readingEarlier, setReadingEarlier] = (0, import_react8.useState)(false);
|
|
2387
2750
|
const elsewhere = useLiveElsewhere(props.provider, props.id, props.session?.activeElsewhere ?? null);
|
|
2388
2751
|
const files = useChangedFiles(preview.messages);
|
|
2389
2752
|
const d = props.session;
|
|
@@ -2393,7 +2756,7 @@ function DiscoveredView(props) {
|
|
|
2393
2756
|
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."
|
|
2394
2757
|
)
|
|
2395
2758
|
);
|
|
2396
|
-
(0,
|
|
2759
|
+
(0, import_react8.useEffect)(() => {
|
|
2397
2760
|
let cancelled = false;
|
|
2398
2761
|
const read = (first) => client.readPreview(props.provider, props.id, maxBytes).then((next) => {
|
|
2399
2762
|
if (cancelled) return;
|
|
@@ -2418,13 +2781,14 @@ function DiscoveredView(props) {
|
|
|
2418
2781
|
if (elsewhere) setConfirming(true);
|
|
2419
2782
|
else void takeover();
|
|
2420
2783
|
};
|
|
2421
|
-
const
|
|
2784
|
+
const [choosingAgent, setChoosingAgent] = (0, import_react8.useState)(false);
|
|
2785
|
+
const takeover = async (agent) => {
|
|
2422
2786
|
if (!d) return;
|
|
2423
2787
|
setConfirming(false);
|
|
2424
2788
|
setBusy(true);
|
|
2425
2789
|
setError(null);
|
|
2426
2790
|
try {
|
|
2427
|
-
const taken = await client.takeover(d);
|
|
2791
|
+
const taken = await client.takeover(d, agent);
|
|
2428
2792
|
props.onTakenOver(taken.id);
|
|
2429
2793
|
} catch (e) {
|
|
2430
2794
|
setError(e instanceof Error ? e.message : String(e));
|
|
@@ -2432,26 +2796,26 @@ function DiscoveredView(props) {
|
|
|
2432
2796
|
setBusy(false);
|
|
2433
2797
|
}
|
|
2434
2798
|
};
|
|
2435
|
-
return /* @__PURE__ */ (0,
|
|
2436
|
-
/* @__PURE__ */ (0,
|
|
2437
|
-
/* @__PURE__ */ (0,
|
|
2438
|
-
/* @__PURE__ */ (0,
|
|
2439
|
-
/* @__PURE__ */ (0,
|
|
2440
|
-
/* @__PURE__ */ (0,
|
|
2441
|
-
/* @__PURE__ */ (0,
|
|
2442
|
-
/* @__PURE__ */ (0,
|
|
2443
|
-
d?.cwd ? /* @__PURE__ */ (0,
|
|
2444
|
-
/* @__PURE__ */ (0,
|
|
2445
|
-
/* @__PURE__ */ (0,
|
|
2446
|
-
/* @__PURE__ */ (0,
|
|
2799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 flex-1", children: [
|
|
2800
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "flex min-w-0 flex-1 flex-col", "aria-label": entry.title, children: [
|
|
2801
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("header", { className: "flex flex-wrap items-center gap-2 border-b border-border px-5 pt-2.5 pb-2.5", children: [
|
|
2802
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProviderMark, { provider: props.provider, size: 22 }),
|
|
2803
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
2804
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderTitle, { entry, renaming, setRenaming }),
|
|
2805
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "flex items-center gap-1.5 truncate text-[12px] leading-4 text-muted-foreground", children: [
|
|
2806
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: PROVIDER_LABEL[props.provider] }),
|
|
2807
|
+
d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2808
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
2809
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FolderIcon, { size: 12 }),
|
|
2810
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate", title: d.cwd, children: prettyPath2(d.cwd) })
|
|
2447
2811
|
] }) : null,
|
|
2448
|
-
d ? /* @__PURE__ */ (0,
|
|
2812
|
+
d ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
2449
2813
|
"\xB7 last active ",
|
|
2450
2814
|
relativeTime(d.updatedAt, now)
|
|
2451
2815
|
] }) : null
|
|
2452
2816
|
] })
|
|
2453
2817
|
] }),
|
|
2454
|
-
files.length > 0 ? /* @__PURE__ */ (0,
|
|
2818
|
+
files.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2455
2819
|
"button",
|
|
2456
2820
|
{
|
|
2457
2821
|
type: "button",
|
|
@@ -2460,13 +2824,13 @@ function DiscoveredView(props) {
|
|
|
2460
2824
|
"aria-pressed": props.changesOpen,
|
|
2461
2825
|
title: "Files this chat changed",
|
|
2462
2826
|
children: [
|
|
2463
|
-
/* @__PURE__ */ (0,
|
|
2827
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FileIcon, { size: 13 }),
|
|
2464
2828
|
`${files.length} ${files.length === 1 ? "file" : "files"} changed`
|
|
2465
2829
|
]
|
|
2466
2830
|
}
|
|
2467
2831
|
) : null,
|
|
2468
|
-
d?.cwd ? /* @__PURE__ */ (0,
|
|
2469
|
-
|
|
2832
|
+
d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2833
|
+
import_design_system6.Button,
|
|
2470
2834
|
{
|
|
2471
2835
|
size: "sm",
|
|
2472
2836
|
variant: elsewhere ? "outline" : "default",
|
|
@@ -2475,44 +2839,56 @@ function DiscoveredView(props) {
|
|
|
2475
2839
|
className: "gap-1.5",
|
|
2476
2840
|
title: elsewhere ? elsewhere.message : void 0,
|
|
2477
2841
|
children: [
|
|
2478
|
-
busy ? /* @__PURE__ */ (0,
|
|
2842
|
+
busy ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 13 }) : elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 14, className: "text-warning" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HandoffIcon, { size: 14 }),
|
|
2479
2843
|
elsewhere ? "Take over anyway\u2026" : "Take over"
|
|
2480
2844
|
]
|
|
2481
2845
|
}
|
|
2482
2846
|
) : null,
|
|
2483
|
-
d ? /* @__PURE__ */ (0,
|
|
2847
|
+
d?.cwd && !elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Button, { size: "sm", variant: "outline", onClick: () => setChoosingAgent(true), disabled: busy, children: "Continue with agent\u2026" }) : null,
|
|
2848
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2849
|
+
ChooseAgentDialog,
|
|
2850
|
+
{
|
|
2851
|
+
transport: client.transport,
|
|
2852
|
+
open: choosingAgent,
|
|
2853
|
+
onOpenChange: setChoosingAgent,
|
|
2854
|
+
title: "Continue with an agent",
|
|
2855
|
+
action: "Take over with this agent",
|
|
2856
|
+
onConfirm: (agent) => takeover(agent)
|
|
2857
|
+
}
|
|
2858
|
+
),
|
|
2859
|
+
d ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderMenu, { entry, onRename: () => setRenaming(true) }) : null
|
|
2484
2860
|
] }),
|
|
2485
|
-
elsewhere ? /* @__PURE__ */ (0,
|
|
2486
|
-
/* @__PURE__ */ (0,
|
|
2487
|
-
/* @__PURE__ */ (0,
|
|
2488
|
-
/* @__PURE__ */ (0,
|
|
2861
|
+
elsewhere ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "status", className: "flex items-start gap-2 border-b border-warning/40 bg-warning/10 px-5 py-2.5 text-[13px]", children: [
|
|
2862
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "mt-0.5 shrink-0 text-warning" }),
|
|
2863
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
2864
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-medium", children: elsewhere.message }),
|
|
2489
2865
|
" 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."
|
|
2490
2866
|
] })
|
|
2491
2867
|
] }) : null,
|
|
2492
|
-
/* @__PURE__ */ (0,
|
|
2493
|
-
/* @__PURE__ */ (0,
|
|
2494
|
-
/* @__PURE__ */ (0,
|
|
2868
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Dialog, { open: confirming, onOpenChange: setConfirming, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogContent, { className: "max-w-[460px]", children: [
|
|
2869
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogHeader, { children: [
|
|
2870
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogTitle, { children: [
|
|
2495
2871
|
"This chat is running right now in ",
|
|
2496
2872
|
PROVIDER_LABEL[props.provider]
|
|
2497
2873
|
] }),
|
|
2498
|
-
/* @__PURE__ */ (0,
|
|
2874
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogDescription, { children: [
|
|
2499
2875
|
elsewhere?.message,
|
|
2500
2876
|
" If you take it over, two agents will work in the same conversation at once and may overwrite each other's changes."
|
|
2501
2877
|
] })
|
|
2502
2878
|
] }),
|
|
2503
|
-
/* @__PURE__ */ (0,
|
|
2504
|
-
/* @__PURE__ */ (0,
|
|
2505
|
-
/* @__PURE__ */ (0,
|
|
2879
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogFooter, { children: [
|
|
2880
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Button, { variant: "ghost", onClick: () => setConfirming(false), children: "Cancel" }),
|
|
2881
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Button, { variant: "destructive", onClick: () => void takeover(), children: "Take over anyway" })
|
|
2506
2882
|
] })
|
|
2507
2883
|
] }) }),
|
|
2508
|
-
error ? /* @__PURE__ */ (0,
|
|
2509
|
-
d && !d.cwd ? /* @__PURE__ */ (0,
|
|
2510
|
-
/* @__PURE__ */ (0,
|
|
2511
|
-
preview.loading ? /* @__PURE__ */ (0,
|
|
2512
|
-
/* @__PURE__ */ (0,
|
|
2884
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "border-b border-destructive/30 bg-destructive/10 px-5 py-2 text-[13px] text-destructive", children: error }) : null,
|
|
2885
|
+
d && !d.cwd ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "border-b border-border bg-muted/50 px-5 py-2 text-[13px] text-muted-foreground", children: "This chat doesn't record which folder it ran in, so it can't be continued from here." }) : null,
|
|
2886
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mx-chat flex min-h-0 flex-1 flex-col", children: [
|
|
2887
|
+
preview.loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 15 }),
|
|
2513
2889
|
" Reading this chat\u2026"
|
|
2514
|
-
] }) : preview.unavailable ? /* @__PURE__ */ (0,
|
|
2515
|
-
preview.truncated ? /* @__PURE__ */ (0,
|
|
2890
|
+
] }) : preview.unavailable ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-1 items-center justify-center px-6 text-center text-[13px] text-muted-foreground", children: preview.unavailable }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react9.ChatProvider, { thread, ports: { notifier, toolLabel: friendlyToolName }, children: [
|
|
2891
|
+
preview.truncated ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2516
2892
|
LongChatNote,
|
|
2517
2893
|
{
|
|
2518
2894
|
loading: readingEarlier,
|
|
@@ -2522,14 +2898,14 @@ function DiscoveredView(props) {
|
|
|
2522
2898
|
}
|
|
2523
2899
|
}
|
|
2524
2900
|
) : null,
|
|
2525
|
-
/* @__PURE__ */ (0,
|
|
2901
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react9.ChatMessageList, { className: "min-h-0 flex-1", label: "Chat preview" })
|
|
2526
2902
|
] }),
|
|
2527
|
-
d?.cwd ? /* @__PURE__ */ (0,
|
|
2903
|
+
d?.cwd ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "border-t border-border bg-muted/30 px-5 py-3 text-center text-[13px] text-muted-foreground", children: [
|
|
2528
2904
|
"This chat was started in ",
|
|
2529
2905
|
PROVIDER_LABEL[props.provider],
|
|
2530
2906
|
".",
|
|
2531
2907
|
" ",
|
|
2532
|
-
/* @__PURE__ */ (0,
|
|
2908
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "font-medium text-foreground underline-offset-4 hover:underline", onClick: requestTakeover, children: "Take it over" }),
|
|
2533
2909
|
" ",
|
|
2534
2910
|
"to continue it here \u2014 it stays in your ",
|
|
2535
2911
|
PROVIDER_LABEL[props.provider],
|
|
@@ -2537,70 +2913,73 @@ function DiscoveredView(props) {
|
|
|
2537
2913
|
] }) : null
|
|
2538
2914
|
] })
|
|
2539
2915
|
] }),
|
|
2540
|
-
props.changesOpen && files.length > 0 ? /* @__PURE__ */ (0,
|
|
2916
|
+
props.changesOpen && files.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChangesPanel, { files, cwd: d?.cwd ?? null, truncated: preview.truncated, onClose: () => props.setChangesOpen(false) }) : null
|
|
2541
2917
|
] });
|
|
2542
2918
|
}
|
|
2543
2919
|
function ProviderCard(props) {
|
|
2544
2920
|
const ready = props.status.ready;
|
|
2545
|
-
return /* @__PURE__ */ (0,
|
|
2921
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2546
2922
|
"button",
|
|
2547
2923
|
{
|
|
2548
2924
|
type: "button",
|
|
2549
2925
|
onClick: props.onSelect,
|
|
2550
2926
|
"aria-pressed": props.selected,
|
|
2551
|
-
className: (0,
|
|
2927
|
+
className: (0, import_design_system6.cn)(
|
|
2552
2928
|
"flex flex-1 flex-col gap-1.5 rounded-xl border px-3.5 py-3 text-left transition-colors",
|
|
2553
2929
|
props.selected ? "border-primary bg-primary/5 ring-1 ring-primary" : "border-border hover:bg-accent/50"
|
|
2554
2930
|
),
|
|
2555
2931
|
children: [
|
|
2556
|
-
/* @__PURE__ */ (0,
|
|
2557
|
-
/* @__PURE__ */ (0,
|
|
2558
|
-
/* @__PURE__ */ (0,
|
|
2932
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "flex items-center gap-2", children: [
|
|
2933
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProviderMark, { provider: props.status.provider, size: 18 }),
|
|
2934
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[13.5px] font-semibold", children: props.status.label })
|
|
2559
2935
|
] }),
|
|
2560
|
-
ready ? /* @__PURE__ */ (0,
|
|
2561
|
-
/* @__PURE__ */ (0,
|
|
2936
|
+
ready ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "flex items-center gap-1 text-[12px] text-success", children: [
|
|
2937
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckIcon, { size: 13 }),
|
|
2562
2938
|
props.status.billing === "subscription" ? `Signed in${props.status.plan ? ` \xB7 ${props.status.plan} plan` : ""}` : "Signed in with an API key (billed per use)"
|
|
2563
|
-
] }) : /* @__PURE__ */ (0,
|
|
2564
|
-
/* @__PURE__ */ (0,
|
|
2939
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "flex items-start gap-1 text-[12px] leading-4 text-warning", children: [
|
|
2940
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 13, className: "mt-px shrink-0" }),
|
|
2565
2941
|
props.status.problem
|
|
2566
2942
|
] }),
|
|
2567
|
-
props.status.quota.filter((w) => w.usedPercent !== null).length > 0 ? /* @__PURE__ */ (0,
|
|
2943
|
+
props.status.quota.filter((w) => w.usedPercent !== null).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[11.5px] leading-4 text-muted-foreground", children: props.status.quota.filter((w) => w.usedPercent !== null).map((w) => `${w.label}: ${w.usedPercent}% used`).join(" \xB7 ") }) : null
|
|
2568
2944
|
]
|
|
2569
2945
|
}
|
|
2570
2946
|
);
|
|
2571
2947
|
}
|
|
2572
2948
|
function FieldError({ id, children }) {
|
|
2573
|
-
return /* @__PURE__ */ (0,
|
|
2574
|
-
/* @__PURE__ */ (0,
|
|
2575
|
-
/* @__PURE__ */ (0,
|
|
2949
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { id, role: "alert", className: "flex items-start gap-1.5 text-[12.5px] leading-5 text-destructive", children: [
|
|
2950
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 14, className: "mt-0.5 shrink-0" }),
|
|
2951
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children })
|
|
2576
2952
|
] });
|
|
2577
2953
|
}
|
|
2578
2954
|
function NewSessionDialog(props) {
|
|
2579
2955
|
const client = useCodingSessionsClient();
|
|
2580
2956
|
const state = useCodingSessionsState();
|
|
2581
2957
|
const now = useMinuteClock();
|
|
2582
|
-
const [provider, setProvider] = (0,
|
|
2583
|
-
const [folder, setFolder] = (0,
|
|
2584
|
-
const [choice, setChoice] = (0,
|
|
2585
|
-
const [prompt, setPrompt] = (0,
|
|
2586
|
-
const [errors, setErrors] = (0,
|
|
2587
|
-
const [problem, setProblem] = (0,
|
|
2588
|
-
const [starting, setStarting] = (0,
|
|
2589
|
-
const [creating, setCreating] = (0,
|
|
2590
|
-
const
|
|
2591
|
-
const
|
|
2592
|
-
const
|
|
2593
|
-
(0,
|
|
2958
|
+
const [provider, setProvider] = (0, import_react8.useState)("claude");
|
|
2959
|
+
const [folder, setFolder] = (0, import_react8.useState)("");
|
|
2960
|
+
const [choice, setChoice] = (0, import_react8.useState)({ model: null, effort: null });
|
|
2961
|
+
const [prompt, setPrompt] = (0, import_react8.useState)("");
|
|
2962
|
+
const [errors, setErrors] = (0, import_react8.useState)({});
|
|
2963
|
+
const [problem, setProblem] = (0, import_react8.useState)(null);
|
|
2964
|
+
const [starting, setStarting] = (0, import_react8.useState)(false);
|
|
2965
|
+
const [creating, setCreating] = (0, import_react8.useState)(false);
|
|
2966
|
+
const [agent, setAgent] = (0, import_react8.useState)(null);
|
|
2967
|
+
const [agentDetails, setAgentDetails] = (0, import_react8.useState)(null);
|
|
2968
|
+
const [agentMissing, setAgentMissing] = (0, import_react8.useState)(null);
|
|
2969
|
+
const promptRef = (0, import_react8.useRef)(null);
|
|
2970
|
+
const folderRef = (0, import_react8.useRef)(null);
|
|
2971
|
+
const agentRef = (0, import_react8.useRef)(null);
|
|
2972
|
+
(0, import_react8.useEffect)(() => {
|
|
2594
2973
|
if (!props.open) return;
|
|
2595
2974
|
setProblem(null);
|
|
2596
2975
|
setErrors({});
|
|
2597
2976
|
void client.refreshProviders();
|
|
2598
2977
|
void client.refreshFolders();
|
|
2599
2978
|
}, [props.open, client]);
|
|
2600
|
-
(0,
|
|
2979
|
+
(0, import_react8.useEffect)(() => {
|
|
2601
2980
|
if (!folder && state.folders.data[0]?.exists) setFolder(state.folders.data[0].path);
|
|
2602
2981
|
}, [state.folders.data, folder]);
|
|
2603
|
-
(0,
|
|
2982
|
+
(0, import_react8.useEffect)(() => {
|
|
2604
2983
|
const ready = state.providers.data.filter((p) => p.ready);
|
|
2605
2984
|
const current = state.providers.data.find((p) => p.provider === provider);
|
|
2606
2985
|
if (current && !current.ready && ready[0]) setProvider(ready[0].provider);
|
|
@@ -2626,9 +3005,22 @@ function NewSessionDialog(props) {
|
|
|
2626
3005
|
focusField(first);
|
|
2627
3006
|
return;
|
|
2628
3007
|
}
|
|
3008
|
+
const missing = missingRequiredVariable(agentDetails, agent);
|
|
3009
|
+
setAgentMissing(missing);
|
|
3010
|
+
if (missing) {
|
|
3011
|
+
document.getElementById(`cs-agent-var-${missing}`)?.focus();
|
|
3012
|
+
return;
|
|
3013
|
+
}
|
|
2629
3014
|
setStarting(true);
|
|
2630
3015
|
try {
|
|
2631
|
-
const result = await client.start({
|
|
3016
|
+
const result = await client.start({
|
|
3017
|
+
provider,
|
|
3018
|
+
cwd: folder.trim(),
|
|
3019
|
+
prompt,
|
|
3020
|
+
model: choice.model,
|
|
3021
|
+
effort: choice.effort,
|
|
3022
|
+
...agent ? { agent } : {}
|
|
3023
|
+
});
|
|
2632
3024
|
setPrompt("");
|
|
2633
3025
|
props.onStarted(result.session.id);
|
|
2634
3026
|
} catch (error) {
|
|
@@ -2664,16 +3056,16 @@ function NewSessionDialog(props) {
|
|
|
2664
3056
|
if (field === "folder") delete next.createFolder;
|
|
2665
3057
|
return next;
|
|
2666
3058
|
});
|
|
2667
|
-
return /* @__PURE__ */ (0,
|
|
2668
|
-
/* @__PURE__ */ (0,
|
|
2669
|
-
/* @__PURE__ */ (0,
|
|
2670
|
-
/* @__PURE__ */ (0,
|
|
3059
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogContent, { className: "max-w-[560px]", children: [
|
|
3060
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogHeader, { children: [
|
|
3061
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.DialogTitle, { children: "New coding session" }),
|
|
3062
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogDescription, { children: [
|
|
2671
3063
|
"Runs on your own ",
|
|
2672
3064
|
provider === "claude" ? "Claude" : "ChatGPT",
|
|
2673
3065
|
" sign-in, in a folder on this computer."
|
|
2674
3066
|
] })
|
|
2675
3067
|
] }),
|
|
2676
|
-
/* @__PURE__ */ (0,
|
|
3068
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2677
3069
|
"form",
|
|
2678
3070
|
{
|
|
2679
3071
|
noValidate: true,
|
|
@@ -2683,13 +3075,13 @@ function NewSessionDialog(props) {
|
|
|
2683
3075
|
},
|
|
2684
3076
|
className: "flex min-h-0 flex-col",
|
|
2685
3077
|
children: [
|
|
2686
|
-
/* @__PURE__ */ (0,
|
|
2687
|
-
/* @__PURE__ */ (0,
|
|
2688
|
-
/* @__PURE__ */ (0,
|
|
2689
|
-
state.providers.loading && state.providers.loadedAt === null ? /* @__PURE__ */ (0,
|
|
2690
|
-
/* @__PURE__ */ (0,
|
|
2691
|
-
/* @__PURE__ */ (0,
|
|
2692
|
-
] }) : state.providers.error ? /* @__PURE__ */ (0,
|
|
3078
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "cs-dialog-body space-y-5 py-1 pr-1", children: [
|
|
3079
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "space-y-2", ref: agentRef, children: [
|
|
3080
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Agent" }),
|
|
3081
|
+
state.providers.loading && state.providers.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-2", children: [
|
|
3082
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "cs-skeleton h-[68px] flex-1 rounded-xl" }),
|
|
3083
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "cs-skeleton h-[68px] flex-1 rounded-xl" })
|
|
3084
|
+
] }) : state.providers.error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-[12.5px] text-destructive", children: state.providers.error }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex gap-2", children: state.providers.data.map((p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2693
3085
|
ProviderCard,
|
|
2694
3086
|
{
|
|
2695
3087
|
status: p,
|
|
@@ -2702,14 +3094,31 @@ function NewSessionDialog(props) {
|
|
|
2702
3094
|
},
|
|
2703
3095
|
p.provider
|
|
2704
3096
|
)) }),
|
|
2705
|
-
errors.agent ? /* @__PURE__ */ (0,
|
|
3097
|
+
errors.agent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldError, { id: "cs-err-agent", children: errors.agent }) : selected && !selected.ready && selected.fix ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "text-[12px] leading-4 text-muted-foreground", children: [
|
|
2706
3098
|
selected.fix,
|
|
2707
3099
|
selected.installed && selected.loggedIn ? " You can still try \u2014 the run will say if it's still blocked." : ""
|
|
2708
3100
|
] }) : null
|
|
2709
3101
|
] }),
|
|
2710
|
-
/* @__PURE__ */ (0,
|
|
2711
|
-
/* @__PURE__ */ (0,
|
|
2712
|
-
|
|
3102
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "space-y-2", children: [
|
|
3103
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "AI Matrx agent" }),
|
|
3104
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3105
|
+
AgentField,
|
|
3106
|
+
{
|
|
3107
|
+
transport: client.transport,
|
|
3108
|
+
open: props.open,
|
|
3109
|
+
value: agent,
|
|
3110
|
+
onChange: (next) => {
|
|
3111
|
+
setAgent(next);
|
|
3112
|
+
setAgentMissing(null);
|
|
3113
|
+
},
|
|
3114
|
+
missing: agentMissing,
|
|
3115
|
+
onDetails: setAgentDetails
|
|
3116
|
+
}
|
|
3117
|
+
)
|
|
3118
|
+
] }),
|
|
3119
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "space-y-2", children: [
|
|
3120
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Folder" }),
|
|
3121
|
+
state.folders.data.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "max-h-[132px] space-y-0.5 overflow-y-auto rounded-lg border border-border p-1", children: state.folders.data.map((f) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2713
3122
|
"button",
|
|
2714
3123
|
{
|
|
2715
3124
|
type: "button",
|
|
@@ -2719,21 +3128,21 @@ function NewSessionDialog(props) {
|
|
|
2719
3128
|
},
|
|
2720
3129
|
disabled: !f.exists,
|
|
2721
3130
|
title: f.exists ? f.path : `${f.path} no longer exists`,
|
|
2722
|
-
className: (0,
|
|
3131
|
+
className: (0, import_design_system6.cn)(
|
|
2723
3132
|
"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[12.5px]",
|
|
2724
3133
|
folder === f.path ? "bg-accent text-accent-foreground" : "hover:bg-accent/50",
|
|
2725
3134
|
!f.exists && "opacity-50"
|
|
2726
3135
|
),
|
|
2727
3136
|
children: [
|
|
2728
|
-
/* @__PURE__ */ (0,
|
|
2729
|
-
/* @__PURE__ */ (0,
|
|
2730
|
-
/* @__PURE__ */ (0,
|
|
3137
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FolderIcon, { size: 14, className: "shrink-0 text-muted-foreground" }),
|
|
3138
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "min-w-0 flex-1 truncate", children: prettyPath2(f.path) }),
|
|
3139
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: f.exists ? relativeTime(f.lastUsedAt, now) : "missing" })
|
|
2731
3140
|
]
|
|
2732
3141
|
},
|
|
2733
3142
|
f.path
|
|
2734
|
-
)) }) : state.folders.loading ? /* @__PURE__ */ (0,
|
|
2735
|
-
/* @__PURE__ */ (0,
|
|
2736
|
-
|
|
3143
|
+
)) }) : state.folders.loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "cs-skeleton h-10 rounded-lg" }) : null,
|
|
3144
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3145
|
+
import_design_system6.Input,
|
|
2737
3146
|
{
|
|
2738
3147
|
ref: folderRef,
|
|
2739
3148
|
value: folder,
|
|
@@ -2748,18 +3157,18 @@ function NewSessionDialog(props) {
|
|
|
2748
3157
|
spellCheck: false
|
|
2749
3158
|
}
|
|
2750
3159
|
),
|
|
2751
|
-
errors.folder ? /* @__PURE__ */ (0,
|
|
2752
|
-
/* @__PURE__ */ (0,
|
|
2753
|
-
errors.createFolder ? /* @__PURE__ */ (0,
|
|
2754
|
-
creating ? /* @__PURE__ */ (0,
|
|
3160
|
+
errors.folder ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1", children: [
|
|
3161
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldError, { id: "cs-err-folder", children: errors.folder }),
|
|
3162
|
+
errors.createFolder ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.Button, { type: "button", size: "sm", variant: "outline", onClick: () => void createFolder(), disabled: creating, className: "gap-1.5", children: [
|
|
3163
|
+
creating ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FolderIcon, { size: 13 }),
|
|
2755
3164
|
"Create this folder"
|
|
2756
3165
|
] }) : null
|
|
2757
3166
|
] }) : null
|
|
2758
3167
|
] }),
|
|
2759
|
-
/* @__PURE__ */ (0,
|
|
2760
|
-
/* @__PURE__ */ (0,
|
|
2761
|
-
/* @__PURE__ */ (0,
|
|
2762
|
-
|
|
3168
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "space-y-2", children: [
|
|
3169
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "What should it do?" }),
|
|
3170
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3171
|
+
import_design_system6.Textarea,
|
|
2763
3172
|
{
|
|
2764
3173
|
ref: promptRef,
|
|
2765
3174
|
value: prompt,
|
|
@@ -2780,25 +3189,25 @@ function NewSessionDialog(props) {
|
|
|
2780
3189
|
"aria-describedby": errors.prompt ? "cs-err-prompt" : void 0
|
|
2781
3190
|
}
|
|
2782
3191
|
),
|
|
2783
|
-
errors.prompt ? /* @__PURE__ */ (0,
|
|
3192
|
+
errors.prompt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldError, { id: "cs-err-prompt", children: errors.prompt }) : null
|
|
2784
3193
|
] }),
|
|
2785
|
-
/* @__PURE__ */ (0,
|
|
2786
|
-
/* @__PURE__ */ (0,
|
|
2787
|
-
/* @__PURE__ */ (0,
|
|
2788
|
-
/* @__PURE__ */ (0,
|
|
3194
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "space-y-2", children: [
|
|
3195
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "mb-2 text-[12.5px] font-medium", children: "Model and thinking effort" }),
|
|
3196
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ModelPicker, { status: selected, value: choice, onChange: setChoice, appearance: "field" }),
|
|
3197
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "text-[11.5px] leading-4 text-muted-foreground", children: [
|
|
2789
3198
|
"Default is ",
|
|
2790
3199
|
defaultModelWords(selected),
|
|
2791
3200
|
". You can change it later from the chat's header."
|
|
2792
3201
|
] })
|
|
2793
3202
|
] }),
|
|
2794
|
-
problem ? /* @__PURE__ */ (0,
|
|
3203
|
+
problem ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FieldError, { id: "cs-err-start", children: problem }) : null
|
|
2795
3204
|
] }),
|
|
2796
|
-
/* @__PURE__ */ (0,
|
|
2797
|
-
/* @__PURE__ */ (0,
|
|
2798
|
-
/* @__PURE__ */ (0,
|
|
2799
|
-
starting ? /* @__PURE__ */ (0,
|
|
3205
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogFooter, { className: "pt-4", children: [
|
|
3206
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Button, { type: "button", variant: "ghost", onClick: () => props.onOpenChange(false), children: "Cancel" }),
|
|
3207
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.Button, { type: "submit", disabled: starting, className: "gap-1.5", children: [
|
|
3208
|
+
starting ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 14 }) : null,
|
|
2800
3209
|
starting ? "Starting\u2026" : "Start session",
|
|
2801
|
-
!starting ? /* @__PURE__ */ (0,
|
|
3210
|
+
!starting ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("kbd", { className: "cs-kbd", children: "\u2318\u21B5" }) : null
|
|
2802
3211
|
] })
|
|
2803
3212
|
] })
|
|
2804
3213
|
]
|
|
@@ -2808,34 +3217,34 @@ function NewSessionDialog(props) {
|
|
|
2808
3217
|
}
|
|
2809
3218
|
function Home({ onNew }) {
|
|
2810
3219
|
const state = useCodingSessionsState();
|
|
2811
|
-
return /* @__PURE__ */ (0,
|
|
2812
|
-
/* @__PURE__ */ (0,
|
|
2813
|
-
/* @__PURE__ */ (0,
|
|
2814
|
-
/* @__PURE__ */ (0,
|
|
2815
|
-
/* @__PURE__ */ (0,
|
|
2816
|
-
/* @__PURE__ */ (0,
|
|
3220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("section", { className: "flex flex-1 items-center justify-center px-6", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "w-full max-w-[460px] text-center", children: [
|
|
3221
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "mx-auto mb-4 flex h-11 w-11 items-center justify-center rounded-2xl bg-primary/10 text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChatBubbleIcon, { size: 22 }) }),
|
|
3222
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { className: "text-[15px] font-semibold leading-5 tracking-[-0.01em]", children: "Drive Claude Code and Codex from here" }),
|
|
3223
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "mx-auto mt-2 max-w-[400px] text-[13.5px] leading-6 text-muted-foreground", children: "Start a session in any folder, or pick up a chat you began somewhere else. Everything runs on your own subscriptions \u2014 no API keys." }),
|
|
3224
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.Button, { className: "mt-5 gap-1.5", onClick: onNew, children: [
|
|
3225
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PlusIcon, { size: 15 }),
|
|
2817
3226
|
"New session"
|
|
2818
3227
|
] }),
|
|
2819
|
-
/* @__PURE__ */ (0,
|
|
2820
|
-
/* @__PURE__ */ (0,
|
|
3228
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "mt-3 text-[12px] text-muted-foreground", children: [
|
|
3229
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("kbd", { className: "cs-kbd", children: "\u2325\u2318N" }),
|
|
2821
3230
|
" new session \xB7 ",
|
|
2822
|
-
/* @__PURE__ */ (0,
|
|
3231
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("kbd", { className: "cs-kbd", children: "\u2318K" }),
|
|
2823
3232
|
" search your chats \xB7",
|
|
2824
3233
|
" ",
|
|
2825
|
-
/* @__PURE__ */ (0,
|
|
3234
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("kbd", { className: "cs-kbd", children: "\u2318/" }),
|
|
2826
3235
|
" all shortcuts"
|
|
2827
3236
|
] }),
|
|
2828
|
-
/* @__PURE__ */ (0,
|
|
2829
|
-
/* @__PURE__ */ (0,
|
|
2830
|
-
/* @__PURE__ */ (0,
|
|
2831
|
-
/* @__PURE__ */ (0,
|
|
2832
|
-
p.ready ? /* @__PURE__ */ (0,
|
|
3237
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-6 grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-1.5 text-left", children: state.providers.data.map((p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-[220px] items-start gap-2.5 rounded-lg border border-border px-3 py-2.5", children: [
|
|
3238
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ProviderMark, { provider: p.provider, size: 16 }),
|
|
3239
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "min-w-0 flex-1 text-[12.5px] leading-5", children: [
|
|
3240
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-medium", children: p.label }),
|
|
3241
|
+
p.ready ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
2833
3242
|
" ",
|
|
2834
3243
|
"\u2014 ready",
|
|
2835
3244
|
p.plan ? ` on your ${p.plan} plan` : "",
|
|
2836
3245
|
p.billing === "api" ? " (API key, billed per use)" : ""
|
|
2837
3246
|
] }) : null,
|
|
2838
|
-
p.installed && p.version ? /* @__PURE__ */ (0,
|
|
3247
|
+
p.installed && p.version ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2839
3248
|
"span",
|
|
2840
3249
|
{
|
|
2841
3250
|
className: "block text-[11.5px] text-muted-foreground",
|
|
@@ -2846,23 +3255,23 @@ function Home({ onNew }) {
|
|
|
2846
3255
|
]
|
|
2847
3256
|
}
|
|
2848
3257
|
) : null,
|
|
2849
|
-
p.ready ? null : /* @__PURE__ */ (0,
|
|
3258
|
+
p.ready ? null : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "block text-muted-foreground", children: [
|
|
2850
3259
|
p.problem,
|
|
2851
3260
|
" ",
|
|
2852
3261
|
p.fix
|
|
2853
3262
|
] })
|
|
2854
3263
|
] }),
|
|
2855
|
-
p.ready ? /* @__PURE__ */ (0,
|
|
3264
|
+
p.ready ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckIcon, { size: 15, className: "mt-0.5 text-success" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlertIcon, { size: 15, className: "mt-0.5 text-warning" })
|
|
2856
3265
|
] }, p.provider)) })
|
|
2857
3266
|
] }) });
|
|
2858
3267
|
}
|
|
2859
3268
|
function useToast() {
|
|
2860
|
-
const [text, setText] = (0,
|
|
2861
|
-
const timer = (0,
|
|
2862
|
-
(0,
|
|
3269
|
+
const [text, setText] = (0, import_react8.useState)(null);
|
|
3270
|
+
const timer = (0, import_react8.useRef)(null);
|
|
3271
|
+
(0, import_react8.useEffect)(() => () => {
|
|
2863
3272
|
if (timer.current) clearTimeout(timer.current);
|
|
2864
3273
|
}, []);
|
|
2865
|
-
const show = (0,
|
|
3274
|
+
const show = (0, import_react8.useCallback)((next) => {
|
|
2866
3275
|
setText(next);
|
|
2867
3276
|
if (timer.current) clearTimeout(timer.current);
|
|
2868
3277
|
timer.current = setTimeout(() => setText(null), 6e3);
|
|
@@ -2871,7 +3280,7 @@ function useToast() {
|
|
|
2871
3280
|
}
|
|
2872
3281
|
function Toast({ text }) {
|
|
2873
3282
|
if (!text) return null;
|
|
2874
|
-
return /* @__PURE__ */ (0,
|
|
3283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { role: "status", className: "cs-toast", children: text });
|
|
2875
3284
|
}
|
|
2876
3285
|
var SIDEBAR_DEFAULT = 300;
|
|
2877
3286
|
var SIDEBAR_MIN = 220;
|
|
@@ -2880,7 +3289,7 @@ function clampWidth(n) {
|
|
|
2880
3289
|
return Math.round(Math.min(SIDEBAR_MAX, Math.max(SIDEBAR_MIN, n)));
|
|
2881
3290
|
}
|
|
2882
3291
|
function useSidebarLayout() {
|
|
2883
|
-
const [width, setWidthState] = (0,
|
|
3292
|
+
const [width, setWidthState] = (0, import_react8.useState)(() => {
|
|
2884
3293
|
try {
|
|
2885
3294
|
const n = Number(localStorage.getItem("coding-sessions.sidebar-width"));
|
|
2886
3295
|
return Number.isFinite(n) && n > 0 ? clampWidth(n) : SIDEBAR_DEFAULT;
|
|
@@ -2888,14 +3297,14 @@ function useSidebarLayout() {
|
|
|
2888
3297
|
return SIDEBAR_DEFAULT;
|
|
2889
3298
|
}
|
|
2890
3299
|
});
|
|
2891
|
-
const [collapsed, setCollapsedState] = (0,
|
|
3300
|
+
const [collapsed, setCollapsedState] = (0, import_react8.useState)(() => {
|
|
2892
3301
|
try {
|
|
2893
3302
|
return localStorage.getItem("coding-sessions.sidebar-collapsed") === "1";
|
|
2894
3303
|
} catch {
|
|
2895
3304
|
return false;
|
|
2896
3305
|
}
|
|
2897
3306
|
});
|
|
2898
|
-
const setWidth = (0,
|
|
3307
|
+
const setWidth = (0, import_react8.useCallback)((n) => {
|
|
2899
3308
|
const next = clampWidth(n);
|
|
2900
3309
|
setWidthState(next);
|
|
2901
3310
|
try {
|
|
@@ -2903,7 +3312,7 @@ function useSidebarLayout() {
|
|
|
2903
3312
|
} catch {
|
|
2904
3313
|
}
|
|
2905
3314
|
}, []);
|
|
2906
|
-
const setCollapsed = (0,
|
|
3315
|
+
const setCollapsed = (0, import_react8.useCallback)((v) => {
|
|
2907
3316
|
setCollapsedState(v);
|
|
2908
3317
|
try {
|
|
2909
3318
|
localStorage.setItem("coding-sessions.sidebar-collapsed", v ? "1" : "0");
|
|
@@ -2913,8 +3322,8 @@ function useSidebarLayout() {
|
|
|
2913
3322
|
return { width, setWidth, collapsed, setCollapsed };
|
|
2914
3323
|
}
|
|
2915
3324
|
function Resizer(props) {
|
|
2916
|
-
const [dragging, setDragging] = (0,
|
|
2917
|
-
return /* @__PURE__ */ (0,
|
|
3325
|
+
const [dragging, setDragging] = (0, import_react8.useState)(false);
|
|
3326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: (0, import_design_system6.cn)("cs-resizer", dragging && "cs-resizer--dragging"), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2918
3327
|
"button",
|
|
2919
3328
|
{
|
|
2920
3329
|
type: "button",
|
|
@@ -2962,24 +3371,24 @@ var SHORTCUTS = [
|
|
|
2962
3371
|
{ keys: "\u2318/", what: "These shortcuts" }
|
|
2963
3372
|
];
|
|
2964
3373
|
function ShortcutsDialog(props) {
|
|
2965
|
-
return /* @__PURE__ */ (0,
|
|
2966
|
-
/* @__PURE__ */ (0,
|
|
2967
|
-
/* @__PURE__ */ (0,
|
|
2968
|
-
/* @__PURE__ */ (0,
|
|
3374
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.Dialog, { open: props.open, onOpenChange: props.onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogContent, { className: "max-w-[420px]", children: [
|
|
3375
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system6.DialogHeader, { children: [
|
|
3376
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.DialogTitle, { children: "Keyboard shortcuts" }),
|
|
3377
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system6.DialogDescription, { children: "Ctrl works in place of \u2318 on Windows and Linux." })
|
|
2969
3378
|
] }),
|
|
2970
|
-
/* @__PURE__ */ (0,
|
|
2971
|
-
/* @__PURE__ */ (0,
|
|
2972
|
-
/* @__PURE__ */ (0,
|
|
3379
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dl", { className: "divide-y divide-border text-[13px]", children: SHORTCUTS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between gap-4 py-2", children: [
|
|
3380
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dt", { className: "text-muted-foreground", children: s.what }),
|
|
3381
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("kbd", { className: "rounded border border-border px-1.5 py-0.5 font-sans text-[12px]", children: s.keys }) })
|
|
2973
3382
|
] }, s.keys)) })
|
|
2974
3383
|
] }) });
|
|
2975
3384
|
}
|
|
2976
3385
|
var BASE_TITLE = "Coding sessions";
|
|
2977
3386
|
function useRunFinishedNotices(openSessionId, show) {
|
|
2978
3387
|
const client = useCodingSessionsClient();
|
|
2979
|
-
const unseen = (0,
|
|
2980
|
-
const openRef = (0,
|
|
3388
|
+
const unseen = (0, import_react8.useRef)(0);
|
|
3389
|
+
const openRef = (0, import_react8.useRef)(openSessionId);
|
|
2981
3390
|
openRef.current = openSessionId;
|
|
2982
|
-
(0,
|
|
3391
|
+
(0, import_react8.useEffect)(() => {
|
|
2983
3392
|
const reset = () => {
|
|
2984
3393
|
if (document.visibilityState === "visible") {
|
|
2985
3394
|
unseen.current = 0;
|
|
@@ -3014,9 +3423,9 @@ function useRunFinishedNotices(openSessionId, show) {
|
|
|
3014
3423
|
}
|
|
3015
3424
|
function NotifyToggle() {
|
|
3016
3425
|
const supported = typeof Notification !== "undefined";
|
|
3017
|
-
const [permission, setPermission] = (0,
|
|
3426
|
+
const [permission, setPermission] = (0, import_react8.useState)(supported ? Notification.permission : "denied");
|
|
3018
3427
|
if (!supported || permission === "granted") return null;
|
|
3019
|
-
return /* @__PURE__ */ (0,
|
|
3428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3020
3429
|
"button",
|
|
3021
3430
|
{
|
|
3022
3431
|
type: "button",
|
|
@@ -3025,7 +3434,7 @@ function NotifyToggle() {
|
|
|
3025
3434
|
"aria-label": permission === "denied" ? "Notifications are blocked for this page in your browser's site settings" : "Notify me when a run finishes",
|
|
3026
3435
|
title: permission === "denied" ? "Notifications are blocked in your browser's site settings" : "Notify me when a run finishes",
|
|
3027
3436
|
disabled: permission === "denied",
|
|
3028
|
-
children: /* @__PURE__ */ (0,
|
|
3437
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BellIcon, { size: 14 })
|
|
3029
3438
|
}
|
|
3030
3439
|
);
|
|
3031
3440
|
}
|
|
@@ -3037,20 +3446,20 @@ function isTyping(target) {
|
|
|
3037
3446
|
function Shell() {
|
|
3038
3447
|
const client = useCodingSessionsClient();
|
|
3039
3448
|
const state = useCodingSessionsState();
|
|
3040
|
-
const [selection, setSelection] = (0,
|
|
3041
|
-
const [newOpen, setNewOpen] = (0,
|
|
3042
|
-
const [shortcutsOpen, setShortcutsOpen] = (0,
|
|
3043
|
-
const [changesOpen, setChangesOpen] = (0,
|
|
3044
|
-
const [found, setFound] = (0,
|
|
3449
|
+
const [selection, setSelection] = (0, import_react8.useState)(readHash);
|
|
3450
|
+
const [newOpen, setNewOpen] = (0, import_react8.useState)(false);
|
|
3451
|
+
const [shortcutsOpen, setShortcutsOpen] = (0, import_react8.useState)(false);
|
|
3452
|
+
const [changesOpen, setChangesOpen] = (0, import_react8.useState)(false);
|
|
3453
|
+
const [found, setFound] = (0, import_react8.useState)({});
|
|
3045
3454
|
const [theme, setTheme] = useTheme();
|
|
3046
3455
|
const [toast, showToast] = useToast();
|
|
3047
3456
|
const layout = useSidebarLayout();
|
|
3048
|
-
const searchRef = (0,
|
|
3049
|
-
const select = (0,
|
|
3457
|
+
const searchRef = (0, import_react8.useRef)(null);
|
|
3458
|
+
const select = (0, import_react8.useCallback)((next) => {
|
|
3050
3459
|
setSelection(next);
|
|
3051
3460
|
writeHash(next);
|
|
3052
3461
|
}, []);
|
|
3053
|
-
(0,
|
|
3462
|
+
(0, import_react8.useEffect)(() => {
|
|
3054
3463
|
const onHash = () => setSelection(readHash());
|
|
3055
3464
|
window.addEventListener("hashchange", onHash);
|
|
3056
3465
|
return () => window.removeEventListener("hashchange", onHash);
|
|
@@ -3060,14 +3469,14 @@ function Shell() {
|
|
|
3060
3469
|
const discovered = selection.kind === "discovered" ? state.discovered.data.find((d) => d.providerSessionId === selection.id) ?? found[`${selection.provider}:${selection.id}`] ?? null : null;
|
|
3061
3470
|
const run = session ? state.runs[session.id] : void 0;
|
|
3062
3471
|
const live = run !== void 0 && !isTerminalRunStatus(run.status);
|
|
3063
|
-
const order = (0,
|
|
3472
|
+
const order = (0, import_react8.useMemo)(() => {
|
|
3064
3473
|
const known = new Set(state.sessions.data.map((s) => s.providerSessionId).filter(Boolean));
|
|
3065
3474
|
return [
|
|
3066
3475
|
...state.sessions.data.map((s) => ({ kind: "session", id: s.id })),
|
|
3067
3476
|
...state.discovered.data.filter((d) => !known.has(d.providerSessionId)).map((d) => ({ kind: "discovered", provider: d.provider, id: d.providerSessionId }))
|
|
3068
3477
|
];
|
|
3069
3478
|
}, [state.sessions.data, state.discovered.data]);
|
|
3070
|
-
(0,
|
|
3479
|
+
(0, import_react8.useEffect)(() => {
|
|
3071
3480
|
const onKey = (e) => {
|
|
3072
3481
|
const mod = e.metaKey || e.ctrlKey;
|
|
3073
3482
|
const key = e.key.toLowerCase();
|
|
@@ -3123,12 +3532,12 @@ function Shell() {
|
|
|
3123
3532
|
}, [client, layout, live, run, order, selection, select, showToast]);
|
|
3124
3533
|
let main;
|
|
3125
3534
|
if (selection.kind === "session") {
|
|
3126
|
-
main = session ? /* @__PURE__ */ (0,
|
|
3127
|
-
/* @__PURE__ */ (0,
|
|
3535
|
+
main = session ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SessionView, { session, changesOpen, setChangesOpen }, session.id) : state.sessions.loadedAt === null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-1 items-center justify-center gap-2 text-[13px] text-muted-foreground", children: [
|
|
3536
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SpinnerIcon, { size: 15 }),
|
|
3128
3537
|
" Loading\u2026"
|
|
3129
|
-
] }) : /* @__PURE__ */ (0,
|
|
3538
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-1 items-center justify-center text-[13px] text-muted-foreground", children: "That session is not in the list anymore." });
|
|
3130
3539
|
} else if (selection.kind === "discovered") {
|
|
3131
|
-
main = /* @__PURE__ */ (0,
|
|
3540
|
+
main = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3132
3541
|
DiscoveredView,
|
|
3133
3542
|
{
|
|
3134
3543
|
session: discovered,
|
|
@@ -3141,13 +3550,13 @@ function Shell() {
|
|
|
3141
3550
|
`${selection.provider}:${selection.id}`
|
|
3142
3551
|
);
|
|
3143
3552
|
} else {
|
|
3144
|
-
main = /* @__PURE__ */ (0,
|
|
3553
|
+
main = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Home, { onNew: () => setNewOpen(true) });
|
|
3145
3554
|
}
|
|
3146
|
-
return /* @__PURE__ */ (0,
|
|
3147
|
-
/* @__PURE__ */ (0,
|
|
3148
|
-
/* @__PURE__ */ (0,
|
|
3149
|
-
layout.collapsed ? /* @__PURE__ */ (0,
|
|
3150
|
-
/* @__PURE__ */ (0,
|
|
3555
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToastContext.Provider, { value: showToast, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "cs-app flex h-full flex-col bg-background text-foreground", children: [
|
|
3556
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ConnectionBanner, {}),
|
|
3557
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-h-0 flex-1", children: [
|
|
3558
|
+
layout.collapsed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col items-center gap-1 border-r border-border bg-muted/30 px-1.5 py-3", children: [
|
|
3559
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3151
3560
|
"button",
|
|
3152
3561
|
{
|
|
3153
3562
|
type: "button",
|
|
@@ -3155,10 +3564,10 @@ function Shell() {
|
|
|
3155
3564
|
onClick: () => layout.setCollapsed(false),
|
|
3156
3565
|
"aria-label": "Show the sidebar (\u2318B)",
|
|
3157
3566
|
title: "Show sidebar \u2318B",
|
|
3158
|
-
children: /* @__PURE__ */ (0,
|
|
3567
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SidebarIcon, { size: 15 })
|
|
3159
3568
|
}
|
|
3160
3569
|
),
|
|
3161
|
-
/* @__PURE__ */ (0,
|
|
3570
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3162
3571
|
"button",
|
|
3163
3572
|
{
|
|
3164
3573
|
type: "button",
|
|
@@ -3166,11 +3575,11 @@ function Shell() {
|
|
|
3166
3575
|
onClick: () => setNewOpen(true),
|
|
3167
3576
|
"aria-label": "New session",
|
|
3168
3577
|
title: "New session \u2325\u2318N",
|
|
3169
|
-
children: /* @__PURE__ */ (0,
|
|
3578
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PlusIcon, { size: 15 })
|
|
3170
3579
|
}
|
|
3171
3580
|
)
|
|
3172
|
-
] }) : /* @__PURE__ */ (0,
|
|
3173
|
-
/* @__PURE__ */ (0,
|
|
3581
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
3582
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3174
3583
|
Sidebar,
|
|
3175
3584
|
{
|
|
3176
3585
|
selection,
|
|
@@ -3180,14 +3589,14 @@ function Shell() {
|
|
|
3180
3589
|
width: layout.width,
|
|
3181
3590
|
searchRef,
|
|
3182
3591
|
onFound: (d) => setFound((f) => ({ ...f, [`${d.provider}:${d.providerSessionId}`]: d })),
|
|
3183
|
-
footer: /* @__PURE__ */ (0,
|
|
3592
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3184
3593
|
ProvidersFooter,
|
|
3185
3594
|
{
|
|
3186
3595
|
theme,
|
|
3187
3596
|
setTheme,
|
|
3188
|
-
extra: /* @__PURE__ */ (0,
|
|
3189
|
-
/* @__PURE__ */ (0,
|
|
3190
|
-
/* @__PURE__ */ (0,
|
|
3597
|
+
extra: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
3598
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(NotifyToggle, {}),
|
|
3599
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3191
3600
|
"button",
|
|
3192
3601
|
{
|
|
3193
3602
|
type: "button",
|
|
@@ -3195,7 +3604,7 @@ function Shell() {
|
|
|
3195
3604
|
onClick: () => setShortcutsOpen(true),
|
|
3196
3605
|
"aria-label": "Keyboard shortcuts (\u2318/)",
|
|
3197
3606
|
title: "Keyboard shortcuts \u2318/",
|
|
3198
|
-
children: /* @__PURE__ */ (0,
|
|
3607
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(KeyboardIcon, { size: 14 })
|
|
3199
3608
|
}
|
|
3200
3609
|
)
|
|
3201
3610
|
] })
|
|
@@ -3203,11 +3612,11 @@ function Shell() {
|
|
|
3203
3612
|
)
|
|
3204
3613
|
}
|
|
3205
3614
|
),
|
|
3206
|
-
/* @__PURE__ */ (0,
|
|
3615
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Resizer, { width: layout.width, setWidth: layout.setWidth })
|
|
3207
3616
|
] }),
|
|
3208
|
-
/* @__PURE__ */ (0,
|
|
3617
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("main", { className: "flex min-w-0 flex-1", children: main })
|
|
3209
3618
|
] }),
|
|
3210
|
-
/* @__PURE__ */ (0,
|
|
3619
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3211
3620
|
NewSessionDialog,
|
|
3212
3621
|
{
|
|
3213
3622
|
open: newOpen,
|
|
@@ -3218,11 +3627,11 @@ function Shell() {
|
|
|
3218
3627
|
}
|
|
3219
3628
|
}
|
|
3220
3629
|
),
|
|
3221
|
-
/* @__PURE__ */ (0,
|
|
3222
|
-
/* @__PURE__ */ (0,
|
|
3630
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ShortcutsDialog, { open: shortcutsOpen, onOpenChange: setShortcutsOpen }),
|
|
3631
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Toast, { text: toast })
|
|
3223
3632
|
] }) });
|
|
3224
3633
|
}
|
|
3225
3634
|
function CodingSessionsApp({ transport }) {
|
|
3226
|
-
return /* @__PURE__ */ (0,
|
|
3635
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CodingSessionsProvider, { transport, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, {}) });
|
|
3227
3636
|
}
|
|
3228
3637
|
//# sourceMappingURL=index.cjs.map
|