@agent-native/core 0.69.0 → 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 +48 -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/mcp/build-server.ts +1 -1
- package/corpus/core/src/mcp/embed-app.ts +112 -6
- 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 +7 -11
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +31 -0
- package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +71 -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/record.tsx +78 -5
- 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/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/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/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
|
@@ -1,157 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
All notable user-facing changes to Agent-Native Videos are documented here. Open it any
|
|
4
|
+
time from the command menu (Cmd+K → "What's new").
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- **Extracted Animation Logic to Reusable Pure Function**
|
|
8
|
-
- Created `app/remotion/animations/useElementAnimations.ts` (202 lines)
|
|
9
|
-
- Exported `calculateElementAnimations()` - pure function (not hook)
|
|
10
|
-
- Removed 130 lines of animation logic from InteractiveCardGrid
|
|
11
|
-
- Centralized all animation calculations in testable function
|
|
12
|
-
- Can be called inside loops (no Rules of Hooks violations)
|
|
13
|
-
- Other compositions can now reuse animation system instantly
|
|
14
|
-
- Reduced InteractiveCardGrid from 400+ to 320 lines
|
|
15
|
-
- Simpler and faster than hook-based approach
|
|
16
|
-
|
|
17
|
-
- **Centralized Configuration Constants**
|
|
18
|
-
- Created `app/config/constants.ts` (204 lines)
|
|
19
|
-
- Eliminated all magic numbers across codebase
|
|
20
|
-
- Organized by domain: ANIMATION_CONFIG, CURSOR_CONFIG, CARD_CONFIG, UI_CONFIG, etc.
|
|
21
|
-
- Type-safe with `as const`
|
|
22
|
-
- Well-documented with inline comments
|
|
23
|
-
|
|
24
|
-
- **Code Quality Improvements**
|
|
25
|
-
- Max function length: 87 lines → 42 lines
|
|
26
|
-
- Animation logic now testable in isolation
|
|
27
|
-
- Proper type guards with centralized validation
|
|
28
|
-
- Cleaner separation of concerns
|
|
29
|
-
|
|
30
|
-
**Impact**: Architecture grade improved from C+ to A-
|
|
6
|
+
## 2026-06-23
|
|
31
7
|
|
|
32
8
|
### Added
|
|
33
9
|
|
|
34
|
-
-
|
|
35
|
-
- Added `backgroundColor` and `borderColor` to animation property options
|
|
36
|
-
- Implemented color interpolation function for smooth color transitions
|
|
37
|
-
- Color picker UI with native browser color input
|
|
38
|
-
- Colors animate from each element's base color to target color (preserves multicolor designs)
|
|
39
|
-
|
|
40
|
-
- **Click Animation Return-to-Hover**: Click animations now properly animate back
|
|
41
|
-
- Implemented "there-and-back" animation (0→1→0 progress mapping)
|
|
42
|
-
- Doubles animation duration to accommodate forward and return transitions
|
|
43
|
-
- Smooth easing applied to both directions
|
|
44
|
-
|
|
45
|
-
- **Timeline Visual Enhancements**
|
|
46
|
-
- Changed cursor keyframe click indicator dot from grey/white to yellow (#facc15)
|
|
47
|
-
- Improved visual distinction for click events in timeline
|
|
48
|
-
|
|
49
|
-
### Changed
|
|
50
|
-
|
|
51
|
-
- **Playback Speed System**: Simplified from adaptive to manual control
|
|
52
|
-
- Removed adaptive playback rate compensation based on FPS measurement
|
|
53
|
-
- Added manual playback speed dropdown (0.25× to 2×)
|
|
54
|
-
- Moved speed selector to VideoPlayer bottom controls (next to Frame counter)
|
|
55
|
-
- Removed playback speed from Timeline component
|
|
56
|
-
|
|
57
|
-
- **Composition Creation Workflow**: Restored AI-powered generation
|
|
58
|
-
- Rewrote `NewCompositionPopover` with full agent chat integration
|
|
59
|
-
- Added file attachment support (images, videos, SVGs via data URLs)
|
|
60
|
-
- Implemented postMessage API for parent window communication
|
|
61
|
-
- Added event listener for `builder.agentChat.chatRunning` completion detection
|
|
62
|
-
- Slug-based URL generation with conflict resolution (`/c/comp-title`, `/c/comp-title-2`)
|
|
63
|
-
- Navigate to `/c/new` on submission for AI generation
|
|
64
|
-
|
|
65
|
-
- **Properties Panel Improvements**
|
|
66
|
-
- Removed composition name input from Properties > Properties section (non-editable)
|
|
67
|
-
- Hidden "x" unit label to avoid confusion with delete button (kept "px", "deg", etc.)
|
|
68
|
-
- Moved "Add Property" section above property list (below Motion Curve)
|
|
69
|
-
- Swapped + button to left side of dropdown
|
|
70
|
-
- Added Enter key support to add properties from dropdown
|
|
71
|
-
- Changed focus ring color to red-400 for consistency
|
|
72
|
-
- Removed hex code display next to color picker (visible in native picker)
|
|
73
|
-
|
|
74
|
-
- **Animation System Architecture**
|
|
75
|
-
- Updated `AnimationKeyframe.value` type to support `number | string` for colors
|
|
76
|
-
- Color animations only apply when `hoverProgress > 0` or `clickProgress > 0`
|
|
77
|
-
- Each element's base color extracted and used as animation starting point
|
|
78
|
-
- Hover and click animations support mixed numeric and color properties
|
|
79
|
-
|
|
80
|
-
### Fixed
|
|
81
|
-
|
|
82
|
-
- Browser cache issues causing stale code errors
|
|
83
|
-
- Fixed `ReferenceError: adaptivePlaybackRate is not defined`
|
|
84
|
-
- Fixed `ReferenceError: onCreateComposition is not defined`
|
|
85
|
-
- Solution: Dev server restart to clear Vite cache
|
|
86
|
-
|
|
87
|
-
- Color animation not preserving element colors
|
|
88
|
-
- Cards were all turning blue when backgroundColor animation added
|
|
89
|
-
- Fixed by interpolating from each card's unique base color instead of fixed start color
|
|
90
|
-
- Only applies color animations during active hover/click (preserves idle state)
|
|
91
|
-
|
|
92
|
-
- Click animations jumping back to hover state
|
|
93
|
-
- Animations were not tweening back, causing abrupt transitions
|
|
94
|
-
- Implemented smooth 0→1→0 progress curve with doubled duration
|
|
95
|
-
|
|
96
|
-
### Technical Details
|
|
97
|
-
|
|
98
|
-
#### Color Interpolation Implementation
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
// New function in elementAnimations.ts
|
|
102
|
-
export function interpolateColor(
|
|
103
|
-
color1: string,
|
|
104
|
-
color2: string,
|
|
105
|
-
progress: number,
|
|
106
|
-
): string;
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
- Parses hex colors to RGB components
|
|
110
|
-
- Linear interpolation per channel
|
|
111
|
-
- Returns hex color string
|
|
112
|
-
|
|
113
|
-
#### Animation Progress Mapping
|
|
114
|
-
|
|
115
|
-
```typescript
|
|
116
|
-
// Click animation: 0→1→0 curve
|
|
117
|
-
const rawProgress = framesSinceClick / clickDuration; // 0→2
|
|
118
|
-
clickProgress = rawProgress <= 1 ? rawProgress : 2 - rawProgress; // 0→1→0
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
#### Files Modified
|
|
122
|
-
|
|
123
|
-
- `app/components/VideoPlayer.tsx` - Simplified playback rate
|
|
124
|
-
- `app/components/Timeline.tsx` - Removed playback UI, changed dot color
|
|
125
|
-
- `app/pages/CompositionView.tsx` - Playback rate state management
|
|
126
|
-
- `app/components/NewCompositionPopover.tsx` - Complete rewrite for agent chat integration
|
|
127
|
-
- `app/components/Sidebar.tsx` - Updated props, removed name input
|
|
128
|
-
- `app/components/PropsEditor.tsx` - Removed composition name field
|
|
129
|
-
- `app/components/CurrentElementPanel.tsx` - Color properties, UI improvements
|
|
130
|
-
- `app/types/elementAnimations.ts` - Color support, interpolation
|
|
131
|
-
- `app/remotion/compositions/InteractiveCardGrid.tsx` - Color animation logic
|
|
132
|
-
|
|
133
|
-
#### Files Created
|
|
134
|
-
|
|
135
|
-
- `app/remotion/animations/useElementAnimations.ts` (209 lines) - **Reusable animation hook**
|
|
136
|
-
- `app/config/constants.ts` (204 lines) - **Centralized configuration**
|
|
137
|
-
- `app/utils/compositionHelpers.ts` (378 lines) - Helper functions library
|
|
138
|
-
- `app/utils/debug.ts` (104 lines) - Production-safe logging utility
|
|
139
|
-
- `scripts/create-composition.ts` (127 lines) - Example composition script
|
|
140
|
-
- `COMPOSITION_GUIDE.md` (787 lines) - Comprehensive API reference
|
|
141
|
-
- `QUICK_START.md` (498 lines) - Beginner-friendly guide
|
|
142
|
-
- `README.md` (209 lines) - Project overview
|
|
143
|
-
- `CHANGELOG.md`, `CODE_REVIEW.md`, `TODO.md`, `PR_DESCRIPTION.md`, `SESSION_SUMMARY.md`
|
|
144
|
-
|
|
145
|
-
### Developer Experience
|
|
146
|
-
|
|
147
|
-
- Native `<select>` supports type-to-search for properties
|
|
148
|
-
- Arrow keys navigate property options
|
|
149
|
-
- Enter key adds selected property
|
|
150
|
-
- Color picker shows hex values natively
|
|
151
|
-
- Improved visual hierarchy in properties panel
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## Notes
|
|
156
|
-
|
|
157
|
-
All changes maintain backward compatibility with existing compositions. Color animation feature is additive and optional.
|
|
10
|
+
- See what's new right inside Agent-Native Videos — a changelog now lives in the command menu (Cmd+K).
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
configureTracking,
|
|
21
21
|
getThemeInitScript,
|
|
22
22
|
} from "@agent-native/core/client";
|
|
23
|
+
import changelog from "../CHANGELOG.md?raw";
|
|
23
24
|
configureTracking({
|
|
24
25
|
getDefaultProps: (_name, properties) => ({
|
|
25
26
|
...properties,
|
|
@@ -83,7 +84,12 @@ function AppContent() {
|
|
|
83
84
|
|
|
84
85
|
return (
|
|
85
86
|
<>
|
|
86
|
-
<CommandMenu
|
|
87
|
+
<CommandMenu
|
|
88
|
+
open={cmdkOpen}
|
|
89
|
+
onOpenChange={setCmdkOpen}
|
|
90
|
+
changelog={changelog}
|
|
91
|
+
changelogKey="videos"
|
|
92
|
+
>
|
|
87
93
|
<CommandMenu.Group heading="Videos">
|
|
88
94
|
<CommandMenu.Item onSelect={() => {}}>
|
|
89
95
|
Search compositions
|
|
@@ -0,0 +1,70 @@
|
|
|
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
|
+
/** A single released section of a CHANGELOG.md file. */
|
|
15
|
+
export interface ChangelogEntry {
|
|
16
|
+
/** Stable id derived from the heading — used for "unseen" tracking. */
|
|
17
|
+
id: string;
|
|
18
|
+
/** Raw heading text, e.g. `2026-06-23` or `v1.2.0 — 2026-06-23`. */
|
|
19
|
+
title: string;
|
|
20
|
+
/** ISO date (YYYY-MM-DD) extracted from the heading, if present. */
|
|
21
|
+
date?: string;
|
|
22
|
+
/** Version label extracted from the heading, if present. */
|
|
23
|
+
version?: string;
|
|
24
|
+
/** Markdown body beneath the heading (until the next `## ` section). */
|
|
25
|
+
body: string;
|
|
26
|
+
}
|
|
27
|
+
/** A not-yet-released entry authored as a `changelog/<file>.md` file. */
|
|
28
|
+
export interface PendingChangelogEntry {
|
|
29
|
+
/** Category — `added`, `improved`, `fixed`, `changed`, etc. */
|
|
30
|
+
type: ChangelogChangeType;
|
|
31
|
+
/** ISO date the entry was authored (YYYY-MM-DD). */
|
|
32
|
+
date?: string;
|
|
33
|
+
/** User-facing description (markdown, single bullet). */
|
|
34
|
+
text: string;
|
|
35
|
+
}
|
|
36
|
+
export type ChangelogChangeType = "added" | "improved" | "fixed" | "changed" | "removed" | "security";
|
|
37
|
+
/**
|
|
38
|
+
* Order changes are grouped under a release heading. Anything not listed here
|
|
39
|
+
* falls back to the "changed" group, then renders in insertion order.
|
|
40
|
+
*/
|
|
41
|
+
export declare const CHANGELOG_GROUP_ORDER: ChangelogChangeType[];
|
|
42
|
+
declare const GROUP_LABELS: Record<ChangelogChangeType, string>;
|
|
43
|
+
/** Lowercase, hyphenate, and strip to a URL/id-safe slug. */
|
|
44
|
+
export declare function changelogSlug(value: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Parse a CHANGELOG.md document into structured release entries.
|
|
47
|
+
*
|
|
48
|
+
* Tolerant by design: an empty or malformed file yields an empty list rather
|
|
49
|
+
* than throwing, so a missing/partial changelog never breaks the UI.
|
|
50
|
+
*/
|
|
51
|
+
export declare function parseChangelog(markdown: string): ChangelogEntry[];
|
|
52
|
+
/**
|
|
53
|
+
* Parse a pending `changelog/<file>.md` entry: optional `---` frontmatter
|
|
54
|
+
* (`type:` / `date:`) followed by the markdown description body.
|
|
55
|
+
*/
|
|
56
|
+
export declare function parsePendingEntry(content: string): PendingChangelogEntry;
|
|
57
|
+
/**
|
|
58
|
+
* Render a set of pending entries as a single dated release section (the body
|
|
59
|
+
* that goes beneath a `## <date>` heading). Groups bullets by type.
|
|
60
|
+
*/
|
|
61
|
+
export declare function renderReleaseBody(entries: PendingChangelogEntry[]): string;
|
|
62
|
+
declare const CHANGELOG_HEADER: string;
|
|
63
|
+
/**
|
|
64
|
+
* Roll a batch of pending entries into an existing CHANGELOG.md document,
|
|
65
|
+
* prepending a new `## <date>` section above the most recent release. Returns
|
|
66
|
+
* the full updated document. Pure — the CLI handles file IO and deletion.
|
|
67
|
+
*/
|
|
68
|
+
export declare function rollupChangelog(existing: string, pending: PendingChangelogEntry[], releaseDate: string): string;
|
|
69
|
+
export { CHANGELOG_HEADER, GROUP_LABELS };
|
|
70
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/changelog/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,yEAAyE;AACzE,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,IAAI,EAAE,mBAAmB,CAAC;IAC1B,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,mBAAmB,GAC3B,OAAO,GACP,UAAU,GACV,OAAO,GACP,SAAS,GACT,SAAS,GACT,UAAU,CAAC;AAEf;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,mBAAmB,EAOtD,CAAC;AAEF,QAAA,MAAM,YAAY,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAOrD,CAAC;AAIF,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMnD;AAiBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CA+CjE;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAuBxE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAwB1E;AAED,QAAA,MAAM,gBAAgB,QAEgD,CAAC;AAEvE;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,qBAAqB,EAAE,EAChC,WAAW,EAAE,MAAM,GAClB,MAAM,CAgBR;AAED,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,200 @@
|
|
|
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
|
+
* Order changes are grouped under a release heading. Anything not listed here
|
|
16
|
+
* falls back to the "changed" group, then renders in insertion order.
|
|
17
|
+
*/
|
|
18
|
+
export const CHANGELOG_GROUP_ORDER = [
|
|
19
|
+
"added",
|
|
20
|
+
"improved",
|
|
21
|
+
"fixed",
|
|
22
|
+
"changed",
|
|
23
|
+
"removed",
|
|
24
|
+
"security",
|
|
25
|
+
];
|
|
26
|
+
const GROUP_LABELS = {
|
|
27
|
+
added: "Added",
|
|
28
|
+
improved: "Improved",
|
|
29
|
+
fixed: "Fixed",
|
|
30
|
+
changed: "Changed",
|
|
31
|
+
removed: "Removed",
|
|
32
|
+
security: "Security",
|
|
33
|
+
};
|
|
34
|
+
const ISO_DATE = /(\d{4}-\d{2}-\d{2})/;
|
|
35
|
+
/** Lowercase, hyphenate, and strip to a URL/id-safe slug. */
|
|
36
|
+
export function changelogSlug(value) {
|
|
37
|
+
return value
|
|
38
|
+
.toLowerCase()
|
|
39
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
40
|
+
.replace(/^-+|-+$/g, "")
|
|
41
|
+
.slice(0, 60);
|
|
42
|
+
}
|
|
43
|
+
function normalizeType(raw) {
|
|
44
|
+
const value = (raw ?? "").trim().toLowerCase();
|
|
45
|
+
if (CHANGELOG_GROUP_ORDER.includes(value)) {
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
// Friendly aliases.
|
|
49
|
+
if (value === "feature" || value === "new" || value === "add")
|
|
50
|
+
return "added";
|
|
51
|
+
if (value === "improvement" || value === "enhancement" || value === "perf") {
|
|
52
|
+
return "improved";
|
|
53
|
+
}
|
|
54
|
+
if (value === "fix" || value === "bugfix" || value === "bug")
|
|
55
|
+
return "fixed";
|
|
56
|
+
if (value === "remove" || value === "deprecated")
|
|
57
|
+
return "removed";
|
|
58
|
+
return "changed";
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Parse a CHANGELOG.md document into structured release entries.
|
|
62
|
+
*
|
|
63
|
+
* Tolerant by design: an empty or malformed file yields an empty list rather
|
|
64
|
+
* than throwing, so a missing/partial changelog never breaks the UI.
|
|
65
|
+
*/
|
|
66
|
+
export function parseChangelog(markdown) {
|
|
67
|
+
if (!markdown || typeof markdown !== "string")
|
|
68
|
+
return [];
|
|
69
|
+
const lines = markdown.split(/\r?\n/);
|
|
70
|
+
const entries = [];
|
|
71
|
+
const seenIds = new Set();
|
|
72
|
+
let currentTitle = null;
|
|
73
|
+
let bodyLines = [];
|
|
74
|
+
const flush = () => {
|
|
75
|
+
if (currentTitle === null)
|
|
76
|
+
return;
|
|
77
|
+
const title = currentTitle.trim();
|
|
78
|
+
const date = title.match(ISO_DATE)?.[1];
|
|
79
|
+
const version = title.match(/v?\d+\.\d+(?:\.\d+)?/)?.[0];
|
|
80
|
+
// Build a stable, unique id from the heading.
|
|
81
|
+
let base = changelogSlug(title) || "entry";
|
|
82
|
+
let id = base;
|
|
83
|
+
let n = 2;
|
|
84
|
+
while (seenIds.has(id))
|
|
85
|
+
id = `${base}-${n++}`;
|
|
86
|
+
seenIds.add(id);
|
|
87
|
+
entries.push({
|
|
88
|
+
id,
|
|
89
|
+
title,
|
|
90
|
+
date,
|
|
91
|
+
version: version && version !== date ? version : undefined,
|
|
92
|
+
body: bodyLines.join("\n").trim(),
|
|
93
|
+
});
|
|
94
|
+
currentTitle = null;
|
|
95
|
+
bodyLines = [];
|
|
96
|
+
};
|
|
97
|
+
for (const line of lines) {
|
|
98
|
+
// `## ` (but not `### `) starts a new release section.
|
|
99
|
+
const match = /^##\s+(?!#)(.+?)\s*$/.exec(line);
|
|
100
|
+
if (match) {
|
|
101
|
+
flush();
|
|
102
|
+
currentTitle = stripBrackets(match[1]);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
// Skip the top-level `# Changelog` title and anything before the first `##`.
|
|
106
|
+
if (currentTitle === null)
|
|
107
|
+
continue;
|
|
108
|
+
bodyLines.push(line);
|
|
109
|
+
}
|
|
110
|
+
flush();
|
|
111
|
+
return entries;
|
|
112
|
+
}
|
|
113
|
+
/** `## [1.2.0]` → `1.2.0`; leaves un-bracketed headings untouched. */
|
|
114
|
+
function stripBrackets(title) {
|
|
115
|
+
return title.replace(/^\[(.+?)\]\s*/, "$1 ").trim();
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Parse a pending `changelog/<file>.md` entry: optional `---` frontmatter
|
|
119
|
+
* (`type:` / `date:`) followed by the markdown description body.
|
|
120
|
+
*/
|
|
121
|
+
export function parsePendingEntry(content) {
|
|
122
|
+
let type;
|
|
123
|
+
let date;
|
|
124
|
+
let body = content;
|
|
125
|
+
const fm = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(content);
|
|
126
|
+
if (fm) {
|
|
127
|
+
for (const raw of fm[1].split(/\r?\n/)) {
|
|
128
|
+
const kv = /^([a-zA-Z]+)\s*:\s*(.+?)\s*$/.exec(raw);
|
|
129
|
+
if (!kv)
|
|
130
|
+
continue;
|
|
131
|
+
const key = kv[1].toLowerCase();
|
|
132
|
+
const value = kv[2].replace(/^["']|["']$/g, "").trim();
|
|
133
|
+
if (key === "type")
|
|
134
|
+
type = value;
|
|
135
|
+
else if (key === "date")
|
|
136
|
+
date = value.match(ISO_DATE)?.[1] ?? value;
|
|
137
|
+
}
|
|
138
|
+
body = content.slice(fm[0].length);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
type: normalizeType(type),
|
|
142
|
+
date,
|
|
143
|
+
text: body.trim(),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Render a set of pending entries as a single dated release section (the body
|
|
148
|
+
* that goes beneath a `## <date>` heading). Groups bullets by type.
|
|
149
|
+
*/
|
|
150
|
+
export function renderReleaseBody(entries) {
|
|
151
|
+
const groups = new Map();
|
|
152
|
+
for (const entry of entries) {
|
|
153
|
+
const text = entry.text.trim();
|
|
154
|
+
if (!text)
|
|
155
|
+
continue;
|
|
156
|
+
const bullet = text.includes("\n")
|
|
157
|
+
? // Preserve multi-line bodies, indenting continuation lines.
|
|
158
|
+
text
|
|
159
|
+
.split(/\r?\n/)
|
|
160
|
+
.map((l, i) => (i === 0 ? `- ${l}` : ` ${l}`))
|
|
161
|
+
.join("\n")
|
|
162
|
+
: `- ${text}`;
|
|
163
|
+
const list = groups.get(entry.type) ?? [];
|
|
164
|
+
list.push(bullet);
|
|
165
|
+
groups.set(entry.type, list);
|
|
166
|
+
}
|
|
167
|
+
const sections = [];
|
|
168
|
+
for (const type of CHANGELOG_GROUP_ORDER) {
|
|
169
|
+
const list = groups.get(type);
|
|
170
|
+
if (!list?.length)
|
|
171
|
+
continue;
|
|
172
|
+
sections.push(`### ${GROUP_LABELS[type]}\n\n${list.join("\n")}`);
|
|
173
|
+
}
|
|
174
|
+
return sections.join("\n\n");
|
|
175
|
+
}
|
|
176
|
+
const CHANGELOG_HEADER = "# Changelog\n\n" +
|
|
177
|
+
"All notable user-facing changes to this app are documented here.\n";
|
|
178
|
+
/**
|
|
179
|
+
* Roll a batch of pending entries into an existing CHANGELOG.md document,
|
|
180
|
+
* prepending a new `## <date>` section above the most recent release. Returns
|
|
181
|
+
* the full updated document. Pure — the CLI handles file IO and deletion.
|
|
182
|
+
*/
|
|
183
|
+
export function rollupChangelog(existing, pending, releaseDate) {
|
|
184
|
+
const body = renderReleaseBody(pending);
|
|
185
|
+
if (!body)
|
|
186
|
+
return existing || `${CHANGELOG_HEADER}`;
|
|
187
|
+
const section = `## ${releaseDate}\n\n${body}\n`;
|
|
188
|
+
const doc = (existing || CHANGELOG_HEADER).replace(/\s+$/, "");
|
|
189
|
+
// Insert the new section immediately before the first existing `## ` release
|
|
190
|
+
// so the header/intro stays on top and releases stay newest-first.
|
|
191
|
+
const firstRelease = doc.search(/^##\s+(?!#)/m);
|
|
192
|
+
if (firstRelease === -1) {
|
|
193
|
+
return `${doc}\n\n${section}\n`;
|
|
194
|
+
}
|
|
195
|
+
const head = doc.slice(0, firstRelease).replace(/\s+$/, "");
|
|
196
|
+
const rest = doc.slice(firstRelease);
|
|
197
|
+
return `${head}\n\n${section}\n${rest}\n`;
|
|
198
|
+
}
|
|
199
|
+
export { CHANGELOG_HEADER, GROUP_LABELS };
|
|
200
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/changelog/parse.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared, dependency-free changelog parsing + serialization.\n *\n * Used by BOTH:\n * - the browser bundle (rendering an app's CHANGELOG.md in the command\n * menu / settings \"What's new\" surface), and\n * - the `agent-native changelog` CLI (rolling pending entry files up into\n * CHANGELOG.md).\n *\n * Keep this file isomorphic: no Node, no browser, no third-party deps. The\n * markdown shape is the conventional \"Keep a Changelog\" layout — a top-level\n * `# Changelog` heading followed by one `## <release>` section per release.\n */\n\n/** A single released section of a CHANGELOG.md file. */\nexport interface ChangelogEntry {\n /** Stable id derived from the heading — used for \"unseen\" tracking. */\n id: string;\n /** Raw heading text, e.g. `2026-06-23` or `v1.2.0 — 2026-06-23`. */\n title: string;\n /** ISO date (YYYY-MM-DD) extracted from the heading, if present. */\n date?: string;\n /** Version label extracted from the heading, if present. */\n version?: string;\n /** Markdown body beneath the heading (until the next `## ` section). */\n body: string;\n}\n\n/** A not-yet-released entry authored as a `changelog/<file>.md` file. */\nexport interface PendingChangelogEntry {\n /** Category — `added`, `improved`, `fixed`, `changed`, etc. */\n type: ChangelogChangeType;\n /** ISO date the entry was authored (YYYY-MM-DD). */\n date?: string;\n /** User-facing description (markdown, single bullet). */\n text: string;\n}\n\nexport type ChangelogChangeType =\n | \"added\"\n | \"improved\"\n | \"fixed\"\n | \"changed\"\n | \"removed\"\n | \"security\";\n\n/**\n * Order changes are grouped under a release heading. Anything not listed here\n * falls back to the \"changed\" group, then renders in insertion order.\n */\nexport const CHANGELOG_GROUP_ORDER: ChangelogChangeType[] = [\n \"added\",\n \"improved\",\n \"fixed\",\n \"changed\",\n \"removed\",\n \"security\",\n];\n\nconst GROUP_LABELS: Record<ChangelogChangeType, string> = {\n added: \"Added\",\n improved: \"Improved\",\n fixed: \"Fixed\",\n changed: \"Changed\",\n removed: \"Removed\",\n security: \"Security\",\n};\n\nconst ISO_DATE = /(\\d{4}-\\d{2}-\\d{2})/;\n\n/** Lowercase, hyphenate, and strip to a URL/id-safe slug. */\nexport function changelogSlug(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 60);\n}\n\nfunction normalizeType(raw: string | undefined): ChangelogChangeType {\n const value = (raw ?? \"\").trim().toLowerCase();\n if ((CHANGELOG_GROUP_ORDER as string[]).includes(value)) {\n return value as ChangelogChangeType;\n }\n // Friendly aliases.\n if (value === \"feature\" || value === \"new\" || value === \"add\") return \"added\";\n if (value === \"improvement\" || value === \"enhancement\" || value === \"perf\") {\n return \"improved\";\n }\n if (value === \"fix\" || value === \"bugfix\" || value === \"bug\") return \"fixed\";\n if (value === \"remove\" || value === \"deprecated\") return \"removed\";\n return \"changed\";\n}\n\n/**\n * Parse a CHANGELOG.md document into structured release entries.\n *\n * Tolerant by design: an empty or malformed file yields an empty list rather\n * than throwing, so a missing/partial changelog never breaks the UI.\n */\nexport function parseChangelog(markdown: string): ChangelogEntry[] {\n if (!markdown || typeof markdown !== \"string\") return [];\n\n const lines = markdown.split(/\\r?\\n/);\n const entries: ChangelogEntry[] = [];\n const seenIds = new Set<string>();\n\n let currentTitle: string | null = null;\n let bodyLines: string[] = [];\n\n const flush = () => {\n if (currentTitle === null) return;\n const title = currentTitle.trim();\n const date = title.match(ISO_DATE)?.[1];\n const version = title.match(/v?\\d+\\.\\d+(?:\\.\\d+)?/)?.[0];\n // Build a stable, unique id from the heading.\n let base = changelogSlug(title) || \"entry\";\n let id = base;\n let n = 2;\n while (seenIds.has(id)) id = `${base}-${n++}`;\n seenIds.add(id);\n entries.push({\n id,\n title,\n date,\n version: version && version !== date ? version : undefined,\n body: bodyLines.join(\"\\n\").trim(),\n });\n currentTitle = null;\n bodyLines = [];\n };\n\n for (const line of lines) {\n // `## ` (but not `### `) starts a new release section.\n const match = /^##\\s+(?!#)(.+?)\\s*$/.exec(line);\n if (match) {\n flush();\n currentTitle = stripBrackets(match[1]);\n continue;\n }\n // Skip the top-level `# Changelog` title and anything before the first `##`.\n if (currentTitle === null) continue;\n bodyLines.push(line);\n }\n flush();\n\n return entries;\n}\n\n/** `## [1.2.0]` → `1.2.0`; leaves un-bracketed headings untouched. */\nfunction stripBrackets(title: string): string {\n return title.replace(/^\\[(.+?)\\]\\s*/, \"$1 \").trim();\n}\n\n/**\n * Parse a pending `changelog/<file>.md` entry: optional `---` frontmatter\n * (`type:` / `date:`) followed by the markdown description body.\n */\nexport function parsePendingEntry(content: string): PendingChangelogEntry {\n let type: string | undefined;\n let date: string | undefined;\n let body = content;\n\n const fm = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/.exec(content);\n if (fm) {\n for (const raw of fm[1].split(/\\r?\\n/)) {\n const kv = /^([a-zA-Z]+)\\s*:\\s*(.+?)\\s*$/.exec(raw);\n if (!kv) continue;\n const key = kv[1].toLowerCase();\n const value = kv[2].replace(/^[\"']|[\"']$/g, \"\").trim();\n if (key === \"type\") type = value;\n else if (key === \"date\") date = value.match(ISO_DATE)?.[1] ?? value;\n }\n body = content.slice(fm[0].length);\n }\n\n return {\n type: normalizeType(type),\n date,\n text: body.trim(),\n };\n}\n\n/**\n * Render a set of pending entries as a single dated release section (the body\n * that goes beneath a `## <date>` heading). Groups bullets by type.\n */\nexport function renderReleaseBody(entries: PendingChangelogEntry[]): string {\n const groups = new Map<ChangelogChangeType, string[]>();\n for (const entry of entries) {\n const text = entry.text.trim();\n if (!text) continue;\n const bullet = text.includes(\"\\n\")\n ? // Preserve multi-line bodies, indenting continuation lines.\n text\n .split(/\\r?\\n/)\n .map((l, i) => (i === 0 ? `- ${l}` : ` ${l}`))\n .join(\"\\n\")\n : `- ${text}`;\n const list = groups.get(entry.type) ?? [];\n list.push(bullet);\n groups.set(entry.type, list);\n }\n\n const sections: string[] = [];\n for (const type of CHANGELOG_GROUP_ORDER) {\n const list = groups.get(type);\n if (!list?.length) continue;\n sections.push(`### ${GROUP_LABELS[type]}\\n\\n${list.join(\"\\n\")}`);\n }\n return sections.join(\"\\n\\n\");\n}\n\nconst CHANGELOG_HEADER =\n \"# Changelog\\n\\n\" +\n \"All notable user-facing changes to this app are documented here.\\n\";\n\n/**\n * Roll a batch of pending entries into an existing CHANGELOG.md document,\n * prepending a new `## <date>` section above the most recent release. Returns\n * the full updated document. Pure — the CLI handles file IO and deletion.\n */\nexport function rollupChangelog(\n existing: string,\n pending: PendingChangelogEntry[],\n releaseDate: string,\n): string {\n const body = renderReleaseBody(pending);\n if (!body) return existing || `${CHANGELOG_HEADER}`;\n\n const section = `## ${releaseDate}\\n\\n${body}\\n`;\n\n const doc = (existing || CHANGELOG_HEADER).replace(/\\s+$/, \"\");\n // Insert the new section immediately before the first existing `## ` release\n // so the header/intro stays on top and releases stay newest-first.\n const firstRelease = doc.search(/^##\\s+(?!#)/m);\n if (firstRelease === -1) {\n return `${doc}\\n\\n${section}\\n`;\n }\n const head = doc.slice(0, firstRelease).replace(/\\s+$/, \"\");\n const rest = doc.slice(firstRelease);\n return `${head}\\n\\n${section}\\n${rest}\\n`;\n}\n\nexport { CHANGELOG_HEADER, GROUP_LABELS };\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/cli/changelog.ts"],"names":[],"mappings":"AAiBA,OAAO,EAKL,gBAAgB,EAEjB,MAAM,uBAAuB,CAAC;AAsJ/B,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBlE;AAGD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,166 @@
|
|
|
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
|
+
import { parsePendingEntry, parseChangelog, rollupChangelog, changelogSlug, CHANGELOG_HEADER, } from "../changelog/parse.js";
|
|
18
|
+
const CHANGELOG_FILE = "CHANGELOG.md";
|
|
19
|
+
const PENDING_DIR = "changelog";
|
|
20
|
+
function todayIso() {
|
|
21
|
+
// Local date in YYYY-MM-DD. The CLI is the one place a wall-clock read is
|
|
22
|
+
// appropriate (unlike workflow scripts), so `new Date()` is fine here.
|
|
23
|
+
const d = new Date();
|
|
24
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
25
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
26
|
+
}
|
|
27
|
+
/** Minimal flag parser: supports `--key value` and `--key=value`. */
|
|
28
|
+
function parseFlags(args) {
|
|
29
|
+
const flags = {};
|
|
30
|
+
const rest = [];
|
|
31
|
+
for (let i = 0; i < args.length; i++) {
|
|
32
|
+
const arg = args[i];
|
|
33
|
+
if (arg.startsWith("--")) {
|
|
34
|
+
const eq = arg.indexOf("=");
|
|
35
|
+
if (eq !== -1) {
|
|
36
|
+
flags[arg.slice(2, eq)] = arg.slice(eq + 1);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const next = args[i + 1];
|
|
40
|
+
if (next && !next.startsWith("--")) {
|
|
41
|
+
flags[arg.slice(2)] = next;
|
|
42
|
+
i++;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
flags[arg.slice(2)] = "true";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
rest.push(arg);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { flags, rest };
|
|
54
|
+
}
|
|
55
|
+
function printUsage() {
|
|
56
|
+
console.log([
|
|
57
|
+
"Usage:",
|
|
58
|
+
' agent-native changelog add "<summary>" [--type added|improved|fixed|changed|removed|security] [--date YYYY-MM-DD]',
|
|
59
|
+
" agent-native changelog release [--date YYYY-MM-DD]",
|
|
60
|
+
" agent-native changelog list",
|
|
61
|
+
"",
|
|
62
|
+
"Entries are user-facing notes. `add` writes a pending file under",
|
|
63
|
+
` ${PENDING_DIR}/; \`release\` rolls all pending files into ${CHANGELOG_FILE}.`,
|
|
64
|
+
].join("\n"));
|
|
65
|
+
}
|
|
66
|
+
function cmdAdd(args) {
|
|
67
|
+
const { flags, rest } = parseFlags(args);
|
|
68
|
+
const summary = rest.join(" ").trim();
|
|
69
|
+
if (!summary) {
|
|
70
|
+
console.error('Provide a summary, e.g. changelog add "Faster search"');
|
|
71
|
+
return 1;
|
|
72
|
+
}
|
|
73
|
+
const type = (flags.type ?? "changed");
|
|
74
|
+
const date = flags.date?.match(/\d{4}-\d{2}-\d{2}/)?.[0] ?? todayIso();
|
|
75
|
+
const dir = path.resolve(PENDING_DIR);
|
|
76
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
77
|
+
const slug = changelogSlug(summary) || "entry";
|
|
78
|
+
let file = path.join(dir, `${date}-${slug}.md`);
|
|
79
|
+
let n = 2;
|
|
80
|
+
while (fs.existsSync(file)) {
|
|
81
|
+
file = path.join(dir, `${date}-${slug}-${n++}.md`);
|
|
82
|
+
}
|
|
83
|
+
// Blank line after the closing frontmatter delimiter so the generated file
|
|
84
|
+
// is already Prettier-clean (Markdown requires a blank line before body text)
|
|
85
|
+
// and never trips the repo fmt check.
|
|
86
|
+
const content = `---\ntype: ${type}\ndate: ${date}\n---\n\n${summary}\n`;
|
|
87
|
+
fs.writeFileSync(file, content, "utf-8");
|
|
88
|
+
console.log(`Added changelog entry: ${path.relative(process.cwd(), file)}`);
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
function readPending() {
|
|
92
|
+
const dir = path.resolve(PENDING_DIR);
|
|
93
|
+
if (!fs.existsSync(dir))
|
|
94
|
+
return [];
|
|
95
|
+
return fs
|
|
96
|
+
.readdirSync(dir)
|
|
97
|
+
.filter((f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md")
|
|
98
|
+
.sort()
|
|
99
|
+
.map((f) => ({
|
|
100
|
+
file: path.join(dir, f),
|
|
101
|
+
content: fs.readFileSync(path.join(dir, f), "utf-8"),
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
function cmdRelease(args) {
|
|
105
|
+
const { flags } = parseFlags(args);
|
|
106
|
+
const date = flags.date?.match(/\d{4}-\d{2}-\d{2}/)?.[0] ?? todayIso();
|
|
107
|
+
const pendingFiles = readPending();
|
|
108
|
+
if (pendingFiles.length === 0) {
|
|
109
|
+
console.log("No pending changelog entries to release.");
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
const pending = pendingFiles.map((p) => parsePendingEntry(p.content));
|
|
113
|
+
const changelogPath = path.resolve(CHANGELOG_FILE);
|
|
114
|
+
const existing = fs.existsSync(changelogPath)
|
|
115
|
+
? fs.readFileSync(changelogPath, "utf-8")
|
|
116
|
+
: "";
|
|
117
|
+
const next = rollupChangelog(existing, pending, date);
|
|
118
|
+
fs.writeFileSync(changelogPath, next, "utf-8");
|
|
119
|
+
// Remove the pending entries now that they're released.
|
|
120
|
+
for (const p of pendingFiles)
|
|
121
|
+
fs.rmSync(p.file);
|
|
122
|
+
console.log(`Released ${pendingFiles.length} entr${pendingFiles.length === 1 ? "y" : "ies"} into ${CHANGELOG_FILE} (## ${date}).`);
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
function cmdList() {
|
|
126
|
+
const pending = readPending();
|
|
127
|
+
const changelogPath = path.resolve(CHANGELOG_FILE);
|
|
128
|
+
const released = fs.existsSync(changelogPath)
|
|
129
|
+
? parseChangelog(fs.readFileSync(changelogPath, "utf-8"))
|
|
130
|
+
: [];
|
|
131
|
+
console.log(`Pending (${pending.length}):`);
|
|
132
|
+
for (const p of pending) {
|
|
133
|
+
const entry = parsePendingEntry(p.content);
|
|
134
|
+
console.log(` - [${entry.type}] ${entry.text.split("\n")[0]} (${path.basename(p.file)})`);
|
|
135
|
+
}
|
|
136
|
+
console.log("");
|
|
137
|
+
console.log(`Released (${released.length}):`);
|
|
138
|
+
for (const r of released.slice(0, 10))
|
|
139
|
+
console.log(` - ${r.title}`);
|
|
140
|
+
return 0;
|
|
141
|
+
}
|
|
142
|
+
export async function runChangelog(args) {
|
|
143
|
+
const sub = args[0];
|
|
144
|
+
const rest = args.slice(1);
|
|
145
|
+
switch (sub) {
|
|
146
|
+
case "add":
|
|
147
|
+
return cmdAdd(rest);
|
|
148
|
+
case "release":
|
|
149
|
+
return cmdRelease(rest);
|
|
150
|
+
case "list":
|
|
151
|
+
return cmdList();
|
|
152
|
+
case undefined:
|
|
153
|
+
case "help":
|
|
154
|
+
case "--help":
|
|
155
|
+
case "-h":
|
|
156
|
+
printUsage();
|
|
157
|
+
return 0;
|
|
158
|
+
default:
|
|
159
|
+
console.error(`Unknown changelog subcommand: ${sub}\n`);
|
|
160
|
+
printUsage();
|
|
161
|
+
return 1;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Re-export header for callers that want to seed an empty CHANGELOG.md.
|
|
165
|
+
export { CHANGELOG_HEADER };
|
|
166
|
+
//# sourceMappingURL=changelog.js.map
|