@agent-native/core-corpus 0.201.0-nightly-20261005153421 → 0.201.0
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 +1 -1
- package/corpus/templates/analytics/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +14 -4
- package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/analytics/CHANGELOG.md +6 -0
- package/corpus/templates/analytics/README.md +2 -2
- package/corpus/templates/analytics/changelog/2026-10-02-events-with-a-very-long-name-app-or-page-path-no-longer-caus.md +6 -0
- package/corpus/templates/analytics/package.json +1 -0
- package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +9 -19
- package/corpus/templates/analytics/server/handlers/session-replay.ts +34 -47
- package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +9 -6
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +57 -36
- package/corpus/templates/analytics/server/lib/indexed-text.ts +53 -0
- package/corpus/templates/analytics/server/lib/request-errors.ts +73 -0
- package/corpus/templates/analytics/server/lib/session-event-index.ts +6 -16
- package/corpus/templates/analytics/server/lib/session-replay.ts +12 -2
- package/corpus/templates/analytics/server/plugins/auth.ts +2 -1
- package/corpus/templates/analytics/server/plugins/otel.ts +6 -0
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/assets/CHANGELOG.md +7 -0
- package/corpus/templates/assets/README.md +2 -2
- package/corpus/templates/assets/package.json +1 -0
- package/corpus/templates/assets/server/plugins/auth.ts +2 -1
- package/corpus/templates/assets/server/plugins/otel.ts +6 -0
- package/corpus/templates/brain/.agents/skills/brain/RUNBOOK.md +2 -1
- package/corpus/templates/brain/.agents/skills/brain/SKILL.md +5 -4
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/brain/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/brain/CHANGELOG.md +6 -0
- package/corpus/templates/brain/README.md +12 -8
- package/corpus/templates/brain/changelog/2026-10-05-private-slack-channels-are-searchable-org-wide.md +6 -0
- package/corpus/templates/brain/package.json +1 -0
- package/corpus/templates/brain/server/lib/audiences.ts +1 -98
- package/corpus/templates/brain/server/lib/connectors.ts +2 -166
- package/corpus/templates/brain/server/plugins/otel.ts +6 -0
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/calendar/CHANGELOG.md +7 -0
- package/corpus/templates/calendar/README.md +2 -2
- package/corpus/templates/calendar/package.json +1 -0
- package/corpus/templates/calendar/server/plugins/auth.ts +2 -1
- package/corpus/templates/calendar/server/plugins/otel.ts +6 -0
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/chat/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/chat/README.md +2 -2
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +9 -0
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/clips/CHANGELOG.md +24 -0
- package/corpus/templates/clips/README.md +2 -2
- package/corpus/templates/clips/actions/lib/audio-chunk-list.ts +23 -0
- package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +187 -292
- package/corpus/templates/clips/actions/lib/chunked-transcription.ts +151 -0
- package/corpus/templates/clips/actions/lib/recording-audio-source.ts +191 -0
- package/corpus/templates/clips/actions/request-transcript.ts +81 -135
- package/corpus/templates/clips/actions/search-recordings.ts +19 -5
- package/corpus/templates/clips/app/components/clips-command-menu.tsx +5 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -1
- package/corpus/templates/clips/app/components/library/search-bar.tsx +5 -0
- package/corpus/templates/clips/app/hooks/use-library.ts +1 -0
- package/corpus/templates/clips/app/lib/local-recording-upload.ts +13 -6
- package/corpus/templates/clips/app/lib/recording-section.ts +1 -1
- package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +7 -5
- package/corpus/templates/clips/app/routes/record.tsx +16 -6
- package/corpus/templates/clips/changelog/2026-10-02-long-uploads-an-hour-or-more-now-transcribe-reliably-instead.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-confirming-discard-recording-now-returns-you-to-your-library.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-discarding-a-recording-now-removes-its-failed-upload-card-fr.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-discarding-a-recovered-recording-no-longer-warns-that-it-s-o.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-search-results-identify-recordings-in-trash-and-open-them-wi.md +6 -0
- package/corpus/templates/clips/package.json +1 -0
- package/corpus/templates/clips/server/lib/builder-cdn.ts +5 -0
- package/corpus/templates/clips/server/lib/builder-media-compression.ts +2 -2
- package/corpus/templates/clips/server/plugins/auth.ts +2 -1
- package/corpus/templates/clips/server/plugins/otel.ts +6 -0
- package/corpus/templates/clips/shared/transcript-failure.ts +5 -0
- package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +8 -2
- package/corpus/templates/content/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/content/CHANGELOG.md +41 -0
- package/corpus/templates/content/README.md +2 -2
- package/corpus/templates/content/actions/_database-navigation.ts +523 -344
- package/corpus/templates/content/actions/_database-row-mutation.ts +44 -10
- package/corpus/templates/content/actions/_database-setup-discovery.ts +9 -3
- package/corpus/templates/content/actions/_database-utils.ts +299 -271
- package/corpus/templates/content/actions/_property-utils.ts +293 -190
- package/corpus/templates/content/actions/_relation-values.ts +3 -1
- package/corpus/templates/content/actions/get-content-database.ts +1 -0
- package/corpus/templates/content/actions/query-content-database-items.ts +32 -5
- package/corpus/templates/content/actions/set-document-property.ts +17 -11
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +21 -6
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +127 -43
- package/corpus/templates/content/app/components/editor/DocumentEditorSkeleton.tsx +159 -50
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +12 -28
- package/corpus/templates/content/app/components/editor/PageDraftRecovery.tsx +6 -1
- package/corpus/templates/content/app/components/editor/TableHoverControls.tsx +139 -70
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +16 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +180 -75
- package/corpus/templates/content/app/components/editor/database/DatabaseViewSkeleton.tsx +76 -0
- package/corpus/templates/content/app/components/editor/database/navigation-state.ts +60 -2
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +41 -42
- package/corpus/templates/content/app/components/editor/document-editor-layout.ts +18 -0
- package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +11 -3
- package/corpus/templates/content/app/components/editor/suggestions/draft-session.ts +15 -7
- package/corpus/templates/content/app/components/editor/suggestions/model.ts +13 -0
- package/corpus/templates/content/app/components/editor/suggestions/read-only-blocks.ts +136 -0
- package/corpus/templates/content/app/components/editor/table-view.ts +73 -0
- package/corpus/templates/content/app/components/layout/ContentStartupShell.tsx +1 -1
- package/corpus/templates/content/app/components/layout/Layout.tsx +5 -1
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +57 -16
- package/corpus/templates/content/app/components/sidebar/MovePageDialog.tsx +4 -4
- package/corpus/templates/content/app/components/sidebar/SidebarNavigationRow.tsx +34 -10
- package/corpus/templates/content/app/global.css +16 -8
- package/corpus/templates/content/app/hooks/content-action-refresh.ts +14 -13
- package/corpus/templates/content/app/hooks/use-content-database.ts +72 -9
- package/corpus/templates/content/app/hooks/use-content-personal-navigation.ts +7 -3
- package/corpus/templates/content/app/hooks/use-documents.ts +27 -0
- package/corpus/templates/content/app/i18n-data.ts +3 -2
- package/corpus/templates/content/app/lib/content-landing.ts +3 -31
- package/corpus/templates/content/app/lib/files-navigation.ts +182 -10
- package/corpus/templates/content/app/lib/files-root-hint.ts +20 -32
- package/corpus/templates/content/app/lib/page-startup-hints.ts +108 -0
- package/corpus/templates/content/app/lib/private-link-redirect.ts +25 -0
- package/corpus/templates/content/app/lib/sidebar-layout-hint.ts +34 -1
- package/corpus/templates/content/app/lib/startup-timing.ts +2 -0
- package/corpus/templates/content/app/root.tsx +3 -1
- package/corpus/templates/content/app/routes/_app.home.tsx +10 -19
- package/corpus/templates/content/app/routes/p.$id.tsx +23 -5
- package/corpus/templates/content/changelog/2026-10-02-a-page-link-you-cant-open-now-says-so-instead-of-opening-an.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-after-a-refresh-the-files-sidebar-shows-the-open-page-s-fold.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-large-collections-open-faster.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-pages-stay-inside-the-window-at-every-width-long-inline-code.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-pages-with-open-comments-and-collections-with-sorted-or-filt.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-suggest-edits-works-on-pages-written-by-agents-including-pag.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-while-you-suggest-edits-tables-and-other-blocks-that-suggest.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-collection-view-context-now-survives-quick-page-changes-when.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-collection-views-keep-their-saved-rows-accurate-during-refre.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-exact-saved-view-links-keep-collection-retry-available.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-expanding-a-files-folder-now-shares-one-navigation-read-acro.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-files-navigation-retries-temporary-failures-consistently.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-shared-page-owners-keep-edit-and-manage-controls-in-files-an.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-tagging-an-ai-in-a-comment-works-again-instead-of-failing-ri.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-the-home-loading-shell-keeps-the-layout-of-your-last-opened-.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-typing-and-a-space-or-inserting-a-toggle-or-callout-no-longe.md +6 -0
- package/corpus/templates/content/docs/product/capabilities/content.workspace.session-restore.md +4 -1
- package/corpus/templates/content/e2e/playwright.config.ts +1 -1
- package/corpus/templates/content/package.json +2 -1
- package/corpus/templates/content/scripts/seed-perf-database.mjs +600 -0
- package/corpus/templates/content/scripts/trace-startup.mjs +25 -3
- package/corpus/templates/content/server/db/index.ts +1 -1
- package/corpus/templates/content/server/lib/suggested-edits.ts +23 -26
- package/corpus/templates/content/server/plugins/auth.ts +2 -1
- package/corpus/templates/content/server/plugins/otel.ts +6 -0
- package/corpus/templates/content/shared/api.ts +17 -0
- package/corpus/templates/content/shared/suggestion-diff.ts +124 -38
- package/corpus/templates/content/shared/suggestion-formatting.ts +134 -3
- package/corpus/templates/crm/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/crm/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/crm/package.json +1 -0
- package/corpus/templates/crm/server/plugins/otel.ts +6 -0
- package/corpus/templates/design/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/design/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/design/CHANGELOG.md +41 -0
- package/corpus/templates/design/README.md +2 -2
- package/corpus/templates/design/actions/list-designs.ts +11 -4
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +110 -32
- package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +28 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +1 -0
- package/corpus/templates/design/app/components/home/DesignHomeLibrary.tsx +79 -0
- package/corpus/templates/design/app/components/layout/Header.tsx +2 -4
- package/corpus/templates/design/app/components/ui/tabs.tsx +59 -1
- package/corpus/templates/design/app/global.css +1 -34
- package/corpus/templates/design/app/i18n/en-US.ts +4 -0
- package/corpus/templates/design/app/lib/design-filter.ts +4 -2
- package/corpus/templates/design/app/pages/Index.tsx +91 -59
- package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-element-drop.ts +58 -17
- package/corpus/templates/design/changelog/2026-10-01-filter-designs-by-owner.md +6 -0
- package/corpus/templates/design/changelog/2026-10-03-layers-dropped-into-visible-canvas-space-beyond-a-screen-now.md +6 -0
- package/corpus/templates/design/changelog/2026-10-03-visible-screen-overflow-no-longer-routes-drops-to-the-canvas.md +6 -0
- package/corpus/templates/design/changelog/2026-10-05-the-recent-tab-shows-loading-placeholders-until-your-designs.md +6 -0
- package/corpus/templates/design/package.json +1 -0
- package/corpus/templates/design/server/plugins/auth.ts +2 -1
- package/corpus/templates/design/server/plugins/otel.ts +6 -0
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/dispatch/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/dispatch/README.md +2 -2
- package/corpus/templates/dispatch/package.json +1 -0
- package/corpus/templates/dispatch/server/plugins/otel.ts +6 -0
- package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +2 -1
- package/corpus/templates/factory/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/factory/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/factory/package.json +1 -0
- package/corpus/templates/factory/server/plugins/otel.ts +6 -0
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/forms/README.md +2 -2
- package/corpus/templates/forms/package.json +1 -0
- package/corpus/templates/forms/server/plugins/auth.ts +2 -1
- package/corpus/templates/forms/server/plugins/otel.ts +6 -0
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/mail/CHANGELOG.md +6 -0
- package/corpus/templates/mail/README.md +2 -2
- package/corpus/templates/mail/package.json +1 -0
- package/corpus/templates/mail/server/plugins/auth.ts +2 -1
- package/corpus/templates/mail/server/plugins/otel.ts +6 -0
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/plan/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/plan/CHANGELOG.md +1 -0
- package/corpus/templates/plan/README.md +2 -2
- package/corpus/templates/plan/package.json +1 -0
- package/corpus/templates/plan/server/plugins/auth.ts +2 -1
- package/corpus/templates/plan/server/plugins/otel.ts +6 -0
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/slides/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/slides/CHANGELOG.md +23 -0
- package/corpus/templates/slides/README.md +2 -2
- package/corpus/templates/slides/actions/list-decks.ts +11 -4
- package/corpus/templates/slides/app/components/deck/DeckFilterMenu.tsx +44 -36
- package/corpus/templates/slides/app/components/home/SlidesHomeLibrary.tsx +79 -0
- package/corpus/templates/slides/app/components/layout/Header.tsx +2 -15
- package/corpus/templates/slides/app/components/ui/tabs.tsx +59 -0
- package/corpus/templates/slides/app/global.css +3 -54
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/lib/deck-filter.ts +5 -2
- package/corpus/templates/slides/app/pages/Index.tsx +102 -88
- package/corpus/templates/slides/changelog/2026-10-01-filter-decks-by-owner.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-02-hide-recent-until-decks-available.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-05-the-recent-tab-shows-loading-placeholders-until-your-decks-a.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/server/handlers/request-auth-context.ts +8 -0
- package/corpus/templates/slides/server/plugins/auth.ts +2 -1
- package/corpus/templates/slides/server/plugins/otel.ts +6 -0
- package/corpus/templates/tasks/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/tasks/.agents/skills/storing-data/SKILL.md +12 -7
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineAction, embedApp } from "@agent-native/core";
|
|
2
2
|
import { buildDeepLink } from "@agent-native/core/server";
|
|
3
|
-
import {
|
|
3
|
+
import { getRequestUserEmail } from "@agent-native/core/server/request-context";
|
|
4
|
+
import { and, eq, isNull, or, sql } from "drizzle-orm";
|
|
4
5
|
import { z } from "zod";
|
|
5
6
|
|
|
6
7
|
import { getDb, schema } from "../server/db/index.js";
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
isAgentRecordingCaller,
|
|
10
11
|
} from "../server/lib/agent-recording-access.js";
|
|
11
12
|
import { listingThumbnailUrl } from "../server/lib/player-thumbnail-url.js";
|
|
13
|
+
import { ownerEmailMatches } from "../server/lib/recordings.js";
|
|
12
14
|
import { buildCaseInsensitiveSearchPattern } from "./search-recordings-utils.js";
|
|
13
15
|
|
|
14
16
|
const SNIPPET_RADIUS = 80;
|
|
@@ -96,7 +98,7 @@ function transcriptMatch(
|
|
|
96
98
|
|
|
97
99
|
export default defineAction({
|
|
98
100
|
description:
|
|
99
|
-
"Search recordings by title, description, transcript text, or comments. Transcript and comment matches include timestamps for jumping to the matching moment. Public/unlisted recordings are searchable only when owned by or previously viewed by the current user.",
|
|
101
|
+
"Search recordings by title, description, transcript text, or comments, including recordings in the caller's Trash. Transcript and comment matches include timestamps for jumping to the matching moment. Public/unlisted recordings are searchable only when owned by or previously viewed by the current user.",
|
|
100
102
|
schema: z.object({
|
|
101
103
|
query: z.string().min(1).describe("Search text"),
|
|
102
104
|
limit: z.coerce.number().int().min(1).max(100).default(30),
|
|
@@ -119,6 +121,13 @@ export default defineAction({
|
|
|
119
121
|
agentOnly: isAgentRecordingCaller(ctx?.caller),
|
|
120
122
|
userEmail: ctx?.userEmail,
|
|
121
123
|
};
|
|
124
|
+
const userEmail = ctx?.userEmail ?? getRequestUserEmail();
|
|
125
|
+
const lifecycleFilter = userEmail
|
|
126
|
+
? or(
|
|
127
|
+
isNull(schema.recordings.trashedAt),
|
|
128
|
+
ownerEmailMatches(schema.recordings.ownerEmail, userEmail),
|
|
129
|
+
)
|
|
130
|
+
: isNull(schema.recordings.trashedAt);
|
|
122
131
|
|
|
123
132
|
const recMatches = await db
|
|
124
133
|
.select({
|
|
@@ -128,6 +137,7 @@ export default defineAction({
|
|
|
128
137
|
thumbnailUrl: schema.recordings.thumbnailUrl,
|
|
129
138
|
kind: schema.recordings.kind,
|
|
130
139
|
mediaUpdatedAt: schema.recordings.mediaUpdatedAt,
|
|
140
|
+
trashedAt: schema.recordings.trashedAt,
|
|
131
141
|
durationMs: schema.recordings.durationMs,
|
|
132
142
|
ownerEmail: schema.recordings.ownerEmail,
|
|
133
143
|
visibility: schema.recordings.visibility,
|
|
@@ -143,7 +153,7 @@ export default defineAction({
|
|
|
143
153
|
schema.recordingViewers,
|
|
144
154
|
recordingAccess,
|
|
145
155
|
),
|
|
146
|
-
|
|
156
|
+
lifecycleFilter,
|
|
147
157
|
sql`(lower(${schema.recordings.title}) LIKE ${pattern} ESCAPE '\\' OR lower(${schema.recordings.description}) LIKE ${pattern} ESCAPE '\\')`,
|
|
148
158
|
),
|
|
149
159
|
)
|
|
@@ -160,6 +170,7 @@ export default defineAction({
|
|
|
160
170
|
thumbnailUrl: schema.recordings.thumbnailUrl,
|
|
161
171
|
kind: schema.recordings.kind,
|
|
162
172
|
mediaUpdatedAt: schema.recordings.mediaUpdatedAt,
|
|
173
|
+
trashedAt: schema.recordings.trashedAt,
|
|
163
174
|
durationMs: schema.recordings.durationMs,
|
|
164
175
|
ownerEmail: schema.recordings.ownerEmail,
|
|
165
176
|
visibility: schema.recordings.visibility,
|
|
@@ -179,7 +190,7 @@ export default defineAction({
|
|
|
179
190
|
schema.recordingViewers,
|
|
180
191
|
recordingAccess,
|
|
181
192
|
),
|
|
182
|
-
|
|
193
|
+
lifecycleFilter,
|
|
183
194
|
sql`lower(${schema.recordingTranscripts.fullText}) LIKE ${pattern} ESCAPE '\\'`,
|
|
184
195
|
),
|
|
185
196
|
)
|
|
@@ -196,6 +207,7 @@ export default defineAction({
|
|
|
196
207
|
thumbnailUrl: schema.recordings.thumbnailUrl,
|
|
197
208
|
kind: schema.recordings.kind,
|
|
198
209
|
mediaUpdatedAt: schema.recordings.mediaUpdatedAt,
|
|
210
|
+
trashedAt: schema.recordings.trashedAt,
|
|
199
211
|
durationMs: schema.recordings.durationMs,
|
|
200
212
|
ownerEmail: schema.recordings.ownerEmail,
|
|
201
213
|
visibility: schema.recordings.visibility,
|
|
@@ -215,7 +227,7 @@ export default defineAction({
|
|
|
215
227
|
schema.recordingViewers,
|
|
216
228
|
recordingAccess,
|
|
217
229
|
),
|
|
218
|
-
|
|
230
|
+
lifecycleFilter,
|
|
219
231
|
sql`lower(${schema.recordingComments.content}) LIKE ${pattern} ESCAPE '\\'`,
|
|
220
232
|
),
|
|
221
233
|
)
|
|
@@ -230,6 +242,7 @@ export default defineAction({
|
|
|
230
242
|
title: r.title,
|
|
231
243
|
description: r.description,
|
|
232
244
|
thumbnailUrl: listingThumbnailUrl(r),
|
|
245
|
+
trashedAt: r.trashedAt,
|
|
233
246
|
durationMs: r.durationMs,
|
|
234
247
|
ownerEmail: r.ownerEmail,
|
|
235
248
|
visibility: r.visibility,
|
|
@@ -241,6 +254,7 @@ export default defineAction({
|
|
|
241
254
|
title: r.title,
|
|
242
255
|
description: r.description,
|
|
243
256
|
thumbnailUrl: listingThumbnailUrl(r),
|
|
257
|
+
trashedAt: r.trashedAt,
|
|
244
258
|
durationMs: r.durationMs,
|
|
245
259
|
ownerEmail: r.ownerEmail,
|
|
246
260
|
visibility: r.visibility,
|
|
@@ -167,6 +167,11 @@ function RecordingSearchResults({
|
|
|
167
167
|
{formatSearchSnippet(hit.snippet ?? hit.description)}
|
|
168
168
|
</span>
|
|
169
169
|
) : null}
|
|
170
|
+
{hit.trashedAt ? (
|
|
171
|
+
<span className="mt-1 block text-xs text-muted-foreground">
|
|
172
|
+
{t("navigation.trash")}
|
|
173
|
+
</span>
|
|
174
|
+
) : null}
|
|
170
175
|
</span>
|
|
171
176
|
{hit.matchPanel ? (
|
|
172
177
|
<span className="shrink-0 text-xs text-muted-foreground">
|
|
@@ -497,7 +497,9 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
|
|
|
497
497
|
to: "/trash",
|
|
498
498
|
label: t("navigation.trash"),
|
|
499
499
|
icon: IconTrash,
|
|
500
|
-
match: (p) =>
|
|
500
|
+
match: (p) =>
|
|
501
|
+
p.startsWith("/trash") ||
|
|
502
|
+
(p.startsWith("/r/") && recordingSection === "trash"),
|
|
501
503
|
},
|
|
502
504
|
];
|
|
503
505
|
|
|
@@ -254,6 +254,11 @@ export function SearchBar({ className, side = "right" }: SearchBarProps) {
|
|
|
254
254
|
<span className="uppercase tracking-wide">
|
|
255
255
|
{matchLabel(hit, t)}
|
|
256
256
|
</span>
|
|
257
|
+
{hit.trashedAt ? (
|
|
258
|
+
<span className="rounded-sm border border-border px-1 py-0.5 text-[9px] font-medium uppercase tracking-wide text-muted-foreground">
|
|
259
|
+
{t("navigation.trash")}
|
|
260
|
+
</span>
|
|
261
|
+
) : null}
|
|
257
262
|
{typeof hit.matchMs === "number" ? (
|
|
258
263
|
<>
|
|
259
264
|
<span aria-hidden="true">·</span>
|
|
@@ -480,19 +480,26 @@ export async function uploadLocalRecording(
|
|
|
480
480
|
|
|
481
481
|
/**
|
|
482
482
|
* Discard a local copy this tab owns. Any in-flight upload of it settles
|
|
483
|
-
* first, so its bookkeeping cannot race the delete, and
|
|
484
|
-
*
|
|
483
|
+
* first, so its bookkeeping cannot race the delete, and every server row the
|
|
484
|
+
* copy produced is trashed unless it is already ready.
|
|
485
485
|
*/
|
|
486
486
|
export async function discardLocalRecording(
|
|
487
487
|
localId: string,
|
|
488
488
|
options: { afterUpload?: Promise<unknown> | null } = {},
|
|
489
489
|
): Promise<void> {
|
|
490
490
|
await options.afterUpload;
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
491
|
+
const ids = new Set<string>();
|
|
492
|
+
try {
|
|
493
|
+
const meta = await getRecordingBackupMeta(localId);
|
|
494
|
+
if (meta?.serverRecordingId) ids.add(meta.serverRecordingId);
|
|
495
|
+
// The row created while recording; each retry uploads to a new id.
|
|
496
|
+
if (meta && !meta.localOnly) ids.add(meta.recordingId);
|
|
497
|
+
for (const id of meta?.staleServerRecordingIds ?? []) ids.add(id);
|
|
498
|
+
} catch {
|
|
499
|
+
// An unreadable copy is keyed by the id of the row its take created.
|
|
500
|
+
ids.add(localId);
|
|
495
501
|
}
|
|
502
|
+
await trashStaleServerRecordings([...ids]);
|
|
496
503
|
await deleteRecordingBackup(localId);
|
|
497
504
|
}
|
|
498
505
|
|
|
@@ -9,7 +9,7 @@ import { useSyncExternalStore } from "react";
|
|
|
9
9
|
* from the same facts — and says so here, so the highlighted section and the
|
|
10
10
|
* breadcrumb always agree.
|
|
11
11
|
*/
|
|
12
|
-
export type RecordingSection = "library" | "screenshots" | "spaces";
|
|
12
|
+
export type RecordingSection = "library" | "screenshots" | "spaces" | "trash";
|
|
13
13
|
|
|
14
14
|
let current: RecordingSection | null = null;
|
|
15
15
|
const listeners = new Set<() => void>();
|
|
@@ -1247,11 +1247,13 @@ export default function RecordingPage() {
|
|
|
1247
1247
|
// a folder keeps that real home instead.
|
|
1248
1248
|
const screenshotIsUnfiled = isImage && !recordingSpace && !recordingFolder;
|
|
1249
1249
|
// The sidebar highlights the same section the breadcrumb starts with.
|
|
1250
|
-
const recordingSection: RecordingSection =
|
|
1251
|
-
? "
|
|
1252
|
-
:
|
|
1253
|
-
? "
|
|
1254
|
-
:
|
|
1250
|
+
const recordingSection: RecordingSection = recording?.trashedAt
|
|
1251
|
+
? "trash"
|
|
1252
|
+
: recordingSpace
|
|
1253
|
+
? "spaces"
|
|
1254
|
+
: screenshotIsUnfiled
|
|
1255
|
+
? "screenshots"
|
|
1256
|
+
: "library";
|
|
1255
1257
|
useEffect(() => {
|
|
1256
1258
|
setRecordingSection(recordingSection);
|
|
1257
1259
|
return () => setRecordingSection(null);
|
|
@@ -2758,13 +2758,14 @@ export default function RecordRoute() {
|
|
|
2758
2758
|
// A copy left by another visit is taken only once this tab holds its lock;
|
|
2759
2759
|
// one that another tab owns is never uploaded or deleted from here.
|
|
2760
2760
|
const openRecoveredCopy = useCallback(
|
|
2761
|
-
async (recordingId: string) => {
|
|
2761
|
+
async (recordingId: string): Promise<boolean> => {
|
|
2762
2762
|
const status = await holdLocalCopy(recordingId);
|
|
2763
2763
|
if (status === "busy") {
|
|
2764
2764
|
toast.info(t("recordRoute.localRecordingOpenElsewhere"));
|
|
2765
|
-
return;
|
|
2765
|
+
return false;
|
|
2766
2766
|
}
|
|
2767
2767
|
enterPendingUploadRef.current(recordingId);
|
|
2768
|
+
return true;
|
|
2768
2769
|
},
|
|
2769
2770
|
[holdLocalCopy, t],
|
|
2770
2771
|
);
|
|
@@ -2778,8 +2779,11 @@ export default function RecordRoute() {
|
|
|
2778
2779
|
[location.search],
|
|
2779
2780
|
);
|
|
2780
2781
|
const sessionEmail = authSession?.email ?? null;
|
|
2782
|
+
// A discarded copy stays locked until deleted; reopening it reads as "busy".
|
|
2783
|
+
const resumedLocalRecordingIdRef = useRef<string | null>(null);
|
|
2781
2784
|
useEffect(() => {
|
|
2782
2785
|
if (!resumeLocalRecordingId || !sessionEmail) return;
|
|
2786
|
+
if (resumedLocalRecordingIdRef.current === resumeLocalRecordingId) return;
|
|
2783
2787
|
if (uiState !== "idle" || pendingLocalRef.current) return;
|
|
2784
2788
|
let cancelled = false;
|
|
2785
2789
|
void (async () => {
|
|
@@ -2805,7 +2809,9 @@ export default function RecordRoute() {
|
|
|
2805
2809
|
void navigate("/record", { replace: true });
|
|
2806
2810
|
return;
|
|
2807
2811
|
}
|
|
2808
|
-
await openRecoveredCopyRef.current(resumeLocalRecordingId)
|
|
2812
|
+
if (await openRecoveredCopyRef.current(resumeLocalRecordingId)) {
|
|
2813
|
+
resumedLocalRecordingIdRef.current = resumeLocalRecordingId;
|
|
2814
|
+
}
|
|
2809
2815
|
})();
|
|
2810
2816
|
return () => {
|
|
2811
2817
|
cancelled = true;
|
|
@@ -3370,9 +3376,13 @@ export default function RecordRoute() {
|
|
|
3370
3376
|
discardAutoPausedRef.current = false;
|
|
3371
3377
|
const intent = discardPrompt;
|
|
3372
3378
|
setDiscardPrompt(null);
|
|
3373
|
-
if (intent === "restart")
|
|
3374
|
-
|
|
3375
|
-
|
|
3379
|
+
if (intent === "restart") {
|
|
3380
|
+
void restart();
|
|
3381
|
+
} else {
|
|
3382
|
+
void doCancel();
|
|
3383
|
+
void navigate("/library");
|
|
3384
|
+
}
|
|
3385
|
+
}, [discardPrompt, doCancel, navigate, restart]);
|
|
3376
3386
|
|
|
3377
3387
|
// "Try again" after a failure never deletes a copy that may still exist:
|
|
3378
3388
|
// a stored copy goes to the finish-upload step, a memory-only one asks.
|
|
@@ -14,6 +14,7 @@ import { and, eq, isNull } from "drizzle-orm";
|
|
|
14
14
|
|
|
15
15
|
import type { MediaWorkerCallback } from "../../shared/media-worker-contract.js";
|
|
16
16
|
import { getDb, schema } from "../db/index.js";
|
|
17
|
+
import { isBuilderCdnHost } from "./builder-cdn.js";
|
|
17
18
|
import { enabledFlag } from "./env-flags.js";
|
|
18
19
|
import {
|
|
19
20
|
enqueueMediaWorkerJob,
|
|
@@ -24,7 +25,6 @@ import {
|
|
|
24
25
|
} from "./media-worker.js";
|
|
25
26
|
import { ownerEmailMatches } from "./recordings.js";
|
|
26
27
|
|
|
27
|
-
const BUILDER_CDN_HOST_RE = /^cdn(?:-qa)?\.builder\.io$/i;
|
|
28
28
|
const DEFAULT_TRIGGER_TIMEOUT_MS = 45_000;
|
|
29
29
|
const DEFAULT_MAX_SOURCE_BYTES = 512 * 1024 * 1024;
|
|
30
30
|
const MAX_TRIGGER_ATTEMPTS = 5;
|
|
@@ -294,7 +294,7 @@ export function extractBuilderMediaTarget(
|
|
|
294
294
|
): BuilderMediaTarget | null {
|
|
295
295
|
try {
|
|
296
296
|
const url = new URL(sourceUrl);
|
|
297
|
-
if (!
|
|
297
|
+
if (!isBuilderCdnHost(url.hostname)) return null;
|
|
298
298
|
if (url.searchParams.get("optimized") === "true") return null;
|
|
299
299
|
|
|
300
300
|
let objectPath: string | null = null;
|
|
@@ -8,7 +8,8 @@ export default createAuthPlugin({
|
|
|
8
8
|
mountGoogleOAuthRoutes: false,
|
|
9
9
|
marketing: {
|
|
10
10
|
appName: "Clips",
|
|
11
|
-
learnMoreUrl:
|
|
11
|
+
learnMoreUrl:
|
|
12
|
+
"https://agent-native.com/apps/clips?utm_source=app&utm_medium=product&utm_content=onboarding-learn-more",
|
|
12
13
|
tagline:
|
|
13
14
|
"Your AI agent transcribes, summarizes, and searches everything you record alongside you.",
|
|
14
15
|
features: [
|
|
@@ -9,6 +9,8 @@ export type TranscriptFailureCode =
|
|
|
9
9
|
| "NO_AUDIO_SAVED"
|
|
10
10
|
/** Cloud transcription was attempted and threw. */
|
|
11
11
|
| "CLOUD_FAILED"
|
|
12
|
+
/** A long recording was split and one of its parts could not be transcribed. */
|
|
13
|
+
| "CHUNK_FAILED"
|
|
12
14
|
/** No cloud provider is connected for this owner. */
|
|
13
15
|
| "CLOUD_UNCONFIGURED"
|
|
14
16
|
/** Anything not yet classified. Prose is preserved; never retried blindly. */
|
|
@@ -18,6 +20,7 @@ const RETRYABLE: ReadonlySet<TranscriptFailureCode> = new Set([
|
|
|
18
20
|
"TIMEOUT",
|
|
19
21
|
"EXTRACTION_FAILED",
|
|
20
22
|
"CLOUD_FAILED",
|
|
23
|
+
"CHUNK_FAILED",
|
|
21
24
|
]);
|
|
22
25
|
|
|
23
26
|
export function isRetryableTranscriptFailure(
|
|
@@ -42,6 +45,8 @@ export function transcriptFailureMessage(code: TranscriptFailureCode): string {
|
|
|
42
45
|
return "Transcription timed out before it finished. Retrying usually works.";
|
|
43
46
|
case "CLOUD_FAILED":
|
|
44
47
|
return "No transcript was captured locally, and cloud transcription could not finish. Retrying usually works; if it persists, check the recording's audio and the Builder connection.";
|
|
48
|
+
case "CHUNK_FAILED":
|
|
49
|
+
return "Part of this recording could not be transcribed, so no transcript was saved. Retrying usually works.";
|
|
45
50
|
case "CLOUD_UNCONFIGURED":
|
|
46
51
|
return "No transcript was captured locally, and no cloud transcription provider is connected. Use Builder.io in Settings to transcribe automatically.";
|
|
47
52
|
case "UNKNOWN":
|
|
@@ -42,11 +42,17 @@ summaries for the visible rows, plus row count and total row count, so agents
|
|
|
42
42
|
can tell whether the user is looking at the full collection or a constrained
|
|
43
43
|
slice and can refer to the same rows and cells the user can currently scan;
|
|
44
44
|
for calendar and timeline views this summary is limited to rows in the
|
|
45
|
-
current visible date window plus rows shown in the "No date" section.
|
|
45
|
+
current visible date window plus rows shown in the "No date" section. Each
|
|
46
|
+
cell summary carries display `text` (cut at 200 characters with
|
|
47
|
+
`textTruncated: true`) and carries `value` only when it differs from that
|
|
48
|
+
text; read the row with `get-content-database` for full values. The row cap
|
|
49
|
+
shrinks to keep the whole navigation state under 48 KB, and
|
|
50
|
+
`databaseVisibleItemLimit` reports the cap actually applied. When
|
|
46
51
|
footer calculations are active, navigation state also includes
|
|
47
52
|
`databaseCalculationResults` with the visible result text for each calculated
|
|
48
53
|
column. When table rows are selected, navigation state also includes
|
|
49
|
-
`databaseSelectedItemCount` and `databaseSelectedItems
|
|
54
|
+
`databaseSelectedItemCount` and `databaseSelectedItems` (under the same
|
|
55
|
+
row cap), and
|
|
50
56
|
`view-screen.databaseCurrentView` mirrors that selected row summary.
|
|
51
57
|
`view-screen` exposes the same slice as `databaseCurrentView` alongside the
|
|
52
58
|
full collection payload. Its row property summaries should mirror the active
|
|
@@ -290,9 +290,16 @@ export default defineEventHandler(async (event) => {
|
|
|
290
290
|
|
|
291
291
|
## Data Scoping
|
|
292
292
|
|
|
293
|
-
In production, the framework automatically restricts all agent SQL queries to the current user's data using temporary views
|
|
293
|
+
In production, the framework automatically restricts all agent SQL queries to the current user's data using temporary views, and checks every statement before it runs so it can only reach those views.
|
|
294
294
|
|
|
295
|
-
The `db-query` / `db-exec` tools (and the extension SQL bridge, which shares the same path)
|
|
295
|
+
The `db-query` / `db-exec` / `db-patch` tools (and the extension SQL bridge, which shares the same path) read each statement the way Postgres does and refuse anything that could reach data around the temp views:
|
|
296
|
+
|
|
297
|
+
- schema- or database-qualified names like `public.<table>`, which resolve to the base table;
|
|
298
|
+
- names that resolve to anything other than the current user's temp views, such as materialized views or tables the scoping does not cover;
|
|
299
|
+
- app-defined SQL or PL/pgSQL functions and operators, whose bodies read tables without the views;
|
|
300
|
+
- built-ins that run SQL text, change session settings, or reach outside the database (`query_to_xml`, `set_config`, `dblink`, most `pg_*` functions).
|
|
301
|
+
|
|
302
|
+
`db-query` runs in a read-only transaction, and an `INSERT` must list its columns when the table has access-control columns. Use bare table names and plain expressions; scoping is applied automatically. When the agent needs data the views do not expose, add an app action with its own access checks.
|
|
296
303
|
|
|
297
304
|
### Per-User Scoping (`owner_email`)
|
|
298
305
|
|
|
@@ -75,10 +75,11 @@ state their PostgreSQL types directly.
|
|
|
75
75
|
|
|
76
76
|
Member offboarding and email changes refuse to run while any column named
|
|
77
77
|
`email`, `*_email`, `*scope_id`, `created_by`, `updated_by`, `invited_by`,
|
|
78
|
-
`owner`, `principal_id`, `session_id`, or `user_id` has no policy.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
`owner`, `principal_id`, `session_id`, or `user_id` has no policy.
|
|
79
|
+
`createSharesTable()` tables are handled for you, and undeclared `owner_email`
|
|
80
|
+
columns transfer to the successor, which is right only for owned content.
|
|
81
|
+
Declare every other one, including columns that are not member identities, from
|
|
82
|
+
the app's database plugin graph (Clips does it in `server/db/index.ts`):
|
|
82
83
|
|
|
83
84
|
```ts
|
|
84
85
|
import { registerIdentityColumns } from "@agent-native/core/org";
|
|
@@ -88,13 +89,17 @@ registerIdentityColumns([
|
|
|
88
89
|
{ table: "space_members", column: "email", emailChange: "rekey", offboard: "delete", orgScope: { column: "space_id", references: { table: "spaces", column: "id", orgColumn: "org_id" } }, reason: "Space membership grants access." },
|
|
89
90
|
// Someone else's address: never rewritten.
|
|
90
91
|
{ table: "meeting_participants", column: "email", emailChange: "retain", offboard: "retain", reason: "Attendee address from the calendar provider." },
|
|
92
|
+
// A credential in an owner_email table: never handed to the successor.
|
|
93
|
+
{ table: "api_keys", column: "owner_email", emailChange: "rekey", offboard: "revoke", reason: "Bearer keys act as their owner." },
|
|
91
94
|
]);
|
|
92
95
|
```
|
|
93
96
|
|
|
94
|
-
Choose `delete` for grants, credentials, and pending tokens
|
|
97
|
+
Choose `delete` for grants, credentials, and pending tokens, or `revoke` (sets
|
|
98
|
+
`revoked_at`) when a reader treats a missing row as "not revoked"; `retain` for
|
|
95
99
|
attribution, history, and third-party addresses; `transfer` only for owned
|
|
96
|
-
data.
|
|
97
|
-
|
|
100
|
+
data. Declare `owner_email` tables that hold credentials or grants, or
|
|
101
|
+
offboarding hands them to the successor. A table without `org_id` needs
|
|
102
|
+
`orgScope` or an organization-scoped removal leaves its rows alone.
|
|
98
103
|
|
|
99
104
|
| Template | Tables |
|
|
100
105
|
| ------------ | --------------------------------------------- |
|
|
@@ -3,10 +3,51 @@
|
|
|
3
3
|
All notable user-facing changes to Agent-Native Content are documented here. Open it any
|
|
4
4
|
time from the command menu (Cmd+K → "What's new").
|
|
5
5
|
|
|
6
|
+
## 2026-10-05
|
|
7
|
+
|
|
8
|
+
### Improved
|
|
9
|
+
|
|
10
|
+
- Collection pages keep selected rows visible through failed refreshes, and review space stays in place while comments refresh.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Collection view context now survives quick page changes when the saved summary fits.
|
|
15
|
+
- Exact saved-view links keep the collection retry available when rows fail to load
|
|
16
|
+
- Expanding a Files folder now shares one navigation read across open branches, and legacy owner shares retain their row controls.
|
|
17
|
+
- Files navigation retries temporary failures consistently
|
|
18
|
+
- Shared page owners keep edit and manage controls in Files, and newly opened folders populate faster.
|
|
19
|
+
- Tagging an AI in a comment works again instead of failing right away with "AI request failed".
|
|
20
|
+
- The home loading shell keeps the layout of your last opened page.
|
|
21
|
+
- Typing `>` and a space, or inserting a toggle or callout, no longer freezes and crashes the page on a Mac.
|
|
22
|
+
|
|
23
|
+
## 2026-10-03
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- A malformed Lab preference no longer blocks unrelated editor commands.
|
|
28
|
+
|
|
29
|
+
## 2026-10-02
|
|
30
|
+
|
|
31
|
+
### Improved
|
|
32
|
+
|
|
33
|
+
- After a refresh, the Files sidebar shows the open page's folders in one load instead of one level at a time
|
|
34
|
+
- Builder.io setup instructions now use consistent action language across editor workflows.
|
|
35
|
+
- Large collections open faster
|
|
36
|
+
- Pages with open comments and collections with sorted or filtered views no longer jump while they load
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- A page link you can't open now says so, with the account you're signed in as, instead of opening another page. People who can open a private share link no longer see "This document is private" first.
|
|
41
|
+
- Comment edits and deletions now refresh collaborators with the document open.
|
|
42
|
+
- Pages stay inside the window at every width: long inline code and links wrap, and wide tables scroll inside their own frame instead of crushing their columns
|
|
43
|
+
- Suggest edits works on pages written by agents, including pages with Markdown tables, instead of refusing to start or rejecting each edit; suggestions inside a table cell are still not supported
|
|
44
|
+
- While you suggest edits, tables and other blocks that suggestions don't support yet are read-only, and an agent that tries to suggest a change inside one gets a clear message instead of "Internal server error".
|
|
45
|
+
|
|
6
46
|
## 2026-10-01
|
|
7
47
|
|
|
8
48
|
### Improved
|
|
9
49
|
|
|
50
|
+
- Home opens the page you were last on sooner
|
|
10
51
|
- Pages and the sidebar load in place instead of jumping around
|
|
11
52
|
|
|
12
53
|
### Fixed
|
|
@@ -4,7 +4,7 @@ Open-source Obsidian for MDX — an agent-native, local-file document workspace
|
|
|
4
4
|
a self-hostable alternative to Notion and Obsidian. Edit local Markdown/MDX files,
|
|
5
5
|
build Notion-style collections, and write with an AI agent.
|
|
6
6
|
|
|
7
|
-
**Live app: [content.agent-native.com](https://content.agent-native.com)**
|
|
7
|
+
**Live app: [content.agent-native.com](https://content.agent-native.com?utm_source=github&utm_medium=referral&utm_content=content-readme)**
|
|
8
8
|
|
|
9
9
|
Open a doc and ask "rewrite this paragraph to be more concise" or "create a page
|
|
10
10
|
called Q4 Planning with sub-pages for Goals, Metrics, and Risks" — the same result
|
|
@@ -31,4 +31,4 @@ pnpm install
|
|
|
31
31
|
pnpm dev
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
Full docs: [agent-native.com/docs/template-content](https://agent-native.com/docs/template-content).
|
|
34
|
+
Full docs: [agent-native.com/docs/template-content](https://agent-native.com/docs/template-content?utm_source=github&utm_medium=referral&utm_content=content-readme).
|