@tutti-os/agent-gui 0.0.103 → 0.0.105

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.
Files changed (81) hide show
  1. package/dist/{AgentGUI-D6IQ0F_N.d.ts → AgentGUI-Do6py-T_.d.ts} +10 -6
  2. package/dist/AgentRichTextReadonly-F6PHC5SX.js +18 -0
  3. package/dist/AgentRichTextReadonly-F6PHC5SX.js.map +1 -0
  4. package/dist/agent-conversation/index.d.ts +3 -3
  5. package/dist/agent-conversation/index.js +11 -7
  6. package/dist/agent-conversation/index.js.map +1 -1
  7. package/dist/agent-gui.d.ts +4 -4
  8. package/dist/agent-gui.js +18 -14
  9. package/dist/agent-message-center/index.d.ts +1 -1
  10. package/dist/agent-message-center/index.js +13 -9
  11. package/dist/agent-message-center/index.js.map +1 -1
  12. package/dist/{agentConversationVM-BzHZhwFP.d.ts → agentConversationVM-Bf3Zv3iI.d.ts} +12 -2
  13. package/dist/{agentFileMentionContracts-58IjMU-u.d.ts → agentFileMentionContracts-B70VnPWO.d.ts} +2 -0
  14. package/dist/{agentGuiNodeTypes-8U3q_frv.d.ts → agentGuiNodeTypes-DbgQBiYz.d.ts} +4 -2
  15. package/dist/app/renderer/agentactivity.css +99 -0
  16. package/dist/{chunk-SGGGE2F3.js → chunk-4ZWV57MF.js} +42 -10
  17. package/dist/chunk-4ZWV57MF.js.map +1 -0
  18. package/dist/{chunk-XZD5KTM4.js → chunk-6R7GHXRQ.js} +12 -6
  19. package/dist/chunk-6R7GHXRQ.js.map +1 -0
  20. package/dist/{chunk-UHOVZI6B.js → chunk-7MPN2JGL.js} +122 -154
  21. package/dist/chunk-7MPN2JGL.js.map +1 -0
  22. package/dist/{chunk-5X7YDOC6.js → chunk-D2JUDUYY.js} +1 -1
  23. package/dist/chunk-D2JUDUYY.js.map +1 -0
  24. package/dist/{chunk-IVY4OL7B.js → chunk-IR2CL2X2.js} +1119 -2178
  25. package/dist/chunk-IR2CL2X2.js.map +1 -0
  26. package/dist/{chunk-PCXBTG5X.js → chunk-J2HG7UCP.js} +46 -22
  27. package/dist/chunk-J2HG7UCP.js.map +1 -0
  28. package/dist/{chunk-WXMBD2O7.js → chunk-JG7HGKZL.js} +597 -63
  29. package/dist/chunk-JG7HGKZL.js.map +1 -0
  30. package/dist/chunk-KPMQGPYU.js +43 -0
  31. package/dist/chunk-KPMQGPYU.js.map +1 -0
  32. package/dist/{chunk-6PMLIVTI.js → chunk-LDZ6C3YV.js} +3 -39
  33. package/dist/chunk-LDZ6C3YV.js.map +1 -0
  34. package/dist/{chunk-L2MTZMVH.js → chunk-N3HTEYLZ.js} +1985 -1315
  35. package/dist/chunk-N3HTEYLZ.js.map +1 -0
  36. package/dist/{chunk-3ZBDWWCV.js → chunk-N4WVVCNI.js} +2 -2
  37. package/dist/{chunk-IBFGOAY3.js → chunk-OWW7CU4U.js} +2 -2
  38. package/dist/chunk-SN6UYX54.js +42 -0
  39. package/dist/chunk-SN6UYX54.js.map +1 -0
  40. package/dist/{chunk-RGG5UGJD.js → chunk-TKBEVCHG.js} +5 -5
  41. package/dist/chunk-TKBEVCHG.js.map +1 -0
  42. package/dist/chunk-UFIEUC3Y.js +755 -0
  43. package/dist/chunk-UFIEUC3Y.js.map +1 -0
  44. package/dist/{chunk-5Z4ZXXX4.js → chunk-V5ROOS2O.js} +124 -2
  45. package/dist/chunk-V5ROOS2O.js.map +1 -0
  46. package/dist/chunk-XJ34OIEQ.js +18 -0
  47. package/dist/chunk-XJ34OIEQ.js.map +1 -0
  48. package/dist/{chunk-ZRJS4MOQ.js → chunk-ZSJBCZUH.js} +54 -7
  49. package/dist/chunk-ZSJBCZUH.js.map +1 -0
  50. package/dist/context-mention-palette/index.d.ts +1 -1
  51. package/dist/context-mention-palette/index.js +10 -8
  52. package/dist/{contribution-CTVBPN0R.d.ts → contribution-C6K5YfJ7.d.ts} +1 -0
  53. package/dist/custom-mention.d.ts +6 -0
  54. package/dist/custom-mention.js +1 -1
  55. package/dist/i18n/index.d.ts +4 -4
  56. package/dist/i18n/index.js +2 -2
  57. package/dist/index.d.ts +6 -6
  58. package/dist/index.js +18 -14
  59. package/dist/index.js.map +1 -1
  60. package/dist/mention-search.d.ts +42 -6
  61. package/dist/mention-search.js +8 -6
  62. package/dist/workbench/contribution.d.ts +1 -1
  63. package/dist/workbench/contribution.js +3 -3
  64. package/dist/workbench/index.d.ts +3 -2
  65. package/dist/workbench/index.js +3 -3
  66. package/dist/workbench/sessionTitle.js +2 -2
  67. package/package.json +14 -14
  68. package/dist/chunk-5X7YDOC6.js.map +0 -1
  69. package/dist/chunk-5Z4ZXXX4.js.map +0 -1
  70. package/dist/chunk-6PMLIVTI.js.map +0 -1
  71. package/dist/chunk-IVY4OL7B.js.map +0 -1
  72. package/dist/chunk-L2MTZMVH.js.map +0 -1
  73. package/dist/chunk-PCXBTG5X.js.map +0 -1
  74. package/dist/chunk-RGG5UGJD.js.map +0 -1
  75. package/dist/chunk-SGGGE2F3.js.map +0 -1
  76. package/dist/chunk-UHOVZI6B.js.map +0 -1
  77. package/dist/chunk-WXMBD2O7.js.map +0 -1
  78. package/dist/chunk-XZD5KTM4.js.map +0 -1
  79. package/dist/chunk-ZRJS4MOQ.js.map +0 -1
  80. /package/dist/{chunk-3ZBDWWCV.js.map → chunk-N4WVVCNI.js.map} +0 -0
  81. /package/dist/{chunk-IBFGOAY3.js.map → chunk-OWW7CU4U.js.map} +0 -0
@@ -3,9 +3,11 @@ import {
3
3
  workspaceAgentSessionMessageAliases
4
4
  } from "./chunk-4YCCATI4.js";
5
5
  import {
6
- isWorkspaceAgentSyntheticControlMessage,
6
+ isWorkspaceAgentSyntheticControlMessage
7
+ } from "./chunk-XJ34OIEQ.js";
8
+ import {
7
9
  normalizeAgentSessionMentionTitle
8
- } from "./chunk-PCXBTG5X.js";
10
+ } from "./chunk-J2HG7UCP.js";
9
11
  import {
10
12
  resolveAgentMentionFileThumbnailUrl
11
13
  } from "./chunk-LUGELG5V.js";
@@ -18,17 +20,20 @@ import {
18
20
  import {
19
21
  getOptionalAgentHostApi,
20
22
  workspaceAgentProviderLabel
21
- } from "./chunk-6PMLIVTI.js";
23
+ } from "./chunk-LDZ6C3YV.js";
22
24
  import {
23
25
  normalizeAgentTitleText
24
26
  } from "./chunk-MIJXEELH.js";
25
27
  import {
26
28
  translate,
27
29
  translateInUiLanguage
28
- } from "./chunk-IBFGOAY3.js";
30
+ } from "./chunk-OWW7CU4U.js";
29
31
 
30
32
  // agent-gui/agentGuiNode/AgentMentionLabels.ts
31
33
  function agentMentionGroupLabel(groupId) {
34
+ if (groupId.startsWith("issue-topic:")) {
35
+ return "";
36
+ }
32
37
  switch (groupId) {
33
38
  case "apps":
34
39
  return translate("agentHost.agentGui.mentionGroupApps");
@@ -46,6 +51,8 @@ function agentMentionGroupLabel(groupId) {
46
51
  return translate("agentHost.agentGui.mentionGroupCollabSessions");
47
52
  case "issues":
48
53
  return translate("agentHost.agentGui.mentionGroupIssues");
54
+ default:
55
+ return "";
49
56
  }
50
57
  }
51
58
  function agentMentionFilterLabel(filter) {
@@ -63,6 +70,9 @@ function agentMentionFilterLabel(filter) {
63
70
  }
64
71
  }
65
72
  function agentMentionEmptyGroupLabel(groupId, query) {
73
+ if (groupId.startsWith("issue-topic:")) {
74
+ return "";
75
+ }
66
76
  if (groupId === "files" || groupId === "opened_files") {
67
77
  return query.trim() ? translate("agentHost.agentGui.mentionNoMatchingFiles") : translate("agentHost.agentGui.mentionEmptyDockFiles");
68
78
  }
@@ -85,7 +95,7 @@ function agentMentionEmptyGroupLabel(groupId, query) {
85
95
  }
86
96
 
87
97
  // shared/workspaceAgentActivityListProjection.ts
88
- import { selectCanonicalAgentActivitySessions } from "@tutti-os/agent-activity-core";
98
+ import { selectRootAgentActivitySessions } from "@tutti-os/agent-activity-core";
89
99
 
90
100
  // shared/workspaceAgentActivityStatus.ts
91
101
  function resolveWorkspaceAgentActivityStatus(session) {
@@ -262,7 +272,7 @@ function compareActivities(left, right) {
262
272
 
263
273
  // shared/workspaceAgentActivityListProjection.ts
264
274
  function buildWorkspaceAgentActivityListViewModel(snapshot, options = {}) {
265
- const activities = selectCanonicalAgentActivitySessions(snapshot).map((session) => {
275
+ const activities = selectRootAgentActivitySessions(snapshot).map((session) => {
266
276
  const presence = snapshot.presences.find(
267
277
  (candidate) => candidate.provider === session.provider && Boolean(candidate.userId) && candidate.userId === session.userId
268
278
  ) ?? null;
@@ -414,6 +424,9 @@ function groupIdsForFilter(filter) {
414
424
  }
415
425
  }
416
426
  function shouldShowEmptyGroup(groupId, filter, query) {
427
+ if (groupId.startsWith("issue-topic:")) {
428
+ return false;
429
+ }
417
430
  const hasQuery = query.trim().length > 0;
418
431
  if (groupId === "files") {
419
432
  return false;
@@ -449,12 +462,18 @@ function emptyGroupLabel(groupId, query) {
449
462
  return agentMentionEmptyGroupLabel(groupId, query);
450
463
  }
451
464
  function resolveMentionGroupItems(groupId, rawGroups) {
465
+ if (groupId.startsWith("issue-topic:")) {
466
+ return [];
467
+ }
452
468
  if (groupId === "files") {
453
469
  return [...rawGroups.opened_files, ...rawGroups.agent_generated_files];
454
470
  }
455
471
  return rawGroups[groupId] ?? [];
456
472
  }
457
473
  function resolveMentionGroupTotalCount(groupId, totalCounts, itemCount) {
474
+ if (groupId.startsWith("issue-topic:")) {
475
+ return itemCount;
476
+ }
458
477
  if (groupId === "files") {
459
478
  return (totalCounts.opened_files ?? 0) + (totalCounts.agent_generated_files ?? 0);
460
479
  }
@@ -602,6 +621,17 @@ function agentGeneratedMentionItemKey(item) {
602
621
 
603
622
  // agent-gui/agentGuiNode/AgentMentionSearchModel.ts
604
623
  function buildAgentMentionGroups(input) {
624
+ if (input.currentFilter === "issue" && input.issueTopicGroups !== null) {
625
+ return input.issueTopicGroups.map((group) => ({
626
+ id: group.id,
627
+ label: group.label,
628
+ items: group.items,
629
+ totalCount: group.totalCount,
630
+ visibleCount: group.items.length,
631
+ hasMore: group.nextPageToken !== null,
632
+ expandStatus: group.loadMoreStatus
633
+ }));
634
+ }
605
635
  const orderedGroupIds = groupIdsForFilter(input.currentFilter);
606
636
  return orderedGroupIds.map((groupId) => {
607
637
  const rawItems = resolveMentionGroupItems(groupId, input.rawGroups);
@@ -636,6 +666,33 @@ function buildAgentMentionGroups(input) {
636
666
  };
637
667
  }).filter((group) => group !== null);
638
668
  }
669
+ function cloneAgentMentionIssueTopicGroups(groups) {
670
+ return groups?.map((group) => ({ ...group, items: [...group.items] })) ?? null;
671
+ }
672
+ function issueTopicPaginationChanges(groupsAtStart, currentGroups) {
673
+ if (!groupsAtStart || !currentGroups) {
674
+ return [];
675
+ }
676
+ const startingGroups = new Map(
677
+ groupsAtStart.map((group) => [group.id, group])
678
+ );
679
+ return currentGroups.flatMap((group) => {
680
+ const startingGroup = startingGroups.get(group.id);
681
+ if (!startingGroup) {
682
+ return [];
683
+ }
684
+ const startingIssueIds = new Set(
685
+ startingGroup.items.filter((item) => item.kind === "workspace-issue").map((item) => item.targetId)
686
+ );
687
+ const appendedItems = group.items.filter(
688
+ (item) => item.kind !== "workspace-issue" || !startingIssueIds.has(item.targetId)
689
+ );
690
+ if (appendedItems.length === 0 && group.nextPageToken === startingGroup.nextPageToken) {
691
+ return [];
692
+ }
693
+ return [{ ...group, items: appendedItems }];
694
+ });
695
+ }
639
696
  function emptyAgentMentionRawGroups() {
640
697
  return {
641
698
  apps: [],
@@ -899,6 +956,51 @@ function writeBrowseCacheEntry(cacheKey, entry) {
899
956
  sharedAgentMentionBrowseCache.delete(oldestKey);
900
957
  }
901
958
  }
959
+ function mergeAgentMentionBrowseIssueGroupPage(input) {
960
+ const entry = sharedAgentMentionBrowseCache.get(input.cacheKey);
961
+ if (!entry?.issueTopicGroups) {
962
+ return;
963
+ }
964
+ const groupIndex = entry.issueTopicGroups.findIndex(
965
+ (group) => group.id === input.group.id
966
+ );
967
+ if (groupIndex < 0) {
968
+ return;
969
+ }
970
+ const previous = entry.issueTopicGroups[groupIndex];
971
+ if (!previous) {
972
+ return;
973
+ }
974
+ const seen = new Set(
975
+ previous.items.filter((item) => item.kind === "workspace-issue").map((item) => item.targetId)
976
+ );
977
+ const appended = input.group.items.filter((item) => {
978
+ if (item.kind !== "workspace-issue") {
979
+ return true;
980
+ }
981
+ if (seen.has(item.targetId)) {
982
+ return false;
983
+ }
984
+ seen.add(item.targetId);
985
+ return true;
986
+ });
987
+ const mergedItems = [...previous.items, ...appended];
988
+ const groups = entry.issueTopicGroups.map(
989
+ (group, index) => index === groupIndex ? {
990
+ ...previous,
991
+ items: mergedItems,
992
+ totalCount: Math.max(input.group.totalCount, mergedItems.length),
993
+ nextPageToken: input.group.nextPageToken,
994
+ loadMoreStatus: "idle",
995
+ loadMoreError: null
996
+ } : group
997
+ );
998
+ writeBrowseCacheEntry(input.cacheKey, {
999
+ ...entry,
1000
+ issueTopicGroups: groups,
1001
+ cachedAt: input.cachedAt
1002
+ });
1003
+ }
902
1004
  function scheduleAgentMentionIdleTask(task) {
903
1005
  const scope = globalThis;
904
1006
  if (typeof scope.requestIdleCallback === "function") {
@@ -910,49 +1012,113 @@ function scheduleAgentMentionIdleTask(task) {
910
1012
  }
911
1013
  function resetAgentMentionSearchBrowseCacheForTests() {
912
1014
  sharedAgentMentionBrowseCache.clear();
1015
+ for (const fetch of sharedAgentMentionBrowseFetches.values()) {
1016
+ fetch.abortController.abort();
1017
+ }
913
1018
  sharedAgentMentionBrowseFetches.clear();
914
1019
  }
915
1020
  globalThis.__tuttiResetAgentMentionSearchBrowseCacheForTests = resetAgentMentionSearchBrowseCacheForTests;
916
1021
  async function loadAgentMentionBrowseFetchResult(input) {
917
1022
  const { cacheKey, reason } = input;
918
1023
  const browseInput = input.input;
919
- const existingFetch = sharedAgentMentionBrowseFetches.get(cacheKey);
920
- if (existingFetch) {
1024
+ let sharedFetch = sharedAgentMentionBrowseFetches.get(cacheKey);
1025
+ if (sharedFetch) {
921
1026
  input.logLifecycle("browse.fetch.dedupe", {
922
1027
  filter: browseInput.filter,
923
1028
  reason,
924
1029
  workspaceId: browseInput.workspaceId
925
1030
  });
926
- return existingFetch;
927
- }
928
- const startedAt = input.diagnosticNow();
929
- input.logLifecycle("browse.fetch.start", {
930
- filter: browseInput.filter,
931
- providerIds: input.providerIds,
932
- reason,
933
- workspaceId: browseInput.workspaceId
934
- });
935
- const fetchPromise = input.fetchBrowseResult().then((result) => {
936
- writeBrowseCacheEntry(cacheKey, {
937
- ...result,
938
- cachedAt: input.diagnosticNow()
939
- });
940
- input.logLifecycle("browse.fetch.success", {
941
- durationMs: elapsedDiagnosticMs(input.diagnosticNow(), startedAt),
1031
+ } else {
1032
+ const startedAt = input.diagnosticNow();
1033
+ input.logLifecycle("browse.fetch.start", {
942
1034
  filter: browseInput.filter,
943
- itemCount: rawGroupItemCount(result.rawGroups),
944
- providerResults: providerDiagnosticsSummary(result.providerDiagnostics),
1035
+ providerIds: input.providerIds,
945
1036
  reason,
946
1037
  workspaceId: browseInput.workspaceId
947
1038
  });
948
- return result;
949
- }).finally(() => {
950
- if (sharedAgentMentionBrowseFetches.get(cacheKey) === fetchPromise) {
951
- sharedAgentMentionBrowseFetches.delete(cacheKey);
1039
+ const abortController = new AbortController();
1040
+ sharedFetch = {
1041
+ abortController,
1042
+ consumers: /* @__PURE__ */ new Set(),
1043
+ promise: null,
1044
+ settled: false
1045
+ };
1046
+ const entry = sharedFetch;
1047
+ entry.promise = input.fetchBrowseResult(abortController.signal).then((result) => {
1048
+ if (abortController.signal.aborted) {
1049
+ const error = new Error("Mention browse request aborted");
1050
+ error.name = "AbortError";
1051
+ throw error;
1052
+ }
1053
+ writeBrowseCacheEntry(cacheKey, {
1054
+ ...result,
1055
+ cachedAt: input.diagnosticNow()
1056
+ });
1057
+ input.logLifecycle("browse.fetch.success", {
1058
+ durationMs: elapsedDiagnosticMs(input.diagnosticNow(), startedAt),
1059
+ filter: browseInput.filter,
1060
+ itemCount: rawGroupItemCount(result.rawGroups),
1061
+ providerResults: providerDiagnosticsSummary(
1062
+ result.providerDiagnostics
1063
+ ),
1064
+ reason,
1065
+ workspaceId: browseInput.workspaceId
1066
+ });
1067
+ return result;
1068
+ }).finally(() => {
1069
+ entry.settled = true;
1070
+ if (sharedAgentMentionBrowseFetches.get(cacheKey) === entry) {
1071
+ sharedAgentMentionBrowseFetches.delete(cacheKey);
1072
+ }
1073
+ });
1074
+ sharedAgentMentionBrowseFetches.set(cacheKey, entry);
1075
+ }
1076
+ return consumeSharedBrowseFetch({
1077
+ abortSignal: input.abortSignal,
1078
+ cacheKey,
1079
+ sharedFetch
1080
+ });
1081
+ }
1082
+ function consumeSharedBrowseFetch(input) {
1083
+ const consumer = Symbol(input.cacheKey);
1084
+ input.sharedFetch.consumers.add(consumer);
1085
+ const sharedPromise = input.sharedFetch.promise;
1086
+ if (!sharedPromise) {
1087
+ input.sharedFetch.consumers.delete(consumer);
1088
+ return Promise.reject(new Error("Mention browse request was not started"));
1089
+ }
1090
+ return new Promise((resolve, reject) => {
1091
+ let finished = false;
1092
+ const finish = (settle, abortWhenUnused) => {
1093
+ if (finished) {
1094
+ return;
1095
+ }
1096
+ finished = true;
1097
+ input.abortSignal?.removeEventListener("abort", onAbort);
1098
+ input.sharedFetch.consumers.delete(consumer);
1099
+ if (abortWhenUnused && !input.sharedFetch.settled && input.sharedFetch.consumers.size === 0) {
1100
+ if (sharedAgentMentionBrowseFetches.get(input.cacheKey) === input.sharedFetch) {
1101
+ sharedAgentMentionBrowseFetches.delete(input.cacheKey);
1102
+ }
1103
+ input.sharedFetch.abortController.abort();
1104
+ }
1105
+ settle();
1106
+ };
1107
+ const onAbort = () => {
1108
+ const error = new Error("Mention browse request aborted");
1109
+ error.name = "AbortError";
1110
+ finish(() => reject(error), true);
1111
+ };
1112
+ if (input.abortSignal?.aborted) {
1113
+ onAbort();
1114
+ return;
952
1115
  }
1116
+ input.abortSignal?.addEventListener("abort", onAbort, { once: true });
1117
+ sharedPromise.then(
1118
+ (result) => finish(() => resolve(result), false),
1119
+ (error) => finish(() => reject(error), false)
1120
+ );
953
1121
  });
954
- sharedAgentMentionBrowseFetches.set(cacheKey, fetchPromise);
955
- return fetchPromise;
956
1122
  }
957
1123
  function readAgentMentionBrowseCache(input) {
958
1124
  const entry = sharedAgentMentionBrowseCache.get(input.cacheKey);
@@ -1042,6 +1208,7 @@ async function queryAgentMentionProviderWithDiagnostics(input) {
1042
1208
  const startedAt = input.diagnosticNow();
1043
1209
  try {
1044
1210
  const { result, timedOut } = await runAgentMentionProviderQuery({
1211
+ abortSignal: input.abortSignal,
1045
1212
  fallback: input.fallback,
1046
1213
  providerTimeoutMs: input.providerTimeoutMs,
1047
1214
  query: input.query
@@ -1055,8 +1222,16 @@ async function queryAgentMentionProviderWithDiagnostics(input) {
1055
1222
  resultCount: input.resultCount(result),
1056
1223
  status: timedOut ? "timeout" : "success"
1057
1224
  });
1225
+ if (timedOut && input.throwOnTimeout) {
1226
+ const error = new Error("Mention provider query timed out.");
1227
+ error.name = "TimeoutError";
1228
+ throw error;
1229
+ }
1058
1230
  return result;
1059
1231
  } catch (error) {
1232
+ if (error instanceof Error && error.name === "TimeoutError" && input.diagnostics.at(-1)?.providerId === input.providerId && input.diagnostics.at(-1)?.status === "timeout") {
1233
+ throw error;
1234
+ }
1060
1235
  input.diagnostics.push({
1061
1236
  durationMs: elapsedAgentMentionSearchDiagnosticMs(
1062
1237
  input.diagnosticNow(),
@@ -1102,6 +1277,14 @@ function providerDiagnosticOrder(providerId) {
1102
1277
  }
1103
1278
  async function runAgentMentionProviderQuery(input) {
1104
1279
  const abortController = new AbortController();
1280
+ const abortFromParent = () => abortController.abort();
1281
+ if (input.abortSignal?.aborted) {
1282
+ abortController.abort();
1283
+ } else {
1284
+ input.abortSignal?.addEventListener("abort", abortFromParent, {
1285
+ once: true
1286
+ });
1287
+ }
1105
1288
  let timedOut = false;
1106
1289
  const queryPromise = Promise.resolve().then(
1107
1290
  () => input.query(abortController.signal)
@@ -1116,7 +1299,11 @@ async function runAgentMentionProviderQuery(input) {
1116
1299
  }
1117
1300
  );
1118
1301
  if (input.providerTimeoutMs <= 0 || !Number.isFinite(input.providerTimeoutMs)) {
1119
- return queryResultPromise;
1302
+ try {
1303
+ return await queryResultPromise;
1304
+ } finally {
1305
+ input.abortSignal?.removeEventListener("abort", abortFromParent);
1306
+ }
1120
1307
  }
1121
1308
  let timeout = null;
1122
1309
  const timeoutPromise = new Promise(
@@ -1131,6 +1318,7 @@ async function runAgentMentionProviderQuery(input) {
1131
1318
  try {
1132
1319
  return await Promise.race([queryResultPromise, timeoutPromise]);
1133
1320
  } finally {
1321
+ input.abortSignal?.removeEventListener("abort", abortFromParent);
1134
1322
  if (timeout !== null) {
1135
1323
  clearTimeout(timeout);
1136
1324
  }
@@ -1178,7 +1366,8 @@ async function fetchAgentMentionFilterResult(input) {
1178
1366
  return {
1179
1367
  providerDiagnostics,
1180
1368
  rawGroups,
1181
- totalCounts: totalCountsFromRawGroups(rawGroups)
1369
+ totalCounts: totalCountsFromRawGroups(rawGroups),
1370
+ issueTopicGroups: null
1182
1371
  };
1183
1372
  }
1184
1373
  case "session": {
@@ -1200,11 +1389,12 @@ async function fetchAgentMentionFilterResult(input) {
1200
1389
  return {
1201
1390
  providerDiagnostics,
1202
1391
  rawGroups,
1203
- totalCounts: totalCountsFromRawGroups(rawGroups)
1392
+ totalCounts: totalCountsFromRawGroups(rawGroups),
1393
+ issueTopicGroups: null
1204
1394
  };
1205
1395
  }
1206
1396
  case "issue": {
1207
- const issueItems = provenanceFilterActive ? [] : await input.queryProviderMentionItemsById({
1397
+ const queryInput = {
1208
1398
  providerId: WORKSPACE_ISSUE_PROVIDER_ID,
1209
1399
  workspaceId: input.workspaceId,
1210
1400
  currentUserId: input.currentUserId,
@@ -1213,7 +1403,9 @@ async function fetchAgentMentionFilterResult(input) {
1213
1403
  sessionCwd: input.sessionCwd,
1214
1404
  diagnostics: providerDiagnostics,
1215
1405
  provenanceFilter: input.provenanceFilter
1216
- });
1406
+ };
1407
+ const issueTopicGroups = provenanceFilterActive ? [] : input.queryProviderMentionGroupsById ? await input.queryProviderMentionGroupsById(queryInput) : null;
1408
+ const issueItems = provenanceFilterActive ? [] : issueTopicGroups === null ? await input.queryProviderMentionItemsById(queryInput) : [];
1217
1409
  const rawGroups = emptyAgentMentionRawGroups();
1218
1410
  rawGroups.issues = issueItems.filter(
1219
1411
  (item) => item.kind === "workspace-issue"
@@ -1221,7 +1413,8 @@ async function fetchAgentMentionFilterResult(input) {
1221
1413
  return {
1222
1414
  providerDiagnostics,
1223
1415
  rawGroups,
1224
- totalCounts: totalCountsFromRawGroups(rawGroups)
1416
+ totalCounts: totalCountsFromRawGroups(rawGroups),
1417
+ issueTopicGroups
1225
1418
  };
1226
1419
  }
1227
1420
  case "agent": {
@@ -1241,7 +1434,8 @@ async function fetchAgentMentionFilterResult(input) {
1241
1434
  return {
1242
1435
  providerDiagnostics,
1243
1436
  rawGroups,
1244
- totalCounts: totalCountsFromRawGroups(rawGroups)
1437
+ totalCounts: totalCountsFromRawGroups(rawGroups),
1438
+ issueTopicGroups: null
1245
1439
  };
1246
1440
  }
1247
1441
  case "app": {
@@ -1259,7 +1453,8 @@ async function fetchAgentMentionFilterResult(input) {
1259
1453
  return {
1260
1454
  providerDiagnostics,
1261
1455
  rawGroups,
1262
- totalCounts: totalCountsFromRawGroups(rawGroups)
1456
+ totalCounts: totalCountsFromRawGroups(rawGroups),
1457
+ issueTopicGroups: null
1263
1458
  };
1264
1459
  }
1265
1460
  }
@@ -1283,8 +1478,111 @@ async function queryAgentMentionProviderItems(input) {
1283
1478
  if (input.abortSignal.aborted) {
1284
1479
  return [];
1285
1480
  }
1481
+ return mapProviderItemsToAgentMentionItems({
1482
+ ...input,
1483
+ items
1484
+ });
1485
+ }
1486
+ async function queryAgentMentionProviderGroups(input) {
1487
+ if (!input.provider.queryGroups) {
1488
+ return null;
1489
+ }
1490
+ const result = await input.provider.queryGroups({
1491
+ keyword: input.query,
1492
+ maxResults: input.limit,
1493
+ abortSignal: input.abortSignal,
1494
+ trigger: "@",
1495
+ context: {
1496
+ metadata: {
1497
+ currentUserId: input.currentUserId,
1498
+ sessionCwd: input.sessionCwd || void 0,
1499
+ target: "agent-gui",
1500
+ workspaceId: input.workspaceId,
1501
+ referenceProvenanceFilter: input.provenanceFilter ?? void 0
1502
+ }
1503
+ }
1504
+ });
1505
+ if (input.abortSignal.aborted) {
1506
+ return [];
1507
+ }
1508
+ return Promise.all(
1509
+ result.groups.map(async (group) => {
1510
+ const items = await mapProviderItemsToAgentMentionItems({
1511
+ ...input,
1512
+ items: group.items
1513
+ });
1514
+ const uniqueItems = dedupeWorkspaceIssueMentionItems(items);
1515
+ return {
1516
+ id: agentMentionIssueTopicGroupId(group.id),
1517
+ providerGroupId: group.id,
1518
+ label: group.label,
1519
+ items: uniqueItems,
1520
+ totalCount: Math.max(group.totalCount, uniqueItems.length),
1521
+ nextPageToken: group.nextCursor ?? null,
1522
+ loadMoreStatus: "idle",
1523
+ loadMoreError: null
1524
+ };
1525
+ })
1526
+ );
1527
+ }
1528
+ async function queryAgentMentionProviderGroupPage(input) {
1529
+ if (!input.provider.queryGroupPage) {
1530
+ throw new Error("Mention provider does not support grouped pagination.");
1531
+ }
1532
+ const group = await input.provider.queryGroupPage({
1533
+ groupId: input.providerGroupId,
1534
+ cursor: input.cursor,
1535
+ pageSize: input.pageSize,
1536
+ keyword: input.query,
1537
+ maxResults: input.pageSize,
1538
+ abortSignal: input.abortSignal,
1539
+ trigger: "@",
1540
+ context: {
1541
+ metadata: {
1542
+ currentUserId: input.currentUserId,
1543
+ sessionCwd: input.sessionCwd || void 0,
1544
+ target: "agent-gui",
1545
+ workspaceId: input.workspaceId,
1546
+ referenceProvenanceFilter: input.provenanceFilter ?? void 0
1547
+ }
1548
+ }
1549
+ });
1550
+ const items = await mapProviderItemsToAgentMentionItems({
1551
+ ...input,
1552
+ provider: input.provider,
1553
+ items: group.items
1554
+ });
1555
+ const uniqueItems = dedupeWorkspaceIssueMentionItems(items);
1556
+ return {
1557
+ id: agentMentionIssueTopicGroupId(input.providerGroupId),
1558
+ providerGroupId: input.providerGroupId,
1559
+ label: group.label,
1560
+ items: uniqueItems,
1561
+ totalCount: Math.max(group.totalCount, uniqueItems.length),
1562
+ nextPageToken: group.nextCursor ?? null,
1563
+ loadMoreStatus: "idle",
1564
+ loadMoreError: null
1565
+ };
1566
+ }
1567
+ function agentMentionIssueTopicGroupId(topicId) {
1568
+ return `issue-topic:${encodeURIComponent(topicId)}`;
1569
+ }
1570
+ function dedupeWorkspaceIssueMentionItems(items) {
1571
+ const issueIds = /* @__PURE__ */ new Set();
1572
+ return items.filter((item) => {
1573
+ if (item.kind !== "workspace-issue") {
1574
+ return true;
1575
+ }
1576
+ if (issueIds.has(item.targetId)) {
1577
+ return false;
1578
+ }
1579
+ issueIds.add(item.targetId);
1580
+ return true;
1581
+ });
1582
+ }
1583
+ async function mapProviderItemsToAgentMentionItems(input) {
1286
1584
  const mentionItems = await Promise.all(
1287
- items.map(async (item) => {
1585
+ input.items.map(async (item) => {
1288
1586
  const mentionItem = providerItemToAgentMentionItem({
1289
1587
  currentUserId: input.currentUserId,
1290
1588
  insertResult: input.provider.toInsertResult(item),
@@ -1351,6 +1649,7 @@ var AgentMentionSearchControllerBase = class {
1351
1649
  preloadCancel = null;
1352
1650
  pendingPreloadKey = null;
1353
1651
  requestId = 0;
1652
+ activeRequestAbortController = null;
1354
1653
  disposed = false;
1355
1654
  activeWorkspaceId = "";
1356
1655
  currentUserId = "";
@@ -1362,6 +1661,7 @@ var AgentMentionSearchControllerBase = class {
1362
1661
  currentIssueSearchLimit;
1363
1662
  agentGeneratedBrowsePath = null;
1364
1663
  rawGroups = emptyAgentMentionRawGroups();
1664
+ issueTopicGroups = null;
1365
1665
  state = {
1366
1666
  status: "idle",
1367
1667
  query: "",
@@ -1437,26 +1737,32 @@ var AgentMentionSearchControllerBase = class {
1437
1737
  this.resetTotalCounts();
1438
1738
  this.emitBrowseState("loading");
1439
1739
  }
1740
+ const abortSignal = this.beginActiveRequest();
1440
1741
  void this.runBrowseSearch({
1441
1742
  workspaceId: this.activeWorkspaceId,
1442
1743
  currentUserId: this.currentUserId,
1443
1744
  requestId,
1444
1745
  filter,
1445
- sessionCwd: this.currentSessionCwd
1746
+ sessionCwd: this.currentSessionCwd,
1747
+ abortSignal
1446
1748
  });
1447
1749
  }
1448
1750
  async runSearch(input) {
1449
1751
  const startedAt = this.diagnosticNow();
1450
1752
  let providerDiagnostics = [];
1451
1753
  try {
1452
- const result = await this.fetchFilterResult({
1453
- workspaceId: input.workspaceId,
1454
- currentUserId: input.currentUserId,
1455
- query: input.query,
1456
- filter: input.filter,
1457
- sessionCwd: this.currentSessionCwd,
1458
- includeAgentGeneratedFiles: false
1459
- });
1754
+ const result = await this.fetchFilterResult(
1755
+ {
1756
+ workspaceId: input.workspaceId,
1757
+ currentUserId: input.currentUserId,
1758
+ query: input.query,
1759
+ filter: input.filter,
1760
+ sessionCwd: input.sessionCwd,
1761
+ includeAgentGeneratedFiles: false
1762
+ },
1763
+ input.provenanceFilter,
1764
+ input.abortSignal
1765
+ );
1460
1766
  providerDiagnostics = result.providerDiagnostics;
1461
1767
  if (!this.canApply(
1462
1768
  input.requestId,
@@ -1525,12 +1831,16 @@ var AgentMentionSearchControllerBase = class {
1525
1831
  let providerDiagnostics = [];
1526
1832
  const provenanceFilter = this.currentProvenanceFilter;
1527
1833
  const cacheKey = this.browseCacheKey(input, provenanceFilter);
1834
+ const issueTopicGroupsAtStart = cloneAgentMentionIssueTopicGroups(
1835
+ this.issueTopicGroups
1836
+ );
1528
1837
  try {
1529
1838
  const result = await this.loadBrowseFetchResult(
1530
1839
  input,
1531
1840
  cacheKey,
1532
1841
  "open",
1533
- provenanceFilter
1842
+ provenanceFilter,
1843
+ input.abortSignal
1534
1844
  );
1535
1845
  providerDiagnostics = result.providerDiagnostics;
1536
1846
  if (!this.canApply(input.requestId, input.workspaceId, "", input.filter)) {
@@ -1542,7 +1852,19 @@ var AgentMentionSearchControllerBase = class {
1542
1852
  });
1543
1853
  return;
1544
1854
  }
1545
- this.applyBrowseFetchResult(result);
1855
+ const paginationChanges = issueTopicPaginationChanges(
1856
+ issueTopicGroupsAtStart,
1857
+ this.issueTopicGroups
1858
+ );
1859
+ for (const group of paginationChanges) {
1860
+ mergeAgentMentionBrowseIssueGroupPage({
1861
+ cacheKey,
1862
+ group,
1863
+ cachedAt: this.diagnosticNow()
1864
+ });
1865
+ }
1866
+ const resultToApply = paginationChanges.length > 0 ? this.readBrowseCache(cacheKey).entry ?? result : result;
1867
+ this.applyBrowseFetchResult(resultToApply);
1546
1868
  const groups = this.groupsFromRawGroups();
1547
1869
  this.setState({
1548
1870
  status: "ready",
@@ -1591,18 +1913,22 @@ var AgentMentionSearchControllerBase = class {
1591
1913
  });
1592
1914
  }
1593
1915
  }
1594
- async fetchBrowseResult(input, provenanceFilter = this.currentProvenanceFilter) {
1916
+ async fetchBrowseResult(input, provenanceFilter = this.currentProvenanceFilter, abortSignal) {
1595
1917
  return this.fetchFilterResult(
1596
1918
  {
1597
1919
  ...input,
1598
1920
  query: "",
1599
1921
  includeAgentGeneratedFiles: input.filter === "file"
1600
1922
  },
1601
- provenanceFilter
1923
+ provenanceFilter,
1924
+ abortSignal
1602
1925
  );
1603
1926
  }
1604
1927
  applyBrowseFetchResult(result) {
1605
1928
  this.rawGroups = cloneAgentMentionRawGroups(result.rawGroups);
1929
+ this.issueTopicGroups = cloneAgentMentionIssueTopicGroups(
1930
+ result.issueTopicGroups
1931
+ );
1606
1932
  this.resetTotalCounts();
1607
1933
  for (const [groupId, count] of Object.entries(result.totalCounts)) {
1608
1934
  this.totalCounts[groupId] = count;
@@ -1629,6 +1955,7 @@ var AgentMentionSearchControllerBase = class {
1629
1955
  const provider = this.contextMentionProviders.get(input.providerId);
1630
1956
  return queryAgentMentionProviderWithDiagnostics({
1631
1957
  diagnosticNow: this.diagnosticNow,
1958
+ abortSignal: input.abortSignal,
1632
1959
  diagnostics: input.diagnostics,
1633
1960
  fallback: [],
1634
1961
  providerId: input.providerId,
@@ -1646,6 +1973,32 @@ var AgentMentionSearchControllerBase = class {
1646
1973
  resultCount: (result) => result.length
1647
1974
  });
1648
1975
  }
1976
+ async queryProviderMentionGroupsById(input) {
1977
+ const provider = this.contextMentionProviders.get(input.providerId);
1978
+ if (!provider?.queryGroups) {
1979
+ return null;
1980
+ }
1981
+ return queryAgentMentionProviderWithDiagnostics({
1982
+ abortSignal: input.abortSignal,
1983
+ diagnosticNow: this.diagnosticNow,
1984
+ diagnostics: input.diagnostics,
1985
+ fallback: [],
1986
+ providerId: input.providerId,
1987
+ providerTimeoutMs: this.providerTimeoutMs,
1988
+ throwOnTimeout: true,
1989
+ query: (abortSignal) => queryAgentMentionProviderGroups({
1990
+ provider,
1991
+ workspaceId: input.workspaceId,
1992
+ currentUserId: input.currentUserId,
1993
+ query: input.query,
1994
+ limit: input.limit,
1995
+ sessionCwd: input.sessionCwd ?? this.currentSessionCwd,
1996
+ abortSignal,
1997
+ provenanceFilter: input.provenanceFilter
1998
+ }).then((groups) => groups ?? []),
1999
+ resultCount: (groups) => groups.reduce((count, group) => count + group.items.length, 0)
2000
+ });
2001
+ }
1649
2002
  logSearchDiagnostic(input) {
1650
2003
  emitAgentMentionSearchDiagnostic({
1651
2004
  debounceMs: this.debounceMs,
@@ -1708,6 +2061,7 @@ var AgentMentionSearchControllerBase = class {
1708
2061
  }
1709
2062
  resetRawGroups() {
1710
2063
  this.rawGroups = emptyAgentMentionRawGroups();
2064
+ this.issueTopicGroups = null;
1711
2065
  this.resetTotalCounts();
1712
2066
  }
1713
2067
  resetAgentGeneratedBrowsePath() {
@@ -1741,7 +2095,8 @@ var AgentMentionSearchControllerBase = class {
1741
2095
  currentQuery: this.currentQuery,
1742
2096
  expandedCounts: this.expandedCounts,
1743
2097
  rawGroups: this.rawGroups,
1744
- totalCounts: this.totalCounts
2098
+ totalCounts: this.totalCounts,
2099
+ issueTopicGroups: this.issueTopicGroups
1745
2100
  });
1746
2101
  }
1747
2102
  browseCacheKey(input, provenanceFilter = this.currentProvenanceFilter) {
@@ -1760,32 +2115,45 @@ var AgentMentionSearchControllerBase = class {
1760
2115
  diagnosticNow: this.diagnosticNow
1761
2116
  });
1762
2117
  }
1763
- loadBrowseFetchResult(input, cacheKey, reason, provenanceFilter = this.currentProvenanceFilter) {
2118
+ loadBrowseFetchResult(input, cacheKey, reason, provenanceFilter = this.currentProvenanceFilter, abortSignal) {
1764
2119
  return loadAgentMentionBrowseFetchResult({
1765
2120
  input,
1766
2121
  cacheKey,
1767
2122
  reason,
2123
+ abortSignal,
1768
2124
  diagnosticNow: this.diagnosticNow,
1769
2125
  providerIds: this.providerIdsForDiagnostics(),
1770
- fetchBrowseResult: () => this.fetchBrowseResult(input, provenanceFilter),
2126
+ fetchBrowseResult: (sharedAbortSignal) => this.fetchBrowseResult(input, provenanceFilter, sharedAbortSignal),
1771
2127
  logLifecycle: (event, details) => this.logLifecycle(event, details)
1772
2128
  });
1773
2129
  }
1774
- fetchFilterResult(input, provenanceFilter = this.currentProvenanceFilter) {
2130
+ fetchFilterResult(input, provenanceFilter = this.currentProvenanceFilter, abortSignal) {
1775
2131
  return fetchAgentMentionFilterResult({
1776
2132
  ...input,
1777
2133
  fileLimit: this.fileLimit,
1778
2134
  currentFileSearchLimit: this.currentFileSearchLimit,
1779
2135
  currentIssueSearchLimit: this.currentIssueSearchLimit,
1780
2136
  provenanceFilter,
1781
- queryProviderMentionItemsById: (queryInput) => this.queryProviderMentionItemsById(queryInput)
2137
+ queryProviderMentionGroupsById: (queryInput) => this.queryProviderMentionGroupsById({ ...queryInput, abortSignal }),
2138
+ queryProviderMentionItemsById: (queryInput) => this.queryProviderMentionItemsById({ ...queryInput, abortSignal })
1782
2139
  });
1783
2140
  }
2141
+ beginActiveRequest() {
2142
+ this.abortActiveRequest();
2143
+ const controller = new AbortController();
2144
+ this.activeRequestAbortController = controller;
2145
+ return controller.signal;
2146
+ }
2147
+ abortActiveRequest() {
2148
+ this.activeRequestAbortController?.abort();
2149
+ this.activeRequestAbortController = null;
2150
+ }
1784
2151
  };
1785
2152
 
1786
2153
  // agent-gui/agentGuiNode/AgentMentionSearchController.ts
1787
2154
  import { referenceProvenanceFilterCacheKey as referenceProvenanceFilterCacheKey2 } from "@tutti-os/workspace-file-reference/core";
1788
2155
  var AgentMentionSearchController = class extends AgentMentionSearchControllerBase {
2156
+ issueLoadMoreRequests = /* @__PURE__ */ new Map();
1789
2157
  setProvenanceFilter(filter) {
1790
2158
  const previousKey = this.currentProvenanceFilter ? referenceProvenanceFilterCacheKey2(this.currentProvenanceFilter) : "disabled";
1791
2159
  const nextKey = filter ? referenceProvenanceFilterCacheKey2(filter) : "disabled";
@@ -1815,6 +2183,8 @@ var AgentMentionSearchController = class extends AgentMentionSearchControllerBas
1815
2183
  this.currentSessionCwd = input.sessionCwd?.trim() ?? "";
1816
2184
  this.currentQuery = normalizeQuery(input.query);
1817
2185
  this.clearTimer();
2186
+ this.abortActiveRequest();
2187
+ this.cancelIssueLoadMoreRequests();
1818
2188
  const requestId = ++this.requestId;
1819
2189
  this.resetAgentGeneratedBrowsePath();
1820
2190
  this.resetExpandedCounts();
@@ -1845,13 +2215,17 @@ var AgentMentionSearchController = class extends AgentMentionSearchControllerBas
1845
2215
  groups: this.groupsFromRawGroups(),
1846
2216
  error: null
1847
2217
  });
2218
+ const abortSignal = this.beginActiveRequest();
1848
2219
  this.timer = this.scheduler.schedule(this.debounceMs, () => {
1849
2220
  void this.runSearch({
1850
2221
  workspaceId: this.activeWorkspaceId,
1851
2222
  currentUserId: this.currentUserId,
1852
2223
  query: this.currentQuery,
1853
2224
  requestId,
1854
- filter: this.currentFilter
2225
+ filter: this.currentFilter,
2226
+ provenanceFilter: this.currentProvenanceFilter,
2227
+ sessionCwd: this.currentSessionCwd,
2228
+ abortSignal
1855
2229
  });
1856
2230
  });
1857
2231
  }
@@ -1861,6 +2235,8 @@ var AgentMentionSearchController = class extends AgentMentionSearchControllerBas
1861
2235
  }
1862
2236
  this.currentFilter = filter;
1863
2237
  this.clearTimer();
2238
+ this.abortActiveRequest();
2239
+ this.cancelIssueLoadMoreRequests();
1864
2240
  const requestId = ++this.requestId;
1865
2241
  this.resetAgentGeneratedBrowsePath();
1866
2242
  this.resetExpandedCounts();
@@ -1891,12 +2267,16 @@ var AgentMentionSearchController = class extends AgentMentionSearchControllerBas
1891
2267
  groups: this.groupsFromRawGroups(),
1892
2268
  error: null
1893
2269
  });
2270
+ const abortSignal = this.beginActiveRequest();
1894
2271
  void this.runSearch({
1895
2272
  workspaceId: this.activeWorkspaceId,
1896
2273
  currentUserId: this.currentUserId,
1897
2274
  query: this.currentQuery,
1898
2275
  requestId,
1899
- filter
2276
+ filter,
2277
+ provenanceFilter: this.currentProvenanceFilter,
2278
+ sessionCwd: this.currentSessionCwd,
2279
+ abortSignal
1900
2280
  });
1901
2281
  }
1902
2282
  preloadBrowse(input) {
@@ -2047,6 +2427,10 @@ var AgentMentionSearchController = class extends AgentMentionSearchControllerBas
2047
2427
  return true;
2048
2428
  }
2049
2429
  expandGroup(groupId) {
2430
+ if (groupId.startsWith("issue-topic:")) {
2431
+ this.loadMoreIssueTopic(groupId);
2432
+ return;
2433
+ }
2050
2434
  const pageSize = mentionGroupPageSize(this.currentFilter, groupId);
2051
2435
  const current = this.expandedCounts[groupId] ?? pageSize;
2052
2436
  this.expandedCounts[groupId] = current + pageSize;
@@ -2072,6 +2456,7 @@ var AgentMentionSearchController = class extends AgentMentionSearchControllerBas
2072
2456
  }
2073
2457
  if (needsMoreFiles || needsMoreIssues) {
2074
2458
  this.clearTimer();
2459
+ this.abortActiveRequest();
2075
2460
  const requestId = ++this.requestId;
2076
2461
  this.setState({
2077
2462
  status: "loading",
@@ -2082,12 +2467,16 @@ var AgentMentionSearchController = class extends AgentMentionSearchControllerBas
2082
2467
  groups: this.groupsFromRawGroups(),
2083
2468
  error: null
2084
2469
  });
2470
+ const abortSignal = this.beginActiveRequest();
2085
2471
  void this.runSearch({
2086
2472
  workspaceId: this.activeWorkspaceId,
2087
2473
  currentUserId: this.currentUserId,
2088
2474
  query: this.currentQuery,
2089
2475
  requestId,
2090
- filter: this.currentFilter
2476
+ filter: this.currentFilter,
2477
+ provenanceFilter: this.currentProvenanceFilter,
2478
+ sessionCwd: this.currentSessionCwd,
2479
+ abortSignal
2091
2480
  });
2092
2481
  return;
2093
2482
  }
@@ -2103,6 +2492,8 @@ var AgentMentionSearchController = class extends AgentMentionSearchControllerBas
2103
2492
  }
2104
2493
  close() {
2105
2494
  this.clearTimer();
2495
+ this.abortActiveRequest();
2496
+ this.cancelIssueLoadMoreRequests();
2106
2497
  this.requestId += 1;
2107
2498
  this.currentFilter = DEFAULT_AGENT_MENTION_FILTER;
2108
2499
  this.resetAgentGeneratedBrowsePath();
@@ -2123,10 +2514,153 @@ var AgentMentionSearchController = class extends AgentMentionSearchControllerBas
2123
2514
  dispose() {
2124
2515
  this.disposed = true;
2125
2516
  this.clearTimer();
2517
+ this.abortActiveRequest();
2518
+ this.cancelIssueLoadMoreRequests();
2126
2519
  this.cancelPendingPreload();
2127
2520
  this.listeners.clear();
2128
2521
  this.requestId += 1;
2129
2522
  }
2523
+ loadMoreIssueTopic(groupId) {
2524
+ const group = this.issueTopicGroups?.find(
2525
+ (candidate) => candidate.id === groupId
2526
+ );
2527
+ const cursor = group?.nextPageToken;
2528
+ const provider = this.contextMentionProviders.get(
2529
+ WORKSPACE_ISSUE_PROVIDER_ID
2530
+ );
2531
+ if (!group || !cursor || !provider?.queryGroupPage) {
2532
+ return;
2533
+ }
2534
+ const requestKey = JSON.stringify({
2535
+ workspaceId: this.activeWorkspaceId,
2536
+ query: this.currentQuery,
2537
+ providerGroupId: group.providerGroupId,
2538
+ cursor
2539
+ });
2540
+ if (this.issueLoadMoreRequests.has(requestKey)) {
2541
+ return;
2542
+ }
2543
+ const requestId = this.requestId;
2544
+ const workspaceId = this.activeWorkspaceId;
2545
+ const currentUserId = this.currentUserId;
2546
+ const sessionCwd = this.currentSessionCwd;
2547
+ const provenanceFilter = this.currentProvenanceFilter;
2548
+ const query = this.currentQuery;
2549
+ const filter = this.currentFilter;
2550
+ const abortController = new AbortController();
2551
+ const requestToken = Symbol(requestKey);
2552
+ group.loadMoreStatus = "loading";
2553
+ group.loadMoreError = null;
2554
+ this.emitIssueTopicGroupsState();
2555
+ void (async () => {
2556
+ try {
2557
+ const diagnostics = [];
2558
+ const page = await queryAgentMentionProviderWithDiagnostics({
2559
+ abortSignal: abortController.signal,
2560
+ diagnosticNow: this.diagnosticNow,
2561
+ diagnostics,
2562
+ fallback: null,
2563
+ providerId: WORKSPACE_ISSUE_PROVIDER_ID,
2564
+ providerTimeoutMs: this.providerTimeoutMs,
2565
+ throwOnTimeout: true,
2566
+ query: (abortSignal) => queryAgentMentionProviderGroupPage({
2567
+ provider,
2568
+ providerGroupId: group.providerGroupId,
2569
+ workspaceId,
2570
+ currentUserId,
2571
+ query,
2572
+ cursor,
2573
+ pageSize: DEFAULT_MENTION_GROUP_PAGE_SIZE,
2574
+ sessionCwd,
2575
+ abortSignal,
2576
+ provenanceFilter
2577
+ }),
2578
+ resultCount: (result) => result?.items.length ?? 0
2579
+ });
2580
+ if (!page || !this.canApply(requestId, workspaceId, query, filter) || abortController.signal.aborted) {
2581
+ return;
2582
+ }
2583
+ const current = this.issueTopicGroups?.find(
2584
+ (candidate) => candidate.id === groupId
2585
+ );
2586
+ if (!current || current.nextPageToken !== cursor) {
2587
+ return;
2588
+ }
2589
+ const seen = new Set(
2590
+ current.items.filter((item) => item.kind === "workspace-issue").map((item) => item.targetId)
2591
+ );
2592
+ const appended = page.items.filter((item) => {
2593
+ if (item.kind !== "workspace-issue") {
2594
+ return true;
2595
+ }
2596
+ if (seen.has(item.targetId)) {
2597
+ return false;
2598
+ }
2599
+ seen.add(item.targetId);
2600
+ return true;
2601
+ });
2602
+ current.items = [...current.items, ...appended];
2603
+ current.totalCount = Math.max(page.totalCount, current.items.length);
2604
+ current.nextPageToken = page.nextPageToken;
2605
+ current.loadMoreStatus = "idle";
2606
+ current.loadMoreError = null;
2607
+ if (!query) {
2608
+ mergeAgentMentionBrowseIssueGroupPage({
2609
+ cacheKey: this.browseCacheKey(
2610
+ {
2611
+ workspaceId,
2612
+ currentUserId,
2613
+ filter,
2614
+ sessionCwd
2615
+ },
2616
+ provenanceFilter
2617
+ ),
2618
+ group: page,
2619
+ cachedAt: this.diagnosticNow()
2620
+ });
2621
+ }
2622
+ this.emitIssueTopicGroupsState();
2623
+ } catch (error) {
2624
+ if (!this.canApply(requestId, workspaceId, query, filter) || abortController.signal.aborted) {
2625
+ return;
2626
+ }
2627
+ const current = this.issueTopicGroups?.find(
2628
+ (candidate) => candidate.id === groupId
2629
+ );
2630
+ if (current?.nextPageToken === cursor) {
2631
+ current.loadMoreStatus = "error";
2632
+ current.loadMoreError = error instanceof Error ? error.message : String(error);
2633
+ this.emitIssueTopicGroupsState();
2634
+ }
2635
+ } finally {
2636
+ const active = this.issueLoadMoreRequests.get(requestKey);
2637
+ if (active?.token === requestToken) {
2638
+ this.issueLoadMoreRequests.delete(requestKey);
2639
+ }
2640
+ }
2641
+ })();
2642
+ this.issueLoadMoreRequests.set(requestKey, {
2643
+ abortController,
2644
+ token: requestToken
2645
+ });
2646
+ }
2647
+ emitIssueTopicGroupsState() {
2648
+ this.setState({
2649
+ status: "ready",
2650
+ query: this.currentQuery,
2651
+ mode: this.currentQuery ? "results" : "browse",
2652
+ filter: this.currentFilter,
2653
+ categories: buildBrowseCategories(),
2654
+ groups: this.groupsFromRawGroups(),
2655
+ error: null
2656
+ });
2657
+ }
2658
+ cancelIssueLoadMoreRequests() {
2659
+ for (const request of this.issueLoadMoreRequests.values()) {
2660
+ request.abortController.abort();
2661
+ }
2662
+ this.issueLoadMoreRequests.clear();
2663
+ }
2130
2664
  };
2131
2665
  function preloadAgentMentionBrowse(input) {
2132
2666
  const controller = new AgentMentionSearchController({
@@ -2155,4 +2689,4 @@ export {
2155
2689
  AgentMentionSearchController,
2156
2690
  preloadAgentMentionBrowse
2157
2691
  };
2158
- //# sourceMappingURL=chunk-WXMBD2O7.js.map
2692
+ //# sourceMappingURL=chunk-JG7HGKZL.js.map