@tutti-os/agent-gui 0.0.15 → 0.0.17

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 (50) hide show
  1. package/dist/AgentMentionSearchController-DqssJ2-b.d.ts +218 -0
  2. package/dist/agent-conversation/index.d.ts +3 -1
  3. package/dist/agent-conversation/index.js +5 -4
  4. package/dist/agent-conversation/index.js.map +1 -1
  5. package/dist/agent-message-center/index.d.ts +6 -2
  6. package/dist/agent-message-center/index.js +714 -291
  7. package/dist/agent-message-center/index.js.map +1 -1
  8. package/dist/app/renderer/agentactivity.css +176 -8
  9. package/dist/{chunk-KJPMZ7G5.js → chunk-65YMY2M3.js} +43 -17
  10. package/dist/chunk-65YMY2M3.js.map +1 -0
  11. package/dist/{chunk-OFGXNXYT.js → chunk-CDTTIUPL.js} +2 -2
  12. package/dist/{chunk-EK5RDKG7.js → chunk-GWR6WGZY.js} +21 -11
  13. package/dist/chunk-GWR6WGZY.js.map +1 -0
  14. package/dist/{chunk-H4HT3FE6.js → chunk-HVOPJU2K.js} +40 -30
  15. package/dist/chunk-HVOPJU2K.js.map +1 -0
  16. package/dist/{chunk-7CBJJNX6.js → chunk-JNGYJ7GM.js} +2 -2
  17. package/dist/{chunk-7CBJJNX6.js.map → chunk-JNGYJ7GM.js.map} +1 -1
  18. package/dist/{chunk-YKDFQADM.js → chunk-K44WER5Z.js} +177 -332
  19. package/dist/chunk-K44WER5Z.js.map +1 -0
  20. package/dist/{chunk-U4F3COKL.js → chunk-KHTIC52P.js} +83 -115
  21. package/dist/chunk-KHTIC52P.js.map +1 -0
  22. package/dist/chunk-O5TUTXHT.js +196 -0
  23. package/dist/chunk-O5TUTXHT.js.map +1 -0
  24. package/dist/{chunk-XHQGCP7A.js → chunk-OJ5WX7SZ.js} +2 -2
  25. package/dist/{chunk-SVOGXWFJ.js → chunk-VNAQ6QFE.js} +562 -468
  26. package/dist/chunk-VNAQ6QFE.js.map +1 -0
  27. package/dist/{chunk-2CA4NPP3.js → chunk-VO2TZNKV.js} +10 -7
  28. package/dist/{chunk-2CA4NPP3.js.map → chunk-VO2TZNKV.js.map} +1 -1
  29. package/dist/context-mention-palette/index.d.ts +5 -104
  30. package/dist/context-mention-palette/index.js +6 -5
  31. package/dist/i18n/index.d.ts +42 -16
  32. package/dist/i18n/index.js +1 -1
  33. package/dist/index.d.ts +22 -2
  34. package/dist/index.js +2002 -1329
  35. package/dist/index.js.map +1 -1
  36. package/dist/workbench/contribution.js +2 -2
  37. package/dist/workbench/index.d.ts +2 -1
  38. package/dist/workbench/index.js +2 -2
  39. package/dist/workbench/launch.js +1 -1
  40. package/dist/workspace-agent-generated-files.js +2 -2
  41. package/package.json +12 -12
  42. package/dist/agentFileMentionExtension-CM1c9bqk.d.ts +0 -86
  43. package/dist/chunk-EK5RDKG7.js.map +0 -1
  44. package/dist/chunk-H4HT3FE6.js.map +0 -1
  45. package/dist/chunk-KJPMZ7G5.js.map +0 -1
  46. package/dist/chunk-SVOGXWFJ.js.map +0 -1
  47. package/dist/chunk-U4F3COKL.js.map +0 -1
  48. package/dist/chunk-YKDFQADM.js.map +0 -1
  49. /package/dist/{chunk-OFGXNXYT.js.map → chunk-CDTTIUPL.js.map} +0 -0
  50. /package/dist/{chunk-XHQGCP7A.js.map → chunk-OJ5WX7SZ.js.map} +0 -0
@@ -3,20 +3,23 @@ import {
3
3
  managedAgentRoundedIconUrl,
4
4
  userAvatarPlaceholderUrl,
5
5
  workspaceAgentActivityStatusLabel
6
- } from "./chunk-OFGXNXYT.js";
6
+ } from "./chunk-CDTTIUPL.js";
7
7
  import {
8
8
  buildAgentGenericMentionHref,
9
9
  buildAgentSessionMentionHref,
10
10
  buildAgentWorkspaceAppMentionHref,
11
11
  buildAgentWorkspaceIssueMentionHref,
12
12
  normalizeAgentSessionMentionTitle
13
- } from "./chunk-U4F3COKL.js";
13
+ } from "./chunk-KHTIC52P.js";
14
+ import {
15
+ getOptionalAgentHostApi
16
+ } from "./chunk-O5TUTXHT.js";
14
17
  import {
15
18
  AGENT_CONTEXT_MENTION_PROVIDER_IDS
16
19
  } from "./chunk-HIREVEZM.js";
17
20
  import {
18
21
  translate
19
- } from "./chunk-KJPMZ7G5.js";
22
+ } from "./chunk-65YMY2M3.js";
20
23
  import {
21
24
  resolveAgentMentionFileThumbnailUrl,
22
25
  resolveAgentMentionFileVisualKind
@@ -305,8 +308,6 @@ function agentMentionGroupLabel(groupId) {
305
308
  }
306
309
  function agentMentionFilterLabel(filter) {
307
310
  switch (filter) {
308
- case "all":
309
- return translate("agentHost.agentGui.mentionFilterAll");
310
311
  case "app":
311
312
  return translate("agentHost.agentGui.mentionFilterApp");
312
313
  case "file":
@@ -338,16 +339,15 @@ function agentMentionEmptyGroupLabel(groupId, query) {
338
339
 
339
340
  // agent-gui/agentGuiNode/agentMentionSearchHelpers.ts
340
341
  var AGENT_MENTION_FILTER_TAB_ORDER = [
341
- "all",
342
342
  "session",
343
343
  "file",
344
344
  "issue",
345
345
  "app"
346
346
  ];
347
- var DEFAULT_MENTION_ALL_TAB_PAGE_SIZE = 5;
347
+ var DEFAULT_AGENT_MENTION_FILTER = "session";
348
348
  var DEFAULT_MENTION_GROUP_PAGE_SIZE = 10;
349
- function mentionGroupPageSize(filter, _groupId) {
350
- return filter === "all" ? DEFAULT_MENTION_ALL_TAB_PAGE_SIZE : DEFAULT_MENTION_GROUP_PAGE_SIZE;
349
+ function mentionGroupPageSize(_filter, _groupId) {
350
+ return DEFAULT_MENTION_GROUP_PAGE_SIZE;
351
351
  }
352
352
  function mentionGroupExpandCount(group, filter) {
353
353
  const pageSize = mentionGroupPageSize(
@@ -367,29 +367,26 @@ function groupIdsForFilter(filter) {
367
367
  return ["my_sessions"];
368
368
  case "issue":
369
369
  return ["issues"];
370
- case "all":
371
- default:
372
- return ["my_sessions", "files", "issues", "apps"];
373
370
  }
374
371
  }
375
372
  function shouldShowEmptyGroup(groupId, filter, query) {
376
373
  const hasQuery = query.trim().length > 0;
377
374
  if (groupId === "files") {
378
- return filter === "all";
375
+ return false;
379
376
  }
380
377
  if (groupId === "opened_files" || groupId === "agent_generated_files") {
381
378
  return filter === "file" && !hasQuery;
382
379
  }
383
380
  if (groupId === "apps") {
384
- return filter === "all" || filter === "app";
381
+ return filter === "app";
385
382
  }
386
383
  if (groupId === "my_sessions") {
387
- return filter === "all" || filter === "session";
384
+ return filter === "session";
388
385
  }
389
386
  if (groupId === "collab_sessions") {
390
387
  return false;
391
388
  }
392
- return filter === "all" || filter === "issue";
389
+ return filter === "issue";
393
390
  }
394
391
  function buildEmptyGroup(groupId, query) {
395
392
  return {
@@ -404,25 +401,6 @@ function buildEmptyGroup(groupId, query) {
404
401
  function emptyGroupLabel(groupId, query) {
405
402
  return agentMentionEmptyGroupLabel(groupId, query);
406
403
  }
407
- function shouldPrefetchBrowseFilter(filter) {
408
- return filter === "all" || filter === "app" || filter === "file" || filter === "session" || filter === "issue";
409
- }
410
- function filterForGroup(groupId) {
411
- switch (groupId) {
412
- case "apps":
413
- return "app";
414
- case "files":
415
- case "opened_files":
416
- case "agent_generated_files":
417
- return "file";
418
- case "my_sessions":
419
- return "session";
420
- case "collab_sessions":
421
- return "session";
422
- case "issues":
423
- return "issue";
424
- }
425
- }
426
404
  function resolveMentionGroupItems(groupId, rawGroups) {
427
405
  if (groupId === "files") {
428
406
  return [...rawGroups.opened_files, ...rawGroups.agent_generated_files];
@@ -452,6 +430,36 @@ var DEFAULT_ISSUE_LIMIT = 25;
452
430
  var DEFAULT_SESSION_LIMIT = 30;
453
431
  var DEFAULT_PROVIDER_TIMEOUT_MS = 3500;
454
432
  var DEFAULT_DIAGNOSTIC_SLOW_THRESHOLD_MS = 250;
433
+ var DEFAULT_BROWSE_CACHE_TTL_MS = 3e4;
434
+ var AGENT_MENTION_LIFECYCLE_LOG_PREFIX = "[agent-gui] mention-lifecycle";
435
+ var sharedAgentMentionBrowseCache = /* @__PURE__ */ new Map();
436
+ var sharedAgentMentionBrowseFetches = /* @__PURE__ */ new Map();
437
+ var MAX_BROWSE_CACHE_ENTRIES = 64;
438
+ function writeBrowseCacheEntry(cacheKey, entry) {
439
+ sharedAgentMentionBrowseCache.delete(cacheKey);
440
+ sharedAgentMentionBrowseCache.set(cacheKey, entry);
441
+ while (sharedAgentMentionBrowseCache.size > MAX_BROWSE_CACHE_ENTRIES) {
442
+ const oldestKey = sharedAgentMentionBrowseCache.keys().next().value;
443
+ if (oldestKey === void 0) {
444
+ break;
445
+ }
446
+ sharedAgentMentionBrowseCache.delete(oldestKey);
447
+ }
448
+ }
449
+ function scheduleIdleTask(task) {
450
+ const scope = globalThis;
451
+ if (typeof scope.requestIdleCallback === "function") {
452
+ const handle2 = scope.requestIdleCallback(() => task(), { timeout: 500 });
453
+ return () => scope.cancelIdleCallback?.(handle2);
454
+ }
455
+ const handle = setTimeout(task, 0);
456
+ return () => clearTimeout(handle);
457
+ }
458
+ function resetAgentMentionSearchBrowseCacheForTests() {
459
+ sharedAgentMentionBrowseCache.clear();
460
+ sharedAgentMentionBrowseFetches.clear();
461
+ }
462
+ globalThis.__tuttiResetAgentMentionSearchBrowseCacheForTests = resetAgentMentionSearchBrowseCacheForTests;
455
463
  function buildBrowseCategories() {
456
464
  return AGENT_MENTION_FILTER_TAB_ORDER.map((id) => ({
457
465
  id,
@@ -470,6 +478,7 @@ var AgentMentionSearchController = class {
470
478
  debounceMs;
471
479
  fileLimit;
472
480
  issueLimit;
481
+ browseCacheTtlMs;
473
482
  providerTimeoutMs;
474
483
  diagnosticInfoLogger;
475
484
  diagnosticNow;
@@ -478,29 +487,24 @@ var AgentMentionSearchController = class {
478
487
  expandedCounts = {};
479
488
  totalCounts = {};
480
489
  timer = null;
490
+ preloadCancel = null;
491
+ pendingPreloadKey = null;
481
492
  requestId = 0;
482
493
  disposed = false;
483
494
  activeWorkspaceId = "";
484
495
  currentUserId = "";
485
- currentFilter = "all";
496
+ currentFilter = DEFAULT_AGENT_MENTION_FILTER;
486
497
  currentQuery = "";
487
498
  currentSessionCwd = "";
488
499
  currentFileSearchLimit;
489
500
  currentIssueSearchLimit;
490
501
  agentGeneratedBrowsePath = null;
491
- rawGroups = {
492
- apps: [],
493
- opened_files: [],
494
- agent_generated_files: [],
495
- my_sessions: [],
496
- collab_sessions: [],
497
- issues: []
498
- };
502
+ rawGroups = emptyAgentMentionRawGroups();
499
503
  state = {
500
504
  status: "idle",
501
505
  query: "",
502
506
  mode: "browse",
503
- filter: "all",
507
+ filter: DEFAULT_AGENT_MENTION_FILTER,
504
508
  categories: buildBrowseCategories(),
505
509
  groups: [],
506
510
  error: null
@@ -515,12 +519,17 @@ var AgentMentionSearchController = class {
515
519
  this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;
516
520
  this.fileLimit = options.fileLimit ?? DEFAULT_FILE_LIMIT;
517
521
  this.issueLimit = options.issueLimit ?? DEFAULT_ISSUE_LIMIT;
522
+ this.browseCacheTtlMs = options.browseCacheTtlMs ?? DEFAULT_BROWSE_CACHE_TTL_MS;
518
523
  this.providerTimeoutMs = options.providerTimeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS;
519
524
  this.diagnosticInfoLogger = options.diagnosticInfoLogger ?? logAgentMentionSearchInfo;
520
525
  this.diagnosticNow = options.diagnosticNow ?? Date.now;
521
526
  this.diagnosticSlowThresholdMs = options.diagnosticSlowThresholdMs ?? DEFAULT_DIAGNOSTIC_SLOW_THRESHOLD_MS;
522
527
  this.currentFileSearchLimit = this.fileLimit;
523
528
  this.currentIssueSearchLimit = this.issueLimit;
529
+ this.logLifecycle("controller.construct", {
530
+ providerIds: this.providerIdsForDiagnostics(),
531
+ providerCount: this.contextMentionProviders.size
532
+ });
524
533
  }
525
534
  subscribe(listener) {
526
535
  this.listeners.add(listener);
@@ -542,6 +551,7 @@ var AgentMentionSearchController = class {
542
551
  this.resetAgentGeneratedBrowsePath();
543
552
  this.resetExpandedCounts();
544
553
  this.resetSearchLimits();
554
+ this.resetRawGroups();
545
555
  if (!this.activeWorkspaceId) {
546
556
  this.setState({
547
557
  status: "idle",
@@ -572,7 +582,8 @@ var AgentMentionSearchController = class {
572
582
  workspaceId: this.activeWorkspaceId,
573
583
  currentUserId: this.currentUserId,
574
584
  query: this.currentQuery,
575
- requestId
585
+ requestId,
586
+ filter: this.currentFilter
576
587
  });
577
588
  }, this.debounceMs);
578
589
  }
@@ -581,14 +592,30 @@ var AgentMentionSearchController = class {
581
592
  return;
582
593
  }
583
594
  this.currentFilter = filter;
595
+ this.clearTimer();
596
+ const requestId = ++this.requestId;
584
597
  this.resetAgentGeneratedBrowsePath();
585
598
  this.resetExpandedCounts();
599
+ this.resetSearchLimits();
600
+ this.resetRawGroups();
586
601
  if (!this.currentQuery) {
587
602
  this.startBrowseModeFetch(filter);
588
603
  return;
589
604
  }
605
+ if (!this.activeWorkspaceId) {
606
+ this.setState({
607
+ status: "ready",
608
+ query: this.currentQuery,
609
+ mode: "results",
610
+ filter: this.currentFilter,
611
+ categories: buildBrowseCategories(),
612
+ groups: [],
613
+ error: null
614
+ });
615
+ return;
616
+ }
590
617
  this.setState({
591
- status: "ready",
618
+ status: "loading",
592
619
  query: this.currentQuery,
593
620
  mode: "results",
594
621
  filter: this.currentFilter,
@@ -596,39 +623,101 @@ var AgentMentionSearchController = class {
596
623
  groups: this.groupsFromRawGroups(),
597
624
  error: null
598
625
  });
626
+ void this.runSearch({
627
+ workspaceId: this.activeWorkspaceId,
628
+ currentUserId: this.currentUserId,
629
+ query: this.currentQuery,
630
+ requestId,
631
+ filter
632
+ });
599
633
  }
600
- enterCategory(category) {
634
+ preloadBrowse(input) {
601
635
  if (this.disposed) {
602
636
  return;
603
637
  }
604
- this.currentFilter = category;
605
- this.resetExpandedCounts();
606
- this.clearTimer();
607
- if (!this.currentQuery) {
608
- this.startBrowseModeFetch(category);
638
+ const workspaceId = input.workspaceId.trim();
639
+ if (!workspaceId) {
609
640
  return;
610
641
  }
611
- if (!this.activeWorkspaceId) {
612
- this.emitBrowseState("ready");
642
+ const filter = input.filter ?? DEFAULT_AGENT_MENTION_FILTER;
643
+ const currentUserId = input.currentUserId?.trim() ?? "";
644
+ const sessionCwd = input.sessionCwd?.trim() ?? "";
645
+ const cacheKey = this.browseCacheKey({
646
+ currentUserId,
647
+ filter,
648
+ sessionCwd,
649
+ workspaceId
650
+ });
651
+ if (this.readBrowseCache(cacheKey).isFresh) {
613
652
  return;
614
653
  }
615
- const requestId = ++this.requestId;
616
- this.setState({
617
- status: "loading",
618
- query: this.currentQuery,
619
- mode: "results",
620
- filter: this.currentFilter,
621
- categories: buildBrowseCategories(),
622
- groups: this.groupsFromRawGroups(),
623
- error: null
654
+ if (this.pendingPreloadKey === cacheKey) {
655
+ return;
656
+ }
657
+ this.cancelPendingPreload();
658
+ this.pendingPreloadKey = cacheKey;
659
+ this.preloadCancel = scheduleIdleTask(() => {
660
+ this.preloadCancel = null;
661
+ this.pendingPreloadKey = null;
662
+ if (this.disposed) {
663
+ return;
664
+ }
665
+ this.runBrowsePreload({
666
+ cacheKey,
667
+ currentUserId,
668
+ filter,
669
+ sessionCwd,
670
+ workspaceId
671
+ });
624
672
  });
625
- void this.runSearch({
626
- workspaceId: this.activeWorkspaceId,
627
- currentUserId: this.currentUserId,
628
- query: this.currentQuery,
629
- requestId
673
+ }
674
+ runBrowsePreload(input) {
675
+ const { cacheKey, currentUserId, filter, sessionCwd, workspaceId } = input;
676
+ this.logLifecycle("browse.preload", {
677
+ filter,
678
+ providerIds: this.providerIdsForDiagnostics(),
679
+ sessionCwdPresent: Boolean(sessionCwd),
680
+ workspaceId
681
+ });
682
+ const cached = this.readBrowseCache(cacheKey);
683
+ this.logBrowseCacheState({
684
+ cacheKey,
685
+ cached,
686
+ filter,
687
+ reason: "preload",
688
+ workspaceId
689
+ });
690
+ if (cached.isFresh) {
691
+ return;
692
+ }
693
+ void this.loadBrowseFetchResult(
694
+ {
695
+ workspaceId,
696
+ currentUserId,
697
+ filter,
698
+ sessionCwd
699
+ },
700
+ cacheKey,
701
+ "preload"
702
+ ).catch((error) => {
703
+ this.logLifecycle("browse.fetch.error", {
704
+ errorKind: diagnosticErrorKind(error),
705
+ filter,
706
+ reason: "preload",
707
+ workspaceId
708
+ });
630
709
  });
631
710
  }
711
+ cancelPendingPreload() {
712
+ if (this.preloadCancel) {
713
+ this.preloadCancel();
714
+ this.preloadCancel = null;
715
+ }
716
+ this.pendingPreloadKey = null;
717
+ }
718
+ enterCategory(category) {
719
+ this.setFilter(category);
720
+ }
632
721
  selectAgentGeneratedMentionItem(item) {
633
722
  if (item.kind !== "file" || !item.mentionNavigation) {
634
723
  return false;
@@ -670,10 +759,6 @@ var AgentMentionSearchController = class {
670
759
  const current = this.expandedCounts[groupId] ?? pageSize;
671
760
  this.expandedCounts[groupId] = current + pageSize;
672
761
  if (!this.currentQuery) {
673
- const nextFilter = filterForGroup(groupId);
674
- if (this.currentFilter === "all") {
675
- this.currentFilter = nextFilter;
676
- }
677
762
  this.setState({
678
763
  status: "ready",
679
764
  query: "",
@@ -709,7 +794,8 @@ var AgentMentionSearchController = class {
709
794
  workspaceId: this.activeWorkspaceId,
710
795
  currentUserId: this.currentUserId,
711
796
  query: this.currentQuery,
712
- requestId
797
+ requestId,
798
+ filter: this.currentFilter
713
799
  });
714
800
  return;
715
801
  }
@@ -726,30 +812,17 @@ var AgentMentionSearchController = class {
726
812
  close() {
727
813
  this.clearTimer();
728
814
  this.requestId += 1;
729
- this.currentFilter = "all";
815
+ this.currentFilter = DEFAULT_AGENT_MENTION_FILTER;
730
816
  this.resetAgentGeneratedBrowsePath();
731
817
  this.resetExpandedCounts();
732
818
  this.resetSearchLimits();
733
- this.rawGroups = {
734
- apps: [],
735
- opened_files: [],
736
- agent_generated_files: [],
737
- my_sessions: [],
738
- collab_sessions: [],
739
- issues: []
740
- };
741
- this.totalCounts.apps = 0;
742
- this.totalCounts.opened_files = 0;
743
- this.totalCounts.agent_generated_files = 0;
744
- this.totalCounts.my_sessions = 0;
745
- this.totalCounts.collab_sessions = 0;
746
- this.totalCounts.issues = 0;
819
+ this.resetRawGroups();
747
820
  this.currentQuery = "";
748
821
  this.setState({
749
822
  status: "idle",
750
823
  query: "",
751
824
  mode: "browse",
752
- filter: "all",
825
+ filter: DEFAULT_AGENT_MENTION_FILTER,
753
826
  categories: buildBrowseCategories(),
754
827
  groups: [],
755
828
  error: null
@@ -758,101 +831,98 @@ var AgentMentionSearchController = class {
758
831
  dispose() {
759
832
  this.disposed = true;
760
833
  this.clearTimer();
834
+ this.cancelPendingPreload();
761
835
  this.listeners.clear();
762
836
  this.requestId += 1;
837
+ this.logLifecycle("controller.dispose", {
838
+ requestId: this.requestId,
839
+ workspaceId: this.activeWorkspaceId
840
+ });
763
841
  }
764
842
  startBrowseModeFetch(filter) {
765
- if (!this.activeWorkspaceId || !shouldPrefetchBrowseFilter(filter)) {
766
- this.rawGroups = {
767
- apps: [],
768
- opened_files: [],
769
- agent_generated_files: [],
770
- my_sessions: [],
771
- collab_sessions: [],
772
- issues: []
773
- };
843
+ if (!this.activeWorkspaceId) {
844
+ this.resetRawGroups();
774
845
  this.emitBrowseState("ready");
775
846
  return;
776
847
  }
777
848
  this.clearTimer();
778
849
  const requestId = ++this.requestId;
779
- this.rawGroups = {
780
- apps: [],
781
- opened_files: [],
782
- agent_generated_files: [],
783
- my_sessions: [],
784
- collab_sessions: [],
785
- issues: []
786
- };
787
- this.emitBrowseState("loading");
850
+ const cacheKey = this.browseCacheKey({
851
+ currentUserId: this.currentUserId,
852
+ filter,
853
+ sessionCwd: this.currentSessionCwd,
854
+ workspaceId: this.activeWorkspaceId
855
+ });
856
+ this.logLifecycle("browse.open", {
857
+ filter,
858
+ providerIds: this.providerIdsForDiagnostics(),
859
+ requestId,
860
+ sessionCwdPresent: Boolean(this.currentSessionCwd),
861
+ workspaceId: this.activeWorkspaceId
862
+ });
863
+ const cached = this.readBrowseCacheForBrowseInput({
864
+ cacheKey,
865
+ currentUserId: this.currentUserId,
866
+ filter,
867
+ sessionCwd: this.currentSessionCwd,
868
+ workspaceId: this.activeWorkspaceId
869
+ });
870
+ this.logBrowseCacheState({
871
+ cacheKey,
872
+ cached,
873
+ filter,
874
+ reason: "open",
875
+ workspaceId: this.activeWorkspaceId
876
+ });
877
+ if (cached.entry) {
878
+ this.applyBrowseFetchResult(cached.entry);
879
+ this.setState({
880
+ status: "ready",
881
+ query: "",
882
+ mode: "browse",
883
+ filter: this.currentFilter,
884
+ categories: buildBrowseCategories(),
885
+ groups: this.groupsFromRawGroups(),
886
+ error: null
887
+ });
888
+ if (cached.isFresh) {
889
+ return;
890
+ }
891
+ } else {
892
+ this.rawGroups = emptyAgentMentionRawGroups();
893
+ this.resetTotalCounts();
894
+ this.emitBrowseState("loading");
895
+ }
788
896
  void this.runBrowseSearch({
789
897
  workspaceId: this.activeWorkspaceId,
790
898
  currentUserId: this.currentUserId,
791
899
  requestId,
792
- filter
900
+ filter,
901
+ sessionCwd: this.currentSessionCwd
793
902
  });
794
903
  }
795
904
  async runSearch(input) {
796
905
  const startedAt = this.diagnosticNow();
797
- const providerDiagnostics = [];
906
+ let providerDiagnostics = [];
798
907
  try {
799
- const [fileItems, appItems, issueItems, sessionItems] = await Promise.all(
800
- [
801
- this.queryProviderMentionItemsById({
802
- providerId: FILE_PROVIDER_ID2,
803
- workspaceId: input.workspaceId,
804
- currentUserId: input.currentUserId,
805
- query: input.query,
806
- limit: this.currentFileSearchLimit,
807
- diagnostics: providerDiagnostics
808
- }),
809
- this.queryProviderMentionItemsById({
810
- providerId: WORKSPACE_APP_PROVIDER_ID2,
811
- workspaceId: input.workspaceId,
812
- currentUserId: input.currentUserId,
813
- query: input.query,
814
- limit: DEFAULT_MENTION_GROUP_PAGE_SIZE,
815
- diagnostics: providerDiagnostics
816
- }),
817
- this.queryProviderMentionItemsById({
818
- providerId: WORKSPACE_ISSUE_PROVIDER_ID2,
819
- workspaceId: input.workspaceId,
820
- currentUserId: input.currentUserId,
821
- query: input.query,
822
- limit: this.currentIssueSearchLimit,
823
- diagnostics: providerDiagnostics
824
- }),
825
- this.queryProviderMentionItemsById({
826
- providerId: AGENT_SESSION_PROVIDER_ID2,
827
- workspaceId: input.workspaceId,
828
- currentUserId: input.currentUserId,
829
- query: input.query,
830
- limit: DEFAULT_SESSION_LIMIT,
831
- diagnostics: providerDiagnostics
832
- })
833
- ]
834
- );
835
- if (!this.canApply(input.requestId, input.workspaceId, input.query)) {
908
+ const result = await this.fetchFilterResult({
909
+ workspaceId: input.workspaceId,
910
+ currentUserId: input.currentUserId,
911
+ query: input.query,
912
+ filter: input.filter,
913
+ sessionCwd: this.currentSessionCwd,
914
+ includeAgentGeneratedFiles: false
915
+ });
916
+ providerDiagnostics = result.providerDiagnostics;
917
+ if (!this.canApply(
918
+ input.requestId,
919
+ input.workspaceId,
920
+ input.query,
921
+ input.filter
922
+ )) {
836
923
  return;
837
924
  }
838
- this.rawGroups = {
839
- apps: appItems.filter((item) => item.kind === "workspace-app"),
840
- opened_files: fileItems.filter((item) => item.kind === "file"),
841
- agent_generated_files: [],
842
- my_sessions: sessionItems.filter(
843
- (item) => item.kind === "session" && item.scope === "my_sessions"
844
- ),
845
- collab_sessions: sessionItems.filter(
846
- (item) => item.kind === "session" && item.scope === "collab_sessions"
847
- ),
848
- issues: issueItems.filter((item) => item.kind === "workspace-issue")
849
- };
850
- this.totalCounts.apps = this.rawGroups.apps.length;
851
- this.totalCounts.opened_files = this.rawGroups.opened_files.length;
852
- this.totalCounts.agent_generated_files = 0;
853
- this.totalCounts.my_sessions = this.rawGroups.my_sessions.length;
854
- this.totalCounts.collab_sessions = this.rawGroups.collab_sessions.length;
855
- this.totalCounts.issues = this.rawGroups.issues.length;
925
+ this.applyBrowseFetchResult(result);
856
926
  const groups = this.groupsFromRawGroups();
857
927
  this.setState({
858
928
  status: "ready",
@@ -864,7 +934,7 @@ var AgentMentionSearchController = class {
864
934
  error: null
865
935
  });
866
936
  this.logSearchDiagnostic({
867
- filter: this.currentFilter,
937
+ filter: input.filter,
868
938
  groups,
869
939
  mode: "results",
870
940
  providerDiagnostics,
@@ -875,7 +945,12 @@ var AgentMentionSearchController = class {
875
945
  workspaceId: input.workspaceId
876
946
  });
877
947
  } catch (error) {
878
- if (!this.canApply(input.requestId, input.workspaceId, input.query)) {
948
+ if (!this.canApply(
949
+ input.requestId,
950
+ input.workspaceId,
951
+ input.query,
952
+ input.filter
953
+ )) {
879
954
  return;
880
955
  }
881
956
  this.setState({
@@ -889,7 +964,7 @@ var AgentMentionSearchController = class {
889
964
  });
890
965
  this.logSearchDiagnostic({
891
966
  error,
892
- filter: this.currentFilter,
967
+ filter: input.filter,
893
968
  groups: [],
894
969
  mode: "results",
895
970
  providerDiagnostics,
@@ -903,205 +978,21 @@ var AgentMentionSearchController = class {
903
978
  }
904
979
  async runBrowseSearch(input) {
905
980
  const startedAt = this.diagnosticNow();
906
- const providerDiagnostics = [];
981
+ let providerDiagnostics = [];
982
+ const cacheKey = this.browseCacheKey(input);
907
983
  try {
908
- if (input.filter === "file") {
909
- const [fileItems, agentGeneratedFileItems] = await Promise.all([
910
- this.queryProviderMentionItemsById({
911
- providerId: FILE_PROVIDER_ID2,
912
- workspaceId: input.workspaceId,
913
- currentUserId: input.currentUserId,
914
- query: "",
915
- limit: this.fileLimit,
916
- diagnostics: providerDiagnostics
917
- }),
918
- this.queryProviderMentionItemsById({
919
- providerId: AGENT_GENERATED_FILE_PROVIDER_ID2,
920
- workspaceId: input.workspaceId,
921
- currentUserId: input.currentUserId,
922
- query: "",
923
- limit: this.fileLimit,
924
- diagnostics: providerDiagnostics
925
- })
926
- ]);
927
- if (!this.canApply(input.requestId, input.workspaceId, "")) {
928
- return;
929
- }
930
- this.rawGroups = {
931
- apps: [],
932
- opened_files: fileItems.filter((item) => item.kind === "file"),
933
- agent_generated_files: agentGeneratedFileItems.filter(
934
- (item) => item.kind === "file"
935
- ),
936
- my_sessions: [],
937
- collab_sessions: [],
938
- issues: []
939
- };
940
- this.totalCounts.apps = 0;
941
- this.totalCounts.opened_files = this.rawGroups.opened_files.length;
942
- this.totalCounts.agent_generated_files = this.rawGroups.agent_generated_files.length;
943
- this.totalCounts.my_sessions = 0;
944
- this.totalCounts.collab_sessions = 0;
945
- this.totalCounts.issues = 0;
946
- } else if (input.filter === "app") {
947
- const appItems = await this.queryProviderMentionItemsById({
948
- providerId: WORKSPACE_APP_PROVIDER_ID2,
949
- workspaceId: input.workspaceId,
950
- currentUserId: input.currentUserId,
951
- query: "",
952
- limit: DEFAULT_MENTION_GROUP_PAGE_SIZE,
953
- diagnostics: providerDiagnostics
954
- });
955
- if (!this.canApply(input.requestId, input.workspaceId, "")) {
956
- return;
957
- }
958
- this.rawGroups = {
959
- apps: appItems.filter((item) => item.kind === "workspace-app"),
960
- opened_files: [],
961
- agent_generated_files: [],
962
- my_sessions: [],
963
- collab_sessions: [],
964
- issues: []
965
- };
966
- this.totalCounts.apps = this.rawGroups.apps.length;
967
- this.totalCounts.opened_files = 0;
968
- this.totalCounts.agent_generated_files = 0;
969
- this.totalCounts.my_sessions = 0;
970
- this.totalCounts.collab_sessions = 0;
971
- this.totalCounts.issues = 0;
972
- } else if (input.filter === "issue") {
973
- const issueItems = await this.queryProviderMentionItemsById({
974
- providerId: WORKSPACE_ISSUE_PROVIDER_ID2,
975
- workspaceId: input.workspaceId,
976
- currentUserId: input.currentUserId,
977
- query: "",
978
- limit: this.currentIssueSearchLimit,
979
- diagnostics: providerDiagnostics
980
- });
981
- if (!this.canApply(input.requestId, input.workspaceId, "")) {
982
- return;
983
- }
984
- this.rawGroups = {
985
- apps: [],
986
- opened_files: [],
987
- agent_generated_files: [],
988
- my_sessions: [],
989
- collab_sessions: [],
990
- issues: issueItems.filter((item) => item.kind === "workspace-issue")
991
- };
992
- this.totalCounts.apps = 0;
993
- this.totalCounts.opened_files = 0;
994
- this.totalCounts.agent_generated_files = 0;
995
- this.totalCounts.my_sessions = 0;
996
- this.totalCounts.collab_sessions = 0;
997
- this.totalCounts.issues = this.rawGroups.issues.length;
998
- } else if (input.filter === "session") {
999
- const sessionItems = await this.queryProviderMentionItemsById({
1000
- providerId: AGENT_SESSION_PROVIDER_ID2,
1001
- workspaceId: input.workspaceId,
1002
- currentUserId: input.currentUserId,
1003
- query: "",
1004
- limit: DEFAULT_SESSION_LIMIT,
1005
- diagnostics: providerDiagnostics
984
+ const result = await this.loadBrowseFetchResult(input, cacheKey, "open");
985
+ providerDiagnostics = result.providerDiagnostics;
986
+ if (!this.canApply(input.requestId, input.workspaceId, "", input.filter)) {
987
+ this.logLifecycle("browse.apply.skipped", {
988
+ filter: input.filter,
989
+ requestId: input.requestId,
990
+ reason: "open",
991
+ workspaceId: input.workspaceId
1006
992
  });
1007
- if (!this.canApply(input.requestId, input.workspaceId, "")) {
1008
- return;
1009
- }
1010
- const sessionMentionItems = sessionItems.filter(
1011
- (item) => item.kind === "session"
1012
- );
1013
- const mySessionItems = sessionMentionItems.filter(
1014
- (item) => input.currentUserId ? item.scope === "my_sessions" : true
1015
- ).map(
1016
- (item) => item.scope === "my_sessions" ? item : { ...item, scope: "my_sessions" }
1017
- );
1018
- this.rawGroups = {
1019
- apps: [],
1020
- opened_files: [],
1021
- agent_generated_files: [],
1022
- my_sessions: mySessionItems,
1023
- collab_sessions: [],
1024
- issues: []
1025
- };
1026
- this.totalCounts.apps = 0;
1027
- this.totalCounts.opened_files = 0;
1028
- this.totalCounts.agent_generated_files = 0;
1029
- this.totalCounts.my_sessions = this.rawGroups.my_sessions.length;
1030
- this.totalCounts.collab_sessions = this.rawGroups.collab_sessions.length;
1031
- this.totalCounts.issues = 0;
1032
- } else {
1033
- const [
1034
- appItems,
1035
- fileItems,
1036
- agentGeneratedFileItems,
1037
- issueItems,
1038
- sessionItems
1039
- ] = await Promise.all([
1040
- this.queryProviderMentionItemsById({
1041
- providerId: WORKSPACE_APP_PROVIDER_ID2,
1042
- workspaceId: input.workspaceId,
1043
- currentUserId: input.currentUserId,
1044
- query: "",
1045
- limit: DEFAULT_MENTION_GROUP_PAGE_SIZE,
1046
- diagnostics: providerDiagnostics
1047
- }),
1048
- this.queryProviderMentionItemsById({
1049
- providerId: FILE_PROVIDER_ID2,
1050
- workspaceId: input.workspaceId,
1051
- currentUserId: input.currentUserId,
1052
- query: "",
1053
- limit: this.fileLimit,
1054
- diagnostics: providerDiagnostics
1055
- }),
1056
- this.queryProviderMentionItemsById({
1057
- providerId: AGENT_GENERATED_FILE_PROVIDER_ID2,
1058
- workspaceId: input.workspaceId,
1059
- currentUserId: input.currentUserId,
1060
- query: "",
1061
- limit: this.fileLimit,
1062
- diagnostics: providerDiagnostics
1063
- }),
1064
- this.queryProviderMentionItemsById({
1065
- providerId: WORKSPACE_ISSUE_PROVIDER_ID2,
1066
- workspaceId: input.workspaceId,
1067
- currentUserId: input.currentUserId,
1068
- query: "",
1069
- limit: this.currentIssueSearchLimit,
1070
- diagnostics: providerDiagnostics
1071
- }),
1072
- this.queryProviderMentionItemsById({
1073
- providerId: AGENT_SESSION_PROVIDER_ID2,
1074
- workspaceId: input.workspaceId,
1075
- currentUserId: input.currentUserId,
1076
- query: "",
1077
- limit: DEFAULT_SESSION_LIMIT,
1078
- diagnostics: providerDiagnostics
1079
- })
1080
- ]);
1081
- if (!this.canApply(input.requestId, input.workspaceId, "")) {
1082
- return;
1083
- }
1084
- this.rawGroups = {
1085
- apps: appItems.filter((item) => item.kind === "workspace-app"),
1086
- opened_files: fileItems.filter((item) => item.kind === "file"),
1087
- agent_generated_files: agentGeneratedFileItems.filter(
1088
- (item) => item.kind === "file"
1089
- ),
1090
- my_sessions: sessionItems.filter(
1091
- (item) => item.kind === "session" && item.scope === "my_sessions"
1092
- ),
1093
- collab_sessions: sessionItems.filter(
1094
- (item) => item.kind === "session" && item.scope === "collab_sessions"
1095
- ),
1096
- issues: issueItems.filter((item) => item.kind === "workspace-issue")
1097
- };
1098
- this.totalCounts.apps = this.rawGroups.apps.length;
1099
- this.totalCounts.opened_files = this.rawGroups.opened_files.length;
1100
- this.totalCounts.agent_generated_files = this.rawGroups.agent_generated_files.length;
1101
- this.totalCounts.my_sessions = this.rawGroups.my_sessions.length;
1102
- this.totalCounts.collab_sessions = this.rawGroups.collab_sessions.length;
1103
- this.totalCounts.issues = this.rawGroups.issues.length;
993
+ return;
1104
994
  }
995
+ this.applyBrowseFetchResult(result);
1105
996
  const groups = this.groupsFromRawGroups();
1106
997
  this.setState({
1107
998
  status: "ready",
@@ -1113,7 +1004,7 @@ var AgentMentionSearchController = class {
1113
1004
  error: null
1114
1005
  });
1115
1006
  this.logSearchDiagnostic({
1116
- filter: this.currentFilter,
1007
+ filter: input.filter,
1117
1008
  groups,
1118
1009
  mode: "browse",
1119
1010
  providerDiagnostics,
@@ -1124,7 +1015,7 @@ var AgentMentionSearchController = class {
1124
1015
  workspaceId: input.workspaceId
1125
1016
  });
1126
1017
  } catch (error) {
1127
- if (!this.canApply(input.requestId, input.workspaceId, "")) {
1018
+ if (!this.canApply(input.requestId, input.workspaceId, "", input.filter)) {
1128
1019
  return;
1129
1020
  }
1130
1021
  this.setState({
@@ -1138,7 +1029,7 @@ var AgentMentionSearchController = class {
1138
1029
  });
1139
1030
  this.logSearchDiagnostic({
1140
1031
  error,
1141
- filter: this.currentFilter,
1032
+ filter: input.filter,
1142
1033
  groups: [],
1143
1034
  mode: "browse",
1144
1035
  providerDiagnostics,
@@ -1150,6 +1041,156 @@ var AgentMentionSearchController = class {
1150
1041
  });
1151
1042
  }
1152
1043
  }
1044
+ async loadBrowseFetchResult(input, cacheKey, reason) {
1045
+ const existingFetch = sharedAgentMentionBrowseFetches.get(cacheKey);
1046
+ if (existingFetch) {
1047
+ this.logLifecycle("browse.fetch.dedupe", {
1048
+ filter: input.filter,
1049
+ reason,
1050
+ workspaceId: input.workspaceId
1051
+ });
1052
+ return existingFetch;
1053
+ }
1054
+ const startedAt = this.diagnosticNow();
1055
+ this.logLifecycle("browse.fetch.start", {
1056
+ filter: input.filter,
1057
+ providerIds: this.providerIdsForDiagnostics(),
1058
+ reason,
1059
+ workspaceId: input.workspaceId
1060
+ });
1061
+ const fetchPromise = this.fetchBrowseResult(input).then((result) => {
1062
+ writeBrowseCacheEntry(cacheKey, {
1063
+ ...result,
1064
+ cachedAt: this.diagnosticNow()
1065
+ });
1066
+ this.logLifecycle("browse.fetch.success", {
1067
+ durationMs: elapsedDiagnosticMs(this.diagnosticNow(), startedAt),
1068
+ filter: input.filter,
1069
+ itemCount: rawGroupItemCount(result.rawGroups),
1070
+ providerResults: providerDiagnosticsSummary(
1071
+ result.providerDiagnostics
1072
+ ),
1073
+ reason,
1074
+ workspaceId: input.workspaceId
1075
+ });
1076
+ return result;
1077
+ }).finally(() => {
1078
+ if (sharedAgentMentionBrowseFetches.get(cacheKey) === fetchPromise) {
1079
+ sharedAgentMentionBrowseFetches.delete(cacheKey);
1080
+ }
1081
+ });
1082
+ sharedAgentMentionBrowseFetches.set(cacheKey, fetchPromise);
1083
+ return fetchPromise;
1084
+ }
1085
+ async fetchBrowseResult(input) {
1086
+ return this.fetchFilterResult({
1087
+ ...input,
1088
+ query: "",
1089
+ includeAgentGeneratedFiles: input.filter === "file"
1090
+ });
1091
+ }
1092
+ async fetchFilterResult(input) {
1093
+ const providerDiagnostics = [];
1094
+ switch (input.filter) {
1095
+ case "file": {
1096
+ const fileQuery = this.queryProviderMentionItemsById({
1097
+ providerId: FILE_PROVIDER_ID2,
1098
+ workspaceId: input.workspaceId,
1099
+ currentUserId: input.currentUserId,
1100
+ query: input.query,
1101
+ limit: input.query ? this.currentFileSearchLimit : this.fileLimit,
1102
+ sessionCwd: input.sessionCwd,
1103
+ diagnostics: providerDiagnostics
1104
+ });
1105
+ const agentGeneratedFileQuery = input.includeAgentGeneratedFiles ? this.queryProviderMentionItemsById({
1106
+ providerId: AGENT_GENERATED_FILE_PROVIDER_ID2,
1107
+ workspaceId: input.workspaceId,
1108
+ currentUserId: input.currentUserId,
1109
+ query: input.query,
1110
+ limit: this.fileLimit,
1111
+ sessionCwd: input.sessionCwd,
1112
+ diagnostics: providerDiagnostics
1113
+ }) : Promise.resolve([]);
1114
+ const [fileItems, agentGeneratedFileItems] = await Promise.all([
1115
+ fileQuery,
1116
+ agentGeneratedFileQuery
1117
+ ]);
1118
+ const rawGroups = emptyAgentMentionRawGroups();
1119
+ rawGroups.opened_files = fileItems.filter(
1120
+ (item) => item.kind === "file"
1121
+ );
1122
+ rawGroups.agent_generated_files = agentGeneratedFileItems.filter(
1123
+ (item) => item.kind === "file"
1124
+ );
1125
+ return {
1126
+ providerDiagnostics,
1127
+ rawGroups,
1128
+ totalCounts: totalCountsFromRawGroups(rawGroups)
1129
+ };
1130
+ }
1131
+ case "session": {
1132
+ const sessionItems = await this.queryProviderMentionItemsById({
1133
+ providerId: AGENT_SESSION_PROVIDER_ID2,
1134
+ workspaceId: input.workspaceId,
1135
+ currentUserId: input.currentUserId,
1136
+ query: input.query,
1137
+ limit: DEFAULT_SESSION_LIMIT,
1138
+ sessionCwd: input.sessionCwd,
1139
+ diagnostics: providerDiagnostics
1140
+ });
1141
+ const rawGroups = emptyAgentMentionRawGroups();
1142
+ rawGroups.my_sessions = normalizeSessionMentionItemsForMySessions({
1143
+ currentUserId: input.currentUserId,
1144
+ items: sessionItems
1145
+ });
1146
+ return {
1147
+ providerDiagnostics,
1148
+ rawGroups,
1149
+ totalCounts: totalCountsFromRawGroups(rawGroups)
1150
+ };
1151
+ }
1152
+ case "issue": {
1153
+ const issueItems = await this.queryProviderMentionItemsById({
1154
+ providerId: WORKSPACE_ISSUE_PROVIDER_ID2,
1155
+ workspaceId: input.workspaceId,
1156
+ currentUserId: input.currentUserId,
1157
+ query: input.query,
1158
+ limit: this.currentIssueSearchLimit,
1159
+ sessionCwd: input.sessionCwd,
1160
+ diagnostics: providerDiagnostics
1161
+ });
1162
+ const rawGroups = emptyAgentMentionRawGroups();
1163
+ rawGroups.issues = issueItems.filter(
1164
+ (item) => item.kind === "workspace-issue"
1165
+ );
1166
+ return {
1167
+ providerDiagnostics,
1168
+ rawGroups,
1169
+ totalCounts: totalCountsFromRawGroups(rawGroups)
1170
+ };
1171
+ }
1172
+ case "app": {
1173
+ const appItems = await this.queryProviderMentionItemsById({
1174
+ providerId: WORKSPACE_APP_PROVIDER_ID2,
1175
+ workspaceId: input.workspaceId,
1176
+ currentUserId: input.currentUserId,
1177
+ query: input.query,
1178
+ limit: DEFAULT_MENTION_GROUP_PAGE_SIZE,
1179
+ sessionCwd: input.sessionCwd,
1180
+ diagnostics: providerDiagnostics
1181
+ });
1182
+ const rawGroups = emptyAgentMentionRawGroups();
1183
+ rawGroups.apps = appItems.filter(
1184
+ (item) => item.kind === "workspace-app"
1185
+ );
1186
+ return {
1187
+ providerDiagnostics,
1188
+ rawGroups,
1189
+ totalCounts: totalCountsFromRawGroups(rawGroups)
1190
+ };
1191
+ }
1192
+ }
1193
+ }
1153
1194
  async queryProviderMentionItems(input) {
1154
1195
  const items = await input.provider.query({
1155
1196
  keyword: input.query,
@@ -1159,7 +1200,7 @@ var AgentMentionSearchController = class {
1159
1200
  context: {
1160
1201
  metadata: {
1161
1202
  currentUserId: input.currentUserId,
1162
- sessionCwd: this.currentSessionCwd || void 0,
1203
+ sessionCwd: input.sessionCwd || void 0,
1163
1204
  target: "agent-gui",
1164
1205
  workspaceId: input.workspaceId
1165
1206
  }
@@ -1201,6 +1242,55 @@ var AgentMentionSearchController = class {
1201
1242
  (item) => item !== null
1202
1243
  );
1203
1244
  }
1245
+ applyBrowseFetchResult(result) {
1246
+ this.rawGroups = cloneAgentMentionRawGroups(result.rawGroups);
1247
+ this.resetTotalCounts();
1248
+ for (const [groupId, count] of Object.entries(result.totalCounts)) {
1249
+ this.totalCounts[groupId] = count;
1250
+ }
1251
+ }
1252
+ readBrowseCache(cacheKey) {
1253
+ const entry = sharedAgentMentionBrowseCache.get(cacheKey);
1254
+ if (!entry) {
1255
+ return { entry: null, isFresh: false };
1256
+ }
1257
+ sharedAgentMentionBrowseCache.delete(cacheKey);
1258
+ sharedAgentMentionBrowseCache.set(cacheKey, entry);
1259
+ const ageMs = this.diagnosticNow() - entry.cachedAt;
1260
+ const isFresh = this.browseCacheTtlMs >= 0 && Number.isFinite(this.browseCacheTtlMs) && ageMs <= this.browseCacheTtlMs;
1261
+ return { entry, isFresh };
1262
+ }
1263
+ readBrowseCacheForBrowseInput(input) {
1264
+ return this.readBrowseCache(input.cacheKey);
1265
+ }
1266
+ browseCacheKey(input) {
1267
+ return JSON.stringify({
1268
+ workspaceId: input.workspaceId,
1269
+ currentUserId: input.currentUserId,
1270
+ sessionCwd: input.sessionCwd,
1271
+ filter: input.filter,
1272
+ fileLimit: this.fileLimit,
1273
+ issueLimit: this.currentIssueSearchLimit,
1274
+ providerIds: [...this.contextMentionProviders.keys()].sort()
1275
+ });
1276
+ }
1277
+ logBrowseCacheState(input) {
1278
+ this.logLifecycle("browse.cache", {
1279
+ ageMs: input.cached.entry ? elapsedDiagnosticMs(this.diagnosticNow(), input.cached.entry.cachedAt) : null,
1280
+ cacheKeyLength: input.cacheKey.length,
1281
+ cacheState: input.cached.entry ? input.cached.isFresh ? "fresh" : "stale" : "miss",
1282
+ filter: input.filter,
1283
+ itemCount: input.cached.entry ? rawGroupItemCount(input.cached.entry.rawGroups) : 0,
1284
+ reason: input.reason,
1285
+ workspaceId: input.workspaceId
1286
+ });
1287
+ }
1288
+ logLifecycle(event, details) {
1289
+ logAgentMentionLifecycleDiagnostic({ event, details });
1290
+ }
1291
+ providerIdsForDiagnostics() {
1292
+ return [...this.contextMentionProviders.keys()].sort().join(",");
1293
+ }
1204
1294
  async queryProviderMentionItemsById(input) {
1205
1295
  const provider = this.contextMentionProviders.get(input.providerId);
1206
1296
  return queryAgentMentionProviderWithDiagnostics({
@@ -1215,6 +1305,7 @@ var AgentMentionSearchController = class {
1215
1305
  currentUserId: input.currentUserId,
1216
1306
  query: input.query,
1217
1307
  limit: input.limit,
1308
+ sessionCwd: input.sessionCwd ?? this.currentSessionCwd,
1218
1309
  abortSignal
1219
1310
  }) : null,
1220
1311
  resultCount: (result) => result.length
@@ -1241,7 +1332,7 @@ var AgentMentionSearchController = class {
1241
1332
  }
1242
1333
  groupsFromRawGroups() {
1243
1334
  const orderedGroupIds = groupIdsForFilter(this.currentFilter);
1244
- const groups = orderedGroupIds.map((groupId) => {
1335
+ return orderedGroupIds.map((groupId) => {
1245
1336
  const rawItems = resolveMentionGroupItems(groupId, this.rawGroups);
1246
1337
  const items = groupId === "agent_generated_files" ? presentAgentGeneratedFileMentionItems({
1247
1338
  files: rawItems,
@@ -1276,11 +1367,6 @@ var AgentMentionSearchController = class {
1276
1367
  hasMore: items.length > visibleCount || (groupId === "opened_files" || groupId === "files" || groupId === "agent_generated_files") && items.length >= this.currentFileSearchLimit || totalCount > visibleCount
1277
1368
  };
1278
1369
  }).filter((group) => group !== null);
1279
- return orderMentionGroupsForFilter({
1280
- filter: this.currentFilter,
1281
- groups,
1282
- query: this.currentQuery
1283
- });
1284
1370
  }
1285
1371
  emitBrowseState(status) {
1286
1372
  this.setState({
@@ -1293,8 +1379,8 @@ var AgentMentionSearchController = class {
1293
1379
  error: null
1294
1380
  });
1295
1381
  }
1296
- canApply(requestId, workspaceId, query) {
1297
- return !this.disposed && requestId === this.requestId && workspaceId === this.activeWorkspaceId && query === this.currentQuery;
1382
+ canApply(requestId, workspaceId, query, filter) {
1383
+ return !this.disposed && requestId === this.requestId && workspaceId === this.activeWorkspaceId && query === this.currentQuery && filter === this.currentFilter;
1298
1384
  }
1299
1385
  clearTimer() {
1300
1386
  if (this.timer !== null) {
@@ -1322,9 +1408,26 @@ var AgentMentionSearchController = class {
1322
1408
  this.currentFileSearchLimit = this.fileLimit;
1323
1409
  this.currentIssueSearchLimit = this.issueLimit;
1324
1410
  }
1411
+ resetRawGroups() {
1412
+ this.rawGroups = emptyAgentMentionRawGroups();
1413
+ this.resetTotalCounts();
1414
+ }
1325
1415
  resetAgentGeneratedBrowsePath() {
1326
1416
  this.agentGeneratedBrowsePath = null;
1327
1417
  }
1418
+ resetTotalCounts() {
1419
+ for (const groupId of [
1420
+ "files",
1421
+ "opened_files",
1422
+ "agent_generated_files",
1423
+ "my_sessions",
1424
+ "collab_sessions",
1425
+ "apps",
1426
+ "issues"
1427
+ ]) {
1428
+ delete this.totalCounts[groupId];
1429
+ }
1430
+ }
1328
1431
  setState(state) {
1329
1432
  this.state = state;
1330
1433
  for (const listener of this.listeners) {
@@ -1332,102 +1435,94 @@ var AgentMentionSearchController = class {
1332
1435
  }
1333
1436
  }
1334
1437
  };
1335
- function orderMentionGroupsForFilter(input) {
1336
- if (input.filter !== "all") {
1337
- return input.groups;
1338
- }
1339
- const query = normalizeQuery(input.query).toLowerCase();
1340
- return input.groups.map((group, index) => ({
1341
- group,
1342
- hasItems: group.items.length > 0,
1343
- index,
1344
- score: mentionGroupBestMatchScore(group, query)
1345
- })).sort((left, right) => {
1346
- if (left.hasItems !== right.hasItems) {
1347
- return left.hasItems ? -1 : 1;
1348
- }
1349
- if (query && left.score !== right.score) {
1350
- return right.score - left.score;
1351
- }
1352
- return left.index - right.index;
1353
- }).map((entry) => entry.group);
1354
- }
1355
- function mentionGroupBestMatchScore(group, query) {
1356
- if (!query) {
1357
- return 0;
1358
- }
1359
- return group.items.reduce(
1360
- (bestScore, item) => Math.max(bestScore, mentionItemMatchScore(item, query)),
1361
- 0
1362
- );
1363
- }
1364
- function mentionItemMatchScore(item, query) {
1365
- const primary = [];
1366
- const secondary = [];
1367
- let kindBoost = 0;
1368
- if (item.kind === "workspace-app") {
1369
- kindBoost = 8;
1370
- primary.push(item.name, item.appId, item.targetId);
1371
- secondary.push(item.description ?? "");
1372
- } else if (item.kind === "file") {
1373
- primary.push(item.name);
1374
- secondary.push(item.path, item.directoryPath);
1375
- } else if (item.kind === "session") {
1376
- primary.push(item.title);
1377
- secondary.push(
1378
- item.name,
1379
- item.initiatorName,
1380
- item.agentName,
1381
- item.inputPreview ?? "",
1382
- item.summaryPreview ?? ""
1383
- );
1384
- } else if (item.kind === "workspace-issue") {
1385
- primary.push(item.title, item.name);
1386
- secondary.push(
1387
- item.creatorName ?? "",
1388
- item.status ?? "",
1389
- item.contentPreview ?? ""
1390
- );
1391
- } else if (item.kind === "workspace-app-factory") {
1392
- primary.push(item.name, item.jobId, item.targetId);
1393
- secondary.push(item.action ?? "", item.contextPath ?? "");
1394
- }
1395
- const primaryScore = maxTextMatchScore(primary, query, {
1396
- contains: 60,
1397
- exact: 100,
1398
- prefix: 90,
1399
- wordPrefix: 80
1438
+ function preloadAgentMentionBrowse(input) {
1439
+ const controller = new AgentMentionSearchController({
1440
+ contextMentionProviders: input.contextMentionProviders
1400
1441
  });
1401
- const secondaryScore = maxTextMatchScore(secondary, query, {
1402
- contains: 25,
1403
- exact: 60,
1404
- prefix: 50,
1405
- wordPrefix: 40
1442
+ controller.preloadBrowse({
1443
+ workspaceId: input.workspaceId,
1444
+ currentUserId: input.currentUserId,
1445
+ sessionCwd: input.sessionCwd,
1446
+ filter: input.filter
1406
1447
  });
1407
- const score = Math.max(primaryScore, secondaryScore);
1408
- return score > 0 ? score + kindBoost : 0;
1409
1448
  }
1410
- function maxTextMatchScore(values, query, scores) {
1411
- return values.reduce(
1412
- (bestScore, value) => Math.max(bestScore, textMatchScore(value, query, scores)),
1449
+ function emptyAgentMentionRawGroups() {
1450
+ return {
1451
+ apps: [],
1452
+ opened_files: [],
1453
+ agent_generated_files: [],
1454
+ my_sessions: [],
1455
+ collab_sessions: [],
1456
+ issues: []
1457
+ };
1458
+ }
1459
+ function cloneAgentMentionRawGroups(rawGroups) {
1460
+ return {
1461
+ apps: [...rawGroups.apps],
1462
+ opened_files: [...rawGroups.opened_files],
1463
+ agent_generated_files: [...rawGroups.agent_generated_files],
1464
+ my_sessions: [...rawGroups.my_sessions],
1465
+ collab_sessions: [...rawGroups.collab_sessions],
1466
+ issues: [...rawGroups.issues]
1467
+ };
1468
+ }
1469
+ function totalCountsFromRawGroups(rawGroups) {
1470
+ return {
1471
+ apps: rawGroups.apps.length,
1472
+ opened_files: rawGroups.opened_files.length,
1473
+ agent_generated_files: rawGroups.agent_generated_files.length,
1474
+ my_sessions: rawGroups.my_sessions.length,
1475
+ collab_sessions: rawGroups.collab_sessions.length,
1476
+ issues: rawGroups.issues.length
1477
+ };
1478
+ }
1479
+ function rawGroupItemCount(rawGroups) {
1480
+ return Object.values(rawGroups).reduce(
1481
+ (count, items) => count + items.length,
1413
1482
  0
1414
1483
  );
1415
1484
  }
1416
- function textMatchScore(value, query, scores) {
1417
- const normalized = normalizeQuery(value).toLowerCase();
1418
- if (!normalized) {
1419
- return 0;
1485
+ function providerDiagnosticsSummary(diagnostics) {
1486
+ return diagnostics.map(
1487
+ (diagnostic) => `${diagnostic.providerId}:${diagnostic.status}:${diagnostic.resultCount}:${diagnostic.durationMs}`
1488
+ ).join(",");
1489
+ }
1490
+ function elapsedDiagnosticMs(now, startedAt) {
1491
+ const durationMs = now - startedAt;
1492
+ return Number.isFinite(durationMs) ? Math.max(0, Math.round(durationMs)) : 0;
1493
+ }
1494
+ function diagnosticErrorKind(error) {
1495
+ if (error instanceof Error && error.name.trim()) {
1496
+ return error.name.trim();
1420
1497
  }
1421
- if (normalized === query) {
1422
- return scores.exact;
1498
+ if (error === null) {
1499
+ return "null";
1423
1500
  }
1424
- if (normalized.startsWith(query)) {
1425
- return scores.prefix;
1501
+ return typeof error;
1502
+ }
1503
+ function logAgentMentionLifecycleDiagnostic(payload) {
1504
+ try {
1505
+ console.info(AGENT_MENTION_LIFECYCLE_LOG_PREFIX, JSON.stringify(payload));
1506
+ } catch {
1426
1507
  }
1427
- if (normalized.split(/[^a-z0-9]+/i).some((word) => word.startsWith(query))) {
1428
- return scores.wordPrefix;
1508
+ try {
1509
+ getOptionalAgentHostApi()?.debug?.logRuntimeDiagnostics?.({
1510
+ source: "renderer-workspace-surface",
1511
+ level: "info",
1512
+ event: `agent-gui.mention.${payload.event}`,
1513
+ // i18n-check-ignore: Internal diagnostic log message.
1514
+ message: "Agent GUI mention search lifecycle event.",
1515
+ details: payload.details
1516
+ });
1517
+ } catch {
1429
1518
  }
1430
- return normalized.includes(query) ? scores.contains : 0;
1519
+ }
1520
+ function normalizeSessionMentionItemsForMySessions(input) {
1521
+ return input.items.filter((item) => item.kind === "session").filter(
1522
+ (item) => input.currentUserId ? item.scope === "my_sessions" : true
1523
+ ).map(
1524
+ (item) => item.scope === "my_sessions" ? item : { ...item, scope: "my_sessions" }
1525
+ );
1431
1526
  }
1432
1527
  function providerItemToAgentMentionItem(input) {
1433
1528
  const label = compactText(input.label);
@@ -1838,7 +1933,7 @@ function shouldRenderMentionGroupLabel(input) {
1838
1933
  if (shouldSuppressFileSearchGroupChrome(input.filter, input.query)) {
1839
1934
  return false;
1840
1935
  }
1841
- if (input.filter === "all" || input.groupCount !== 1) {
1936
+ if (input.groupCount !== 1) {
1842
1937
  return true;
1843
1938
  }
1844
1939
  return agentMentionGroupLabel(input.groupId) !== agentMentionFilterLabel(input.filter);
@@ -1886,7 +1981,7 @@ function agentMentionItemToRowItem(item) {
1886
1981
  iconUrl: item.iconUrl ?? null
1887
1982
  };
1888
1983
  }
1889
- if (item.kind === "workspace-app-bundle") {
1984
+ if (item.kind === "workspace-reference") {
1890
1985
  return {
1891
1986
  kind: "app",
1892
1987
  name: item.name,
@@ -1963,9 +2058,6 @@ function mentionStatusTone(status) {
1963
2058
  return "neutral";
1964
2059
  }
1965
2060
  function browseHintForFilter(filter) {
1966
- if (filter === "all") {
1967
- return translate("agentHost.agentGui.contextPickerBrowseAllHint");
1968
- }
1969
2061
  switch (filter) {
1970
2062
  case "app":
1971
2063
  return translate("agentHost.agentGui.contextPickerBrowseAppHint");
@@ -2020,10 +2112,12 @@ function shouldShowBrowseSearchHint(input) {
2020
2112
 
2021
2113
  export {
2022
2114
  AGENT_MENTION_FILTER_TAB_ORDER,
2115
+ DEFAULT_AGENT_MENTION_FILTER,
2023
2116
  AgentMentionSearchController,
2117
+ preloadAgentMentionBrowse,
2024
2118
  flattenAgentMentionPaletteEntries,
2025
2119
  groupStartKeys,
2026
2120
  AgentFileMentionPalette,
2027
2121
  AgentContextMentionPalette
2028
2122
  };
2029
- //# sourceMappingURL=chunk-SVOGXWFJ.js.map
2123
+ //# sourceMappingURL=chunk-VNAQ6QFE.js.map