research-copilot 0.2.0 → 0.2.2
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/app/out/main/index.mjs +3222 -412
- package/app/out/preload/index.js +26 -0
- package/app/out/renderer/assets/{MilkdownMarkdownEditor-Czh2N6UQ.js → MilkdownMarkdownEditor-jaF-aGPn.js} +50 -50
- package/app/out/renderer/assets/{arc-BWoErJNa.js → arc-C1kBmvvR.js} +1 -1
- package/app/out/renderer/assets/{blockDiagram-c4efeb88-Bod-vAlS.js → blockDiagram-c4efeb88-Do93X2rs.js} +8 -8
- package/app/out/renderer/assets/{c4Diagram-c83219d4-CTVUA_li.js → c4Diagram-c83219d4-DgxxcZWC.js} +3 -3
- package/app/out/renderer/assets/{channel-CxGr5Q5E.js → channel-Co_M0Svj.js} +1 -1
- package/app/out/renderer/assets/{classDiagram-beda092f-DABwUrsU.js → classDiagram-beda092f-CQlHgE6H.js} +6 -6
- package/app/out/renderer/assets/{classDiagram-v2-2358418a-CFt8hqf5.js → classDiagram-v2-2358418a-CkGG3aI2.js} +10 -10
- package/app/out/renderer/assets/{clone-BL91dKYn.js → clone-C18Y6dgC.js} +1 -1
- package/app/out/renderer/assets/{createText-1719965b-DGkv4rEO.js → createText-1719965b-DGRc6nys.js} +2 -2
- package/app/out/renderer/assets/{edges-96097737-Gf41lQOd.js → edges-96097737-BXvJ4fAK.js} +3 -3
- package/app/out/renderer/assets/{erDiagram-0228fc6a-Dj75BiRy.js → erDiagram-0228fc6a-CXjPp0pt.js} +5 -5
- package/app/out/renderer/assets/{flowDb-c6c81e3f-C_xVBMxS.js → flowDb-c6c81e3f-CNhpbtw_.js} +1 -1
- package/app/out/renderer/assets/{flowDiagram-50d868cf-B-lLn2XC.js → flowDiagram-50d868cf-KZ_BUCPA.js} +12 -12
- package/app/out/renderer/assets/{flowDiagram-v2-4f6560a1-BFnLU3PE.js → flowDiagram-v2-4f6560a1-IMv50KZP.js} +12 -12
- package/app/out/renderer/assets/{flowchart-elk-definition-6af322e1-DmjfyXbt.js → flowchart-elk-definition-6af322e1-BFwFiPvq.js} +6 -6
- package/app/out/renderer/assets/{ganttDiagram-a2739b55-BTPRekAy.js → ganttDiagram-a2739b55-D0-ehN-T.js} +3 -3
- package/app/out/renderer/assets/{gitGraphDiagram-82fe8481-1riYxgGS.js → gitGraphDiagram-82fe8481-DUyIR0Dv.js} +2 -2
- package/app/out/renderer/assets/{graph-CvDtMlX-.js → graph-DnTq2_3F.js} +1 -1
- package/app/out/renderer/assets/{index-5325376f-BGaoNMNN.js → index-5325376f-CBwuFbRF.js} +6 -6
- package/app/out/renderer/assets/{index-8tvmsRje.js → index-7hDGClrI.js} +3 -3
- package/app/out/renderer/assets/{index-CUPy7R5v.js → index-BB-a1ajC.js} +2122 -471
- package/app/out/renderer/assets/{index-Bii7x9Rr.js → index-BHcU72Rm.js} +3 -3
- package/app/out/renderer/assets/{index-qS7qbXvX.js → index-BQ7qz1CD.js} +3 -3
- package/app/out/renderer/assets/{index-DrvR7Peq.js → index-BVYoMX5H.js} +3 -3
- package/app/out/renderer/assets/{index-CXN1f9OT.js → index-BpKrXGYD.js} +3 -3
- package/app/out/renderer/assets/{index-0kPJXDfu.js → index-C1oXjI4L.js} +3 -3
- package/app/out/renderer/assets/{index-BK5rYWMs.js → index-CKXwBmK7.js} +5 -5
- package/app/out/renderer/assets/{index-B9lieynj.js → index-COZSDrEw.js} +6 -6
- package/app/out/renderer/assets/{index-Ctwkk-AW.css → index-CT1HtzVp.css} +165 -14
- package/app/out/renderer/assets/{index-zr8uxb8p.js → index-CjffvluT.js} +6 -6
- package/app/out/renderer/assets/{index-CnL9yPzK.js → index-D6jljsup.js} +3 -3
- package/app/out/renderer/assets/{index-BxOmAXUZ.js → index-D6r8msaQ.js} +3 -3
- package/app/out/renderer/assets/{index-D2fFfHUR.js → index-DWU4ia28.js} +6 -6
- package/app/out/renderer/assets/{index-BVNrdWzl.js → index-DZbrRR7w.js} +6 -6
- package/app/out/renderer/assets/{index-BCOrnr8q.js → index-Diy30-34.js} +4 -4
- package/app/out/renderer/assets/{index-NHbUPOmb.js → index-DuhageEr.js} +3 -3
- package/app/out/renderer/assets/{index-BnRwUKpv.js → index-ESFHcvWy.js} +3 -3
- package/app/out/renderer/assets/{index-B4djqBxS.js → index-JT8OCsRP.js} +1 -1
- package/app/out/renderer/assets/{index-cAZJ88Np.js → index-bMe3RSkw.js} +6 -6
- package/app/out/renderer/assets/{index-3LdRym1K.js → index-gH-w4EHk.js} +3 -3
- package/app/out/renderer/assets/{index-O3gvL3-Z.js → index-h_fNksib.js} +3 -3
- package/app/out/renderer/assets/{index-y5XZ-0EB.js → index-u0FZRZON.js} +4 -4
- package/app/out/renderer/assets/{index-BgSz3yUy.js → index-yanwpi6t.js} +6 -6
- package/app/out/renderer/assets/{infoDiagram-8eee0895-Cq8aXV8u.js → infoDiagram-8eee0895-Qra4japr.js} +2 -2
- package/app/out/renderer/assets/{journeyDiagram-c64418c1-D4ewDrYD.js → journeyDiagram-c64418c1-BTN9SgOL.js} +4 -4
- package/app/out/renderer/assets/{layout-CZmLZO9t.js → layout-DGrHHJdN.js} +2 -2
- package/app/out/renderer/assets/{line-D7kWOiRx.js → line-DXtxdS2B.js} +1 -1
- package/app/out/renderer/assets/{linear-B055Dz0c.js → linear-CexrSQK6.js} +1 -1
- package/app/out/renderer/assets/{mindmap-definition-8da855dc-D6EW4QCj.js → mindmap-definition-8da855dc-pvG2hzEB.js} +3 -3
- package/app/out/renderer/assets/{pieDiagram-a8764435-BX_Dz4T9.js → pieDiagram-a8764435-D_neFVMq.js} +3 -3
- package/app/out/renderer/assets/{quadrantDiagram-1e28029f-BsI6xGsm.js → quadrantDiagram-1e28029f-C47W3UMp.js} +3 -3
- package/app/out/renderer/assets/{requirementDiagram-08caed73-c2d8T0BS.js → requirementDiagram-08caed73-DW4Bo_fu.js} +5 -5
- package/app/out/renderer/assets/{sankeyDiagram-a04cb91d-CkDhRKRC.js → sankeyDiagram-a04cb91d-D_3PD7JI.js} +2 -2
- package/app/out/renderer/assets/{sequenceDiagram-c5b8d532-DS0RKYnD.js → sequenceDiagram-c5b8d532-BW6nGtuQ.js} +3 -3
- package/app/out/renderer/assets/{stateDiagram-1ecb1508-BjTK27QX.js → stateDiagram-1ecb1508-CDgBJ3-T.js} +6 -6
- package/app/out/renderer/assets/{stateDiagram-v2-c2b004d7-D1wWbeR3.js → stateDiagram-v2-c2b004d7-CBw5TtXo.js} +10 -10
- package/app/out/renderer/assets/{styles-b4e223ce-DXUfbXTM.js → styles-b4e223ce-DeeiEsuW.js} +1 -1
- package/app/out/renderer/assets/{styles-ca3715f6-CE_JRTmB.js → styles-ca3715f6-CMpiebrG.js} +1 -1
- package/app/out/renderer/assets/{styles-d45a18b0-CdtAXXSE.js → styles-d45a18b0-CZe9hU7H.js} +4 -4
- package/app/out/renderer/assets/{svgDrawCommon-b86b1483-dCxPWgBl.js → svgDrawCommon-b86b1483-CmJZfZzJ.js} +1 -1
- package/app/out/renderer/assets/{timeline-definition-faaaa080-B7ZP3Dqw.js → timeline-definition-faaaa080-Beo2kiiz.js} +3 -3
- package/app/out/renderer/assets/{xychartDiagram-f5964ef8-CXagmo1Q.js → xychartDiagram-f5964ef8-DYmo7moz.js} +5 -5
- package/app/out/renderer/index.html +2 -2
- package/app/package.json +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./MilkdownMarkdownEditor-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./MilkdownMarkdownEditor-jaF-aGPn.js","./MilkdownMarkdownEditor-tTNRIB2K.css"])))=>i.map(i=>d[i]);
|
|
2
2
|
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
3
3
|
function getDefaultExportFromCjs(x) {
|
|
4
4
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
@@ -12641,6 +12641,27 @@ const ChevronRight = createLucideIcon("ChevronRight", [
|
|
|
12641
12641
|
* See the LICENSE file in the root directory of this source tree.
|
|
12642
12642
|
*/
|
|
12643
12643
|
const ChevronUp = createLucideIcon("ChevronUp", [["path", { d: "m18 15-6-6-6 6", key: "153udz" }]]);
|
|
12644
|
+
/**
|
|
12645
|
+
* @license lucide-react v0.469.0 - ISC
|
|
12646
|
+
*
|
|
12647
|
+
* This source code is licensed under the ISC license.
|
|
12648
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
12649
|
+
*/
|
|
12650
|
+
const CircleAlert = createLucideIcon("CircleAlert", [
|
|
12651
|
+
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
12652
|
+
["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
|
|
12653
|
+
["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
|
|
12654
|
+
]);
|
|
12655
|
+
/**
|
|
12656
|
+
* @license lucide-react v0.469.0 - ISC
|
|
12657
|
+
*
|
|
12658
|
+
* This source code is licensed under the ISC license.
|
|
12659
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
12660
|
+
*/
|
|
12661
|
+
const CircleCheck = createLucideIcon("CircleCheck", [
|
|
12662
|
+
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
12663
|
+
["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
|
|
12664
|
+
]);
|
|
12644
12665
|
/**
|
|
12645
12666
|
* @license lucide-react v0.469.0 - ISC
|
|
12646
12667
|
*
|
|
@@ -12681,23 +12702,6 @@ const Database = createLucideIcon("Database", [
|
|
|
12681
12702
|
["path", { d: "M3 5V19A9 3 0 0 0 21 19V5", key: "1wlel7" }],
|
|
12682
12703
|
["path", { d: "M3 12A9 3 0 0 0 21 12", key: "mv7ke4" }]
|
|
12683
12704
|
]);
|
|
12684
|
-
/**
|
|
12685
|
-
* @license lucide-react v0.469.0 - ISC
|
|
12686
|
-
*
|
|
12687
|
-
* This source code is licensed under the ISC license.
|
|
12688
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
12689
|
-
*/
|
|
12690
|
-
const Eraser = createLucideIcon("Eraser", [
|
|
12691
|
-
[
|
|
12692
|
-
"path",
|
|
12693
|
-
{
|
|
12694
|
-
d: "m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21",
|
|
12695
|
-
key: "182aya"
|
|
12696
|
-
}
|
|
12697
|
-
],
|
|
12698
|
-
["path", { d: "M22 21H7", key: "t4ddhn" }],
|
|
12699
|
-
["path", { d: "m5 11 9 9", key: "1mo9qw" }]
|
|
12700
|
-
]);
|
|
12701
12705
|
/**
|
|
12702
12706
|
* @license lucide-react v0.469.0 - ISC
|
|
12703
12707
|
*
|
|
@@ -12883,6 +12887,28 @@ const GitBranch = createLucideIcon("GitBranch", [
|
|
|
12883
12887
|
["circle", { cx: "6", cy: "18", r: "3", key: "fqmcym" }],
|
|
12884
12888
|
["path", { d: "M18 9a9 9 0 0 1-9 9", key: "n2h4wq" }]
|
|
12885
12889
|
]);
|
|
12890
|
+
/**
|
|
12891
|
+
* @license lucide-react v0.469.0 - ISC
|
|
12892
|
+
*
|
|
12893
|
+
* This source code is licensed under the ISC license.
|
|
12894
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
12895
|
+
*/
|
|
12896
|
+
const Globe = createLucideIcon("Globe", [
|
|
12897
|
+
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
12898
|
+
["path", { d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20", key: "13o1zl" }],
|
|
12899
|
+
["path", { d: "M2 12h20", key: "9i4pu4" }]
|
|
12900
|
+
]);
|
|
12901
|
+
/**
|
|
12902
|
+
* @license lucide-react v0.469.0 - ISC
|
|
12903
|
+
*
|
|
12904
|
+
* This source code is licensed under the ISC license.
|
|
12905
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
12906
|
+
*/
|
|
12907
|
+
const Info$1 = createLucideIcon("Info", [
|
|
12908
|
+
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
12909
|
+
["path", { d: "M12 16v-4", key: "1dtifu" }],
|
|
12910
|
+
["path", { d: "M12 8h.01", key: "e9boi3" }]
|
|
12911
|
+
]);
|
|
12886
12912
|
/**
|
|
12887
12913
|
* @license lucide-react v0.469.0 - ISC
|
|
12888
12914
|
*
|
|
@@ -12920,6 +12946,28 @@ const Lightbulb = createLucideIcon("Lightbulb", [
|
|
|
12920
12946
|
const LoaderCircle = createLucideIcon("LoaderCircle", [
|
|
12921
12947
|
["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]
|
|
12922
12948
|
]);
|
|
12949
|
+
/**
|
|
12950
|
+
* @license lucide-react v0.469.0 - ISC
|
|
12951
|
+
*
|
|
12952
|
+
* This source code is licensed under the ISC license.
|
|
12953
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
12954
|
+
*/
|
|
12955
|
+
const LogIn = createLucideIcon("LogIn", [
|
|
12956
|
+
["path", { d: "M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4", key: "u53s6r" }],
|
|
12957
|
+
["polyline", { points: "10 17 15 12 10 7", key: "1ail0h" }],
|
|
12958
|
+
["line", { x1: "15", x2: "3", y1: "12", y2: "12", key: "v6grx8" }]
|
|
12959
|
+
]);
|
|
12960
|
+
/**
|
|
12961
|
+
* @license lucide-react v0.469.0 - ISC
|
|
12962
|
+
*
|
|
12963
|
+
* This source code is licensed under the ISC license.
|
|
12964
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
12965
|
+
*/
|
|
12966
|
+
const LogOut = createLucideIcon("LogOut", [
|
|
12967
|
+
["path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4", key: "1uf3rs" }],
|
|
12968
|
+
["polyline", { points: "16 17 21 12 16 7", key: "1gabdz" }],
|
|
12969
|
+
["line", { x1: "21", x2: "9", y1: "12", y2: "12", key: "1uyos4" }]
|
|
12970
|
+
]);
|
|
12923
12971
|
/**
|
|
12924
12972
|
* @license lucide-react v0.469.0 - ISC
|
|
12925
12973
|
*
|
|
@@ -12929,6 +12977,17 @@ const LoaderCircle = createLucideIcon("LoaderCircle", [
|
|
|
12929
12977
|
const MessageSquare = createLucideIcon("MessageSquare", [
|
|
12930
12978
|
["path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z", key: "1lielz" }]
|
|
12931
12979
|
]);
|
|
12980
|
+
/**
|
|
12981
|
+
* @license lucide-react v0.469.0 - ISC
|
|
12982
|
+
*
|
|
12983
|
+
* This source code is licensed under the ISC license.
|
|
12984
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
12985
|
+
*/
|
|
12986
|
+
const Monitor = createLucideIcon("Monitor", [
|
|
12987
|
+
["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
|
|
12988
|
+
["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
|
|
12989
|
+
["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
|
|
12990
|
+
]);
|
|
12932
12991
|
/**
|
|
12933
12992
|
* @license lucide-react v0.469.0 - ISC
|
|
12934
12993
|
*
|
|
@@ -13182,6 +13241,21 @@ const Upload = createLucideIcon("Upload", [
|
|
|
13182
13241
|
["polyline", { points: "17 8 12 3 7 8", key: "t8dd8p" }],
|
|
13183
13242
|
["line", { x1: "12", x2: "12", y1: "3", y2: "15", key: "widbto" }]
|
|
13184
13243
|
]);
|
|
13244
|
+
/**
|
|
13245
|
+
* @license lucide-react v0.469.0 - ISC
|
|
13246
|
+
*
|
|
13247
|
+
* This source code is licensed under the ISC license.
|
|
13248
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
13249
|
+
*/
|
|
13250
|
+
const Wrench = createLucideIcon("Wrench", [
|
|
13251
|
+
[
|
|
13252
|
+
"path",
|
|
13253
|
+
{
|
|
13254
|
+
d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z",
|
|
13255
|
+
key: "cbrjhi"
|
|
13256
|
+
}
|
|
13257
|
+
]
|
|
13258
|
+
]);
|
|
13185
13259
|
/**
|
|
13186
13260
|
* @license lucide-react v0.469.0 - ISC
|
|
13187
13261
|
*
|
|
@@ -13207,7 +13281,7 @@ const Zap = createLucideIcon("Zap", [
|
|
|
13207
13281
|
}
|
|
13208
13282
|
]
|
|
13209
13283
|
]);
|
|
13210
|
-
const api$
|
|
13284
|
+
const api$b = window.api;
|
|
13211
13285
|
const KEY_FIELDS = [
|
|
13212
13286
|
{
|
|
13213
13287
|
name: "ANTHROPIC_API_KEY",
|
|
@@ -13248,21 +13322,40 @@ function ApiKeySetup({ onComplete }) {
|
|
|
13248
13322
|
const [visible, setVisible] = reactExports.useState({});
|
|
13249
13323
|
const [saving, setSaving] = reactExports.useState(false);
|
|
13250
13324
|
const [error, setError] = reactExports.useState(null);
|
|
13325
|
+
const [codexStatus, setCodexStatus] = reactExports.useState(null);
|
|
13326
|
+
const [codexLoggingIn, setCodexLoggingIn] = reactExports.useState(false);
|
|
13251
13327
|
reactExports.useEffect(() => {
|
|
13252
|
-
api$
|
|
13328
|
+
api$b.getApiKeyStatus().then((s15) => setStatus(s15));
|
|
13329
|
+
api$b.getOpenAICodexStatus?.().then((s15) => setCodexStatus(s15)).catch(() => {
|
|
13330
|
+
});
|
|
13253
13331
|
}, []);
|
|
13254
|
-
const
|
|
13332
|
+
const handleCodexLogin = async () => {
|
|
13333
|
+
setCodexLoggingIn(true);
|
|
13334
|
+
try {
|
|
13335
|
+
const result = await api$b.openaiCodexLogin?.();
|
|
13336
|
+
if (result?.success) {
|
|
13337
|
+
setCodexStatus({ isLoggedIn: true });
|
|
13338
|
+
} else {
|
|
13339
|
+
setError(result?.error || "ChatGPT sign-in failed");
|
|
13340
|
+
}
|
|
13341
|
+
} catch (err) {
|
|
13342
|
+
setError(err.message || "ChatGPT sign-in failed");
|
|
13343
|
+
} finally {
|
|
13344
|
+
setCodexLoggingIn(false);
|
|
13345
|
+
}
|
|
13346
|
+
};
|
|
13347
|
+
const hasAnyLlmKey = status.ANTHROPIC_API_KEY || status.OPENAI_API_KEY || codexStatus?.isLoggedIn || !!(values.ANTHROPIC_API_KEY || "").trim() || !!(values.OPENAI_API_KEY || "").trim();
|
|
13255
13348
|
const handleSave = async () => {
|
|
13256
13349
|
const entries = Object.entries(values).filter(([, v3]) => v3.trim());
|
|
13257
|
-
if (entries.length === 0 && !status.ANTHROPIC_API_KEY && !status.OPENAI_API_KEY) {
|
|
13258
|
-
setError("Please enter at least one API key
|
|
13350
|
+
if (entries.length === 0 && !status.ANTHROPIC_API_KEY && !status.OPENAI_API_KEY && !codexStatus?.isLoggedIn) {
|
|
13351
|
+
setError("Please enter at least one API key or sign in with ChatGPT to continue.");
|
|
13259
13352
|
return;
|
|
13260
13353
|
}
|
|
13261
13354
|
setSaving(true);
|
|
13262
13355
|
setError(null);
|
|
13263
13356
|
try {
|
|
13264
13357
|
for (const [key, val] of entries) {
|
|
13265
|
-
await api$
|
|
13358
|
+
await api$b.saveApiKey(key, val);
|
|
13266
13359
|
}
|
|
13267
13360
|
onComplete();
|
|
13268
13361
|
} catch (err) {
|
|
@@ -13278,11 +13371,7 @@ function ApiKeySetup({ onComplete }) {
|
|
|
13278
13371
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "relative mx-auto mb-6 w-fit", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13279
13372
|
"div",
|
|
13280
13373
|
{
|
|
13281
|
-
className: "w-14 h-14 rounded-2xl flex items-center justify-center",
|
|
13282
|
-
style: {
|
|
13283
|
-
background: "linear-gradient(135deg, var(--color-accent) 0%, var(--color-accent-2) 100%)",
|
|
13284
|
-
boxShadow: "0 8px 32px var(--color-accent-2-muted)"
|
|
13285
|
-
},
|
|
13374
|
+
className: "w-14 h-14 rounded-2xl flex items-center justify-center t-gradient-accent t-gradient-accent-shadow-lg",
|
|
13286
13375
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Key, { className: "text-white", size: 22 })
|
|
13287
13376
|
}
|
|
13288
13377
|
) }),
|
|
@@ -13333,7 +13422,8 @@ function ApiKeySetup({ onComplete }) {
|
|
|
13333
13422
|
className: "w-full text-xs px-2.5 py-1.5 rounded-md border t-border t-bg-base t-text font-mono pr-8\n focus:outline-none focus:ring-1 focus:ring-[var(--color-accent)]",
|
|
13334
13423
|
placeholder: alreadySet ? "•••••••• (already set — leave blank to keep)" : field.placeholder,
|
|
13335
13424
|
value: values[field.name] || "",
|
|
13336
|
-
onChange: (e) => setValues((prev) => ({ ...prev, [field.name]: e.target.value }))
|
|
13425
|
+
onChange: (e) => setValues((prev) => ({ ...prev, [field.name]: e.target.value })),
|
|
13426
|
+
"aria-label": `${field.label} API key`
|
|
13337
13427
|
}
|
|
13338
13428
|
),
|
|
13339
13429
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -13350,10 +13440,33 @@ function ApiKeySetup({ onComplete }) {
|
|
|
13350
13440
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] t-text-muted mt-1", children: field.hint })
|
|
13351
13441
|
] }, field.name);
|
|
13352
13442
|
}) }),
|
|
13353
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
13354
|
-
|
|
13443
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg border t-border t-bg-surface/50 p-3", children: [
|
|
13444
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-between mb-1.5", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "text-xs font-medium t-text flex items-center gap-1.5", children: [
|
|
13445
|
+
"ChatGPT Subscription",
|
|
13446
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] t-text-muted", children: "(alternative to OpenAI API key)" }),
|
|
13447
|
+
codexStatus?.isLoggedIn && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-0.5 text-[10px] text-green-500", children: [
|
|
13448
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 10 }),
|
|
13449
|
+
" signed in"
|
|
13450
|
+
] })
|
|
13451
|
+
] }) }),
|
|
13452
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
13453
|
+
"button",
|
|
13454
|
+
{
|
|
13455
|
+
onClick: handleCodexLogin,
|
|
13456
|
+
disabled: codexLoggingIn || codexStatus?.isLoggedIn,
|
|
13457
|
+
className: "flex items-center gap-1.5 px-3 py-1.5 rounded-md border t-border text-xs t-text-secondary hover:t-text t-bg-hover disabled:opacity-50",
|
|
13458
|
+
children: [
|
|
13459
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LogIn, { size: 12 }),
|
|
13460
|
+
codexLoggingIn ? "Signing in..." : codexStatus?.isLoggedIn ? "Already signed in" : "Sign in with ChatGPT"
|
|
13461
|
+
]
|
|
13462
|
+
}
|
|
13463
|
+
),
|
|
13464
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] t-text-muted mt-1", children: "Use your ChatGPT Plus/Pro subscription instead of an API key. No per-token billing." })
|
|
13465
|
+
] }),
|
|
13466
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] t-text-muted mb-1", children: "* You need at least one of Anthropic or OpenAI (API key or ChatGPT subscription)." }),
|
|
13467
|
+
error && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-red-400 mb-3", role: "alert", children: error }),
|
|
13355
13468
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
13356
|
-
(status.ANTHROPIC_API_KEY || status.OPENAI_API_KEY) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13469
|
+
(status.ANTHROPIC_API_KEY || status.OPENAI_API_KEY || codexStatus?.isLoggedIn) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
13357
13470
|
"button",
|
|
13358
13471
|
{
|
|
13359
13472
|
onClick: onComplete,
|
|
@@ -13367,11 +13480,7 @@ function ApiKeySetup({ onComplete }) {
|
|
|
13367
13480
|
{
|
|
13368
13481
|
onClick: handleSave,
|
|
13369
13482
|
disabled: saving,
|
|
13370
|
-
className: "px-5 py-2 rounded-lg text-white text-sm font-medium hover:opacity-90 transition-all duration-200 disabled:opacity-50",
|
|
13371
|
-
style: {
|
|
13372
|
-
background: "linear-gradient(135deg, var(--color-accent) 0%, var(--color-accent-2) 100%)",
|
|
13373
|
-
boxShadow: "0 4px 16px var(--color-accent-2-muted)"
|
|
13374
|
-
},
|
|
13483
|
+
className: "px-5 py-2 rounded-lg text-white text-sm font-medium hover:opacity-90 transition-all duration-200 disabled:opacity-50 t-gradient-accent t-gradient-accent-shadow",
|
|
13375
13484
|
children: saving ? "Saving..." : hasAnyLlmKey ? "Save & Continue" : "Save & Continue"
|
|
13376
13485
|
}
|
|
13377
13486
|
)
|
|
@@ -13418,11 +13527,44 @@ const createImpl = (createState2) => {
|
|
|
13418
13527
|
return useBoundStore;
|
|
13419
13528
|
};
|
|
13420
13529
|
const create$1 = (createState2) => createState2 ? createImpl(createState2) : createImpl;
|
|
13530
|
+
const REASONING_MODELS = [
|
|
13531
|
+
"openai:gpt-5.4",
|
|
13532
|
+
"openai:gpt-5.4-mini",
|
|
13533
|
+
"openai:gpt-5.4-nano",
|
|
13534
|
+
"openai-codex:gpt-5.4",
|
|
13535
|
+
"openai-codex:gpt-5.4-mini",
|
|
13536
|
+
"openai-codex:gpt-5.4-nano",
|
|
13537
|
+
"anthropic:claude-opus-4-6"
|
|
13538
|
+
];
|
|
13539
|
+
const SUPPORTED_MODELS = [
|
|
13540
|
+
// OpenAI (API key)
|
|
13541
|
+
{ id: "openai:gpt-5.4", label: "GPT-5.4", provider: "OpenAI" },
|
|
13542
|
+
{ id: "openai:gpt-5.4-mini", label: "GPT-5.4 Mini", provider: "OpenAI" },
|
|
13543
|
+
{ id: "openai:gpt-5.4-nano", label: "GPT-5.4 Nano", provider: "OpenAI" },
|
|
13544
|
+
{ id: "openai:gpt-4o", label: "GPT-4o", provider: "OpenAI" },
|
|
13545
|
+
// ChatGPT Subscription (OAuth)
|
|
13546
|
+
{ id: "openai-codex:gpt-5.4", label: "GPT-5.4", provider: "ChatGPT Subscription" },
|
|
13547
|
+
{ id: "openai-codex:gpt-5.4-mini", label: "GPT-5.4 Mini", provider: "ChatGPT Subscription" },
|
|
13548
|
+
{ id: "openai-codex:gpt-5.4-pro", label: "GPT-5.4 Pro", provider: "ChatGPT Subscription" },
|
|
13549
|
+
// Anthropic (API key)
|
|
13550
|
+
{ id: "anthropic:claude-opus-4-6", label: "Claude Opus 4.6", provider: "Anthropic" },
|
|
13551
|
+
{ id: "anthropic:claude-opus-4-5-20251101", label: "Claude Opus 4.5", provider: "Anthropic" },
|
|
13552
|
+
{ id: "anthropic:claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5", provider: "Anthropic" },
|
|
13553
|
+
{ id: "anthropic:claude-haiku-4-5-20251001", label: "Claude Haiku 4.5", provider: "Anthropic" }
|
|
13554
|
+
];
|
|
13555
|
+
const DEFAULT_MODEL = "openai:gpt-5.4";
|
|
13556
|
+
function parseModelKey(key) {
|
|
13557
|
+
const i = key.indexOf(":");
|
|
13558
|
+
if (i > 0) return { provider: key.slice(0, i), modelId: key.slice(i + 1) };
|
|
13559
|
+
if (key.startsWith("claude-")) return { provider: "anthropic", modelId: key };
|
|
13560
|
+
if (key.startsWith("gemini-")) return { provider: "google", modelId: key };
|
|
13561
|
+
return { provider: "openai", modelId: key };
|
|
13562
|
+
}
|
|
13421
13563
|
const useUIStore = create$1((set) => ({
|
|
13422
13564
|
theme: "light",
|
|
13423
13565
|
leftTab: "files",
|
|
13424
13566
|
centerView: "chat",
|
|
13425
|
-
selectedModel:
|
|
13567
|
+
selectedModel: DEFAULT_MODEL,
|
|
13426
13568
|
isIdle: true,
|
|
13427
13569
|
rightSidebarCollapsed: false,
|
|
13428
13570
|
leftSidebarCollapsed: false,
|
|
@@ -13528,16 +13670,321 @@ async function hydratePreferences() {
|
|
|
13528
13670
|
const prefs = await api2?.loadPreferences?.();
|
|
13529
13671
|
if (!prefs) return;
|
|
13530
13672
|
const updates = {};
|
|
13531
|
-
if (prefs.selectedModel)
|
|
13673
|
+
if (prefs.selectedModel) {
|
|
13674
|
+
const m = prefs.selectedModel;
|
|
13675
|
+
if (!m.includes(":")) {
|
|
13676
|
+
const { provider, modelId } = parseModelKey(m);
|
|
13677
|
+
updates.selectedModel = `${provider}:${modelId}`;
|
|
13678
|
+
} else {
|
|
13679
|
+
updates.selectedModel = m;
|
|
13680
|
+
}
|
|
13681
|
+
}
|
|
13532
13682
|
if (prefs.reasoningEffort) updates.reasoningEffort = prefs.reasoningEffort;
|
|
13533
13683
|
if (prefs.theme) updates.theme = prefs.theme;
|
|
13534
13684
|
if (Object.keys(updates).length > 0) useUIStore.setState(updates);
|
|
13535
13685
|
}
|
|
13536
13686
|
const uiStore = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
13537
13687
|
__proto__: null,
|
|
13688
|
+
REASONING_MODELS,
|
|
13689
|
+
SUPPORTED_MODELS,
|
|
13538
13690
|
hydratePreferences,
|
|
13539
13691
|
useUIStore
|
|
13540
13692
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
13693
|
+
const scriptRel = function detectScriptRel() {
|
|
13694
|
+
const relList = typeof document !== "undefined" && document.createElement("link").relList;
|
|
13695
|
+
return relList && relList.supports && relList.supports("modulepreload") ? "modulepreload" : "preload";
|
|
13696
|
+
}();
|
|
13697
|
+
const assetsURL = function(dep, importerUrl) {
|
|
13698
|
+
return new URL(dep, importerUrl).href;
|
|
13699
|
+
};
|
|
13700
|
+
const seen = {};
|
|
13701
|
+
const __vitePreload = function preload2(baseModule, deps, importerUrl) {
|
|
13702
|
+
let promise = Promise.resolve();
|
|
13703
|
+
if (deps && deps.length > 0) {
|
|
13704
|
+
const links = document.getElementsByTagName("link");
|
|
13705
|
+
const cspNonceMeta = document.querySelector(
|
|
13706
|
+
"meta[property=csp-nonce]"
|
|
13707
|
+
);
|
|
13708
|
+
const cspNonce = cspNonceMeta?.nonce || cspNonceMeta?.getAttribute("nonce");
|
|
13709
|
+
promise = Promise.allSettled(
|
|
13710
|
+
deps.map((dep) => {
|
|
13711
|
+
dep = assetsURL(dep, importerUrl);
|
|
13712
|
+
if (dep in seen) return;
|
|
13713
|
+
seen[dep] = true;
|
|
13714
|
+
const isCss = dep.endsWith(".css");
|
|
13715
|
+
const cssSelector = isCss ? '[rel="stylesheet"]' : "";
|
|
13716
|
+
const isBaseRelative = !!importerUrl;
|
|
13717
|
+
if (isBaseRelative) {
|
|
13718
|
+
for (let i = links.length - 1; i >= 0; i--) {
|
|
13719
|
+
const link22 = links[i];
|
|
13720
|
+
if (link22.href === dep && (!isCss || link22.rel === "stylesheet")) {
|
|
13721
|
+
return;
|
|
13722
|
+
}
|
|
13723
|
+
}
|
|
13724
|
+
} else if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) {
|
|
13725
|
+
return;
|
|
13726
|
+
}
|
|
13727
|
+
const link2 = document.createElement("link");
|
|
13728
|
+
link2.rel = isCss ? "stylesheet" : scriptRel;
|
|
13729
|
+
if (!isCss) {
|
|
13730
|
+
link2.as = "script";
|
|
13731
|
+
}
|
|
13732
|
+
link2.crossOrigin = "";
|
|
13733
|
+
link2.href = dep;
|
|
13734
|
+
if (cspNonce) {
|
|
13735
|
+
link2.setAttribute("nonce", cspNonce);
|
|
13736
|
+
}
|
|
13737
|
+
document.head.appendChild(link2);
|
|
13738
|
+
if (isCss) {
|
|
13739
|
+
return new Promise((res, rej) => {
|
|
13740
|
+
link2.addEventListener("load", res);
|
|
13741
|
+
link2.addEventListener(
|
|
13742
|
+
"error",
|
|
13743
|
+
() => rej(new Error(`Unable to preload CSS for ${dep}`))
|
|
13744
|
+
);
|
|
13745
|
+
});
|
|
13746
|
+
}
|
|
13747
|
+
})
|
|
13748
|
+
);
|
|
13749
|
+
}
|
|
13750
|
+
function handlePreloadError(err) {
|
|
13751
|
+
const e = new Event("vite:preloadError", {
|
|
13752
|
+
cancelable: true
|
|
13753
|
+
});
|
|
13754
|
+
e.payload = err;
|
|
13755
|
+
window.dispatchEvent(e);
|
|
13756
|
+
if (!e.defaultPrevented) {
|
|
13757
|
+
throw err;
|
|
13758
|
+
}
|
|
13759
|
+
}
|
|
13760
|
+
return promise.then((res) => {
|
|
13761
|
+
for (const item of res || []) {
|
|
13762
|
+
if (item.status !== "rejected") continue;
|
|
13763
|
+
handlePreloadError(item.reason);
|
|
13764
|
+
}
|
|
13765
|
+
return baseModule().catch(handlePreloadError);
|
|
13766
|
+
});
|
|
13767
|
+
};
|
|
13768
|
+
function extractProgress(tool, data) {
|
|
13769
|
+
if (!data?.partialResult) return void 0;
|
|
13770
|
+
const text2 = data.partialResult?.content?.[0]?.text;
|
|
13771
|
+
if (typeof text2 === "string" && text2.length > 0) {
|
|
13772
|
+
const lines = text2.split("\n").filter(Boolean);
|
|
13773
|
+
const maxLines = tool === "bash" ? 5 : 3;
|
|
13774
|
+
return lines.slice(-maxLines).join("\n");
|
|
13775
|
+
}
|
|
13776
|
+
return void 0;
|
|
13777
|
+
}
|
|
13778
|
+
const useToolEventsStore = create$1((set, get) => ({
|
|
13779
|
+
currentRunEvents: [],
|
|
13780
|
+
onToolCall: (event) => {
|
|
13781
|
+
const toolCallId = event.toolCallId || `${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
13782
|
+
const newEvent = {
|
|
13783
|
+
id: toolCallId,
|
|
13784
|
+
toolCallId,
|
|
13785
|
+
tool: event.tool,
|
|
13786
|
+
status: "running",
|
|
13787
|
+
summary: event.summary,
|
|
13788
|
+
detail: event.detail,
|
|
13789
|
+
startedAt: Date.now()
|
|
13790
|
+
};
|
|
13791
|
+
set((state) => ({
|
|
13792
|
+
currentRunEvents: [...state.currentRunEvents, newEvent]
|
|
13793
|
+
}));
|
|
13794
|
+
},
|
|
13795
|
+
onToolResult: (event) => {
|
|
13796
|
+
set((state) => {
|
|
13797
|
+
const events = [...state.currentRunEvents];
|
|
13798
|
+
const idx = event.toolCallId ? events.findLastIndex((e) => e.toolCallId === event.toolCallId && e.status === "running") : events.findLastIndex((e) => e.tool === event.tool && e.status === "running");
|
|
13799
|
+
if (idx !== -1) {
|
|
13800
|
+
events[idx] = {
|
|
13801
|
+
...events[idx],
|
|
13802
|
+
status: event.success !== false ? "success" : "error",
|
|
13803
|
+
resultSummary: event.summary,
|
|
13804
|
+
resultDetail: event.resultDetail,
|
|
13805
|
+
durationMs: event.durationMs,
|
|
13806
|
+
completedAt: Date.now()
|
|
13807
|
+
};
|
|
13808
|
+
}
|
|
13809
|
+
return { currentRunEvents: events };
|
|
13810
|
+
});
|
|
13811
|
+
},
|
|
13812
|
+
onToolProgress: (event) => {
|
|
13813
|
+
if (event.phase === "end") return;
|
|
13814
|
+
set((state) => {
|
|
13815
|
+
const events = [...state.currentRunEvents];
|
|
13816
|
+
const idx = events.findLastIndex((e) => e.toolCallId === event.toolCallId);
|
|
13817
|
+
if (idx !== -1) {
|
|
13818
|
+
const progress = extractProgress(event.tool, event.data) ?? events[idx].progress;
|
|
13819
|
+
events[idx] = { ...events[idx], progress };
|
|
13820
|
+
}
|
|
13821
|
+
return { currentRunEvents: events };
|
|
13822
|
+
});
|
|
13823
|
+
},
|
|
13824
|
+
snapshot: () => [...get().currentRunEvents],
|
|
13825
|
+
clearRun: () => set({ currentRunEvents: [] })
|
|
13826
|
+
}));
|
|
13827
|
+
const PAGE_SIZE = 20;
|
|
13828
|
+
const api$a = window.api;
|
|
13829
|
+
let _sessionId = "";
|
|
13830
|
+
const useChatStore = create$1((set, get) => ({
|
|
13831
|
+
messages: [],
|
|
13832
|
+
streamingText: "",
|
|
13833
|
+
isStreaming: false,
|
|
13834
|
+
savedMessageIds: /* @__PURE__ */ new Set(),
|
|
13835
|
+
turnToolEvents: /* @__PURE__ */ new Map(),
|
|
13836
|
+
draftText: "",
|
|
13837
|
+
setDraftText: (text2) => set({ draftText: text2 }),
|
|
13838
|
+
hasMore: false,
|
|
13839
|
+
isLoadingHistory: false,
|
|
13840
|
+
_offset: 0,
|
|
13841
|
+
scrollToMessageId: null,
|
|
13842
|
+
send: async (text2, images) => {
|
|
13843
|
+
const userMsg = {
|
|
13844
|
+
id: crypto.randomUUID(),
|
|
13845
|
+
role: "user",
|
|
13846
|
+
content: text2,
|
|
13847
|
+
images: images?.map((i) => `data:${i.mimeType};base64,${i.base64}`),
|
|
13848
|
+
timestamp: Date.now()
|
|
13849
|
+
};
|
|
13850
|
+
set((s15) => ({
|
|
13851
|
+
messages: [...s15.messages, userMsg],
|
|
13852
|
+
streamingText: "",
|
|
13853
|
+
isStreaming: true
|
|
13854
|
+
}));
|
|
13855
|
+
if (_sessionId) {
|
|
13856
|
+
api$a.saveMessage(_sessionId, userMsg).catch(() => {
|
|
13857
|
+
});
|
|
13858
|
+
}
|
|
13859
|
+
const { useUsageStore: useUsageStore2 } = await __vitePreload(async () => {
|
|
13860
|
+
const { useUsageStore: useUsageStore3 } = await Promise.resolve().then(() => usageStore);
|
|
13861
|
+
return { useUsageStore: useUsageStore3 };
|
|
13862
|
+
}, true ? void 0 : void 0, import.meta.url);
|
|
13863
|
+
useUsageStore2.getState().resetRun();
|
|
13864
|
+
try {
|
|
13865
|
+
const { useUIStore: useUIStore2 } = await __vitePreload(async () => {
|
|
13866
|
+
const { useUIStore: useUIStore3 } = await Promise.resolve().then(() => uiStore);
|
|
13867
|
+
return { useUIStore: useUIStore3 };
|
|
13868
|
+
}, true ? void 0 : void 0, import.meta.url);
|
|
13869
|
+
const model = useUIStore2.getState().selectedModel;
|
|
13870
|
+
await api$a.sendMessage(text2, void 0, model, images);
|
|
13871
|
+
} catch {
|
|
13872
|
+
}
|
|
13873
|
+
},
|
|
13874
|
+
stop: async () => {
|
|
13875
|
+
await api$a.stopAgent();
|
|
13876
|
+
},
|
|
13877
|
+
appendChunk: (chunk) => {
|
|
13878
|
+
set((s15) => ({ streamingText: s15.streamingText + chunk }));
|
|
13879
|
+
},
|
|
13880
|
+
finalize: (result) => {
|
|
13881
|
+
const content2 = result.response || result.error || "No response";
|
|
13882
|
+
const assistantMsg = {
|
|
13883
|
+
id: crypto.randomUUID(),
|
|
13884
|
+
role: "assistant",
|
|
13885
|
+
content: content2,
|
|
13886
|
+
images: result.images?.map((i) => `data:${i.mimeType};base64,${i.base64}`),
|
|
13887
|
+
timestamp: Date.now()
|
|
13888
|
+
};
|
|
13889
|
+
const toolEventsSnapshot = useToolEventsStore.getState().snapshot();
|
|
13890
|
+
useToolEventsStore.getState().clearRun();
|
|
13891
|
+
set((s15) => {
|
|
13892
|
+
const nextToolEvents = new Map(s15.turnToolEvents);
|
|
13893
|
+
if (toolEventsSnapshot.length > 0) {
|
|
13894
|
+
nextToolEvents.set(assistantMsg.id, toolEventsSnapshot);
|
|
13895
|
+
}
|
|
13896
|
+
return {
|
|
13897
|
+
messages: [...s15.messages, assistantMsg],
|
|
13898
|
+
streamingText: "",
|
|
13899
|
+
isStreaming: false,
|
|
13900
|
+
turnToolEvents: nextToolEvents
|
|
13901
|
+
};
|
|
13902
|
+
});
|
|
13903
|
+
if (_sessionId) {
|
|
13904
|
+
api$a.saveMessage(_sessionId, assistantMsg).catch(() => {
|
|
13905
|
+
});
|
|
13906
|
+
}
|
|
13907
|
+
},
|
|
13908
|
+
clear: () => {
|
|
13909
|
+
_sessionId = "";
|
|
13910
|
+
return set({
|
|
13911
|
+
messages: [],
|
|
13912
|
+
streamingText: "",
|
|
13913
|
+
isStreaming: false,
|
|
13914
|
+
savedMessageIds: /* @__PURE__ */ new Set(),
|
|
13915
|
+
turnToolEvents: /* @__PURE__ */ new Map(),
|
|
13916
|
+
draftText: "",
|
|
13917
|
+
hasMore: false,
|
|
13918
|
+
isLoadingHistory: false,
|
|
13919
|
+
_offset: 0,
|
|
13920
|
+
scrollToMessageId: null
|
|
13921
|
+
});
|
|
13922
|
+
},
|
|
13923
|
+
markSaved: (messageId) => {
|
|
13924
|
+
set((s15) => {
|
|
13925
|
+
const next = new Set(s15.savedMessageIds);
|
|
13926
|
+
next.add(messageId);
|
|
13927
|
+
return { savedMessageIds: next };
|
|
13928
|
+
});
|
|
13929
|
+
if (_sessionId) {
|
|
13930
|
+
api$a.markMessageSaved(_sessionId, messageId).catch(() => {
|
|
13931
|
+
});
|
|
13932
|
+
}
|
|
13933
|
+
},
|
|
13934
|
+
insertContextReset: () => {
|
|
13935
|
+
const divider = {
|
|
13936
|
+
id: `ctx-reset-${Date.now()}`,
|
|
13937
|
+
role: "system",
|
|
13938
|
+
content: "AI context has been reset — chat history is preserved.",
|
|
13939
|
+
timestamp: Date.now()
|
|
13940
|
+
};
|
|
13941
|
+
set((s15) => ({ messages: [...s15.messages, divider] }));
|
|
13942
|
+
},
|
|
13943
|
+
loadInitial: async (sessionId) => {
|
|
13944
|
+
_sessionId = sessionId;
|
|
13945
|
+
try {
|
|
13946
|
+
const [count, messages, savedIds] = await Promise.all([
|
|
13947
|
+
api$a.getMessageCount(sessionId),
|
|
13948
|
+
api$a.loadMessages(sessionId, 0, PAGE_SIZE),
|
|
13949
|
+
api$a.loadSavedMessageIds(sessionId)
|
|
13950
|
+
]);
|
|
13951
|
+
set({
|
|
13952
|
+
messages,
|
|
13953
|
+
hasMore: count > PAGE_SIZE,
|
|
13954
|
+
_offset: PAGE_SIZE,
|
|
13955
|
+
savedMessageIds: new Set(savedIds || [])
|
|
13956
|
+
});
|
|
13957
|
+
} catch {
|
|
13958
|
+
}
|
|
13959
|
+
},
|
|
13960
|
+
loadHistory: async () => {
|
|
13961
|
+
const { hasMore, isLoadingHistory, _offset } = get();
|
|
13962
|
+
if (!hasMore || isLoadingHistory || !_sessionId) return;
|
|
13963
|
+
set({ isLoadingHistory: true });
|
|
13964
|
+
try {
|
|
13965
|
+
const [count, older] = await Promise.all([
|
|
13966
|
+
api$a.getMessageCount(_sessionId),
|
|
13967
|
+
api$a.loadMessages(_sessionId, _offset, PAGE_SIZE)
|
|
13968
|
+
]);
|
|
13969
|
+
if (older.length > 0) {
|
|
13970
|
+
set((s15) => ({
|
|
13971
|
+
messages: [...older, ...s15.messages],
|
|
13972
|
+
_offset: s15._offset + older.length,
|
|
13973
|
+
hasMore: s15._offset + older.length < count,
|
|
13974
|
+
isLoadingHistory: false
|
|
13975
|
+
}));
|
|
13976
|
+
} else {
|
|
13977
|
+
set({ hasMore: false, isLoadingHistory: false });
|
|
13978
|
+
}
|
|
13979
|
+
} catch {
|
|
13980
|
+
set({ isLoadingHistory: false });
|
|
13981
|
+
}
|
|
13982
|
+
},
|
|
13983
|
+
requestScrollTo: (messageId) => {
|
|
13984
|
+
set({ scrollToMessageId: messageId });
|
|
13985
|
+
setTimeout(() => set({ scrollToMessageId: null }), 100);
|
|
13986
|
+
}
|
|
13987
|
+
}));
|
|
13541
13988
|
function ok$1() {
|
|
13542
13989
|
}
|
|
13543
13990
|
function unreachable() {
|
|
@@ -26140,219 +26587,6 @@ const useEntityStore = create$1((set, get) => ({
|
|
|
26140
26587
|
await get().refreshAll();
|
|
26141
26588
|
}
|
|
26142
26589
|
}));
|
|
26143
|
-
const scriptRel = function detectScriptRel() {
|
|
26144
|
-
const relList = typeof document !== "undefined" && document.createElement("link").relList;
|
|
26145
|
-
return relList && relList.supports && relList.supports("modulepreload") ? "modulepreload" : "preload";
|
|
26146
|
-
}();
|
|
26147
|
-
const assetsURL = function(dep, importerUrl) {
|
|
26148
|
-
return new URL(dep, importerUrl).href;
|
|
26149
|
-
};
|
|
26150
|
-
const seen = {};
|
|
26151
|
-
const __vitePreload = function preload2(baseModule, deps, importerUrl) {
|
|
26152
|
-
let promise = Promise.resolve();
|
|
26153
|
-
if (deps && deps.length > 0) {
|
|
26154
|
-
const links = document.getElementsByTagName("link");
|
|
26155
|
-
const cspNonceMeta = document.querySelector(
|
|
26156
|
-
"meta[property=csp-nonce]"
|
|
26157
|
-
);
|
|
26158
|
-
const cspNonce = cspNonceMeta?.nonce || cspNonceMeta?.getAttribute("nonce");
|
|
26159
|
-
promise = Promise.allSettled(
|
|
26160
|
-
deps.map((dep) => {
|
|
26161
|
-
dep = assetsURL(dep, importerUrl);
|
|
26162
|
-
if (dep in seen) return;
|
|
26163
|
-
seen[dep] = true;
|
|
26164
|
-
const isCss = dep.endsWith(".css");
|
|
26165
|
-
const cssSelector = isCss ? '[rel="stylesheet"]' : "";
|
|
26166
|
-
const isBaseRelative = !!importerUrl;
|
|
26167
|
-
if (isBaseRelative) {
|
|
26168
|
-
for (let i = links.length - 1; i >= 0; i--) {
|
|
26169
|
-
const link22 = links[i];
|
|
26170
|
-
if (link22.href === dep && (!isCss || link22.rel === "stylesheet")) {
|
|
26171
|
-
return;
|
|
26172
|
-
}
|
|
26173
|
-
}
|
|
26174
|
-
} else if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) {
|
|
26175
|
-
return;
|
|
26176
|
-
}
|
|
26177
|
-
const link2 = document.createElement("link");
|
|
26178
|
-
link2.rel = isCss ? "stylesheet" : scriptRel;
|
|
26179
|
-
if (!isCss) {
|
|
26180
|
-
link2.as = "script";
|
|
26181
|
-
}
|
|
26182
|
-
link2.crossOrigin = "";
|
|
26183
|
-
link2.href = dep;
|
|
26184
|
-
if (cspNonce) {
|
|
26185
|
-
link2.setAttribute("nonce", cspNonce);
|
|
26186
|
-
}
|
|
26187
|
-
document.head.appendChild(link2);
|
|
26188
|
-
if (isCss) {
|
|
26189
|
-
return new Promise((res, rej) => {
|
|
26190
|
-
link2.addEventListener("load", res);
|
|
26191
|
-
link2.addEventListener(
|
|
26192
|
-
"error",
|
|
26193
|
-
() => rej(new Error(`Unable to preload CSS for ${dep}`))
|
|
26194
|
-
);
|
|
26195
|
-
});
|
|
26196
|
-
}
|
|
26197
|
-
})
|
|
26198
|
-
);
|
|
26199
|
-
}
|
|
26200
|
-
function handlePreloadError(err) {
|
|
26201
|
-
const e = new Event("vite:preloadError", {
|
|
26202
|
-
cancelable: true
|
|
26203
|
-
});
|
|
26204
|
-
e.payload = err;
|
|
26205
|
-
window.dispatchEvent(e);
|
|
26206
|
-
if (!e.defaultPrevented) {
|
|
26207
|
-
throw err;
|
|
26208
|
-
}
|
|
26209
|
-
}
|
|
26210
|
-
return promise.then((res) => {
|
|
26211
|
-
for (const item of res || []) {
|
|
26212
|
-
if (item.status !== "rejected") continue;
|
|
26213
|
-
handlePreloadError(item.reason);
|
|
26214
|
-
}
|
|
26215
|
-
return baseModule().catch(handlePreloadError);
|
|
26216
|
-
});
|
|
26217
|
-
};
|
|
26218
|
-
const PAGE_SIZE = 20;
|
|
26219
|
-
const api$8 = window.api;
|
|
26220
|
-
let _sessionId = "";
|
|
26221
|
-
const useChatStore = create$1((set, get) => ({
|
|
26222
|
-
messages: [],
|
|
26223
|
-
streamingText: "",
|
|
26224
|
-
isStreaming: false,
|
|
26225
|
-
savedMessageIds: /* @__PURE__ */ new Set(),
|
|
26226
|
-
hasMore: false,
|
|
26227
|
-
isLoadingHistory: false,
|
|
26228
|
-
_offset: 0,
|
|
26229
|
-
scrollToMessageId: null,
|
|
26230
|
-
send: async (text2, images) => {
|
|
26231
|
-
const userMsg = {
|
|
26232
|
-
id: crypto.randomUUID(),
|
|
26233
|
-
role: "user",
|
|
26234
|
-
content: text2,
|
|
26235
|
-
images: images?.map((i) => `data:${i.mimeType};base64,${i.base64}`),
|
|
26236
|
-
timestamp: Date.now()
|
|
26237
|
-
};
|
|
26238
|
-
set((s15) => ({
|
|
26239
|
-
messages: [...s15.messages, userMsg],
|
|
26240
|
-
streamingText: "",
|
|
26241
|
-
isStreaming: true
|
|
26242
|
-
}));
|
|
26243
|
-
if (_sessionId) {
|
|
26244
|
-
api$8.saveMessage(_sessionId, userMsg).catch(() => {
|
|
26245
|
-
});
|
|
26246
|
-
}
|
|
26247
|
-
const { useUsageStore: useUsageStore2 } = await __vitePreload(async () => {
|
|
26248
|
-
const { useUsageStore: useUsageStore3 } = await Promise.resolve().then(() => usageStore);
|
|
26249
|
-
return { useUsageStore: useUsageStore3 };
|
|
26250
|
-
}, true ? void 0 : void 0, import.meta.url);
|
|
26251
|
-
useUsageStore2.getState().resetRun();
|
|
26252
|
-
try {
|
|
26253
|
-
const { useUIStore: useUIStore2 } = await __vitePreload(async () => {
|
|
26254
|
-
const { useUIStore: useUIStore3 } = await Promise.resolve().then(() => uiStore);
|
|
26255
|
-
return { useUIStore: useUIStore3 };
|
|
26256
|
-
}, true ? void 0 : void 0, import.meta.url);
|
|
26257
|
-
const model = useUIStore2.getState().selectedModel;
|
|
26258
|
-
await api$8.sendMessage(text2, void 0, model, images);
|
|
26259
|
-
} catch {
|
|
26260
|
-
}
|
|
26261
|
-
},
|
|
26262
|
-
stop: async () => {
|
|
26263
|
-
await api$8.stopAgent();
|
|
26264
|
-
},
|
|
26265
|
-
appendChunk: (chunk) => {
|
|
26266
|
-
set((s15) => ({ streamingText: s15.streamingText + chunk }));
|
|
26267
|
-
},
|
|
26268
|
-
finalize: (result) => {
|
|
26269
|
-
const content2 = result.response || result.error || "No response";
|
|
26270
|
-
const assistantMsg = {
|
|
26271
|
-
id: crypto.randomUUID(),
|
|
26272
|
-
role: "assistant",
|
|
26273
|
-
content: content2,
|
|
26274
|
-
images: result.images?.map((i) => `data:${i.mimeType};base64,${i.base64}`),
|
|
26275
|
-
timestamp: Date.now()
|
|
26276
|
-
};
|
|
26277
|
-
set((s15) => ({
|
|
26278
|
-
messages: [...s15.messages, assistantMsg],
|
|
26279
|
-
streamingText: "",
|
|
26280
|
-
isStreaming: false
|
|
26281
|
-
}));
|
|
26282
|
-
if (_sessionId) {
|
|
26283
|
-
api$8.saveMessage(_sessionId, assistantMsg).catch(() => {
|
|
26284
|
-
});
|
|
26285
|
-
}
|
|
26286
|
-
},
|
|
26287
|
-
clear: () => {
|
|
26288
|
-
_sessionId = "";
|
|
26289
|
-
return set({
|
|
26290
|
-
messages: [],
|
|
26291
|
-
streamingText: "",
|
|
26292
|
-
isStreaming: false,
|
|
26293
|
-
savedMessageIds: /* @__PURE__ */ new Set(),
|
|
26294
|
-
hasMore: false,
|
|
26295
|
-
isLoadingHistory: false,
|
|
26296
|
-
_offset: 0,
|
|
26297
|
-
scrollToMessageId: null
|
|
26298
|
-
});
|
|
26299
|
-
},
|
|
26300
|
-
markSaved: (messageId) => {
|
|
26301
|
-
set((s15) => {
|
|
26302
|
-
const next = new Set(s15.savedMessageIds);
|
|
26303
|
-
next.add(messageId);
|
|
26304
|
-
return { savedMessageIds: next };
|
|
26305
|
-
});
|
|
26306
|
-
if (_sessionId) {
|
|
26307
|
-
api$8.markMessageSaved(_sessionId, messageId).catch(() => {
|
|
26308
|
-
});
|
|
26309
|
-
}
|
|
26310
|
-
},
|
|
26311
|
-
loadInitial: async (sessionId) => {
|
|
26312
|
-
_sessionId = sessionId;
|
|
26313
|
-
try {
|
|
26314
|
-
const [count, messages, savedIds] = await Promise.all([
|
|
26315
|
-
api$8.getMessageCount(sessionId),
|
|
26316
|
-
api$8.loadMessages(sessionId, 0, PAGE_SIZE),
|
|
26317
|
-
api$8.loadSavedMessageIds(sessionId)
|
|
26318
|
-
]);
|
|
26319
|
-
set({
|
|
26320
|
-
messages,
|
|
26321
|
-
hasMore: count > PAGE_SIZE,
|
|
26322
|
-
_offset: PAGE_SIZE,
|
|
26323
|
-
savedMessageIds: new Set(savedIds || [])
|
|
26324
|
-
});
|
|
26325
|
-
} catch {
|
|
26326
|
-
}
|
|
26327
|
-
},
|
|
26328
|
-
loadHistory: async () => {
|
|
26329
|
-
const { hasMore, isLoadingHistory, _offset } = get();
|
|
26330
|
-
if (!hasMore || isLoadingHistory || !_sessionId) return;
|
|
26331
|
-
set({ isLoadingHistory: true });
|
|
26332
|
-
try {
|
|
26333
|
-
const [count, older] = await Promise.all([
|
|
26334
|
-
api$8.getMessageCount(_sessionId),
|
|
26335
|
-
api$8.loadMessages(_sessionId, _offset, PAGE_SIZE)
|
|
26336
|
-
]);
|
|
26337
|
-
if (older.length > 0) {
|
|
26338
|
-
set((s15) => ({
|
|
26339
|
-
messages: [...older, ...s15.messages],
|
|
26340
|
-
_offset: s15._offset + older.length,
|
|
26341
|
-
hasMore: s15._offset + older.length < count,
|
|
26342
|
-
isLoadingHistory: false
|
|
26343
|
-
}));
|
|
26344
|
-
} else {
|
|
26345
|
-
set({ hasMore: false, isLoadingHistory: false });
|
|
26346
|
-
}
|
|
26347
|
-
} catch {
|
|
26348
|
-
set({ isLoadingHistory: false });
|
|
26349
|
-
}
|
|
26350
|
-
},
|
|
26351
|
-
requestScrollTo: (messageId) => {
|
|
26352
|
-
set({ scrollToMessageId: messageId });
|
|
26353
|
-
setTimeout(() => set({ scrollToMessageId: null }), 100);
|
|
26354
|
-
}
|
|
26355
|
-
}));
|
|
26356
26590
|
const useProgressStore = create$1((set) => ({
|
|
26357
26591
|
items: [],
|
|
26358
26592
|
upsertItem: (item) => set((state) => {
|
|
@@ -26377,16 +26611,19 @@ const useActivityStore = create$1((set) => ({
|
|
|
26377
26611
|
push: (event) => set((state) => {
|
|
26378
26612
|
if (event.tool && event.tool.startsWith("todo-")) return state;
|
|
26379
26613
|
if (event.type === "tool-result") {
|
|
26380
|
-
const idx = findLastIndex(state.events, (e) => e.type === "tool-call" && e.tool === event.tool);
|
|
26614
|
+
const idx = event.toolCallId ? findLastIndex(state.events, (e) => e.type === "tool-call" && e.toolCallId === event.toolCallId) : findLastIndex(state.events, (e) => e.type === "tool-call" && e.tool === event.tool);
|
|
26381
26615
|
if (idx !== -1) {
|
|
26382
26616
|
const updated = [...state.events];
|
|
26383
26617
|
updated[idx] = {
|
|
26384
26618
|
...updated[idx],
|
|
26619
|
+
// preserve original detail (tool-call params)
|
|
26385
26620
|
type: "tool-result",
|
|
26386
26621
|
summary: event.summary,
|
|
26387
26622
|
success: event.success,
|
|
26388
26623
|
error: event.error,
|
|
26389
|
-
timestamp: event.timestamp
|
|
26624
|
+
timestamp: event.timestamp,
|
|
26625
|
+
resultDetail: event.resultDetail,
|
|
26626
|
+
durationMs: event.durationMs
|
|
26390
26627
|
};
|
|
26391
26628
|
return { events: updated };
|
|
26392
26629
|
}
|
|
@@ -26402,10 +26639,10 @@ function findLastIndex(arr, pred) {
|
|
|
26402
26639
|
}
|
|
26403
26640
|
return -1;
|
|
26404
26641
|
}
|
|
26405
|
-
const api$
|
|
26642
|
+
const api$8 = window.api;
|
|
26406
26643
|
async function loadFromFramework() {
|
|
26407
26644
|
try {
|
|
26408
|
-
const data = await api$
|
|
26645
|
+
const data = await api$8?.getUsageTotals?.();
|
|
26409
26646
|
return data ?? null;
|
|
26410
26647
|
} catch (e) {
|
|
26411
26648
|
console.warn("[usage-store] Failed to load persisted totals:", e);
|
|
@@ -26415,6 +26652,10 @@ async function loadFromFramework() {
|
|
|
26415
26652
|
const useUsageStore = create$1((set, get) => {
|
|
26416
26653
|
return {
|
|
26417
26654
|
// Current run
|
|
26655
|
+
runPromptTokens: 0,
|
|
26656
|
+
runCompletionTokens: 0,
|
|
26657
|
+
runCachedTokens: 0,
|
|
26658
|
+
runCacheWriteTokens: 0,
|
|
26418
26659
|
runTokens: 0,
|
|
26419
26660
|
runCost: 0,
|
|
26420
26661
|
runCacheHitRate: 0,
|
|
@@ -26426,37 +26667,54 @@ const useUsageStore = create$1((set, get) => {
|
|
|
26426
26667
|
// All-time totals (from framework persistence)
|
|
26427
26668
|
allTimeTokens: 0,
|
|
26428
26669
|
allTimePromptTokens: 0,
|
|
26670
|
+
allTimeCompletionTokens: 0,
|
|
26429
26671
|
allTimeCachedTokens: 0,
|
|
26672
|
+
allTimeCacheWriteTokens: 0,
|
|
26430
26673
|
allTimeCost: 0,
|
|
26431
26674
|
allTimeBillableCost: 0,
|
|
26432
26675
|
allTimeCalls: 0,
|
|
26433
26676
|
billingSource: "none",
|
|
26434
26677
|
recordCall: (event) => set((state) => {
|
|
26435
|
-
const
|
|
26678
|
+
const callTokens = event.promptTokens + event.completionTokens + event.cachedTokens;
|
|
26679
|
+
const cacheWrite = event.cacheWriteTokens ?? 0;
|
|
26436
26680
|
const billableCost = event.billableCost ?? event.cost;
|
|
26437
|
-
const
|
|
26438
|
-
|
|
26681
|
+
const newRunPrompt = state.runPromptTokens + event.promptTokens;
|
|
26682
|
+
const newRunCached = state.runCachedTokens + event.cachedTokens;
|
|
26683
|
+
const totalRunInput = newRunPrompt + newRunCached;
|
|
26684
|
+
const runCacheHitRate = totalRunInput > 0 ? newRunCached / totalRunInput : 0;
|
|
26685
|
+
return {
|
|
26686
|
+
runPromptTokens: newRunPrompt,
|
|
26687
|
+
runCompletionTokens: state.runCompletionTokens + event.completionTokens,
|
|
26688
|
+
runCachedTokens: newRunCached,
|
|
26689
|
+
runCacheWriteTokens: state.runCacheWriteTokens + cacheWrite,
|
|
26690
|
+
runTokens: state.runTokens + callTokens,
|
|
26439
26691
|
runCost: state.runCost + event.cost,
|
|
26440
|
-
runCacheHitRate
|
|
26692
|
+
runCacheHitRate,
|
|
26441
26693
|
runCallCount: state.runCallCount + 1,
|
|
26442
|
-
//
|
|
26443
|
-
sessionTokens: state.sessionTokens +
|
|
26694
|
+
// Session
|
|
26695
|
+
sessionTokens: state.sessionTokens + callTokens,
|
|
26444
26696
|
sessionCost: state.sessionCost + event.cost,
|
|
26445
26697
|
sessionCalls: state.sessionCalls + 1,
|
|
26446
|
-
|
|
26698
|
+
// All-time
|
|
26699
|
+
allTimeTokens: state.allTimeTokens + callTokens,
|
|
26447
26700
|
allTimePromptTokens: state.allTimePromptTokens + event.promptTokens,
|
|
26701
|
+
allTimeCompletionTokens: state.allTimeCompletionTokens + event.completionTokens,
|
|
26448
26702
|
allTimeCachedTokens: state.allTimeCachedTokens + event.cachedTokens,
|
|
26703
|
+
allTimeCacheWriteTokens: state.allTimeCacheWriteTokens + cacheWrite,
|
|
26449
26704
|
allTimeCost: state.allTimeCost + event.cost,
|
|
26450
26705
|
allTimeBillableCost: state.allTimeBillableCost + billableCost,
|
|
26451
26706
|
allTimeCalls: state.allTimeCalls + 1,
|
|
26452
26707
|
billingSource: event.billingSource ?? state.billingSource
|
|
26453
26708
|
};
|
|
26454
|
-
return newState;
|
|
26455
26709
|
}),
|
|
26456
26710
|
completeRun: (_summary) => {
|
|
26457
26711
|
},
|
|
26458
26712
|
// Reset run stats - called when a NEW run starts (not when old one ends)
|
|
26459
26713
|
resetRun: () => set({
|
|
26714
|
+
runPromptTokens: 0,
|
|
26715
|
+
runCompletionTokens: 0,
|
|
26716
|
+
runCachedTokens: 0,
|
|
26717
|
+
runCacheWriteTokens: 0,
|
|
26460
26718
|
runTokens: 0,
|
|
26461
26719
|
runCost: 0,
|
|
26462
26720
|
runCacheHitRate: 0,
|
|
@@ -26464,6 +26722,10 @@ const useUsageStore = create$1((set, get) => {
|
|
|
26464
26722
|
}),
|
|
26465
26723
|
// Reset session stats (but keep all-time)
|
|
26466
26724
|
resetSession: () => set({
|
|
26725
|
+
runPromptTokens: 0,
|
|
26726
|
+
runCompletionTokens: 0,
|
|
26727
|
+
runCachedTokens: 0,
|
|
26728
|
+
runCacheWriteTokens: 0,
|
|
26467
26729
|
runTokens: 0,
|
|
26468
26730
|
runCost: 0,
|
|
26469
26731
|
runCacheHitRate: 0,
|
|
@@ -26476,26 +26738,33 @@ const useUsageStore = create$1((set, get) => {
|
|
|
26476
26738
|
loadPersisted: async () => {
|
|
26477
26739
|
const persisted = await loadFromFramework();
|
|
26478
26740
|
if (persisted?.totals) {
|
|
26741
|
+
const t = persisted.totals;
|
|
26479
26742
|
set({
|
|
26480
|
-
allTimeTokens:
|
|
26481
|
-
allTimePromptTokens:
|
|
26482
|
-
|
|
26483
|
-
|
|
26484
|
-
|
|
26485
|
-
|
|
26743
|
+
allTimeTokens: t.tokens ?? 0,
|
|
26744
|
+
allTimePromptTokens: t.promptTokens ?? 0,
|
|
26745
|
+
allTimeCompletionTokens: t.completionTokens ?? 0,
|
|
26746
|
+
allTimeCachedTokens: t.cachedTokens ?? 0,
|
|
26747
|
+
allTimeCacheWriteTokens: t.cacheWriteTokens ?? 0,
|
|
26748
|
+
allTimeCost: t.cost ?? 0,
|
|
26749
|
+
allTimeBillableCost: t.cost ?? 0,
|
|
26750
|
+
allTimeCalls: t.calls ?? 0,
|
|
26486
26751
|
billingSource: "api-key",
|
|
26487
26752
|
// Also restore to session totals
|
|
26488
|
-
sessionTokens:
|
|
26489
|
-
sessionCost:
|
|
26490
|
-
sessionCalls:
|
|
26753
|
+
sessionTokens: t.tokens ?? 0,
|
|
26754
|
+
sessionCost: t.cost ?? 0,
|
|
26755
|
+
sessionCalls: t.calls ?? 0
|
|
26491
26756
|
});
|
|
26492
26757
|
}
|
|
26493
26758
|
},
|
|
26494
26759
|
// Reset all-time totals (user-initiated)
|
|
26495
26760
|
resetAllTime: () => {
|
|
26496
|
-
api$
|
|
26761
|
+
api$8?.resetUsageTotals?.().catch?.(() => {
|
|
26497
26762
|
});
|
|
26498
26763
|
set({
|
|
26764
|
+
runPromptTokens: 0,
|
|
26765
|
+
runCompletionTokens: 0,
|
|
26766
|
+
runCachedTokens: 0,
|
|
26767
|
+
runCacheWriteTokens: 0,
|
|
26499
26768
|
runTokens: 0,
|
|
26500
26769
|
runCost: 0,
|
|
26501
26770
|
runCacheHitRate: 0,
|
|
@@ -26505,7 +26774,9 @@ const useUsageStore = create$1((set, get) => {
|
|
|
26505
26774
|
sessionCalls: 0,
|
|
26506
26775
|
allTimeTokens: 0,
|
|
26507
26776
|
allTimePromptTokens: 0,
|
|
26777
|
+
allTimeCompletionTokens: 0,
|
|
26508
26778
|
allTimeCachedTokens: 0,
|
|
26779
|
+
allTimeCacheWriteTokens: 0,
|
|
26509
26780
|
allTimeCost: 0,
|
|
26510
26781
|
allTimeBillableCost: 0,
|
|
26511
26782
|
billingSource: "none",
|
|
@@ -26518,13 +26789,13 @@ const usageStore = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
26518
26789
|
__proto__: null,
|
|
26519
26790
|
useUsageStore
|
|
26520
26791
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
26521
|
-
const api$
|
|
26792
|
+
const api$7 = window.api;
|
|
26522
26793
|
const useSessionStore = create$1((set) => ({
|
|
26523
26794
|
sessionId: "",
|
|
26524
26795
|
projectPath: "",
|
|
26525
26796
|
hasProject: false,
|
|
26526
26797
|
init: async () => {
|
|
26527
|
-
const session = await api$
|
|
26798
|
+
const session = await api$7.getCurrentSession();
|
|
26528
26799
|
set({
|
|
26529
26800
|
sessionId: session.sessionId,
|
|
26530
26801
|
projectPath: session.projectPath,
|
|
@@ -26535,7 +26806,7 @@ const useSessionStore = create$1((set) => ({
|
|
|
26535
26806
|
}
|
|
26536
26807
|
},
|
|
26537
26808
|
pickFolder: async () => {
|
|
26538
|
-
const result = await api$
|
|
26809
|
+
const result = await api$7.pickFolder();
|
|
26539
26810
|
if (result) {
|
|
26540
26811
|
useChatStore.getState().clear();
|
|
26541
26812
|
useProgressStore.getState().clear();
|
|
@@ -26556,7 +26827,7 @@ const useSessionStore = create$1((set) => ({
|
|
|
26556
26827
|
return false;
|
|
26557
26828
|
},
|
|
26558
26829
|
closeProject: async () => {
|
|
26559
|
-
await api$
|
|
26830
|
+
await api$7.closeProject();
|
|
26560
26831
|
useChatStore.getState().clear();
|
|
26561
26832
|
useProgressStore.getState().clear();
|
|
26562
26833
|
useActivityStore.getState().clear();
|
|
@@ -26566,7 +26837,7 @@ const useSessionStore = create$1((set) => ({
|
|
|
26566
26837
|
set({ sessionId: "", projectPath: "", hasProject: false });
|
|
26567
26838
|
}
|
|
26568
26839
|
}));
|
|
26569
|
-
const api$
|
|
26840
|
+
const api$6 = window.api;
|
|
26570
26841
|
const ROW_HEIGHT = 28;
|
|
26571
26842
|
const OVERSCAN_ROWS = 10;
|
|
26572
26843
|
const MAX_DROP_FILE_SIZE = 100 * 1024 * 1024;
|
|
@@ -26665,7 +26936,7 @@ function WorkspaceTree() {
|
|
|
26665
26936
|
const parentKey = toKey(relativePath);
|
|
26666
26937
|
setParentLoading(parentKey, true);
|
|
26667
26938
|
try {
|
|
26668
|
-
const children = await api$
|
|
26939
|
+
const children = await api$6.listTree({
|
|
26669
26940
|
relativePath,
|
|
26670
26941
|
showIgnored,
|
|
26671
26942
|
limit: 2e3
|
|
@@ -26690,8 +26961,8 @@ function WorkspaceTree() {
|
|
|
26690
26961
|
void Promise.all(dirs.map((dir) => loadChildren(dir)));
|
|
26691
26962
|
}, 500);
|
|
26692
26963
|
};
|
|
26693
|
-
const unsubFileCreated = api$
|
|
26694
|
-
const unsubAgentDone = api$
|
|
26964
|
+
const unsubFileCreated = api$6.onFileCreated(scheduleRefresh);
|
|
26965
|
+
const unsubAgentDone = api$6.onAgentDone(scheduleRefresh);
|
|
26695
26966
|
return () => {
|
|
26696
26967
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
26697
26968
|
unsubFileCreated();
|
|
@@ -26731,7 +27002,7 @@ function WorkspaceTree() {
|
|
|
26731
27002
|
}
|
|
26732
27003
|
setSearching(true);
|
|
26733
27004
|
try {
|
|
26734
|
-
const results = await api$
|
|
27005
|
+
const results = await api$6.searchTree(query.trim(), { showIgnored, maxResults: 4e3 });
|
|
26735
27006
|
setSearchResults(results);
|
|
26736
27007
|
} finally {
|
|
26737
27008
|
setSearching(false);
|
|
@@ -26775,7 +27046,7 @@ function WorkspaceTree() {
|
|
|
26775
27046
|
if (node2.type !== "file") return;
|
|
26776
27047
|
const ext = (node2.name.split(".").pop() || "").toLowerCase();
|
|
26777
27048
|
if (!TEXT_EXTENSIONS.has(ext)) {
|
|
26778
|
-
api$
|
|
27049
|
+
api$6.openFile(node2.path);
|
|
26779
27050
|
return;
|
|
26780
27051
|
}
|
|
26781
27052
|
const normalizedNodePath = normalizePath(node2.path);
|
|
@@ -26800,14 +27071,14 @@ function WorkspaceTree() {
|
|
|
26800
27071
|
});
|
|
26801
27072
|
}, [data, openPreview]);
|
|
26802
27073
|
const createArtifact = reactExports.useCallback(async (node2) => {
|
|
26803
|
-
await api$
|
|
27074
|
+
await api$6.createArtifactFromFile(node2.path);
|
|
26804
27075
|
await refreshEntities();
|
|
26805
27076
|
}, [refreshEntities]);
|
|
26806
27077
|
const handleTrashClick = reactExports.useCallback(async (node2) => {
|
|
26807
27078
|
if (confirmTrashPath === node2.relativePath) {
|
|
26808
27079
|
if (confirmTimerRef.current) clearTimeout(confirmTimerRef.current);
|
|
26809
27080
|
setConfirmTrashPath(null);
|
|
26810
|
-
const result = await api$
|
|
27081
|
+
const result = await api$6.trashFile(node2.path);
|
|
26811
27082
|
if (result.success) {
|
|
26812
27083
|
const parentRelPath = node2.relativePath.includes("/") ? node2.relativePath.slice(0, node2.relativePath.lastIndexOf("/")) : "";
|
|
26813
27084
|
await loadChildren(parentRelPath);
|
|
@@ -26856,7 +27127,7 @@ function WorkspaceTree() {
|
|
|
26856
27127
|
return;
|
|
26857
27128
|
}
|
|
26858
27129
|
const relPath = creating.parentDir ? `${creating.parentDir}/${createValue.trim()}` : createValue.trim();
|
|
26859
|
-
const result = creating.type === "file" ? await api$
|
|
27130
|
+
const result = creating.type === "file" ? await api$6.createFile(relPath) : await api$6.createDir(relPath);
|
|
26860
27131
|
if (result.success) {
|
|
26861
27132
|
await loadChildren(creating.parentDir);
|
|
26862
27133
|
}
|
|
@@ -26883,7 +27154,7 @@ function WorkspaceTree() {
|
|
|
26883
27154
|
const parentDir = renaming.includes("/") ? renaming.slice(0, renaming.lastIndexOf("/")) : "";
|
|
26884
27155
|
const newRelPath = parentDir ? `${parentDir}/${renameValue.trim()}` : renameValue.trim();
|
|
26885
27156
|
if (newRelPath !== renaming) {
|
|
26886
|
-
await api$
|
|
27157
|
+
await api$6.renameFile(renaming, newRelPath);
|
|
26887
27158
|
await loadChildren(parentDir);
|
|
26888
27159
|
}
|
|
26889
27160
|
setRenaming(null);
|
|
@@ -26925,7 +27196,7 @@ function WorkspaceTree() {
|
|
|
26925
27196
|
const base64 = btoa(
|
|
26926
27197
|
new Uint8Array(buffer).reduce((data2, byte) => data2 + String.fromCharCode(byte), "")
|
|
26927
27198
|
);
|
|
26928
|
-
await api$
|
|
27199
|
+
await api$6.dropToDir(file.name, base64, targetRelPath);
|
|
26929
27200
|
}
|
|
26930
27201
|
await loadChildren(targetRelPath);
|
|
26931
27202
|
}, [getDropDir, loadChildren]);
|
|
@@ -26951,7 +27222,7 @@ function WorkspaceTree() {
|
|
|
26951
27222
|
const base64 = btoa(
|
|
26952
27223
|
new Uint8Array(buffer).reduce((data2, byte) => data2 + String.fromCharCode(byte), "")
|
|
26953
27224
|
);
|
|
26954
|
-
await api$
|
|
27225
|
+
await api$6.dropToDir(file.name, base64, "");
|
|
26955
27226
|
}
|
|
26956
27227
|
await loadChildren("");
|
|
26957
27228
|
}, [loadChildren]);
|
|
@@ -27013,7 +27284,7 @@ function WorkspaceTree() {
|
|
|
27013
27284
|
"div",
|
|
27014
27285
|
{
|
|
27015
27286
|
className: "flex items-center gap-1 rounded px-1.5 h-7 text-xs bg-[var(--color-accent)]/10",
|
|
27016
|
-
style: { paddingLeft: `${depth *
|
|
27287
|
+
style: { paddingLeft: `${depth * 1.1 + 0.4}em` },
|
|
27017
27288
|
children: [
|
|
27018
27289
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-3 shrink-0" }),
|
|
27019
27290
|
creating.type === "directory" ? /* @__PURE__ */ jsxRuntimeExports.jsx(Folder, { size: 12, className: "shrink-0 t-text-warning" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(File, { size: 12, className: "shrink-0 t-text-muted" }),
|
|
@@ -27040,7 +27311,7 @@ function WorkspaceTree() {
|
|
|
27040
27311
|
"div",
|
|
27041
27312
|
{
|
|
27042
27313
|
className: "flex items-center gap-1 text-xs t-text-muted h-7",
|
|
27043
|
-
style: { paddingLeft: `${row.depth *
|
|
27314
|
+
style: { paddingLeft: `${row.depth * 1.1 + 2}em` },
|
|
27044
27315
|
children: [
|
|
27045
27316
|
/* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { size: 11, className: "animate-spin" }),
|
|
27046
27317
|
"Loading..."
|
|
@@ -27173,6 +27444,7 @@ function WorkspaceTree() {
|
|
|
27173
27444
|
value: query,
|
|
27174
27445
|
onChange: (e) => setQuery(e.target.value),
|
|
27175
27446
|
placeholder: "Filter files...",
|
|
27447
|
+
"aria-label": "Filter files",
|
|
27176
27448
|
className: "w-full bg-transparent text-xs outline-none t-focus-ring t-text"
|
|
27177
27449
|
}
|
|
27178
27450
|
)
|
|
@@ -27686,6 +27958,7 @@ function SkillsContent() {
|
|
|
27686
27958
|
onClick: () => fileInputRef.current?.click(),
|
|
27687
27959
|
className: "no-drag flex items-center gap-1 px-1.5 py-0.5 text-[10px] t-text-muted hover:t-text-accent-soft transition-colors rounded t-bg-hover",
|
|
27688
27960
|
title: "Upload skill (.zip)",
|
|
27961
|
+
"aria-label": "Install skill from zip file",
|
|
27689
27962
|
children: [
|
|
27690
27963
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CloudUpload, { size: 11 }),
|
|
27691
27964
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Install" })
|
|
@@ -27713,6 +27986,7 @@ function SkillsContent() {
|
|
|
27713
27986
|
value: searchQuery,
|
|
27714
27987
|
onChange: (e) => setSearchQuery(e.target.value),
|
|
27715
27988
|
placeholder: "Search skills or tags...",
|
|
27989
|
+
"aria-label": "Search skills",
|
|
27716
27990
|
className: "w-full pl-6 pr-2 py-1 text-[11px] rounded border t-border t-bg-surface t-text focus:outline-none focus:border-[var(--color-accent-soft)]"
|
|
27717
27991
|
}
|
|
27718
27992
|
)
|
|
@@ -27800,13 +28074,30 @@ function EntityTabs() {
|
|
|
27800
28074
|
return null;
|
|
27801
28075
|
}
|
|
27802
28076
|
};
|
|
28077
|
+
const handleTabKeyDown = (e) => {
|
|
28078
|
+
const tabKeys = tabs.map((t) => t.key);
|
|
28079
|
+
const idx = tabKeys.indexOf(leftTab);
|
|
28080
|
+
if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
28081
|
+
e.preventDefault();
|
|
28082
|
+
const next = tabKeys[(idx + 1) % tabKeys.length];
|
|
28083
|
+
setLeftTab(next);
|
|
28084
|
+
} else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
|
|
28085
|
+
e.preventDefault();
|
|
28086
|
+
const prev = tabKeys[(idx - 1 + tabKeys.length) % tabKeys.length];
|
|
28087
|
+
setLeftTab(prev);
|
|
28088
|
+
}
|
|
28089
|
+
};
|
|
27803
28090
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col min-h-0", children: [
|
|
27804
28091
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex border-b t-border px-1", role: "tablist", "aria-label": "Content categories", children: tabs.map(({ key, label, icon: Icon2 }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
27805
28092
|
"button",
|
|
27806
28093
|
{
|
|
27807
28094
|
role: "tab",
|
|
28095
|
+
id: `tab-${key}`,
|
|
27808
28096
|
"aria-selected": leftTab === key,
|
|
28097
|
+
"aria-controls": `tabpanel-${key}`,
|
|
28098
|
+
tabIndex: leftTab === key ? 0 : -1,
|
|
27809
28099
|
onClick: () => setLeftTab(key),
|
|
28100
|
+
onKeyDown: handleTabKeyDown,
|
|
27810
28101
|
className: `no-drag flex items-center gap-1 px-2 py-2 text-[11px] font-medium border-b-2 transition-colors ${leftTab === key ? "border-[var(--color-accent-soft)] t-text-accent" : "border-transparent t-text-muted hover:t-text-secondary"}`,
|
|
27811
28102
|
title: label,
|
|
27812
28103
|
children: [
|
|
@@ -27816,7 +28107,16 @@ function EntityTabs() {
|
|
|
27816
28107
|
},
|
|
27817
28108
|
key
|
|
27818
28109
|
)) }),
|
|
27819
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28110
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28111
|
+
"div",
|
|
28112
|
+
{
|
|
28113
|
+
role: "tabpanel",
|
|
28114
|
+
id: `tabpanel-${leftTab}`,
|
|
28115
|
+
"aria-labelledby": `tab-${leftTab}`,
|
|
28116
|
+
className: "flex-1 min-h-0 overflow-hidden flex flex-col",
|
|
28117
|
+
children: renderContent()
|
|
28118
|
+
}
|
|
28119
|
+
)
|
|
27820
28120
|
] });
|
|
27821
28121
|
}
|
|
27822
28122
|
function QuickAction({
|
|
@@ -28001,6 +28301,166 @@ function LiteratureSidebar() {
|
|
|
28001
28301
|
] })
|
|
28002
28302
|
] });
|
|
28003
28303
|
}
|
|
28304
|
+
const useComputeStore = create$1((set) => ({
|
|
28305
|
+
runs: /* @__PURE__ */ new Map(),
|
|
28306
|
+
environment: null,
|
|
28307
|
+
updateRun: (runId, data) => set((state) => {
|
|
28308
|
+
const next = new Map(state.runs);
|
|
28309
|
+
const existing = next.get(runId);
|
|
28310
|
+
if (existing) {
|
|
28311
|
+
next.set(runId, { ...existing, ...data });
|
|
28312
|
+
} else {
|
|
28313
|
+
next.set(runId, {
|
|
28314
|
+
runId,
|
|
28315
|
+
status: "running",
|
|
28316
|
+
currentPhase: "full",
|
|
28317
|
+
command: "",
|
|
28318
|
+
sandbox: "process",
|
|
28319
|
+
weight: "heavy",
|
|
28320
|
+
elapsedSeconds: 0,
|
|
28321
|
+
outputBytes: 0,
|
|
28322
|
+
outputLines: 0,
|
|
28323
|
+
stalled: false,
|
|
28324
|
+
outputTail: "",
|
|
28325
|
+
...data
|
|
28326
|
+
});
|
|
28327
|
+
}
|
|
28328
|
+
return { runs: next };
|
|
28329
|
+
}),
|
|
28330
|
+
removeRun: (runId) => set((state) => {
|
|
28331
|
+
const next = new Map(state.runs);
|
|
28332
|
+
next.delete(runId);
|
|
28333
|
+
return { runs: next };
|
|
28334
|
+
}),
|
|
28335
|
+
setEnvironment: (env2) => set({ environment: env2 }),
|
|
28336
|
+
reset: () => set({ runs: /* @__PURE__ */ new Map(), environment: null })
|
|
28337
|
+
}));
|
|
28338
|
+
function useActiveRuns() {
|
|
28339
|
+
const runs = useComputeStore((s15) => s15.runs);
|
|
28340
|
+
return Array.from(runs.values()).filter(
|
|
28341
|
+
(r) => r.status === "running" || r.status === "stalled"
|
|
28342
|
+
);
|
|
28343
|
+
}
|
|
28344
|
+
function useRecentRuns() {
|
|
28345
|
+
const runs = useComputeStore((s15) => s15.runs);
|
|
28346
|
+
return Array.from(runs.values()).filter((r) => r.status !== "running" && r.status !== "stalled").sort((a, b2) => {
|
|
28347
|
+
const aTime = a.startedAt ? new Date(a.startedAt).getTime() : 0;
|
|
28348
|
+
const bTime = b2.startedAt ? new Date(b2.startedAt).getTime() : 0;
|
|
28349
|
+
return bTime - aTime;
|
|
28350
|
+
}).slice(0, 20);
|
|
28351
|
+
}
|
|
28352
|
+
function useActiveRunCount() {
|
|
28353
|
+
const runs = useComputeStore((s15) => s15.runs);
|
|
28354
|
+
let count = 0;
|
|
28355
|
+
for (const r of runs.values()) {
|
|
28356
|
+
if (r.status === "running" || r.status === "stalled") count++;
|
|
28357
|
+
}
|
|
28358
|
+
return count;
|
|
28359
|
+
}
|
|
28360
|
+
function ResourceBar({ label, percent }) {
|
|
28361
|
+
const clamped = Math.min(100, Math.max(0, percent));
|
|
28362
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
28363
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] t-text-muted w-11 text-right shrink-0", children: label }),
|
|
28364
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 h-1 rounded-full t-bg-elevated overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28365
|
+
"div",
|
|
28366
|
+
{
|
|
28367
|
+
className: `h-full rounded-full transition-all duration-700 ${clamped > 85 ? "" : "t-gradient-accent-h"}`,
|
|
28368
|
+
style: {
|
|
28369
|
+
width: `${clamped}%`,
|
|
28370
|
+
...clamped > 85 ? { background: "var(--color-text-muted)", opacity: 0.6 } : { opacity: 0.5 }
|
|
28371
|
+
}
|
|
28372
|
+
}
|
|
28373
|
+
) }),
|
|
28374
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] t-text-muted tabular-nums w-7 shrink-0", children: [
|
|
28375
|
+
clamped,
|
|
28376
|
+
"%"
|
|
28377
|
+
] })
|
|
28378
|
+
] });
|
|
28379
|
+
}
|
|
28380
|
+
function SandboxExplanation({ environment }) {
|
|
28381
|
+
const [expanded, setExpanded] = reactExports.useState(false);
|
|
28382
|
+
const isDocker = environment.sandbox === "docker";
|
|
28383
|
+
const isMac = environment.os === "darwin";
|
|
28384
|
+
const hasMLX = environment.mlxAvailable;
|
|
28385
|
+
let explanation;
|
|
28386
|
+
if (isDocker && isMac) {
|
|
28387
|
+
explanation = "Docker available. Note: Docker on macOS lacks GPU passthrough. Switch to Process sandbox for MLX/Metal GPU access if needed.";
|
|
28388
|
+
} else if (isDocker) {
|
|
28389
|
+
explanation = "Docker available. Runs execute in isolated containers with resource limits.";
|
|
28390
|
+
} else if (isMac && hasMLX) {
|
|
28391
|
+
explanation = "Process sandbox uses Python virtual environments with process-group isolation. Direct MLX/Metal GPU access for ML training.";
|
|
28392
|
+
} else if (isMac) {
|
|
28393
|
+
explanation = "Process sandbox uses Python virtual environments. Install Docker for stronger container-based isolation.";
|
|
28394
|
+
} else {
|
|
28395
|
+
explanation = "Process sandbox uses Python virtual environments with process-group isolation.";
|
|
28396
|
+
}
|
|
28397
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 pt-2 border-t t-border-subtle", children: [
|
|
28398
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
28399
|
+
"button",
|
|
28400
|
+
{
|
|
28401
|
+
onClick: () => setExpanded(!expanded),
|
|
28402
|
+
className: "flex items-center gap-1 text-[10px] t-text-muted hover:t-text-secondary transition-colors w-full text-left",
|
|
28403
|
+
children: [
|
|
28404
|
+
expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { size: 10 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 10 }),
|
|
28405
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
28406
|
+
"Sandbox: ",
|
|
28407
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-secondary", children: isDocker ? "Docker" : "Process (venv)" })
|
|
28408
|
+
] })
|
|
28409
|
+
]
|
|
28410
|
+
}
|
|
28411
|
+
),
|
|
28412
|
+
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1.5 ml-3.5 text-[10px] t-text-muted leading-relaxed", children: explanation })
|
|
28413
|
+
] });
|
|
28414
|
+
}
|
|
28415
|
+
function ComputeSidebar() {
|
|
28416
|
+
const environment = useComputeStore((s15) => s15.environment);
|
|
28417
|
+
const activeCount = useActiveRunCount();
|
|
28418
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col min-h-0", children: [
|
|
28419
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-2 pt-2 pb-2", children: [
|
|
28420
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] t-text-accent-soft uppercase tracking-wider px-3 pb-1.5 font-medium", children: "Compute Target" }),
|
|
28421
|
+
environment ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-2.5 rounded-lg t-bg-surface border t-border-subtle", children: [
|
|
28422
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
28423
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `w-1.5 h-1.5 rounded-full shrink-0 ${activeCount > 0 ? "bg-[var(--color-accent)]" : "bg-[var(--color-text-muted)]"}`, style: { opacity: activeCount > 0 ? 1 : 0.5 } }),
|
|
28424
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs t-text font-medium", children: "Local Machine" })
|
|
28425
|
+
] }),
|
|
28426
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] t-text-muted leading-relaxed space-y-0.5", children: [
|
|
28427
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
28428
|
+
environment.gpu || `${environment.os} ${environment.arch}`,
|
|
28429
|
+
" · ",
|
|
28430
|
+
Math.round(environment.totalMemoryMb / 1024),
|
|
28431
|
+
" GB"
|
|
28432
|
+
] }),
|
|
28433
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 flex-wrap", children: [
|
|
28434
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Python" }),
|
|
28435
|
+
environment.mlxAvailable && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-1 py-px rounded text-[9px] bg-[var(--color-accent-soft)]/10 t-text-accent", children: "MLX" }),
|
|
28436
|
+
environment.sandbox === "docker" && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-1 py-px rounded text-[9px] t-bg-elevated t-text-muted", children: "Docker" })
|
|
28437
|
+
] })
|
|
28438
|
+
] }),
|
|
28439
|
+
(environment.freeMemoryMb !== void 0 || environment.freeDiskMb !== void 0) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2.5 space-y-1.5", children: environment.freeMemoryMb !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28440
|
+
ResourceBar,
|
|
28441
|
+
{
|
|
28442
|
+
label: "Memory",
|
|
28443
|
+
percent: Math.round((1 - environment.freeMemoryMb / environment.totalMemoryMb) * 100)
|
|
28444
|
+
}
|
|
28445
|
+
) }),
|
|
28446
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SandboxExplanation, { environment }),
|
|
28447
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 pt-2 border-t t-border-subtle text-[10px] t-text-muted", children: activeCount > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
28448
|
+
activeCount,
|
|
28449
|
+
" running"
|
|
28450
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Ready" }) })
|
|
28451
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-4 rounded-lg t-bg-surface border t-border-subtle", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 t-text-muted", children: [
|
|
28452
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Monitor, { size: 14, className: "opacity-40" }),
|
|
28453
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px]", children: "Detecting environment..." })
|
|
28454
|
+
] }) }),
|
|
28455
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1.5 px-3 py-2 rounded-lg border border-dashed t-border-subtle cursor-default", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] t-text-muted opacity-60", children: "+ Add remote target" }) })
|
|
28456
|
+
] }),
|
|
28457
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-3 border-t t-border" }),
|
|
28458
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto px-3 py-3", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 text-[10px] t-text-muted leading-relaxed", children: [
|
|
28459
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Info$1, { size: 12, className: "shrink-0 mt-0.5 opacity-40" }),
|
|
28460
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Ask the agent to run scripts, train models, or process data. Code executes in a sandboxed environment with progress tracking and failure analysis." })
|
|
28461
|
+
] }) })
|
|
28462
|
+
] });
|
|
28463
|
+
}
|
|
28004
28464
|
function UserProfile() {
|
|
28005
28465
|
const projectPath = useSessionStore((s15) => s15.projectPath);
|
|
28006
28466
|
const pickFolder = useSessionStore((s15) => s15.pickFolder);
|
|
@@ -28024,25 +28484,6 @@ function UserProfile() {
|
|
|
28024
28484
|
}
|
|
28025
28485
|
);
|
|
28026
28486
|
}
|
|
28027
|
-
const REASONING_MODELS = [
|
|
28028
|
-
"gpt-5.4",
|
|
28029
|
-
"gpt-5.4-mini",
|
|
28030
|
-
"gpt-5.4-nano",
|
|
28031
|
-
"claude-opus-4-6"
|
|
28032
|
-
];
|
|
28033
|
-
const SUPPORTED_MODELS = [
|
|
28034
|
-
// GPT
|
|
28035
|
-
{ id: "gpt-5.4", label: "GPT-5.4", provider: "OpenAI" },
|
|
28036
|
-
{ id: "gpt-5.4-mini", label: "GPT-5.4 Mini", provider: "OpenAI" },
|
|
28037
|
-
{ id: "gpt-5.4-nano", label: "GPT-5.4 Nano", provider: "OpenAI" },
|
|
28038
|
-
{ id: "gpt-4o", label: "GPT-4o", provider: "OpenAI" },
|
|
28039
|
-
// Anthropic Claude 4.6
|
|
28040
|
-
{ id: "claude-opus-4-6", label: "Claude Opus 4.6", provider: "Anthropic" },
|
|
28041
|
-
// Anthropic Claude 4.5
|
|
28042
|
-
{ id: "claude-opus-4-5-20251101", label: "Claude Opus 4.5", provider: "Anthropic" },
|
|
28043
|
-
{ id: "claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5", provider: "Anthropic" },
|
|
28044
|
-
{ id: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5", provider: "Anthropic" }
|
|
28045
|
-
];
|
|
28046
28487
|
const providers = [...new Set(SUPPORTED_MODELS.map((m) => m.provider))];
|
|
28047
28488
|
const groupedModels = {};
|
|
28048
28489
|
for (const p of providers) {
|
|
@@ -28051,6 +28492,8 @@ for (const p of providers) {
|
|
|
28051
28492
|
function ModelSelector$1({ selectedModel, onSelectModel }) {
|
|
28052
28493
|
const [open, setOpen] = reactExports.useState(false);
|
|
28053
28494
|
const [anthropicStatus, setAnthropicStatus] = reactExports.useState(null);
|
|
28495
|
+
const [codexStatus, setCodexStatus] = reactExports.useState(null);
|
|
28496
|
+
const [codexLoggingIn, setCodexLoggingIn] = reactExports.useState(false);
|
|
28054
28497
|
const [showAnthropicDialog, setShowAnthropicDialog] = reactExports.useState(false);
|
|
28055
28498
|
const [showOpenAIDialog, setShowOpenAIDialog] = reactExports.useState(false);
|
|
28056
28499
|
const ref = reactExports.useRef(null);
|
|
@@ -28064,6 +28507,14 @@ function ModelSelector$1({ selectedModel, onSelectModel }) {
|
|
|
28064
28507
|
setAnthropicStatus(null);
|
|
28065
28508
|
}
|
|
28066
28509
|
}, [api2]);
|
|
28510
|
+
const refreshCodexStatus = reactExports.useCallback(async () => {
|
|
28511
|
+
try {
|
|
28512
|
+
const status = await api2?.getOpenAICodexStatus?.();
|
|
28513
|
+
setCodexStatus(status ?? null);
|
|
28514
|
+
} catch {
|
|
28515
|
+
setCodexStatus(null);
|
|
28516
|
+
}
|
|
28517
|
+
}, [api2]);
|
|
28067
28518
|
reactExports.useEffect(() => {
|
|
28068
28519
|
if (!open) return;
|
|
28069
28520
|
const handler = (e) => {
|
|
@@ -28084,13 +28535,47 @@ function ModelSelector$1({ selectedModel, onSelectModel }) {
|
|
|
28084
28535
|
}, [open]);
|
|
28085
28536
|
reactExports.useEffect(() => {
|
|
28086
28537
|
refreshAnthropicStatus();
|
|
28538
|
+
refreshCodexStatus();
|
|
28087
28539
|
const unsub = api2?.onAnthropicAuthStatus?.((status) => setAnthropicStatus(status));
|
|
28088
28540
|
return () => {
|
|
28089
28541
|
if (typeof unsub === "function") unsub();
|
|
28090
28542
|
};
|
|
28091
|
-
}, [api2, refreshAnthropicStatus]);
|
|
28543
|
+
}, [api2, refreshAnthropicStatus, refreshCodexStatus]);
|
|
28544
|
+
const handleCodexLogin = async () => {
|
|
28545
|
+
setCodexLoggingIn(true);
|
|
28546
|
+
try {
|
|
28547
|
+
const result = await api2?.openaiCodexLogin?.();
|
|
28548
|
+
if (result?.success) {
|
|
28549
|
+
await refreshCodexStatus();
|
|
28550
|
+
} else {
|
|
28551
|
+
console.error("[ModelSelector] Codex login failed:", result?.error);
|
|
28552
|
+
}
|
|
28553
|
+
} catch (err) {
|
|
28554
|
+
console.error("[ModelSelector] Codex login error:", err);
|
|
28555
|
+
} finally {
|
|
28556
|
+
setCodexLoggingIn(false);
|
|
28557
|
+
}
|
|
28558
|
+
};
|
|
28559
|
+
const handleCodexLogout = async () => {
|
|
28560
|
+
await api2?.openaiCodexLogout?.();
|
|
28561
|
+
await refreshCodexStatus();
|
|
28562
|
+
};
|
|
28092
28563
|
const handleModelSelect = async (model) => {
|
|
28093
|
-
|
|
28564
|
+
const { provider } = parseModelKey(model.id);
|
|
28565
|
+
if (provider === "openai-codex") {
|
|
28566
|
+
if (!codexStatus?.isLoggedIn) {
|
|
28567
|
+
await handleCodexLogin();
|
|
28568
|
+
const status = await api2?.getOpenAICodexStatus?.();
|
|
28569
|
+
if (!status?.isLoggedIn) {
|
|
28570
|
+
setOpen(false);
|
|
28571
|
+
return;
|
|
28572
|
+
}
|
|
28573
|
+
}
|
|
28574
|
+
onSelectModel(model.id);
|
|
28575
|
+
setOpen(false);
|
|
28576
|
+
return;
|
|
28577
|
+
}
|
|
28578
|
+
if (provider === "openai") {
|
|
28094
28579
|
const status = await api2?.getOpenAIAuthStatus?.();
|
|
28095
28580
|
if (!status?.hasApiKey) {
|
|
28096
28581
|
setShowOpenAIDialog(true);
|
|
@@ -28098,7 +28583,7 @@ function ModelSelector$1({ selectedModel, onSelectModel }) {
|
|
|
28098
28583
|
return;
|
|
28099
28584
|
}
|
|
28100
28585
|
}
|
|
28101
|
-
if (
|
|
28586
|
+
if (provider === "anthropic") {
|
|
28102
28587
|
const status = await api2?.getAnthropicAuthStatus?.();
|
|
28103
28588
|
if (!status?.hasApiKeyFallback) {
|
|
28104
28589
|
setShowAnthropicDialog(true);
|
|
@@ -28110,18 +28595,27 @@ function ModelSelector$1({ selectedModel, onSelectModel }) {
|
|
|
28110
28595
|
setOpen(false);
|
|
28111
28596
|
refreshAnthropicStatus();
|
|
28112
28597
|
};
|
|
28113
|
-
const
|
|
28598
|
+
const { provider: currentProvider } = current ? parseModelKey(current.id) : { provider: "" };
|
|
28599
|
+
const authBadge = currentProvider === "anthropic" ? anthropicStatus?.authMode === "api-key" ? "api" : "auth" : currentProvider === "openai-codex" ? "sub" : currentProvider === "openai" ? "api" : null;
|
|
28114
28600
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref, className: "relative", children: [
|
|
28115
28601
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
28116
28602
|
"button",
|
|
28117
28603
|
{
|
|
28118
28604
|
onClick: () => setOpen(!open),
|
|
28119
|
-
className: "no-drag flex items-center gap-1.5 px-2 py-1.5 rounded-lg t-text-secondary text-xs font-medium t-bg-hover transition-colors",
|
|
28120
|
-
title: "Select model",
|
|
28605
|
+
className: "no-drag group relative flex items-center gap-1.5 px-2 py-1.5 rounded-lg t-text-secondary text-xs font-medium t-bg-hover transition-colors",
|
|
28121
28606
|
"aria-label": "Select model",
|
|
28122
28607
|
"aria-haspopup": "listbox",
|
|
28123
28608
|
"aria-expanded": open,
|
|
28124
28609
|
children: [
|
|
28610
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28611
|
+
"span",
|
|
28612
|
+
{
|
|
28613
|
+
role: "tooltip",
|
|
28614
|
+
className: "pointer-events-none absolute left-1/2 -translate-x-1/2 top-full mt-1 px-2 py-0.5 rounded text-[10px] t-bg-elevated t-text-secondary border t-border shadow-lg whitespace-nowrap opacity-0 group-hover:opacity-100 z-50",
|
|
28615
|
+
style: { transition: "opacity 0.15s ease", transitionDelay: "0.2s" },
|
|
28616
|
+
children: "Select model"
|
|
28617
|
+
}
|
|
28618
|
+
),
|
|
28125
28619
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Cpu, { size: 14 }),
|
|
28126
28620
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate max-w-[100px]", children: current?.label || selectedModel }),
|
|
28127
28621
|
authBadge && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] px-1 rounded border t-border t-text-muted uppercase", children: authBadge }),
|
|
@@ -28131,7 +28625,39 @@ function ModelSelector$1({ selectedModel, onSelectModel }) {
|
|
|
28131
28625
|
),
|
|
28132
28626
|
open && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-full left-0 mt-1 w-64 max-h-80 overflow-y-auto rounded-xl border t-border t-bg-surface shadow-xl z-50", role: "listbox", "aria-label": "Available models", children: providers.map((provider) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
28133
28627
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-1.5 text-[10px] font-semibold uppercase tracking-wider t-text-muted sticky top-0 t-bg-surface", children: provider }),
|
|
28134
|
-
|
|
28628
|
+
provider === "ChatGPT Subscription" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 pb-1 flex items-center justify-between", children: [
|
|
28629
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] t-text-muted", children: codexStatus?.isLoggedIn ? "Signed in" : "OAuth required" }),
|
|
28630
|
+
codexStatus?.isLoggedIn ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
28631
|
+
"button",
|
|
28632
|
+
{
|
|
28633
|
+
onClick: (e) => {
|
|
28634
|
+
e.stopPropagation();
|
|
28635
|
+
handleCodexLogout();
|
|
28636
|
+
},
|
|
28637
|
+
className: "text-[10px] t-text-muted hover:t-text flex items-center gap-0.5",
|
|
28638
|
+
children: [
|
|
28639
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LogOut, { size: 10 }),
|
|
28640
|
+
" Sign out"
|
|
28641
|
+
]
|
|
28642
|
+
}
|
|
28643
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
28644
|
+
"button",
|
|
28645
|
+
{
|
|
28646
|
+
onClick: (e) => {
|
|
28647
|
+
e.stopPropagation();
|
|
28648
|
+
handleCodexLogin();
|
|
28649
|
+
},
|
|
28650
|
+
disabled: codexLoggingIn,
|
|
28651
|
+
className: "text-[10px] t-text-accent flex items-center gap-0.5 hover:opacity-80 disabled:opacity-50",
|
|
28652
|
+
children: [
|
|
28653
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(LogIn, { size: 10 }),
|
|
28654
|
+
" ",
|
|
28655
|
+
codexLoggingIn ? "Signing in..." : "Sign in"
|
|
28656
|
+
]
|
|
28657
|
+
}
|
|
28658
|
+
)
|
|
28659
|
+
] }),
|
|
28660
|
+
(provider === "OpenAI" || provider === "Anthropic") && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 pb-1 text-[11px] t-text-muted", children: "API Key" }),
|
|
28135
28661
|
groupedModels[provider].map((model) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
28136
28662
|
"button",
|
|
28137
28663
|
{
|
|
@@ -28185,7 +28711,39 @@ function ApiKeyDialog({
|
|
|
28185
28711
|
const [saving, setSaving] = reactExports.useState(false);
|
|
28186
28712
|
const [error, setError] = reactExports.useState(null);
|
|
28187
28713
|
const [showKey, setShowKey] = reactExports.useState(false);
|
|
28714
|
+
const dialogRef = reactExports.useRef(null);
|
|
28188
28715
|
const api2 = window.api;
|
|
28716
|
+
reactExports.useEffect(() => {
|
|
28717
|
+
const dialog = dialogRef.current;
|
|
28718
|
+
if (!dialog) return;
|
|
28719
|
+
const focusable = dialog.querySelectorAll(
|
|
28720
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
28721
|
+
);
|
|
28722
|
+
if (focusable.length === 0) return;
|
|
28723
|
+
const first = focusable[0];
|
|
28724
|
+
const last = focusable[focusable.length - 1];
|
|
28725
|
+
first.focus();
|
|
28726
|
+
const handler = (e) => {
|
|
28727
|
+
if (e.key === "Escape") {
|
|
28728
|
+
onClose();
|
|
28729
|
+
return;
|
|
28730
|
+
}
|
|
28731
|
+
if (e.key !== "Tab") return;
|
|
28732
|
+
if (e.shiftKey) {
|
|
28733
|
+
if (document.activeElement === first) {
|
|
28734
|
+
e.preventDefault();
|
|
28735
|
+
last.focus();
|
|
28736
|
+
}
|
|
28737
|
+
} else {
|
|
28738
|
+
if (document.activeElement === last) {
|
|
28739
|
+
e.preventDefault();
|
|
28740
|
+
first.focus();
|
|
28741
|
+
}
|
|
28742
|
+
}
|
|
28743
|
+
};
|
|
28744
|
+
dialog.addEventListener("keydown", handler);
|
|
28745
|
+
return () => dialog.removeEventListener("keydown", handler);
|
|
28746
|
+
}, []);
|
|
28189
28747
|
const handleSave = async () => {
|
|
28190
28748
|
const trimmed = value.trim();
|
|
28191
28749
|
if (!trimmed) {
|
|
@@ -28203,7 +28761,7 @@ function ApiKeyDialog({
|
|
|
28203
28761
|
setSaving(false);
|
|
28204
28762
|
}
|
|
28205
28763
|
};
|
|
28206
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-[90] flex items-center justify-center bg-black/40 p-4", role: "dialog", "aria-modal": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full max-w-md rounded-xl border t-border t-bg-surface shadow-2xl p-4 space-y-3", children: [
|
|
28764
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-[90] flex items-center justify-center bg-black/40 p-4", role: "dialog", "aria-modal": "true", "aria-label": `${provider} API Key Required`, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: dialogRef, className: "w-full max-w-md rounded-xl border t-border t-bg-surface shadow-2xl p-4 space-y-3", children: [
|
|
28207
28765
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
28208
28766
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm font-semibold t-text", children: [
|
|
28209
28767
|
provider,
|
|
@@ -28229,6 +28787,7 @@ function ApiKeyDialog({
|
|
|
28229
28787
|
onKeyDown: (e) => {
|
|
28230
28788
|
if (e.key === "Enter") handleSave();
|
|
28231
28789
|
},
|
|
28790
|
+
"aria-label": `${provider} API key`,
|
|
28232
28791
|
autoFocus: true
|
|
28233
28792
|
}
|
|
28234
28793
|
),
|
|
@@ -28248,7 +28807,7 @@ function ApiKeyDialog({
|
|
|
28248
28807
|
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "px-1 rounded t-bg-surface", children: "~/.research-copilot/config.json" }),
|
|
28249
28808
|
". No restart needed."
|
|
28250
28809
|
] }),
|
|
28251
|
-
error && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-red-400", children: error }),
|
|
28810
|
+
error && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-red-400", role: "alert", children: error }),
|
|
28252
28811
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-end gap-2", children: [
|
|
28253
28812
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28254
28813
|
"button",
|
|
@@ -28295,13 +28854,27 @@ const COLORS = {
|
|
|
28295
28854
|
};
|
|
28296
28855
|
function ReasoningToggle$1({ selectedModel, reasoningEffort, onChangeEffort }) {
|
|
28297
28856
|
if (!REASONING_MODELS.includes(selectedModel)) return null;
|
|
28298
|
-
return /* @__PURE__ */ jsxRuntimeExports.
|
|
28857
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
28299
28858
|
"button",
|
|
28300
28859
|
{
|
|
28301
28860
|
onClick: () => onChangeEffort(CYCLE[reasoningEffort]),
|
|
28302
|
-
className: "no-drag p-
|
|
28303
|
-
|
|
28304
|
-
children:
|
|
28861
|
+
className: "no-drag group relative p-2.5 rounded-lg t-bg-hover transition-colors",
|
|
28862
|
+
"aria-label": `Reasoning effort: ${reasoningEffort}`,
|
|
28863
|
+
children: [
|
|
28864
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Lightbulb, { size: 16, className: COLORS[reasoningEffort] }),
|
|
28865
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
28866
|
+
"span",
|
|
28867
|
+
{
|
|
28868
|
+
role: "tooltip",
|
|
28869
|
+
className: "pointer-events-none absolute left-1/2 -translate-x-1/2 top-full mt-1 px-2 py-0.5 rounded text-[10px] t-bg-elevated t-text-secondary border t-border shadow-lg whitespace-nowrap opacity-0 group-hover:opacity-100 z-50",
|
|
28870
|
+
style: { transition: "opacity 0.15s ease", transitionDelay: "0.2s" },
|
|
28871
|
+
children: [
|
|
28872
|
+
"Reasoning: ",
|
|
28873
|
+
reasoningEffort
|
|
28874
|
+
]
|
|
28875
|
+
}
|
|
28876
|
+
)
|
|
28877
|
+
]
|
|
28305
28878
|
}
|
|
28306
28879
|
);
|
|
28307
28880
|
}
|
|
@@ -28318,45 +28891,87 @@ function ReasoningToggle() {
|
|
|
28318
28891
|
}
|
|
28319
28892
|
);
|
|
28320
28893
|
}
|
|
28894
|
+
function ToolbarButton({ onClick, tooltip, children }) {
|
|
28895
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
28896
|
+
"button",
|
|
28897
|
+
{
|
|
28898
|
+
onClick,
|
|
28899
|
+
"aria-label": tooltip,
|
|
28900
|
+
className: "no-drag group relative p-2.5 rounded-lg t-text-muted t-bg-hover transition-colors",
|
|
28901
|
+
children: [
|
|
28902
|
+
children,
|
|
28903
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28904
|
+
"span",
|
|
28905
|
+
{
|
|
28906
|
+
role: "tooltip",
|
|
28907
|
+
className: "pointer-events-none absolute left-1/2 -translate-x-1/2 top-full mt-1 px-2 py-0.5 rounded text-[10px] t-bg-elevated t-text-secondary border t-border shadow-lg whitespace-nowrap opacity-0 group-hover:opacity-100 z-50",
|
|
28908
|
+
style: { transition: "opacity 0.15s ease", transitionDelay: "0.2s" },
|
|
28909
|
+
children: tooltip
|
|
28910
|
+
}
|
|
28911
|
+
)
|
|
28912
|
+
]
|
|
28913
|
+
}
|
|
28914
|
+
);
|
|
28915
|
+
}
|
|
28321
28916
|
function LeftSidebar() {
|
|
28322
28917
|
const theme = useUIStore((s15) => s15.theme);
|
|
28323
28918
|
const toggleTheme = useUIStore((s15) => s15.toggleTheme);
|
|
28324
28919
|
const centerView = useUIStore((s15) => s15.centerView);
|
|
28920
|
+
const noContextShownRef = reactExports.useRef(false);
|
|
28921
|
+
const handleResetContext = reactExports.useCallback(async () => {
|
|
28922
|
+
const messages = useChatStore.getState().messages;
|
|
28923
|
+
const hasContext = messages.some((m) => m.role === "user" || m.role === "assistant");
|
|
28924
|
+
if (!hasContext) {
|
|
28925
|
+
if (!noContextShownRef.current) {
|
|
28926
|
+
noContextShownRef.current = true;
|
|
28927
|
+
useChatStore.getState().insertContextReset();
|
|
28928
|
+
useChatStore.setState((s15) => {
|
|
28929
|
+
const msgs = [...s15.messages];
|
|
28930
|
+
const last = msgs[msgs.length - 1];
|
|
28931
|
+
if (last?.role === "system") {
|
|
28932
|
+
msgs[msgs.length - 1] = { ...last, content: "No context to reset yet." };
|
|
28933
|
+
}
|
|
28934
|
+
return { messages: msgs };
|
|
28935
|
+
});
|
|
28936
|
+
}
|
|
28937
|
+
return;
|
|
28938
|
+
}
|
|
28939
|
+
await window.api.clearSessionMemory();
|
|
28940
|
+
useChatStore.getState().insertContextReset();
|
|
28941
|
+
noContextShownRef.current = false;
|
|
28942
|
+
}, []);
|
|
28325
28943
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("aside", { className: "w-80 flex flex-col border-r t-border t-bg-base pt-10", children: [
|
|
28326
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("
|
|
28944
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("nav", { "aria-label": "Sidebar tools", className: "px-4 pb-3 flex items-center justify-between", children: [
|
|
28327
28945
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ModelSelector, {}),
|
|
28328
28946
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
28329
28947
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ReasoningToggle, {}),
|
|
28330
28948
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28331
|
-
|
|
28949
|
+
ToolbarButton,
|
|
28332
28950
|
{
|
|
28333
|
-
onClick:
|
|
28334
|
-
|
|
28335
|
-
|
|
28336
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Eraser, { size: 16 })
|
|
28951
|
+
onClick: handleResetContext,
|
|
28952
|
+
tooltip: "Reset AI context",
|
|
28953
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 16 })
|
|
28337
28954
|
}
|
|
28338
28955
|
),
|
|
28339
28956
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28340
|
-
|
|
28957
|
+
ToolbarButton,
|
|
28341
28958
|
{
|
|
28342
28959
|
onClick: toggleTheme,
|
|
28343
|
-
|
|
28344
|
-
title: `Switch to ${theme === "dark" ? "light" : "dark"} mode`,
|
|
28960
|
+
tooltip: `${theme === "dark" ? "Light" : "Dark"} mode`,
|
|
28345
28961
|
children: theme === "dark" ? /* @__PURE__ */ jsxRuntimeExports.jsx(Sun, { size: 16 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Moon, { size: 16 })
|
|
28346
28962
|
}
|
|
28347
28963
|
),
|
|
28348
28964
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28349
|
-
|
|
28965
|
+
ToolbarButton,
|
|
28350
28966
|
{
|
|
28351
28967
|
onClick: () => useUIStore.getState().toggleTerminal(),
|
|
28352
|
-
|
|
28353
|
-
title: "Toggle terminal (⌘`)",
|
|
28968
|
+
tooltip: "Terminal ⌘`",
|
|
28354
28969
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { size: 16 })
|
|
28355
28970
|
}
|
|
28356
28971
|
)
|
|
28357
28972
|
] })
|
|
28358
28973
|
] }),
|
|
28359
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0", children: centerView === "literature" ? /* @__PURE__ */ jsxRuntimeExports.jsx(LiteratureSidebar, {}) : /* @__PURE__ */ jsxRuntimeExports.jsx(EntityTabs, {}) }),
|
|
28974
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0", children: centerView === "literature" ? /* @__PURE__ */ jsxRuntimeExports.jsx(LiteratureSidebar, {}) : centerView === "compute" && window.api?.isComputeEnabled?.() ? /* @__PURE__ */ jsxRuntimeExports.jsx(ComputeSidebar, {}) : /* @__PURE__ */ jsxRuntimeExports.jsx(EntityTabs, {}) }),
|
|
28360
28975
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-t t-border p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx(UserProfile, {}) })
|
|
28361
28976
|
] });
|
|
28362
28977
|
}
|
|
@@ -28367,17 +28982,11 @@ const suggestions = [
|
|
|
28367
28982
|
{ icon: Sparkles, label: "Brainstorm ideas", prompt: "Help me brainstorm ideas for " }
|
|
28368
28983
|
];
|
|
28369
28984
|
function HeroIdle() {
|
|
28985
|
+
const setDraftText = useChatStore((s15) => s15.setDraftText);
|
|
28370
28986
|
const handleSuggestion = (prompt) => {
|
|
28987
|
+
setDraftText(prompt);
|
|
28371
28988
|
const input = document.querySelector("[data-chat-input]");
|
|
28372
|
-
|
|
28373
|
-
const nativeSetter = Object.getOwnPropertyDescriptor(
|
|
28374
|
-
window.HTMLTextAreaElement.prototype,
|
|
28375
|
-
"value"
|
|
28376
|
-
)?.set;
|
|
28377
|
-
nativeSetter?.call(input, prompt);
|
|
28378
|
-
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
28379
|
-
input.focus();
|
|
28380
|
-
}
|
|
28989
|
+
input?.focus();
|
|
28381
28990
|
};
|
|
28382
28991
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-10 w-full max-w-lg px-8", children: [
|
|
28383
28992
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center space-y-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -28402,7 +29011,631 @@ function HeroIdle() {
|
|
|
28402
29011
|
)) })
|
|
28403
29012
|
] });
|
|
28404
29013
|
}
|
|
28405
|
-
|
|
29014
|
+
function getFileName(path2) {
|
|
29015
|
+
if (!path2) return "";
|
|
29016
|
+
const parts = path2.replace(/\\/g, "/").split("/");
|
|
29017
|
+
return parts[parts.length - 1] || path2;
|
|
29018
|
+
}
|
|
29019
|
+
function truncStr(s15, max) {
|
|
29020
|
+
if (!s15) return "";
|
|
29021
|
+
return s15.length > max ? s15.slice(0, max - 3) + "..." : s15;
|
|
29022
|
+
}
|
|
29023
|
+
function safeRecord(obj) {
|
|
29024
|
+
return obj && typeof obj === "object" ? obj : {};
|
|
29025
|
+
}
|
|
29026
|
+
function extractResultText(result) {
|
|
29027
|
+
const r = safeRecord(result);
|
|
29028
|
+
const content2 = r.content;
|
|
29029
|
+
return content2?.[0]?.text || "";
|
|
29030
|
+
}
|
|
29031
|
+
function lastNLines$1(text2, n) {
|
|
29032
|
+
const lines = text2.split("\n").filter(Boolean);
|
|
29033
|
+
return lines.slice(-n).join("\n");
|
|
29034
|
+
}
|
|
29035
|
+
const configs = [
|
|
29036
|
+
// ── File tools ────────────────────────
|
|
29037
|
+
{
|
|
29038
|
+
name: "read",
|
|
29039
|
+
displayName: "Read",
|
|
29040
|
+
icon: "FileText",
|
|
29041
|
+
category: "file",
|
|
29042
|
+
formatCallSummary: (a) => {
|
|
29043
|
+
const path2 = a.path || "";
|
|
29044
|
+
const offset = a.offset;
|
|
29045
|
+
const limit = a.limit;
|
|
29046
|
+
const suffix2 = offset ? ` · lines ${offset}-${offset + (limit || 2e3)}` : "";
|
|
29047
|
+
return `${getFileName(path2)}${suffix2}`;
|
|
29048
|
+
},
|
|
29049
|
+
formatCallDetail: (a) => ({ path: a.path, offset: a.offset, limit: a.limit }),
|
|
29050
|
+
formatResultSummary: (result) => {
|
|
29051
|
+
const text2 = extractResultText(result);
|
|
29052
|
+
const lineCount = text2 ? text2.split("\n").length : 0;
|
|
29053
|
+
return lineCount ? `${lineCount} lines` : "Read completed";
|
|
29054
|
+
},
|
|
29055
|
+
formatResultDetail: (result) => {
|
|
29056
|
+
const text2 = extractResultText(result);
|
|
29057
|
+
return { lineCount: text2 ? text2.split("\n").length : 0 };
|
|
29058
|
+
}
|
|
29059
|
+
},
|
|
29060
|
+
{
|
|
29061
|
+
name: "write",
|
|
29062
|
+
displayName: "Write",
|
|
29063
|
+
icon: "FileText",
|
|
29064
|
+
category: "file",
|
|
29065
|
+
formatCallSummary: (a) => getFileName(a.path || ""),
|
|
29066
|
+
formatCallDetail: (a) => ({ path: a.path }),
|
|
29067
|
+
formatResultSummary: (_2, a) => `Written: ${getFileName(a?.path || "")}`,
|
|
29068
|
+
formatResultDetail: (_2, a) => ({ path: a?.path })
|
|
29069
|
+
},
|
|
29070
|
+
{
|
|
29071
|
+
name: "edit",
|
|
29072
|
+
displayName: "Edit",
|
|
29073
|
+
icon: "FileText",
|
|
29074
|
+
category: "file",
|
|
29075
|
+
formatCallSummary: (a) => getFileName(a.path || ""),
|
|
29076
|
+
formatCallDetail: (a) => ({ path: a.path }),
|
|
29077
|
+
formatResultSummary: (_2, a) => `Edited: ${getFileName(a?.path || "")}`,
|
|
29078
|
+
formatResultDetail: (_2, a) => ({ path: a?.path })
|
|
29079
|
+
},
|
|
29080
|
+
// ── Code tools ────────────────────────
|
|
29081
|
+
{
|
|
29082
|
+
name: "bash",
|
|
29083
|
+
displayName: "Bash",
|
|
29084
|
+
icon: "Terminal",
|
|
29085
|
+
category: "code",
|
|
29086
|
+
formatCallSummary: (a) => {
|
|
29087
|
+
const cmd = a.command || "";
|
|
29088
|
+
return cmd.length > 60 ? `$ ${cmd.slice(0, 57)}...` : `$ ${cmd}`;
|
|
29089
|
+
},
|
|
29090
|
+
formatCallDetail: (a) => ({ command: truncStr(a.command, 200) }),
|
|
29091
|
+
formatResultSummary: () => "Command completed",
|
|
29092
|
+
formatResultDetail: (result) => {
|
|
29093
|
+
const text2 = extractResultText(result);
|
|
29094
|
+
const lines = text2.split("\n").filter(Boolean);
|
|
29095
|
+
return { outputLines: lines.length, outputPreview: truncStr(lastNLines$1(text2, 3), 200) };
|
|
29096
|
+
},
|
|
29097
|
+
formatProgress: (partial) => {
|
|
29098
|
+
const text2 = partial?.content?.[0]?.text;
|
|
29099
|
+
if (typeof text2 === "string" && text2.length > 0) {
|
|
29100
|
+
return lastNLines$1(text2, 5);
|
|
29101
|
+
}
|
|
29102
|
+
return void 0;
|
|
29103
|
+
}
|
|
29104
|
+
},
|
|
29105
|
+
// ── Search tools ────────────────────────
|
|
29106
|
+
{
|
|
29107
|
+
name: "grep",
|
|
29108
|
+
displayName: "Search",
|
|
29109
|
+
icon: "Search",
|
|
29110
|
+
category: "search",
|
|
29111
|
+
formatCallSummary: (a) => `"${truncStr(a.pattern, 30)}"${a.path ? ` in ${a.path}` : ""}`,
|
|
29112
|
+
formatCallDetail: (a) => ({ pattern: a.pattern, path: a.path, glob: a.glob }),
|
|
29113
|
+
formatResultSummary: (result) => {
|
|
29114
|
+
const text2 = extractResultText(result);
|
|
29115
|
+
const count = text2.split("\n").filter(Boolean).length;
|
|
29116
|
+
return `${count} results`;
|
|
29117
|
+
},
|
|
29118
|
+
formatResultDetail: (result) => {
|
|
29119
|
+
const text2 = extractResultText(result);
|
|
29120
|
+
return { matchCount: text2.split("\n").filter(Boolean).length };
|
|
29121
|
+
}
|
|
29122
|
+
},
|
|
29123
|
+
{
|
|
29124
|
+
name: "glob",
|
|
29125
|
+
displayName: "Find Files",
|
|
29126
|
+
icon: "Search",
|
|
29127
|
+
category: "search",
|
|
29128
|
+
formatCallSummary: (a) => a.pattern || "",
|
|
29129
|
+
formatCallDetail: (a) => ({ pattern: a.pattern, path: a.path }),
|
|
29130
|
+
formatResultSummary: (result) => {
|
|
29131
|
+
const text2 = extractResultText(result);
|
|
29132
|
+
const count = text2.split("\n").filter(Boolean).length;
|
|
29133
|
+
return `${count} files`;
|
|
29134
|
+
},
|
|
29135
|
+
formatResultDetail: (result) => {
|
|
29136
|
+
const text2 = extractResultText(result);
|
|
29137
|
+
return { fileCount: text2.split("\n").filter(Boolean).length };
|
|
29138
|
+
}
|
|
29139
|
+
},
|
|
29140
|
+
{
|
|
29141
|
+
name: "find",
|
|
29142
|
+
displayName: "Find",
|
|
29143
|
+
icon: "Search",
|
|
29144
|
+
category: "search",
|
|
29145
|
+
formatCallSummary: (a) => truncStr(a.pattern || a.path, 40),
|
|
29146
|
+
formatCallDetail: (a) => ({ pattern: a.pattern, path: a.path }),
|
|
29147
|
+
formatResultSummary: () => "Find completed",
|
|
29148
|
+
formatResultDetail: () => ({})
|
|
29149
|
+
},
|
|
29150
|
+
{
|
|
29151
|
+
name: "ls",
|
|
29152
|
+
displayName: "List",
|
|
29153
|
+
icon: "FileText",
|
|
29154
|
+
category: "file",
|
|
29155
|
+
formatCallSummary: (a) => a.path || ".",
|
|
29156
|
+
formatCallDetail: (a) => ({ path: a.path }),
|
|
29157
|
+
formatResultSummary: () => "Listed",
|
|
29158
|
+
formatResultDetail: () => ({})
|
|
29159
|
+
},
|
|
29160
|
+
// ── Web tools ────────────────────────
|
|
29161
|
+
{
|
|
29162
|
+
name: "fetch",
|
|
29163
|
+
displayName: "Fetch",
|
|
29164
|
+
icon: "Globe",
|
|
29165
|
+
category: "web",
|
|
29166
|
+
formatCallSummary: (a) => truncStr(a.url, 50),
|
|
29167
|
+
formatCallDetail: (a) => ({ url: a.url }),
|
|
29168
|
+
formatResultSummary: (result) => {
|
|
29169
|
+
const text2 = extractResultText(result);
|
|
29170
|
+
const kb = (text2.length / 1024).toFixed(1);
|
|
29171
|
+
return `${kb}KB received`;
|
|
29172
|
+
},
|
|
29173
|
+
formatResultDetail: (result) => {
|
|
29174
|
+
const text2 = extractResultText(result);
|
|
29175
|
+
return { sizeKB: parseFloat((text2.length / 1024).toFixed(1)) };
|
|
29176
|
+
}
|
|
29177
|
+
},
|
|
29178
|
+
{
|
|
29179
|
+
name: "web_fetch",
|
|
29180
|
+
displayName: "Web Fetch",
|
|
29181
|
+
icon: "Globe",
|
|
29182
|
+
category: "web",
|
|
29183
|
+
formatCallSummary: (a) => truncStr(a.url, 50),
|
|
29184
|
+
formatCallDetail: (a) => ({ url: a.url }),
|
|
29185
|
+
formatResultSummary: (result) => {
|
|
29186
|
+
const r = safeRecord(result);
|
|
29187
|
+
const data = safeRecord(r.data);
|
|
29188
|
+
const charCount = data.charCount;
|
|
29189
|
+
if (charCount) return `${(charCount / 1024).toFixed(1)}KB received`;
|
|
29190
|
+
return "Fetch completed";
|
|
29191
|
+
},
|
|
29192
|
+
formatResultDetail: (result) => {
|
|
29193
|
+
const r = safeRecord(result);
|
|
29194
|
+
const data = safeRecord(r.data);
|
|
29195
|
+
return { charCount: data.charCount, url: data.url };
|
|
29196
|
+
}
|
|
29197
|
+
},
|
|
29198
|
+
{
|
|
29199
|
+
name: "web_search",
|
|
29200
|
+
displayName: "Web Search",
|
|
29201
|
+
icon: "Globe",
|
|
29202
|
+
category: "web",
|
|
29203
|
+
formatCallSummary: (a) => truncStr(a.query, 50),
|
|
29204
|
+
formatCallDetail: (a) => ({ query: a.query }),
|
|
29205
|
+
formatResultSummary: () => "Search completed",
|
|
29206
|
+
formatResultDetail: () => ({})
|
|
29207
|
+
},
|
|
29208
|
+
// ── Research tools ────────────────────────
|
|
29209
|
+
{
|
|
29210
|
+
name: "literature-search",
|
|
29211
|
+
displayName: "Literature Search",
|
|
29212
|
+
icon: "BookOpen",
|
|
29213
|
+
category: "research",
|
|
29214
|
+
formatCallSummary: (a) => truncStr(a.query, 40),
|
|
29215
|
+
formatCallDetail: (a) => ({ query: a.query, maxResults: a.max_results }),
|
|
29216
|
+
formatResultSummary: (result) => {
|
|
29217
|
+
const r = safeRecord(result);
|
|
29218
|
+
const data = safeRecord(r.data);
|
|
29219
|
+
const totalFound = data.totalPapersFound ?? 0;
|
|
29220
|
+
const saved = data.papersAutoSaved ?? 0;
|
|
29221
|
+
const coverage = data.coverage;
|
|
29222
|
+
if (totalFound > 0) {
|
|
29223
|
+
let s15 = `Found ${totalFound} papers`;
|
|
29224
|
+
if (coverage?.score != null) s15 += ` (${Math.round(coverage.score * 100)}%)`;
|
|
29225
|
+
if (saved > 0) s15 += `, saved ${saved}`;
|
|
29226
|
+
return s15;
|
|
29227
|
+
}
|
|
29228
|
+
const local = data.localPapersUsed ?? 0;
|
|
29229
|
+
const external = data.externalPapersUsed ?? 0;
|
|
29230
|
+
return `Found ${local + external} papers`;
|
|
29231
|
+
},
|
|
29232
|
+
formatResultDetail: (result) => {
|
|
29233
|
+
const r = safeRecord(result);
|
|
29234
|
+
const data = safeRecord(r.data);
|
|
29235
|
+
return {
|
|
29236
|
+
papersFound: data.totalPapersFound ?? 0,
|
|
29237
|
+
papersSaved: data.papersAutoSaved ?? 0,
|
|
29238
|
+
coverage: data.coverage?.score
|
|
29239
|
+
};
|
|
29240
|
+
}
|
|
29241
|
+
},
|
|
29242
|
+
{
|
|
29243
|
+
name: "lit-subtopic",
|
|
29244
|
+
displayName: "Sub-topic Search",
|
|
29245
|
+
icon: "BookOpen",
|
|
29246
|
+
category: "research",
|
|
29247
|
+
formatCallSummary: (a) => a._summary || "Searching sub-topic",
|
|
29248
|
+
formatCallDetail: (a) => ({ summary: a._summary }),
|
|
29249
|
+
formatResultSummary: (result) => safeRecord(result).data || "Search completed",
|
|
29250
|
+
formatResultDetail: () => ({})
|
|
29251
|
+
},
|
|
29252
|
+
{
|
|
29253
|
+
name: "lit-enrich",
|
|
29254
|
+
displayName: "Enrich Papers",
|
|
29255
|
+
icon: "BookOpen",
|
|
29256
|
+
category: "research",
|
|
29257
|
+
formatCallSummary: (a) => a._summary || "Enriching paper metadata",
|
|
29258
|
+
formatCallDetail: (a) => ({ summary: a._summary }),
|
|
29259
|
+
formatResultSummary: (result) => safeRecord(result).data || "Enriched metadata",
|
|
29260
|
+
formatResultDetail: () => ({})
|
|
29261
|
+
},
|
|
29262
|
+
{
|
|
29263
|
+
name: "lit-autosave",
|
|
29264
|
+
displayName: "Save Papers",
|
|
29265
|
+
icon: "BookOpen",
|
|
29266
|
+
category: "research",
|
|
29267
|
+
formatCallSummary: (a) => a._summary || "Saving papers",
|
|
29268
|
+
formatCallDetail: (a) => ({ summary: a._summary }),
|
|
29269
|
+
formatResultSummary: (result) => safeRecord(result).data || "Saved papers",
|
|
29270
|
+
formatResultDetail: () => ({})
|
|
29271
|
+
},
|
|
29272
|
+
{
|
|
29273
|
+
name: "data_analyze",
|
|
29274
|
+
displayName: "Data Analysis",
|
|
29275
|
+
icon: "Database",
|
|
29276
|
+
category: "research",
|
|
29277
|
+
formatCallSummary: (a) => getFileName(a.file_path || "") || "data",
|
|
29278
|
+
formatCallDetail: (a) => ({ file_path: a.file_path }),
|
|
29279
|
+
formatResultSummary: () => "Analysis completed",
|
|
29280
|
+
formatResultDetail: () => ({})
|
|
29281
|
+
},
|
|
29282
|
+
// ── Artifact tools ────────────────────────
|
|
29283
|
+
{
|
|
29284
|
+
name: "artifact-create",
|
|
29285
|
+
displayName: "Create Artifact",
|
|
29286
|
+
icon: "Sparkles",
|
|
29287
|
+
category: "memory",
|
|
29288
|
+
formatCallSummary: (a) => {
|
|
29289
|
+
const type = (a.type || "artifact").toLowerCase();
|
|
29290
|
+
const title = truncStr(a.title, 35);
|
|
29291
|
+
return `${type}: ${title}`;
|
|
29292
|
+
},
|
|
29293
|
+
formatCallDetail: (a) => ({ type: a.type, title: a.title }),
|
|
29294
|
+
formatResultSummary: (result) => {
|
|
29295
|
+
const data = safeRecord(safeRecord(result).data);
|
|
29296
|
+
const type = data.type || "artifact";
|
|
29297
|
+
const title = truncStr(data.title, 30);
|
|
29298
|
+
return title ? `Created ${type}: ${title}` : `Created ${type}`;
|
|
29299
|
+
},
|
|
29300
|
+
formatResultDetail: (result) => {
|
|
29301
|
+
const data = safeRecord(safeRecord(result).data);
|
|
29302
|
+
return { type: data.type, title: data.title };
|
|
29303
|
+
}
|
|
29304
|
+
},
|
|
29305
|
+
{
|
|
29306
|
+
name: "artifact-update",
|
|
29307
|
+
displayName: "Update Artifact",
|
|
29308
|
+
icon: "Sparkles",
|
|
29309
|
+
category: "memory",
|
|
29310
|
+
formatCallSummary: (a) => truncStr(a.id, 30),
|
|
29311
|
+
formatCallDetail: (a) => ({ id: a.id }),
|
|
29312
|
+
formatResultSummary: () => "Updated",
|
|
29313
|
+
formatResultDetail: () => ({})
|
|
29314
|
+
},
|
|
29315
|
+
{
|
|
29316
|
+
name: "artifact-search",
|
|
29317
|
+
displayName: "Search Artifacts",
|
|
29318
|
+
icon: "Search",
|
|
29319
|
+
category: "memory",
|
|
29320
|
+
formatCallSummary: (a) => truncStr(a.query, 40),
|
|
29321
|
+
formatCallDetail: (a) => ({ query: a.query, types: a.types }),
|
|
29322
|
+
formatResultSummary: () => "Search completed",
|
|
29323
|
+
formatResultDetail: () => ({})
|
|
29324
|
+
},
|
|
29325
|
+
// ── System tools ────────────────────────
|
|
29326
|
+
{
|
|
29327
|
+
name: "convert_document",
|
|
29328
|
+
displayName: "Convert Document",
|
|
29329
|
+
icon: "FileText",
|
|
29330
|
+
category: "system",
|
|
29331
|
+
formatCallSummary: (a) => getFileName(a.source || ""),
|
|
29332
|
+
formatCallDetail: (a) => ({ source: a.source }),
|
|
29333
|
+
formatResultSummary: (result, a) => {
|
|
29334
|
+
const data = safeRecord(safeRecord(result).data);
|
|
29335
|
+
const skill = data.converterSkill;
|
|
29336
|
+
const sourceName = getFileName(a?.source || "");
|
|
29337
|
+
return skill ? `Converted ${sourceName} via ${skill}` : `Converted ${sourceName}`;
|
|
29338
|
+
},
|
|
29339
|
+
formatResultDetail: (result) => {
|
|
29340
|
+
const data = safeRecord(safeRecord(result).data);
|
|
29341
|
+
return { converterSkill: data.converterSkill, outputFile: data.outputFile };
|
|
29342
|
+
}
|
|
29343
|
+
},
|
|
29344
|
+
{
|
|
29345
|
+
name: "load_skill",
|
|
29346
|
+
displayName: "Load Skill",
|
|
29347
|
+
icon: "Sparkles",
|
|
29348
|
+
category: "system",
|
|
29349
|
+
formatCallSummary: (a) => a.name || "skill",
|
|
29350
|
+
formatCallDetail: (a) => ({ name: a.name }),
|
|
29351
|
+
formatResultSummary: (_2, a) => `Loaded: ${a?.name || "skill"}`,
|
|
29352
|
+
formatResultDetail: () => ({})
|
|
29353
|
+
}
|
|
29354
|
+
];
|
|
29355
|
+
const registry = /* @__PURE__ */ new Map();
|
|
29356
|
+
for (const config of configs) {
|
|
29357
|
+
registry.set(config.name, config);
|
|
29358
|
+
}
|
|
29359
|
+
function getToolDisplayName(toolName) {
|
|
29360
|
+
return registry.get(toolName)?.displayName || toolName;
|
|
29361
|
+
}
|
|
29362
|
+
function getToolIcon(toolName) {
|
|
29363
|
+
return registry.get(toolName)?.icon || "Wrench";
|
|
29364
|
+
}
|
|
29365
|
+
const ICON_MAP = {
|
|
29366
|
+
FileText,
|
|
29367
|
+
Terminal,
|
|
29368
|
+
Search,
|
|
29369
|
+
Globe,
|
|
29370
|
+
Wrench,
|
|
29371
|
+
BookOpen,
|
|
29372
|
+
Database,
|
|
29373
|
+
Sparkles
|
|
29374
|
+
};
|
|
29375
|
+
function getToolMeta(tool) {
|
|
29376
|
+
return {
|
|
29377
|
+
name: getToolDisplayName(tool),
|
|
29378
|
+
Icon: ICON_MAP[getToolIcon(tool)] || Wrench
|
|
29379
|
+
};
|
|
29380
|
+
}
|
|
29381
|
+
function StatusIcon({ status, size = 13 }) {
|
|
29382
|
+
switch (status) {
|
|
29383
|
+
case "running":
|
|
29384
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { size, className: "animate-spin t-text-accent-soft" });
|
|
29385
|
+
case "success":
|
|
29386
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheck, { size, className: "t-text-success" });
|
|
29387
|
+
case "error":
|
|
29388
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { size, className: "t-text-error" });
|
|
29389
|
+
}
|
|
29390
|
+
}
|
|
29391
|
+
function formatDuration$1(ms2) {
|
|
29392
|
+
if (ms2 < 1e3) return `${ms2}ms`;
|
|
29393
|
+
if (ms2 < 6e4) return `${(ms2 / 1e3).toFixed(1)}s`;
|
|
29394
|
+
return `${(ms2 / 6e4).toFixed(1)}m`;
|
|
29395
|
+
}
|
|
29396
|
+
function ElapsedTimer({ startedAt }) {
|
|
29397
|
+
const [elapsed, setElapsed] = reactExports.useState(Date.now() - startedAt);
|
|
29398
|
+
reactExports.useEffect(() => {
|
|
29399
|
+
const interval = setInterval(() => setElapsed(Date.now() - startedAt), 500);
|
|
29400
|
+
return () => clearInterval(interval);
|
|
29401
|
+
}, [startedAt]);
|
|
29402
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] t-text-muted tabular-nums", children: formatDuration$1(elapsed) });
|
|
29403
|
+
}
|
|
29404
|
+
const CompactToolLine = React$2.memo(function CompactToolLine2({ event }) {
|
|
29405
|
+
const [expanded, setExpanded] = reactExports.useState(false);
|
|
29406
|
+
const { name: name2, Icon: Icon2 } = getToolMeta(event.tool);
|
|
29407
|
+
const displaySummary = event.resultSummary || event.summary;
|
|
29408
|
+
const detailItems = buildDetailItems(event.tool, event.detail, event.resultDetail);
|
|
29409
|
+
const hasExpandable = detailItems.length > 0;
|
|
29410
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
29411
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
29412
|
+
"button",
|
|
29413
|
+
{
|
|
29414
|
+
onClick: () => hasExpandable && setExpanded(!expanded),
|
|
29415
|
+
className: `w-full flex items-center gap-1.5 px-2 py-[3px] text-[11px] rounded transition-colors ${hasExpandable ? "hover:t-bg-hover cursor-pointer" : "cursor-default"}`,
|
|
29416
|
+
children: [
|
|
29417
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(StatusIcon, { status: event.status, size: 11 }),
|
|
29418
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Icon2, { size: 10, className: "t-text-muted shrink-0" }),
|
|
29419
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium t-text-secondary shrink-0", children: name2 }),
|
|
29420
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-muted select-none", children: "·" }),
|
|
29421
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-muted truncate flex-1 text-left", children: displaySummary }),
|
|
29422
|
+
event.durationMs != null && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] t-text-muted tabular-nums shrink-0", children: formatDuration$1(event.durationMs) }),
|
|
29423
|
+
hasExpandable && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29424
|
+
"span",
|
|
29425
|
+
{
|
|
29426
|
+
className: "t-text-muted shrink-0 transition-transform duration-150",
|
|
29427
|
+
style: { transform: expanded ? "rotate(90deg)" : "rotate(0deg)" },
|
|
29428
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 9 })
|
|
29429
|
+
}
|
|
29430
|
+
)
|
|
29431
|
+
]
|
|
29432
|
+
}
|
|
29433
|
+
),
|
|
29434
|
+
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-5 mr-2 mb-1 mt-0.5", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandedDetail, { event }) })
|
|
29435
|
+
] });
|
|
29436
|
+
});
|
|
29437
|
+
const RunningToolCard = React$2.memo(function RunningToolCard2({ event }) {
|
|
29438
|
+
const [expanded, setExpanded] = reactExports.useState(false);
|
|
29439
|
+
const { name: name2, Icon: Icon2 } = getToolMeta(event.tool);
|
|
29440
|
+
const displaySummary = event.summary;
|
|
29441
|
+
const detailItems = buildDetailItems(event.tool, event.detail, event.resultDetail);
|
|
29442
|
+
const hasExpandable = detailItems.length > 0 || event.progress;
|
|
29443
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg border t-border t-bg-surface shadow-sm overflow-hidden", children: [
|
|
29444
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
29445
|
+
"button",
|
|
29446
|
+
{
|
|
29447
|
+
onClick: () => hasExpandable && setExpanded(!expanded),
|
|
29448
|
+
className: `w-full flex items-center gap-2 px-3 py-2 text-xs transition-colors ${hasExpandable ? "hover:t-bg-hover cursor-pointer" : "cursor-default"}`,
|
|
29449
|
+
children: [
|
|
29450
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(StatusIcon, { status: event.status }),
|
|
29451
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Icon2, { size: 12, className: "t-text-accent-soft shrink-0" }),
|
|
29452
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium t-text shrink-0", children: name2 }),
|
|
29453
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-muted select-none", children: "·" }),
|
|
29454
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-secondary truncate flex-1 text-left", children: displaySummary }),
|
|
29455
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ElapsedTimer, { startedAt: event.startedAt }),
|
|
29456
|
+
hasExpandable && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29457
|
+
"span",
|
|
29458
|
+
{
|
|
29459
|
+
className: "t-text-muted shrink-0 transition-transform duration-150",
|
|
29460
|
+
style: { transform: expanded ? "rotate(90deg)" : "rotate(0deg)" },
|
|
29461
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 10 })
|
|
29462
|
+
}
|
|
29463
|
+
)
|
|
29464
|
+
]
|
|
29465
|
+
}
|
|
29466
|
+
),
|
|
29467
|
+
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-t t-border px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ExpandedDetail, { event }) }),
|
|
29468
|
+
!expanded && event.progress && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-t t-border px-3 py-1.5", children: /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-[10px] font-mono t-text-muted overflow-hidden max-h-14 leading-relaxed whitespace-pre-wrap", children: event.progress }) })
|
|
29469
|
+
] });
|
|
29470
|
+
});
|
|
29471
|
+
const ToolUseCard = React$2.memo(function ToolUseCard2({ event, compact }) {
|
|
29472
|
+
if (compact || event.status !== "running") {
|
|
29473
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(CompactToolLine, { event });
|
|
29474
|
+
}
|
|
29475
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(RunningToolCard, { event });
|
|
29476
|
+
});
|
|
29477
|
+
function ExpandedDetail({ event }) {
|
|
29478
|
+
const items = buildDetailItems(event.tool, event.detail, event.resultDetail);
|
|
29479
|
+
const hasProgress = !!event.progress;
|
|
29480
|
+
if (items.length === 0 && !hasProgress) return null;
|
|
29481
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5", children: [
|
|
29482
|
+
items.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1", children: items.map((item, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(DetailItem, { ...item }, i)) }),
|
|
29483
|
+
hasProgress && /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "p-2 rounded t-bg-base text-[10px] font-mono t-text-secondary overflow-x-auto max-h-28 overflow-y-auto leading-relaxed whitespace-pre-wrap border t-border-subtle", children: event.progress })
|
|
29484
|
+
] });
|
|
29485
|
+
}
|
|
29486
|
+
function DetailItem({ type, label, value }) {
|
|
29487
|
+
switch (type) {
|
|
29488
|
+
case "path":
|
|
29489
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 text-[11px]", children: [
|
|
29490
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { size: 10, className: "t-text-muted shrink-0" }),
|
|
29491
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono t-text-secondary truncate", title: value, children: value })
|
|
29492
|
+
] });
|
|
29493
|
+
case "code":
|
|
29494
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "p-2 rounded t-bg-base text-[10px] font-mono t-text-secondary overflow-x-auto leading-relaxed whitespace-pre-wrap border t-border-subtle", children: value });
|
|
29495
|
+
case "stat":
|
|
29496
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-[10px]", children: [
|
|
29497
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-muted", children: label }),
|
|
29498
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium t-text-secondary tabular-nums", children: value })
|
|
29499
|
+
] });
|
|
29500
|
+
case "kv":
|
|
29501
|
+
default:
|
|
29502
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-baseline gap-2 text-[11px]", children: [
|
|
29503
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-muted shrink-0 text-[10px]", children: label }),
|
|
29504
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-secondary font-mono truncate", title: value, children: value })
|
|
29505
|
+
] });
|
|
29506
|
+
}
|
|
29507
|
+
}
|
|
29508
|
+
function buildDetailItems(tool, detail, resultDetail) {
|
|
29509
|
+
const items = [];
|
|
29510
|
+
if (!detail && !resultDetail) return items;
|
|
29511
|
+
switch (tool) {
|
|
29512
|
+
case "read": {
|
|
29513
|
+
const path2 = detail?.path;
|
|
29514
|
+
if (path2) items.push({ type: "path", value: path2 });
|
|
29515
|
+
const lineCount = resultDetail?.lineCount;
|
|
29516
|
+
if (lineCount) items.push({ type: "stat", label: "Lines read", value: String(lineCount) });
|
|
29517
|
+
break;
|
|
29518
|
+
}
|
|
29519
|
+
case "write":
|
|
29520
|
+
case "edit": {
|
|
29521
|
+
const path2 = detail?.path || resultDetail?.path;
|
|
29522
|
+
if (path2) items.push({ type: "path", value: path2 });
|
|
29523
|
+
break;
|
|
29524
|
+
}
|
|
29525
|
+
case "bash": {
|
|
29526
|
+
const cmd = detail?.command;
|
|
29527
|
+
if (cmd) items.push({ type: "code", value: `$ ${cmd}` });
|
|
29528
|
+
const preview = resultDetail?.outputPreview;
|
|
29529
|
+
if (preview) items.push({ type: "code", value: preview });
|
|
29530
|
+
const lines = resultDetail?.outputLines;
|
|
29531
|
+
if (lines && !preview) items.push({ type: "stat", label: "Output", value: `${lines} lines` });
|
|
29532
|
+
break;
|
|
29533
|
+
}
|
|
29534
|
+
case "grep": {
|
|
29535
|
+
const pattern = detail?.pattern;
|
|
29536
|
+
const path2 = detail?.path;
|
|
29537
|
+
if (pattern) items.push({ type: "kv", label: "Pattern", value: pattern });
|
|
29538
|
+
if (path2) items.push({ type: "kv", label: "Path", value: path2 });
|
|
29539
|
+
const count = resultDetail?.matchCount;
|
|
29540
|
+
if (count != null) items.push({ type: "stat", label: "Matches", value: String(count) });
|
|
29541
|
+
break;
|
|
29542
|
+
}
|
|
29543
|
+
case "glob": {
|
|
29544
|
+
const pattern = detail?.pattern;
|
|
29545
|
+
if (pattern) items.push({ type: "kv", label: "Pattern", value: pattern });
|
|
29546
|
+
const count = resultDetail?.fileCount;
|
|
29547
|
+
if (count != null) items.push({ type: "stat", label: "Files found", value: String(count) });
|
|
29548
|
+
break;
|
|
29549
|
+
}
|
|
29550
|
+
case "fetch":
|
|
29551
|
+
case "web_fetch": {
|
|
29552
|
+
const url = detail?.url;
|
|
29553
|
+
if (url) items.push({ type: "kv", label: "URL", value: url });
|
|
29554
|
+
const size = resultDetail?.sizeKB || resultDetail?.charCount;
|
|
29555
|
+
if (size) items.push({ type: "stat", label: "Received", value: size > 1024 ? `${(size / 1024).toFixed(1)}MB` : `${size}KB` });
|
|
29556
|
+
break;
|
|
29557
|
+
}
|
|
29558
|
+
case "web_search": {
|
|
29559
|
+
const query = detail?.query;
|
|
29560
|
+
if (query) items.push({ type: "kv", label: "Query", value: query });
|
|
29561
|
+
break;
|
|
29562
|
+
}
|
|
29563
|
+
case "literature-search": {
|
|
29564
|
+
const query = detail?.query;
|
|
29565
|
+
if (query) items.push({ type: "kv", label: "Query", value: query });
|
|
29566
|
+
const found = resultDetail?.papersFound;
|
|
29567
|
+
const saved = resultDetail?.papersSaved;
|
|
29568
|
+
const coverage = resultDetail?.coverage;
|
|
29569
|
+
if (found != null) items.push({ type: "stat", label: "Papers found", value: String(found) });
|
|
29570
|
+
if (saved != null && saved > 0) items.push({ type: "stat", label: "Saved", value: String(saved) });
|
|
29571
|
+
if (coverage != null) items.push({ type: "stat", label: "Coverage", value: `${Math.round(coverage * 100)}%` });
|
|
29572
|
+
break;
|
|
29573
|
+
}
|
|
29574
|
+
case "artifact-create":
|
|
29575
|
+
case "artifact-update": {
|
|
29576
|
+
const type = detail?.type || resultDetail?.type;
|
|
29577
|
+
const title = detail?.title || resultDetail?.title;
|
|
29578
|
+
if (type) items.push({ type: "kv", label: "Type", value: type });
|
|
29579
|
+
if (title) items.push({ type: "kv", label: "Title", value: title });
|
|
29580
|
+
break;
|
|
29581
|
+
}
|
|
29582
|
+
case "artifact-search": {
|
|
29583
|
+
const query = detail?.query;
|
|
29584
|
+
if (query) items.push({ type: "kv", label: "Query", value: query });
|
|
29585
|
+
break;
|
|
29586
|
+
}
|
|
29587
|
+
default: {
|
|
29588
|
+
const skipKeys = /* @__PURE__ */ new Set(["success", "path"]);
|
|
29589
|
+
const source = { ...detail, ...resultDetail };
|
|
29590
|
+
for (const [key, val] of Object.entries(source)) {
|
|
29591
|
+
if (val == null || skipKeys.has(key)) continue;
|
|
29592
|
+
const strVal = typeof val === "string" ? val : JSON.stringify(val);
|
|
29593
|
+
if (strVal.length === 0 || strVal === "true" || strVal === "false") continue;
|
|
29594
|
+
items.push({ type: "kv", label: key, value: strVal });
|
|
29595
|
+
}
|
|
29596
|
+
break;
|
|
29597
|
+
}
|
|
29598
|
+
}
|
|
29599
|
+
return items;
|
|
29600
|
+
}
|
|
29601
|
+
const VISIBLE_COMPLETED = 3;
|
|
29602
|
+
function ToolUseStream({ events: propEvents }) {
|
|
29603
|
+
const liveEvents = useToolEventsStore((s15) => s15.currentRunEvents);
|
|
29604
|
+
const events = propEvents ?? liveEvents;
|
|
29605
|
+
const [showAll, setShowAll] = reactExports.useState(false);
|
|
29606
|
+
const { running, completed } = reactExports.useMemo(() => {
|
|
29607
|
+
const running2 = [];
|
|
29608
|
+
const completed2 = [];
|
|
29609
|
+
for (const e of events) {
|
|
29610
|
+
if (e.status === "running") running2.push(e);
|
|
29611
|
+
else completed2.push(e);
|
|
29612
|
+
}
|
|
29613
|
+
return { running: running2, completed: completed2 };
|
|
29614
|
+
}, [events]);
|
|
29615
|
+
if (events.length === 0) return null;
|
|
29616
|
+
const hiddenCount = showAll ? 0 : Math.max(0, completed.length - VISIBLE_COMPLETED);
|
|
29617
|
+
const visibleCompleted = showAll ? completed : completed.slice(-VISIBLE_COMPLETED);
|
|
29618
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "my-2 max-w-[80%]", children: [
|
|
29619
|
+
hiddenCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
29620
|
+
"button",
|
|
29621
|
+
{
|
|
29622
|
+
onClick: () => setShowAll(true),
|
|
29623
|
+
className: "flex items-center gap-1.5 px-2 py-1 mb-1 text-[10px] t-text-muted hover:t-text-accent-soft transition-colors rounded",
|
|
29624
|
+
children: [
|
|
29625
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 10 }),
|
|
29626
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
29627
|
+
hiddenCount,
|
|
29628
|
+
" more tool ",
|
|
29629
|
+
hiddenCount === 1 ? "call" : "calls"
|
|
29630
|
+
] })
|
|
29631
|
+
]
|
|
29632
|
+
}
|
|
29633
|
+
),
|
|
29634
|
+
visibleCompleted.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-0", children: visibleCompleted.map((event) => /* @__PURE__ */ jsxRuntimeExports.jsx(ToolUseCard, { event, compact: true }, event.id)) }),
|
|
29635
|
+
running.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 mt-1", children: running.map((event) => /* @__PURE__ */ jsxRuntimeExports.jsx(ToolUseCard, { event }, event.id)) })
|
|
29636
|
+
] });
|
|
29637
|
+
}
|
|
29638
|
+
const api$5 = window.api;
|
|
28406
29639
|
const remarkPlugins$1 = [remarkGfm];
|
|
28407
29640
|
function SelectionBookmark() {
|
|
28408
29641
|
const refreshAll = useEntityStore((s15) => s15.refreshAll);
|
|
@@ -28463,7 +29696,7 @@ function SelectionBookmark() {
|
|
|
28463
29696
|
try {
|
|
28464
29697
|
const first = selectedText.split(/[.!?\n]/)[0].trim();
|
|
28465
29698
|
const title = first.length > 60 ? first.slice(0, 57) + "…" : first || "Untitled selection";
|
|
28466
|
-
const created = await api$
|
|
29699
|
+
const created = await api$5.artifactCreate({
|
|
28467
29700
|
type: "note",
|
|
28468
29701
|
title,
|
|
28469
29702
|
content: selectedText,
|
|
@@ -28495,7 +29728,7 @@ function SelectionBookmark() {
|
|
|
28495
29728
|
{
|
|
28496
29729
|
ref: tooltipRef,
|
|
28497
29730
|
onMouseDown: handleSave,
|
|
28498
|
-
className: "fixed z-
|
|
29731
|
+
className: "fixed z-50 flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-xs font-medium shadow-lg border t-border transition-colors",
|
|
28499
29732
|
style: {
|
|
28500
29733
|
left: pos.x,
|
|
28501
29734
|
top: pos.y,
|
|
@@ -28528,7 +29761,7 @@ const MessageBubble = React$2.memo(function MessageBubble2({ msg, isSaved }) {
|
|
|
28528
29761
|
try {
|
|
28529
29762
|
const first = msg.content.replace(/^#+\s*/, "").split(/[.!?\n]/)[0].trim();
|
|
28530
29763
|
const title = first.length > 60 ? first.slice(0, 57) + "…" : first || "Untitled note";
|
|
28531
|
-
const created = await api$
|
|
29764
|
+
const created = await api$5.artifactCreate({
|
|
28532
29765
|
type: "note",
|
|
28533
29766
|
title,
|
|
28534
29767
|
content: msg.content,
|
|
@@ -28562,6 +29795,7 @@ const MessageBubble = React$2.memo(function MessageBubble2({ msg, isSaved }) {
|
|
|
28562
29795
|
{
|
|
28563
29796
|
src,
|
|
28564
29797
|
alt: "",
|
|
29798
|
+
loading: "lazy",
|
|
28565
29799
|
className: `rounded-lg border t-border cursor-pointer hover:opacity-90 transition-opacity ${isUser ? "max-h-48" : "max-h-80"}`,
|
|
28566
29800
|
onClick: () => window.open(src, "_blank")
|
|
28567
29801
|
},
|
|
@@ -28583,37 +29817,12 @@ const MessageBubble = React$2.memo(function MessageBubble2({ msg, isSaved }) {
|
|
|
28583
29817
|
}
|
|
28584
29818
|
) });
|
|
28585
29819
|
});
|
|
28586
|
-
function
|
|
28587
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex gap-
|
|
28588
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-
|
|
28589
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-
|
|
28590
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-
|
|
28591
|
-
] });
|
|
28592
|
-
}
|
|
28593
|
-
function ThinkingBubble() {
|
|
28594
|
-
const events = useActivityStore((s15) => s15.events);
|
|
28595
|
-
const activity = reactExports.useMemo(() => {
|
|
28596
|
-
const latest = [...events].reverse().find((e) => e.type === "tool-call") || events[events.length - 1];
|
|
28597
|
-
return latest?.summary || "";
|
|
28598
|
-
}, [events]);
|
|
28599
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
28600
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28601
|
-
"div",
|
|
28602
|
-
{
|
|
28603
|
-
className: "rounded-2xl px-4 py-3 text-sm t-text-secondary shrink-0",
|
|
28604
|
-
style: { background: "var(--color-bubble-assistant)" },
|
|
28605
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
28606
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(ThinkingDots, {}),
|
|
28607
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs", children: "Thinking" })
|
|
28608
|
-
] })
|
|
28609
|
-
}
|
|
28610
|
-
),
|
|
28611
|
-
activity && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex items-center gap-2 min-w-0", children: [
|
|
28612
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 h-px border-t t-border" }),
|
|
28613
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs t-text-muted whitespace-nowrap truncate max-w-[60%] animate-pulse", children: activity }),
|
|
28614
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 h-px border-t t-border" })
|
|
28615
|
-
] })
|
|
28616
|
-
] });
|
|
29820
|
+
function ThinkingIndicator() {
|
|
29821
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 mt-3 ml-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex gap-[3px] items-center", "aria-label": "Thinking", children: [
|
|
29822
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-[5px] h-[5px] rounded-full t-bg-accent-soft animate-bounce animation-delay-0" }),
|
|
29823
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-[5px] h-[5px] rounded-full t-bg-accent-soft animate-bounce animation-delay-150" }),
|
|
29824
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-[5px] h-[5px] rounded-full t-bg-accent-soft animate-bounce animation-delay-300" })
|
|
29825
|
+
] }) });
|
|
28617
29826
|
}
|
|
28618
29827
|
function StreamingBubble() {
|
|
28619
29828
|
const text2 = useChatStore((s15) => s15.streamingText);
|
|
@@ -28635,10 +29844,13 @@ function ChatMessages() {
|
|
|
28635
29844
|
const isStreaming = useChatStore((s15) => s15.isStreaming);
|
|
28636
29845
|
const streamingText = useChatStore((s15) => s15.streamingText);
|
|
28637
29846
|
const savedMessageIds = useChatStore((s15) => s15.savedMessageIds);
|
|
29847
|
+
const turnToolEvents = useChatStore((s15) => s15.turnToolEvents);
|
|
28638
29848
|
const hasMore = useChatStore((s15) => s15.hasMore);
|
|
28639
29849
|
const isLoadingHistory = useChatStore((s15) => s15.isLoadingHistory);
|
|
28640
29850
|
const loadHistory = useChatStore((s15) => s15.loadHistory);
|
|
28641
29851
|
const scrollToMessageId = useChatStore((s15) => s15.scrollToMessageId);
|
|
29852
|
+
const toolEventsCount = useToolEventsStore((s15) => s15.currentRunEvents.length);
|
|
29853
|
+
const hasRunningTools = useToolEventsStore((s15) => s15.currentRunEvents.some((e) => e.status === "running"));
|
|
28642
29854
|
const bottomRef = reactExports.useRef(null);
|
|
28643
29855
|
const scrollContainerRef = reactExports.useRef(null);
|
|
28644
29856
|
const [autoScroll, setAutoScroll] = reactExports.useState(true);
|
|
@@ -28671,7 +29883,7 @@ function ChatMessages() {
|
|
|
28671
29883
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
28672
29884
|
}
|
|
28673
29885
|
}
|
|
28674
|
-
}, [messages, streamingText, autoScroll]);
|
|
29886
|
+
}, [messages, streamingText, toolEventsCount, autoScroll]);
|
|
28675
29887
|
reactExports.useEffect(() => {
|
|
28676
29888
|
if (!scrollToMessageId || !scrollContainerRef.current) return;
|
|
28677
29889
|
const el2 = scrollContainerRef.current.querySelector(`[data-msg-id="${scrollToMessageId}"]`);
|
|
@@ -28695,24 +29907,42 @@ function ChatMessages() {
|
|
|
28695
29907
|
children: [
|
|
28696
29908
|
isLoadingHistory && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { size: 16, className: "animate-spin t-text-muted" }) }),
|
|
28697
29909
|
messages.map((msg, i) => {
|
|
29910
|
+
if (msg.role === "system") {
|
|
29911
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 my-5 px-2", children: [
|
|
29912
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 h-px t-bg-elevated" }),
|
|
29913
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] t-text-muted shrink-0", children: msg.content }),
|
|
29914
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 h-px t-bg-elevated" })
|
|
29915
|
+
] }, msg.id);
|
|
29916
|
+
}
|
|
28698
29917
|
const prev = messages[i - 1];
|
|
28699
29918
|
const gap = prev && prev.role !== msg.role ? "mt-5" : "mt-3";
|
|
28700
|
-
|
|
28701
|
-
|
|
28702
|
-
{
|
|
28703
|
-
|
|
28704
|
-
|
|
28705
|
-
|
|
28706
|
-
|
|
29919
|
+
const toolEvents = msg.role === "assistant" ? turnToolEvents.get(msg.id) : void 0;
|
|
29920
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: i === 0 ? "" : gap, children: [
|
|
29921
|
+
toolEvents && toolEvents.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(ToolUseStream, { events: toolEvents }),
|
|
29922
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29923
|
+
MessageBubble,
|
|
29924
|
+
{
|
|
29925
|
+
msg,
|
|
29926
|
+
isSaved: savedMessageIds.has(msg.id)
|
|
29927
|
+
}
|
|
29928
|
+
)
|
|
29929
|
+
] }, msg.id);
|
|
28707
29930
|
}),
|
|
28708
|
-
isStreaming && /* @__PURE__ */ jsxRuntimeExports.
|
|
29931
|
+
isStreaming && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-5", children: [
|
|
29932
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ToolUseStream, {}),
|
|
29933
|
+
streamingText ? /* @__PURE__ */ jsxRuntimeExports.jsx(StreamingBubble, {}) : !hasRunningTools ? (
|
|
29934
|
+
/* Show thinking dots only when no tools are running —
|
|
29935
|
+
running tool cards already have spinners as progress indicator */
|
|
29936
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ThinkingIndicator, {})
|
|
29937
|
+
) : null
|
|
29938
|
+
] }),
|
|
28709
29939
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: bottomRef })
|
|
28710
29940
|
]
|
|
28711
29941
|
}
|
|
28712
29942
|
)
|
|
28713
29943
|
] });
|
|
28714
29944
|
}
|
|
28715
|
-
const api$
|
|
29945
|
+
const api$4 = window.api;
|
|
28716
29946
|
const typeIcons$1 = {
|
|
28717
29947
|
note: /* @__PURE__ */ jsxRuntimeExports.jsx(StickyNote, { size: 13, className: "t-text-warning" }),
|
|
28718
29948
|
paper: /* @__PURE__ */ jsxRuntimeExports.jsx(BookOpen, { size: 13, className: "t-text-info" }),
|
|
@@ -28761,7 +29991,7 @@ function MentionPopover({ query, onSelect, onClose }) {
|
|
|
28761
29991
|
setLoading(true);
|
|
28762
29992
|
clearTimeout(debounceRef.current);
|
|
28763
29993
|
debounceRef.current = setTimeout(() => {
|
|
28764
|
-
api$
|
|
29994
|
+
api$4.getCandidates(query).then((result) => {
|
|
28765
29995
|
if (stale) return;
|
|
28766
29996
|
setCandidates(result || []);
|
|
28767
29997
|
setSelectedIdx(0);
|
|
@@ -28807,8 +30037,8 @@ function MentionPopover({ query, onSelect, onClose }) {
|
|
|
28807
30037
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
28808
30038
|
"div",
|
|
28809
30039
|
{
|
|
28810
|
-
className: "absolute z-50 w-[32rem] max-h-80 overflow-y-auto rounded-xl border t-border t-bg-surface shadow-xl",
|
|
28811
|
-
style: { bottom: "100%", left:
|
|
30040
|
+
className: "absolute z-50 w-[32rem] max-w-[calc(100vw-2rem)] max-h-80 overflow-y-auto rounded-xl border t-border t-bg-surface shadow-xl",
|
|
30041
|
+
style: { bottom: "100%", left: 0, marginBottom: 8 },
|
|
28812
30042
|
children: [
|
|
28813
30043
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-1.5 border-b t-border flex items-center gap-2 text-xs t-text-secondary", children: [
|
|
28814
30044
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AtSign, { size: 11 }),
|
|
@@ -28901,7 +30131,7 @@ function CommandPopover({ query, commands, onSelect, onClose }) {
|
|
|
28901
30131
|
"div",
|
|
28902
30132
|
{
|
|
28903
30133
|
className: "absolute z-50 w-72 rounded-xl border t-border t-bg-surface shadow-xl",
|
|
28904
|
-
style: { bottom: "100%", left:
|
|
30134
|
+
style: { bottom: "100%", left: 0, marginBottom: 8 },
|
|
28905
30135
|
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-3 text-xs t-text-muted", children: [
|
|
28906
30136
|
'No matching commands for "/',
|
|
28907
30137
|
query,
|
|
@@ -28914,7 +30144,7 @@ function CommandPopover({ query, commands, onSelect, onClose }) {
|
|
|
28914
30144
|
"div",
|
|
28915
30145
|
{
|
|
28916
30146
|
className: "absolute z-50 w-80 max-h-64 overflow-y-auto rounded-xl border t-border t-bg-surface shadow-xl",
|
|
28917
|
-
style: { bottom: "100%", left:
|
|
30147
|
+
style: { bottom: "100%", left: 0, marginBottom: 8 },
|
|
28918
30148
|
children: [
|
|
28919
30149
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-2 border-b t-border flex items-center gap-2 text-xs t-text-secondary", children: [
|
|
28920
30150
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { size: 12 }),
|
|
@@ -28954,7 +30184,7 @@ const SLASH_COMMANDS = [
|
|
|
28954
30184
|
{ name: "/delete", description: "Delete an entity", args: "<id>" },
|
|
28955
30185
|
{ name: "/help", description: "Show available commands" }
|
|
28956
30186
|
];
|
|
28957
|
-
const api$
|
|
30187
|
+
const api$3 = window.api;
|
|
28958
30188
|
const ACCEPTED_IMAGE_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
28959
30189
|
const MAX_IMAGES = 5;
|
|
28960
30190
|
const ACCEPTED_DOC_EXTENSIONS = [".pdf", ".csv", ".md", ".txt", ".json", ".xml", ".html", ".docx"];
|
|
@@ -28993,7 +30223,8 @@ function parseFlagArgs(raw) {
|
|
|
28993
30223
|
return { cleaned: cleaned.trim(), flags };
|
|
28994
30224
|
}
|
|
28995
30225
|
function ChatInput() {
|
|
28996
|
-
const
|
|
30226
|
+
const text2 = useChatStore((s15) => s15.draftText);
|
|
30227
|
+
const setText = useChatStore((s15) => s15.setDraftText);
|
|
28997
30228
|
const [showMention, setShowMention] = reactExports.useState(false);
|
|
28998
30229
|
const [mentionQuery, setMentionQuery] = reactExports.useState("");
|
|
28999
30230
|
const [showCommand, setShowCommand] = reactExports.useState(false);
|
|
@@ -29010,7 +30241,6 @@ function ChatInput() {
|
|
|
29010
30241
|
const hasProject = useSessionStore((s15) => s15.hasProject);
|
|
29011
30242
|
const refreshEntities = useEntityStore((s15) => s15.refreshAll);
|
|
29012
30243
|
reactExports.useEffect(() => {
|
|
29013
|
-
setText("");
|
|
29014
30244
|
setShowMention(false);
|
|
29015
30245
|
setShowCommand(false);
|
|
29016
30246
|
setPendingImages([]);
|
|
@@ -29075,7 +30305,7 @@ function ChatInput() {
|
|
|
29075
30305
|
const dataUrl = reader.result;
|
|
29076
30306
|
const base64 = dataUrl.split(",")[1];
|
|
29077
30307
|
try {
|
|
29078
|
-
const result = await api$
|
|
30308
|
+
const result = await api$3.convertFileToText(file.name, base64);
|
|
29079
30309
|
if (result?.success && result.content) {
|
|
29080
30310
|
setPendingFiles((p) => p.map(
|
|
29081
30311
|
(f) => f.name === file.name ? { ...f, content: result.content, loading: false } : f
|
|
@@ -29192,19 +30422,19 @@ ${fileBlocks}`;
|
|
|
29192
30422
|
try {
|
|
29193
30423
|
switch (cmd) {
|
|
29194
30424
|
case "/notes": {
|
|
29195
|
-
const notes = await api$
|
|
30425
|
+
const notes = await api$3.listNotes();
|
|
29196
30426
|
result = notes?.length ? `**Notes (${notes.length}):**
|
|
29197
30427
|
` + notes.map((n) => `- ${n.title} \`${n.id.slice(0, 8)}\``).join("\n") : "No notes yet.";
|
|
29198
30428
|
break;
|
|
29199
30429
|
}
|
|
29200
30430
|
case "/papers": {
|
|
29201
|
-
const papers = await api$
|
|
30431
|
+
const papers = await api$3.listLiterature();
|
|
29202
30432
|
result = papers?.length ? `**Papers (${papers.length}):**
|
|
29203
30433
|
` + papers.map((p) => `- ${p.title} \`${p.citeKey}\``).join("\n") : "No papers yet.";
|
|
29204
30434
|
break;
|
|
29205
30435
|
}
|
|
29206
30436
|
case "/data": {
|
|
29207
|
-
const data = await api$
|
|
30437
|
+
const data = await api$3.listData();
|
|
29208
30438
|
result = data?.length ? `**Data (${data.length}):**
|
|
29209
30439
|
` + data.map((d) => `- ${d.name} \`${d.id.slice(0, 8)}\``).join("\n") : "No data attachments yet.";
|
|
29210
30440
|
break;
|
|
@@ -29214,7 +30444,7 @@ ${fileBlocks}`;
|
|
|
29214
30444
|
result = "Usage: `/search <query>`";
|
|
29215
30445
|
break;
|
|
29216
30446
|
}
|
|
29217
|
-
const results = await api$
|
|
30447
|
+
const results = await api$3.search(rest);
|
|
29218
30448
|
result = results?.length ? `**Search results for "${rest}":**
|
|
29219
30449
|
` + results.map((r) => `- [${r.type}] ${r.title} \`${r.id.slice(0, 8)}\``).join("\n") : `No results for "${rest}".`;
|
|
29220
30450
|
break;
|
|
@@ -29224,7 +30454,7 @@ ${fileBlocks}`;
|
|
|
29224
30454
|
result = "Usage: `/note <title>`";
|
|
29225
30455
|
break;
|
|
29226
30456
|
}
|
|
29227
|
-
const r = await api$
|
|
30457
|
+
const r = await api$3.artifactCreate({ type: "note", title: rest, content: "" });
|
|
29228
30458
|
result = r?.success ? `Note saved: **${rest}**` : `Failed: ${r?.error || "unknown error"}`;
|
|
29229
30459
|
refreshEntities();
|
|
29230
30460
|
break;
|
|
@@ -29247,7 +30477,7 @@ ${fileBlocks}`;
|
|
|
29247
30477
|
const bibtex = flags.bibtex || `@article{${citeKey},
|
|
29248
30478
|
title = {${cleaned}}
|
|
29249
30479
|
}`;
|
|
29250
|
-
const r = await api$
|
|
30480
|
+
const r = await api$3.artifactCreate({
|
|
29251
30481
|
type: "paper",
|
|
29252
30482
|
title: cleaned,
|
|
29253
30483
|
authors,
|
|
@@ -29274,7 +30504,7 @@ ${fileBlocks}`;
|
|
|
29274
30504
|
result = "Usage: `/save-data <name> --path <file>`";
|
|
29275
30505
|
break;
|
|
29276
30506
|
}
|
|
29277
|
-
const r = await api$
|
|
30507
|
+
const r = await api$3.artifactCreate({
|
|
29278
30508
|
type: "data",
|
|
29279
30509
|
title: cleaned,
|
|
29280
30510
|
filePath: flags.path,
|
|
@@ -29285,7 +30515,7 @@ ${fileBlocks}`;
|
|
|
29285
30515
|
break;
|
|
29286
30516
|
}
|
|
29287
30517
|
case "/summary": {
|
|
29288
|
-
const summaryResult = await api$
|
|
30518
|
+
const summaryResult = await api$3.sessionSummaryGet();
|
|
29289
30519
|
if (!summaryResult?.success || !summaryResult?.summary) {
|
|
29290
30520
|
result = "No session summary available yet.";
|
|
29291
30521
|
break;
|
|
@@ -29312,7 +30542,7 @@ ${s15.openQuestions.map((q2) => `- ${q2}`).join("\n")}`;
|
|
|
29312
30542
|
result = "Usage: `/delete <id>`";
|
|
29313
30543
|
break;
|
|
29314
30544
|
}
|
|
29315
|
-
const r = await api$
|
|
30545
|
+
const r = await api$3.deleteEntity(rest);
|
|
29316
30546
|
result = r?.success ? `Deleted \`${rest}\`` : `Failed: ${r?.error || "not found"}`;
|
|
29317
30547
|
refreshEntities();
|
|
29318
30548
|
break;
|
|
@@ -29500,6 +30730,7 @@ ${s15.openQuestions.map((q2) => `- ${q2}`).join("\n")}`;
|
|
|
29500
30730
|
onKeyDown: handleKeyDown,
|
|
29501
30731
|
onPaste: handlePaste,
|
|
29502
30732
|
placeholder: "Ask anything, attach files, or type /commands...",
|
|
30733
|
+
"aria-label": "Chat message input",
|
|
29503
30734
|
rows: 1,
|
|
29504
30735
|
className: "flex-1 bg-transparent text-sm t-text placeholder:t-text-muted resize-none outline-none"
|
|
29505
30736
|
}
|
|
@@ -29691,7 +30922,7 @@ function PaperRow({
|
|
|
29691
30922
|
] })
|
|
29692
30923
|
] });
|
|
29693
30924
|
}
|
|
29694
|
-
function CoverageBar({ papers }) {
|
|
30925
|
+
function CoverageBar$1({ papers }) {
|
|
29695
30926
|
const topicCounts = reactExports.useMemo(() => {
|
|
29696
30927
|
const counts = /* @__PURE__ */ new Map();
|
|
29697
30928
|
for (const p of papers) {
|
|
@@ -29723,16 +30954,15 @@ function CoverageBar({ papers }) {
|
|
|
29723
30954
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 max-w-48", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1.5 rounded-full t-bg-elevated overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29724
30955
|
"div",
|
|
29725
30956
|
{
|
|
29726
|
-
className: "h-full rounded-full",
|
|
30957
|
+
className: "h-full rounded-full t-gradient-accent-h",
|
|
29727
30958
|
style: {
|
|
29728
|
-
width: `${Math.min(100, highRelevance / Math.max(papers.length, 1) * 100)}
|
|
29729
|
-
background: "linear-gradient(90deg, var(--color-accent), var(--color-accent-2))"
|
|
30959
|
+
width: `${Math.min(100, highRelevance / Math.max(papers.length, 1) * 100)}%`
|
|
29730
30960
|
}
|
|
29731
30961
|
}
|
|
29732
30962
|
) }) })
|
|
29733
30963
|
] });
|
|
29734
30964
|
}
|
|
29735
|
-
function FilterBar() {
|
|
30965
|
+
function FilterBar$1() {
|
|
29736
30966
|
const filter = useUIStore((s15) => s15.literatureFilter);
|
|
29737
30967
|
const setFilter = useUIStore((s15) => s15.setLiteratureFilter);
|
|
29738
30968
|
const [showFilters, setShowFilters] = reactExports.useState(false);
|
|
@@ -29868,7 +31098,7 @@ function LiteratureView() {
|
|
|
29868
31098
|
}, [papers, filter]);
|
|
29869
31099
|
const hasTopics = papers.some((p) => p.subTopic);
|
|
29870
31100
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col min-h-0", children: [
|
|
29871
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(FilterBar, {}),
|
|
31101
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(FilterBar$1, {}),
|
|
29872
31102
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex min-h-0", children: [
|
|
29873
31103
|
hasTopics && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29874
31104
|
TopicTree,
|
|
@@ -29943,18 +31173,360 @@ function LiteratureView() {
|
|
|
29943
31173
|
)) })
|
|
29944
31174
|
] })
|
|
29945
31175
|
] }),
|
|
29946
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CoverageBar, { papers: filtered })
|
|
31176
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CoverageBar$1, { papers: filtered })
|
|
29947
31177
|
] });
|
|
29948
31178
|
}
|
|
31179
|
+
function formatDuration(seconds) {
|
|
31180
|
+
if (!seconds || seconds < 0) return "--";
|
|
31181
|
+
if (seconds < 60) return `${Math.round(seconds)}s`;
|
|
31182
|
+
if (seconds < 3600) {
|
|
31183
|
+
const m2 = Math.floor(seconds / 60);
|
|
31184
|
+
const s15 = Math.round(seconds % 60);
|
|
31185
|
+
return s15 > 0 ? `${m2}m ${s15}s` : `${m2}m`;
|
|
31186
|
+
}
|
|
31187
|
+
const h2 = Math.floor(seconds / 3600);
|
|
31188
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
31189
|
+
return `${h2}h ${m}m`;
|
|
31190
|
+
}
|
|
31191
|
+
function formatBytes(bytes) {
|
|
31192
|
+
if (!bytes || bytes < 0) return "--";
|
|
31193
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
31194
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
31195
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
31196
|
+
}
|
|
31197
|
+
function timeAgo(iso) {
|
|
31198
|
+
const diff = Date.now() - new Date(iso).getTime();
|
|
31199
|
+
if (diff < 6e4) return "just now";
|
|
31200
|
+
if (diff < 36e5) return `${Math.floor(diff / 6e4)}m ago`;
|
|
31201
|
+
if (diff < 864e5) return `${Math.floor(diff / 36e5)}h ago`;
|
|
31202
|
+
return `${Math.floor(diff / 864e5)}d ago`;
|
|
31203
|
+
}
|
|
31204
|
+
const STATUS_LABELS = {
|
|
31205
|
+
running: "Running",
|
|
31206
|
+
stalled: "Stalled",
|
|
31207
|
+
completed: "Completed",
|
|
31208
|
+
failed: "Failed",
|
|
31209
|
+
timed_out: "Timed out",
|
|
31210
|
+
cancelled: "Cancelled"
|
|
31211
|
+
};
|
|
31212
|
+
function StatusDot({ status }) {
|
|
31213
|
+
const isActive = status === "running";
|
|
31214
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `inline-block w-1.5 h-1.5 rounded-full shrink-0 ${isActive ? "bg-[var(--color-accent)]" : "t-bg-elevated"}`, style: isActive ? {} : { opacity: 0.8 } });
|
|
31215
|
+
}
|
|
31216
|
+
function ProgressBar({ percentage }) {
|
|
31217
|
+
const value = Math.min(100, Math.max(0, percentage || 0));
|
|
31218
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1 rounded-full t-bg-elevated overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31219
|
+
"div",
|
|
31220
|
+
{
|
|
31221
|
+
className: "h-full rounded-full transition-all duration-700 t-gradient-accent-h",
|
|
31222
|
+
style: { width: `${value}%` }
|
|
31223
|
+
}
|
|
31224
|
+
) });
|
|
31225
|
+
}
|
|
31226
|
+
function RunRow({
|
|
31227
|
+
run,
|
|
31228
|
+
expanded,
|
|
31229
|
+
onToggle
|
|
31230
|
+
}) {
|
|
31231
|
+
const isActive = run.status === "running" || run.status === "stalled";
|
|
31232
|
+
const hasProgress = run.progress?.percentage !== void 0;
|
|
31233
|
+
const setCenterView = useUIStore((s15) => s15.setCenterView);
|
|
31234
|
+
const sendToChat = (text2) => {
|
|
31235
|
+
setCenterView("chat");
|
|
31236
|
+
setTimeout(() => {
|
|
31237
|
+
const inputEl = document.querySelector("[data-chat-input]");
|
|
31238
|
+
if (inputEl) {
|
|
31239
|
+
inputEl.value = text2;
|
|
31240
|
+
inputEl.focus();
|
|
31241
|
+
inputEl.dispatchEvent(new Event("input", { bubbles: true }));
|
|
31242
|
+
}
|
|
31243
|
+
}, 100);
|
|
31244
|
+
};
|
|
31245
|
+
const hasMetrics = run.progress?.metrics && Object.keys(run.progress.metrics).length > 0;
|
|
31246
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-b t-border last:border-b-0", children: [
|
|
31247
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
31248
|
+
"div",
|
|
31249
|
+
{
|
|
31250
|
+
className: "flex items-center gap-3 px-3 py-2 hover:bg-[var(--color-accent-soft)]/5 transition-colors cursor-pointer",
|
|
31251
|
+
onClick: onToggle,
|
|
31252
|
+
children: [
|
|
31253
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "shrink-0 t-text-muted", children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { size: 14 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 14 }) }),
|
|
31254
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(StatusDot, { status: run.status }),
|
|
31255
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
31256
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[13px] t-text font-medium truncate leading-tight font-mono", children: run.command }),
|
|
31257
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[11px] t-text-muted truncate mt-0.5", children: [
|
|
31258
|
+
run.runId,
|
|
31259
|
+
run.status !== "running" && run.status !== "stalled" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
31260
|
+
" · ",
|
|
31261
|
+
STATUS_LABELS[run.status] ?? run.status
|
|
31262
|
+
] }),
|
|
31263
|
+
run.stalled && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
31264
|
+
" · ",
|
|
31265
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-accent-soft", children: "stalled — no output for a while" })
|
|
31266
|
+
] }),
|
|
31267
|
+
run.failure && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
31268
|
+
" · ",
|
|
31269
|
+
run.failure.code
|
|
31270
|
+
] }),
|
|
31271
|
+
run.parentRunId && /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: " · retry" })
|
|
31272
|
+
] })
|
|
31273
|
+
] }),
|
|
31274
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 text-[11px] t-text-muted tabular-nums w-14 text-right", children: formatDuration(run.elapsedSeconds) }),
|
|
31275
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 text-[11px] t-text-muted w-14 text-right", children: isActive ? run.currentPhase : run.startedAt ? timeAgo(run.startedAt) : "--" })
|
|
31276
|
+
]
|
|
31277
|
+
}
|
|
31278
|
+
),
|
|
31279
|
+
isActive && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-10 pb-1.5", children: [
|
|
31280
|
+
hasProgress ? /* @__PURE__ */ jsxRuntimeExports.jsx(ProgressBar, { percentage: run.progress.percentage }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1 rounded-full t-bg-elevated overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full w-1/3 rounded-full animate-pulse t-gradient-accent-h opacity-30" }) }),
|
|
31281
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 mt-1 text-[10px] t-text-muted", children: [
|
|
31282
|
+
hasProgress && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
31283
|
+
run.progress.percentage,
|
|
31284
|
+
"%"
|
|
31285
|
+
] }),
|
|
31286
|
+
run.progress?.currentStep !== void 0 && run.progress?.totalSteps !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
31287
|
+
"Step ",
|
|
31288
|
+
run.progress.currentStep,
|
|
31289
|
+
"/",
|
|
31290
|
+
run.progress.totalSteps
|
|
31291
|
+
] }),
|
|
31292
|
+
run.progress?.phase && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: run.progress.phase }),
|
|
31293
|
+
run.progress?.etaSeconds !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
31294
|
+
"ETA ",
|
|
31295
|
+
formatDuration(run.progress.etaSeconds)
|
|
31296
|
+
] }),
|
|
31297
|
+
run.startedAt && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
31298
|
+
"started ",
|
|
31299
|
+
timeAgo(run.startedAt)
|
|
31300
|
+
] }),
|
|
31301
|
+
run.outputLines > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
31302
|
+
run.outputLines,
|
|
31303
|
+
" lines"
|
|
31304
|
+
] })
|
|
31305
|
+
] }),
|
|
31306
|
+
hasMetrics && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-1.5 mt-1.5", children: Object.entries(run.progress.metrics).map(([key, val]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-1.5 py-0.5 text-[10px] rounded t-bg-elevated t-text-secondary font-mono", children: [
|
|
31307
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-muted", children: key }),
|
|
31308
|
+
" ",
|
|
31309
|
+
typeof val === "number" ? val < 0.01 ? val.toExponential(2) : val.toFixed(4) : val
|
|
31310
|
+
] }, key)) })
|
|
31311
|
+
] }),
|
|
31312
|
+
expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-10 pb-3 space-y-2", children: [
|
|
31313
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap gap-1.5", children: [
|
|
31314
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-1.5 py-0.5 text-[10px] rounded t-bg-elevated t-text-muted", children: run.sandbox }),
|
|
31315
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-1.5 py-0.5 text-[10px] rounded t-bg-elevated t-text-muted", children: run.weight }),
|
|
31316
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-1.5 py-0.5 text-[10px] rounded t-bg-elevated t-text-muted", children: [
|
|
31317
|
+
formatBytes(run.outputBytes),
|
|
31318
|
+
" · ",
|
|
31319
|
+
run.outputLines,
|
|
31320
|
+
" lines"
|
|
31321
|
+
] }),
|
|
31322
|
+
run.exitCode !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-1.5 py-0.5 text-[10px] rounded t-bg-elevated t-text-muted", children: [
|
|
31323
|
+
"exit ",
|
|
31324
|
+
run.exitCode
|
|
31325
|
+
] }),
|
|
31326
|
+
run.startedAt && !isActive && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-1.5 py-0.5 text-[10px] rounded t-bg-elevated t-text-muted", children: [
|
|
31327
|
+
"started ",
|
|
31328
|
+
timeAgo(run.startedAt)
|
|
31329
|
+
] })
|
|
31330
|
+
] }),
|
|
31331
|
+
!isActive && hasMetrics && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-1.5", children: Object.entries(run.progress.metrics).map(([key, val]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-1.5 py-0.5 text-[10px] rounded t-bg-elevated t-text-secondary font-mono", children: [
|
|
31332
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-muted", children: key }),
|
|
31333
|
+
" ",
|
|
31334
|
+
typeof val === "number" ? val < 0.01 ? val.toExponential(2) : val.toFixed(4) : val
|
|
31335
|
+
] }, key)) }),
|
|
31336
|
+
run.failure && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs t-text-secondary leading-relaxed", children: [
|
|
31337
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "font-medium", children: [
|
|
31338
|
+
run.failure.code,
|
|
31339
|
+
": ",
|
|
31340
|
+
run.failure.message
|
|
31341
|
+
] }),
|
|
31342
|
+
run.failure.suggestions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "mt-1 space-y-0.5", children: run.failure.suggestions.map((s15, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "flex items-start gap-1.5 t-text-muted", children: [
|
|
31343
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 mt-1.5 w-1 h-1 rounded-full t-bg-elevated" }),
|
|
31344
|
+
s15
|
|
31345
|
+
] }, i)) })
|
|
31346
|
+
] }),
|
|
31347
|
+
run.parentRunId && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 text-[10px] t-text-muted", children: [
|
|
31348
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 10 }),
|
|
31349
|
+
"Retry of ",
|
|
31350
|
+
run.parentRunId
|
|
31351
|
+
] }),
|
|
31352
|
+
run.outputTail && /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "p-2 rounded t-bg-elevated text-[10px] t-text-secondary font-mono overflow-x-auto max-h-40 overflow-y-auto whitespace-pre-wrap leading-relaxed", children: run.outputTail.slice(-2048) }),
|
|
31353
|
+
run.failure?.retryable && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31354
|
+
"button",
|
|
31355
|
+
{
|
|
31356
|
+
onClick: (e) => {
|
|
31357
|
+
e.stopPropagation();
|
|
31358
|
+
sendToChat(`Compute run ${run.runId} failed with ${run.failure.code}. Please review the error and fix the code, then retry.`);
|
|
31359
|
+
},
|
|
31360
|
+
className: "text-[10px] t-text-accent hover:underline",
|
|
31361
|
+
children: "Fix & retry in chat"
|
|
31362
|
+
}
|
|
31363
|
+
)
|
|
31364
|
+
] })
|
|
31365
|
+
] });
|
|
31366
|
+
}
|
|
31367
|
+
function FilterBar({
|
|
31368
|
+
search: search2,
|
|
31369
|
+
onSearchChange
|
|
31370
|
+
}) {
|
|
31371
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-2 border-b t-border", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
|
|
31372
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Search, { size: 13, className: "absolute left-2.5 top-1/2 -translate-y-1/2 t-text-muted" }),
|
|
31373
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31374
|
+
"input",
|
|
31375
|
+
{
|
|
31376
|
+
type: "text",
|
|
31377
|
+
value: search2,
|
|
31378
|
+
onChange: (e) => onSearchChange(e.target.value),
|
|
31379
|
+
placeholder: "Search runs by command or ID...",
|
|
31380
|
+
className: "w-full pl-8 pr-3 py-1.5 text-xs rounded-lg border t-border t-bg-surface t-text focus:outline-none focus:border-[var(--color-accent-soft)]"
|
|
31381
|
+
}
|
|
31382
|
+
),
|
|
31383
|
+
search2 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31384
|
+
"button",
|
|
31385
|
+
{
|
|
31386
|
+
onClick: () => onSearchChange(""),
|
|
31387
|
+
className: "absolute right-2 top-1/2 -translate-y-1/2 t-text-muted hover:t-text",
|
|
31388
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$1, { size: 12 })
|
|
31389
|
+
}
|
|
31390
|
+
)
|
|
31391
|
+
] }) });
|
|
31392
|
+
}
|
|
31393
|
+
function CoverageBar({ runs }) {
|
|
31394
|
+
const completed = runs.filter((r) => r.status === "completed").length;
|
|
31395
|
+
const failed = runs.filter((r) => ["failed", "timed_out"].includes(r.status)).length;
|
|
31396
|
+
const total = runs.length;
|
|
31397
|
+
const successRate = total > 0 ? completed / total : 0;
|
|
31398
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4 px-4 py-2 border-t t-border t-bg-surface text-[11px] t-text-muted", children: [
|
|
31399
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
31400
|
+
total,
|
|
31401
|
+
" runs"
|
|
31402
|
+
] }),
|
|
31403
|
+
completed > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
31404
|
+
completed,
|
|
31405
|
+
" completed"
|
|
31406
|
+
] }),
|
|
31407
|
+
failed > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
31408
|
+
failed,
|
|
31409
|
+
" failed"
|
|
31410
|
+
] }),
|
|
31411
|
+
total > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
31412
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 max-w-48", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-1.5 rounded-full t-bg-elevated overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31413
|
+
"div",
|
|
31414
|
+
{
|
|
31415
|
+
className: "h-full rounded-full t-gradient-accent-h",
|
|
31416
|
+
style: { width: `${successRate * 100}%` }
|
|
31417
|
+
}
|
|
31418
|
+
) }) }),
|
|
31419
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
31420
|
+
Math.round(successRate * 100),
|
|
31421
|
+
"% success"
|
|
31422
|
+
] })
|
|
31423
|
+
] })
|
|
31424
|
+
] });
|
|
31425
|
+
}
|
|
31426
|
+
function EmptyState() {
|
|
31427
|
+
const environment = useComputeStore((s15) => s15.environment);
|
|
31428
|
+
const setCenterView = useUIStore((s15) => s15.setCenterView);
|
|
31429
|
+
const goToChat = (text2) => {
|
|
31430
|
+
setCenterView("chat");
|
|
31431
|
+
setTimeout(() => {
|
|
31432
|
+
const inputEl = document.querySelector("[data-chat-input]");
|
|
31433
|
+
if (inputEl) {
|
|
31434
|
+
inputEl.value = text2;
|
|
31435
|
+
inputEl.focus();
|
|
31436
|
+
inputEl.dispatchEvent(new Event("input", { bubbles: true }));
|
|
31437
|
+
}
|
|
31438
|
+
}, 100);
|
|
31439
|
+
};
|
|
31440
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center h-full text-center px-8", children: [
|
|
31441
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Cpu, { size: 32, className: "t-text-muted mb-3 opacity-30" }),
|
|
31442
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm t-text font-medium mb-1", children: "Your compute environment is ready" }),
|
|
31443
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs t-text-muted max-w-sm leading-relaxed mb-4", children: "Ask the agent to run scripts, train models, or process data. Code executes in a sandboxed environment with progress tracking and failure analysis." }),
|
|
31444
|
+
environment && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-2.5 rounded-lg t-bg-elevated text-[11px] t-text-secondary mb-5", children: [
|
|
31445
|
+
environment.gpu || `${environment.os} ${environment.arch}`,
|
|
31446
|
+
" · ",
|
|
31447
|
+
Math.round(environment.totalMemoryMb / 1024),
|
|
31448
|
+
" GB",
|
|
31449
|
+
environment.mlxAvailable && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
31450
|
+
" · ",
|
|
31451
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-accent", children: "MLX" })
|
|
31452
|
+
] }),
|
|
31453
|
+
environment.sandbox === "docker" && /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: " · Docker" })
|
|
31454
|
+
] }),
|
|
31455
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1.5 w-full max-w-sm", children: [
|
|
31456
|
+
"Train a model on my dataset",
|
|
31457
|
+
"Run my analysis script",
|
|
31458
|
+
"Process and clean this data"
|
|
31459
|
+
].map((prompt) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
31460
|
+
"button",
|
|
31461
|
+
{
|
|
31462
|
+
onClick: () => goToChat(prompt),
|
|
31463
|
+
className: "w-full flex items-center justify-between px-3 py-2 rounded-lg border t-border-subtle hover:bg-[var(--color-accent-soft)]/5 transition-colors text-left",
|
|
31464
|
+
children: [
|
|
31465
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs t-text-secondary", children: [
|
|
31466
|
+
'"',
|
|
31467
|
+
prompt,
|
|
31468
|
+
'"'
|
|
31469
|
+
] }),
|
|
31470
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 12, className: "t-text-muted" })
|
|
31471
|
+
]
|
|
31472
|
+
},
|
|
31473
|
+
prompt
|
|
31474
|
+
)) })
|
|
31475
|
+
] });
|
|
31476
|
+
}
|
|
31477
|
+
function ComputeView() {
|
|
31478
|
+
const activeRuns = useActiveRuns();
|
|
31479
|
+
const recentRuns = useRecentRuns();
|
|
31480
|
+
const [expandedId, setExpandedId] = reactExports.useState(null);
|
|
31481
|
+
const [search2, setSearch] = reactExports.useState("");
|
|
31482
|
+
const allRuns = reactExports.useMemo(() => [...activeRuns, ...recentRuns], [activeRuns, recentRuns]);
|
|
31483
|
+
const filtered = reactExports.useMemo(() => {
|
|
31484
|
+
if (!search2.trim()) return allRuns;
|
|
31485
|
+
const q2 = search2.toLowerCase();
|
|
31486
|
+
return allRuns.filter(
|
|
31487
|
+
(r) => r.command.toLowerCase().includes(q2) || r.runId.toLowerCase().includes(q2)
|
|
31488
|
+
);
|
|
31489
|
+
}, [allRuns, search2]);
|
|
31490
|
+
const isEmpty = allRuns.length === 0;
|
|
31491
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col min-h-0", children: [
|
|
31492
|
+
!isEmpty && /* @__PURE__ */ jsxRuntimeExports.jsx(FilterBar, { search: search2, onSearchChange: setSearch }),
|
|
31493
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: isEmpty ? /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, {}) : filtered.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center h-full text-center px-8", children: [
|
|
31494
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Cpu, { size: 32, className: "t-text-muted mb-3 opacity-40" }),
|
|
31495
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm t-text-muted", children: "No runs match your search." })
|
|
31496
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
31497
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 px-3 py-1.5 border-b t-border t-bg-surface", children: [
|
|
31498
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-5" }),
|
|
31499
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-1.5" }),
|
|
31500
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 text-[10px] uppercase tracking-wider font-medium t-text-muted", children: "Command" }),
|
|
31501
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-14 text-right text-[10px] uppercase tracking-wider font-medium t-text-muted", children: "Duration" }),
|
|
31502
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-14 text-right text-[10px] uppercase tracking-wider font-medium t-text-muted", children: "Phase" })
|
|
31503
|
+
] }),
|
|
31504
|
+
filtered.map((run) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31505
|
+
RunRow,
|
|
31506
|
+
{
|
|
31507
|
+
run,
|
|
31508
|
+
expanded: expandedId === run.runId,
|
|
31509
|
+
onToggle: () => setExpandedId(expandedId === run.runId ? null : run.runId)
|
|
31510
|
+
},
|
|
31511
|
+
run.runId
|
|
31512
|
+
))
|
|
31513
|
+
] }) }),
|
|
31514
|
+
!isEmpty && /* @__PURE__ */ jsxRuntimeExports.jsx(CoverageBar, { runs: allRuns })
|
|
31515
|
+
] });
|
|
31516
|
+
}
|
|
31517
|
+
const api$2 = window.api;
|
|
31518
|
+
const computeEnabled = api$2?.isComputeEnabled?.() ?? false;
|
|
29949
31519
|
const viewTabs = [
|
|
29950
31520
|
{ key: "chat", label: "Chat", icon: MessageSquare, shortcut: "⌘1" },
|
|
29951
|
-
{ key: "literature", label: "Literature", icon: BookOpen, shortcut: "⌘2" }
|
|
31521
|
+
{ key: "literature", label: "Literature", icon: BookOpen, shortcut: "⌘2" },
|
|
31522
|
+
...computeEnabled ? [{ key: "compute", label: "Compute", icon: Cpu, shortcut: "⌘3" }] : []
|
|
29952
31523
|
];
|
|
29953
31524
|
function ViewSwitcher() {
|
|
29954
31525
|
const centerView = useUIStore((s15) => s15.centerView);
|
|
29955
31526
|
const setCenterView = useUIStore((s15) => s15.setCenterView);
|
|
29956
31527
|
const paperCount = useEntityStore((s15) => s15.papers.length);
|
|
29957
|
-
|
|
31528
|
+
const activeComputeRuns = useActiveRunCount();
|
|
31529
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("nav", { "aria-label": "View switcher", className: "flex items-center gap-0.5 px-4 pt-10 pb-1", children: viewTabs.map(({ key, label, icon: Icon2, shortcut }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
29958
31530
|
"button",
|
|
29959
31531
|
{
|
|
29960
31532
|
onClick: () => setCenterView(key),
|
|
@@ -29963,7 +31535,9 @@ function ViewSwitcher() {
|
|
|
29963
31535
|
children: [
|
|
29964
31536
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Icon2, { size: 13 }),
|
|
29965
31537
|
label,
|
|
29966
|
-
key === "literature" && paperCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-0.5 px-1 py-px text-[9px] rounded-full t-bg-elevated t-text-muted tabular-nums", children: paperCount })
|
|
31538
|
+
key === "literature" && paperCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-0.5 px-1 py-px text-[9px] rounded-full t-bg-elevated t-text-muted tabular-nums", children: paperCount }),
|
|
31539
|
+
key === "compute" && activeComputeRuns > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-0.5 px-1 py-px text-[9px] rounded-full bg-[var(--color-accent-soft)]/10 t-text-accent tabular-nums", children: activeComputeRuns }),
|
|
31540
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] t-text-muted opacity-40 ml-0.5", children: shortcut })
|
|
29967
31541
|
]
|
|
29968
31542
|
},
|
|
29969
31543
|
key
|
|
@@ -29975,12 +31549,18 @@ function CenterPanel() {
|
|
|
29975
31549
|
const messages = useChatStore((s15) => s15.messages);
|
|
29976
31550
|
const showHero = isIdle && messages.length === 0;
|
|
29977
31551
|
if (centerView === "literature") {
|
|
29978
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "flex-1 flex flex-col min-w-0", children: [
|
|
31552
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { id: "main-content", className: "flex-1 flex flex-col min-w-0", children: [
|
|
29979
31553
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ViewSwitcher, {}),
|
|
29980
31554
|
/* @__PURE__ */ jsxRuntimeExports.jsx(LiteratureView, {})
|
|
29981
31555
|
] });
|
|
29982
31556
|
}
|
|
29983
|
-
|
|
31557
|
+
if (centerView === "compute") {
|
|
31558
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { id: "main-content", className: "flex-1 flex flex-col min-w-0", children: [
|
|
31559
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ViewSwitcher, {}),
|
|
31560
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ComputeView, {})
|
|
31561
|
+
] });
|
|
31562
|
+
}
|
|
31563
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { id: "main-content", className: "flex-1 flex flex-col min-w-0", children: [
|
|
29984
31564
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ViewSwitcher, {}),
|
|
29985
31565
|
showHero ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(HeroIdle, {}) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0 px-6 pt-4 pb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto h-full", style: { maxWidth: "48rem" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChatMessages, {}) }) }),
|
|
29986
31566
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-6 pb-5", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto", style: { maxWidth: "48rem" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChatInput, {}) }) })
|
|
@@ -29988,7 +31568,7 @@ function CenterPanel() {
|
|
|
29988
31568
|
}
|
|
29989
31569
|
const remarkPlugins = [remarkGfm];
|
|
29990
31570
|
const LazyMilkdownMarkdownEditor = reactExports.lazy(async () => {
|
|
29991
|
-
const mod = await __vitePreload(() => import("./MilkdownMarkdownEditor-
|
|
31571
|
+
const mod = await __vitePreload(() => import("./MilkdownMarkdownEditor-jaF-aGPn.js").then((n) => n.bL), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url);
|
|
29992
31572
|
return { default: mod.MilkdownMarkdownEditor };
|
|
29993
31573
|
});
|
|
29994
31574
|
const typeIcons = {
|
|
@@ -30585,6 +32165,9 @@ function StatusBar() {
|
|
|
30585
32165
|
const events = useActivityStore((s15) => s15.events);
|
|
30586
32166
|
const activeSkills = useActivityStore((s15) => s15.activeSkills);
|
|
30587
32167
|
const runTokens = useUsageStore((s15) => s15.runTokens);
|
|
32168
|
+
const runPromptTokens = useUsageStore((s15) => s15.runPromptTokens);
|
|
32169
|
+
const runCompletionTokens = useUsageStore((s15) => s15.runCompletionTokens);
|
|
32170
|
+
const runCachedTokens = useUsageStore((s15) => s15.runCachedTokens);
|
|
30588
32171
|
const runCost = useUsageStore((s15) => s15.runCost);
|
|
30589
32172
|
const runCacheHitRate = useUsageStore((s15) => s15.runCacheHitRate);
|
|
30590
32173
|
const allTimeTokens = useUsageStore((s15) => s15.allTimeTokens);
|
|
@@ -30610,7 +32193,7 @@ function StatusBar() {
|
|
|
30610
32193
|
const hasSkills = activeSkills.length > 0;
|
|
30611
32194
|
const hasRunUsage = runTokens > 0;
|
|
30612
32195
|
const hasProjectUsage = allTimeTokens > 0;
|
|
30613
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-7 flex items-center px-4 gap-5 border-t t-border t-bg-surface text-[11px] t-text-
|
|
32196
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-7 flex items-center px-4 gap-5 border-t t-border t-bg-surface text-[11px] t-text-secondary select-none shrink-0", children: [
|
|
30614
32197
|
hasSkills && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2 overflow-hidden", children: activeSkills.map((name2) => /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 px-1.5 py-0.5 rounded t-bg-accent/10 t-text-accent whitespace-nowrap", children: [
|
|
30615
32198
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px]", children: "⚡" }),
|
|
30616
32199
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: name2 })
|
|
@@ -30626,12 +32209,12 @@ function StatusBar() {
|
|
|
30626
32209
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1" }),
|
|
30627
32210
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 whitespace-nowrap", children: [
|
|
30628
32211
|
hasRunUsage && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
30629
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
32212
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { title: `In: ${formatTokens(runPromptTokens)} · Cache: ${formatTokens(runCachedTokens)} · Out: ${formatTokens(runCompletionTokens)}`, children: [
|
|
30630
32213
|
formatTokens(runTokens),
|
|
30631
32214
|
" tokens"
|
|
30632
32215
|
] }),
|
|
30633
32216
|
runCost > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "t-text-success", children: formatCost(runCost) }),
|
|
30634
|
-
|
|
32217
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: runCacheHitRate > 0.5 ? "t-text-accent" : "t-text-accent-soft", children: [
|
|
30635
32218
|
Math.round(runCacheHitRate * 100),
|
|
30636
32219
|
"% cache"
|
|
30637
32220
|
] })
|
|
@@ -39234,22 +40817,17 @@ function TerminalPanel() {
|
|
|
39234
40817
|
};
|
|
39235
40818
|
reactExports.useEffect(() => {
|
|
39236
40819
|
if (!termRef.current) return;
|
|
39237
|
-
const
|
|
40820
|
+
const cs2 = getComputedStyle(document.documentElement);
|
|
39238
40821
|
const term = new Dl({
|
|
39239
40822
|
fontSize: 13,
|
|
39240
40823
|
fontFamily: 'Menlo, Monaco, "Courier New", monospace',
|
|
39241
40824
|
cursorBlink: true,
|
|
39242
40825
|
allowProposedApi: true,
|
|
39243
|
-
theme:
|
|
39244
|
-
background: "
|
|
39245
|
-
foreground: "
|
|
39246
|
-
cursor: "
|
|
39247
|
-
selectionBackground: "
|
|
39248
|
-
} : {
|
|
39249
|
-
background: "#fafafa",
|
|
39250
|
-
foreground: "#1a1a1a",
|
|
39251
|
-
cursor: "#1a1a1a",
|
|
39252
|
-
selectionBackground: "#c0d0e0"
|
|
40826
|
+
theme: {
|
|
40827
|
+
background: cs2.getPropertyValue("--color-bg-base").trim(),
|
|
40828
|
+
foreground: cs2.getPropertyValue("--color-text").trim(),
|
|
40829
|
+
cursor: cs2.getPropertyValue("--color-text").trim(),
|
|
40830
|
+
selectionBackground: cs2.getPropertyValue("--color-bg-elevated").trim()
|
|
39253
40831
|
}
|
|
39254
40832
|
});
|
|
39255
40833
|
const fit = new o();
|
|
@@ -39306,17 +40884,12 @@ function TerminalPanel() {
|
|
|
39306
40884
|
reactExports.useEffect(() => {
|
|
39307
40885
|
const term = xtermRef.current;
|
|
39308
40886
|
if (!term) return;
|
|
39309
|
-
const
|
|
39310
|
-
term.options.theme =
|
|
39311
|
-
background: "
|
|
39312
|
-
foreground: "
|
|
39313
|
-
cursor: "
|
|
39314
|
-
selectionBackground: "
|
|
39315
|
-
} : {
|
|
39316
|
-
background: "#fafafa",
|
|
39317
|
-
foreground: "#1a1a1a",
|
|
39318
|
-
cursor: "#1a1a1a",
|
|
39319
|
-
selectionBackground: "#c0d0e0"
|
|
40887
|
+
const cs2 = getComputedStyle(document.documentElement);
|
|
40888
|
+
term.options.theme = {
|
|
40889
|
+
background: cs2.getPropertyValue("--color-bg-base").trim(),
|
|
40890
|
+
foreground: cs2.getPropertyValue("--color-text").trim(),
|
|
40891
|
+
cursor: cs2.getPropertyValue("--color-text").trim(),
|
|
40892
|
+
selectionBackground: cs2.getPropertyValue("--color-bg-elevated").trim()
|
|
39320
40893
|
};
|
|
39321
40894
|
}, [theme]);
|
|
39322
40895
|
reactExports.useEffect(() => {
|
|
@@ -39343,8 +40916,9 @@ function TerminalPanel() {
|
|
|
39343
40916
|
"button",
|
|
39344
40917
|
{
|
|
39345
40918
|
onClick: handleRestart,
|
|
39346
|
-
className: "p-
|
|
40919
|
+
className: "p-1 rounded t-text-muted hover:t-text-secondary t-bg-hover",
|
|
39347
40920
|
title: "Restart terminal",
|
|
40921
|
+
"aria-label": "Restart terminal",
|
|
39348
40922
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 12 })
|
|
39349
40923
|
}
|
|
39350
40924
|
),
|
|
@@ -39352,8 +40926,9 @@ function TerminalPanel() {
|
|
|
39352
40926
|
"button",
|
|
39353
40927
|
{
|
|
39354
40928
|
onClick: handleClose,
|
|
39355
|
-
className: "p-
|
|
40929
|
+
className: "p-1 rounded t-text-muted hover:t-text-secondary t-bg-hover",
|
|
39356
40930
|
title: "Close terminal",
|
|
40931
|
+
"aria-label": "Close terminal",
|
|
39357
40932
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$1, { size: 12 })
|
|
39358
40933
|
}
|
|
39359
40934
|
)
|
|
@@ -39390,6 +40965,53 @@ class ErrorBoundary extends reactExports.Component {
|
|
|
39390
40965
|
] }) });
|
|
39391
40966
|
}
|
|
39392
40967
|
}
|
|
40968
|
+
function lastNLines(text2, n) {
|
|
40969
|
+
const lines = text2.split("\n").filter(Boolean);
|
|
40970
|
+
return lines.slice(-n).join("\n");
|
|
40971
|
+
}
|
|
40972
|
+
function extractPartialOutput(tool, data) {
|
|
40973
|
+
if (!data?.partialResult) return void 0;
|
|
40974
|
+
const pr = data.partialResult;
|
|
40975
|
+
const text2 = pr?.content?.[0]?.text;
|
|
40976
|
+
if (typeof text2 === "string" && text2.length > 0) {
|
|
40977
|
+
const maxLines = tool === "bash" ? 5 : 3;
|
|
40978
|
+
return lastNLines(text2, maxLines);
|
|
40979
|
+
}
|
|
40980
|
+
return void 0;
|
|
40981
|
+
}
|
|
40982
|
+
const useToolProgressStore = create$1((set) => ({
|
|
40983
|
+
inFlight: /* @__PURE__ */ new Map(),
|
|
40984
|
+
reportProgress: (event) => {
|
|
40985
|
+
set((state) => {
|
|
40986
|
+
const next = new Map(state.inFlight);
|
|
40987
|
+
const phase = event.phase;
|
|
40988
|
+
if (phase === "start") {
|
|
40989
|
+
next.set(event.toolCallId, {
|
|
40990
|
+
tool: event.tool,
|
|
40991
|
+
toolCallId: event.toolCallId,
|
|
40992
|
+
phase,
|
|
40993
|
+
startedAt: event.timestamp,
|
|
40994
|
+
updatedAt: event.timestamp
|
|
40995
|
+
});
|
|
40996
|
+
} else if (phase === "update") {
|
|
40997
|
+
const existing = next.get(event.toolCallId);
|
|
40998
|
+
const partialOutput = extractPartialOutput(event.tool, event.data);
|
|
40999
|
+
next.set(event.toolCallId, {
|
|
41000
|
+
tool: event.tool,
|
|
41001
|
+
toolCallId: event.toolCallId,
|
|
41002
|
+
phase,
|
|
41003
|
+
partialOutput: partialOutput ?? existing?.partialOutput,
|
|
41004
|
+
startedAt: existing?.startedAt ?? event.timestamp,
|
|
41005
|
+
updatedAt: event.timestamp
|
|
41006
|
+
});
|
|
41007
|
+
} else if (phase === "end") {
|
|
41008
|
+
next.delete(event.toolCallId);
|
|
41009
|
+
}
|
|
41010
|
+
return { inFlight: next };
|
|
41011
|
+
});
|
|
41012
|
+
},
|
|
41013
|
+
clearAll: () => set({ inFlight: /* @__PURE__ */ new Map() })
|
|
41014
|
+
}));
|
|
39393
41015
|
const api = window.api;
|
|
39394
41016
|
function FolderGate({ onOpenSettings }) {
|
|
39395
41017
|
const pickFolder = useSessionStore((s15) => s15.pickFolder);
|
|
@@ -39407,19 +41029,14 @@ function FolderGate({ onOpenSettings }) {
|
|
|
39407
41029
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
39408
41030
|
"div",
|
|
39409
41031
|
{
|
|
39410
|
-
className: "w-14 h-14 rounded-2xl flex items-center justify-center",
|
|
39411
|
-
style: {
|
|
39412
|
-
background: "linear-gradient(135deg, var(--color-accent) 0%, var(--color-accent-2) 100%)",
|
|
39413
|
-
boxShadow: "0 8px 32px var(--color-accent-2-muted)"
|
|
39414
|
-
},
|
|
41032
|
+
className: "w-14 h-14 rounded-2xl flex items-center justify-center t-gradient-accent t-gradient-accent-shadow-lg",
|
|
39415
41033
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-white text-xl font-bold tracking-tight", children: "P" })
|
|
39416
41034
|
}
|
|
39417
41035
|
),
|
|
39418
41036
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
39419
41037
|
"div",
|
|
39420
41038
|
{
|
|
39421
|
-
className: "absolute -inset-2 rounded-3xl opacity-15 blur-xl -z-10"
|
|
39422
|
-
style: { background: "linear-gradient(135deg, var(--color-accent), var(--color-accent-2))" }
|
|
41039
|
+
className: "absolute -inset-2 rounded-3xl opacity-15 blur-xl -z-10 t-gradient-accent"
|
|
39423
41040
|
}
|
|
39424
41041
|
)
|
|
39425
41042
|
] }),
|
|
@@ -39440,11 +41057,7 @@ function FolderGate({ onOpenSettings }) {
|
|
|
39440
41057
|
"button",
|
|
39441
41058
|
{
|
|
39442
41059
|
onClick: handlePick,
|
|
39443
|
-
className: "inline-flex items-center gap-2 px-5 py-2.5 rounded-lg text-white text-sm font-medium\n hover:opacity-90 transition-all duration-200",
|
|
39444
|
-
style: {
|
|
39445
|
-
background: "linear-gradient(135deg, var(--color-accent) 0%, var(--color-accent-2) 100%)",
|
|
39446
|
-
boxShadow: "0 4px 16px var(--color-accent-2-muted)"
|
|
39447
|
-
},
|
|
41060
|
+
className: "inline-flex items-center gap-2 px-5 py-2.5 rounded-lg text-white text-sm font-medium\n hover:opacity-90 transition-all duration-200 t-gradient-accent t-gradient-accent-shadow",
|
|
39448
41061
|
children: [
|
|
39449
41062
|
/* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { size: 16 }),
|
|
39450
41063
|
"Open Project Folder"
|
|
@@ -39521,6 +41134,16 @@ function App() {
|
|
|
39521
41134
|
});
|
|
39522
41135
|
}
|
|
39523
41136
|
}
|
|
41137
|
+
if (snapshot && snapshot.toolEvents?.length > 0) {
|
|
41138
|
+
const toolStore = useToolEventsStore.getState();
|
|
41139
|
+
for (const evt of snapshot.toolEvents) {
|
|
41140
|
+
if (evt.type === "tool-call") {
|
|
41141
|
+
toolStore.onToolCall(evt);
|
|
41142
|
+
} else if (evt.type === "tool-result") {
|
|
41143
|
+
toolStore.onToolResult(evt);
|
|
41144
|
+
}
|
|
41145
|
+
}
|
|
41146
|
+
}
|
|
39524
41147
|
});
|
|
39525
41148
|
api.getCurrentSession().then((session) => {
|
|
39526
41149
|
useChatStore.getState().loadInitial(session.sessionId);
|
|
@@ -39536,14 +41159,26 @@ function App() {
|
|
|
39536
41159
|
});
|
|
39537
41160
|
const unsubActivityClear = api.onActivityClear(() => {
|
|
39538
41161
|
useActivityStore.getState().clear();
|
|
41162
|
+
useToolProgressStore.getState().clearAll();
|
|
41163
|
+
useToolEventsStore.getState().clearRun();
|
|
39539
41164
|
useUsageStore.getState().resetRun();
|
|
39540
41165
|
});
|
|
39541
41166
|
const unsubActivity = api.onActivity((event) => {
|
|
39542
|
-
|
|
41167
|
+
const enrichedEvent = {
|
|
39543
41168
|
id: `${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
39544
41169
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39545
41170
|
...event
|
|
39546
|
-
}
|
|
41171
|
+
};
|
|
41172
|
+
useActivityStore.getState().push(enrichedEvent);
|
|
41173
|
+
if (event.type === "tool-call") {
|
|
41174
|
+
useToolEventsStore.getState().onToolCall(enrichedEvent);
|
|
41175
|
+
} else if (event.type === "tool-result") {
|
|
41176
|
+
useToolEventsStore.getState().onToolResult(enrichedEvent);
|
|
41177
|
+
}
|
|
41178
|
+
});
|
|
41179
|
+
const unsubToolProgress = api.onToolProgress((event) => {
|
|
41180
|
+
useToolProgressStore.getState().reportProgress(event);
|
|
41181
|
+
useToolEventsStore.getState().onToolProgress(event);
|
|
39547
41182
|
});
|
|
39548
41183
|
const unsubSkillLoaded = api.onSkillLoaded((skillName) => {
|
|
39549
41184
|
useActivityStore.getState().addSkill(skillName);
|
|
@@ -39581,6 +41216,19 @@ function App() {
|
|
|
39581
41216
|
const unsub6 = api.onEntityCreated(() => {
|
|
39582
41217
|
refreshEntities();
|
|
39583
41218
|
});
|
|
41219
|
+
if (api?.isComputeEnabled?.()) {
|
|
41220
|
+
api.probeComputeEnvironment?.().catch(() => {
|
|
41221
|
+
});
|
|
41222
|
+
}
|
|
41223
|
+
const unsubComputeUpdate = api.onComputeRunUpdate((event) => {
|
|
41224
|
+
useComputeStore.getState().updateRun(event.runId, event);
|
|
41225
|
+
});
|
|
41226
|
+
const unsubComputeComplete = api.onComputeRunComplete((event) => {
|
|
41227
|
+
useComputeStore.getState().updateRun(event.runId, event);
|
|
41228
|
+
});
|
|
41229
|
+
const unsubComputeEnv = api.onComputeEnvironment((event) => {
|
|
41230
|
+
useComputeStore.getState().setEnvironment(event);
|
|
41231
|
+
});
|
|
39584
41232
|
return () => {
|
|
39585
41233
|
unsub1();
|
|
39586
41234
|
unsub2();
|
|
@@ -39590,8 +41238,12 @@ function App() {
|
|
|
39590
41238
|
unsub6();
|
|
39591
41239
|
unsubActivity();
|
|
39592
41240
|
unsubActivityClear();
|
|
41241
|
+
unsubToolProgress();
|
|
39593
41242
|
unsubSkillLoaded();
|
|
39594
41243
|
unsubUsage();
|
|
41244
|
+
unsubComputeUpdate();
|
|
41245
|
+
unsubComputeComplete();
|
|
41246
|
+
unsubComputeEnv();
|
|
39595
41247
|
};
|
|
39596
41248
|
}, [hasProject]);
|
|
39597
41249
|
reactExports.useEffect(() => {
|
|
@@ -39603,12 +41255,6 @@ function App() {
|
|
|
39603
41255
|
reactExports.useEffect(() => {
|
|
39604
41256
|
const handler = (e) => {
|
|
39605
41257
|
if (previewEditorFocused) return;
|
|
39606
|
-
if ((e.metaKey || e.ctrlKey) && e.key === "n") {
|
|
39607
|
-
e.preventDefault();
|
|
39608
|
-
useChatStore.getState().clear();
|
|
39609
|
-
useUIStore.getState().setIdle(true);
|
|
39610
|
-
useUIStore.getState().closePreview();
|
|
39611
|
-
}
|
|
39612
41258
|
if ((e.metaKey || e.ctrlKey) && e.key === "1") {
|
|
39613
41259
|
e.preventDefault();
|
|
39614
41260
|
useUIStore.getState().setCenterView("chat");
|
|
@@ -39617,6 +41263,10 @@ function App() {
|
|
|
39617
41263
|
e.preventDefault();
|
|
39618
41264
|
useUIStore.getState().setCenterView("literature");
|
|
39619
41265
|
}
|
|
41266
|
+
if ((e.metaKey || e.ctrlKey) && e.key === "3" && api?.isComputeEnabled?.()) {
|
|
41267
|
+
e.preventDefault();
|
|
41268
|
+
useUIStore.getState().setCenterView("compute");
|
|
41269
|
+
}
|
|
39620
41270
|
if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === "K") {
|
|
39621
41271
|
e.preventDefault();
|
|
39622
41272
|
if (useChatStore.getState().isStreaming) {
|
|
@@ -39648,6 +41298,7 @@ function App() {
|
|
|
39648
41298
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(FolderGate, { onOpenSettings: () => setShowApiKeySetup(true) });
|
|
39649
41299
|
}
|
|
39650
41300
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBoundary, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-screen w-screen t-bg-base t-text", children: [
|
|
41301
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "#main-content", className: "skip-link", children: "Skip to content" }),
|
|
39651
41302
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "drag-region fixed top-0 left-0 right-0 h-8 z-50" }),
|
|
39652
41303
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 min-h-0", children: [
|
|
39653
41304
|
!leftCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: previewEntity ? "hidden" : "contents", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LeftSidebar, {}) }),
|