@agent-native/core 0.221.0 → 0.221.1-nightly-20261028032829
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.
- package/dist/client/agent-chat.js +6 -1
- package/dist/client/api-path.d.ts +2 -0
- package/dist/client/api-path.js +76 -55
- package/dist/client/application-state.js +12 -6
- package/dist/client/browser-tab-id.d.ts +2 -0
- package/dist/client/browser-tab-id.js +113 -13
- package/dist/client/collab/index.d.ts +1 -1
- package/dist/client/embed-auth.js +145 -26
- package/dist/client/route-state.js +15 -4
- package/dist/client/sse-event-processor.js +3 -0
- package/dist/client/use-change-version.js +6 -1
- package/dist/client/use-db-sync.js +70 -11
- package/dist/collab/client.d.ts +34 -0
- package/dist/collab/client.js +506 -53
- package/dist/deploy/build.js +10 -0
- package/dist/mcp/embed-app.js +165 -16
- package/dist/provider-api/actions/custom-provider-registration.d.ts +3 -3
- package/dist/provider-api/actions/provider-api.d.ts +4 -4
- package/dist/server/app-origin-config.d.ts +2 -0
- package/dist/server/app-origin-config.js +10 -0
- package/dist/shared/mcp-app-widget-embed.d.ts +23 -1
- package/dist/shared/mcp-app-widget-embed.js +178 -5
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +41 -18
- package/package.json +4 -4
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +41 -18
|
@@ -4,6 +4,7 @@ import { parseBase64DataUrl } from "../shared/data-url.js";
|
|
|
4
4
|
import { trackEvent } from "./analytics.js";
|
|
5
5
|
import { agentNativePath } from "./api-path.js";
|
|
6
6
|
import { readClientAppState, writeClientAppState, } from "./application-state.js";
|
|
7
|
+
import { getBrowserTabId } from "./browser-tab-id.js";
|
|
7
8
|
import { isInBuilderFrame, isTrustedBuilderMessage, sendToBuilderChat, } from "./builder-frame.js";
|
|
8
9
|
import { trackRoutedTurnSubmitted } from "./chat/turn-submitted-telemetry.js";
|
|
9
10
|
import { DEFAULT_TURN_SURFACE } from "./chat/turn-submitted.js";
|
|
@@ -662,7 +663,11 @@ function dispatchAgentChatRunning(isRunning, tabId) {
|
|
|
662
663
|
if (typeof window === "undefined")
|
|
663
664
|
return;
|
|
664
665
|
window.dispatchEvent(new CustomEvent("agentNative.chatRunning", {
|
|
665
|
-
detail: {
|
|
666
|
+
detail: {
|
|
667
|
+
isRunning,
|
|
668
|
+
...(tabId ? { tabId } : {}),
|
|
669
|
+
browserTabId: getBrowserTabId(),
|
|
670
|
+
},
|
|
666
671
|
}));
|
|
667
672
|
}
|
|
668
673
|
function normalizeAgentChatRequestMode(value) {
|
|
@@ -15,6 +15,8 @@ export declare function isWorkspaceRuntime(): boolean;
|
|
|
15
15
|
* keep the basename supplied by the server instead of guessing from the URL.
|
|
16
16
|
*/
|
|
17
17
|
export declare function configureClientRouterBasename(): boolean;
|
|
18
|
+
export declare function resolveExternalEmbedTargetAppBasePath(target: string): string | undefined;
|
|
19
|
+
export declare function resolveAppBasePath(): string;
|
|
18
20
|
export declare function appBasePath(): string;
|
|
19
21
|
export declare function isWorkspaceAppPath(path: string): boolean;
|
|
20
22
|
export declare function appMountPath(appLocalRoute: string): string;
|
package/dist/client/api-path.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FRAMEWORK_INTERNAL_ROUTE_PREFIX, matchesPathPrefix, normalizeFrameworkRoutePrefix, SERVER_ROUTE_PREFIXES, toPublicFrameworkPath, } from "../shared/framework-route-prefix.js";
|
|
2
|
+
import { resolveExternalEmbedTargetBasePath, resolveWorkspaceAppMountPath, } from "../shared/mcp-app-widget-embed.js";
|
|
2
3
|
import { isTruthyRuntimeValue } from "../shared/runtime-config.js";
|
|
3
4
|
import { injectedAgentNativeConfig } from "./app-config.js";
|
|
4
5
|
import { initializeAgentNativeClient } from "./client-bootstrap.js";
|
|
@@ -69,10 +70,6 @@ function frameworkMarkerIndex(pathname) {
|
|
|
69
70
|
}
|
|
70
71
|
return -1;
|
|
71
72
|
}
|
|
72
|
-
function isFrameworkSegment(segment) {
|
|
73
|
-
return (`/${segment}` === FRAMEWORK_INTERNAL_ROUTE_PREFIX ||
|
|
74
|
-
`/${segment}` === frameworkRoutePrefix());
|
|
75
|
-
}
|
|
76
73
|
function pathDerivedBasePath() {
|
|
77
74
|
if (typeof window === "undefined" ||
|
|
78
75
|
typeof window.location?.pathname !== "string") {
|
|
@@ -106,7 +103,8 @@ function hasExplicitWorkspaceRootPath() {
|
|
|
106
103
|
return false;
|
|
107
104
|
const config = window;
|
|
108
105
|
const env = clientEnv();
|
|
109
|
-
return (
|
|
106
|
+
return (config.__AGENT_NATIVE_CONFIG__?.explicitRootPath === true ||
|
|
107
|
+
isDeclaredRootPath(config.__AGENT_NATIVE_CONFIG__?.workspaceAppPath) ||
|
|
110
108
|
isDeclaredRootPath(env?.VITE_APP_BASE_PATH ?? env?.APP_BASE_PATH));
|
|
111
109
|
}
|
|
112
110
|
export function isWorkspaceRuntime() {
|
|
@@ -125,38 +123,21 @@ function workspacePathBasePath(fallbackPath = "") {
|
|
|
125
123
|
const pathname = window.location?.pathname;
|
|
126
124
|
if (typeof pathname !== "string")
|
|
127
125
|
return "";
|
|
128
|
-
const routerBasePath = routerContextBasePath();
|
|
129
|
-
if (routerBasePath && pathMatchesBasePath(pathname, routerBasePath)) {
|
|
130
|
-
return routerBasePath;
|
|
131
|
-
}
|
|
132
|
-
const configuredWorkspacePath = workspaceAppConfiguredPath();
|
|
133
|
-
if (configuredWorkspacePath &&
|
|
134
|
-
pathMatchesBasePath(pathname, configuredWorkspacePath)) {
|
|
135
|
-
return configuredWorkspacePath;
|
|
136
|
-
}
|
|
137
126
|
const segment = pathname.split("/").find(Boolean);
|
|
127
|
+
const mounts = workspaceAppMountPaths();
|
|
128
|
+
const resolved = resolveWorkspaceAppMountPath(pathname, {
|
|
129
|
+
routerBasePath: routerContextBasePath(),
|
|
130
|
+
workspaceAppPath: workspaceAppConfiguredPath(),
|
|
131
|
+
workspaceAppMountPaths: mounts ? [...mounts] : undefined,
|
|
132
|
+
fallbackPath,
|
|
133
|
+
explicitRootPath: hasExplicitWorkspaceRootPath(),
|
|
134
|
+
frameworkRoutePrefix: frameworkRoutePrefix(),
|
|
135
|
+
});
|
|
136
|
+
if (resolved !== undefined)
|
|
137
|
+
return resolved;
|
|
138
138
|
if (!segment) {
|
|
139
|
-
if (hasExplicitWorkspaceRootPath())
|
|
140
|
-
return "";
|
|
141
|
-
if (fallbackPath)
|
|
142
|
-
return fallbackPath;
|
|
143
139
|
throw new WorkspaceAppMountResolutionError("Cannot resolve workspace app mount path without explicit mount metadata.");
|
|
144
140
|
}
|
|
145
|
-
if (isFrameworkSegment(segment) || segment === "api") {
|
|
146
|
-
return fallbackPath;
|
|
147
|
-
}
|
|
148
|
-
if (hasExplicitWorkspaceRootPath())
|
|
149
|
-
return "";
|
|
150
|
-
const mounts = workspaceAppMountPaths();
|
|
151
|
-
const matchingMount = mounts
|
|
152
|
-
? [...mounts]
|
|
153
|
-
.filter((mount) => pathMatchesBasePath(pathname, mount))
|
|
154
|
-
.sort((a, b) => b.length - a.length)[0]
|
|
155
|
-
: undefined;
|
|
156
|
-
if (matchingMount)
|
|
157
|
-
return matchingMount;
|
|
158
|
-
if (fallbackPath)
|
|
159
|
-
return fallbackPath;
|
|
160
141
|
throw new WorkspaceAppMountResolutionError(mounts
|
|
161
142
|
? "Cannot resolve workspace app mount path because the current URL matches no projected mount."
|
|
162
143
|
: "Cannot resolve workspace app mount path without explicit mount metadata.");
|
|
@@ -188,34 +169,70 @@ export function configureClientRouterBasename() {
|
|
|
188
169
|
context.basename = routerBasePath;
|
|
189
170
|
return true;
|
|
190
171
|
}
|
|
172
|
+
export function resolveExternalEmbedTargetAppBasePath(target) {
|
|
173
|
+
const mounts = workspaceAppMountPaths();
|
|
174
|
+
return resolveExternalEmbedTargetBasePath(target, {
|
|
175
|
+
workspaceRuntime: isWorkspaceRuntime(),
|
|
176
|
+
routerBasePath: routerContextBasePath(),
|
|
177
|
+
workspaceAppPath: workspaceAppConfiguredPath(),
|
|
178
|
+
workspaceAppMountPaths: mounts ? [...mounts] : undefined,
|
|
179
|
+
explicitRootPath: hasExplicitWorkspaceRootPath(),
|
|
180
|
+
frameworkRoutePrefix: frameworkRoutePrefix(),
|
|
181
|
+
});
|
|
182
|
+
}
|
|
191
183
|
function externalEmbedTargetBasePath() {
|
|
192
184
|
if (typeof window === "undefined")
|
|
193
|
-
return
|
|
194
|
-
const
|
|
195
|
-
if (typeof
|
|
196
|
-
return
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return normalizeBasePath(url.pathname.slice(0, markerIndex));
|
|
202
|
-
}
|
|
203
|
-
if (isWorkspaceRuntime()) {
|
|
204
|
-
const segment = url.pathname.split("/").find(Boolean);
|
|
205
|
-
if (segment && !isFrameworkSegment(segment) && segment !== "api") {
|
|
206
|
-
return normalizeBasePath(segment);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
185
|
+
return undefined;
|
|
186
|
+
const externalEmbed = window.__AGENT_NATIVE_EXTERNAL_EMBED;
|
|
187
|
+
if (!externalEmbed || typeof externalEmbed !== "object")
|
|
188
|
+
return undefined;
|
|
189
|
+
const config = externalEmbed;
|
|
190
|
+
const target = config.target;
|
|
191
|
+
if (typeof target !== "string" || !target.startsWith("/")) {
|
|
192
|
+
return undefined;
|
|
209
193
|
}
|
|
210
|
-
|
|
211
|
-
|
|
194
|
+
const basePath = resolveExternalEmbedTargetAppBasePath(target);
|
|
195
|
+
const pathname = window.location.pathname;
|
|
196
|
+
if (!pathname.startsWith("/")) {
|
|
197
|
+
return basePath;
|
|
198
|
+
}
|
|
199
|
+
const storedPathState = config.__agentNativePathState;
|
|
200
|
+
let pathState = storedPathState && typeof storedPathState === "object"
|
|
201
|
+
? storedPathState
|
|
202
|
+
: undefined;
|
|
203
|
+
if (!pathState ||
|
|
204
|
+
pathState.target !== target ||
|
|
205
|
+
typeof pathState.initialPathname !== "string" ||
|
|
206
|
+
typeof pathState.navigated !== "boolean") {
|
|
207
|
+
const nextPathState = {
|
|
208
|
+
target,
|
|
209
|
+
initialPathname: pathname,
|
|
210
|
+
navigated: false,
|
|
211
|
+
};
|
|
212
|
+
config.__agentNativePathState = nextPathState;
|
|
213
|
+
pathState = nextPathState;
|
|
214
|
+
}
|
|
215
|
+
else if (pathState.initialPathname !== pathname) {
|
|
216
|
+
pathState.navigated = true;
|
|
212
217
|
}
|
|
213
|
-
|
|
218
|
+
// Keep the target for handoff, then follow later route changes.
|
|
219
|
+
if (!pathState.navigated || !pathname.startsWith("/"))
|
|
220
|
+
return basePath;
|
|
221
|
+
const mounts = workspaceAppMountPaths();
|
|
222
|
+
const currentMount = resolveWorkspaceAppMountPath(pathname, {
|
|
223
|
+
workspaceAppMountPaths: mounts ? [...mounts] : undefined,
|
|
224
|
+
frameworkRoutePrefix: frameworkRoutePrefix(),
|
|
225
|
+
});
|
|
226
|
+
if (currentMount !== undefined && currentMount !== basePath) {
|
|
227
|
+
return currentMount;
|
|
228
|
+
}
|
|
229
|
+
if (basePath && !pathMatchesBasePath(pathname, basePath))
|
|
230
|
+
return undefined;
|
|
231
|
+
return basePath;
|
|
214
232
|
}
|
|
215
|
-
export function
|
|
216
|
-
initializeAgentNativeClient();
|
|
233
|
+
export function resolveAppBasePath() {
|
|
217
234
|
const externalEmbed = externalEmbedTargetBasePath();
|
|
218
|
-
if (externalEmbed)
|
|
235
|
+
if (externalEmbed !== undefined)
|
|
219
236
|
return externalEmbed;
|
|
220
237
|
const configured = configuredBasePath();
|
|
221
238
|
const derived = pathDerivedBasePath();
|
|
@@ -228,6 +245,10 @@ export function appBasePath() {
|
|
|
228
245
|
return configured;
|
|
229
246
|
return derived || workspacePathBasePath(configured);
|
|
230
247
|
}
|
|
248
|
+
export function appBasePath() {
|
|
249
|
+
initializeAgentNativeClient();
|
|
250
|
+
return resolveAppBasePath();
|
|
251
|
+
}
|
|
231
252
|
function workspaceAppMountPaths() {
|
|
232
253
|
const projected = typeof window === "undefined"
|
|
233
254
|
? undefined
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { agentNativePath } from "./api-path.js";
|
|
2
2
|
import { assertAgentNativeApiEnabled } from "./api-surface.js";
|
|
3
|
-
import { getBrowserTabId } from "./browser-tab-id.js";
|
|
3
|
+
import { getBrowserTabId, isBrowserTabIdForCurrentDocument, } from "./browser-tab-id.js";
|
|
4
4
|
import { recordStateWrite } from "./recorder.js";
|
|
5
5
|
const APP_STATE_KEY_PATTERN = /^[a-zA-Z0-9_:-]+$/;
|
|
6
6
|
const pendingMutations = new Map();
|
|
@@ -18,10 +18,18 @@ function buildHeaders(requestSource) {
|
|
|
18
18
|
if (typeof window !== "undefined") {
|
|
19
19
|
headers["X-Agent-Native-Browser-Tab"] = getBrowserTabId();
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
headers["X-Request-Source"] = requestSource;
|
|
21
|
+
Object.assign(headers, requestSourceHeader(requestSource));
|
|
23
22
|
return headers;
|
|
24
23
|
}
|
|
24
|
+
function requestSourceHeader(requestSource) {
|
|
25
|
+
if (!requestSource)
|
|
26
|
+
return {};
|
|
27
|
+
return {
|
|
28
|
+
"X-Request-Source": isBrowserTabIdForCurrentDocument(requestSource)
|
|
29
|
+
? getBrowserTabId()
|
|
30
|
+
: requestSource,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
25
33
|
function browserTabHeaders() {
|
|
26
34
|
return typeof window === "undefined"
|
|
27
35
|
? undefined
|
|
@@ -239,9 +247,7 @@ export async function deleteClientAppState(key, options = {}) {
|
|
|
239
247
|
headers: {
|
|
240
248
|
"X-Agent-Native-CSRF": "1",
|
|
241
249
|
...(browserTabHeaders() ?? {}),
|
|
242
|
-
...(options.requestSource
|
|
243
|
-
? { "X-Request-Source": options.requestSource }
|
|
244
|
-
: {}),
|
|
250
|
+
...requestSourceHeader(options.requestSource),
|
|
245
251
|
},
|
|
246
252
|
keepalive: options.keepalive,
|
|
247
253
|
signal: options.signal,
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
import { appBasePath, isWorkspaceRuntime } from "./api-path.js";
|
|
2
|
-
let cached;
|
|
1
|
+
import { appBasePath, isWorkspaceRuntime, WorkspaceAppMountResolutionError, } from "./api-path.js";
|
|
3
2
|
const STORAGE_KEY = "agent-native:browser-tab-id";
|
|
4
3
|
const SAFE_BROWSER_TAB_ID_RE = /^[A-Za-z0-9_-]{1,96}$/;
|
|
4
|
+
const BROWSER_TAB_ID_STATE_SYMBOL = Symbol.for("@agent-native/core/client/browser-tab-id");
|
|
5
|
+
const browserTabIdGlobal = globalThis;
|
|
6
|
+
// Vite can load optimized package and deep-import copies in the same tab.
|
|
7
|
+
const browserTabIdState = browserTabIdGlobal[BROWSER_TAB_ID_STATE_SYMBOL] ??
|
|
8
|
+
(browserTabIdGlobal[BROWSER_TAB_ID_STATE_SYMBOL] = {
|
|
9
|
+
ids: new Map(),
|
|
10
|
+
aliases: new Map(),
|
|
11
|
+
pendingId: null,
|
|
12
|
+
});
|
|
13
|
+
browserTabIdState.pendingId ??= null;
|
|
14
|
+
const browserTabIdAliases = (browserTabIdState.aliases ??= new Map());
|
|
15
|
+
let serverCached;
|
|
5
16
|
function storageKey() {
|
|
6
17
|
const appScope = isWorkspaceRuntime() ? appBasePath() : "";
|
|
7
18
|
return appScope ? `${STORAGE_KEY}:${appScope}` : STORAGE_KEY;
|
|
@@ -21,28 +32,117 @@ function shouldReuseStoredTabId() {
|
|
|
21
32
|
return navigation?.type === "reload" || navigation?.type === "back_forward";
|
|
22
33
|
}
|
|
23
34
|
export function getBrowserTabId() {
|
|
24
|
-
if (cached)
|
|
25
|
-
return cached;
|
|
26
35
|
if (typeof window === "undefined") {
|
|
27
|
-
|
|
36
|
+
serverCached ??= generate();
|
|
37
|
+
return serverCached;
|
|
38
|
+
}
|
|
39
|
+
let key;
|
|
40
|
+
try {
|
|
41
|
+
key = storageKey();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return getOrCreatePendingId();
|
|
45
|
+
}
|
|
46
|
+
const cached = browserTabIdState.ids.get(key);
|
|
47
|
+
if (cached) {
|
|
48
|
+
const pending = browserTabIdState.pendingId;
|
|
49
|
+
if (pending && pending !== cached) {
|
|
50
|
+
browserTabIdAliases.set(pending, { storageKey: key, id: cached });
|
|
51
|
+
}
|
|
52
|
+
browserTabIdState.pendingId = null;
|
|
28
53
|
return cached;
|
|
29
54
|
}
|
|
55
|
+
let existing;
|
|
56
|
+
let storageReadable = true;
|
|
30
57
|
try {
|
|
31
|
-
|
|
32
|
-
|
|
58
|
+
existing = sessionStorage.getItem(key);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
existing = null;
|
|
62
|
+
storageReadable = false;
|
|
63
|
+
}
|
|
64
|
+
const pending = browserTabIdState.pendingId;
|
|
65
|
+
if (pending) {
|
|
33
66
|
if (existing &&
|
|
34
67
|
SAFE_BROWSER_TAB_ID_RE.test(existing) &&
|
|
35
68
|
shouldReuseStoredTabId()) {
|
|
36
|
-
|
|
69
|
+
browserTabIdState.pendingId = null;
|
|
70
|
+
browserTabIdState.ids.set(key, existing);
|
|
71
|
+
browserTabIdAliases.set(pending, { storageKey: key, id: existing });
|
|
37
72
|
return existing;
|
|
38
73
|
}
|
|
39
|
-
|
|
74
|
+
browserTabIdState.pendingId = null;
|
|
75
|
+
try {
|
|
76
|
+
sessionStorage.setItem(key, pending);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
browserTabIdState.ids.set(key, pending);
|
|
80
|
+
return pending;
|
|
81
|
+
}
|
|
82
|
+
browserTabIdState.ids.set(key, pending);
|
|
83
|
+
return pending;
|
|
84
|
+
}
|
|
85
|
+
if (!storageReadable)
|
|
86
|
+
return getOrCreateMemoryId(key);
|
|
87
|
+
if (existing &&
|
|
88
|
+
SAFE_BROWSER_TAB_ID_RE.test(existing) &&
|
|
89
|
+
shouldReuseStoredTabId()) {
|
|
90
|
+
browserTabIdState.ids.set(key, existing);
|
|
91
|
+
return existing;
|
|
92
|
+
}
|
|
93
|
+
const id = generate();
|
|
94
|
+
try {
|
|
40
95
|
sessionStorage.setItem(key, id);
|
|
41
|
-
cached = id;
|
|
42
|
-
return id;
|
|
43
96
|
}
|
|
44
97
|
catch {
|
|
45
|
-
|
|
46
|
-
return
|
|
98
|
+
browserTabIdState.ids.set(key, id);
|
|
99
|
+
return id;
|
|
100
|
+
}
|
|
101
|
+
browserTabIdState.ids.set(key, id);
|
|
102
|
+
return id;
|
|
103
|
+
}
|
|
104
|
+
export function resolveBrowserTabIdAlias(tabId) {
|
|
105
|
+
if (typeof tabId !== "string")
|
|
106
|
+
return undefined;
|
|
107
|
+
const alias = browserTabIdAliases.get(tabId);
|
|
108
|
+
if (!alias)
|
|
109
|
+
return undefined;
|
|
110
|
+
return browserTabIdState.ids.get(alias.storageKey) === alias.id
|
|
111
|
+
? alias.id
|
|
112
|
+
: undefined;
|
|
113
|
+
}
|
|
114
|
+
export function isBrowserTabIdForCurrentDocument(tabId) {
|
|
115
|
+
if (typeof tabId !== "string")
|
|
116
|
+
return false;
|
|
117
|
+
if (browserTabIdState.pendingId === tabId)
|
|
118
|
+
return true;
|
|
119
|
+
for (const knownTabId of browserTabIdState.ids.values()) {
|
|
120
|
+
if (knownTabId === tabId)
|
|
121
|
+
return true;
|
|
47
122
|
}
|
|
123
|
+
const alias = browserTabIdAliases.get(tabId);
|
|
124
|
+
if (!alias || resolveBrowserTabIdAlias(tabId) === undefined)
|
|
125
|
+
return false;
|
|
126
|
+
let currentStorageKey;
|
|
127
|
+
try {
|
|
128
|
+
currentStorageKey = storageKey();
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (error instanceof WorkspaceAppMountResolutionError)
|
|
132
|
+
return false;
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
return currentStorageKey === alias.storageKey;
|
|
136
|
+
}
|
|
137
|
+
function getOrCreateMemoryId(key) {
|
|
138
|
+
const cached = browserTabIdState.ids.get(key);
|
|
139
|
+
if (cached)
|
|
140
|
+
return cached;
|
|
141
|
+
const id = generate();
|
|
142
|
+
browserTabIdState.ids.set(key, id);
|
|
143
|
+
return id;
|
|
144
|
+
}
|
|
145
|
+
function getOrCreatePendingId() {
|
|
146
|
+
browserTabIdState.pendingId ??= generate();
|
|
147
|
+
return browserTabIdState.pendingId;
|
|
48
148
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { useCollaborativeDoc, isReconcileLeadClient, emailToColor, emailToName, dedupeCollabUsersByEmail, type CollabUser, type UseCollaborativeDocOptions, type UseCollaborativeDocResult, type CollabInitializationErrorCategory, type CollabInitializationState, type CollaborativeDocSyncResult, } from "../../collab/client.js";
|
|
1
|
+
export { useCollaborativeDoc, isReconcileLeadClient, emailToColor, emailToName, dedupeCollabUsersByEmail, type CollabUser, type UseCollaborativeDocOptions, type UseCollaborativeDocResult, type CollabInitializationErrorCategory, type CollabInitializationState, type CollaborativeDocSyncResult, type CollabUpdateAck, } from "../../collab/client.js";
|
|
2
2
|
export { AGENT_CLIENT_ID } from "../../collab/agent-identity.js";
|
|
3
3
|
export { usePresence, toNormalized, fromNormalized, type OtherPresence, type PresencePayload, type UsePresenceResult, type NormalizedPoint, } from "../../collab/presence.js";
|
|
4
4
|
export { useFollowUser, type UseFollowUserOptions, type UseFollowUserResult, type ViewportDescriptor, } from "../../collab/follow-mode.js";
|