@agimon-ai/doompi-author 0.0.1-alpha.41 → 0.0.1-alpha.43

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.
@@ -530,11 +530,8 @@ const TERMINAL_REQUEST_STATUSES = /* @__PURE__ */ new Set([
530
530
  ]);
531
531
  const EMPTY_SESSION = {
532
532
  generation: 0,
533
- activeTool: "select",
534
533
  annotationsByDocument: {},
535
- annotations: [],
536
- candidateText: "",
537
- regions: [],
534
+ toolsByDocument: {},
538
535
  requests: []
539
536
  };
540
537
  function normalizeAuthorPath(path) {
@@ -561,8 +558,19 @@ function authorSessionWorkspace(sessionId) {
561
558
  if (sessionId === null) return EMPTY_SESSION;
562
559
  return authorWorkspace.store.state.sessions[sessionId] ?? EMPTY_SESSION;
563
560
  }
564
- function authorDocumentAnnotations(sessionId, path) {
565
- return sessionId === null ? void 0 : authorWorkspace.store.state.sessions[sessionId]?.annotationsByDocument[normalizeAuthorPath(path)];
561
+ const EMPTY_COLLECTION = Object.freeze({
562
+ revision: 0,
563
+ stale: false,
564
+ candidate: void 0,
565
+ candidateText: "",
566
+ annotations: Object.freeze([]),
567
+ updatedAt: 0
568
+ });
569
+ function authorDocumentAnnotations(sessionId, path, state = authorWorkspace.store.state) {
570
+ if (sessionId === null) return EMPTY_COLLECTION;
571
+ const document = state.documents[authorDocumentKey(sessionId, path)];
572
+ const collection = state.sessions[sessionId]?.annotationsByDocument[normalizeAuthorPath(path)];
573
+ return document !== void 0 && collection !== void 0 && !collection.stale && collection.revision === document.version && collection.sourceSha256 === document.sourceSha256 ? collection : EMPTY_COLLECTION;
566
574
  }
567
575
  function hydrateAuthorAnnotationCollections(records) {
568
576
  authorWorkspace.update((state) => {
@@ -579,8 +587,6 @@ function hydrateAuthorAnnotationCollections(records) {
579
587
  ...record.collection,
580
588
  stale
581
589
  });
582
- const visible = session.focusedDocument?.path === path && !stale;
583
- const annotations = visible ? collection.annotations : session.annotations;
584
590
  sessions = {
585
591
  ...sessions,
586
592
  [record.sessionId]: {
@@ -588,13 +594,7 @@ function hydrateAuthorAnnotationCollections(records) {
588
594
  annotationsByDocument: {
589
595
  ...session.annotationsByDocument,
590
596
  [path]: collection
591
- },
592
- ...visible ? {
593
- annotations,
594
- regions: annotations,
595
- candidate: collection.candidate,
596
- candidateText: collection.candidateText
597
- } : {}
597
+ }
598
598
  }
599
599
  };
600
600
  }
@@ -626,32 +626,25 @@ function putAuthorDocument(sessionId, input) {
626
626
  };
627
627
  const session = state.sessions[sessionId];
628
628
  let sessions = state.sessions;
629
- if (sourceChanged && session?.focusedDocument?.path === path) {
630
- staleThumbnails.push(...session.candidate?.thumbnailUrl === void 0 ? [] : [session.candidate.thumbnailUrl], ...session.annotations.flatMap((annotation) => annotation.thumbnailUrl === void 0 ? [] : [annotation.thumbnailUrl]));
629
+ if (sourceChanged && session !== void 0) {
630
+ const collection = session.annotationsByDocument[path];
631
+ if (collection?.candidate?.thumbnailUrl !== void 0) staleThumbnails.push(collection.candidate.thumbnailUrl);
632
+ staleThumbnails.push(...(collection?.annotations ?? []).flatMap((annotation) => annotation.thumbnailUrl === void 0 ? [] : [annotation.thumbnailUrl]));
631
633
  const now = Date.now();
632
- const generation = session.generation + 1;
633
- const staleCollection = staleAuthorCollection(session.annotationsByDocument[path], now);
634
+ const staleCollection = staleAuthorCollection(collection, now);
634
635
  sessions = {
635
636
  ...sessions,
636
637
  [sessionId]: {
637
638
  ...session,
638
- generation,
639
- focusedDocument: {
640
- path,
641
- generation,
642
- revision: baselineVersion,
643
- sourceSha256: input.sourceSha256,
644
- focusedAt: now
645
- },
646
639
  annotationsByDocument: {
647
640
  ...session.annotationsByDocument,
648
641
  ...staleCollection && { [path]: staleCollection }
649
642
  },
650
- annotations: [],
651
- regions: [],
652
- candidate: void 0,
653
- candidateText: "",
654
- requests: session.requests.map((request) => input.kind !== "story-preview" && request.documentPath === path && (request.status === "REQUESTED" || request.status === "CHANGING" || request.status === "CHANGED") ? {
643
+ requests: session.requests.map((request) => input.kind !== "story-preview" && request.documentPath === path && [
644
+ "REQUESTED",
645
+ "CHANGING",
646
+ "CHANGED"
647
+ ].includes(request.status) ? {
655
648
  ...request,
656
649
  status: "FAILED",
657
650
  currentOperation: void 0,
@@ -660,20 +653,6 @@ function putAuthorDocument(sessionId, input) {
660
653
  } : request)
661
654
  }
662
655
  };
663
- } else if (sourceChanged && session?.annotationsByDocument[path] !== void 0) {
664
- const collection = session.annotationsByDocument[path];
665
- if (collection.candidate?.thumbnailUrl !== void 0) staleThumbnails.push(collection.candidate.thumbnailUrl);
666
- staleThumbnails.push(...collection.annotations.flatMap((annotation) => annotation.thumbnailUrl === void 0 ? [] : [annotation.thumbnailUrl]));
667
- sessions = {
668
- ...sessions,
669
- [sessionId]: {
670
- ...session,
671
- annotationsByDocument: {
672
- ...session.annotationsByDocument,
673
- [path]: staleAuthorCollection(collection, Date.now())
674
- }
675
- }
676
- };
677
656
  }
678
657
  return {
679
658
  documents: {
@@ -687,76 +666,37 @@ function putAuthorDocument(sessionId, input) {
687
666
  return result;
688
667
  }
689
668
  /** Claims focus and returns a generation token that makes cleanup race-safe. */
690
- function focusAuthorDocument(sessionId, path, revision, sourceSha256) {
691
- const normalized = normalizeAuthorPath(path);
669
+ function focusAuthorDocument(sessionId, path) {
692
670
  let generation = 0;
693
- authorWorkspace.update((state) => {
694
- const session = state.sessions[sessionId] ?? EMPTY_SESSION;
695
- generation = session.generation + 1;
696
- const stored = session.annotationsByDocument[normalized];
697
- const current = stored !== void 0 && stored.revision === revision && stored.sourceSha256 === sourceSha256 && !stored.stale ? stored : void 0;
698
- const annotations = current?.annotations ?? [];
699
- return {
700
- ...state,
701
- sessions: {
702
- ...state.sessions,
703
- [sessionId]: {
704
- ...session,
705
- generation,
706
- focusedDocument: {
707
- path: normalized,
708
- generation,
709
- revision,
710
- sourceSha256,
711
- focusedAt: Date.now()
712
- },
713
- annotations,
714
- regions: annotations,
715
- candidate: current?.candidate,
716
- candidateText: current?.candidateText ?? ""
717
- }
718
- }
719
- };
720
- });
721
- return generation;
722
- }
723
- function syncAuthorDocumentFocus(sessionId, generation, revision, sourceSha256) {
724
671
  updateSession(sessionId, (session) => {
725
- const focused = session.focusedDocument;
726
- if (focused === void 0 || focused.generation !== generation) return session;
727
- if (focused.revision === revision && focused.sourceSha256 === sourceSha256) return session;
672
+ generation = session.generation + 1;
728
673
  return {
729
674
  ...session,
675
+ generation,
730
676
  focusedDocument: {
731
- ...focused,
732
- revision,
733
- sourceSha256
677
+ path: normalizeAuthorPath(path),
678
+ generation,
679
+ focusedAt: Date.now()
734
680
  }
735
681
  };
736
682
  });
683
+ return generation;
737
684
  }
738
685
  function releaseAuthorDocumentFocus(sessionId, generation) {
739
- updateSession(sessionId, (session) => {
740
- if (session.focusedDocument?.generation !== generation) return session;
741
- return {
742
- ...session,
743
- focusedDocument: void 0,
744
- candidate: void 0,
745
- candidateText: "",
746
- annotations: [],
747
- regions: []
748
- };
749
- });
686
+ updateSession(sessionId, (session) => session.focusedDocument?.generation === generation ? {
687
+ ...session,
688
+ focusedDocument: void 0
689
+ } : session);
750
690
  }
751
- function seekAuthorVideo(sessionId, timeSeconds) {
752
- const workspace = authorSessionWorkspace(sessionId);
753
- const focused = workspace.focusedDocument;
754
- if (!focused || workspace.candidate || !Number.isFinite(timeSeconds) || timeSeconds < 0 || authorDocument(sessionId, focused.path)?.kind !== "video") return false;
691
+ function seekAuthorVideo(sessionId, path, timeSeconds) {
692
+ const normalized = normalizeAuthorPath(path);
693
+ const focused = authorSessionWorkspace(sessionId).focusedDocument;
694
+ if (focused?.path !== normalized || authorDocumentAnnotations(sessionId, normalized).candidate || !Number.isFinite(timeSeconds) || timeSeconds < 0 || authorDocument(sessionId, normalized)?.kind !== "video") return false;
695
+ setAuthorToolMode(sessionId, normalized, "select");
755
696
  updateSession(sessionId, (session) => ({
756
697
  ...session,
757
- activeTool: "select",
758
698
  videoSeekRequest: {
759
- path: focused.path,
699
+ path: normalized,
760
700
  generation: focused.generation,
761
701
  timeSeconds,
762
702
  sequence: (session.videoSeekRequest?.sequence ?? 0) + 1
@@ -764,110 +704,78 @@ function seekAuthorVideo(sessionId, timeSeconds) {
764
704
  }));
765
705
  return true;
766
706
  }
767
- function setAuthorToolMode(sessionId, activeTool) {
768
- updateSession(sessionId, (session) => session.activeTool === activeTool ? session : {
707
+ function setAuthorToolMode(sessionId, path, tool) {
708
+ const normalized = normalizeAuthorPath(path);
709
+ updateSession(sessionId, (session) => ({
769
710
  ...session,
770
- activeTool
771
- });
772
- }
773
- function setAuthorRegionCandidate(sessionId, candidate) {
774
- let staleThumbnail;
775
- updateSession(sessionId, (session) => {
776
- const focused = session.focusedDocument;
777
- if (candidate !== void 0) {
778
- if (focused === void 0 || focused.path !== normalizeAuthorPath(candidate.documentPath)) throw new Error("The Author selection does not belong to the focused document.");
779
- if (focused.revision !== candidate.revision || focused.sourceSha256 !== candidate.sourceSha256) throw new Error("The Author selection is stale for the focused document.");
711
+ toolsByDocument: {
712
+ ...session.toolsByDocument,
713
+ [normalized]: tool
780
714
  }
781
- if (focused === void 0) return session;
782
- staleThumbnail = session.candidate?.thumbnailUrl;
783
- const copied = candidate === void 0 ? void 0 : copyCandidate(candidate);
784
- return withFocusedCollection({
785
- ...session,
786
- candidate: copied
787
- }, focused.path, { candidate: copied });
788
- });
789
- if (staleThumbnail !== void 0 && staleThumbnail !== candidate?.thumbnailUrl) revokeThumbnail(staleThumbnail);
715
+ }));
716
+ }
717
+ function validateCandidate(sessionId, path, candidate) {
718
+ const document = authorDocument(sessionId, path);
719
+ if (document === void 0 || normalizeAuthorPath(candidate.documentPath) !== normalizeAuthorPath(path)) throw new Error("The Author selection does not belong to the document.");
720
+ if (document.version !== candidate.revision || document.sourceSha256 !== candidate.sourceSha256) throw new Error("The Author selection is stale for the document.");
790
721
  }
791
- function setAuthorCandidateText(sessionId, candidateText) {
722
+ function setAuthorRegionCandidate(sessionId, path, candidate) {
723
+ if (candidate !== void 0) validateCandidate(sessionId, path, candidate);
724
+ const thumbnail = authorDocumentAnnotations(sessionId, path).candidate?.thumbnailUrl;
725
+ updateCollection(sessionId, path, (collection) => ({
726
+ ...collection,
727
+ candidate: candidate && copyCandidate(candidate)
728
+ }));
729
+ if (thumbnail !== void 0 && thumbnail !== candidate?.thumbnailUrl) revokeThumbnail(thumbnail);
730
+ }
731
+ function setAuthorCandidateText(sessionId, path, candidateText) {
792
732
  if (new TextEncoder().encode(candidateText).byteLength > 2048) throw new Error("Author candidate text must not exceed 2 KiB.");
793
- updateSession(sessionId, (session) => {
794
- const path = session.focusedDocument?.path;
795
- return path === void 0 ? session : withFocusedCollection({
796
- ...session,
797
- candidateText
798
- }, path, { candidateText });
799
- });
733
+ updateCollection(sessionId, path, (collection) => ({
734
+ ...collection,
735
+ candidateText
736
+ }));
800
737
  }
801
- function commitAuthorRegion(sessionId, comment) {
738
+ function commitAuthorRegion(sessionId, path, comment) {
739
+ const candidate = authorDocumentAnnotations(sessionId, path).candidate;
740
+ if (candidate === void 0) throw new Error("Select a document annotation before adding a comment.");
802
741
  const id = crypto.randomUUID();
803
- const session = authorSessionWorkspace(sessionId);
804
- if (session.candidate === void 0) throw new Error("Select a document annotation before adding a comment.");
805
742
  addAuthorRegion(sessionId, {
806
- ...session.candidate,
743
+ ...candidate,
807
744
  id,
808
745
  comment,
809
746
  version: 1
810
747
  });
811
- updateSession(sessionId, (current) => {
812
- const path = current.focusedDocument?.path;
813
- return path === void 0 ? current : withFocusedCollection({
814
- ...current,
815
- candidate: void 0,
816
- candidateText: ""
817
- }, path, {
818
- candidate: void 0,
819
- candidateText: ""
820
- });
821
- });
748
+ updateCollection(sessionId, path, (collection) => ({
749
+ ...collection,
750
+ candidate: void 0,
751
+ candidateText: ""
752
+ }));
822
753
  return id;
823
754
  }
824
755
  function addAuthorRegion(sessionId, region) {
825
756
  if (region.comment.trim() === "") throw new Error("Every Author annotation requires a comment.");
826
- updateSession(sessionId, (session) => {
827
- const focused = session.focusedDocument;
828
- if (focused === void 0 || focused.path !== normalizeAuthorPath(region.documentPath)) throw new Error("The Author annotation does not belong to the focused document.");
829
- if (focused.revision !== region.revision || focused.sourceSha256 !== region.sourceSha256) throw new Error("The Author annotation is stale for the focused document.");
830
- if (session.annotations.length >= 16) throw new Error(`Author requests support at most 16 annotations.`);
831
- if (session.annotations.some((candidate) => candidate.id === region.id)) throw new Error(`Author annotation '${region.id}' already exists.`);
832
- const annotations = [...session.annotations, copyRegion({
833
- ...region,
834
- version: region.version ?? 1
835
- })];
836
- return withFocusedCollection({
837
- ...session,
838
- annotations,
839
- regions: annotations
840
- }, focused.path, { annotations });
757
+ validateCandidate(sessionId, region.documentPath, region);
758
+ updateCollection(sessionId, region.documentPath, (collection) => {
759
+ if (collection.annotations.length >= 16) throw new Error(`Author requests support at most 16 annotations.`);
760
+ if (collection.annotations.some((candidate) => candidate.id === region.id)) throw new Error(`Author annotation '${region.id}' already exists.`);
761
+ return {
762
+ ...collection,
763
+ annotations: [...collection.annotations, copyRegion({
764
+ ...region,
765
+ version: region.version ?? 1
766
+ })]
767
+ };
841
768
  });
842
769
  }
843
- function removeAuthorRegion(sessionId, regionId, expectedVersion, documentPath) {
770
+ function removeAuthorRegion(sessionId, path, regionId, expectedVersion) {
844
771
  let thumbnail;
845
- updateSession(sessionId, (session) => {
846
- const path = documentPath === void 0 ? session.focusedDocument?.path : normalizeAuthorPath(documentPath);
847
- if (path === void 0) return session;
848
- const focused = session.focusedDocument?.path === path;
849
- const collection = session.annotationsByDocument[path];
850
- const current = focused ? session.annotations : collection?.annotations;
851
- if (current === void 0) return session;
852
- const annotation = current.find((candidate) => candidate.id === regionId);
853
- if (annotation === void 0 || expectedVersion !== void 0 && (annotation.version ?? 1) !== expectedVersion) return session;
772
+ updateCollection(sessionId, path, (collection) => {
773
+ const annotation = collection.annotations.find((candidate) => candidate.id === regionId);
774
+ if (annotation === void 0 || expectedVersion !== void 0 && (annotation.version ?? 1) !== expectedVersion) return collection;
854
775
  thumbnail = annotation.thumbnailUrl;
855
- const annotations = current.filter((candidate) => candidate.id !== regionId);
856
- if (focused) return withFocusedCollection({
857
- ...session,
858
- annotations,
859
- regions: annotations
860
- }, path, { annotations });
861
776
  return {
862
- ...session,
863
- annotationsByDocument: {
864
- ...session.annotationsByDocument,
865
- [path]: {
866
- ...collection,
867
- annotations,
868
- updatedAt: Date.now()
869
- }
870
- }
777
+ ...collection,
778
+ annotations: collection.annotations.filter((candidate) => candidate.id !== regionId)
871
779
  };
872
780
  });
873
781
  if (thumbnail !== void 0) revokeThumbnail(thumbnail);
@@ -1012,9 +920,7 @@ function updateDocument(sessionId, path, update) {
1012
920
  if (document === void 0) return state;
1013
921
  const next = update(document);
1014
922
  const session = state.sessions[sessionId];
1015
- const focused = session?.focusedDocument;
1016
923
  const identityChanged = document.version !== next.version || document.sourceSha256 !== next.sourceSha256;
1017
- const focusedChanged = identityChanged && focused?.path === document.path;
1018
924
  const collection = identityChanged ? session?.annotationsByDocument[document.path] : void 0;
1019
925
  if (collection !== void 0) {
1020
926
  if (collection.candidate?.thumbnailUrl !== void 0) staleThumbnails.push(collection.candidate.thumbnailUrl);
@@ -1028,18 +934,7 @@ function updateDocument(sessionId, path, update) {
1028
934
  annotationsByDocument: {
1029
935
  ...session.annotationsByDocument,
1030
936
  ...staleCollection && { [document.path]: staleCollection }
1031
- },
1032
- ...focusedChanged ? {
1033
- focusedDocument: {
1034
- ...focused,
1035
- revision: next.version,
1036
- sourceSha256: next.sourceSha256
1037
- },
1038
- candidate: void 0,
1039
- candidateText: "",
1040
- annotations: [],
1041
- regions: []
1042
- } : {}
937
+ }
1043
938
  }
1044
939
  } : state.sessions;
1045
940
  return {
@@ -1100,27 +995,31 @@ function staleAuthorCollection(collection, updatedAt) {
1100
995
  updatedAt
1101
996
  };
1102
997
  }
1103
- function withFocusedCollection(session, path, update) {
1104
- const focused = session.focusedDocument;
1105
- if (focused === void 0 || focused.path !== path) return session;
1106
- const collection = {
1107
- ...session.annotationsByDocument[path],
1108
- revision: focused.revision,
1109
- sourceSha256: focused.sourceSha256,
1110
- stale: false,
1111
- candidate: session.candidate,
1112
- candidateText: session.candidateText,
1113
- annotations: session.annotations,
1114
- updatedAt: Date.now(),
1115
- ...update
1116
- };
1117
- return {
1118
- ...session,
1119
- annotationsByDocument: {
1120
- ...session.annotationsByDocument,
1121
- [path]: collection
1122
- }
1123
- };
998
+ function updateCollection(sessionId, path, update) {
999
+ const normalized = normalizeAuthorPath(path);
1000
+ const document = authorDocument(sessionId, normalized);
1001
+ if (document === void 0) return;
1002
+ updateSession(sessionId, (session) => {
1003
+ const current = authorDocumentAnnotations(sessionId, normalized);
1004
+ const base = current === EMPTY_COLLECTION ? {
1005
+ ...EMPTY_COLLECTION,
1006
+ revision: document.version,
1007
+ sourceSha256: document.sourceSha256
1008
+ } : current;
1009
+ const next = update(base);
1010
+ if (next === base) return session;
1011
+ return {
1012
+ ...session,
1013
+ annotationsByDocument: {
1014
+ ...session.annotationsByDocument,
1015
+ [normalized]: {
1016
+ ...next,
1017
+ stale: false,
1018
+ updatedAt: Date.now()
1019
+ }
1020
+ }
1021
+ };
1022
+ });
1124
1023
  }
1125
1024
  function boundedHistoryText(value) {
1126
1025
  if (value === void 0) return void 0;
@@ -1346,6 +1245,7 @@ function normalizedAuthorRectangle(bounds, drag) {
1346
1245
  //#endregion
1347
1246
  //#region src/extensions/workspaces/sessions/(frontend)/_lib/authorCapture.ts
1348
1247
  const AUTHOR_CAPTURE_MAX_DIMENSION = 1600;
1248
+ const AUTHOR_PACKET_MAX_BYTES = 65536;
1349
1249
  const AUTHOR_QUOTE_MAX_BYTES = 4096;
1350
1250
  const AUTHOR_REGION_COLORS = [
1351
1251
  "#ff5f57",
@@ -1426,6 +1326,12 @@ function percent(value) {
1426
1326
  function rectLocation(rect) {
1427
1327
  return `x ${percent(rect.x)}, y ${percent(rect.y)}, w ${percent(rect.width)}, h ${percent(rect.height)}`;
1428
1328
  }
1329
+ /** Context stays below the host limit even when paths and anchor locations are unusually long. */
1330
+ function authorDocumentContextContent(path, alias, annotations) {
1331
+ const heading = `Author document: ${path}${alias === void 0 ? "" : ` (canvas ${alias})`}`;
1332
+ const drafts = annotations.map((region, index) => `(${index + 1}) ${region.comment.slice(0, 1e3)} [${anchorLocation(region.anchor)}]`);
1333
+ return utf8Prefix([heading, ...drafts.length === 0 ? [] : ["Unsent annotations (not yet submitted):", ...drafts]].join("\n"), AUTHOR_PACKET_MAX_BYTES);
1334
+ }
1429
1335
  function anchorLocation(anchor) {
1430
1336
  switch (anchor.kind) {
1431
1337
  case "text-range": return anchor.startLine === anchor.endLine ? `line ${String(anchor.startLine)}` : `lines ${String(anchor.startLine)}-${String(anchor.endLine)}`;
@@ -1626,23 +1532,23 @@ function multiRegionCaptureProvider(regions) {
1626
1532
  }
1627
1533
  //#endregion
1628
1534
  //#region src/extensions/workspaces/sessions/(frontend)/dock/_components/AuthorRegionDrafts.tsx
1629
- function AuthorRegionDrafts({ sessionId, workspace }) {
1535
+ function AuthorRegionDrafts({ sessionId, path, drafts }) {
1630
1536
  const [error, setError] = useState();
1631
1537
  const add = () => {
1632
1538
  try {
1633
- commitAuthorRegion(sessionId, workspace.candidateText);
1539
+ commitAuthorRegion(sessionId, path, drafts.candidateText);
1634
1540
  setError(void 0);
1635
1541
  } catch (reason) {
1636
1542
  setError(reason instanceof Error ? reason.message : String(reason));
1637
1543
  }
1638
1544
  };
1639
- if (!workspace.candidate && workspace.annotations.length === 0) return null;
1640
- const candidateKind = workspace.candidate?.mode === "point" ? "point" : "region";
1545
+ if (!drafts.candidate && drafts.annotations.length === 0) return null;
1546
+ const candidateKind = drafts.candidate?.mode === "point" ? "point" : "region";
1641
1547
  return /* @__PURE__ */ jsxs("section", {
1642
1548
  className: "space-y-2",
1643
1549
  "data-testid": "author-region-drafts",
1644
1550
  children: [
1645
- workspace.candidate ? /* @__PURE__ */ jsxs(Fragment, { children: [
1551
+ drafts.candidate ? /* @__PURE__ */ jsxs(Fragment, { children: [
1646
1552
  /* @__PURE__ */ jsxs("h3", {
1647
1553
  className: "text-base font-semibold text-doom-text",
1648
1554
  children: ["Current ", candidateKind]
@@ -1655,18 +1561,18 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
1655
1561
  " as an unsent annotation."
1656
1562
  ]
1657
1563
  }),
1658
- workspace.candidate.anchor.kind === "video-time-rect" || workspace.candidate.anchor.kind === "video-time-point" ? /* @__PURE__ */ jsxs("p", {
1564
+ drafts.candidate.anchor.kind === "video-time-rect" || drafts.candidate.anchor.kind === "video-time-point" ? /* @__PURE__ */ jsxs("p", {
1659
1565
  className: "text-base text-doom-dim sm:text-sm",
1660
1566
  children: [
1661
1567
  "Frame at ",
1662
- workspace.candidate.anchor.timeSeconds.toFixed(3),
1568
+ drafts.candidate.anchor.timeSeconds.toFixed(3),
1663
1569
  "s"
1664
1570
  ]
1665
1571
  }) : null,
1666
1572
  /* @__PURE__ */ jsx("textarea", {
1667
1573
  "aria-label": "Annotation comment",
1668
- value: workspace.candidateText,
1669
- onChange: (event) => setAuthorCandidateText(sessionId, event.target.value),
1574
+ value: drafts.candidateText,
1575
+ onChange: (event) => setAuthorCandidateText(sessionId, path, event.target.value),
1670
1576
  placeholder: "What should change here?",
1671
1577
  rows: 3,
1672
1578
  className: "min-h-11 w-full resize-y rounded border border-doom-border bg-doom-deep p-2 text-lg leading-normal text-doom-text focus:border-doom-red focus:outline-none sm:text-sm"
@@ -1675,15 +1581,15 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
1675
1581
  className: "min-h-11 min-w-11 text-base [@media(pointer:fine)]:min-h-8 sm:text-sm",
1676
1582
  variant: "outline",
1677
1583
  onClick: add,
1678
- disabled: !workspace.candidate || !workspace.candidateText.trim() || workspace.annotations.length >= 16,
1584
+ disabled: !drafts.candidate || !drafts.candidateText.trim() || drafts.annotations.length >= 16,
1679
1585
  children: "add annotation"
1680
1586
  }),
1681
1587
  /* @__PURE__ */ jsx(Button, {
1682
1588
  variant: "ghost",
1683
1589
  className: "min-h-11 min-w-11 text-base [@media(pointer:fine)]:min-h-8 sm:text-sm",
1684
1590
  onClick: () => {
1685
- setAuthorRegionCandidate(sessionId, void 0);
1686
- setAuthorCandidateText(sessionId, "");
1591
+ setAuthorRegionCandidate(sessionId, path, void 0);
1592
+ setAuthorCandidateText(sessionId, path, "");
1687
1593
  setError(void 0);
1688
1594
  },
1689
1595
  children: "Discard annotation"
@@ -1693,17 +1599,17 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
1693
1599
  className: "block text-base text-doom-red",
1694
1600
  children: error
1695
1601
  }) : null,
1696
- workspace.annotations.length > 0 ? /* @__PURE__ */ jsxs("h3", {
1602
+ drafts.annotations.length > 0 ? /* @__PURE__ */ jsxs("h3", {
1697
1603
  className: "text-base font-semibold text-doom-text",
1698
1604
  children: [
1699
1605
  "Unsent annotations (",
1700
- workspace.annotations.length,
1606
+ drafts.annotations.length,
1701
1607
  ")"
1702
1608
  ]
1703
1609
  }) : null,
1704
1610
  /* @__PURE__ */ jsx("ol", {
1705
1611
  className: "space-y-2",
1706
- children: workspace.annotations.map((region, index) => /* @__PURE__ */ jsxs("li", {
1612
+ children: drafts.annotations.map((region, index) => /* @__PURE__ */ jsxs("li", {
1707
1613
  className: "rounded border border-doom-border bg-doom-panel p-2 text-base leading-normal text-doom-text sm:text-sm",
1708
1614
  children: [
1709
1615
  /* @__PURE__ */ jsxs("span", { children: [
@@ -1717,9 +1623,9 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
1717
1623
  region.anchor.kind === "video-time-rect" || region.anchor.kind === "video-time-point" ? /* @__PURE__ */ jsxs(Button, {
1718
1624
  variant: "outline",
1719
1625
  className: "min-h-11 min-w-11 text-base [@media(pointer:fine)]:min-h-8 sm:text-sm",
1720
- disabled: workspace.candidate !== void 0,
1626
+ disabled: drafts.candidate !== void 0,
1721
1627
  onClick: () => {
1722
- if (region.anchor.kind === "video-time-rect" || region.anchor.kind === "video-time-point") seekAuthorVideo(sessionId, region.anchor.timeSeconds);
1628
+ if (region.anchor.kind === "video-time-rect" || region.anchor.kind === "video-time-point") seekAuthorVideo(sessionId, path, region.anchor.timeSeconds);
1723
1629
  },
1724
1630
  children: [
1725
1631
  "Go to ",
@@ -1731,7 +1637,7 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
1731
1637
  className: "min-h-11 min-w-11 text-base [@media(pointer:fine)]:min-h-8 sm:text-sm",
1732
1638
  variant: "ghost",
1733
1639
  "aria-label": `Remove annotation ${index + 1}`,
1734
- onClick: () => removeAuthorRegion(sessionId, region.id),
1640
+ onClick: () => removeAuthorRegion(sessionId, path, region.id),
1735
1641
  children: "remove"
1736
1642
  })
1737
1643
  ]
@@ -1742,7 +1648,7 @@ function AuthorRegionDrafts({ sessionId, workspace }) {
1742
1648
  }
1743
1649
  //#endregion
1744
1650
  //#region src/extensions/workspaces/sessions/(frontend)/dock/_components/AuthorFeedbackControls.tsx
1745
- function AuthorFeedbackControls({ sessionId, document, workspace, submitCapture }) {
1651
+ function AuthorFeedbackControls({ sessionId, document, drafts, submitCapture }) {
1746
1652
  const [status, setStatus] = useState();
1747
1653
  const [capturing, setCapturing] = useState(false);
1748
1654
  return /* @__PURE__ */ jsxs("div", {
@@ -1750,21 +1656,22 @@ function AuthorFeedbackControls({ sessionId, document, workspace, submitCapture
1750
1656
  children: [
1751
1657
  /* @__PURE__ */ jsx(AuthorRegionDrafts, {
1752
1658
  sessionId,
1753
- workspace
1659
+ path: document.path,
1660
+ drafts
1754
1661
  }),
1755
- workspace.annotations.length > 0 ? /* @__PURE__ */ jsx(Button, {
1662
+ drafts.annotations.length > 0 ? /* @__PURE__ */ jsx(Button, {
1756
1663
  className: "min-h-11 min-w-11 w-full text-base [@media(pointer:fine)]:min-h-8 sm:text-sm",
1757
1664
  variant: "outline",
1758
1665
  "data-testid": "author-attach-capture",
1759
- disabled: capturing || workspace.candidate !== void 0 || submitCapture === void 0,
1666
+ disabled: capturing || drafts.candidate !== void 0 || submitCapture === void 0,
1760
1667
  onClick: async () => {
1761
- if (capturing || workspace.candidate || submitCapture === void 0) return;
1668
+ if (capturing || drafts.candidate || submitCapture === void 0) return;
1762
1669
  setCapturing(true);
1763
1670
  setStatus("Submitting annotations…");
1764
1671
  try {
1765
- const packet = createAuthorCapturePacket(crypto.randomUUID(), Date.now(), document, workspace.annotations, authorCanvasAlias(sessionId, document.path));
1672
+ const packet = createAuthorCapturePacket(crypto.randomUUID(), Date.now(), document, drafts.annotations, authorCanvasAlias(sessionId, document.path));
1766
1673
  await submitCapture({
1767
- ...await multiRegionCaptureProvider(workspace.annotations).capture(),
1674
+ ...await multiRegionCaptureProvider(drafts.annotations).capture(),
1768
1675
  context: authorCaptureContext(packet)
1769
1676
  });
1770
1677
  setStatus("Request submitted. You can keep annotating here.");
@@ -1774,7 +1681,7 @@ function AuthorFeedbackControls({ sessionId, document, workspace, submitCapture
1774
1681
  setCapturing(false);
1775
1682
  }
1776
1683
  },
1777
- children: capturing ? "Submitting…" : `Submit ${workspace.annotations.length} annotation${workspace.annotations.length === 1 ? "" : "s"}`
1684
+ children: capturing ? "Submitting…" : `Submit ${drafts.annotations.length} annotation${drafts.annotations.length === 1 ? "" : "s"}`
1778
1685
  }) : null,
1779
1686
  submitCapture === void 0 ? /* @__PURE__ */ jsx("output", {
1780
1687
  className: "text-sm text-doom-red",
@@ -1991,10 +1898,10 @@ function AuthorRequestLog({ requests }) {
1991
1898
  }
1992
1899
  //#endregion
1993
1900
  //#region src/extensions/workspaces/sessions/(frontend)/dock/_components/AuthorToolPalette.tsx
1994
- function AuthorToolPalette({ sessionId, kind, activeTool }) {
1901
+ function AuthorToolPalette({ sessionId, path, kind, activeTool }) {
1995
1902
  const [error, setError] = useState();
1996
1903
  const format = (style) => {
1997
- const selected = authorSessionWorkspace(sessionId).candidate;
1904
+ const selected = authorDocumentAnnotations(sessionId, path).candidate;
1998
1905
  const document = selected && authorDocument(sessionId, selected.documentPath);
1999
1906
  if (!selected || !document || selected.anchor.kind !== "text-range" || selected.revision !== document.version || selected.sourceSha256 !== document.sourceSha256) {
2000
1907
  setError("Select text in the document first.");
@@ -2005,7 +1912,7 @@ function AuthorToolPalette({ sessionId, kind, activeTool }) {
2005
1912
  const text = content.slice(startOffset, endOffset);
2006
1913
  const replacement = style === "Bold" ? `**${text}**` : style === "Link" ? `[${text}](https://)` : text.split("\n").map((line) => `${style === "Heading" ? "## " : "- "}${line}`).join("\n");
2007
1914
  reviseAuthorDocument(sessionId, document.path, content.slice(0, startOffset) + replacement + content.slice(endOffset));
2008
- setAuthorRegionCandidate(sessionId, void 0);
1915
+ setAuthorRegionCandidate(sessionId, path, void 0);
2009
1916
  setError(void 0);
2010
1917
  };
2011
1918
  const tools = [
@@ -2017,18 +1924,18 @@ function AuthorToolPalette({ sessionId, kind, activeTool }) {
2017
1924
  ].includes(kind) ? [{
2018
1925
  label: "Pan",
2019
1926
  glyph: "✋",
2020
- action: () => setAuthorToolMode(sessionId, activeTool === "pan" ? "select" : "pan"),
1927
+ action: () => setAuthorToolMode(sessionId, path, activeTool === "pan" ? "select" : "pan"),
2021
1928
  active: activeTool === "pan"
2022
1929
  }, {
2023
1930
  label: "Draw",
2024
1931
  glyph: "✎",
2025
- action: () => setAuthorToolMode(sessionId, activeTool === "draw" ? "select" : "draw"),
1932
+ action: () => setAuthorToolMode(sessionId, path, activeTool === "draw" ? "select" : "draw"),
2026
1933
  active: activeTool === "draw"
2027
1934
  }] : [],
2028
1935
  {
2029
1936
  label: "Region",
2030
1937
  glyph: "⌗",
2031
- action: () => setAuthorToolMode(sessionId, activeTool === "mark" ? "select" : "mark"),
1938
+ action: () => setAuthorToolMode(sessionId, path, activeTool === "mark" ? "select" : "mark"),
2032
1939
  active: activeTool === "mark"
2033
1940
  },
2034
1941
  ...kind === "markdown" ? [
@@ -2056,7 +1963,7 @@ function AuthorToolPalette({ sessionId, kind, activeTool }) {
2056
1963
  {
2057
1964
  label: "Comment",
2058
1965
  glyph: "●",
2059
- action: () => setAuthorToolMode(sessionId, activeTool === "comment" ? "select" : "comment"),
1966
+ action: () => setAuthorToolMode(sessionId, path, activeTool === "comment" ? "select" : "comment"),
2060
1967
  active: activeTool === "comment"
2061
1968
  }
2062
1969
  ];
@@ -2110,7 +2017,8 @@ function AuthorPanel({ sessionId, activeMinorModes, submitCapture, statuses, ren
2110
2017
  const focused = documents.find((document) => document.path === workspace?.focusedDocument?.path);
2111
2018
  const focusedPath = workspace?.focusedDocument?.path;
2112
2019
  const requests = (workspace?.requests ?? []).filter((request) => focusedPath === void 0 || request.documentPath === focusedPath);
2113
- const activity = sessionId === null ? null : renderSessionActivity?.() ?? null;
2020
+ const drafts = useStore(authorWorkspace.store, (state) => authorDocumentAnnotations(sessionId, focusedPath ?? "", state));
2021
+ const activity = sessionId !== null && focusedPath !== void 0 && requests.some((request) => request.status === "REQUESTED" || request.status === "CHANGING") ? renderSessionActivity?.() ?? null : null;
2114
2022
  if (!activeMinorModes?.includes("author")) return null;
2115
2023
  return /* @__PURE__ */ jsxs("section", {
2116
2024
  "data-testid": "author-panel",
@@ -2139,8 +2047,9 @@ function AuthorPanel({ sessionId, activeMinorModes, submitCapture, statuses, ren
2139
2047
  }) : null,
2140
2048
  /* @__PURE__ */ jsx(AuthorToolPalette, {
2141
2049
  sessionId,
2050
+ path: focused.path,
2142
2051
  kind: focused.kind,
2143
- activeTool: workspace.activeTool
2052
+ activeTool: workspace.toolsByDocument[normalizeAuthorPath(focused.path)] ?? "select"
2144
2053
  }),
2145
2054
  autonomousVoiceGridVisible(statuses) && grid !== void 0 ? /* @__PURE__ */ jsxs("div", {
2146
2055
  "data-testid": "author-grid-snapshot",
@@ -2158,7 +2067,7 @@ function AuthorPanel({ sessionId, activeMinorModes, submitCapture, statuses, ren
2158
2067
  children: /* @__PURE__ */ jsx(AuthorFeedbackControls, {
2159
2068
  sessionId,
2160
2069
  document: focused,
2161
- workspace,
2070
+ drafts,
2162
2071
  submitCapture
2163
2072
  }, focused.path)
2164
2073
  })
@@ -3177,11 +3086,11 @@ function AuthorMediaView({ sessionId, document: source, activeTool, displayedReg
3177
3086
  };
3178
3087
  }, [source.mediaUrl]);
3179
3088
  const seek = (seconds) => {
3180
- if (authorSessionWorkspace(sessionId).candidate || !Number.isFinite(seconds)) return;
3089
+ if (authorDocumentAnnotations(sessionId, source.path).candidate || !Number.isFinite(seconds)) return;
3181
3090
  const player = video.current;
3182
3091
  if (!player) return;
3183
3092
  player.pause();
3184
- setAuthorToolMode(sessionId, "select");
3093
+ setAuthorToolMode(sessionId, source.path, "select");
3185
3094
  setSelection(void 0);
3186
3095
  if (player.getState().currentTime === seconds) return;
3187
3096
  setFrameReady(false);
@@ -3316,7 +3225,7 @@ function AuthorMediaView({ sessionId, document: source, activeTool, displayedReg
3316
3225
  if (!blob) throw new Error("Unable to capture selected media.");
3317
3226
  if (authorSessionWorkspace(sessionId).focusedDocument?.generation !== focused.generation) return;
3318
3227
  thumbnailUrl = URL.createObjectURL(blob);
3319
- setAuthorRegionCandidate(sessionId, {
3228
+ setAuthorRegionCandidate(sessionId, source.path, {
3320
3229
  documentPath: source.path,
3321
3230
  revision: source.version,
3322
3231
  sourceSha256: source.sourceSha256,
@@ -3675,14 +3584,14 @@ function AuthorMediaView({ sessionId, document: source, activeTool, displayedReg
3675
3584
  marking: activeTool === "mark",
3676
3585
  onSeek: seek,
3677
3586
  onToggle: () => {
3678
- setAuthorToolMode(sessionId, "select");
3587
+ setAuthorToolMode(sessionId, source.path, "select");
3679
3588
  setSelection(void 0);
3680
3589
  if (playback.playing) video.current?.pause();
3681
3590
  else video.current?.play().catch((reason) => setError(String(reason)));
3682
3591
  },
3683
3592
  onAnnotate: () => {
3684
3593
  video.current?.pause();
3685
- setAuthorToolMode(sessionId, "mark");
3594
+ setAuthorToolMode(sessionId, source.path, "mark");
3686
3595
  }
3687
3596
  }) : null,
3688
3597
  error ? /* @__PURE__ */ jsx("output", {
@@ -3763,7 +3672,7 @@ function AuthorStructuredView({ sessionId, document, displayedRegions }) {
3763
3672
  const bounds = event.currentTarget.getBoundingClientRect();
3764
3673
  const slide = Number(fragment.location.match(/(?:slide\s*|slides\/slide)(\d+)/)?.[1]);
3765
3674
  if (!cells && !Number.isSafeInteger(slide)) return;
3766
- setAuthorRegionCandidate(sessionId, {
3675
+ setAuthorRegionCandidate(sessionId, document.path, {
3767
3676
  documentPath: document.path,
3768
3677
  revision: document.version,
3769
3678
  sourceSha256: document.sourceSha256,
@@ -3851,7 +3760,7 @@ function AuthorTextView({ sessionId, document, preview, displayedRegions }) {
3851
3760
  const current = authorDocument(sessionId, document.path);
3852
3761
  const bounds = host.current?.getBoundingClientRect();
3853
3762
  if (!current || !bounds || range.from === range.to) return;
3854
- setAuthorRegionCandidate(sessionId, {
3763
+ setAuthorRegionCandidate(sessionId, document.path, {
3855
3764
  documentPath: current.path,
3856
3765
  revision: current.version,
3857
3766
  sourceSha256: current.sourceSha256,
@@ -3884,7 +3793,7 @@ function tabId(path) {
3884
3793
  }
3885
3794
  /** Unsent annotations only. Sent ones live in the request log, not on the canvas. */
3886
3795
  function displayedAuthorRegions(workspace) {
3887
- return (workspace?.regions ?? []).map((region, index) => ({
3796
+ return (workspace?.annotations ?? []).map((region, index) => ({
3888
3797
  ordinal: index + 1,
3889
3798
  region
3890
3799
  }));
@@ -3907,9 +3816,9 @@ function ActiveAuthorDocumentPanel(props) {
3907
3816
  const alias = useStore(canvasAliases, (state) => props.alias ?? (sessionId === null ? void 0 : state[authorDocumentKey(sessionId, props.path)]));
3908
3817
  const loadFailure = useStore(canvasFailures, (state) => sessionId === null ? void 0 : state[authorDocumentKey(sessionId, props.path)]);
3909
3818
  const document = useStore(authorWorkspace.store, (state) => sessionId === null ? void 0 : state.documents[authorDocumentKey(sessionId, path)]);
3910
- const focusGeneration = useRef(void 0);
3911
3819
  const workspace = useStore(authorWorkspace.store, (state) => sessionId === null ? void 0 : state.sessions[sessionId]);
3912
- const activeTool = workspace?.activeTool ?? "select";
3820
+ const drafts = useStore(authorWorkspace.store, (state) => authorDocumentAnnotations(sessionId, path, state));
3821
+ const activeTool = workspace?.toolsByDocument[normalizeAuthorPath(path)] ?? "select";
3913
3822
  const [markdownPreview, setMarkdownPreview] = useState(true);
3914
3823
  const [status, setStatus] = useState();
3915
3824
  const [previewOpen, setPreviewOpen] = useState(false);
@@ -3923,25 +3832,10 @@ function ActiveAuthorDocumentPanel(props) {
3923
3832
  };
3924
3833
  const PreviewPanel = (previewSource === void 0 ? void 0 : (props.slotData?.(authorPreviewActionSlot) ?? []).find(({ data }) => data.embeddedPanel !== void 0 && (data.supportsSource === void 0 || data.supportsSource(previewSource))))?.data.embeddedPanel;
3925
3834
  useEffect(() => {
3926
- if (document === void 0 || sessionId === null) return;
3927
- const generation = focusAuthorDocument(sessionId, path, document.version, document.sourceSha256);
3928
- focusGeneration.current = generation;
3835
+ if (sessionId === null) return;
3836
+ const generation = focusAuthorDocument(sessionId, path);
3929
3837
  return () => releaseAuthorDocumentFocus(sessionId, generation);
3930
- }, [
3931
- kind,
3932
- document?.sourceSha256,
3933
- path,
3934
- sessionId
3935
- ]);
3936
- useEffect(() => {
3937
- const generation = focusGeneration.current;
3938
- if (document === void 0 || sessionId === null || generation === void 0) return;
3939
- syncAuthorDocumentFocus(sessionId, generation, document.version, document.sourceSha256);
3940
- }, [
3941
- document?.sourceSha256,
3942
- document?.version,
3943
- sessionId
3944
- ]);
3838
+ }, [path, sessionId]);
3945
3839
  useEffect(() => {
3946
3840
  if (kind === void 0 || sessionId === null || alias === void 0) return;
3947
3841
  const profiles = authorProfilesForDocument(sessionId, path, kind);
@@ -3980,8 +3874,7 @@ function ActiveAuthorDocumentPanel(props) {
3980
3874
  }
3981
3875
  };
3982
3876
  const gridVisible = autonomousVoiceGridVisible(statuses);
3983
- const focusedWorkspace = workspace?.focusedDocument?.path === document.path ? workspace : void 0;
3984
- const displayedRegions = displayedAuthorRegions(focusedWorkspace);
3877
+ const displayedRegions = displayedAuthorRegions(drafts);
3985
3878
  const displayedPreviewAnnotations = displayedRegions.flatMap(({ ordinal, region }) => {
3986
3879
  if (region.anchor.kind === "story-preview-rect") return [{
3987
3880
  ordinal,
@@ -4012,7 +3905,7 @@ function ActiveAuthorDocumentPanel(props) {
4012
3905
  document,
4013
3906
  activeTool,
4014
3907
  displayedRegions,
4015
- pendingCandidate: focusedWorkspace?.candidate !== void 0,
3908
+ pendingCandidate: drafts.candidate !== void 0,
4016
3909
  seekRequest: workspace?.videoSeekRequest
4017
3910
  }, document.path);
4018
3911
  return /* @__PURE__ */ jsxs("section", {
@@ -4079,7 +3972,7 @@ function ActiveAuthorDocumentPanel(props) {
4079
3972
  className: "min-h-11 min-w-11 shrink-0",
4080
3973
  "aria-label": `${mode} tool`,
4081
3974
  "aria-pressed": activeTool === mode,
4082
- onClick: () => setAuthorToolMode(sessionId, mode),
3975
+ onClick: () => setAuthorToolMode(sessionId, document.path, mode),
4083
3976
  children: mode
4084
3977
  }, mode))
4085
3978
  }) : null,
@@ -4090,10 +3983,10 @@ function ActiveAuthorDocumentPanel(props) {
4090
3983
  source: previewSource,
4091
3984
  activeTool: activeTool === "crop" ? "select" : activeTool,
4092
3985
  displayedAnnotations: displayedPreviewAnnotations,
4093
- pendingCandidate: focusedWorkspace?.candidate !== void 0,
3986
+ pendingCandidate: drafts.candidate !== void 0,
4094
3987
  onAnnotationCandidate: (candidate) => {
4095
3988
  setAuthorStoryPreview(sessionId, document.path, candidate.preview);
4096
- setAuthorRegionCandidate(sessionId, {
3989
+ setAuthorRegionCandidate(sessionId, document.path, {
4097
3990
  documentPath: document.path,
4098
3991
  revision: document.version,
4099
3992
  sourceSha256: document.sourceSha256,
@@ -4120,7 +4013,7 @@ function ActiveAuthorDocumentPanel(props) {
4120
4013
  visible: gridVisible
4121
4014
  })]
4122
4015
  }),
4123
- focusedWorkspace !== void 0 && [
4016
+ [
4124
4017
  "image",
4125
4018
  "pdf",
4126
4019
  "video",
@@ -4130,7 +4023,7 @@ function ActiveAuthorDocumentPanel(props) {
4130
4023
  children: /* @__PURE__ */ jsx(AuthorFeedbackControls, {
4131
4024
  sessionId,
4132
4025
  document,
4133
- workspace: focusedWorkspace,
4026
+ drafts,
4134
4027
  submitCapture: props.submitCapture
4135
4028
  })
4136
4029
  }) : null
@@ -4153,7 +4046,7 @@ function authorFileTab(path, preferredAlias) {
4153
4046
  source: "author",
4154
4047
  id: documentPath,
4155
4048
  label: alias === void 0 ? name : `${alias} · ${name}`,
4156
- content: `Author document: ${documentPath}${alias === void 0 ? "" : ` (canvas ${alias})`}`
4049
+ content: authorDocumentContextContent(documentPath, alias, authorDocumentAnnotations(sessionId, documentPath).annotations)
4157
4050
  };
4158
4051
  },
4159
4052
  onOpen(sessionId) {
@@ -4214,6 +4107,7 @@ function authorFileTab(path, preferredAlias) {
4214
4107
  },
4215
4108
  onClose(sessionId) {
4216
4109
  const key = authorDocumentKey(sessionId, normalized);
4110
+ setAuthorToolMode(sessionId, canvasPaths.state[key] ?? normalized, "select");
4217
4111
  pendingCanvases.get(key)?.abort();
4218
4112
  pendingCanvases.delete(key);
4219
4113
  const alias = canvasAliases.state[key] ?? preferredAlias;
@@ -4494,7 +4388,7 @@ function recordAuthorComposerSubmission(submission) {
4494
4388
  revision: packet.document.revision,
4495
4389
  sourceSha256: packet.document.sourceSha256
4496
4390
  });
4497
- for (const region of packet.regions) removeAuthorRegion(submission.sessionId, region.id, region.version ?? 1, packet.document.path);
4391
+ for (const region of packet.regions) removeAuthorRegion(submission.sessionId, packet.document.path, region.id, region.version ?? 1);
4498
4392
  }
4499
4393
  }
4500
4394
  /** Only the host's correlated execution events may settle a submitted capture. */