@chainingintention/pi-web-cn 1.202608.9 → 1.202608.11

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 (187) hide show
  1. package/README.md +2 -0
  2. package/dist/cli.js +123 -72
  3. package/dist/cli.js.map +1 -1
  4. package/dist/client/assets/{CodeViewer-B9BLGnQ2.js → CodeViewer-DCl56K0Z.js} +2 -2
  5. package/dist/client/assets/{TerminalPanel-C1BWg5W2.js → TerminalPanel-DCvoEjUF.js} +6 -6
  6. package/dist/client/assets/{index-x7EWN9ro.js → index-CMvms5cF.js} +534 -512
  7. package/dist/client/index.html +1 -1
  8. package/dist/config.js +39 -18
  9. package/dist/config.js.map +1 -1
  10. package/dist/nativeServices/serviceAction.js +128 -0
  11. package/dist/nativeServices/serviceAction.js.map +1 -0
  12. package/dist/pi-web-plugins/git/browser/git-contract.js +108 -0
  13. package/dist/pi-web-plugins/git/browser/git-panel.js +609 -0
  14. package/dist/pi-web-plugins/git/browser/gitFileList.js +43 -0
  15. package/dist/pi-web-plugins/git/browser/gitFileShared.js +16 -0
  16. package/dist/pi-web-plugins/git/browser/gitFileTree.js +81 -0
  17. package/dist/pi-web-plugins/git/browser/gitFileViewPreference.js +35 -0
  18. package/dist/pi-web-plugins/git/browser/gitRoute.js +42 -0
  19. package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +10 -0
  20. package/dist/pi-web-plugins/git/browser/unifiedDiff.js +301 -0
  21. package/dist/pi-web-plugins/git/git-backend.js +433 -0
  22. package/dist/pi-web-plugins/git/package.json +15 -0
  23. package/dist/pi-web-plugins/git/server-plugin.js +176 -0
  24. package/dist/pi-web-plugins/info/infoInternals.js +1 -1
  25. package/dist/pi-web-plugins/info/pi-web-plugin.js +2 -2
  26. package/dist/pi-web-plugins/relays/pi-web-plugin.js +1 -1
  27. package/dist/pi-web-plugins/relays/relayDiscovery.js +128 -23
  28. package/dist/pi-web-plugins/relays/relaysPanelElement.js +138 -16
  29. package/dist/pi-web-plugins/updates/pi-web-plugin.js +1 -1
  30. package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +1 -1
  31. package/dist/piWebVersionReport.js +63 -4
  32. package/dist/piWebVersionReport.js.map +1 -1
  33. package/dist/plugin-api.d.ts +40 -18
  34. package/dist/pluginRecoveryCli.js +172 -0
  35. package/dist/pluginRecoveryCli.js.map +1 -0
  36. package/dist/server/activity/workspaceActivityService.js +7 -1
  37. package/dist/server/activity/workspaceActivityService.js.map +1 -1
  38. package/dist/server/app.js +49 -23
  39. package/dist/server/app.js.map +1 -1
  40. package/dist/server/configRoutes.js +4 -5
  41. package/dist/server/configRoutes.js.map +1 -1
  42. package/dist/server/machines/machineClient.js +23 -4
  43. package/dist/server/machines/machineClient.js.map +1 -1
  44. package/dist/server/machines/machineProxyRoutes.js +162 -8
  45. package/dist/server/machines/machineProxyRoutes.js.map +1 -1
  46. package/dist/server/piWebPluginCatalog.js +441 -0
  47. package/dist/server/piWebPluginCatalog.js.map +1 -0
  48. package/dist/server/piWebPluginLifecycle.js +162 -0
  49. package/dist/server/piWebPluginLifecycle.js.map +1 -0
  50. package/dist/server/piWebPluginService.js +55 -7
  51. package/dist/server/piWebPluginService.js.map +1 -1
  52. package/dist/server/plugins/pluginBackendProxyRoutes.js +80 -0
  53. package/dist/server/plugins/pluginBackendProxyRoutes.js.map +1 -0
  54. package/dist/server/plugins/serverPluginExec.js +184 -0
  55. package/dist/server/plugins/serverPluginExec.js.map +1 -0
  56. package/dist/server/plugins/serverPluginRuntime.js +480 -0
  57. package/dist/server/plugins/serverPluginRuntime.js.map +1 -0
  58. package/dist/server/realtime/sessionEventHub.js +13 -0
  59. package/dist/server/realtime/sessionEventHub.js.map +1 -1
  60. package/dist/server/realtime/sessionEventScope.js +8 -1
  61. package/dist/server/realtime/sessionEventScope.js.map +1 -1
  62. package/dist/server/requestCancellation.js +28 -0
  63. package/dist/server/requestCancellation.js.map +1 -0
  64. package/dist/server/sessiond/agentProcessEnvironment.js +61 -0
  65. package/dist/server/sessiond/agentProcessEnvironment.js.map +1 -0
  66. package/dist/server/sessiond/managementProjectResolver.js +16 -0
  67. package/dist/server/sessiond/managementProjectResolver.js.map +1 -0
  68. package/dist/server/sessiond/pluginBackendRoutes.js +78 -0
  69. package/dist/server/sessiond/pluginBackendRoutes.js.map +1 -0
  70. package/dist/server/sessiond/sessionProxyRoutes.js +1 -0
  71. package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
  72. package/dist/server/sessiond/sessionServiceDependencies.js +0 -1
  73. package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -1
  74. package/dist/server/sessiond/sessiondStateOwnership.js +139 -0
  75. package/dist/server/sessiond/sessiondStateOwnership.js.map +1 -0
  76. package/dist/server/sessiond/workspaceCatalogRoutes.js +38 -0
  77. package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -0
  78. package/dist/server/sessiond/workspaceRemovalRoutes.js +56 -0
  79. package/dist/server/sessiond/workspaceRemovalRoutes.js.map +1 -0
  80. package/dist/server/sessiond.js +98 -14
  81. package/dist/server/sessiond.js.map +1 -1
  82. package/dist/server/sessions/authService.js +15 -51
  83. package/dist/server/sessions/authService.js.map +1 -1
  84. package/dist/server/sessions/dockerEnvironmentFacts.js +181 -0
  85. package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -0
  86. package/dist/server/sessions/piSessionManagerGateway.js +129 -2
  87. package/dist/server/sessions/piSessionManagerGateway.js.map +1 -1
  88. package/dist/server/sessions/piSessionService.js +131 -97
  89. package/dist/server/sessions/piSessionService.js.map +1 -1
  90. package/dist/server/sessions/sessionCommandService.js +15 -1
  91. package/dist/server/sessions/sessionCommandService.js.map +1 -1
  92. package/dist/server/sessions/sessionEnvironmentFacts.js +48 -0
  93. package/dist/server/sessions/sessionEnvironmentFacts.js.map +1 -0
  94. package/dist/server/sessions/sessionFileFormat.js +27 -0
  95. package/dist/server/sessions/sessionFileFormat.js.map +1 -0
  96. package/dist/server/sessions/sessionFileHeader.js +82 -23
  97. package/dist/server/sessions/sessionFileHeader.js.map +1 -1
  98. package/dist/server/sessions/sessionRoutes.js +16 -2
  99. package/dist/server/sessions/sessionRoutes.js.map +1 -1
  100. package/dist/server/sessions/sessionSummaryScanner.js +491 -0
  101. package/dist/server/sessions/sessionSummaryScanner.js.map +1 -0
  102. package/dist/server/sessions/spawnSubsessionTool.js +4 -8
  103. package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
  104. package/dist/server/sessions/spawnTargetResolver.js +2 -2
  105. package/dist/server/sessions/spawnTargetResolver.js.map +1 -1
  106. package/dist/server/status/machineStatusRoutes.js +10 -0
  107. package/dist/server/status/machineStatusRoutes.js.map +1 -0
  108. package/dist/server/status/machineStatusService.js +115 -0
  109. package/dist/server/status/machineStatusService.js.map +1 -0
  110. package/dist/server/status/workspaceAttribution.js +71 -0
  111. package/dist/server/status/workspaceAttribution.js.map +1 -0
  112. package/dist/server/terminalProxyRoutes.js.map +1 -1
  113. package/dist/server/workspaceExplorerRoutes.js +12 -25
  114. package/dist/server/workspaceExplorerRoutes.js.map +1 -1
  115. package/dist/server/workspaces/effectivePathAccess.js +3 -2
  116. package/dist/server/workspaces/effectivePathAccess.js.map +1 -1
  117. package/dist/server/workspaces/fileContentService.js +17 -9
  118. package/dist/server/workspaces/fileContentService.js.map +1 -1
  119. package/dist/server/workspaces/fileOperationService.js +4 -17
  120. package/dist/server/workspaces/fileOperationService.js.map +1 -1
  121. package/dist/server/workspaces/filePreviewResponseHeaders.js +18 -0
  122. package/dist/server/workspaces/filePreviewResponseHeaders.js.map +1 -0
  123. package/dist/server/workspaces/filePreviewResponsePolicy.js +55 -0
  124. package/dist/server/workspaces/filePreviewResponsePolicy.js.map +1 -0
  125. package/dist/server/workspaces/filePreviewService.js +81 -0
  126. package/dist/server/workspaces/filePreviewService.js.map +1 -0
  127. package/dist/server/workspaces/projectWorkspaceCwds.js +2 -2
  128. package/dist/server/workspaces/projectWorkspaceCwds.js.map +1 -1
  129. package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js +416 -0
  130. package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js.map +1 -0
  131. package/dist/server/workspaces/workspaceCatalog.js +87 -0
  132. package/dist/server/workspaces/workspaceCatalog.js.map +1 -0
  133. package/dist/server/workspaces/workspaceContext.js +5 -5
  134. package/dist/server/workspaces/workspaceContext.js.map +1 -1
  135. package/dist/server/workspaces/workspaceDeletionRoutes.js +114 -99
  136. package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -1
  137. package/dist/server/workspaces/workspaceProviderRegistry.js +650 -0
  138. package/dist/server/workspaces/workspaceProviderRegistry.js.map +1 -0
  139. package/dist/server/workspaces/workspaceRemovalService.js +258 -0
  140. package/dist/server/workspaces/workspaceRemovalService.js.map +1 -0
  141. package/dist/server/workspaces/workspaceRouteContext.js +2 -1
  142. package/dist/server/workspaces/workspaceRouteContext.js.map +1 -1
  143. package/dist/server/workspaces/workspaceRouteErrors.js +7 -0
  144. package/dist/server/workspaces/workspaceRouteErrors.js.map +1 -0
  145. package/dist/server/workspaces/worktreePreRemoveHook.js +39 -0
  146. package/dist/server/workspaces/worktreePreRemoveHook.js.map +1 -0
  147. package/dist/server-plugin-api.d.ts +115 -0
  148. package/dist/server-plugin-api.js +2 -0
  149. package/dist/server-plugin-api.js.map +1 -0
  150. package/dist/serverPluginRecovery.js +138 -0
  151. package/dist/serverPluginRecovery.js.map +1 -0
  152. package/dist/sessiond/config.js +6 -0
  153. package/dist/sessiond/config.js.map +1 -1
  154. package/dist/sessiond/sessionDaemonClient.js +7 -6
  155. package/dist/sessiond/sessionDaemonClient.js.map +1 -1
  156. package/dist/shared/apiTypes.js +2 -0
  157. package/dist/shared/apiTypes.js.map +1 -1
  158. package/dist/shared/capabilities.js +2 -0
  159. package/dist/shared/capabilities.js.map +1 -1
  160. package/dist/shared/federatedRoutes.js +28 -2
  161. package/dist/shared/federatedRoutes.js.map +1 -1
  162. package/dist/shared/machineStatus.js +60 -0
  163. package/dist/shared/machineStatus.js.map +1 -0
  164. package/dist/shared/pluginApiTypes.d.ts +155 -0
  165. package/dist/shared/pluginBackendProtocol.js +110 -0
  166. package/dist/shared/pluginBackendProtocol.js.map +1 -0
  167. package/dist/shared/pluginIds.js +3 -0
  168. package/dist/shared/pluginIds.js.map +1 -1
  169. package/dist/shared/pluginRecoveryCommands.js +14 -0
  170. package/dist/shared/pluginRecoveryCommands.js.map +1 -0
  171. package/dist/shared/workspaceFiles.js +41 -2
  172. package/dist/shared/workspaceFiles.js.map +1 -1
  173. package/dist/shared/workspaceRemovalProtocol.js +24 -0
  174. package/dist/shared/workspaceRemovalProtocol.js.map +1 -0
  175. package/docs/config.md +13 -6
  176. package/docs/plugins.md +15 -21
  177. package/package.json +26 -8
  178. package/server-plugin-api.d.ts +1 -0
  179. package/dist/client/assets/UnifiedDiffViewer-ClTQ6Ok0.js +0 -39
  180. package/dist/plugin-api/unstable.d.ts +0 -22
  181. package/dist/server/sessions/parentSessionLocator.js +0 -75
  182. package/dist/server/sessions/parentSessionLocator.js.map +0 -1
  183. package/dist/server/workspaces/imagePreviewService.js +0 -40
  184. package/dist/server/workspaces/imagePreviewService.js.map +0 -1
  185. package/dist/shared/apiTypes.d.ts +0 -1323
  186. package/dist/shared/thinkingLevels.d.ts +0 -29
  187. package/plugin-api/unstable.d.ts +0 -1
@@ -1,8 +1,10 @@
1
1
  import { readdir } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
- import { dirname, isAbsolute, join, resolve } from "node:path";
3
+ import { basename, dirname, isAbsolute, join, resolve } from "node:path";
4
4
  import { SessionManager, SettingsManager } from "@earendil-works/pi-coding-agent";
5
5
  import { canonicalizeStoredCwd, cwdPathsEqual } from "../workingDirectory.js";
6
+ import { readSessionHeaderSummary } from "./sessionFileHeader.js";
7
+ import { SessionSummaryScanner } from "./sessionSummaryScanner.js";
6
8
  export class SessionDirResolver {
7
9
  constructor(options) {
8
10
  this.agentDir = options.agentDir;
@@ -38,10 +40,36 @@ export function createPiSessionManagerGateway(options) {
38
40
  class SettingsAwarePiSessionManagerGateway {
39
41
  constructor(resolver) {
40
42
  this.resolver = resolver;
43
+ /**
44
+ * One memoized scanner per gateway: its per-file summary memo lives as long
45
+ * as the daemon, so repeated listings answer unchanged files from one stat
46
+ * and re-scan changed ones whole. Invalidation is automatic (file identity +
47
+ * size; see SessionSummaryScanner), with `invalidateSessionFile` for the
48
+ * in-place rewrites those checks cannot see.
49
+ */
50
+ this.summaryScanner = new SessionSummaryScanner();
41
51
  }
42
52
  async list(cwd) {
43
53
  const resolution = this.resolver.resolve(cwd);
44
- return filterSessionsForCwd(await listSessionsInDir(resolution.sessionDir), cwd);
54
+ // Lightweight streaming summaries instead of the SDK's full-transcript
55
+ // listing: same fields, but message bodies are never parsed once the first
56
+ // user message is found. The cross-project cleanup listing (listAll) keeps
57
+ // the SDK path.
58
+ const sessions = (await this.summaryScanner.scanSessionSummariesInDir(resolution.sessionDir)).map((session) => ({
59
+ ...session,
60
+ cwd: canonicalizeStoredCwd(session.cwd),
61
+ }));
62
+ return filterSessionsForCwd(sessions, cwd);
63
+ }
64
+ resolveSessionFile(cwd, sessionId) {
65
+ const resolution = this.resolver.resolve(cwd);
66
+ return resolveSessionFileInDir(resolution.sessionDir, cwd, sessionId, readSessionHeaderSummary);
67
+ }
68
+ invalidateSessionFile(sessionFile) {
69
+ // Detach is the only flow that rewrites a session file in place (keeping
70
+ // the inode), and the summary memo cannot detect such rewrites from
71
+ // identity + size alone. Drop the entry so the next listing re-reads it.
72
+ this.summaryScanner.invalidate(sessionFile);
45
73
  }
46
74
  create(cwd, options) {
47
75
  const resolution = this.resolver.resolve(cwd);
@@ -85,6 +113,105 @@ export function filterSessionsForCwd(sessions, cwd) {
85
113
  // resolve to this process's cwd and produce false matches.
86
114
  return sessions.filter((session) => session.cwd !== "" && cwdPathsEqual(session.cwd, cwd));
87
115
  }
116
+ /**
117
+ * Locate a session file by id without parsing transcripts.
118
+ *
119
+ * Session filenames embed the session id (`<timestamp>_<sessionId>.jsonl`), so
120
+ * exact and prefix matches are normally found from the directory names alone
121
+ * and confirmed by one header read. Filename candidates that fail header
122
+ * verification (a copy whose header holds a different session) do not end the
123
+ * search: the remaining files are checked too, so sessions in renamed or
124
+ * hand-named files still resolve. Headers decide: a file whose header id or cwd
125
+ * does not match is not the session.
126
+ *
127
+ * Among matches, an exact header id wins over a prefix match wherever it
128
+ * appears. Ambiguous prefix candidates are considered in two buckets: filename
129
+ * matches before remaining files, with each bucket sorted by the creation time
130
+ * embedded in SDK-style names (see `byNewestEmbeddedTimestamp`).
131
+ *
132
+ * The header's cwd is returned canonicalized, matching what `list` reports.
133
+ */
134
+ export async function resolveSessionFileInDir(sessionDir, cwd, sessionId, readHeader) {
135
+ const sessionFiles = await listSessionFiles(sessionDir);
136
+ const fileNameMatches = [];
137
+ const remainingFiles = [];
138
+ for (const sessionFile of sessionFiles) {
139
+ (fileNameMatchesSessionId(basename(sessionFile), sessionId) ? fileNameMatches : remainingFiles).push(sessionFile);
140
+ }
141
+ fileNameMatches.sort(byNewestEmbeddedTimestamp);
142
+ remainingFiles.sort(byNewestEmbeddedTimestamp);
143
+ // A prefix match is only provisional: an exact header id wins over it
144
+ // wherever it appears, so the search continues after one is found.
145
+ let prefixMatch;
146
+ // Filename matches first; the remaining files follow so a renamed file still
147
+ // resolves when every filename candidate fails header verification.
148
+ for (const sessionFile of [...fileNameMatches, ...remainingFiles]) {
149
+ const header = await readHeader(sessionFile);
150
+ if (header?.cwd === undefined)
151
+ continue;
152
+ if (!cwdPathsEqual(header.cwd, cwd))
153
+ continue;
154
+ if (header.id === sessionId) {
155
+ return { id: header.id, cwd: canonicalizeStoredCwd(header.cwd), path: sessionFile };
156
+ }
157
+ if (prefixMatch === undefined && header.id.startsWith(sessionId)) {
158
+ prefixMatch = { id: header.id, cwd: canonicalizeStoredCwd(header.cwd), path: sessionFile };
159
+ }
160
+ }
161
+ return prefixMatch;
162
+ }
163
+ /**
164
+ * Order session files newest-first by the timestamp embedded in SDK-style names
165
+ * (`<timestamp>_<sessionId>.jsonl`; the SDK stamps the session's creation time
166
+ * into the name, so this is creation-time order). Files sharing a timestamp,
167
+ * or without one, fall back to a plain code-unit path comparison — never
168
+ * `localeCompare`, whose result varies by locale — so the order is
169
+ * deterministic everywhere.
170
+ *
171
+ * This deliberately drifts from the listing, which orders by modified time:
172
+ * the resolver never stats transcript files, so ambiguous prefix candidates
173
+ * within each bucket are considered in this creation-time order instead.
174
+ */
175
+ function byNewestEmbeddedTimestamp(a, b) {
176
+ const timestampA = embeddedFileNameTimestamp(basename(a));
177
+ const timestampB = embeddedFileNameTimestamp(basename(b));
178
+ if (timestampA !== timestampB)
179
+ return timestampA < timestampB ? 1 : -1;
180
+ return a < b ? 1 : a > b ? -1 : 0;
181
+ }
182
+ /** The creation timestamp embedded in an SDK-style session file name ("" when absent). */
183
+ function embeddedFileNameTimestamp(fileName) {
184
+ const stem = fileName.slice(0, -".jsonl".length);
185
+ const separatorIndex = stem.indexOf("_");
186
+ return separatorIndex === -1 ? "" : stem.slice(0, separatorIndex);
187
+ }
188
+ /** Whether a `.jsonl` file name embeds `sessionId` (exactly or as a prefix). */
189
+ function fileNameMatchesSessionId(fileName, sessionId) {
190
+ const embeddedId = embeddedFileNameSessionId(fileName);
191
+ return embeddedId !== undefined && (embeddedId === sessionId || embeddedId.startsWith(sessionId));
192
+ }
193
+ /**
194
+ * The session id embedded in an SDK-style session file name
195
+ * (`<timestamp>_<sessionId>.jsonl`). The timestamp never contains `_`, so the
196
+ * id is everything after the first separator; files without one fall back to
197
+ * the whole stem, and header verification discards false guesses.
198
+ */
199
+ function embeddedFileNameSessionId(fileName) {
200
+ const stem = fileName.slice(0, -".jsonl".length);
201
+ const separatorIndex = stem.indexOf("_");
202
+ const candidate = separatorIndex === -1 ? stem : stem.slice(separatorIndex + 1);
203
+ return candidate === "" ? undefined : candidate;
204
+ }
205
+ async function listSessionFiles(sessionDir) {
206
+ try {
207
+ const names = await readdir(sessionDir);
208
+ return names.filter((name) => name.endsWith(".jsonl")).map((name) => join(sessionDir, name));
209
+ }
210
+ catch {
211
+ // Matches the SDK listing behavior: an unreadable directory lists nothing.
212
+ return [];
213
+ }
214
+ }
88
215
  function uniqueSessionsByPath(sessions) {
89
216
  const byPath = new Map();
90
217
  for (const session of sessions)
@@ -1 +1 @@
1
- {"version":3,"file":"piSessionManagerGateway.js","sourceRoot":"","sources":["../../../src/server/sessions/piSessionManagerGateway.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"piSessionManagerGateway.js","sourceRoot":"","sources":["../../../src/server/sessions/piSessionManagerGateway.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { constants, realpathSync, statSync } from "node:fs";
2
2
  import { copyFile, mkdir, readFile, writeFile } from "node:fs/promises";
3
3
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, createEditToolDefinition, createFindToolDefinition, createGrepToolDefinition, getAgentDir, createLsToolDefinition, createReadToolDefinition, createWriteToolDefinition, defineTool, ModelRuntime, readStoredCredential, SessionManager, } from "@earendil-works/pi-coding-agent";
5
+ import { createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, createEditToolDefinition, createFindToolDefinition, createGrepToolDefinition, getAgentDir, createLsToolDefinition, createReadToolDefinition, createWriteToolDefinition, defineTool, readStoredCredential, SessionManager, } from "@earendil-works/pi-coding-agent";
6
6
  import { projectBrowserMessage } from "../browserMessageProjection.js";
7
7
  import { pageMessagesAtSafeBoundary } from "./messagePaging.js";
8
8
  import { eventScopeFromManagementContext, managementContextKey, NORMAL_SESSION_EVENT_SCOPE } from "../realtime/sessionEventScope.js";
@@ -20,10 +20,9 @@ import { createPiSessionManagerGateway } from "./piSessionManagerGateway.js";
20
20
  import { SessionPinStore } from "./sessionPinStore.js";
21
21
  import { SessionActivityCoordinator } from "./sessionActivityCoordinator.js";
22
22
  import { searchSessionContent } from "./sessionContentSearch.js";
23
+ import { createLocalOnlyModelRuntime } from "./authService.js";
23
24
  import { canonicalizeStoredCwd, cwdPathsEqual } from "../workingDirectory.js";
24
25
  import { readSessionHeaderSummary } from "./sessionFileHeader.js";
25
- import { countOutOfListingChildren, locateOutOfListingParents } from "./parentSessionLocator.js";
26
- import { siblingWorkspaceCwds } from "../workspaces/projectWorkspaceCwds.js";
27
26
  import { workbenchAccessHandle } from "../managementEmbed.js";
28
27
  import { DEFAULT_EXTENSION_DIALOGS_TIMEOUT_MS, piWebDataDir } from "../../config.js";
29
28
  import { createScopedSettingsManager, resolveSettingsScopeDirectory } from "./projectSettingsScope.js";
@@ -89,6 +88,9 @@ function spawnTargetError(decision) {
89
88
  return new Error("派生会话不在已注册项目中");
90
89
  return new Error(`cwd 必须是此项目的工作区。允许的路径:${decision.allowedCwds.join(", ")}`);
91
90
  }
91
+ function subsessionCwdError(spawningCwd, requestedCwd) {
92
+ return new Error(`跟踪子会话只能在父会话的工作区中运行(${spawningCwd}),不能使用 ${requestedCwd}。如需在其它工作区运行,请使用 spawn_session 创建独立会话。`);
93
+ }
92
94
  function modelSpecOf(model) {
93
95
  return `${model.provider}/${model.id}`;
94
96
  }
@@ -402,7 +404,13 @@ function createRuntimeWithContextAndOneShotSessionOptions(createRuntime, managem
402
404
  });
403
405
  };
404
406
  }
405
- function createDefaultRuntimeFactory(normalModelRuntimeForCwd, managementModelRuntime, resolveSettingsScope, spawn, subsessions, askUser, workbench, logger = noopLogger, managementAudit, managementProjectIdForCwd) {
407
+ /** Append PI WEB-owned prompt sections after the operator's Pi prompt files. */
408
+ export function piWebResourceLoaderOptions(appendSystemPromptSections) {
409
+ if (appendSystemPromptSections.length === 0)
410
+ return undefined;
411
+ return { appendSystemPromptOverride: (base) => [...base, ...appendSystemPromptSections] };
412
+ }
413
+ function createDefaultRuntimeFactory(normalModelRuntimeForCwd, managementModelRuntime, resolveSettingsScope, spawn, subsessions, askUser, workbench, logger = noopLogger, managementAudit, managementProjectIdForCwd, appendSystemPromptSections = []) {
406
414
  return async ({ cwd, agentDir, sessionManager, sessionStartEvent, managementContext, initialModel, initialThinkingLevel, delegationToolsEnabled = true }) => {
407
415
  const scopedModelRuntime = managementContext === undefined ? await normalModelRuntimeForCwd(cwd) : await managementModelRuntime();
408
416
  if (managementContext !== undefined) {
@@ -421,7 +429,14 @@ function createDefaultRuntimeFactory(normalModelRuntimeForCwd, managementModelRu
421
429
  scopeDirectory: await resolveSettingsScope(cwd, "normal"),
422
430
  globalAgentDir: agentDir,
423
431
  });
424
- const services = await createAgentSessionServices({ cwd, agentDir, modelRuntime: scopedModelRuntime, settingsManager });
432
+ const resourceLoaderOptions = piWebResourceLoaderOptions(appendSystemPromptSections);
433
+ const services = await createAgentSessionServices({
434
+ cwd,
435
+ agentDir,
436
+ modelRuntime: scopedModelRuntime,
437
+ settingsManager,
438
+ ...(resourceLoaderOptions === undefined ? {} : { resourceLoaderOptions }),
439
+ });
425
440
  const customTools = createPiWebCustomToolDefinitions(cwd, delegationToolsEnabled, spawn, subsessions, askUser);
426
441
  const result = await createAgentSessionFromServices({
427
442
  services,
@@ -592,7 +607,6 @@ export class PiSessionService {
592
607
  /** Parent id/file identities whose persisted links have already been loaded. */
593
608
  this.subsessionHydratedParents = new Set();
594
609
  /** Session file path -> its parsed header. Headers are written once, so successful reads are cached. */
595
- this.sessionHeaderCache = new Map();
596
610
  /**
597
611
  * Tracked subsession id -> whether a completion notification is armed.
598
612
  * Armed when the child starts working; firing on completion disarms it so a
@@ -605,20 +619,6 @@ export class PiSessionService {
605
619
  this.pendingUnreadMutations = [];
606
620
  this.unreadPublicationFlushRequested = false;
607
621
  this.unreadPublicationStopped = false;
608
- /**
609
- * Read a session file header, memoized per path. Pi writes the header once at
610
- * session creation, so a successful read stays valid for the process lifetime;
611
- * failures are not cached so a session file that appears later is picked up.
612
- */
613
- this.readCachedSessionHeader = async (sessionFile) => {
614
- const cached = this.sessionHeaderCache.get(sessionFile);
615
- if (cached !== undefined)
616
- return cached;
617
- const header = await readSessionHeaderSummary(sessionFile);
618
- if (header !== undefined)
619
- this.sessionHeaderCache.set(sessionFile, header);
620
- return header;
621
- };
622
622
  this.archiveStore = deps.archiveStore ?? new SessionArchiveStore();
623
623
  this.pinStore = deps.pinStore ?? new SessionPinStore(join(deps.dataDir ?? piWebDataDir(), "session-pins.json"));
624
624
  this.agentDir = deps.agentDir ?? getAgentDir();
@@ -631,7 +631,7 @@ export class PiSessionService {
631
631
  });
632
632
  let defaultModelRuntime;
633
633
  const resolveDefaultModelRuntime = () => {
634
- defaultModelRuntime ??= deps.modelRuntime === undefined ? ModelRuntime.create() : Promise.resolve(deps.modelRuntime);
634
+ defaultModelRuntime ??= deps.modelRuntime === undefined ? createLocalOnlyModelRuntime() : Promise.resolve(deps.modelRuntime);
635
635
  return defaultModelRuntime;
636
636
  };
637
637
  this.normalModelRuntimeForCwd = deps.normalModelRuntimeForCwd ?? resolveDefaultModelRuntime;
@@ -640,7 +640,6 @@ export class PiSessionService {
640
640
  ? resolveDefaultModelRuntime
641
641
  : () => Promise.resolve(managementModelRuntime);
642
642
  this.spawnTargets = deps.spawnTargets;
643
- this.projectWorkspaces = deps.projectWorkspaces;
644
643
  this.logger = deps.logger ?? noopLogger;
645
644
  this.normalToolAudit = deps.normalToolAudit;
646
645
  this.managementAudit = deps.managementAudit;
@@ -648,13 +647,14 @@ export class PiSessionService {
648
647
  this.now = deps.now ?? (() => new Date());
649
648
  this.notificationStore = deps.notificationStore ?? new SessionNotificationStore();
650
649
  this.unreadStore = deps.unreadStore ?? new SessionUnreadStore();
650
+ this.onUnreadChanged = deps.onUnreadChanged;
651
651
  this.pendingAskStore = deps.pendingAskStore ?? new PendingAskStore();
652
652
  this.pendingExtensionDialogStore = deps.pendingExtensionDialogStore ?? new PendingExtensionDialogStore();
653
653
  this.extensionDialogsTimeoutMs = deps.extensionDialogsTimeoutMs ?? DEFAULT_EXTENSION_DIALOGS_TIMEOUT_MS;
654
654
  this.catalogRefreshStatus = deps.catalogRefreshStatus;
655
655
  this.unreadPublicationRetryInitialMs = Math.max(0, deps.unreadPublicationRetryDelayMs ?? DEFAULT_UNREAD_PUBLICATION_RETRY_MS);
656
656
  this.unreadPublicationRetryDelayMs = this.unreadPublicationRetryInitialMs;
657
- // Subsessions are a beta capability gated behind their own flag, and they
657
+ // Subsessions are gated behind their own flag, and they
658
658
  // also require the spawn capability (they share its project-scope resolver).
659
659
  const subsessionsActive = this.spawnTargets !== undefined && deps.subsessionsEnabled === true;
660
660
  this.createRuntime = deps.createRuntime ?? createDefaultRuntimeFactory(this.normalModelRuntimeForCwd, this.managementModelRuntime, (cwd, mode) => this.resolveSettingsScopeDirectory(cwd, mode), this.spawnTargets === undefined ? undefined : (input) => this.spawnSession(input), !subsessionsActive ? undefined : {
@@ -662,7 +662,7 @@ export class PiSessionService {
662
662
  list: (parentSessionId, parentSessionFile) => this.listSubsessions(parentSessionId, parentSessionFile),
663
663
  check: (parentSessionId, sessionId, parentSessionFile) => this.checkSubsession(parentSessionId, sessionId, parentSessionFile),
664
664
  read: (parentSessionId, sessionId, query, parentSessionFile) => this.readSubsession(parentSessionId, sessionId, query, parentSessionFile),
665
- }, deps.askUserEnabled === true ? { open: (input) => this.openAsk(input) } : undefined, deps.workbench, this.logger, this.managementAudit, this.managementProjectIdForCwd);
665
+ }, deps.askUserEnabled === true ? { open: (input) => this.openAsk(input) } : undefined, deps.workbench, this.logger, this.managementAudit, this.managementProjectIdForCwd, deps.appendSystemPromptSections ?? []);
666
666
  this.createAgentRuntime = deps.createAgentRuntime ?? defaultCreateAgentRuntime;
667
667
  this.workspaceActivity = deps.workspaceActivity;
668
668
  this.heartbeat = setInterval(() => { this.publishHeartbeats(); }, deps.heartbeatIntervalMs ?? 2000);
@@ -775,7 +775,6 @@ export class PiSessionService {
775
775
  this.subsessionLinks.clear();
776
776
  this.subsessionHydratedParents.clear();
777
777
  this.subsessionNotifyArmed.clear();
778
- this.sessionHeaderCache.clear();
779
778
  this.notificationStore.clearAll("service-dispose");
780
779
  await Promise.all(activeSessions.map(async (active) => {
781
780
  active.unsubscribe();
@@ -854,67 +853,11 @@ export class PiSessionService {
854
853
  .map((record) => clientSessionFromArchivedRecord(record, sessionsById.get(record.sessionId)))
855
854
  .filter(isDefined);
856
855
  return {
857
- sessions: await this.withRelatedSessionsElsewhere([...unarchivedSessions, ...archivedSessions], cwd),
856
+ sessions: [...unarchivedSessions, ...archivedSessions],
858
857
  entriesById: new Map(sessions.map((session) => [session.id, session])),
859
858
  archivedById,
860
859
  };
861
860
  }
862
- /**
863
- * Annotate a listing with the session relationships that cross workspace
864
- * boundaries: where an out-of-listing parent lives, and how many children a
865
- * listed session has in sibling workspaces.
866
- *
867
- * Both directions are best-effort. An unreadable parent header or a sibling
868
- * workspace that cannot be listed leaves the session unannotated rather than
869
- * failing the listing, and the browser falls back to its generic states.
870
- */
871
- async withRelatedSessionsElsewhere(sessions, cwd) {
872
- const [parentLocations, childCounts] = await Promise.all([
873
- locateOutOfListingParents(sessions, cwd, this.readCachedSessionHeader),
874
- this.countChildrenInSiblingWorkspaces(sessions, cwd),
875
- ]);
876
- return sessions.map((session) => {
877
- const parent = session.parentSessionPath === undefined ? undefined : parentLocations.get(session.parentSessionPath);
878
- const childrenElsewhere = childCounts.get(session.path);
879
- if (parent === undefined && childrenElsewhere === undefined)
880
- return session;
881
- const annotated = { ...session };
882
- if (parent !== undefined) {
883
- annotated.parentSessionId = parent.parentSessionId;
884
- annotated.parentSessionCwd = parent.parentSessionCwd;
885
- }
886
- if (childrenElsewhere !== undefined)
887
- annotated.childSessionsElsewhere = childrenElsewhere;
888
- return annotated;
889
- });
890
- }
891
- /**
892
- * Count children of the listed sessions that live in other workspaces of the
893
- * same project.
894
- *
895
- * Only sibling workspaces are scanned: agents may only spawn into workspaces
896
- * of the spawning session's own project, so that bounds where a child can be.
897
- * Listing is skipped entirely when no project-workspace locator is configured
898
- * or the cwd belongs to no registered project.
899
- */
900
- async countChildrenInSiblingWorkspaces(sessions, cwd) {
901
- if (this.projectWorkspaces === undefined || sessions.length === 0)
902
- return new Map();
903
- try {
904
- const siblingCwds = await siblingWorkspaceCwds(this.projectWorkspaces, cwd);
905
- if (siblingCwds.length === 0)
906
- return new Map();
907
- const listings = await Promise.all(siblingCwds.map(async (siblingCwd) => {
908
- const entries = await this.sessionManager.list(siblingCwd);
909
- return entries.flatMap((entry) => entry.parentSessionPath === undefined ? [] : [entry.parentSessionPath]);
910
- }));
911
- return countOutOfListingChildren(sessions, listings.flat());
912
- }
913
- catch (error) {
914
- this.logger.info({ cwd, error: error instanceof Error ? error.message : String(error) }, "failed to count child sessions in sibling workspaces");
915
- return new Map();
916
- }
917
- }
918
861
  async start(cwd, options = {}) {
919
862
  if (options.managementContext === undefined)
920
863
  await this.normalModelRuntimeForCwd(cwd);
@@ -956,7 +899,7 @@ export class PiSessionService {
956
899
  async spawnSession(input) {
957
900
  if (this.spawnTargets === undefined)
958
901
  throw new Error("派生会话已禁用");
959
- const decision = await this.spawnTargets.resolveSpawnTarget(input.spawningCwd, input.cwd);
902
+ const decision = await this.spawnTargets.resolveSpawnTarget(input.spawningCwd, input.cwd, eventScopeFromManagementContext(input.managementContext));
960
903
  if (!decision.allowed)
961
904
  throw spawnTargetError(decision);
962
905
  // A model spec overrides the inherited model. Only a spec triggers a
@@ -981,16 +924,14 @@ export class PiSessionService {
981
924
  ...(modelUsed === undefined ? {} : { model: modelSpecOf(modelUsed) }),
982
925
  };
983
926
  }
984
- /**
985
- * Start a *tracked* child session on behalf of a LLM. Identical to
986
- * {@link spawnSession} in how the target cwd is resolved, but the child
987
- * records its parent (so it shows in the session tree) and is registered so
988
- * the parent is notified when it stops working and can inspect it later.
989
- */
927
+ /** Start a tracked child in the parent's workspace so it remains visible in the same session tree. */
990
928
  async spawnSubsession(input) {
991
929
  if (this.spawnTargets === undefined)
992
930
  throw new Error("派生会话已禁用");
993
- const decision = await this.spawnTargets.resolveSpawnTarget(input.spawningCwd, input.cwd);
931
+ if (input.cwd !== undefined && input.cwd !== "" && !cwdPathsEqual(input.cwd, input.spawningCwd)) {
932
+ throw subsessionCwdError(input.spawningCwd, input.cwd);
933
+ }
934
+ const decision = await this.spawnTargets.resolveSpawnTarget(input.spawningCwd, undefined, eventScopeFromManagementContext(input.managementContext));
994
935
  if (!decision.allowed)
995
936
  throw spawnTargetError(decision);
996
937
  // A model spec overrides the inherited model and is resolved against the
@@ -1033,7 +974,9 @@ export class PiSessionService {
1033
974
  * first so callers see newly configured providers and models.
1034
975
  */
1035
976
  async sessionModelCandidates(session) {
1036
- await session.modelRuntime.refresh();
977
+ // Pi 0.84 keeps request paths local-only; the bounded catalog refresher is
978
+ // the only path allowed to fetch provider catalogs over the network.
979
+ await session.modelRuntime.refresh({ allowNetwork: false });
1037
980
  return session.scopedModels.length > 0
1038
981
  ? session.scopedModels.map((scoped) => scoped.model)
1039
982
  : await session.modelRuntime.getAvailable();
@@ -1084,9 +1027,9 @@ export class PiSessionService {
1084
1027
  * work (`deliverAs: "followUp"`), which is how the run that `ask_user`
1085
1028
  * terminated continues.
1086
1029
  */
1087
- async submitAsk(ref, askId, submission) {
1030
+ async submitAsk(ref, askId, submission, managementContext) {
1088
1031
  await this.assertWritable(ref);
1089
- const session = await this.getOrOpen(ref);
1032
+ const session = await this.getOrOpen(ref, managementContext);
1090
1033
  // Checked before the store closes the ask so a refused delivery cannot
1091
1034
  // discard answers the user already submitted.
1092
1035
  this.assertTreeNavigationInactive(session, "answer questions");
@@ -1097,9 +1040,9 @@ export class PiSessionService {
1097
1040
  * question as unanswered: it was promised a follow-up message and would
1098
1041
  * otherwise wait for one that never comes.
1099
1042
  */
1100
- async cancelAsk(ref, askId) {
1043
+ async cancelAsk(ref, askId, managementContext) {
1101
1044
  await this.assertWritable(ref);
1102
- const session = await this.getOrOpen(ref);
1045
+ const session = await this.getOrOpen(ref, managementContext);
1103
1046
  this.assertTreeNavigationInactive(session, "dismiss questions");
1104
1047
  return this.closeAsk(session, this.pendingAskStore.cancel(session.sessionId, askId));
1105
1048
  }
@@ -1851,6 +1794,73 @@ export class PiSessionService {
1851
1794
  }
1852
1795
  }
1853
1796
  }
1797
+ async forkFromTree(ref, request, managementContext) {
1798
+ if (request.entryId.trim() === "")
1799
+ throw new Error("Session tree entry is required");
1800
+ const requestedSessionId = sessionIdFromLookup(ref);
1801
+ if (this.isTreeExclusiveSessionIdentityActive(requestedSessionId)) {
1802
+ throw new Error("Stop current session activity before forking the session tree");
1803
+ }
1804
+ await this.assertWritable(ref);
1805
+ const session = await this.getOrOpen(ref, managementContext);
1806
+ if (this.hasActiveWork(session))
1807
+ throw new Error("Stop current session activity before forking the session tree");
1808
+ const sourceSessionId = session.sessionId;
1809
+ const sourceEventScope = this.eventScopeForSession(session);
1810
+ const sourceCwd = session.sessionManager.getCwd();
1811
+ this.publishActivity(session, "正在从会话树条目分叉", "active");
1812
+ this.publishStatus(session);
1813
+ try {
1814
+ const result = await this.commandService.forkEntry(session.sessionId, request.entryId, sourceEventScope, {
1815
+ expectedLeafId: request.expectedLeafId,
1816
+ });
1817
+ if (result.type === "unsupported")
1818
+ throw new Error(result.message);
1819
+ if (result.type !== "done")
1820
+ throw new Error("Session fork is unavailable");
1821
+ if (result.session === undefined) {
1822
+ if (this.isCurrentActiveSession(session)) {
1823
+ this.publishActivity(session, "会话分叉已取消", "idle");
1824
+ this.publishStatus(session);
1825
+ }
1826
+ return { cancelled: true };
1827
+ }
1828
+ const forked = this.activeForLookup({ id: result.session.id, cwd: result.session.cwd }, managementContext)?.runtime.session;
1829
+ if (forked !== undefined && this.isCurrentActiveSession(forked)) {
1830
+ this.publishActivity(forked, "会话已分叉", "idle");
1831
+ this.publishStatus(forked);
1832
+ }
1833
+ if (result.session.id !== sourceSessionId)
1834
+ this.clearSupersededSessionActivity(sourceSessionId, sourceCwd, sourceEventScope);
1835
+ return {
1836
+ cancelled: false,
1837
+ session: result.session,
1838
+ ...(result.promptDraft === undefined ? {} : { promptDraft: result.promptDraft }),
1839
+ };
1840
+ }
1841
+ catch (error) {
1842
+ const message = error instanceof Error ? error.message : String(error);
1843
+ if (this.isCurrentActiveSession(session)) {
1844
+ this.publishActivity(session, "会话分叉失败", "error", message);
1845
+ this.events.publish(session.sessionId, { type: "session.error", message }, sourceEventScope);
1846
+ this.publishStatus(session);
1847
+ }
1848
+ throw error;
1849
+ }
1850
+ }
1851
+ clearSupersededSessionActivity(sessionId, cwd, eventScope) {
1852
+ const sessionKey = activeSessionKey(sessionId, eventScope);
1853
+ if (this.activities.get(sessionKey)?.phase === "active") {
1854
+ const at = new Date().toISOString();
1855
+ const stored = { phase: "idle", label: "空闲", at };
1856
+ this.activities.set(sessionKey, stored);
1857
+ const activity = { sessionId, ...stored };
1858
+ this.events.publish(sessionId, { type: "activity.update", activity }, eventScope);
1859
+ this.events.publishGlobal({ type: "activity.update", activity }, eventScope);
1860
+ }
1861
+ this.workspaceActivity?.removeSession(sessionId, cwd, eventScope);
1862
+ this.activities.delete(sessionKey);
1863
+ }
1854
1864
  async archive(ref, managementContext) {
1855
1865
  const active = await this.getActive(ref, managementContext);
1856
1866
  const session = active.runtime.session;
@@ -2090,6 +2100,7 @@ export class PiSessionService {
2090
2100
  if (sessionFile === undefined || sessionFile === "")
2091
2101
  throw new Error("会话尚未持久化");
2092
2102
  await clearParentSession(sessionFile);
2103
+ this.sessionManager.invalidateSessionFile?.(sessionFile);
2093
2104
  clearParentSessionHeader(session.sessionManager);
2094
2105
  this.unregisterSubsession(session.sessionId);
2095
2106
  await this.forgetUnreadSessions([{ sessionId: session.sessionId, cwd: session.sessionManager.getCwd() }]);
@@ -2432,8 +2443,10 @@ export class PiSessionService {
2432
2443
  return this.openPending(archived.sessionId, archived.cwd, managementContext, () => this.sessionManager.open(archivePath), { notifications: "disabled" });
2433
2444
  }
2434
2445
  const match = isPiSessionRef(ref)
2435
- ? (await this.sessionManager.list(ref.cwd)).find((s) => s.id === ref.id || s.id.startsWith(ref.id))
2436
- : (await this.sessionManager.listAll?.() ?? []).find((s) => s.id === ref || s.id.startsWith(ref));
2446
+ ? this.sessionManager.resolveSessionFile === undefined
2447
+ ? findSessionByIdOrPrefix(await this.sessionManager.list(ref.cwd), ref.id)
2448
+ : await this.sessionManager.resolveSessionFile(ref.cwd, ref.id)
2449
+ : findSessionByIdOrPrefix(await this.sessionManager.listAll?.() ?? [], ref);
2437
2450
  if (!match)
2438
2451
  throw new Error("未找到会话");
2439
2452
  return this.openPending(match.id, match.cwd, managementContext, () => this.sessionManager.open(match.path));
@@ -3137,6 +3150,16 @@ export class PiSessionService {
3137
3150
  await this.publishUnreadMutations([]);
3138
3151
  return this.unreadStore.durableCatalogSnapshot();
3139
3152
  }
3153
+ /** Scope-filtered unread view used only by the daemon-owned status tree. */
3154
+ async unreadCatalogForScope(eventScope) {
3155
+ const catalog = await this.unreadCatalog();
3156
+ if (eventScope === NORMAL_SESSION_EVENT_SCOPE)
3157
+ return catalog;
3158
+ const visible = new Set([...this.active.values()]
3159
+ .filter((active) => active.eventScope === eventScope)
3160
+ .map((active) => active.runtime.session.sessionId));
3161
+ return { ...catalog, sessions: catalog.sessions.filter((session) => visible.has(session.sessionId)) };
3162
+ }
3140
3163
  async acknowledgeUnread(sessionId, request) {
3141
3164
  const result = this.unreadStore.acknowledge(sessionId, {
3142
3165
  ...request,
@@ -3440,6 +3463,17 @@ export class PiSessionService {
3440
3463
  void this.publishUnreadMutations(mutations).catch(() => undefined);
3441
3464
  }
3442
3465
  publishUnreadMutations(mutations) {
3466
+ if (mutations.length > 0) {
3467
+ const scopes = new Set();
3468
+ for (const mutation of mutations) {
3469
+ const activeScopes = this.activeSessionsForId(mutation.event.sessionId).map((active) => active.eventScope);
3470
+ if (activeScopes.length === 0)
3471
+ scopes.add(NORMAL_SESSION_EVENT_SCOPE);
3472
+ else
3473
+ activeScopes.forEach((scope) => scopes.add(scope));
3474
+ }
3475
+ scopes.forEach((scope) => this.onUnreadChanged?.(scope));
3476
+ }
3443
3477
  this.enqueueUnreadMutations(mutations);
3444
3478
  this.unreadPublicationFlushRequested = true;
3445
3479
  if (this.unreadPublication === undefined && this.unreadPublicationRetryTimer !== undefined) {