@agimon-ai/po-file-edit 0.0.0-alpha.2 → 0.0.0-alpha.21

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.
@@ -1,22 +1,13 @@
1
- import { createApiClient, defineActivityGroup, defineChannelFile, defineFileLinks, defineFill, defineLeaderBinding, defineSessionStore, defineWebPlugin, sessionApiAddress } from "@agimon-ai/po-core/web";
2
- import { Badge, Breadcrumb, Button, CloseIcon, CodeEditor, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DiffView, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Input, KebabIcon, Markdown, MediaPreview, ReviewCommentDraft, buildReviewPrompt, grammarKeyOf, groupByDirectory, groupRowLabel, mediaKindOf, reviewCommentAnchor } from "@agimon-ai/po-web-components";
1
+ import { createApiClient, defineChannelFile, defineFileLinks, defineSessionStore, defineWebPlugin, sessionApiAddress } from "@agimon-ai/po-core/web";
2
+ import { Badge, Breadcrumb, Button, CodeEditor, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DiffView, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, KebabIcon, Markdown, MediaPreview, ReviewCommentDraft, buildReviewPrompt, grammarKeyOf, mediaKindOf, reviewCommentAnchor } from "@agimon-ai/po-web-components";
3
3
  import { useStore } from "@tanstack/react-store";
4
- import { Fragment, useCallback, useEffect, useRef, useState } from "react";
4
+ import { useCallback, useEffect, useRef, useState } from "react";
5
5
  import { sealedTransport } from "@agimon-ai/po-web-security/browser";
6
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region src/types/webFiles.ts
8
8
  /** The frame type the hub publishes and the web plugin claims; declared in the poWeb block too. */
9
9
  const filesChannelType = "file_edits";
10
10
  //#endregion
11
- //#region src/extensions/workspaces/sessions/(frontend)/activity-group/files.web.ts
12
- var files_web_default$2 = defineActivityGroup({
13
- keys: "e f",
14
- statusKey: "doom-file-edit-files",
15
- hideWhenEmpty: true,
16
- marksBackgroundWork: false,
17
- order: 15
18
- });
19
- //#endregion
20
11
  //#region src/extensions/workspaces/sessions/(frontend)/_lib/filesModel.ts
21
12
  function isRecord$1(value) {
22
13
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -288,12 +279,6 @@ const TOOL_LABEL = {
288
279
  bash: "command",
289
280
  user: "you"
290
281
  };
291
- /** Filters visible relative paths without changing the timeline's newest-first order. */
292
- function filterFileItems(items, query) {
293
- const normalized = query.trim().toLocaleLowerCase();
294
- if (normalized.length === 0) return [...items];
295
- return items.filter((item) => item.relPath.toLocaleLowerCase().includes(normalized));
296
- }
297
282
  function previewModeOf(filePath, unavailable) {
298
283
  if (mediaKindOf(filePath) !== "download") return "media";
299
284
  if (unavailable) return "unavailable";
@@ -335,7 +320,7 @@ function DeleteFileDialog({ relPath, open, onConfirm, onCancel }) {
335
320
  children: [/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "delete file" }) }), /* @__PURE__ */ jsxs(DialogBody, { children: [/* @__PURE__ */ jsxs(DialogDescription, { children: [
336
321
  "this removes ",
337
322
  /* @__PURE__ */ jsx("span", {
338
- className: "font-semibold text-doom-hi",
323
+ className: "font-semibold text-po-hi",
339
324
  children: relPath
340
325
  }),
341
326
  " from disk. the session keeps its record of the change, but the file itself is gone."
@@ -528,7 +513,7 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
528
513
  className: "flex min-h-0 flex-1 flex-col",
529
514
  children: [
530
515
  /* @__PURE__ */ jsxs("header", {
531
- className: "flex shrink-0 items-center gap-2 border-b border-doom-border px-4 py-2",
516
+ className: "flex shrink-0 items-center gap-2 border-b border-po-border px-4 py-2",
532
517
  children: [
533
518
  /* @__PURE__ */ jsx(Breadcrumb, {
534
519
  path: relPath,
@@ -542,7 +527,7 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
542
527
  children: "editing"
543
528
  }) : null,
544
529
  detail === void 0 ? null : /* @__PURE__ */ jsxs("span", {
545
- className: "shrink-0 text-sm text-doom-dim",
530
+ className: "shrink-0 text-sm text-po-dim",
546
531
  children: [
547
532
  "+",
548
533
  detail.cumulative.additions,
@@ -568,7 +553,7 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
568
553
  size: "icon",
569
554
  "data-testid": "files-menu",
570
555
  title: "file actions",
571
- className: "shrink-0 text-doom-faint hover:text-doom-hi",
556
+ className: "shrink-0 text-po-faint hover:text-po-hi",
572
557
  children: /* @__PURE__ */ jsx(KebabIcon, { className: "h-3 w-3" })
573
558
  })
574
559
  }), /* @__PURE__ */ jsxs(DropdownMenuContent, {
@@ -604,12 +589,12 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
604
589
  }),
605
590
  loading && detail === void 0 ? /* @__PURE__ */ jsx("p", {
606
591
  "data-testid": "files-loading",
607
- className: "px-4 py-3 text-sm text-doom-dim",
592
+ className: "px-4 py-3 text-sm text-po-dim",
608
593
  children: "reading this file's history…"
609
594
  }) : null,
610
595
  error === void 0 ? null : /* @__PURE__ */ jsx("p", {
611
596
  "data-testid": "files-error",
612
- className: "px-4 py-3 text-sm text-doom-red",
597
+ className: "px-4 py-3 text-sm text-po-red",
613
598
  children: error
614
599
  }),
615
600
  /* @__PURE__ */ jsx("div", {
@@ -619,7 +604,7 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
619
604
  children: [
620
605
  detail.cumulative.note === void 0 ? null : /* @__PURE__ */ jsx("p", {
621
606
  "data-testid": "files-cumulative-note",
622
- className: "px-4 py-2 text-sm text-doom-yellow",
607
+ className: "px-4 py-2 text-sm text-po-yellow",
623
608
  children: detail.cumulative.note
624
609
  }),
625
610
  detail.cumulative.hunks === void 0 ? null : /* @__PURE__ */ jsx(DiffView, {
@@ -628,9 +613,9 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
628
613
  onSelect: (selection) => openDraft(selection)
629
614
  }),
630
615
  /* @__PURE__ */ jsxs("section", {
631
- className: "mt-2 border-t border-doom-border",
616
+ className: "mt-2 border-t border-po-border",
632
617
  children: [/* @__PURE__ */ jsxs("h2", {
633
- className: "px-4 py-2 text-lg font-semibold text-doom-hi ",
618
+ className: "px-4 py-2 text-lg font-semibold text-po-hi ",
634
619
  children: [
635
620
  detail.versions.length,
636
621
  " ",
@@ -644,16 +629,16 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
644
629
  size: "card",
645
630
  "data-testid": `files-version-toggle-${version.index}`,
646
631
  onClick: () => setExpanded(expanded === version.index ? void 0 : version.index),
647
- className: "w-full gap-2 rounded-none px-4 py-1.5 hover:bg-doom-panel",
632
+ className: "w-full gap-2 rounded-none px-4 py-1.5 hover:bg-po-panel",
648
633
  children: /* @__PURE__ */ jsxs("span", {
649
634
  className: "flex w-full min-w-0 items-center gap-2",
650
635
  children: [
651
636
  /* @__PURE__ */ jsxs("span", {
652
- className: "shrink-0 text-sm text-doom-dim",
637
+ className: "shrink-0 text-sm text-po-dim",
653
638
  children: ["#", version.index]
654
639
  }),
655
640
  /* @__PURE__ */ jsx("span", {
656
- className: "min-w-0 flex-1 truncate text-left text-base text-doom-text",
641
+ className: "min-w-0 flex-1 truncate text-left text-base text-po-text",
657
642
  children: versionSummary(version)
658
643
  }),
659
644
  version.origin === "scan" ? /* @__PURE__ */ jsx(Badge, {
@@ -662,13 +647,13 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
662
647
  children: "no baseline"
663
648
  }) : null,
664
649
  /* @__PURE__ */ jsx("span", {
665
- className: "shrink-0 text-sm text-doom-dim",
650
+ className: "shrink-0 text-sm text-po-dim",
666
651
  children: expanded === version.index ? "▾" : "▸"
667
652
  })
668
653
  ]
669
654
  })
670
655
  }), expanded !== version.index ? null : version.hunks === void 0 ? /* @__PURE__ */ jsx("p", {
671
- className: "px-4 py-1.5 text-sm text-doom-dim",
656
+ className: "px-4 py-1.5 text-sm text-po-dim",
672
657
  children: version.note ?? "nothing to show"
673
658
  }) : /* @__PURE__ */ jsx(DiffView, {
674
659
  hunks: version.hunks,
@@ -682,9 +667,9 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
682
667
  className: "flex h-full flex-col gap-2 p-3",
683
668
  children: working?.unavailable === true ? /* @__PURE__ */ jsx("p", {
684
669
  "data-testid": "files-source-unavailable",
685
- className: "text-sm text-doom-dim",
670
+ className: "text-sm text-po-dim",
686
671
  children: working.reason ?? "this file cannot be shown"
687
- }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
672
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
688
673
  className: "min-h-[24rem] flex-1",
689
674
  onMouseUp: openSelectionDraft,
690
675
  onKeyUp: (event) => {
@@ -698,7 +683,7 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
698
683
  onSelect: (range) => {
699
684
  selection.current = range;
700
685
  },
701
- className: "h-full rounded border border-doom-border"
686
+ className: "h-full rounded border border-po-border"
702
687
  })
703
688
  }), /* @__PURE__ */ jsxs("div", {
704
689
  className: "flex shrink-0 items-center gap-2",
@@ -723,7 +708,7 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
723
708
  }),
724
709
  saveNote === void 0 ? null : /* @__PURE__ */ jsx("span", {
725
710
  "data-testid": "files-save-note",
726
- className: saveNote === "saved" ? "text-sm text-doom-green" : "text-sm text-doom-red",
711
+ className: saveNote === "saved" ? "text-sm text-po-green" : "text-sm text-po-red",
727
712
  children: saveNote
728
713
  })
729
714
  ]
@@ -731,7 +716,7 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
731
716
  }) : /* @__PURE__ */ jsxs("div", {
732
717
  "data-testid": "files-preview",
733
718
  "data-mode": previewMode,
734
- className: previewMode === "code" ? "flex h-full flex-col gap-2 p-4 text-base text-doom-text" : "flex flex-col gap-2 p-4 text-base text-doom-text",
719
+ className: previewMode === "code" ? "flex h-full flex-col gap-2 p-4 text-base text-po-text" : "flex flex-col gap-2 p-4 text-base text-po-text",
735
720
  onMouseUp: () => {
736
721
  if (previewMode === "code") {
737
722
  openSelectionDraft();
@@ -742,7 +727,7 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
742
727
  },
743
728
  children: [previewMode === "unavailable" ? /* @__PURE__ */ jsx("p", {
744
729
  "data-testid": "files-preview-unavailable",
745
- className: "text-sm text-doom-dim",
730
+ className: "text-sm text-po-dim",
746
731
  children: working?.reason ?? "this file cannot be shown"
747
732
  }) : null, previewMode === "media" || previewMode === "unavailable" ? /* @__PURE__ */ jsx(SessionMediaPreview, {
748
733
  src: mediaSrc,
@@ -756,7 +741,7 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
756
741
  title: relPath,
757
742
  sandbox: "",
758
743
  srcDoc: content,
759
- className: "h-[36rem] w-full rounded border border-doom-border bg-doom-deep"
744
+ className: "h-[36rem] w-full rounded border border-po-border bg-po-deep"
760
745
  }) : previewMode === "code" ? /* @__PURE__ */ jsx(CodeEditor, {
761
746
  "data-testid": "files-preview-code",
762
747
  value: content,
@@ -765,10 +750,10 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
765
750
  onSelect: (range) => {
766
751
  selection.current = range;
767
752
  },
768
- className: "min-h-[24rem] flex-1 rounded border border-doom-border"
753
+ className: "min-h-[24rem] flex-1 rounded border border-po-border"
769
754
  }) : /* @__PURE__ */ jsx("pre", {
770
755
  "data-testid": "files-preview-text",
771
- className: "whitespace-pre-wrap break-words font-mono text-sm leading-normal text-doom-text",
756
+ className: "whitespace-pre-wrap break-words font-mono text-sm leading-normal text-po-text",
772
757
  children: content
773
758
  })]
774
759
  })
@@ -784,12 +769,12 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
784
769
  }),
785
770
  comments.length === 0 ? null : /* @__PURE__ */ jsxs("footer", {
786
771
  "data-testid": "files-review",
787
- className: "shrink-0 border-t border-doom-border px-3 py-2",
772
+ className: "shrink-0 border-t border-po-border px-3 py-2",
788
773
  children: [
789
774
  /* @__PURE__ */ jsxs("div", {
790
775
  className: "flex items-center gap-2 pb-1",
791
776
  children: [/* @__PURE__ */ jsxs("span", {
792
- className: "flex-1 text-base font-semibold text-doom-hi",
777
+ className: "flex-1 text-base font-semibold text-po-hi",
793
778
  children: [
794
779
  comments.length,
795
780
  " ",
@@ -807,7 +792,7 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
807
792
  reviewError === void 0 ? null : /* @__PURE__ */ jsxs("p", {
808
793
  role: "alert",
809
794
  "data-testid": "files-review-error",
810
- className: "pb-1 text-sm text-doom-red",
795
+ className: "pb-1 text-sm text-po-red",
811
796
  children: ["review not sent: ", reviewError]
812
797
  }),
813
798
  comments.map((comment) => /* @__PURE__ */ jsxs("div", {
@@ -815,11 +800,11 @@ function FilePanel({ filePath, relPath, sessionId, sendSessionFrame, closeTransi
815
800
  className: "flex items-start gap-2 py-0.5",
816
801
  children: [
817
802
  /* @__PURE__ */ jsx("span", {
818
- className: "shrink-0 text-sm text-doom-dim",
803
+ className: "shrink-0 text-sm text-po-dim",
819
804
  children: reviewCommentAnchor(comment)
820
805
  }),
821
806
  /* @__PURE__ */ jsx("span", {
822
- className: "min-w-0 flex-1 truncate text-base text-doom-text",
807
+ className: "min-w-0 flex-1 truncate text-base text-po-text",
823
808
  children: comment.body
824
809
  }),
825
810
  /* @__PURE__ */ jsx(Button, {
@@ -888,7 +873,7 @@ function FilePreviewPanel({ filePath, sessionId, closeTransientTab }) {
888
873
  className: "flex min-h-0 flex-1 flex-col",
889
874
  children: [
890
875
  /* @__PURE__ */ jsxs("header", {
891
- className: "flex shrink-0 items-center gap-2 border-b border-doom-border px-4 py-2",
876
+ className: "flex shrink-0 items-center gap-2 border-b border-po-border px-4 py-2",
892
877
  children: [
893
878
  /* @__PURE__ */ jsx(Breadcrumb, {
894
879
  path: relPath,
@@ -896,7 +881,7 @@ function FilePreviewPanel({ filePath, sessionId, closeTransientTab }) {
896
881
  className: "min-w-0 flex-1"
897
882
  }),
898
883
  /* @__PURE__ */ jsx("span", {
899
- className: "shrink-0 text-sm text-doom-dim",
884
+ className: "shrink-0 text-sm text-po-dim",
900
885
  children: "unchanged"
901
886
  }),
902
887
  /* @__PURE__ */ jsx(Button, {
@@ -911,12 +896,12 @@ function FilePreviewPanel({ filePath, sessionId, closeTransientTab }) {
911
896
  }),
912
897
  error === void 0 ? null : /* @__PURE__ */ jsx("p", {
913
898
  "data-testid": "files-preview-error",
914
- className: "px-4 py-3 text-sm text-doom-red",
899
+ className: "px-4 py-3 text-sm text-po-red",
915
900
  children: error
916
901
  }),
917
902
  preview === void 0 && error === void 0 ? /* @__PURE__ */ jsx("p", {
918
903
  "data-testid": "files-preview-loading",
919
- className: "px-4 py-3 text-sm text-doom-dim",
904
+ className: "px-4 py-3 text-sm text-po-dim",
920
905
  children: "reading this file…"
921
906
  }) : null,
922
907
  preview === void 0 ? null : /* @__PURE__ */ jsx("div", {
@@ -924,10 +909,10 @@ function FilePreviewPanel({ filePath, sessionId, closeTransientTab }) {
924
909
  children: /* @__PURE__ */ jsxs("div", {
925
910
  "data-testid": "files-preview",
926
911
  "data-mode": previewMode,
927
- className: "flex h-full flex-col gap-2 p-4 text-base text-doom-text",
912
+ className: "flex h-full flex-col gap-2 p-4 text-base text-po-text",
928
913
  children: [previewMode === "unavailable" ? /* @__PURE__ */ jsx("p", {
929
914
  "data-testid": "files-preview-unavailable",
930
- className: "text-sm text-doom-dim",
915
+ className: "text-sm text-po-dim",
931
916
  children: working?.reason ?? "this file cannot be shown"
932
917
  }) : null, previewMode === "media" || previewMode === "unavailable" ? /* @__PURE__ */ jsx(SessionMediaPreview, {
933
918
  src: mediaSrc,
@@ -941,16 +926,16 @@ function FilePreviewPanel({ filePath, sessionId, closeTransientTab }) {
941
926
  title: relPath,
942
927
  sandbox: "",
943
928
  srcDoc: content,
944
- className: "h-[36rem] w-full rounded border border-doom-border bg-doom-deep"
929
+ className: "h-[36rem] w-full rounded border border-po-border bg-po-deep"
945
930
  }) : previewMode === "code" ? /* @__PURE__ */ jsx(CodeEditor, {
946
931
  "data-testid": "files-preview-code",
947
932
  value: content,
948
933
  path: relPath,
949
934
  readOnly: true,
950
- className: "min-h-[24rem] flex-1 rounded border border-doom-border"
935
+ className: "min-h-[24rem] flex-1 rounded border border-po-border"
951
936
  }) : /* @__PURE__ */ jsx("pre", {
952
937
  "data-testid": "files-preview-text",
953
- className: "whitespace-pre-wrap break-words font-mono text-sm leading-normal text-doom-text",
938
+ className: "whitespace-pre-wrap break-words font-mono text-sm leading-normal text-po-text",
954
939
  children: content
955
940
  })]
956
941
  })
@@ -1001,7 +986,7 @@ function match(sessionId, path) {
1001
986
  }
1002
987
  //#endregion
1003
988
  //#region src/extensions/workspaces/sessions/(frontend)/file-links/files.web.ts
1004
- var files_web_default$1 = defineFileLinks({
989
+ var files_web_default = defineFileLinks({
1005
990
  subscribe(listener) {
1006
991
  const subscription = files.store.subscribe(listener);
1007
992
  return () => subscription.unsubscribe();
@@ -1015,293 +1000,10 @@ var files_web_default$1 = defineFileLinks({
1015
1000
  const item = match(sessionId, path);
1016
1001
  if (item !== void 0) return fileTab(item.path, item.relPath);
1017
1002
  const candidate = path.trim();
1018
- return candidate === "" ? void 0 : filePreviewTab(candidate);
1003
+ return candidate === "" || candidate.startsWith("artifact:") ? void 0 : filePreviewTab(candidate);
1019
1004
  }
1020
1005
  });
1021
1006
  //#endregion
1022
- //#region src/extensions/workspaces/sessions/(frontend)/fill/_components/FilesBrowser.tsx
1023
- function FileMetadata({ item, label, recent = false }) {
1024
- return /* @__PURE__ */ jsxs("span", {
1025
- className: "flex min-w-0 w-full items-center gap-1.5",
1026
- children: [
1027
- /* @__PURE__ */ jsx("span", {
1028
- className: "min-w-0 flex-1 truncate text-left text-base font-semibold text-doom-hi",
1029
- children: label ?? item.relPath
1030
- }),
1031
- recent ? /* @__PURE__ */ jsx("span", {
1032
- "data-recent": "true",
1033
- title: "most recent change",
1034
- className: "shrink-0 text-2xs text-doom-blue",
1035
- children: "●"
1036
- }) : null,
1037
- item.count > 1 ? /* @__PURE__ */ jsxs("span", {
1038
- className: "shrink-0 text-2xs text-doom-faint",
1039
- children: [item.count, "×"]
1040
- }) : null,
1041
- /* @__PURE__ */ jsx("span", {
1042
- className: `shrink-0 text-sm ${item.diffable ? "text-doom-dim" : "text-doom-yellow"}`,
1043
- children: TOOL_LABEL[item.tool] ?? item.tool
1044
- })
1045
- ]
1046
- });
1047
- }
1048
- function FileActivityRow({ item, onOpen }) {
1049
- return /* @__PURE__ */ jsx(Button, {
1050
- variant: "ghost",
1051
- size: "card",
1052
- "data-testid": `activity-file-${item.relPath}`,
1053
- "data-file-diffable": item.diffable,
1054
- title: item.diffable ? item.path : `${item.path} (changed by a command, so no diff was captured)`,
1055
- onClick: onOpen,
1056
- className: "min-w-0 gap-0.5 rounded-md px-1 py-1 hover:bg-doom-panel",
1057
- children: /* @__PURE__ */ jsx(FileMetadata, { item })
1058
- });
1059
- }
1060
- /**
1061
- * The directory a run of rows shares.
1062
- *
1063
- * Deliberately not an option: the cursor counts files, and a header is a label
1064
- * rather than something to open. Keeping it out of the listbox is what lets
1065
- * arrow keys and Enter stay exactly what they were before the tree existed.
1066
- */
1067
- function FileGroupHeader({ prefix }) {
1068
- return /* @__PURE__ */ jsx("div", {
1069
- "data-testid": `files-browser-group-${prefix}`,
1070
- className: "truncate px-4 pt-2 pb-1 text-sm font-semibold text-doom-dim",
1071
- children: prefix
1072
- });
1073
- }
1074
- function BrowserFileRow({ item, label, indented = false, recent = false, selected, onSelect, onOpen }) {
1075
- return /* @__PURE__ */ jsx("div", {
1076
- role: "option",
1077
- "aria-selected": selected,
1078
- tabIndex: -1,
1079
- "data-testid": `files-browser-file-${item.relPath}`,
1080
- "data-file-diffable": item.diffable,
1081
- "data-selected": selected,
1082
- title: item.diffable ? item.path : `${item.path} (changed by a command, so no diff was captured)`,
1083
- onMouseEnter: onSelect,
1084
- onClick: onOpen,
1085
- className: `flex min-w-0 cursor-pointer border-l-2 py-2 ${indented ? "pr-4 pl-8" : "px-4"} ${selected ? "border-doom-blue bg-doom-panel" : "border-transparent hover:bg-doom-panel/60"}`,
1086
- children: /* @__PURE__ */ jsx(FileMetadata, {
1087
- item,
1088
- label,
1089
- recent
1090
- })
1091
- });
1092
- }
1093
- /** The complete session file picker, ordered exactly as the file timeline supplies it. */
1094
- function FilesBrowser({ items, onClose, onOpen }) {
1095
- const [query, setQuery] = useState("");
1096
- const [selectedIndex, setSelectedIndex] = useState(0);
1097
- const inputRef = useRef(null);
1098
- const listRef = useRef(null);
1099
- const shown = filterFileItems(items, query);
1100
- const grouped = query.trim() === "" ? groupByDirectory(shown, (item) => item.relPath) : void 0;
1101
- const ordered = grouped === void 0 ? shown : grouped.flatMap((group) => group.items);
1102
- const positions = new Map(ordered.map((item, index) => [item.path, index]));
1103
- const selected = ordered[selectedIndex];
1104
- const recentPath = items[0]?.path;
1105
- const [lastShownLength, setLastShownLength] = useState(shown.length);
1106
- if (lastShownLength !== shown.length) {
1107
- setLastShownLength(shown.length);
1108
- setSelectedIndex((current) => Math.min(current, Math.max(0, shown.length - 1)));
1109
- }
1110
- useEffect(() => {
1111
- listRef.current?.querySelector("[aria-selected=\"true\"]")?.scrollIntoView({ block: "nearest" });
1112
- }, [selectedIndex]);
1113
- const move = (delta) => {
1114
- if (ordered.length === 0) return;
1115
- setSelectedIndex((current) => (current + delta + ordered.length) % ordered.length);
1116
- };
1117
- const onKeyDown = (event) => {
1118
- if (event.key === "ArrowDown" || event.key === "ArrowUp") {
1119
- event.preventDefault();
1120
- move(event.key === "ArrowDown" ? 1 : -1);
1121
- return;
1122
- }
1123
- if (event.key === "Escape") {
1124
- event.preventDefault();
1125
- onClose();
1126
- return;
1127
- }
1128
- if (event.key === "Enter" && selected !== void 0 && (!(event.target instanceof Element) || event.target.closest("button") === null)) {
1129
- event.preventDefault();
1130
- onOpen(selected);
1131
- }
1132
- };
1133
- return /* @__PURE__ */ jsxs("aside", {
1134
- "data-testid": "files-browser",
1135
- "aria-label": "changed files",
1136
- tabIndex: -1,
1137
- onKeyDown,
1138
- className: "fixed inset-y-0 right-0 z-50 flex w-[min(440px,calc(100vw-24px))] flex-col overflow-hidden border-l border-doom-border bg-doom-rail outline-none",
1139
- children: [
1140
- /* @__PURE__ */ jsxs("div", {
1141
- className: "flex h-11 shrink-0 items-center gap-2.5 border-b border-doom-border px-4",
1142
- children: [
1143
- /* @__PURE__ */ jsx("span", {
1144
- className: "text-lg font-semibold text-doom-hi",
1145
- children: "# files"
1146
- }),
1147
- /* @__PURE__ */ jsxs("span", {
1148
- "data-testid": "files-browser-total",
1149
- className: "text-sm text-doom-dim",
1150
- children: [items.length, " changed"]
1151
- }),
1152
- /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
1153
- /* @__PURE__ */ jsx(Button, {
1154
- variant: "ghost",
1155
- size: "icon",
1156
- "data-testid": "files-browser-close",
1157
- "aria-label": "close changed files",
1158
- title: "close changed files",
1159
- onClick: onClose,
1160
- children: /* @__PURE__ */ jsx(CloseIcon, { className: "h-3 w-3" })
1161
- })
1162
- ]
1163
- }),
1164
- /* @__PURE__ */ jsxs("div", {
1165
- className: "flex items-center gap-2 px-4 pt-2.5 pb-1.5",
1166
- children: [/* @__PURE__ */ jsx(Input, {
1167
- ref: inputRef,
1168
- "data-testid": "files-browser-search",
1169
- "aria-label": "search changed file paths",
1170
- value: query,
1171
- placeholder: "search paths…",
1172
- autoFocus: true,
1173
- onChange: (event) => {
1174
- setQuery(event.target.value);
1175
- setSelectedIndex(0);
1176
- }
1177
- }), query.length > 0 ? /* @__PURE__ */ jsx(Button, {
1178
- variant: "ghost",
1179
- size: "xs",
1180
- "data-testid": "files-browser-clear",
1181
- "aria-label": "clear path search",
1182
- onClick: () => {
1183
- setQuery("");
1184
- setSelectedIndex(0);
1185
- inputRef.current?.focus();
1186
- },
1187
- children: "clear"
1188
- }) : null]
1189
- }),
1190
- /* @__PURE__ */ jsxs("p", {
1191
- "data-testid": "files-browser-matches",
1192
- className: "shrink-0 px-4 pb-2 text-sm text-doom-dim",
1193
- children: [
1194
- shown.length,
1195
- " matches · ",
1196
- grouped === void 0 ? "newest change first" : "by path"
1197
- ]
1198
- }),
1199
- /* @__PURE__ */ jsxs("div", {
1200
- ref: listRef,
1201
- role: "listbox",
1202
- "aria-label": "changed files",
1203
- className: "flex min-h-0 flex-1 flex-col overflow-y-auto pb-2",
1204
- children: [shown.length === 0 ? /* @__PURE__ */ jsx("p", {
1205
- className: "px-4 py-3 text-sm text-doom-dim",
1206
- children: "nothing matches the path"
1207
- }) : null, grouped === void 0 ? shown.map((item) => /* @__PURE__ */ jsx(BrowserFileRow, {
1208
- item,
1209
- label: item.relPath,
1210
- recent: item.path === recentPath,
1211
- selected: positions.get(item.path) === selectedIndex,
1212
- onSelect: () => setSelectedIndex(positions.get(item.path) ?? 0),
1213
- onOpen: () => onOpen(item)
1214
- }, item.path)) : grouped.map((group) => /* @__PURE__ */ jsxs(Fragment, { children: [group.prefix === "" ? null : /* @__PURE__ */ jsx(FileGroupHeader, { prefix: group.prefix }), group.items.map((item) => /* @__PURE__ */ jsx(BrowserFileRow, {
1215
- item,
1216
- label: groupRowLabel(group.prefix, item.relPath),
1217
- indented: true,
1218
- recent: item.path === recentPath,
1219
- selected: positions.get(item.path) === selectedIndex,
1220
- onSelect: () => setSelectedIndex(positions.get(item.path) ?? 0),
1221
- onOpen: () => onOpen(item)
1222
- }, item.path))] }, group.prefix))]
1223
- }),
1224
- /* @__PURE__ */ jsx("div", {
1225
- className: "flex h-8 shrink-0 items-center border-t border-doom-border-soft bg-doom-deep px-4",
1226
- children: /* @__PURE__ */ jsx("span", {
1227
- className: "text-sm text-doom-dim",
1228
- children: "↑↓ choose · enter open · esc close"
1229
- })
1230
- })
1231
- ]
1232
- });
1233
- }
1234
- //#endregion
1235
- //#region src/extensions/workspaces/sessions/(frontend)/fill/_components/FilesActivitySection.tsx
1236
- /**
1237
- * The files group's body in the activity dock: what this session has changed.
1238
- *
1239
- * Every recorded file is listed, not only the ones the agent named. A file
1240
- * found by comparing the tree around a bash call is marked, because it is
1241
- * openable and editable but has no baseline to diff against, and a row that
1242
- * hid that distinction would promise a diff the tab cannot show.
1243
- */
1244
- /** The most recent changes first, which is the order the timeline already folds to. */
1245
- const VISIBLE_ROWS = 5;
1246
- function FilesActivitySection({ sessionId, openTransientTab }) {
1247
- const { items } = useStore(files.store, (state) => files.select(state, sessionId));
1248
- const [browserOpen, setBrowserOpen] = useState(false);
1249
- const openFile = (item) => {
1250
- if (sessionId === null) return;
1251
- openTransientTab(fileTab(item.path, item.relPath));
1252
- setBrowserOpen(false);
1253
- };
1254
- if (items.length === 0) return /* @__PURE__ */ jsx("p", {
1255
- "data-testid": "activity-summary-files",
1256
- className: "px-1 text-sm text-doom-dim",
1257
- children: "nothing changed yet"
1258
- });
1259
- const visible = items.slice(0, VISIBLE_ROWS);
1260
- return /* @__PURE__ */ jsxs("div", {
1261
- "data-testid": "activity-file-edits",
1262
- className: "flex flex-col gap-0.5",
1263
- children: [
1264
- visible.map((item) => /* @__PURE__ */ jsx(FileActivityRow, {
1265
- item,
1266
- onOpen: () => openFile(item)
1267
- }, item.path)),
1268
- items.length > visible.length ? /* @__PURE__ */ jsxs(Button, {
1269
- variant: "link",
1270
- size: "xs",
1271
- "data-testid": "activity-files-show-all",
1272
- "aria-label": `show all ${items.length} changed files`,
1273
- className: "self-start px-1 pt-0.5 text-doom-faint",
1274
- onClick: () => setBrowserOpen(true),
1275
- children: [
1276
- "show all ",
1277
- items.length,
1278
- " files"
1279
- ]
1280
- }) : null,
1281
- browserOpen ? /* @__PURE__ */ jsx(FilesBrowser, {
1282
- items,
1283
- onClose: () => setBrowserOpen(false),
1284
- onOpen: openFile
1285
- }) : null
1286
- ]
1287
- });
1288
- }
1289
- //#endregion
1290
- //#region src/extensions/workspaces/sessions/(frontend)/fill/Files.activity.files.web.tsx
1291
- var Files_activity_files_web_default = defineFill({ component: FilesActivitySection });
1292
- var files_web_default = defineLeaderBinding({
1293
- path: [{
1294
- key: "e",
1295
- label: "extension",
1296
- detail: "tools, skills and config"
1297
- }, {
1298
- key: "f",
1299
- label: "files",
1300
- detail: "files this session changed"
1301
- }],
1302
- command: "file-edits"
1303
- });
1304
- //#endregion
1305
1007
  //#region generated/web.ts
1306
1008
  const via = (identity, value) => value === void 0 ? void 0 : {
1307
1009
  ...identity,
@@ -1310,23 +1012,11 @@ const via = (identity, value) => value === void 0 ? void 0 : {
1310
1012
  const webPlugin = defineWebPlugin({
1311
1013
  id: "files",
1312
1014
  session: {
1313
- get activityGroups() {
1314
- return [via({ name: "files" }, files_web_default$2)];
1315
- },
1316
1015
  get channels() {
1317
1016
  return [via({ channel: "file_edits" }, file_edits_web_default)];
1318
1017
  },
1319
1018
  get fileLinks() {
1320
- return files_web_default$1;
1321
- },
1322
- get fills() {
1323
- return [via({
1324
- slot: "activity.files",
1325
- id: "files"
1326
- }, Files_activity_files_web_default)];
1327
- },
1328
- get leaderBindings() {
1329
- return [via({ id: "files.files" }, files_web_default)];
1019
+ return files_web_default;
1330
1020
  }
1331
1021
  }
1332
1022
  });