@agent-native/core 0.85.5 → 0.85.7
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/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/AssistantChat.tsx +1 -1
- package/corpus/core/src/client/use-pinch-zoom.ts +76 -11
- package/corpus/core/src/collab/presence.ts +63 -3
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +245 -77
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +190 -13
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +16 -4
- package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +46 -3
- package/corpus/templates/design/AGENTS.md +40 -4
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +20 -73
- package/corpus/templates/design/actions/apply-motion-edit.ts +29 -2
- package/corpus/templates/design/actions/apply-visual-edit.ts +4 -2
- package/corpus/templates/design/actions/connect-localhost.ts +25 -18
- package/corpus/templates/design/actions/edit-design.ts +5 -3
- package/corpus/templates/design/actions/export-pdf.ts +8 -1
- package/corpus/templates/design/actions/export-zip.ts +10 -1
- package/corpus/templates/design/actions/get-motion-timeline.ts +26 -20
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +10 -0
- package/corpus/templates/design/actions/insert-asset.ts +190 -7
- package/corpus/templates/design/actions/open-visual-edit.ts +27 -5
- package/corpus/templates/design/actions/present-design-variants.ts +12 -8
- package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +18 -14
- package/corpus/templates/design/actions/run-design-audit.ts +7 -4
- package/corpus/templates/design/actions/write-local-file.ts +47 -22
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +221 -66
- package/corpus/templates/design/app/components/design/EditPanel.tsx +650 -237
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +526 -127
- package/corpus/templates/design/app/components/design/MotionDock.tsx +234 -46
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1520 -410
- package/corpus/templates/design/app/components/design/StatesPanel.tsx +25 -2
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +640 -72
- package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +605 -0
- package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +50 -26
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +16 -4
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +90 -103
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +111 -5
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +13 -2
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +42 -2
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +11 -2
- package/corpus/templates/design/app/components/design/types.ts +16 -0
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +24 -6
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +15 -1
- package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +77 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/design/app/i18n-data.ts +18 -0
- package/corpus/templates/design/app/lib/design-import.ts +95 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +4015 -840
- package/corpus/templates/design/changelog/2026-07-02-creating-two-frames-in-a-row-no-longer-freezes-and-reloads-t.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-canvas-interactions-now-match-figma-rotation-aware-resizing-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-design-retries-stalled-screen-edits-with-a-smaller-safer-fol.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-inspector-fixes-mixed-selections-show-mixed-instead-of-wrong.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-keyframe-timeline-works-reliably-drag-keyframes-smoothly-pic.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-layers-panel-matches-figma-top-layer-on-top-drag-with-auto-s.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-much-faster-editor-smooth-dragging-zooming-and-panel-updates.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-pen-tool-refinements-click-the-first-point-to-close-with-a-d.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-text-editing-enter-adds-a-line-break-international-ime-typin.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-undo-and-redo-are-dependable-across-agent-edits-screen-switc.md +6 -0
- package/corpus/templates/design/server/lib/design-export.ts +43 -1
- package/corpus/templates/design/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/design/shared/board-file.ts +25 -5
- package/corpus/templates/design/shared/canvas-math.ts +754 -9
- package/corpus/templates/design/shared/code-layer.ts +304 -26
- package/corpus/templates/design/shared/color-utils.ts +84 -0
- package/corpus/templates/design/shared/design-source-capabilities.ts +16 -7
- package/corpus/templates/design/shared/motion-compiler.ts +75 -31
- package/corpus/templates/design/shared/motion-timeline.ts +335 -0
- package/corpus/templates/design/shared/pen-path.ts +200 -23
- package/dist/client/AssistantChat.js +1 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/use-pinch-zoom.d.ts.map +1 -1
- package/dist/client/use-pinch-zoom.js +76 -11
- package/dist/client/use-pinch-zoom.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/presence.d.ts.map +1 -1
- package/dist/collab/presence.js +54 -3
- package/dist/collab/presence.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/observability/routes.d.ts +2 -2
- package/dist/secrets/routes.d.ts +3 -3
- package/package.json +1 -1
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.85.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b2e1b6c: Fix presence local-echo re-renders and coalesce pinch-zoom updates through requestAnimationFrame. `usePresence` no longer re-derives and re-renders subscribers when an awareness "change" event only reflects the local client's own state (e.g. cursor/selection echoes), and `usePinchZoom` now batches wheel and touch pinch zoom updates to at most one state update per animation frame instead of one per input event. When multiple wheel events land in the same animation frame, the cursor-anchored scroll compensation now accumulates across all of them (matching the pre-batching, one-event-at-a-time result) instead of anchoring later events in the burst against the stale pre-burst scroll position.
|
|
8
|
+
|
|
9
|
+
## 0.85.6
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- be6d307: Make stalled chat auto-continues change strategy instead of repeating oversized action inputs.
|
|
14
|
+
|
|
3
15
|
## 0.85.5
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.85.
|
|
3
|
+
"version": "0.85.7",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -244,7 +244,7 @@ const ACTIVE_RUN_POLL_INTERVAL_MS = 150;
|
|
|
244
244
|
const AUTO_RESUME_STATUS_TIMEOUT_MS = 30_000;
|
|
245
245
|
const MAX_RECONNECT_AUTO_RECOVERIES = 3;
|
|
246
246
|
const RECONNECT_NO_PROGRESS_CONTINUE_MESSAGE =
|
|
247
|
-
"Continue from where you stopped. Use the partial work above, verify what succeeded, and finish the original request. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. Prefer dedicated app actions over raw database edits when they exist.";
|
|
247
|
+
"Continue from where you stopped. Use the partial work above, verify what succeeded, and finish the original request. If the last visible step was preparing an app action and no tool result was returned, treat that action input as stalled or too large: change strategy, use a smaller bounded input, and preserve optional details as visible affordances instead of repeating the same giant action. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. Prefer dedicated app actions over raw database edits when they exist.";
|
|
248
248
|
// How long a single activity (model call, tool prep, long tool) must stay
|
|
249
249
|
// in-flight before its label is surfaced in the running indicator. Below this
|
|
250
250
|
// the indicator stays a steady "Thinking" so normal fast turns don't flicker
|
|
@@ -55,11 +55,57 @@ export function usePinchZoom({
|
|
|
55
55
|
|
|
56
56
|
const clamp = (n: number) => Math.max(min, Math.min(max, n));
|
|
57
57
|
|
|
58
|
+
// rAF coalescing: multiple wheel/pointermove events can fire per frame
|
|
59
|
+
// (trackpad pinch and touch pinch both deliver many events between
|
|
60
|
+
// paints). Instead of calling setZoom() synchronously per event — which
|
|
61
|
+
// schedules a React re-render per event — stash the latest pending zoom
|
|
62
|
+
// (and its cursor-anchored scroll delta) in a ref and flush once per
|
|
63
|
+
// animation frame with the last-wins value. This preserves the exact
|
|
64
|
+
// zoom-to-cursor math; it just applies it at most once per frame.
|
|
65
|
+
//
|
|
66
|
+
// Within a burst the DOM's real scrollLeft/scrollTop do NOT move until
|
|
67
|
+
// flush() runs, so per-event math must not read them directly — every
|
|
68
|
+
// event after the first in the same frame would anchor against the
|
|
69
|
+
// pre-burst scroll position instead of where the (not-yet-committed)
|
|
70
|
+
// previous events in the burst would have scrolled to. Track a simulated
|
|
71
|
+
// running scroll position (`simScrollLeft`/`simScrollTop`, seeded from the
|
|
72
|
+
// real scroll position when a new burst starts) and use that as the
|
|
73
|
+
// anchor base, so each event's math composes exactly as if the prior
|
|
74
|
+
// events in the burst had already been applied — matching the
|
|
75
|
+
// pre-coalescing, one-setZoom-per-event behavior.
|
|
76
|
+
let pendingZoom: number | null = null;
|
|
77
|
+
let pendingScrollDelta: { dx: number; dy: number } | null = null;
|
|
78
|
+
let simScrollLeft = 0;
|
|
79
|
+
let simScrollTop = 0;
|
|
80
|
+
let rafId: number | null = null;
|
|
81
|
+
|
|
82
|
+
const flush = () => {
|
|
83
|
+
rafId = null;
|
|
84
|
+
if (pendingZoom === null) return;
|
|
85
|
+
const nextZoom = pendingZoom;
|
|
86
|
+
const scrollDelta = pendingScrollDelta;
|
|
87
|
+
pendingZoom = null;
|
|
88
|
+
pendingScrollDelta = null;
|
|
89
|
+
setZoomRef.current(nextZoom);
|
|
90
|
+
if (scrollDelta) {
|
|
91
|
+
container.scrollLeft += scrollDelta.dx;
|
|
92
|
+
container.scrollTop += scrollDelta.dy;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const scheduleFlush = () => {
|
|
97
|
+
if (rafId !== null) return;
|
|
98
|
+
rafId = requestAnimationFrame(flush);
|
|
99
|
+
};
|
|
100
|
+
|
|
58
101
|
const handleWheel = (e: WheelEvent) => {
|
|
59
102
|
if (!(e.ctrlKey || e.metaKey)) return;
|
|
60
103
|
e.preventDefault();
|
|
61
104
|
|
|
62
|
-
|
|
105
|
+
// Use the latest not-yet-applied zoom (if a flush is pending) so rapid
|
|
106
|
+
// wheel events within the same frame compound correctly instead of
|
|
107
|
+
// each computing off the last-committed React state.
|
|
108
|
+
const currentZoom = pendingZoom ?? zoomRef.current;
|
|
63
109
|
const clampedDelta = Math.max(-50, Math.min(50, e.deltaY));
|
|
64
110
|
const factor = Math.exp(-clampedDelta * 0.01);
|
|
65
111
|
const nextZoom = clamp(currentZoom * factor);
|
|
@@ -67,20 +113,33 @@ export function usePinchZoom({
|
|
|
67
113
|
if (nextZoom === currentZoom) return;
|
|
68
114
|
|
|
69
115
|
if (zoomToCursor) {
|
|
116
|
+
// Starting a new burst (nothing pending yet): seed the simulated
|
|
117
|
+
// scroll position from the container's real, currently-committed
|
|
118
|
+
// scroll offset.
|
|
119
|
+
if (pendingScrollDelta === null) {
|
|
120
|
+
simScrollLeft = container.scrollLeft;
|
|
121
|
+
simScrollTop = container.scrollTop;
|
|
122
|
+
}
|
|
70
123
|
const rect = container.getBoundingClientRect();
|
|
71
|
-
const cx = e.clientX - rect.left +
|
|
72
|
-
const cy = e.clientY - rect.top +
|
|
124
|
+
const cx = e.clientX - rect.left + simScrollLeft;
|
|
125
|
+
const cy = e.clientY - rect.top + simScrollTop;
|
|
73
126
|
const ratio = nextZoom / currentZoom;
|
|
74
127
|
const dx = cx * (ratio - 1);
|
|
75
128
|
const dy = cy * (ratio - 1);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
129
|
+
// Advance the simulated scroll position so the next event in this
|
|
130
|
+
// same burst anchors against where this event would have left it.
|
|
131
|
+
simScrollLeft += dx;
|
|
132
|
+
simScrollTop += dy;
|
|
133
|
+
pendingZoom = nextZoom;
|
|
134
|
+
const prevDelta = pendingScrollDelta;
|
|
135
|
+
pendingScrollDelta = {
|
|
136
|
+
dx: (prevDelta?.dx ?? 0) + dx,
|
|
137
|
+
dy: (prevDelta?.dy ?? 0) + dy,
|
|
138
|
+
};
|
|
81
139
|
} else {
|
|
82
|
-
|
|
140
|
+
pendingZoom = nextZoom;
|
|
83
141
|
}
|
|
142
|
+
scheduleFlush();
|
|
84
143
|
};
|
|
85
144
|
|
|
86
145
|
const activePointers = new Map<number, { x: number; y: number }>();
|
|
@@ -105,8 +164,11 @@ export function usePinchZoom({
|
|
|
105
164
|
const [p1, p2] = Array.from(activePointers.values());
|
|
106
165
|
const distance = Math.hypot(p2.x - p1.x, p2.y - p1.y);
|
|
107
166
|
const nextZoom = clamp(initialZoom * (distance / initialDistance));
|
|
108
|
-
if (nextZoom !== zoomRef.current) {
|
|
109
|
-
|
|
167
|
+
if (nextZoom !== (pendingZoom ?? zoomRef.current)) {
|
|
168
|
+
// Touch pinch has no cursor-anchoring math, so last-wins is simply
|
|
169
|
+
// the newest zoom value — no scroll delta to accumulate.
|
|
170
|
+
pendingZoom = nextZoom;
|
|
171
|
+
scheduleFlush();
|
|
110
172
|
}
|
|
111
173
|
e.preventDefault();
|
|
112
174
|
}
|
|
@@ -132,6 +194,9 @@ export function usePinchZoom({
|
|
|
132
194
|
container.removeEventListener("pointermove", handlePointerMove);
|
|
133
195
|
container.removeEventListener("pointerup", handlePointerEnd);
|
|
134
196
|
container.removeEventListener("pointercancel", handlePointerEnd);
|
|
197
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
198
|
+
pendingZoom = null;
|
|
199
|
+
pendingScrollDelta = null;
|
|
135
200
|
};
|
|
136
201
|
}, [containerRef, enabled, min, max, zoomToCursor]);
|
|
137
202
|
}
|
|
@@ -63,6 +63,40 @@ export function usePresence(
|
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
// Keep the last derived snapshot so genuinely no-op change events (e.g. a
|
|
67
|
+
// local-only awareness field flip that doesn't affect any remote entry)
|
|
68
|
+
// can bail out without triggering a subscriber re-render.
|
|
69
|
+
let lastOthers: OtherPresence[] = [];
|
|
70
|
+
|
|
71
|
+
function shallowEqualOthers(
|
|
72
|
+
a: readonly OtherPresence[],
|
|
73
|
+
b: readonly OtherPresence[],
|
|
74
|
+
): boolean {
|
|
75
|
+
if (a === b) return true;
|
|
76
|
+
if (a.length !== b.length) return false;
|
|
77
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
78
|
+
const left = a[i]!;
|
|
79
|
+
const right = b[i]!;
|
|
80
|
+
if (left === right) continue;
|
|
81
|
+
if (
|
|
82
|
+
left.clientId !== right.clientId ||
|
|
83
|
+
left.isAgent !== right.isAgent ||
|
|
84
|
+
left.user.name !== right.user.name ||
|
|
85
|
+
left.user.email !== right.user.email ||
|
|
86
|
+
left.user.color !== right.user.color
|
|
87
|
+
) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
// Compare presence payloads with a stable JSON.stringify — presence
|
|
91
|
+
// fields (cursor/selection/viewport) are small JSON-safe records, so
|
|
92
|
+
// this is cheap and avoids a re-render when nothing actually changed.
|
|
93
|
+
if (JSON.stringify(left.presence) !== JSON.stringify(right.presence)) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
|
|
66
100
|
function derive(): OtherPresence[] {
|
|
67
101
|
const result: OtherPresence[] = [];
|
|
68
102
|
awareness!.getStates().forEach((state, clientId) => {
|
|
@@ -100,12 +134,38 @@ export function usePresence(
|
|
|
100
134
|
return result;
|
|
101
135
|
}
|
|
102
136
|
|
|
103
|
-
function onAwarenessChange(
|
|
104
|
-
|
|
137
|
+
function onAwarenessChange(changes?: {
|
|
138
|
+
added: number[];
|
|
139
|
+
updated: number[];
|
|
140
|
+
removed: number[];
|
|
141
|
+
}) {
|
|
142
|
+
// The awareness "change" event fires for local-only state edits too
|
|
143
|
+
// (e.g. this hook's own setPresence() calls, or the doc's
|
|
144
|
+
// activeFileId/visible fields). When every changed client id is the
|
|
145
|
+
// local client, the derived `others` array (which excludes the local
|
|
146
|
+
// client) cannot have changed, so skip the re-render entirely.
|
|
147
|
+
if (changes) {
|
|
148
|
+
const changedIds = [
|
|
149
|
+
...changes.added,
|
|
150
|
+
...changes.updated,
|
|
151
|
+
...changes.removed,
|
|
152
|
+
];
|
|
153
|
+
if (
|
|
154
|
+
changedIds.length > 0 &&
|
|
155
|
+
changedIds.every((id) => id === localClientId)
|
|
156
|
+
) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const next = derive();
|
|
161
|
+
if (shallowEqualOthers(lastOthers, next)) return;
|
|
162
|
+
lastOthers = next;
|
|
163
|
+
setOthers(next);
|
|
105
164
|
}
|
|
106
165
|
|
|
107
166
|
// Derive immediately.
|
|
108
|
-
|
|
167
|
+
lastOthers = derive();
|
|
168
|
+
setOthers(lastOthers);
|
|
109
169
|
awareness.on("change", onAwarenessChange);
|
|
110
170
|
return () => {
|
|
111
171
|
awareness.off("change", onAwarenessChange);
|