@agent-native/core 0.167.1 → 0.167.4
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/corpus/templates/analytics/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/assets/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/brain/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/calendar/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/clips/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/clips/app/routes/download.tsx +78 -131
- package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/dist/chat-threads/store.d.ts +7 -0
- package/dist/chat-threads/store.js +15 -0
- package/dist/client/AgentPanel.d.ts +5 -1
- package/dist/client/AgentPanel.js +8 -8
- package/dist/client/AssistantChat.d.ts +3 -1
- package/dist/client/AssistantChat.js +22 -6
- package/dist/client/MultiTabAssistantChat.d.ts +3 -1
- package/dist/client/MultiTabAssistantChat.js +5 -4
- package/dist/client/agent-page/AgentJobsTab.js +39 -6
- package/dist/client/agent-page/AutomationScheduleDialog.d.ts +10 -1
- package/dist/client/agent-page/AutomationScheduleDialog.js +3 -2
- package/dist/client/agent-page/ScheduledTriggerNotice.d.ts +22 -0
- package/dist/client/agent-page/ScheduledTriggerNotice.js +84 -0
- package/dist/client/agent-page/scheduled-trigger-state.d.ts +28 -0
- package/dist/client/agent-page/scheduled-trigger-state.js +10 -0
- package/dist/client/agent-page/use-jobs.d.ts +7 -0
- package/dist/client/agent-page/use-jobs.js +14 -0
- package/dist/client/blocks/library/diagram.config.d.ts +4 -1
- package/dist/client/blocks/library/diagram.js +1 -1
- package/dist/client/chat/run-recovery.js +15 -7
- package/dist/client/use-chat-threads.d.ts +7 -0
- package/dist/client/use-chat-threads.js +144 -40
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.d.ts +5 -0
- package/dist/deploy/build.js +12 -1
- package/dist/framework-tools.js +1 -0
- package/dist/jobs/actions/get-scheduled-trigger-status.d.ts +13 -0
- package/dist/jobs/actions/get-scheduled-trigger-status.js +21 -0
- package/dist/localization/default-messages.d.ts +14 -0
- package/dist/localization/default-messages.js +14 -0
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +13 -13
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/server/action-discovery.js +4 -0
- package/dist/server/agent-chat/recurring-jobs-runtime.d.ts +42 -1
- package/dist/server/agent-chat/recurring-jobs-runtime.js +102 -9
- package/dist/server/agent-chat-plugin.d.ts +3 -1
- package/dist/server/agent-chat-plugin.js +115 -24
- package/dist/server/attribution.d.ts +29 -0
- package/dist/server/attribution.js +68 -0
- package/dist/server/auth.js +58 -15
- package/dist/server/better-auth-instance.js +16 -4
- package/dist/server/identity-sso.js +14 -2
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/request-context.d.ts +8 -0
- package/dist/server/request-context.js +4 -0
- package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/dist/vite/client.js +10 -0
- package/docs/content/deployment.mdx +3 -1
- package/docs/content/recurring-jobs.mdx +6 -0
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +11 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +11 -0
|
@@ -37,7 +37,10 @@ export interface DiagramData {
|
|
|
37
37
|
*/
|
|
38
38
|
html?: string;
|
|
39
39
|
css?: string;
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* `design` forces clean HTML/CSS rendering without the sketch overlay. Use it
|
|
42
|
+
* for UI-like blocks such as cards, logo walls, tables, and controls.
|
|
43
|
+
*/
|
|
41
44
|
renderMode?: "wireframe" | "design";
|
|
42
45
|
caption?: string;
|
|
43
46
|
/** Outer surface frame. `auto` lets the host choose the right default. */
|
|
@@ -393,7 +393,7 @@ export const diagramBlock = defineBlock({
|
|
|
393
393
|
// edit from a corner button + panel rather than inline.
|
|
394
394
|
editSurface: "panel",
|
|
395
395
|
label: "Diagram",
|
|
396
|
-
description: "A flexible inline architecture/code diagram. Prefer html/css with SVG or semantic HTML for polished two-dimensional layouts; use renderMode design for
|
|
396
|
+
description: "A flexible inline architecture/code diagram. Prefer html/css with SVG or semantic HTML for polished two-dimensional layouts; use renderMode design for UI-like blocks such as cards, logo walls, tables, and controls, or .diagram-* primitives and --wf-* tokens for actual diagrams that need theme/sketch compatibility. Legacy nodes/edges are only for simple previews.",
|
|
397
397
|
// Seed the legacy fallback shape so a fresh block validates while agents can
|
|
398
398
|
// replace it with html/css when layout quality matters.
|
|
399
399
|
empty: () => ({ nodes: [{ id: "n1", label: "Module" }], edges: [] }),
|
|
@@ -298,17 +298,25 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
|
|
|
298
298
|
return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: runErrorHeadline(info, {
|
|
299
299
|
recoverable: t("agentChat.error.stopped"),
|
|
300
300
|
terminal: t("agentChat.error.failed"),
|
|
301
|
-
}) }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: localizeKnownChatErrorText(info.message, t) }), isProviderAuthError && (_jsx("div", { className: "mt-3 rounded-md border border-border/70 bg-background/60 p-2.5", children: _jsx(BuilderSetupContent, { layout: "sidebar", onConnected: handleProviderConnected }) })), shouldShowBuilderReconnect && !builderReconnectResolved && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: t("agentChat.recovery.credentialRejected") })), isConnectionRecoveryError && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: t("agentChat.recovery.newChatHint") })), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), t("agentChat.common.details")] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": t("agentChat.common.dismiss"), className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex
|
|
301
|
+
}) }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: localizeKnownChatErrorText(info.message, t) }), isProviderAuthError && (_jsx("div", { className: "mt-3 rounded-md border border-border/70 bg-background/60 p-2.5", children: _jsx(BuilderSetupContent, { layout: "sidebar", onConnected: handleProviderConnected }) })), shouldShowBuilderReconnect && !builderReconnectResolved && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: t("agentChat.recovery.credentialRejected") })), isConnectionRecoveryError && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: t("agentChat.recovery.newChatHint") })), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), t("agentChat.common.details")] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": t("agentChat.common.dismiss"), className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex min-w-0 items-center gap-2", children: [shouldShowBuilderReconnect && !builderReconnectResolved && (_jsxs("button", { type: "button", onClick: () => builderReconnect.start(), disabled: builderReconnect.connecting, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90 disabled:cursor-wait disabled:opacity-70", children: [builderReconnect.connecting ? (_jsx(IconLoader2, { size: 13, className: "animate-spin" })) : null, builderReconnect.connecting
|
|
302
302
|
? t("agentChat.recovery.connectingBuilder")
|
|
303
|
-
: t("agentChat.recovery.reconnectBuilder")] })), canRecover && (
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
303
|
+
: t("agentChat.recovery.reconnectBuilder")] })), canRecover && (_jsxs("button", { type: "button", onClick: onContinue, className: "inline-flex min-w-0 flex-1 items-center justify-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconPlayerPlay, { size: 13 }), _jsx("span", { className: "truncate", children: t("agentChat.common.continue") })] })), _jsxs("div", { className: "flex shrink-0 items-center gap-0.5 rounded-md border border-border/70 bg-background/60 p-0.5", children: [canRetry && (_jsx("button", { type: "button", onClick: onRetry, title: isQueryError
|
|
304
|
+
? t("agentChat.recovery.diagnoseRetry")
|
|
305
|
+
: t("agentChat.common.retry"), "aria-label": isQueryError
|
|
306
|
+
? t("agentChat.recovery.diagnoseRetry")
|
|
307
|
+
: t("agentChat.common.retry"), className: "inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: _jsx(IconRefresh, { size: 14 }) })), canRecover && isConnectionRecoveryError && (_jsx("button", { type: "button", onClick: startNewChat, title: t("agentChat.tabs.newChat"), "aria-label": t("agentChat.tabs.newChat"), className: "inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: _jsx(IconPlus, { size: 14 }) })), canRecover && onFork && !isConnectionRecoveryError && (_jsx("button", { type: "button", onClick: handleFork, disabled: forking, title: t("agentChat.recovery.forkDescription"), "aria-label": t("agentChat.recovery.forkDescription"), className: "inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground disabled:cursor-wait disabled:opacity-70", children: forking ? (_jsx(IconLoader2, { size: 14, className: "animate-spin" })) : (_jsx(IconGitFork, { size: 14 })) })), _jsxs("button", { type: "button", onClick: copyDetails, title: copyState === "copied"
|
|
308
308
|
? t("agentChat.common.copied")
|
|
309
309
|
: copyState === "failed"
|
|
310
310
|
? t("agentChat.recovery.copyFailed")
|
|
311
|
-
: copyLabel
|
|
311
|
+
: copyLabel, "aria-label": copyState === "copied"
|
|
312
|
+
? t("agentChat.common.copied")
|
|
313
|
+
: copyState === "failed"
|
|
314
|
+
? t("agentChat.recovery.copyFailed")
|
|
315
|
+
: copyLabel, className: "inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: [copyState === "copied" ? (_jsx(IconCheck, { size: 14 })) : copyState === "failed" ? (_jsx(IconX, { size: 14 })) : (_jsx(IconCopy, { size: 14 })), _jsx("span", { className: "sr-only", "aria-live": "polite", children: copyState === "copied"
|
|
316
|
+
? t("agentChat.common.copied")
|
|
317
|
+
: copyState === "failed"
|
|
318
|
+
? t("agentChat.recovery.copyFailed")
|
|
319
|
+
: copyLabel })] })] })] }), shouldShowBuilderReconnect && builderReconnect.error && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-red-500", children: builderReconnect.error })), forkError && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-red-500", children: forkError }))] }));
|
|
312
320
|
}
|
|
313
321
|
// ─── LoopLimitContinueCard ────────────────────────────────────────────────────
|
|
314
322
|
export function LoopLimitContinueCard({ info, onContinue, }) {
|
|
@@ -66,7 +66,14 @@ export interface UseChatThreadsOptions {
|
|
|
66
66
|
routeThreadId?: string | null;
|
|
67
67
|
/** Include connected and other-app chats in list/search results. */
|
|
68
68
|
includeExternal?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Restrict history to the supplied scope. App-owned chat rails use this to
|
|
71
|
+
* keep one app's conversations out of another app's history; ordinary
|
|
72
|
+
* resource scopes intentionally continue to show general chats.
|
|
73
|
+
*/
|
|
74
|
+
isolateHistoryByScope?: boolean;
|
|
69
75
|
}
|
|
76
|
+
export declare function appendChatThreadScopeParams(params: URLSearchParams, scope?: ChatThreadScope | null): void;
|
|
70
77
|
export declare function useChatThreads(apiUrl?: string, storageKey?: string, scope?: ChatThreadScope | null, options?: UseChatThreadsOptions): {
|
|
71
78
|
threads: ChatThreadSummary[];
|
|
72
79
|
activeThreadId: string | null;
|
|
@@ -3,12 +3,13 @@ import { agentNativePath } from "./api-path.js";
|
|
|
3
3
|
const ACTIVE_THREAD_KEY = "agent-chat-active-thread";
|
|
4
4
|
const THREADS_UPDATED_EVENT = "agent-chat:threads-updated";
|
|
5
5
|
const THREADS_PAGE_SIZE = 50;
|
|
6
|
-
async function fetchThreadListPage(apiUrl, offset, includeExternal) {
|
|
6
|
+
async function fetchThreadListPage(apiUrl, offset, includeExternal, scope) {
|
|
7
7
|
const params = new URLSearchParams();
|
|
8
8
|
if (offset > 0)
|
|
9
9
|
params.set("offset", String(offset));
|
|
10
10
|
if (includeExternal)
|
|
11
11
|
params.set("includeExternal", "1");
|
|
12
|
+
appendChatThreadScopeParams(params, scope);
|
|
12
13
|
const query = params.toString();
|
|
13
14
|
return fetch(`${apiUrl}/threads${query ? `?${query}` : ""}`).then(async (res) => {
|
|
14
15
|
if (!res.ok)
|
|
@@ -22,9 +23,12 @@ async function fetchThreadListPage(apiUrl, offset, includeExternal) {
|
|
|
22
23
|
* the caller must not collapse: the thread (found), `null` (the server denies it
|
|
23
24
|
* exists), and `undefined` (unreachable — nothing was learned).
|
|
24
25
|
*/
|
|
25
|
-
async function fetchThreadById(apiUrl, id) {
|
|
26
|
+
async function fetchThreadById(apiUrl, id, scope) {
|
|
26
27
|
try {
|
|
27
|
-
const
|
|
28
|
+
const params = new URLSearchParams();
|
|
29
|
+
appendChatThreadScopeParams(params, scope);
|
|
30
|
+
const query = params.toString();
|
|
31
|
+
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(id)}${query ? `?${query}` : ""}`);
|
|
28
32
|
if (res.status === 404)
|
|
29
33
|
return null;
|
|
30
34
|
if (!res.ok)
|
|
@@ -35,6 +39,20 @@ async function fetchThreadById(apiUrl, id) {
|
|
|
35
39
|
return undefined;
|
|
36
40
|
}
|
|
37
41
|
}
|
|
42
|
+
export function appendChatThreadScopeParams(params, scope) {
|
|
43
|
+
if (!scope)
|
|
44
|
+
return;
|
|
45
|
+
params.set("scopeType", scope.type);
|
|
46
|
+
params.set("scopeId", scope.id);
|
|
47
|
+
}
|
|
48
|
+
function withChatThreadScope(url, scope) {
|
|
49
|
+
const params = new URLSearchParams();
|
|
50
|
+
appendChatThreadScopeParams(params, scope);
|
|
51
|
+
const query = params.toString();
|
|
52
|
+
if (!query)
|
|
53
|
+
return url;
|
|
54
|
+
return `${url}${url.includes("?") ? "&" : "?"}${query}`;
|
|
55
|
+
}
|
|
38
56
|
function emitThreadsUpdated() {
|
|
39
57
|
if (typeof window === "undefined")
|
|
40
58
|
return;
|
|
@@ -91,6 +109,12 @@ function threadCanStayVisibleInScope(threadScope, currentScope) {
|
|
|
91
109
|
return true;
|
|
92
110
|
return scopesMatch(threadScope, currentScope);
|
|
93
111
|
}
|
|
112
|
+
function threadCanStayVisibleInHistory(threadScope, currentScope, isolateHistoryByScope = false) {
|
|
113
|
+
if (!isolateHistoryByScope) {
|
|
114
|
+
return threadCanStayVisibleInScope(threadScope, currentScope);
|
|
115
|
+
}
|
|
116
|
+
return scopesMatch(threadScope, currentScope);
|
|
117
|
+
}
|
|
94
118
|
function nextThreadTitle(currentTitle, incomingTitle, incomingPreview, source = "extracted", options = {}) {
|
|
95
119
|
if (options.preserveUserTitle && currentTitle)
|
|
96
120
|
return currentTitle;
|
|
@@ -109,6 +133,12 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
109
133
|
const autoCreate = options?.autoCreate !== false;
|
|
110
134
|
const restoreActiveThread = options?.restoreActiveThread !== false;
|
|
111
135
|
const includeExternal = options?.includeExternal === true;
|
|
136
|
+
const isolateHistoryByScope = options?.isolateHistoryByScope === true;
|
|
137
|
+
const isolateHistory = isolateHistoryByScope && Boolean(scope);
|
|
138
|
+
const historyScope = useMemo(() => (isolateHistory && scope ? { type: scope.type, id: scope.id } : null), [isolateHistory, scope?.id, scope?.type]);
|
|
139
|
+
const historyScopeKey = historyScope
|
|
140
|
+
? `${historyScope.type}:${historyScope.id}`
|
|
141
|
+
: null;
|
|
112
142
|
const routeControlsActiveThread = options?.routeThreadId !== undefined;
|
|
113
143
|
const routeThreadId = normalizeThreadId(options?.routeThreadId);
|
|
114
144
|
// Each (storageKey, scope) pair gets its own active-thread localStorage key
|
|
@@ -170,6 +200,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
170
200
|
? new Set([initialActiveThreadRef.current.id])
|
|
171
201
|
: new Set());
|
|
172
202
|
const optimisticThreadScopesRef = useRef(new Map());
|
|
203
|
+
const knownThreadScopesRef = useRef(new Map());
|
|
173
204
|
const pendingPinnedAtRef = useRef(new Map());
|
|
174
205
|
const pendingArchivedAtRef = useRef(new Map());
|
|
175
206
|
const userRenamedThreadIdsRef = useRef(new Set());
|
|
@@ -215,6 +246,9 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
215
246
|
if (optimisticThreadScopesRef.current.has(id)) {
|
|
216
247
|
return optimisticThreadScopesRef.current.get(id) ?? null;
|
|
217
248
|
}
|
|
249
|
+
if (knownThreadScopesRef.current.has(id)) {
|
|
250
|
+
return knownThreadScopesRef.current.get(id) ?? null;
|
|
251
|
+
}
|
|
218
252
|
return undefined;
|
|
219
253
|
}, []);
|
|
220
254
|
// Add a client-generated thread to the local list optimistically.
|
|
@@ -290,7 +324,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
290
324
|
if (currentThreadScope === undefined) {
|
|
291
325
|
return;
|
|
292
326
|
}
|
|
293
|
-
if (
|
|
327
|
+
if (threadCanStayVisibleInHistory(currentThreadScope, scopeRef.current, isolateHistory)) {
|
|
294
328
|
persistedKeyRef.current = activeThreadKey;
|
|
295
329
|
return;
|
|
296
330
|
}
|
|
@@ -308,7 +342,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
308
342
|
if (nextActiveThreadId) {
|
|
309
343
|
const savedScope = readKnownThreadScope(nextActiveThreadId);
|
|
310
344
|
if (savedScope !== undefined &&
|
|
311
|
-
!
|
|
345
|
+
!threadCanStayVisibleInHistory(savedScope, scopeRef.current, isolateHistory)) {
|
|
312
346
|
nextActiveThreadId = null;
|
|
313
347
|
}
|
|
314
348
|
}
|
|
@@ -356,7 +390,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
356
390
|
const requestId = ++latestFetchRequestRef.current;
|
|
357
391
|
try {
|
|
358
392
|
const offset = options?.append ? nextThreadsOffsetRef.current : 0;
|
|
359
|
-
const loaded = await fetchThreadListPage(apiUrl, offset, includeExternal);
|
|
393
|
+
const loaded = await fetchThreadListPage(apiUrl, offset, includeExternal, historyScope);
|
|
360
394
|
if (requestId !== latestFetchRequestRef.current)
|
|
361
395
|
return undefined;
|
|
362
396
|
if (!loaded) {
|
|
@@ -365,6 +399,9 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
365
399
|
}
|
|
366
400
|
return;
|
|
367
401
|
}
|
|
402
|
+
for (const thread of loaded) {
|
|
403
|
+
knownThreadScopesRef.current.set(thread.id, thread.scope ?? null);
|
|
404
|
+
}
|
|
368
405
|
setThreadsLoadError(null);
|
|
369
406
|
if (!options?.append) {
|
|
370
407
|
nextThreadsOffsetRef.current = loaded.length;
|
|
@@ -373,8 +410,11 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
373
410
|
nextThreadsOffsetRef.current += loaded.length;
|
|
374
411
|
}
|
|
375
412
|
setHasMoreThreads(loaded.length >= THREADS_PAGE_SIZE);
|
|
413
|
+
const visibleLoaded = isolateHistory
|
|
414
|
+
? loaded.filter((thread) => threadCanStayVisibleInHistory(thread.scope, historyScope, isolateHistory))
|
|
415
|
+
: loaded;
|
|
376
416
|
setThreads((prev) => {
|
|
377
|
-
const loadedIds = new Set(
|
|
417
|
+
const loadedIds = new Set(visibleLoaded.map((t) => t.id));
|
|
378
418
|
// Preserve any optimistic threads we've created this session that
|
|
379
419
|
// haven't shown up in the server list yet — the server only learns
|
|
380
420
|
// about a thread when the user actually sends a message and the
|
|
@@ -387,13 +427,15 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
387
427
|
// and get preserved forever instead of disappearing once archived.
|
|
388
428
|
const optimisticOnly = prev.filter((t) => newlyCreatedRef.current.has(t.id) &&
|
|
389
429
|
!loadedIds.has(t.id) &&
|
|
390
|
-
!t.archivedAt
|
|
430
|
+
!t.archivedAt &&
|
|
431
|
+
(!isolateHistory ||
|
|
432
|
+
threadCanStayVisibleInHistory(t.scope, historyScope, isolateHistory)));
|
|
391
433
|
// Reconcile each server thread against our local copy. If the local
|
|
392
434
|
// copy has a newer updatedAt or higher messageCount, keep those
|
|
393
435
|
// fields — the server probably hasn't observed the user's latest
|
|
394
436
|
// send yet, and naively replacing makes the recent-chats list
|
|
395
437
|
// visibly jump back to older timestamps right after a send.
|
|
396
|
-
const merged =
|
|
438
|
+
const merged = visibleLoaded.map((server) => {
|
|
397
439
|
const local = prev.find((t) => t.id === server.id);
|
|
398
440
|
if (!local)
|
|
399
441
|
return server;
|
|
@@ -438,7 +480,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
438
480
|
}
|
|
439
481
|
return [...optimisticOnly, ...merged];
|
|
440
482
|
});
|
|
441
|
-
return
|
|
483
|
+
return visibleLoaded;
|
|
442
484
|
}
|
|
443
485
|
catch {
|
|
444
486
|
if (requestId !== latestFetchRequestRef.current)
|
|
@@ -448,7 +490,28 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
448
490
|
}
|
|
449
491
|
return undefined;
|
|
450
492
|
}
|
|
451
|
-
}, [apiUrl, includeExternal]);
|
|
493
|
+
}, [apiUrl, historyScope, includeExternal, isolateHistory]);
|
|
494
|
+
const loadedHistoryScopeKeyRef = useRef(historyScopeKey);
|
|
495
|
+
useEffect(() => {
|
|
496
|
+
if (loadedHistoryScopeKeyRef.current === historyScopeKey)
|
|
497
|
+
return;
|
|
498
|
+
loadedHistoryScopeKeyRef.current = historyScopeKey;
|
|
499
|
+
if (!isolateHistoryByScope)
|
|
500
|
+
return;
|
|
501
|
+
nextThreadsOffsetRef.current = 0;
|
|
502
|
+
setHasMoreThreads(false);
|
|
503
|
+
setThreadsLoadError(null);
|
|
504
|
+
setThreads((prev) => prev.filter((thread) => !isolateHistory ||
|
|
505
|
+
threadCanStayVisibleInHistory(thread.scope, historyScope, isolateHistory)));
|
|
506
|
+
setIsLoading(true);
|
|
507
|
+
void fetchThreads().finally(() => setIsLoading(false));
|
|
508
|
+
}, [
|
|
509
|
+
fetchThreads,
|
|
510
|
+
historyScope,
|
|
511
|
+
historyScopeKey,
|
|
512
|
+
isolateHistory,
|
|
513
|
+
isolateHistoryByScope,
|
|
514
|
+
]);
|
|
452
515
|
const loadMoreThreads = useCallback(async () => {
|
|
453
516
|
if (isLoadingMoreThreads || !hasMoreThreads)
|
|
454
517
|
return;
|
|
@@ -509,8 +572,11 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
509
572
|
// One page, so absence from it is not absence from the server — this is what
|
|
510
573
|
// separates an older real thread from an unavailable saved id below.
|
|
511
574
|
const restoredThread = lookupRestored && !restoredOnPage
|
|
512
|
-
? await fetchThreadById(apiUrl, restoredId)
|
|
575
|
+
? await fetchThreadById(apiUrl, restoredId, historyScope)
|
|
513
576
|
: restoredOnPage;
|
|
577
|
+
if (restoredThread) {
|
|
578
|
+
knownThreadScopesRef.current.set(restoredThread.id, restoredThread.scope ?? null);
|
|
579
|
+
}
|
|
514
580
|
if (restoredThread === undefined && lookupRestored && !restoredOnPage) {
|
|
515
581
|
// Lookup unreachable. Reclassifying now would stamp this thread with the
|
|
516
582
|
// current scope on a guess; leave it untouched for the next mount.
|
|
@@ -519,7 +585,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
519
585
|
}
|
|
520
586
|
const restoredIsUnavailable = restoredThread === null && lookupRestored && !restoredOnPage;
|
|
521
587
|
const restoredBelongsElsewhere = Boolean(restoredThread &&
|
|
522
|
-
!
|
|
588
|
+
!threadCanStayVisibleInHistory(restoredThread.scope ?? null, scopeRef.current, isolateHistory));
|
|
523
589
|
// A missing saved id is stale local UI state on a normal home surface,
|
|
524
590
|
// not a reason to show an error above a fresh composer. Preserve it for
|
|
525
591
|
// explicit routes and list-only readers, where the caller still owns
|
|
@@ -587,6 +653,8 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
587
653
|
fetchThreads,
|
|
588
654
|
addOptimisticThread,
|
|
589
655
|
autoCreate,
|
|
656
|
+
historyScope,
|
|
657
|
+
isolateHistory,
|
|
590
658
|
routeControlsActiveThread,
|
|
591
659
|
routeThreadId,
|
|
592
660
|
]);
|
|
@@ -641,7 +709,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
641
709
|
// list right away.
|
|
642
710
|
const detachThread = useCallback(async (threadId) => {
|
|
643
711
|
try {
|
|
644
|
-
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}`, {
|
|
712
|
+
const res = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(threadId)}`, historyScope), {
|
|
645
713
|
method: "PUT",
|
|
646
714
|
headers: { "Content-Type": "application/json" },
|
|
647
715
|
body: JSON.stringify({ scope: null }),
|
|
@@ -652,14 +720,42 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
652
720
|
await fetchThreads();
|
|
653
721
|
return;
|
|
654
722
|
}
|
|
655
|
-
|
|
723
|
+
knownThreadScopesRef.current.set(threadId, null);
|
|
656
724
|
optimisticThreadScopesRef.current.set(threadId, null);
|
|
725
|
+
const wasActive = activeThreadIdRef.current === threadId;
|
|
726
|
+
if (isolateHistory) {
|
|
727
|
+
setThreads((prev) => prev.filter((thread) => thread.id !== threadId &&
|
|
728
|
+
threadCanStayVisibleInHistory(thread.scope, historyScope, isolateHistory)));
|
|
729
|
+
if (wasActive) {
|
|
730
|
+
const remaining = threadsRef.current.filter((thread) => thread.id !== threadId &&
|
|
731
|
+
threadCanStayVisibleInHistory(thread.scope, historyScope, isolateHistory));
|
|
732
|
+
if (remaining.length > 0) {
|
|
733
|
+
setActiveThreadId(remaining[0].id);
|
|
734
|
+
}
|
|
735
|
+
else if (autoCreate) {
|
|
736
|
+
void createThread();
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
setActiveThreadId(null);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
setThreads((prev) => prev.map((t) => (t.id === threadId ? { ...t, scope: null } : t)));
|
|
745
|
+
}
|
|
657
746
|
emitThreadsUpdated();
|
|
658
747
|
}
|
|
659
748
|
catch {
|
|
660
749
|
await fetchThreads().catch(() => { });
|
|
661
750
|
}
|
|
662
|
-
}, [
|
|
751
|
+
}, [
|
|
752
|
+
apiUrl,
|
|
753
|
+
autoCreate,
|
|
754
|
+
createThread,
|
|
755
|
+
fetchThreads,
|
|
756
|
+
historyScope,
|
|
757
|
+
isolateHistory,
|
|
758
|
+
]);
|
|
663
759
|
const pinThread = useCallback(async (threadId, pinned) => {
|
|
664
760
|
const previousPinnedAt = threadsRef.current.find((t) => t.id === threadId)?.pinnedAt ?? null;
|
|
665
761
|
const previousUpdatedAt = threadsRef.current.find((t) => t.id === threadId)?.updatedAt ?? null;
|
|
@@ -680,7 +776,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
680
776
|
};
|
|
681
777
|
setThreads((prev) => prev.map((t) => (t.id === threadId ? { ...t, pinnedAt } : t)));
|
|
682
778
|
try {
|
|
683
|
-
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}/pin`, {
|
|
779
|
+
const res = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(threadId)}/pin`, historyScope), {
|
|
684
780
|
method: "POST",
|
|
685
781
|
headers: { "Content-Type": "application/json" },
|
|
686
782
|
body: JSON.stringify({ pinned }),
|
|
@@ -701,7 +797,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
701
797
|
await fetchThreads();
|
|
702
798
|
return false;
|
|
703
799
|
}
|
|
704
|
-
}, [apiUrl, fetchThreads]);
|
|
800
|
+
}, [apiUrl, fetchThreads, historyScope]);
|
|
705
801
|
const archiveThread = useCallback(async (threadId) => {
|
|
706
802
|
const previousArchivedAt = threadsRef.current.find((t) => t.id === threadId)?.archivedAt ?? null;
|
|
707
803
|
const previousUpdatedAt = threadsRef.current.find((t) => t.id === threadId)?.updatedAt ?? null;
|
|
@@ -726,7 +822,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
726
822
|
};
|
|
727
823
|
setThreads((prev) => prev.map((t) => (t.id === threadId ? { ...t, archivedAt } : t)));
|
|
728
824
|
try {
|
|
729
|
-
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}/archive`, {
|
|
825
|
+
const res = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(threadId)}/archive`, historyScope), {
|
|
730
826
|
method: "POST",
|
|
731
827
|
headers: { "Content-Type": "application/json" },
|
|
732
828
|
body: JSON.stringify({ archived: true }),
|
|
@@ -750,7 +846,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
750
846
|
await fetchThreads();
|
|
751
847
|
return false;
|
|
752
848
|
}
|
|
753
|
-
}, [apiUrl, fetchThreads]);
|
|
849
|
+
}, [apiUrl, fetchThreads, historyScope]);
|
|
754
850
|
const renameThread = useCallback(async (threadId, title) => {
|
|
755
851
|
const nextTitle = title.replace(/\s+/g, " ").trim().slice(0, 160);
|
|
756
852
|
if (!nextTitle)
|
|
@@ -768,7 +864,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
768
864
|
markUserRenamedThread(threadId);
|
|
769
865
|
setThreads((prev) => prev.map((t) => (t.id === threadId ? { ...t, title: nextTitle } : t)));
|
|
770
866
|
try {
|
|
771
|
-
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}/rename`, {
|
|
867
|
+
const res = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(threadId)}/rename`, historyScope), {
|
|
772
868
|
method: "POST",
|
|
773
869
|
headers: { "Content-Type": "application/json" },
|
|
774
870
|
body: JSON.stringify({ title: nextTitle }),
|
|
@@ -786,7 +882,13 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
786
882
|
await fetchThreads();
|
|
787
883
|
return false;
|
|
788
884
|
}
|
|
789
|
-
}, [
|
|
885
|
+
}, [
|
|
886
|
+
apiUrl,
|
|
887
|
+
clearUserRenamedThread,
|
|
888
|
+
fetchThreads,
|
|
889
|
+
historyScope,
|
|
890
|
+
markUserRenamedThread,
|
|
891
|
+
]);
|
|
790
892
|
const isNewThread = useCallback((id) => newlyCreatedRef.current.has(id), []);
|
|
791
893
|
const switchThread = useCallback((id) => {
|
|
792
894
|
persistActiveThreadId(id);
|
|
@@ -794,7 +896,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
794
896
|
}, [persistActiveThreadId]);
|
|
795
897
|
const removeThread = useCallback(async (id) => {
|
|
796
898
|
try {
|
|
797
|
-
await fetch(`${apiUrl}/threads/${encodeURIComponent(id)}`, {
|
|
899
|
+
await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(id)}`, historyScope), {
|
|
798
900
|
method: "DELETE",
|
|
799
901
|
});
|
|
800
902
|
emitThreadsUpdated();
|
|
@@ -816,7 +918,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
816
918
|
createThread();
|
|
817
919
|
}
|
|
818
920
|
}
|
|
819
|
-
}, [apiUrl, clearUserRenamedThread, createThread]);
|
|
921
|
+
}, [apiUrl, clearUserRenamedThread, createThread, historyScope]);
|
|
820
922
|
// Reads scope through refs so this callback survives every setThreads. Scope
|
|
821
923
|
// rides only on creation: a periodic save must never move an existing thread
|
|
822
924
|
// between resources, however stale this client's guess is.
|
|
@@ -828,7 +930,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
828
930
|
const preserveUserTitle = userRenamedThreadIdsRef.current.has(id);
|
|
829
931
|
const title = nextThreadTitle(localThread?.title, data.title, data.preview, titleSource, { preserveUserTitle });
|
|
830
932
|
const payload = { ...threadDataPayload, title };
|
|
831
|
-
let response = await fetch(`${apiUrl}/threads/${encodeURIComponent(id)}`, {
|
|
933
|
+
let response = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(id)}`, historyScope), {
|
|
832
934
|
method: "PUT",
|
|
833
935
|
headers: { "Content-Type": "application/json" },
|
|
834
936
|
body: JSON.stringify(payload),
|
|
@@ -837,7 +939,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
837
939
|
// client-created thread, so no agent run has created its SQL row yet.
|
|
838
940
|
// Materialize that row idempotently and retry the same full save.
|
|
839
941
|
if (response.status === 404) {
|
|
840
|
-
const created = await fetch(`${apiUrl}/threads`, {
|
|
942
|
+
const created = await fetch(withChatThreadScope(`${apiUrl}/threads`, historyScope), {
|
|
841
943
|
method: "POST",
|
|
842
944
|
headers: { "Content-Type": "application/json" },
|
|
843
945
|
body: JSON.stringify({
|
|
@@ -848,7 +950,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
848
950
|
});
|
|
849
951
|
if (!created.ok)
|
|
850
952
|
return;
|
|
851
|
-
response = await fetch(`${apiUrl}/threads/${encodeURIComponent(id)}`, {
|
|
953
|
+
response = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(id)}`, historyScope), {
|
|
852
954
|
method: "PUT",
|
|
853
955
|
headers: { "Content-Type": "application/json" },
|
|
854
956
|
body: JSON.stringify(payload),
|
|
@@ -894,7 +996,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
894
996
|
});
|
|
895
997
|
}
|
|
896
998
|
catch { }
|
|
897
|
-
}, [apiUrl, readKnownThreadScope]);
|
|
999
|
+
}, [apiUrl, historyScope, readKnownThreadScope]);
|
|
898
1000
|
const generateTitle = useCallback(async (threadId, message) => {
|
|
899
1001
|
try {
|
|
900
1002
|
const res = await fetch(`${apiUrl}/generate-title`, {
|
|
@@ -923,7 +1025,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
923
1025
|
const fallbackForkFromSnapshot = async (source) => {
|
|
924
1026
|
const title = source.title ? `${source.title} (fork)` : "";
|
|
925
1027
|
const createdAt = Date.now();
|
|
926
|
-
const createRes = await fetch(`${apiUrl}/threads`, {
|
|
1028
|
+
const createRes = await fetch(withChatThreadScope(`${apiUrl}/threads`, historyScope), {
|
|
927
1029
|
method: "POST",
|
|
928
1030
|
headers: { "Content-Type": "application/json" },
|
|
929
1031
|
body: JSON.stringify({
|
|
@@ -934,7 +1036,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
934
1036
|
});
|
|
935
1037
|
if (!createRes.ok)
|
|
936
1038
|
return null;
|
|
937
|
-
const saveRes = await fetch(`${apiUrl}/threads/${encodeURIComponent(id)}`, {
|
|
1039
|
+
const saveRes = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(id)}`, historyScope), {
|
|
938
1040
|
method: "PUT",
|
|
939
1041
|
headers: { "Content-Type": "application/json" },
|
|
940
1042
|
body: JSON.stringify({
|
|
@@ -962,7 +1064,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
962
1064
|
const source = sourceSnapshot && sourceSnapshot.messageCount > 0
|
|
963
1065
|
? { ...sourceSnapshot, scope: localScope }
|
|
964
1066
|
: undefined;
|
|
965
|
-
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(sourceId)}/fork`, {
|
|
1067
|
+
const res = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(sourceId)}/fork`, historyScope), {
|
|
966
1068
|
method: "POST",
|
|
967
1069
|
headers: { "Content-Type": "application/json" },
|
|
968
1070
|
body: JSON.stringify({ id, ...(source ? { source } : {}) }),
|
|
@@ -1003,25 +1105,27 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
1003
1105
|
console.error(`[chat] fork threw for ${sourceId}:`, err);
|
|
1004
1106
|
return null;
|
|
1005
1107
|
}
|
|
1006
|
-
}, [apiUrl]);
|
|
1108
|
+
}, [apiUrl, historyScope]);
|
|
1007
1109
|
const searchThreads = useCallback(async (query) => {
|
|
1008
1110
|
try {
|
|
1009
1111
|
const params = new URLSearchParams({ q: query });
|
|
1010
1112
|
if (includeExternal)
|
|
1011
1113
|
params.set("includeExternal", "1");
|
|
1114
|
+
appendChatThreadScopeParams(params, historyScope);
|
|
1012
1115
|
const res = await fetch(`${apiUrl}/threads?${params.toString()}`);
|
|
1013
1116
|
if (!res.ok)
|
|
1014
1117
|
return [];
|
|
1015
1118
|
const data = await res.json();
|
|
1016
|
-
return data.threads ?? []
|
|
1119
|
+
return (data.threads ?? []).filter((thread) => !isolateHistory ||
|
|
1120
|
+
threadCanStayVisibleInHistory(thread.scope, historyScope, isolateHistory));
|
|
1017
1121
|
}
|
|
1018
1122
|
catch {
|
|
1019
1123
|
return [];
|
|
1020
1124
|
}
|
|
1021
|
-
}, [apiUrl, includeExternal]);
|
|
1125
|
+
}, [apiUrl, historyScope, includeExternal, isolateHistory]);
|
|
1022
1126
|
const getThreadShareState = useCallback(async (threadId) => {
|
|
1023
1127
|
try {
|
|
1024
|
-
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}/share
|
|
1128
|
+
const res = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(threadId)}/share`, historyScope));
|
|
1025
1129
|
if (!res.ok)
|
|
1026
1130
|
return null;
|
|
1027
1131
|
const data = await res.json();
|
|
@@ -1030,10 +1134,10 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
1030
1134
|
catch {
|
|
1031
1135
|
return null;
|
|
1032
1136
|
}
|
|
1033
|
-
}, [apiUrl]);
|
|
1137
|
+
}, [apiUrl, historyScope]);
|
|
1034
1138
|
const createThreadShareLink = useCallback(async (threadId) => {
|
|
1035
1139
|
try {
|
|
1036
|
-
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}/share`, { method: "POST" });
|
|
1140
|
+
const res = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(threadId)}/share`, historyScope), { method: "POST" });
|
|
1037
1141
|
if (!res.ok)
|
|
1038
1142
|
return null;
|
|
1039
1143
|
const data = await res.json();
|
|
@@ -1044,10 +1148,10 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
1044
1148
|
catch {
|
|
1045
1149
|
return null;
|
|
1046
1150
|
}
|
|
1047
|
-
}, [apiUrl]);
|
|
1151
|
+
}, [apiUrl, historyScope]);
|
|
1048
1152
|
const revokeThreadShareLink = useCallback(async (threadId) => {
|
|
1049
1153
|
try {
|
|
1050
|
-
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}/share`, { method: "DELETE" });
|
|
1154
|
+
const res = await fetch(withChatThreadScope(`${apiUrl}/threads/${encodeURIComponent(threadId)}/share`, historyScope), { method: "DELETE" });
|
|
1051
1155
|
if (!res.ok)
|
|
1052
1156
|
return null;
|
|
1053
1157
|
const data = await res.json();
|
|
@@ -1056,7 +1160,7 @@ export function useChatThreads(apiUrl = agentNativePath("/_agent-native/agent-ch
|
|
|
1056
1160
|
catch {
|
|
1057
1161
|
return null;
|
|
1058
1162
|
}
|
|
1059
|
-
}, [apiUrl]);
|
|
1163
|
+
}, [apiUrl, historyScope]);
|
|
1060
1164
|
const refreshThreads = useCallback(() => {
|
|
1061
1165
|
fetchThreads();
|
|
1062
1166
|
}, [fetchThreads]);
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
+
error?: undefined;
|
|
65
66
|
states: {
|
|
66
67
|
clientId: number;
|
|
67
68
|
state: string;
|
|
68
69
|
}[];
|
|
69
|
-
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
+
error?: undefined;
|
|
80
81
|
users: {
|
|
81
82
|
clientId: number;
|
|
82
83
|
lastSeen: number;
|
|
83
84
|
}[];
|
|
84
|
-
error?: undefined;
|
|
85
85
|
}>>;
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
error: string;
|
|
17
16
|
ok?: undefined;
|
|
17
|
+
error: string;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
package/dist/deploy/build.d.ts
CHANGED
|
@@ -101,6 +101,11 @@ export declare function isDurableBackgroundDeployEnabled(): boolean;
|
|
|
101
101
|
export declare const NETLIFY_INTEGRATION_RECOVERY_FUNCTION_NAME = "server-integration-recovery";
|
|
102
102
|
export declare function isIntegrationDurableDispatchDeployEnabled(): boolean;
|
|
103
103
|
export declare const NETLIFY_RECURRING_JOBS_FUNCTION_NAME = "agent-native-recurring-jobs";
|
|
104
|
+
/**
|
|
105
|
+
* Routed through the same resolver that produces the runtime marker, so the gate
|
|
106
|
+
* that emits the scheduled function and the value the deployed app reports
|
|
107
|
+
* cannot drift: a build that skips the emit always ships `"disabled"`.
|
|
108
|
+
*/
|
|
104
109
|
export declare function isRecurringJobsDeployEnabled(): boolean;
|
|
105
110
|
/**
|
|
106
111
|
* Keep-warm is opt-in because a once-a-minute wake prevents autosuspend on
|