@agent-native/core 0.95.0 → 0.95.1
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/README.md +2 -2
- package/corpus/core/CHANGELOG.md +10 -0
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +13 -0
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +18 -0
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +16 -0
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +17 -0
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +16 -0
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +17 -0
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +15 -0
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +16 -0
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +11 -0
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +12 -0
- package/corpus/core/docs/content/template-design.mdx +16 -0
- package/corpus/core/package.json +2 -2
- package/corpus/core/src/agent/production-agent.ts +20 -0
- package/corpus/core/src/agent/thread-data-builder.ts +41 -17
- package/corpus/core/src/client/AssistantChat.tsx +250 -25
- package/corpus/core/src/client/chat/tool-call-display.tsx +1 -1
- package/corpus/core/src/client/chat/use-reconnect-reader-owner.ts +28 -0
- package/corpus/core/src/client/guided-questions.tsx +9 -1
- package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +6 -7
- package/corpus/core/src/client/sse-event-processor.ts +90 -21
- package/corpus/core/src/connections/catalog.ts +2 -2
- package/corpus/core/src/deploy/build.ts +3 -0
- package/corpus/core/src/integrations/catalog.ts +2 -2
- package/corpus/core/src/server/auth.ts +1 -1
- package/corpus/core/src/server/credential-provider.ts +7 -3
- package/corpus/core/src/shared/cache-control.ts +10 -4
- package/corpus/templates/analytics/app/lib/data-sources.ts +5 -4
- package/corpus/templates/analytics/changelog/2026-07-10-slack-token-setup-marked-legacy.md +6 -0
- package/corpus/templates/analytics/server/lib/credential-keys.ts +6 -2
- package/corpus/templates/brain/changelog/2026-07-10-slack-backfill-token-marked-legacy.md +6 -0
- package/corpus/templates/brain/server/register-secrets.ts +2 -2
- package/corpus/templates/clips/app/components/library/library-layout.tsx +7 -1
- package/corpus/templates/clips/app/components/library/page-header.tsx +19 -3
- package/corpus/templates/clips/app/routes/_app.library._index.tsx +16 -12
- package/corpus/templates/clips/changelog/2026-07-10-new-recording-appears-once-when-the-library-sidebar-is-open.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-slack-token-fallback-guidance.md +6 -0
- package/corpus/templates/clips/server/register-secrets.ts +1 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +0 -66
- package/corpus/templates/content/app/routes/_app.local-files.tsx +7 -47
- package/corpus/templates/content/changelog/2026-07-10-local-folders-now-wait-for-an-explicit-pull-before-content-r.md +6 -0
- package/corpus/templates/content/package.json +1 -1
- package/corpus/templates/design/actions/generate-design.ts +128 -31
- package/corpus/templates/design/actions/present-design-variants.ts +37 -9
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +9 -3
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +32 -10
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +2 -2
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +9 -1
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +7 -5
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +3 -0
- package/corpus/templates/design/app/global.css +10 -0
- package/corpus/templates/design/app/hooks/use-question-flow.ts +9 -2
- package/corpus/templates/design/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/design/app/i18n-data.ts +21 -11
- package/corpus/templates/design/changelog/2026-07-10-editor-panels-are-easier-to-distinguish-and-design-intake-qu.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-interact-mode-now-stays-on-the-full-canvas-matches-edit-visu.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-new-web-designs-open-at-desktop-size-and-adapt-across-mobile.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-tweaks-now-link-to-full-documentation.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/mail/app/i18n/ar-SA.ts +3 -3
- package/corpus/templates/mail/app/i18n/de-DE.ts +3 -3
- package/corpus/templates/mail/app/i18n/en-US.ts +4 -3
- package/corpus/templates/mail/app/i18n/es-ES.ts +3 -3
- package/corpus/templates/mail/app/i18n/fr-FR.ts +3 -3
- package/corpus/templates/mail/app/i18n/hi-IN.ts +3 -3
- package/corpus/templates/mail/app/i18n/ja-JP.ts +3 -3
- package/corpus/templates/mail/app/i18n/ko-KR.ts +3 -3
- package/corpus/templates/mail/app/i18n/pt-BR.ts +3 -3
- package/corpus/templates/mail/app/i18n/zh-CN.ts +3 -3
- package/corpus/templates/mail/app/i18n/zh-TW.ts +3 -3
- package/corpus/templates/mail/changelog/2026-07-10-slack-intake-marked-legacy.md +6 -0
- package/corpus/templates/mail/server/lib/env-config.ts +5 -4
- package/corpus/templates/plan/package.json +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +20 -0
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +36 -18
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +3 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +200 -28
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/chat/tool-call-display.js +1 -1
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/chat/use-reconnect-reader-owner.d.ts +11 -0
- package/dist/client/chat/use-reconnect-reader-owner.d.ts.map +1 -0
- package/dist/client/chat/use-reconnect-reader-owner.js +21 -0
- package/dist/client/chat/use-reconnect-reader-owner.js.map +1 -0
- package/dist/client/guided-questions.d.ts.map +1 -1
- package/dist/client/guided-questions.js +5 -1
- package/dist/client/guided-questions.js.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.js +5 -7
- package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +67 -20
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +2 -2
- package/dist/connections/catalog.js +2 -2
- package/dist/connections/catalog.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +3 -1
- package/dist/deploy/build.js.map +1 -1
- package/dist/integrations/catalog.js +2 -2
- package/dist/integrations/catalog.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.js +1 -1
- package/dist/server/auth.js.map +1 -1
- package/dist/server/credential-provider.d.ts +5 -3
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +7 -3
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/shared/cache-control.d.ts +8 -6
- package/dist/shared/cache-control.d.ts.map +1 -1
- package/dist/shared/cache-control.js +8 -3
- package/dist/shared/cache-control.js.map +1 -1
- package/docs/content/locales/ar-SA/template-design.mdx +13 -0
- package/docs/content/locales/de-DE/template-design.mdx +18 -0
- package/docs/content/locales/es-ES/template-design.mdx +16 -0
- package/docs/content/locales/fr-FR/template-design.mdx +17 -0
- package/docs/content/locales/hi-IN/template-design.mdx +16 -0
- package/docs/content/locales/ja-JP/template-design.mdx +17 -0
- package/docs/content/locales/ko-KR/template-design.mdx +15 -0
- package/docs/content/locales/pt-BR/template-design.mdx +16 -0
- package/docs/content/locales/zh-CN/template-design.mdx +11 -0
- package/docs/content/locales/zh-TW/template-design.mdx +12 -0
- package/docs/content/template-design.mdx +16 -0
- package/package.json +2 -2
|
@@ -32,6 +32,7 @@ import { normalizeAppBasePath } from "../server/app-base-path.js";
|
|
|
32
32
|
import {
|
|
33
33
|
DEFAULT_SSR_CDN_CACHE_CONTROL,
|
|
34
34
|
DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL,
|
|
35
|
+
DEFAULT_SSR_NETLIFY_VARY,
|
|
35
36
|
DEFAULT_SPECULATION_RULES_PATH,
|
|
36
37
|
DEFAULT_SSR_CACHE_CONTROL,
|
|
37
38
|
} from "../shared/cache-control.js";
|
|
@@ -908,6 +909,7 @@ function injectHeadScript(html, script) {
|
|
|
908
909
|
const DEFAULT_SSR_CACHE_CONTROL = ${JSON.stringify(DEFAULT_SSR_CACHE_CONTROL)};
|
|
909
910
|
const DEFAULT_SSR_CDN_CACHE_CONTROL = ${JSON.stringify(DEFAULT_SSR_CDN_CACHE_CONTROL)};
|
|
910
911
|
const DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL = ${JSON.stringify(DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL)};
|
|
912
|
+
const DEFAULT_SSR_NETLIFY_VARY = ${JSON.stringify(DEFAULT_SSR_NETLIFY_VARY)};
|
|
911
913
|
const DEFAULT_SPECULATION_RULES_PATH = ${JSON.stringify(DEFAULT_SPECULATION_RULES_PATH)};
|
|
912
914
|
const IMMUTABLE_ASSET_CACHE_CONTROL = ${JSON.stringify(IMMUTABLE_ASSET_CACHE_CONTROL)};
|
|
913
915
|
const IMMUTABLE_ASSET_PATHS = new Set(${JSON.stringify(
|
|
@@ -1003,6 +1005,7 @@ function applyDefaultSsrCacheHeader(headers, status, pathname) {
|
|
|
1003
1005
|
// Netlify-specific header so SSR HTML/.data are served from the shared
|
|
1004
1006
|
// durable CDN cache instead of stampeding origin — for every visitor.
|
|
1005
1007
|
headers.set("netlify-cdn-cache-control", DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL);
|
|
1008
|
+
headers.set("netlify-vary", DEFAULT_SSR_NETLIFY_VARY);
|
|
1006
1009
|
}
|
|
1007
1010
|
|
|
1008
1011
|
function applyDefaultSpeculationRulesHeader(headers, status, basePath) {
|
|
@@ -137,10 +137,10 @@ const BUILT_IN_CHANNEL_CATALOG = [
|
|
|
137
137
|
credentialRequirements: [
|
|
138
138
|
{
|
|
139
139
|
key: "SLACK_BOT_TOKEN",
|
|
140
|
-
label: "Slack Bot Token",
|
|
140
|
+
label: "Slack Bot Token (legacy)",
|
|
141
141
|
required: false,
|
|
142
142
|
helpText:
|
|
143
|
-
"
|
|
143
|
+
"Legacy single-workspace fallback only. For new setups, install Slack from Settings → Messaging; managed OAuth stores each workspace token automatically.",
|
|
144
144
|
},
|
|
145
145
|
{
|
|
146
146
|
key: "SLACK_CLIENT_ID",
|
|
@@ -1627,7 +1627,7 @@ function loginHtmlResponse(loginHtml: string, event: H3Event): Response {
|
|
|
1627
1627
|
headers: {
|
|
1628
1628
|
"Content-Type": "text/html; charset=utf-8",
|
|
1629
1629
|
// The sign-in document is part of the public server shell. Keep it on the
|
|
1630
|
-
// same
|
|
1630
|
+
// same long-fresh/long-SWR CDN policy as React Router SSR so hosted
|
|
1631
1631
|
// template roots do not invoke origin just to render anonymous login UI.
|
|
1632
1632
|
// The login HTML is env-INDEPENDENT (a Google-only app always renders a
|
|
1633
1633
|
// working button), so a cached copy is never "wrong" — never downgrade
|
|
@@ -78,6 +78,8 @@ const APP_PROVIDED_DEPLOY_CREDENTIAL_KEYS = new Set([
|
|
|
78
78
|
"OPENAI_API_KEY",
|
|
79
79
|
"OPENAI_BASE_URL",
|
|
80
80
|
"OPENROUTER_API_KEY",
|
|
81
|
+
"GOOGLE_CLIENT_ID",
|
|
82
|
+
"GOOGLE_CLIENT_SECRET",
|
|
81
83
|
"GOOGLE_GENERATIVE_AI_API_KEY",
|
|
82
84
|
"GROQ_API_KEY",
|
|
83
85
|
"MISTRAL_API_KEY",
|
|
@@ -93,9 +95,11 @@ function isAppProvidedDeployCredentialKey(key: string | undefined): boolean {
|
|
|
93
95
|
* single-tenant contexts. In hosted production with a shared database, every
|
|
94
96
|
* signed-in user needs their own user/org/workspace credential for
|
|
95
97
|
* identity-bearing provider keys so one deploy key does not silently
|
|
96
|
-
* impersonate another tenant. App-provided
|
|
97
|
-
* they
|
|
98
|
-
* that
|
|
98
|
+
* impersonate another tenant. App-provided service credentials are different:
|
|
99
|
+
* they configure the deployed app itself rather than identifying a user. This
|
|
100
|
+
* includes LLM keys that let the app developer pay for model usage and OAuth
|
|
101
|
+
* client credentials whose per-user identity remains in scoped OAuth tokens.
|
|
102
|
+
* Key-aware callers may use those env vars.
|
|
99
103
|
*
|
|
100
104
|
* @deprecated Use `canUseDeployCredentialFallbackForRequest()` for generic
|
|
101
105
|
* provider secrets. This stricter helper remains for legacy call sites with
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
export const DEFAULT_SSR_CACHE_CONTROL =
|
|
2
|
-
"public, max-age=5, stale-while-revalidate=604800, stale-if-error=3600";
|
|
1
|
+
export const DEFAULT_SSR_CACHE_CONTROL = "public, max-age=0, must-revalidate";
|
|
3
2
|
|
|
4
|
-
export const DEFAULT_SSR_CDN_CACHE_CONTROL =
|
|
3
|
+
export const DEFAULT_SSR_CDN_CACHE_CONTROL =
|
|
4
|
+
"public, s-maxage=3600, stale-while-revalidate=604800, stale-if-error=3600";
|
|
5
5
|
|
|
6
6
|
export const DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL =
|
|
7
|
-
"public, durable,
|
|
7
|
+
"public, durable, s-maxage=3600, stale-while-revalidate=604800, stale-if-error=3600";
|
|
8
|
+
|
|
9
|
+
// React Router data requests can select a subset of route loaders with
|
|
10
|
+
// `?_routes=...`. Ignore every other query parameter (UTM tags, click ids,
|
|
11
|
+
// and similar tracking noise) so they cannot fragment Netlify's SSR cache.
|
|
12
|
+
export const DEFAULT_SSR_NETLIFY_VARY = "query=_routes";
|
|
8
13
|
|
|
9
14
|
export const DEFAULT_SSR_CACHE_HEADERS = {
|
|
10
15
|
"cache-control": DEFAULT_SSR_CACHE_CONTROL,
|
|
11
16
|
"cdn-cache-control": DEFAULT_SSR_CDN_CACHE_CONTROL,
|
|
12
17
|
"netlify-cdn-cache-control": DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL,
|
|
18
|
+
"netlify-vary": DEFAULT_SSR_NETLIFY_VARY,
|
|
13
19
|
} as const;
|
|
14
20
|
|
|
15
21
|
export const DEFAULT_SPECULATION_RULES_PATH =
|
|
@@ -748,14 +748,15 @@ export const dataSources: DataSource[] = [
|
|
|
748
748
|
{
|
|
749
749
|
id: "slack",
|
|
750
750
|
name: "Slack",
|
|
751
|
-
description:
|
|
751
|
+
description:
|
|
752
|
+
"Channel history and workspace search. Prefer a Slack workspace integration from Settings > Connections; a local bot token remains available as a legacy fallback.",
|
|
752
753
|
category: "communication",
|
|
753
754
|
icon: IconMessage,
|
|
754
755
|
envKeys: ["SLACK_BOT_TOKEN"],
|
|
755
756
|
docsUrl: "https://api.slack.com/methods",
|
|
756
757
|
walkthroughSteps: [
|
|
757
758
|
{
|
|
758
|
-
title: "Create a Slack App",
|
|
759
|
+
title: "Create a Slack App for local fallback access",
|
|
759
760
|
description:
|
|
760
761
|
"Go to api.slack.com/apps, create a new app, and add OAuth scopes: channels:read, channels:history, search:read.",
|
|
761
762
|
url: "https://api.slack.com/apps",
|
|
@@ -767,10 +768,10 @@ export const dataSources: DataSource[] = [
|
|
|
767
768
|
'Under "OAuth & Permissions", install the app and copy the Bot User OAuth Token.',
|
|
768
769
|
},
|
|
769
770
|
{
|
|
770
|
-
title: "Enter your Bot Token",
|
|
771
|
+
title: "Enter your local fallback Bot Token",
|
|
771
772
|
description: 'Paste the Bot User OAuth Token (starts with "xoxb-").',
|
|
772
773
|
inputKey: "SLACK_BOT_TOKEN",
|
|
773
|
-
inputLabel: "Bot Token",
|
|
774
|
+
inputLabel: "Bot Token (legacy local fallback)",
|
|
774
775
|
inputPlaceholder: "xoxb-...",
|
|
775
776
|
inputType: "password",
|
|
776
777
|
},
|
|
@@ -107,10 +107,14 @@ export const credentialKeys: CredentialKeyConfig[] = [
|
|
|
107
107
|
required: false,
|
|
108
108
|
},
|
|
109
109
|
// Slack
|
|
110
|
-
{
|
|
110
|
+
{
|
|
111
|
+
key: "SLACK_BOT_TOKEN",
|
|
112
|
+
label: "Slack Bot Token (legacy local fallback)",
|
|
113
|
+
required: false,
|
|
114
|
+
},
|
|
111
115
|
{
|
|
112
116
|
key: "SLACK_BOT_TOKEN_2",
|
|
113
|
-
label: "Slack Bot Token (secondary)",
|
|
117
|
+
label: "Slack Bot Token (legacy secondary fallback)",
|
|
114
118
|
required: false,
|
|
115
119
|
},
|
|
116
120
|
// Notion
|
|
@@ -2,9 +2,9 @@ import { registerRequiredSecret } from "@agent-native/core/secrets";
|
|
|
2
2
|
|
|
3
3
|
registerRequiredSecret({
|
|
4
4
|
key: "SLACK_BOT_TOKEN",
|
|
5
|
-
label: "Slack Bot Token",
|
|
5
|
+
label: "Slack Bot Token (local fallback)",
|
|
6
6
|
description:
|
|
7
|
-
"Optional
|
|
7
|
+
"Optional local fallback for Brain channel backfills. Prefer a Slack workspace integration in Settings > Connections. Brain only scans allow-listed channels and never enumerates DMs.",
|
|
8
8
|
docsUrl: "https://api.slack.com/authentication/token-types",
|
|
9
9
|
scope: "workspace",
|
|
10
10
|
kind: "api-key",
|
|
@@ -154,6 +154,9 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
|
|
|
154
154
|
);
|
|
155
155
|
const [headerSlot, setHeaderSlot] = useState<HTMLElement | null>(null);
|
|
156
156
|
const showCollapsedSidebar = sidebarCollapsed && !isMobile;
|
|
157
|
+
const sidebarHasNewRecordingAction = isMobile
|
|
158
|
+
? sidebarOpen
|
|
159
|
+
: !sidebarCollapsed;
|
|
157
160
|
|
|
158
161
|
// Routes whose page renders its own h-12 toolbar. Layout still mounts Sidebar
|
|
159
162
|
// + AgentSidebar, but skips its own header so there's no double-header.
|
|
@@ -603,7 +606,10 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
|
|
|
603
606
|
</div>
|
|
604
607
|
)}
|
|
605
608
|
<main className="agent-native-app-main flex min-h-0 flex-1 flex-col overflow-y-auto">
|
|
606
|
-
<PageHeaderSlotProvider
|
|
609
|
+
<PageHeaderSlotProvider
|
|
610
|
+
slot={headerSlot}
|
|
611
|
+
sidebarHasNewRecordingAction={sidebarHasNewRecordingAction}
|
|
612
|
+
>
|
|
607
613
|
{children}
|
|
608
614
|
</PageHeaderSlotProvider>
|
|
609
615
|
</main>
|
|
@@ -7,24 +7,40 @@ import {
|
|
|
7
7
|
} from "react";
|
|
8
8
|
import { createPortal } from "react-dom";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface PageHeaderSlotContextValue {
|
|
11
|
+
slot: HTMLElement | null;
|
|
12
|
+
sidebarHasNewRecordingAction: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const PageHeaderSlotContext = createContext<PageHeaderSlotContextValue>({
|
|
16
|
+
slot: null,
|
|
17
|
+
sidebarHasNewRecordingAction: false,
|
|
18
|
+
});
|
|
11
19
|
|
|
12
20
|
export function PageHeaderSlotProvider({
|
|
13
21
|
slot,
|
|
22
|
+
sidebarHasNewRecordingAction,
|
|
14
23
|
children,
|
|
15
24
|
}: {
|
|
16
25
|
slot: HTMLElement | null;
|
|
26
|
+
sidebarHasNewRecordingAction: boolean;
|
|
17
27
|
children: ReactNode;
|
|
18
28
|
}) {
|
|
19
29
|
return (
|
|
20
|
-
<PageHeaderSlotContext.Provider
|
|
30
|
+
<PageHeaderSlotContext.Provider
|
|
31
|
+
value={{ slot, sidebarHasNewRecordingAction }}
|
|
32
|
+
>
|
|
21
33
|
{children}
|
|
22
34
|
</PageHeaderSlotContext.Provider>
|
|
23
35
|
);
|
|
24
36
|
}
|
|
25
37
|
|
|
38
|
+
export function usePageHeaderLayout() {
|
|
39
|
+
return useContext(PageHeaderSlotContext);
|
|
40
|
+
}
|
|
41
|
+
|
|
26
42
|
export function PageHeader({ children }: { children: ReactNode }) {
|
|
27
|
-
const slot =
|
|
43
|
+
const { slot } = usePageHeaderLayout();
|
|
28
44
|
const [ready, setReady] = useState(false);
|
|
29
45
|
useEffect(() => setReady(true), []);
|
|
30
46
|
if (!ready || !slot) return null;
|
|
@@ -4,6 +4,7 @@ import { IconPlayerRecord } from "@tabler/icons-react";
|
|
|
4
4
|
import { NavLink } from "react-router";
|
|
5
5
|
|
|
6
6
|
import { LibraryGrid } from "@/components/library/library-grid";
|
|
7
|
+
import { usePageHeaderLayout } from "@/components/library/page-header";
|
|
7
8
|
|
|
8
9
|
const SEO_TITLE =
|
|
9
10
|
"Agent-Native Clips - Open Source, agent-friendly Loom alternative";
|
|
@@ -24,24 +25,27 @@ export function meta() {
|
|
|
24
25
|
|
|
25
26
|
export default function LibraryIndexRoute() {
|
|
26
27
|
const t = useT();
|
|
28
|
+
const { sidebarHasNewRecordingAction } = usePageHeaderLayout();
|
|
27
29
|
return (
|
|
28
30
|
<LibraryGrid
|
|
29
31
|
view="library"
|
|
30
32
|
folderId={null}
|
|
31
33
|
title="Library"
|
|
32
34
|
extraActions={
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
!sidebarHasNewRecordingAction && (
|
|
36
|
+
<Button
|
|
37
|
+
className="gap-1.5 bg-primary text-primary-foreground shadow-sm hover:bg-primary/90"
|
|
38
|
+
size="sm"
|
|
39
|
+
asChild
|
|
40
|
+
>
|
|
41
|
+
<NavLink to="/record" aria-label={t("navigation.newRecording")}>
|
|
42
|
+
<IconPlayerRecord className="h-4 w-4" />
|
|
43
|
+
<span className="hidden sm:inline">
|
|
44
|
+
{t("navigation.newRecording")}
|
|
45
|
+
</span>
|
|
46
|
+
</NavLink>
|
|
47
|
+
</Button>
|
|
48
|
+
)
|
|
45
49
|
}
|
|
46
50
|
/>
|
|
47
51
|
);
|
|
@@ -212,7 +212,7 @@ registerRequiredSecret({
|
|
|
212
212
|
key: "SLACK_BOT_TOKEN",
|
|
213
213
|
label: "Slack Bot Token (legacy)",
|
|
214
214
|
description:
|
|
215
|
-
"Legacy single-workspace bot token fallback for Clips link unfurls. New installs should use the Slack
|
|
215
|
+
"Legacy single-workspace bot token fallback for Clips link unfurls. New installs should use the Clips Slack workspace connection; new messaging automations should connect Slack in Settings > Messaging.",
|
|
216
216
|
docsUrl: "https://api.slack.com/apps",
|
|
217
217
|
scope: "workspace",
|
|
218
218
|
kind: "api-key",
|
|
@@ -50,7 +50,6 @@ import {
|
|
|
50
50
|
} from "@/hooks/use-notion";
|
|
51
51
|
import {
|
|
52
52
|
canWriteLinkedLocalSource,
|
|
53
|
-
readDocumentFromLinkedLocalSource,
|
|
54
53
|
writeDocumentToLinkedLocalSource,
|
|
55
54
|
} from "@/lib/local-content-source-files";
|
|
56
55
|
import { cn } from "@/lib/utils";
|
|
@@ -538,71 +537,6 @@ function DocumentEditorBody({ documentId, document }: DocumentEditorBodyProps) {
|
|
|
538
537
|
}
|
|
539
538
|
}, [document, documentId]);
|
|
540
539
|
|
|
541
|
-
useEffect(() => {
|
|
542
|
-
if (!isInitializedRef.current || !isLinkedLocalSourceDocument) {
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
let cancelled = false;
|
|
547
|
-
readDocumentFromLinkedLocalSource(document)
|
|
548
|
-
.then((result) => {
|
|
549
|
-
if (cancelled) return;
|
|
550
|
-
if (!result.ok) {
|
|
551
|
-
toast.error(t("editor.couldNotReadLocalSourceFile"), {
|
|
552
|
-
description: result.error,
|
|
553
|
-
});
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
const fileDocument = result.document;
|
|
558
|
-
setLocalTitle(fileDocument.title);
|
|
559
|
-
setLocalContent(fileDocument.content);
|
|
560
|
-
setLocalContentUpdatedAt(result.updatedAt);
|
|
561
|
-
lastSavedTitleRef.current = {
|
|
562
|
-
title: fileDocument.title,
|
|
563
|
-
updatedAt: result.updatedAt,
|
|
564
|
-
};
|
|
565
|
-
lastSavedContentRef.current = {
|
|
566
|
-
content: fileDocument.content,
|
|
567
|
-
updatedAt: result.updatedAt,
|
|
568
|
-
};
|
|
569
|
-
queryClient.setQueryData(
|
|
570
|
-
["action", "get-document", { id: documentId }],
|
|
571
|
-
(old: Document | undefined) =>
|
|
572
|
-
old && typeof old === "object" ? { ...old, ...fileDocument } : old,
|
|
573
|
-
);
|
|
574
|
-
queryClient.setQueryData(
|
|
575
|
-
["action", "list-documents", undefined],
|
|
576
|
-
(old: any) => {
|
|
577
|
-
const docs = old?.documents ?? (Array.isArray(old) ? old : null);
|
|
578
|
-
if (!Array.isArray(docs)) return old;
|
|
579
|
-
const nextDocs = docs.map((doc: Document) =>
|
|
580
|
-
doc.id === documentId ? { ...doc, ...fileDocument } : doc,
|
|
581
|
-
);
|
|
582
|
-
return Array.isArray(old)
|
|
583
|
-
? nextDocs
|
|
584
|
-
: { ...old, documents: nextDocs };
|
|
585
|
-
},
|
|
586
|
-
);
|
|
587
|
-
})
|
|
588
|
-
.catch((error) => {
|
|
589
|
-
if (cancelled) return;
|
|
590
|
-
toast.error(t("editor.couldNotReadLocalSourceFile"), {
|
|
591
|
-
description:
|
|
592
|
-
error instanceof Error ? error.message : t("empty.genericError"),
|
|
593
|
-
});
|
|
594
|
-
});
|
|
595
|
-
|
|
596
|
-
return () => {
|
|
597
|
-
cancelled = true;
|
|
598
|
-
};
|
|
599
|
-
}, [
|
|
600
|
-
documentId,
|
|
601
|
-
document.source?.path,
|
|
602
|
-
isLinkedLocalSourceDocument,
|
|
603
|
-
queryClient,
|
|
604
|
-
]);
|
|
605
|
-
|
|
606
540
|
// NOTE: External body changes (agent edit, Notion pull, update-document) are
|
|
607
541
|
// reconciled into the editor by VisualEditor via its content prop + the
|
|
608
542
|
// updatedAt gate. The effects below keep DocumentEditor's own mirror
|
|
@@ -814,13 +814,6 @@ export default function LocalFilesRoute() {
|
|
|
814
814
|
count: restoredDirectories.length,
|
|
815
815
|
}),
|
|
816
816
|
});
|
|
817
|
-
await pullDirectories(restoredDirectories, {
|
|
818
|
-
showToast: false,
|
|
819
|
-
syncControlResources: false,
|
|
820
|
-
});
|
|
821
|
-
await connectLocalComponentWorkspaces(restoredDirectories, {
|
|
822
|
-
showToast: false,
|
|
823
|
-
});
|
|
824
817
|
return;
|
|
825
818
|
}
|
|
826
819
|
|
|
@@ -835,13 +828,6 @@ export default function LocalFilesRoute() {
|
|
|
835
828
|
count: restoredDirectories.length,
|
|
836
829
|
}),
|
|
837
830
|
});
|
|
838
|
-
await pullDirectories(restoredDirectories, {
|
|
839
|
-
showToast: false,
|
|
840
|
-
syncControlResources: false,
|
|
841
|
-
});
|
|
842
|
-
await connectLocalComponentWorkspaces(restoredDirectories, {
|
|
843
|
-
showToast: false,
|
|
844
|
-
});
|
|
845
831
|
};
|
|
846
832
|
restoreDirectories()
|
|
847
833
|
.catch((err) => {
|
|
@@ -943,32 +929,6 @@ export default function LocalFilesRoute() {
|
|
|
943
929
|
return { directories: nextDirectories, result };
|
|
944
930
|
}
|
|
945
931
|
|
|
946
|
-
async function pullDirectories(
|
|
947
|
-
selectedDirectories: SelectedDirectory[],
|
|
948
|
-
{
|
|
949
|
-
showToast = true,
|
|
950
|
-
syncControlResources = true,
|
|
951
|
-
}: { showToast?: boolean; syncControlResources?: boolean } = {},
|
|
952
|
-
) {
|
|
953
|
-
let activeDirectories = selectedDirectories;
|
|
954
|
-
let latestResult: ImportContentSourceResult | null = null;
|
|
955
|
-
for (const directory of selectedDirectories) {
|
|
956
|
-
const pulled = await pullDirectoryFiles(directory, activeDirectories, {
|
|
957
|
-
syncControlResources,
|
|
958
|
-
});
|
|
959
|
-
latestResult = pulled.result;
|
|
960
|
-
activeDirectories = pulled.directories;
|
|
961
|
-
}
|
|
962
|
-
if (latestResult) {
|
|
963
|
-
setStatus({
|
|
964
|
-
kind: "success",
|
|
965
|
-
title: t("localFiles.foldersPulled"),
|
|
966
|
-
detail: resultSummary(latestResult, t),
|
|
967
|
-
});
|
|
968
|
-
if (showToast) toast.success(t("localFiles.pulledLocalFiles"));
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
|
|
972
932
|
async function connectLocalComponentWorkspaces(
|
|
973
933
|
selectedDirectories: SelectedDirectory[],
|
|
974
934
|
{ showToast = true }: { showToast?: boolean } = {},
|
|
@@ -1029,7 +989,13 @@ export default function LocalFilesRoute() {
|
|
|
1029
989
|
});
|
|
1030
990
|
|
|
1031
991
|
setBusy(`pull:${selected.id}`);
|
|
1032
|
-
await
|
|
992
|
+
const { result } = await pullDirectoryFiles(selected, nextDirectories);
|
|
993
|
+
setStatus({
|
|
994
|
+
kind: "success",
|
|
995
|
+
title: t("localFiles.foldersPulled"),
|
|
996
|
+
detail: resultSummary(result, t),
|
|
997
|
+
});
|
|
998
|
+
toast.success(t("localFiles.pulledLocalFiles"));
|
|
1033
999
|
await connectLocalComponentWorkspaces([selected]);
|
|
1034
1000
|
} catch (err) {
|
|
1035
1001
|
setStatus({
|
|
@@ -1171,12 +1137,6 @@ export default function LocalFilesRoute() {
|
|
|
1171
1137
|
title: t("localFiles.folderRemoved"),
|
|
1172
1138
|
detail: directory.name,
|
|
1173
1139
|
});
|
|
1174
|
-
if (nextDirectories.length === 1) {
|
|
1175
|
-
await pullDirectories(nextDirectories, {
|
|
1176
|
-
showToast: false,
|
|
1177
|
-
syncControlResources: false,
|
|
1178
|
-
});
|
|
1179
|
-
}
|
|
1180
1140
|
} catch (err) {
|
|
1181
1141
|
setStatus({
|
|
1182
1142
|
kind: "error",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"@swc/core": "^1.13.3",
|
|
82
82
|
"@tailwindcss/typography": "^0.5.16",
|
|
83
83
|
"@tailwindcss/vite": "catalog:",
|
|
84
|
-
"@tanstack/react-query": "
|
|
84
|
+
"@tanstack/react-query": "5.101.2",
|
|
85
85
|
"@types/node": "^24.2.1",
|
|
86
86
|
"@types/react": "catalog:",
|
|
87
87
|
"@types/react-dom": "catalog:",
|