@agent-native/core 0.68.3 → 0.70.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 +2 -2
- package/corpus/core/CHANGELOG.md +54 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/changelog/parse.ts +245 -0
- package/corpus/core/src/cli/changelog.ts +199 -0
- package/corpus/core/src/cli/index.ts +19 -0
- package/corpus/core/src/cli/recap.ts +24 -1
- package/corpus/core/src/cli/skills.ts +72 -45
- package/corpus/core/src/client/CommandMenu.tsx +183 -75
- package/corpus/core/src/client/agent-chat-adapter.ts +44 -7
- package/corpus/core/src/client/analytics.ts +181 -0
- package/corpus/core/src/client/changelog/Changelog.tsx +321 -0
- package/corpus/core/src/client/index.ts +11 -0
- package/corpus/core/src/client/mcp-apps/McpAppRenderer.tsx +54 -0
- package/corpus/core/src/client/settings/useBuilderStatus.ts +82 -20
- package/corpus/core/src/extensions/web-search-tool.ts +45 -4
- package/corpus/core/src/mcp/build-server.ts +1 -1
- package/corpus/core/src/mcp/embed-app.ts +112 -6
- package/corpus/core/src/secrets/register-framework-secrets.ts +7 -0
- package/corpus/core/src/server/attribution.ts +211 -0
- package/corpus/core/src/server/auth.ts +6 -0
- package/corpus/core/src/server/better-auth-instance.ts +49 -5
- package/corpus/core/src/server/builder-browser.ts +27 -1
- package/corpus/core/src/server/core-routes-plugin.ts +58 -0
- package/corpus/core/src/server/google-oauth.ts +19 -6
- package/corpus/core/src/shared/mcp-embed-headers.ts +1 -1
- package/corpus/core/src/styles/agent-conversation.css +21 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
- package/corpus/templates/analytics/CHANGELOG.md +10 -0
- package/corpus/templates/analytics/actions/install-dashboard-template.ts +2 -2
- package/corpus/templates/analytics/actions/open-traffic-dashboard.ts +1 -1
- package/corpus/templates/analytics/actions/update-dashboard.ts +5 -3
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +180 -144
- package/corpus/templates/analytics/app/components/layout/Header.tsx +2 -2
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -5
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +221 -213
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +6 -3
- package/corpus/templates/analytics/app/lib/demo-dashboard-path.ts +1 -1
- package/corpus/templates/analytics/app/lib/last-opened.ts +2 -1
- package/corpus/templates/analytics/app/pages/Settings.tsx +4 -0
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +2 -2
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +101 -99
- package/corpus/templates/analytics/app/pages/overview/OverviewPage.tsx +1 -1
- package/corpus/templates/analytics/app/routes/adhoc.$id.tsx +18 -5
- package/corpus/templates/analytics/app/routes/catalog.tsx +1 -1
- package/corpus/templates/analytics/app/routes/dashboards.$id.tsx +9 -0
- package/corpus/templates/analytics/app/routes/traffic.tsx +1 -1
- package/corpus/templates/analytics/changelog/2026-06-23-the-dashboards-and-analyses-sidebar-settings-buttons-now-sta.md +6 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +145 -0
- package/corpus/templates/analytics/server/db/index.ts +1 -1
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +9 -2
- package/corpus/templates/analytics/server/lib/demo-dashboards.ts +1 -1
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +2 -2
- package/corpus/templates/analytics/server/plugins/core-routes.ts +6 -6
- package/corpus/templates/assets/CHANGELOG.md +10 -0
- package/corpus/templates/assets/app/root.tsx +7 -1
- package/corpus/templates/assets/app/routes/settings.tsx +6 -0
- package/corpus/templates/brain/CHANGELOG.md +10 -0
- package/corpus/templates/brain/app/root.tsx +7 -1
- package/corpus/templates/brain/app/routes/settings.tsx +8 -1
- package/corpus/templates/calendar/CHANGELOG.md +10 -0
- package/corpus/templates/calendar/app/pages/Settings.tsx +4 -0
- package/corpus/templates/calendar/app/root.tsx +7 -1
- package/corpus/templates/chat/CHANGELOG.md +10 -0
- package/corpus/templates/chat/app/root.tsx +7 -1
- package/corpus/templates/clips/CHANGELOG.md +10 -0
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +33 -7
- package/corpus/templates/clips/app/components/player/sign-in-prompt-dialog.tsx +8 -0
- package/corpus/templates/clips/app/components/player/video-player.tsx +150 -20
- package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +72 -20
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +69 -2
- package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +71 -0
- package/corpus/templates/clips/app/lib/recorder-preferences.ts +67 -0
- package/corpus/templates/clips/app/root.tsx +7 -1
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +15 -1
- package/corpus/templates/clips/app/routes/_app.trash.tsx +21 -0
- package/corpus/templates/clips/app/routes/record.tsx +92 -8
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +86 -5
- package/corpus/templates/clips/changelog/2026-06-23-clips-shared-in-slack-no-longer-show-a-could-not-start-playb.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-made-the-play-button-on-shared-and-embedded-clips-scale-with.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-public-clip-share-links-now-show-whether-they-ll-play-inline.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-screen-camera-recordings-now-keep-the-presenter-s-face-in-th.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +20 -0
- package/corpus/templates/clips/desktop/src/main.tsx +3 -0
- package/corpus/templates/clips/desktop/src/overlays/region-record-border.tsx +76 -0
- package/corpus/templates/clips/desktop/src/styles.css +49 -0
- package/corpus/templates/clips/desktop/src-tauri/capabilities/default.json +2 -1
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +67 -1
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -0
- package/corpus/templates/clips/desktop/src-tauri/src/util.rs +4 -1
- package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +51 -1
- package/corpus/templates/clips/shared/share-attribution.ts +79 -0
- package/corpus/templates/content/CHANGELOG.md +10 -0
- package/corpus/templates/content/app/root.tsx +7 -1
- package/corpus/templates/content/vitest.config.ts +3 -0
- package/corpus/templates/design/CHANGELOG.md +10 -0
- package/corpus/templates/design/actions/generate-design.ts +4 -0
- package/corpus/templates/design/app/root.tsx +7 -1
- package/corpus/templates/design/app/routes/settings.tsx +10 -2
- package/corpus/templates/dispatch/CHANGELOG.md +10 -0
- package/corpus/templates/dispatch/app/root.tsx +7 -1
- package/corpus/templates/forms/CHANGELOG.md +10 -0
- package/corpus/templates/forms/app/root.tsx +7 -1
- package/corpus/templates/macros/CHANGELOG.md +10 -0
- package/corpus/templates/macros/app/root.tsx +7 -1
- package/corpus/templates/mail/CHANGELOG.md +10 -0
- package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +3 -0
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +27 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +31 -17
- package/corpus/templates/plan/.agents/skills/visual-plan/references/wireframe.md +7 -4
- package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +34 -24
- package/corpus/templates/plan/.agents/skills/visual-recap/references/wireframe.md +7 -4
- package/corpus/templates/plan/AGENTS.md +4 -0
- package/corpus/templates/plan/CHANGELOG.md +10 -0
- package/corpus/templates/plan/actions/view-screen.ts +5 -0
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +98 -1
- package/corpus/templates/plan/app/pages/PlansPage.tsx +107 -7
- package/corpus/templates/plan/app/root.tsx +7 -1
- package/corpus/templates/plan/shared/share-attribution.ts +72 -0
- package/corpus/templates/slides/CHANGELOG.md +10 -0
- package/corpus/templates/slides/app/root.tsx +7 -1
- package/corpus/templates/videos/CHANGELOG.md +4 -151
- package/corpus/templates/videos/app/root.tsx +7 -1
- package/dist/changelog/parse.d.ts +70 -0
- package/dist/changelog/parse.d.ts.map +1 -0
- package/dist/changelog/parse.js +200 -0
- package/dist/changelog/parse.js.map +1 -0
- package/dist/cli/changelog.d.ts +4 -0
- package/dist/cli/changelog.d.ts.map +1 -0
- package/dist/cli/changelog.js +166 -0
- package/dist/cli/changelog.js.map +1 -0
- package/dist/cli/index.js +18 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +22 -1
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +3 -3
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +72 -45
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/CommandMenu.d.ts +17 -1
- package/dist/client/CommandMenu.d.ts.map +1 -1
- package/dist/client/CommandMenu.js +49 -13
- package/dist/client/CommandMenu.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +43 -6
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/analytics.d.ts +18 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +177 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/changelog/Changelog.d.ts +47 -0
- package/dist/client/changelog/Changelog.d.ts.map +1 -0
- package/dist/client/changelog/Changelog.js +138 -0
- package/dist/client/changelog/Changelog.js.map +1 -0
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/mcp-apps/McpAppRenderer.d.ts +1 -0
- package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/client/mcp-apps/McpAppRenderer.js +42 -1
- package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +2 -0
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +58 -10
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/extensions/web-search-tool.d.ts +5 -3
- package/dist/extensions/web-search-tool.d.ts.map +1 -1
- package/dist/extensions/web-search-tool.js +36 -4
- package/dist/extensions/web-search-tool.js.map +1 -1
- package/dist/mcp/build-server.js +1 -1
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/embed-app.d.ts.map +1 -1
- package/dist/mcp/embed-app.js +112 -6
- package/dist/mcp/embed-app.js.map +1 -1
- package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
- package/dist/secrets/register-framework-secrets.js +6 -0
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/server/attribution.d.ts +83 -0
- package/dist/server/attribution.d.ts.map +1 -0
- package/dist/server/attribution.js +178 -0
- package/dist/server/attribution.js.map +1 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +7 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts +9 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +32 -2
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/builder-browser.d.ts +4 -0
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +20 -1
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +25 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +38 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +16 -2
- package/dist/server/google-oauth.js.map +1 -1
- package/dist/shared/mcp-embed-headers.js +1 -1
- package/dist/shared/mcp-embed-headers.js.map +1 -1
- package/dist/styles/agent-conversation.css +21 -0
- package/dist/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
- package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
- package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
- /package/corpus/templates/analytics/app/routes/{dashboards.tsx → dashboards._index.tsx} +0 -0
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.70.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b35c8cb: Add an in-app changelog ("What's new") surface. Every app can now ship a
|
|
8
|
+
user-facing `CHANGELOG.md` that renders in the command menu (Cmd+K) and in
|
|
9
|
+
settings. Core provides `<ChangelogDialog>`, `<ChangelogSettingsCard>`, a
|
|
10
|
+
`changelog` prop on `CommandMenu` (with an unseen-release dot), and an
|
|
11
|
+
`agent-native changelog add|release|list` CLI that authors changeset-style
|
|
12
|
+
pending entry files and rolls them up into the dated `CHANGELOG.md`.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- b35c8cb: Fix MCP app embeds for OpenAI's default web-sandbox origin and keep an Open in new tab fallback available when inline app loading fails.
|
|
17
|
+
- b35c8cb: Return native redirect responses from web OAuth callbacks so successful sign-ins
|
|
18
|
+
land on the clean return URL instead of retaining provider callback query
|
|
19
|
+
parameters.
|
|
20
|
+
- b35c8cb: Add a public `GET /_agent-native/health` route that runs a trivial `SELECT 1`
|
|
21
|
+
to report database liveness and, as a side effect, keep a scale-to-zero
|
|
22
|
+
serverless database (e.g. Neon) warm. A scheduled ping against this endpoint
|
|
23
|
+
prevents the multi-second cold-start that otherwise stalls the first request
|
|
24
|
+
to an idle app. The probe always responds (apps with no database report
|
|
25
|
+
`db: false` rather than failing) and is never cached. Disable it with the
|
|
26
|
+
`disableHealth` core-routes option.
|
|
27
|
+
- b35c8cb: Fix MCP app embeds rendering only a flashing/permanent loading state in Codex
|
|
28
|
+
and Cursor. These standards-track hosts render the `ui://` resource in a strict
|
|
29
|
+
opaque-origin sandbox (`sandbox="allow-scripts"`) and talk to it over the
|
|
30
|
+
postMessage `ui/*` bridge. The shell's handshake was already correct, but for
|
|
31
|
+
these hosts it fell through to self-navigating the sandboxed iframe to the real
|
|
32
|
+
app origin, which tears down the host bridge and loses the opaque-origin auth
|
|
33
|
+
context. Any host connected through the native MCP Apps bridge (Codex, Cursor,
|
|
34
|
+
the SDK App fallback, our own renderer) now transplants the app document into
|
|
35
|
+
the shell — the same robust path Claude already uses — keeping the bridge alive
|
|
36
|
+
and loading via embed-token auth. Also handle the spec `host-context-changed`
|
|
37
|
+
notification and bump the cached resource shell version so hosts refetch.
|
|
38
|
+
- b35c8cb: Fix the missing inline screenshot on PR Visual Recap comments. The `recap shot`
|
|
39
|
+
command runs `page.evaluate`/`addInitScript` payloads that contain named inner
|
|
40
|
+
functions; when the CLI is run through `tsx`/esbuild (CI's trusted-workspace
|
|
41
|
+
path), esbuild's `keepNames` wraps those functions in `__name(...)`, which
|
|
42
|
+
Playwright then serializes into the browser where `__name` is undefined —
|
|
43
|
+
throwing `ReferenceError: __name is not defined`, dropping the screenshot, and
|
|
44
|
+
falling back to a link-only comment. `runShot` now injects an identity `__name`
|
|
45
|
+
shim as the first browser init script, so every main-world payload is safe
|
|
46
|
+
regardless of how the CLI was transpiled (the tsc-built published package, which
|
|
47
|
+
never emits `__name`, is unaffected).
|
|
48
|
+
- b35c8cb: When a long agent run is cut off mid-stream while assembling one large tool input (a generation that exceeds the ~40s soft-timeout window), the auto-continue nudge now points the resumed model at the incremental-edit path for that specific action instead of only handling `create-extension`. Designs (`generate-design` → `edit-design`), plans (`create-visual-plan`/`create-ui-plan` → `update-visual-plan`/`patch-visual-plan-source`), and dashboards (`update-dashboard` incremental `ops`) get tailored "ship a compact first version, then refine" guidance, with a generic compact-first fallback for any other large-payload action. This breaks the re-stream-the-same-oversized-payload thrash loop that could otherwise burn the whole continuation budget without making progress.
|
|
49
|
+
- b35c8cb: Capture first-touch referral attribution and enrich the signup event (`referral_source`, `referrer_user`, UTM, `first_touch_path`) to measure app virality. The browser records an anonymous visitor's first-touch context (`ref`/`via`/`utm_*` params, landing path, and referring host) into an `an_attribution` localStorage key and a first-party `an_ft` cookie, and the server-side `signup` event is enriched from that cookie so every template can see where new users came from.
|
|
50
|
+
|
|
51
|
+
## 0.69.0
|
|
52
|
+
|
|
53
|
+
### Minor Changes
|
|
54
|
+
|
|
55
|
+
- 530de18: Add Firecrawl as a BYOK backend for the web-search agent tool. When `FIRECRAWL_API_KEY` is configured (via app secrets or environment) the tool routes searches through Firecrawl's `/v2/search` API. It slots into the existing first-configured-wins chain after Brave, Tavily, and Exa, and before Builder-managed search, and is registered as an optional framework secret so it surfaces in every template's settings UI.
|
|
56
|
+
|
|
3
57
|
## 0.68.3
|
|
4
58
|
|
|
5
59
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared, dependency-free changelog parsing + serialization.
|
|
3
|
+
*
|
|
4
|
+
* Used by BOTH:
|
|
5
|
+
* - the browser bundle (rendering an app's CHANGELOG.md in the command
|
|
6
|
+
* menu / settings "What's new" surface), and
|
|
7
|
+
* - the `agent-native changelog` CLI (rolling pending entry files up into
|
|
8
|
+
* CHANGELOG.md).
|
|
9
|
+
*
|
|
10
|
+
* Keep this file isomorphic: no Node, no browser, no third-party deps. The
|
|
11
|
+
* markdown shape is the conventional "Keep a Changelog" layout — a top-level
|
|
12
|
+
* `# Changelog` heading followed by one `## <release>` section per release.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** A single released section of a CHANGELOG.md file. */
|
|
16
|
+
export interface ChangelogEntry {
|
|
17
|
+
/** Stable id derived from the heading — used for "unseen" tracking. */
|
|
18
|
+
id: string;
|
|
19
|
+
/** Raw heading text, e.g. `2026-06-23` or `v1.2.0 — 2026-06-23`. */
|
|
20
|
+
title: string;
|
|
21
|
+
/** ISO date (YYYY-MM-DD) extracted from the heading, if present. */
|
|
22
|
+
date?: string;
|
|
23
|
+
/** Version label extracted from the heading, if present. */
|
|
24
|
+
version?: string;
|
|
25
|
+
/** Markdown body beneath the heading (until the next `## ` section). */
|
|
26
|
+
body: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A not-yet-released entry authored as a `changelog/<file>.md` file. */
|
|
30
|
+
export interface PendingChangelogEntry {
|
|
31
|
+
/** Category — `added`, `improved`, `fixed`, `changed`, etc. */
|
|
32
|
+
type: ChangelogChangeType;
|
|
33
|
+
/** ISO date the entry was authored (YYYY-MM-DD). */
|
|
34
|
+
date?: string;
|
|
35
|
+
/** User-facing description (markdown, single bullet). */
|
|
36
|
+
text: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type ChangelogChangeType =
|
|
40
|
+
| "added"
|
|
41
|
+
| "improved"
|
|
42
|
+
| "fixed"
|
|
43
|
+
| "changed"
|
|
44
|
+
| "removed"
|
|
45
|
+
| "security";
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Order changes are grouped under a release heading. Anything not listed here
|
|
49
|
+
* falls back to the "changed" group, then renders in insertion order.
|
|
50
|
+
*/
|
|
51
|
+
export const CHANGELOG_GROUP_ORDER: ChangelogChangeType[] = [
|
|
52
|
+
"added",
|
|
53
|
+
"improved",
|
|
54
|
+
"fixed",
|
|
55
|
+
"changed",
|
|
56
|
+
"removed",
|
|
57
|
+
"security",
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const GROUP_LABELS: Record<ChangelogChangeType, string> = {
|
|
61
|
+
added: "Added",
|
|
62
|
+
improved: "Improved",
|
|
63
|
+
fixed: "Fixed",
|
|
64
|
+
changed: "Changed",
|
|
65
|
+
removed: "Removed",
|
|
66
|
+
security: "Security",
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const ISO_DATE = /(\d{4}-\d{2}-\d{2})/;
|
|
70
|
+
|
|
71
|
+
/** Lowercase, hyphenate, and strip to a URL/id-safe slug. */
|
|
72
|
+
export function changelogSlug(value: string): string {
|
|
73
|
+
return value
|
|
74
|
+
.toLowerCase()
|
|
75
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
76
|
+
.replace(/^-+|-+$/g, "")
|
|
77
|
+
.slice(0, 60);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function normalizeType(raw: string | undefined): ChangelogChangeType {
|
|
81
|
+
const value = (raw ?? "").trim().toLowerCase();
|
|
82
|
+
if ((CHANGELOG_GROUP_ORDER as string[]).includes(value)) {
|
|
83
|
+
return value as ChangelogChangeType;
|
|
84
|
+
}
|
|
85
|
+
// Friendly aliases.
|
|
86
|
+
if (value === "feature" || value === "new" || value === "add") return "added";
|
|
87
|
+
if (value === "improvement" || value === "enhancement" || value === "perf") {
|
|
88
|
+
return "improved";
|
|
89
|
+
}
|
|
90
|
+
if (value === "fix" || value === "bugfix" || value === "bug") return "fixed";
|
|
91
|
+
if (value === "remove" || value === "deprecated") return "removed";
|
|
92
|
+
return "changed";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Parse a CHANGELOG.md document into structured release entries.
|
|
97
|
+
*
|
|
98
|
+
* Tolerant by design: an empty or malformed file yields an empty list rather
|
|
99
|
+
* than throwing, so a missing/partial changelog never breaks the UI.
|
|
100
|
+
*/
|
|
101
|
+
export function parseChangelog(markdown: string): ChangelogEntry[] {
|
|
102
|
+
if (!markdown || typeof markdown !== "string") return [];
|
|
103
|
+
|
|
104
|
+
const lines = markdown.split(/\r?\n/);
|
|
105
|
+
const entries: ChangelogEntry[] = [];
|
|
106
|
+
const seenIds = new Set<string>();
|
|
107
|
+
|
|
108
|
+
let currentTitle: string | null = null;
|
|
109
|
+
let bodyLines: string[] = [];
|
|
110
|
+
|
|
111
|
+
const flush = () => {
|
|
112
|
+
if (currentTitle === null) return;
|
|
113
|
+
const title = currentTitle.trim();
|
|
114
|
+
const date = title.match(ISO_DATE)?.[1];
|
|
115
|
+
const version = title.match(/v?\d+\.\d+(?:\.\d+)?/)?.[0];
|
|
116
|
+
// Build a stable, unique id from the heading.
|
|
117
|
+
let base = changelogSlug(title) || "entry";
|
|
118
|
+
let id = base;
|
|
119
|
+
let n = 2;
|
|
120
|
+
while (seenIds.has(id)) id = `${base}-${n++}`;
|
|
121
|
+
seenIds.add(id);
|
|
122
|
+
entries.push({
|
|
123
|
+
id,
|
|
124
|
+
title,
|
|
125
|
+
date,
|
|
126
|
+
version: version && version !== date ? version : undefined,
|
|
127
|
+
body: bodyLines.join("\n").trim(),
|
|
128
|
+
});
|
|
129
|
+
currentTitle = null;
|
|
130
|
+
bodyLines = [];
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
for (const line of lines) {
|
|
134
|
+
// `## ` (but not `### `) starts a new release section.
|
|
135
|
+
const match = /^##\s+(?!#)(.+?)\s*$/.exec(line);
|
|
136
|
+
if (match) {
|
|
137
|
+
flush();
|
|
138
|
+
currentTitle = stripBrackets(match[1]);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
// Skip the top-level `# Changelog` title and anything before the first `##`.
|
|
142
|
+
if (currentTitle === null) continue;
|
|
143
|
+
bodyLines.push(line);
|
|
144
|
+
}
|
|
145
|
+
flush();
|
|
146
|
+
|
|
147
|
+
return entries;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** `## [1.2.0]` → `1.2.0`; leaves un-bracketed headings untouched. */
|
|
151
|
+
function stripBrackets(title: string): string {
|
|
152
|
+
return title.replace(/^\[(.+?)\]\s*/, "$1 ").trim();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Parse a pending `changelog/<file>.md` entry: optional `---` frontmatter
|
|
157
|
+
* (`type:` / `date:`) followed by the markdown description body.
|
|
158
|
+
*/
|
|
159
|
+
export function parsePendingEntry(content: string): PendingChangelogEntry {
|
|
160
|
+
let type: string | undefined;
|
|
161
|
+
let date: string | undefined;
|
|
162
|
+
let body = content;
|
|
163
|
+
|
|
164
|
+
const fm = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(content);
|
|
165
|
+
if (fm) {
|
|
166
|
+
for (const raw of fm[1].split(/\r?\n/)) {
|
|
167
|
+
const kv = /^([a-zA-Z]+)\s*:\s*(.+?)\s*$/.exec(raw);
|
|
168
|
+
if (!kv) continue;
|
|
169
|
+
const key = kv[1].toLowerCase();
|
|
170
|
+
const value = kv[2].replace(/^["']|["']$/g, "").trim();
|
|
171
|
+
if (key === "type") type = value;
|
|
172
|
+
else if (key === "date") date = value.match(ISO_DATE)?.[1] ?? value;
|
|
173
|
+
}
|
|
174
|
+
body = content.slice(fm[0].length);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
type: normalizeType(type),
|
|
179
|
+
date,
|
|
180
|
+
text: body.trim(),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Render a set of pending entries as a single dated release section (the body
|
|
186
|
+
* that goes beneath a `## <date>` heading). Groups bullets by type.
|
|
187
|
+
*/
|
|
188
|
+
export function renderReleaseBody(entries: PendingChangelogEntry[]): string {
|
|
189
|
+
const groups = new Map<ChangelogChangeType, string[]>();
|
|
190
|
+
for (const entry of entries) {
|
|
191
|
+
const text = entry.text.trim();
|
|
192
|
+
if (!text) continue;
|
|
193
|
+
const bullet = text.includes("\n")
|
|
194
|
+
? // Preserve multi-line bodies, indenting continuation lines.
|
|
195
|
+
text
|
|
196
|
+
.split(/\r?\n/)
|
|
197
|
+
.map((l, i) => (i === 0 ? `- ${l}` : ` ${l}`))
|
|
198
|
+
.join("\n")
|
|
199
|
+
: `- ${text}`;
|
|
200
|
+
const list = groups.get(entry.type) ?? [];
|
|
201
|
+
list.push(bullet);
|
|
202
|
+
groups.set(entry.type, list);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const sections: string[] = [];
|
|
206
|
+
for (const type of CHANGELOG_GROUP_ORDER) {
|
|
207
|
+
const list = groups.get(type);
|
|
208
|
+
if (!list?.length) continue;
|
|
209
|
+
sections.push(`### ${GROUP_LABELS[type]}\n\n${list.join("\n")}`);
|
|
210
|
+
}
|
|
211
|
+
return sections.join("\n\n");
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const CHANGELOG_HEADER =
|
|
215
|
+
"# Changelog\n\n" +
|
|
216
|
+
"All notable user-facing changes to this app are documented here.\n";
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Roll a batch of pending entries into an existing CHANGELOG.md document,
|
|
220
|
+
* prepending a new `## <date>` section above the most recent release. Returns
|
|
221
|
+
* the full updated document. Pure — the CLI handles file IO and deletion.
|
|
222
|
+
*/
|
|
223
|
+
export function rollupChangelog(
|
|
224
|
+
existing: string,
|
|
225
|
+
pending: PendingChangelogEntry[],
|
|
226
|
+
releaseDate: string,
|
|
227
|
+
): string {
|
|
228
|
+
const body = renderReleaseBody(pending);
|
|
229
|
+
if (!body) return existing || `${CHANGELOG_HEADER}`;
|
|
230
|
+
|
|
231
|
+
const section = `## ${releaseDate}\n\n${body}\n`;
|
|
232
|
+
|
|
233
|
+
const doc = (existing || CHANGELOG_HEADER).replace(/\s+$/, "");
|
|
234
|
+
// Insert the new section immediately before the first existing `## ` release
|
|
235
|
+
// so the header/intro stays on top and releases stay newest-first.
|
|
236
|
+
const firstRelease = doc.search(/^##\s+(?!#)/m);
|
|
237
|
+
if (firstRelease === -1) {
|
|
238
|
+
return `${doc}\n\n${section}\n`;
|
|
239
|
+
}
|
|
240
|
+
const head = doc.slice(0, firstRelease).replace(/\s+$/, "");
|
|
241
|
+
const rest = doc.slice(firstRelease);
|
|
242
|
+
return `${head}\n\n${section}\n${rest}\n`;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export { CHANGELOG_HEADER, GROUP_LABELS };
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agent-native changelog` — author and roll up an app's user-facing changelog.
|
|
3
|
+
*
|
|
4
|
+
* The model mirrors changesets: instead of editing the shared CHANGELOG.md
|
|
5
|
+
* directly (which conflicts when many agents work in parallel), each change
|
|
6
|
+
* drops a small pending entry file under `changelog/`. A later `release` rolls
|
|
7
|
+
* every pending file up into a single dated section of CHANGELOG.md.
|
|
8
|
+
*
|
|
9
|
+
* agent-native changelog add "Recordings can be trimmed before sharing" --type added
|
|
10
|
+
* agent-native changelog release # roll pending → CHANGELOG.md (today)
|
|
11
|
+
* agent-native changelog list # show pending + released
|
|
12
|
+
*
|
|
13
|
+
* Runs in the current app directory (process.cwd()).
|
|
14
|
+
*/
|
|
15
|
+
import fs from "fs";
|
|
16
|
+
import path from "path";
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
parsePendingEntry,
|
|
20
|
+
parseChangelog,
|
|
21
|
+
rollupChangelog,
|
|
22
|
+
changelogSlug,
|
|
23
|
+
CHANGELOG_HEADER,
|
|
24
|
+
type ChangelogChangeType,
|
|
25
|
+
} from "../changelog/parse.js";
|
|
26
|
+
|
|
27
|
+
const CHANGELOG_FILE = "CHANGELOG.md";
|
|
28
|
+
const PENDING_DIR = "changelog";
|
|
29
|
+
|
|
30
|
+
function todayIso(): string {
|
|
31
|
+
// Local date in YYYY-MM-DD. The CLI is the one place a wall-clock read is
|
|
32
|
+
// appropriate (unlike workflow scripts), so `new Date()` is fine here.
|
|
33
|
+
const d = new Date();
|
|
34
|
+
const pad = (n: number) => String(n).padStart(2, "0");
|
|
35
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Minimal flag parser: supports `--key value` and `--key=value`. */
|
|
39
|
+
function parseFlags(args: string[]): {
|
|
40
|
+
flags: Record<string, string>;
|
|
41
|
+
rest: string[];
|
|
42
|
+
} {
|
|
43
|
+
const flags: Record<string, string> = {};
|
|
44
|
+
const rest: string[] = [];
|
|
45
|
+
for (let i = 0; i < args.length; i++) {
|
|
46
|
+
const arg = args[i];
|
|
47
|
+
if (arg.startsWith("--")) {
|
|
48
|
+
const eq = arg.indexOf("=");
|
|
49
|
+
if (eq !== -1) {
|
|
50
|
+
flags[arg.slice(2, eq)] = arg.slice(eq + 1);
|
|
51
|
+
} else {
|
|
52
|
+
const next = args[i + 1];
|
|
53
|
+
if (next && !next.startsWith("--")) {
|
|
54
|
+
flags[arg.slice(2)] = next;
|
|
55
|
+
i++;
|
|
56
|
+
} else {
|
|
57
|
+
flags[arg.slice(2)] = "true";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
rest.push(arg);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { flags, rest };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function printUsage(): void {
|
|
68
|
+
console.log(
|
|
69
|
+
[
|
|
70
|
+
"Usage:",
|
|
71
|
+
' agent-native changelog add "<summary>" [--type added|improved|fixed|changed|removed|security] [--date YYYY-MM-DD]',
|
|
72
|
+
" agent-native changelog release [--date YYYY-MM-DD]",
|
|
73
|
+
" agent-native changelog list",
|
|
74
|
+
"",
|
|
75
|
+
"Entries are user-facing notes. `add` writes a pending file under",
|
|
76
|
+
` ${PENDING_DIR}/; \`release\` rolls all pending files into ${CHANGELOG_FILE}.`,
|
|
77
|
+
].join("\n"),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function cmdAdd(args: string[]): number {
|
|
82
|
+
const { flags, rest } = parseFlags(args);
|
|
83
|
+
const summary = rest.join(" ").trim();
|
|
84
|
+
if (!summary) {
|
|
85
|
+
console.error('Provide a summary, e.g. changelog add "Faster search"');
|
|
86
|
+
return 1;
|
|
87
|
+
}
|
|
88
|
+
const type = (flags.type ?? "changed") as ChangelogChangeType;
|
|
89
|
+
const date = flags.date?.match(/\d{4}-\d{2}-\d{2}/)?.[0] ?? todayIso();
|
|
90
|
+
|
|
91
|
+
const dir = path.resolve(PENDING_DIR);
|
|
92
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
93
|
+
|
|
94
|
+
const slug = changelogSlug(summary) || "entry";
|
|
95
|
+
let file = path.join(dir, `${date}-${slug}.md`);
|
|
96
|
+
let n = 2;
|
|
97
|
+
while (fs.existsSync(file)) {
|
|
98
|
+
file = path.join(dir, `${date}-${slug}-${n++}.md`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Blank line after the closing frontmatter delimiter so the generated file
|
|
102
|
+
// is already Prettier-clean (Markdown requires a blank line before body text)
|
|
103
|
+
// and never trips the repo fmt check.
|
|
104
|
+
const content = `---\ntype: ${type}\ndate: ${date}\n---\n\n${summary}\n`;
|
|
105
|
+
fs.writeFileSync(file, content, "utf-8");
|
|
106
|
+
console.log(`Added changelog entry: ${path.relative(process.cwd(), file)}`);
|
|
107
|
+
return 0;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function readPending(): { file: string; content: string }[] {
|
|
111
|
+
const dir = path.resolve(PENDING_DIR);
|
|
112
|
+
if (!fs.existsSync(dir)) return [];
|
|
113
|
+
return fs
|
|
114
|
+
.readdirSync(dir)
|
|
115
|
+
.filter((f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md")
|
|
116
|
+
.sort()
|
|
117
|
+
.map((f) => ({
|
|
118
|
+
file: path.join(dir, f),
|
|
119
|
+
content: fs.readFileSync(path.join(dir, f), "utf-8"),
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function cmdRelease(args: string[]): number {
|
|
124
|
+
const { flags } = parseFlags(args);
|
|
125
|
+
const date = flags.date?.match(/\d{4}-\d{2}-\d{2}/)?.[0] ?? todayIso();
|
|
126
|
+
|
|
127
|
+
const pendingFiles = readPending();
|
|
128
|
+
if (pendingFiles.length === 0) {
|
|
129
|
+
console.log("No pending changelog entries to release.");
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const pending = pendingFiles.map((p) => parsePendingEntry(p.content));
|
|
134
|
+
const changelogPath = path.resolve(CHANGELOG_FILE);
|
|
135
|
+
const existing = fs.existsSync(changelogPath)
|
|
136
|
+
? fs.readFileSync(changelogPath, "utf-8")
|
|
137
|
+
: "";
|
|
138
|
+
|
|
139
|
+
const next = rollupChangelog(existing, pending, date);
|
|
140
|
+
fs.writeFileSync(changelogPath, next, "utf-8");
|
|
141
|
+
|
|
142
|
+
// Remove the pending entries now that they're released.
|
|
143
|
+
for (const p of pendingFiles) fs.rmSync(p.file);
|
|
144
|
+
|
|
145
|
+
console.log(
|
|
146
|
+
`Released ${pendingFiles.length} entr${
|
|
147
|
+
pendingFiles.length === 1 ? "y" : "ies"
|
|
148
|
+
} into ${CHANGELOG_FILE} (## ${date}).`,
|
|
149
|
+
);
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function cmdList(): number {
|
|
154
|
+
const pending = readPending();
|
|
155
|
+
const changelogPath = path.resolve(CHANGELOG_FILE);
|
|
156
|
+
const released = fs.existsSync(changelogPath)
|
|
157
|
+
? parseChangelog(fs.readFileSync(changelogPath, "utf-8"))
|
|
158
|
+
: [];
|
|
159
|
+
|
|
160
|
+
console.log(`Pending (${pending.length}):`);
|
|
161
|
+
for (const p of pending) {
|
|
162
|
+
const entry = parsePendingEntry(p.content);
|
|
163
|
+
console.log(
|
|
164
|
+
` - [${entry.type}] ${entry.text.split("\n")[0]} (${path.basename(
|
|
165
|
+
p.file,
|
|
166
|
+
)})`,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
console.log("");
|
|
170
|
+
console.log(`Released (${released.length}):`);
|
|
171
|
+
for (const r of released.slice(0, 10)) console.log(` - ${r.title}`);
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export async function runChangelog(args: string[]): Promise<number> {
|
|
176
|
+
const sub = args[0];
|
|
177
|
+
const rest = args.slice(1);
|
|
178
|
+
switch (sub) {
|
|
179
|
+
case "add":
|
|
180
|
+
return cmdAdd(rest);
|
|
181
|
+
case "release":
|
|
182
|
+
return cmdRelease(rest);
|
|
183
|
+
case "list":
|
|
184
|
+
return cmdList();
|
|
185
|
+
case undefined:
|
|
186
|
+
case "help":
|
|
187
|
+
case "--help":
|
|
188
|
+
case "-h":
|
|
189
|
+
printUsage();
|
|
190
|
+
return 0;
|
|
191
|
+
default:
|
|
192
|
+
console.error(`Unknown changelog subcommand: ${sub}\n`);
|
|
193
|
+
printUsage();
|
|
194
|
+
return 1;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Re-export header for callers that want to seed an empty CHANGELOG.md.
|
|
199
|
+
export { CHANGELOG_HEADER };
|
|
@@ -827,6 +827,21 @@ switch (command) {
|
|
|
827
827
|
break;
|
|
828
828
|
}
|
|
829
829
|
|
|
830
|
+
case "changelog": {
|
|
831
|
+
// Author and roll up the app's user-facing changelog (changeset-style
|
|
832
|
+
// pending entry files → a dated CHANGELOG.md section).
|
|
833
|
+
import("./changelog.js")
|
|
834
|
+
.then(async (m) => {
|
|
835
|
+
const code = await m.runChangelog(args);
|
|
836
|
+
process.exit(code);
|
|
837
|
+
})
|
|
838
|
+
.catch((err) => {
|
|
839
|
+
console.error(err?.message ?? err);
|
|
840
|
+
process.exit(1);
|
|
841
|
+
});
|
|
842
|
+
break;
|
|
843
|
+
}
|
|
844
|
+
|
|
830
845
|
case "--version":
|
|
831
846
|
case "-v": {
|
|
832
847
|
console.log(_version);
|
|
@@ -906,6 +921,10 @@ Usage:
|
|
|
906
921
|
Pass a URL instead of a name for a generic
|
|
907
922
|
research-and-integrate blueprint. --list to
|
|
908
923
|
browse available blueprints.
|
|
924
|
+
agent-native changelog <cmd> Author the app's user-facing changelog.
|
|
925
|
+
cmds: add "<summary>" [--type added|fixed|...] |
|
|
926
|
+
release | list. Pending entries live in
|
|
927
|
+
changelog/; 'release' rolls them into CHANGELOG.md.
|
|
909
928
|
agent-native audit-agent-web Audit a public URL for agent-readable surfaces
|
|
910
929
|
agent-native eval [pattern] Run the app's evals (**/*.eval.ts, evals/*.ts)
|
|
911
930
|
and exit non-zero if any scores below its
|
|
@@ -1932,7 +1932,7 @@ export function buildCommentBody(env: NodeJS.ProcessEnv = process.env): string {
|
|
|
1932
1932
|
lines.push(`</a>`);
|
|
1933
1933
|
lines.push("");
|
|
1934
1934
|
}
|
|
1935
|
-
lines.push(`**
|
|
1935
|
+
lines.push(`**Open the [full interactive recap](${safeUrl})**`);
|
|
1936
1936
|
if (env.DIFF_HUGE === "true") {
|
|
1937
1937
|
lines.push("");
|
|
1938
1938
|
lines.push(
|
|
@@ -2546,6 +2546,25 @@ const RECAP_SHOT_VIEWPORT = {
|
|
|
2546
2546
|
};
|
|
2547
2547
|
const RECAP_SHOT_DEVICE_SCALE_FACTOR = 2;
|
|
2548
2548
|
|
|
2549
|
+
/**
|
|
2550
|
+
* Identity shim for esbuild's `__name` helper, injected into the browser before
|
|
2551
|
+
* any screenshot init script or `page.evaluate` payload.
|
|
2552
|
+
*
|
|
2553
|
+
* esbuild/tsx `keepNames` (on by default) rewrites a named inner function — e.g.
|
|
2554
|
+
* `const readHeights = (…) => {…}` inside a `page.evaluate` callback — into
|
|
2555
|
+
* `__name(() => {…}, "readHeights")`. Playwright serializes that callback with
|
|
2556
|
+
* `Function.prototype.toString` and runs it in the page, where `__name` does not
|
|
2557
|
+
* exist, throwing `ReferenceError: __name is not defined` and silently dropping
|
|
2558
|
+
* the recap's inline PR-comment screenshot. CI's trusted-workspace path runs this
|
|
2559
|
+
* CLI through `tsx` (esbuild), so it fires there even though the tsc-built
|
|
2560
|
+
* published package never emits `__name`. Defining `__name` as an identity
|
|
2561
|
+
* function (esbuild's helper returns the target unchanged) makes every main-world
|
|
2562
|
+
* payload safe regardless of how the CLI was transpiled. Kept as a raw string so
|
|
2563
|
+
* esbuild can't rewrite the shim itself.
|
|
2564
|
+
*/
|
|
2565
|
+
const RECAP_SHOT_NAME_SHIM =
|
|
2566
|
+
"globalThis.__name = globalThis.__name || function (value) { return value; };";
|
|
2567
|
+
|
|
2549
2568
|
type PlaywrightModule = { chromium: import("playwright").BrowserType };
|
|
2550
2569
|
|
|
2551
2570
|
async function defaultImportPlaywright(): Promise<PlaywrightModule> {
|
|
@@ -2704,6 +2723,10 @@ export async function runShot(
|
|
|
2704
2723
|
deviceScaleFactor: RECAP_SHOT_DEVICE_SCALE_FACTOR,
|
|
2705
2724
|
...(theme ? { colorScheme: theme } : {}),
|
|
2706
2725
|
});
|
|
2726
|
+
// Must run before the theme init script and every page.evaluate below so
|
|
2727
|
+
// esbuild/tsx `keepNames` wrappers don't throw `__name is not defined` in
|
|
2728
|
+
// the browser (see RECAP_SHOT_NAME_SHIM).
|
|
2729
|
+
await context.addInitScript(RECAP_SHOT_NAME_SHIM);
|
|
2707
2730
|
if (theme) {
|
|
2708
2731
|
await context.addInitScript(
|
|
2709
2732
|
({ background, nextTheme }) => {
|