@agent-native/core 0.207.1 → 0.207.2-nightly-20261013011333
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/dist/agent/production-agent.js +2 -0
- package/dist/cli/design-connect.d.ts +6 -0
- package/dist/cli/design-connect.js +880 -9
- package/dist/client/action-query-cache.d.ts +3 -1
- package/dist/client/action-query-cache.js +628 -161
- package/dist/client/action-query-cache.session-test-fixture.d.ts +49 -0
- package/dist/client/action-query-cache.session-test-fixture.js +151 -0
- package/dist/client/action-query-cache.test-fixtures.d.ts +2 -0
- package/dist/client/action-query-cache.test-fixtures.js +56 -0
- package/dist/client/motion-text.css +3 -0
- package/dist/client/motion-text.d.ts +38 -0
- package/dist/client/motion-text.js +551 -0
- package/dist/client/org/hooks.d.ts +3 -1
- package/dist/client/org/hooks.js +8 -2
- package/dist/client/route-chunk-recovery.d.ts +2 -0
- package/dist/client/route-chunk-recovery.js +11 -0
- package/dist/client/use-action.d.ts +10 -2
- package/dist/client/use-action.js +81 -12
- package/dist/client/use-settings-shortcut.js +8 -3
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/extensions/fetch-tool.js +8 -2
- package/dist/extensions/routes.js +7 -3
- package/dist/extensions/web-content.js +17 -2
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/mcp/build-server.js +5 -0
- package/dist/observability/routes.d.ts +4 -4
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +5 -5
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +2 -2
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/visual-edit-bridge-capability.d.ts +26 -0
- package/dist/server/visual-edit-bridge-capability.js +233 -0
- package/dist/shared/motion-easing.d.ts +6 -0
- package/dist/shared/motion-easing.js +109 -0
- package/dist/shared/motion-source-node-id.d.ts +3 -0
- package/dist/shared/motion-source-node-id.js +12 -0
- package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +35 -36
- package/dist/triggers/actions/manage-automation.d.ts +5 -5
- package/dist/vite/client.js +2 -0
- package/dist/vite/motion-source-provenance-plugin.d.ts +3 -0
- package/dist/vite/motion-source-provenance-plugin.js +339 -0
- package/package.json +14 -5
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +35 -36
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export const LOCALHOST_BRIDGE_OPERATION_CAPABILITY_FIELD = "bridgeOperationCapability";
|
|
4
|
+
const CAPABILITY_TTL_MS = 120_000;
|
|
5
|
+
const MAX_CLOCK_SKEW_MS = 30_000;
|
|
6
|
+
const MAX_CANONICAL_BODY_BYTES = 8 * 1024 * 1024;
|
|
7
|
+
const MAX_JSON_DEPTH = 64;
|
|
8
|
+
const CAPABILITY_DOMAIN = "agent-native:visual-edit-bridge-operation:v2\0";
|
|
9
|
+
const AUDIENCE_DOMAIN = "agent-native:visual-edit-bridge-audience:v1\0";
|
|
10
|
+
function base64UrlEncode(value) {
|
|
11
|
+
return (typeof value === "string" ? Buffer.from(value, "utf8") : value)
|
|
12
|
+
.toString("base64")
|
|
13
|
+
.replace(/\+/g, "-")
|
|
14
|
+
.replace(/\//g, "_")
|
|
15
|
+
.replace(/=+$/g, "");
|
|
16
|
+
}
|
|
17
|
+
function base64UrlDecode(value) {
|
|
18
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value))
|
|
19
|
+
return null;
|
|
20
|
+
const decoded = Buffer.from(value.replace(/-/g, "+").replace(/_/g, "/") +
|
|
21
|
+
"=".repeat((4 - (value.length % 4)) % 4), "base64");
|
|
22
|
+
return base64UrlEncode(decoded) === value ? decoded : null;
|
|
23
|
+
}
|
|
24
|
+
function canonicalJson(value, depth = 0, root = false) {
|
|
25
|
+
if (depth > MAX_JSON_DEPTH) {
|
|
26
|
+
throw new Error("bridge capability body exceeds the JSON depth limit");
|
|
27
|
+
}
|
|
28
|
+
if (value === null)
|
|
29
|
+
return "null";
|
|
30
|
+
if (typeof value === "string" || typeof value === "boolean") {
|
|
31
|
+
return JSON.stringify(value);
|
|
32
|
+
}
|
|
33
|
+
if (typeof value === "number") {
|
|
34
|
+
if (!Number.isFinite(value)) {
|
|
35
|
+
throw new Error("bridge capability body contains a non-finite number");
|
|
36
|
+
}
|
|
37
|
+
return JSON.stringify(value);
|
|
38
|
+
}
|
|
39
|
+
if (Array.isArray(value)) {
|
|
40
|
+
if (Object.getPrototypeOf(value) !== Array.prototype) {
|
|
41
|
+
throw new Error("bridge capability body contains a non-JSON array");
|
|
42
|
+
}
|
|
43
|
+
const keys = Reflect.ownKeys(value);
|
|
44
|
+
if (keys.length !== value.length + 1 ||
|
|
45
|
+
keys.some((key) => typeof key !== "string" ||
|
|
46
|
+
(key !== "length" &&
|
|
47
|
+
(!/^(0|[1-9]\d*)$/.test(key) || Number(key) >= value.length)))) {
|
|
48
|
+
throw new Error("bridge capability body contains a non-JSON array");
|
|
49
|
+
}
|
|
50
|
+
const items = [];
|
|
51
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
52
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
53
|
+
if (!descriptor || !("value" in descriptor)) {
|
|
54
|
+
throw new Error("bridge capability body contains a non-JSON array");
|
|
55
|
+
}
|
|
56
|
+
items.push(canonicalJson(descriptor.value, depth + 1));
|
|
57
|
+
}
|
|
58
|
+
return `[${items.join(",")}]`;
|
|
59
|
+
}
|
|
60
|
+
if (typeof value !== "object") {
|
|
61
|
+
throw new Error("bridge capability body contains a non-JSON value");
|
|
62
|
+
}
|
|
63
|
+
const prototype = Object.getPrototypeOf(value);
|
|
64
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
65
|
+
throw new Error("bridge capability body contains a non-JSON object");
|
|
66
|
+
}
|
|
67
|
+
const keys = Reflect.ownKeys(value);
|
|
68
|
+
if (keys.some((key) => typeof key !== "string")) {
|
|
69
|
+
throw new Error("bridge capability body contains a non-JSON object");
|
|
70
|
+
}
|
|
71
|
+
const entries = keys
|
|
72
|
+
.filter((key) => !(root && key === LOCALHOST_BRIDGE_OPERATION_CAPABILITY_FIELD))
|
|
73
|
+
.sort()
|
|
74
|
+
.map((key) => {
|
|
75
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
76
|
+
if (!descriptor || !("value" in descriptor)) {
|
|
77
|
+
throw new Error("bridge capability body contains an accessor");
|
|
78
|
+
}
|
|
79
|
+
return `${JSON.stringify(key)}:${canonicalJson(descriptor.value, depth + 1)}`;
|
|
80
|
+
});
|
|
81
|
+
return `{${entries.join(",")}}`;
|
|
82
|
+
}
|
|
83
|
+
function canonicalBodyHash(body) {
|
|
84
|
+
if (body === null ||
|
|
85
|
+
typeof body !== "object" ||
|
|
86
|
+
Array.isArray(body) ||
|
|
87
|
+
(Object.getPrototypeOf(body) !== Object.prototype &&
|
|
88
|
+
Object.getPrototypeOf(body) !== null)) {
|
|
89
|
+
throw new Error("bridge capability body must be a JSON object");
|
|
90
|
+
}
|
|
91
|
+
const canonical = canonicalJson(body, 0, true);
|
|
92
|
+
if (Buffer.byteLength(canonical, "utf8") > MAX_CANONICAL_BODY_BYTES) {
|
|
93
|
+
throw new Error("bridge capability body exceeds the size limit");
|
|
94
|
+
}
|
|
95
|
+
return base64UrlEncode(crypto.createHash("sha256").update(canonical, "utf8").digest());
|
|
96
|
+
}
|
|
97
|
+
function assertOperation(operation) {
|
|
98
|
+
if (typeof operation !== "string" ||
|
|
99
|
+
operation.length === 0 ||
|
|
100
|
+
operation.length > 512) {
|
|
101
|
+
throw new Error("bridge capability operation is invalid");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function canonicalBridgeRootPath(rootPath) {
|
|
105
|
+
if (typeof rootPath !== "string" ||
|
|
106
|
+
rootPath.length === 0 ||
|
|
107
|
+
rootPath !== rootPath.trim() ||
|
|
108
|
+
rootPath.length > 32_768) {
|
|
109
|
+
throw new Error("bridge root path is invalid");
|
|
110
|
+
}
|
|
111
|
+
// Use the platform-independent path implementation for the path syntax so
|
|
112
|
+
// a cloud server and a local Windows CLI derive the same audience.
|
|
113
|
+
if ((/^[A-Za-z]:[\\/]/.test(rootPath) || rootPath.startsWith("\\\\")) &&
|
|
114
|
+
path.win32.isAbsolute(rootPath)) {
|
|
115
|
+
const normalized = path.win32.normalize(rootPath).replace(/\\/g, "/");
|
|
116
|
+
const canonicalRoot = path.win32.parse(rootPath).root.replace(/\\/g, "/");
|
|
117
|
+
return normalized.length > canonicalRoot.length
|
|
118
|
+
? normalized.replace(/\/+$/, "")
|
|
119
|
+
: normalized;
|
|
120
|
+
}
|
|
121
|
+
if (path.posix.isAbsolute(rootPath)) {
|
|
122
|
+
const normalized = path.posix.normalize(rootPath);
|
|
123
|
+
return normalized === "/" ? normalized : normalized.replace(/\/+$/, "");
|
|
124
|
+
}
|
|
125
|
+
throw new Error("bridge root path must be absolute");
|
|
126
|
+
}
|
|
127
|
+
export function createLocalhostBridgeAudience(rootPath) {
|
|
128
|
+
return crypto
|
|
129
|
+
.createHash("sha256")
|
|
130
|
+
.update(AUDIENCE_DOMAIN, "utf8")
|
|
131
|
+
.update(canonicalBridgeRootPath(rootPath), "utf8")
|
|
132
|
+
.digest("base64url");
|
|
133
|
+
}
|
|
134
|
+
function signPayload(bridgeToken, encodedPayload) {
|
|
135
|
+
return base64UrlEncode(crypto
|
|
136
|
+
.createHmac("sha256", bridgeToken)
|
|
137
|
+
.update(CAPABILITY_DOMAIN, "utf8")
|
|
138
|
+
.update(encodedPayload, "ascii")
|
|
139
|
+
.digest());
|
|
140
|
+
}
|
|
141
|
+
export function issueLocalhostBridgeOperationCapability({ bridgeToken, audience, operation, body, issuedAt = Date.now(), }) {
|
|
142
|
+
if (typeof bridgeToken !== "string" || bridgeToken.length === 0) {
|
|
143
|
+
throw new Error("bridge token is required");
|
|
144
|
+
}
|
|
145
|
+
if (!/^[A-Za-z0-9_-]{43}$/.test(audience)) {
|
|
146
|
+
throw new Error("bridge capability audience is invalid");
|
|
147
|
+
}
|
|
148
|
+
assertOperation(operation);
|
|
149
|
+
if (!Number.isSafeInteger(issuedAt) || issuedAt <= 0) {
|
|
150
|
+
throw new Error("bridge capability issuance time is invalid");
|
|
151
|
+
}
|
|
152
|
+
const claims = {
|
|
153
|
+
version: 2,
|
|
154
|
+
audience,
|
|
155
|
+
operation,
|
|
156
|
+
issuedAt,
|
|
157
|
+
expiresAt: issuedAt + CAPABILITY_TTL_MS,
|
|
158
|
+
nonce: base64UrlEncode(crypto.randomBytes(32)),
|
|
159
|
+
bodyHash: canonicalBodyHash(body),
|
|
160
|
+
};
|
|
161
|
+
if (!Number.isSafeInteger(claims.expiresAt)) {
|
|
162
|
+
throw new Error("bridge capability expiration time is invalid");
|
|
163
|
+
}
|
|
164
|
+
const encodedPayload = base64UrlEncode(JSON.stringify(claims));
|
|
165
|
+
return {
|
|
166
|
+
capability: `${encodedPayload}.${signPayload(bridgeToken, encodedPayload)}`,
|
|
167
|
+
nonce: claims.nonce,
|
|
168
|
+
expiresAt: claims.expiresAt,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
export function verifyLocalhostBridgeOperationCapability({ bridgeToken, audience, operation, body, capability, now = Date.now(), }) {
|
|
172
|
+
try {
|
|
173
|
+
if (typeof bridgeToken !== "string" ||
|
|
174
|
+
bridgeToken.length === 0 ||
|
|
175
|
+
typeof capability !== "string" ||
|
|
176
|
+
capability.length > 4096 ||
|
|
177
|
+
!/^[A-Za-z0-9_-]{43}$/.test(audience) ||
|
|
178
|
+
!Number.isSafeInteger(now)) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
assertOperation(operation);
|
|
182
|
+
const segments = capability.split(".");
|
|
183
|
+
if (segments.length !== 2)
|
|
184
|
+
return null;
|
|
185
|
+
const payloadBytes = base64UrlDecode(segments[0] ?? "");
|
|
186
|
+
const signature = base64UrlDecode(segments[1] ?? "");
|
|
187
|
+
if (!payloadBytes || !signature || signature.length !== 32)
|
|
188
|
+
return null;
|
|
189
|
+
const expectedSignature = base64UrlDecode(signPayload(bridgeToken, segments[0] ?? ""));
|
|
190
|
+
if (!expectedSignature ||
|
|
191
|
+
!crypto.timingSafeEqual(signature, expectedSignature)) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
const claims = JSON.parse(payloadBytes.toString("utf8"));
|
|
195
|
+
if (claims.version !== 2 ||
|
|
196
|
+
claims.audience !== audience ||
|
|
197
|
+
claims.operation !== operation ||
|
|
198
|
+
!Number.isSafeInteger(claims.issuedAt) ||
|
|
199
|
+
!Number.isSafeInteger(claims.expiresAt) ||
|
|
200
|
+
typeof claims.nonce !== "string" ||
|
|
201
|
+
typeof claims.bodyHash !== "string" ||
|
|
202
|
+
claims.expiresAt !== claims.issuedAt + CAPABILITY_TTL_MS ||
|
|
203
|
+
claims.issuedAt > now + MAX_CLOCK_SKEW_MS ||
|
|
204
|
+
claims.expiresAt <= now ||
|
|
205
|
+
!/^[A-Za-z0-9_-]{43}$/.test(claims.nonce) ||
|
|
206
|
+
!/^[A-Za-z0-9_-]{43}$/.test(claims.bodyHash)) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
const allowedKeys = [
|
|
210
|
+
"version",
|
|
211
|
+
"audience",
|
|
212
|
+
"operation",
|
|
213
|
+
"issuedAt",
|
|
214
|
+
"expiresAt",
|
|
215
|
+
"nonce",
|
|
216
|
+
"bodyHash",
|
|
217
|
+
];
|
|
218
|
+
if (Object.keys(claims).length !== allowedKeys.length ||
|
|
219
|
+
Object.keys(claims).some((key) => !allowedKeys.includes(key))) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
if (canonicalBodyHash(body) !== claims.bodyHash)
|
|
223
|
+
return null;
|
|
224
|
+
return {
|
|
225
|
+
nonce: claims.nonce,
|
|
226
|
+
expiresAt: claims.expiresAt,
|
|
227
|
+
};
|
|
228
|
+
// coercion-ok: malformed capability claims are an explicit authorization denial; null never grants access.
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function motionEaseVariableName(ease: string): string | null;
|
|
2
|
+
export declare function isMotionEaseVariableReference(ease: string): boolean;
|
|
3
|
+
/** True only for timing functions accepted by the Motion authoring model. */
|
|
4
|
+
export declare function isValidMotionEase(ease: string): boolean;
|
|
5
|
+
/** Resolves Motion variables and spring tokens to easing strings accepted by WAAPI. */
|
|
6
|
+
export declare function resolveMotionEaseForWebAnimations(ease: string, readCssVariable: (name: string) => string): string;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const CSS_NUMBER = String.raw `[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?`;
|
|
2
|
+
const CSS_PERCENTAGE = String.raw `${CSS_NUMBER}%`;
|
|
3
|
+
const MOTION_EASING_VARIABLE_REFERENCE_RE = /^var\(--an-motion-ease-([a-z0-9][a-z0-9-]{0,63})\)$/;
|
|
4
|
+
const SPRING_EASING_RE = /^spring\(\s*([+-]?(?:\d+\.?\d*|\.\d+))\s*(?:,\s*([+-]?(?:\d+\.?\d*|\.\d+))\s*)?\)$/i;
|
|
5
|
+
export function motionEaseVariableName(ease) {
|
|
6
|
+
const match = MOTION_EASING_VARIABLE_REFERENCE_RE.exec(ease);
|
|
7
|
+
return match ? `--an-motion-ease-${match[1]}` : null;
|
|
8
|
+
}
|
|
9
|
+
export function isMotionEaseVariableReference(ease) {
|
|
10
|
+
return motionEaseVariableName(ease) !== null;
|
|
11
|
+
}
|
|
12
|
+
/** True only for timing functions accepted by the Motion authoring model. */
|
|
13
|
+
export function isValidMotionEase(ease) {
|
|
14
|
+
if (isMotionEaseVariableReference(ease))
|
|
15
|
+
return true;
|
|
16
|
+
const value = ease.trim();
|
|
17
|
+
const keyword = value.toLowerCase();
|
|
18
|
+
if ([
|
|
19
|
+
"linear",
|
|
20
|
+
"ease",
|
|
21
|
+
"ease-in",
|
|
22
|
+
"ease-out",
|
|
23
|
+
"ease-in-out",
|
|
24
|
+
"step-start",
|
|
25
|
+
"step-end",
|
|
26
|
+
].includes(keyword)) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
const spring = SPRING_EASING_RE.exec(value);
|
|
30
|
+
if (keyword === "spring")
|
|
31
|
+
return true;
|
|
32
|
+
if (spring) {
|
|
33
|
+
const bounce = Number(spring[1]);
|
|
34
|
+
const settle = spring[2] === undefined ? 1 : Number(spring[2]);
|
|
35
|
+
return bounce >= 0 && bounce <= 1 && settle >= 0.05 && settle <= 1;
|
|
36
|
+
}
|
|
37
|
+
if (/^spring/i.test(value))
|
|
38
|
+
return false;
|
|
39
|
+
const bezier = new RegExp(`^cubic-bezier\\(\\s*(${CSS_NUMBER})\\s*,\\s*(${CSS_NUMBER})\\s*,\\s*(${CSS_NUMBER})\\s*,\\s*(${CSS_NUMBER})\\s*\\)$`, "i").exec(value);
|
|
40
|
+
if (bezier) {
|
|
41
|
+
const [, x1, , x2] = bezier;
|
|
42
|
+
return (Number(x1) >= 0 && Number(x1) <= 1 && Number(x2) >= 0 && Number(x2) <= 1);
|
|
43
|
+
}
|
|
44
|
+
const steps = /^steps\(\s*(\d+)\s*(?:,\s*(jump-start|jump-end|jump-none|jump-both|start|end)\s*)?\)$/i.exec(value);
|
|
45
|
+
if (steps) {
|
|
46
|
+
const count = Number(steps[1]);
|
|
47
|
+
const position = steps[2]?.toLowerCase();
|
|
48
|
+
return (count > 0 &&
|
|
49
|
+
Number.isSafeInteger(count) &&
|
|
50
|
+
(position === "jump-none" ? count > 1 : true));
|
|
51
|
+
}
|
|
52
|
+
const linear = /^linear\((.*)\)$/i.exec(value);
|
|
53
|
+
if (!linear)
|
|
54
|
+
return false;
|
|
55
|
+
const stops = linear[1].split(",").map((stop) => stop.trim());
|
|
56
|
+
if (stops.length < 2)
|
|
57
|
+
return false;
|
|
58
|
+
return stops.every((stop) => new RegExp(`^${CSS_NUMBER}(?:\\s+${CSS_PERCENTAGE}(?:\\s+${CSS_PERCENTAGE})?)?$`, "i").test(stop));
|
|
59
|
+
}
|
|
60
|
+
/** Resolves Motion variables and spring tokens to easing strings accepted by WAAPI. */
|
|
61
|
+
export function resolveMotionEaseForWebAnimations(ease, readCssVariable) {
|
|
62
|
+
const variableName = motionEaseVariableName(ease);
|
|
63
|
+
let resolvedEase = ease;
|
|
64
|
+
if (variableName) {
|
|
65
|
+
resolvedEase = readCssVariable(variableName).trim();
|
|
66
|
+
if (!resolvedEase ||
|
|
67
|
+
isMotionEaseVariableReference(resolvedEase) ||
|
|
68
|
+
!isValidMotionEase(resolvedEase)) {
|
|
69
|
+
throw new TypeError(`Motion easing variable "${variableName}" is not defined or does not resolve to a concrete easing.`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (!isValidMotionEase(resolvedEase)) {
|
|
73
|
+
throw new TypeError(`"${resolvedEase}" is not a supported motion easing value.`);
|
|
74
|
+
}
|
|
75
|
+
const normalized = resolvedEase.trim();
|
|
76
|
+
if (normalized.toLowerCase() === "spring") {
|
|
77
|
+
return springToCssLinear(0.25, 1);
|
|
78
|
+
}
|
|
79
|
+
const spring = SPRING_EASING_RE.exec(normalized);
|
|
80
|
+
if (!spring)
|
|
81
|
+
return resolvedEase;
|
|
82
|
+
return springToCssLinear(Number(spring[1]), Number(spring[2] ?? 1));
|
|
83
|
+
}
|
|
84
|
+
function springToCssLinear(bounce, settle) {
|
|
85
|
+
const sampleCount = 16 + Math.round(bounce * 34);
|
|
86
|
+
const stops = Array.from({ length: sampleCount + 1 }, (_, index) => {
|
|
87
|
+
const x = index / sampleCount;
|
|
88
|
+
const value = index === sampleCount ? 1 : sampleSpring(bounce, settle, x);
|
|
89
|
+
return (Math.round(value * 10_000) / 10_000).toString();
|
|
90
|
+
});
|
|
91
|
+
return `linear(${stops.join(", ")})`;
|
|
92
|
+
}
|
|
93
|
+
function sampleSpring(bounce, settle, x) {
|
|
94
|
+
if (x <= 0)
|
|
95
|
+
return 0;
|
|
96
|
+
const u = x / settle;
|
|
97
|
+
if (u >= 1)
|
|
98
|
+
return 1;
|
|
99
|
+
const zeta = Math.min(1, Math.max(0.02, 1 - bounce));
|
|
100
|
+
const omega = Math.log(1 / 0.001) / zeta;
|
|
101
|
+
if (zeta >= 1) {
|
|
102
|
+
return 1 - Math.exp(-omega * u) * (1 + omega * u);
|
|
103
|
+
}
|
|
104
|
+
const omegaD = omega * Math.sqrt(1 - zeta * zeta);
|
|
105
|
+
const decay = Math.exp(-zeta * omega * u);
|
|
106
|
+
return (1 -
|
|
107
|
+
decay *
|
|
108
|
+
(Math.cos(omegaD * u) + ((zeta * omega) / omegaD) * Math.sin(omegaD * u)));
|
|
109
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Stable ID for a host JSX element within its project-relative source module. */
|
|
2
|
+
export function generatedMotionNodeId(modulePath, hostElementOrdinal) {
|
|
3
|
+
let hash = 0xcbf29ce484222325n;
|
|
4
|
+
for (let index = 0; index < modulePath.length; index += 1) {
|
|
5
|
+
hash ^= BigInt(modulePath.charCodeAt(index));
|
|
6
|
+
hash = BigInt.asUintN(64, hash * 0x100000001b3n);
|
|
7
|
+
}
|
|
8
|
+
return `an-${hash.toString(16).padStart(16, "0")}-${hostElementOrdinal}`;
|
|
9
|
+
}
|
|
10
|
+
export function isMotionSourceHostElementTag(tagName) {
|
|
11
|
+
return /^[a-z]/.test(tagName) && tagName !== "script" && tagName !== "style";
|
|
12
|
+
}
|
|
@@ -2,6 +2,7 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
2
2
|
resourceType: string;
|
|
3
3
|
resourceId: string;
|
|
4
4
|
}, {
|
|
5
|
+
role?: undefined;
|
|
5
6
|
ownerEmail: any;
|
|
6
7
|
visibility: any;
|
|
7
8
|
shares: any[];
|
|
@@ -11,7 +12,6 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
11
12
|
supportsGroupShares?: boolean;
|
|
12
13
|
};
|
|
13
14
|
orgId?: undefined;
|
|
14
|
-
role?: undefined;
|
|
15
15
|
agentReadable?: undefined;
|
|
16
16
|
} | {
|
|
17
17
|
ownerEmail: string;
|
|
@@ -19,7 +19,7 @@ Four phases, in order. Phase 0 comes before any investigation, not after.
|
|
|
19
19
|
before investigating any of it.
|
|
20
20
|
1. **Answer the people who answered you.** Older open questions first.
|
|
21
21
|
2. **Fix** what the evidence actually proves, at the owning boundary.
|
|
22
|
-
3. **Reply
|
|
22
|
+
3. **Reply** with useful questions, then recap.
|
|
23
23
|
|
|
24
24
|
Output is fixes. Reply in-thread for every workflow reaction added this run;
|
|
25
25
|
continuing work gets a concrete progress reply, and resolved work gets a final
|
|
@@ -82,9 +82,13 @@ error message, URL, or visible flow is enough to start tracing its owner; don't
|
|
|
82
82
|
wait for details that would not change the reproduction attempt. Phase 2's
|
|
83
83
|
local reproduction procedure applies to all defect reports, not only bashes.
|
|
84
84
|
|
|
85
|
-
If no safe repo-owned fix is evident after
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
If no safe repo-owned fix is evident after reproduction, record the evidence
|
|
86
|
+
limit. For each defect where reporter input changes reproduction or unblocks a
|
|
87
|
+
fix, ask one direct question naming the missing detail or action and why it
|
|
88
|
+
gates the next step. Inspect supplied run IDs, logs, links, and artifacts
|
|
89
|
+
yourself. Keep internal access, config, observability, and deployment gaps
|
|
90
|
+
internal; never ask reporters for developer traces. Do not label the thread
|
|
91
|
+
**Open** instead of asking. After four days unanswered, record **Abandoned - no
|
|
88
92
|
answer in 4 days**.
|
|
89
93
|
|
|
90
94
|
Use **Skipped** only for non-defects, never breakage. **Open - no question**
|
|
@@ -448,9 +452,11 @@ instruction or prompt exception.
|
|
|
448
452
|
|
|
449
453
|
## Phase 3: reply
|
|
450
454
|
|
|
451
|
-
Thank issue reporters for opening it and Slack reporters for sharing. Give
|
|
452
|
-
status
|
|
453
|
-
|
|
455
|
+
Thank issue reporters for opening it and Slack reporters for sharing. Give an
|
|
456
|
+
active status while work continues. If reporter input gates a fix, ask the
|
|
457
|
+
direct question specified in Phase 0; do not substitute **Open**, **pending**,
|
|
458
|
+
or an evidence description. Follow `address-feedback-with-replies` for Slack
|
|
459
|
+
voice. End each Slack reply with `this was sent from a bot.` after its
|
|
454
460
|
plain-language status.
|
|
455
461
|
|
|
456
462
|
Short replies: say the change, limits, and next step. Link merged PRs and say
|
|
@@ -474,32 +480,26 @@ needed. Do not reopen Slack in later runs to reply.
|
|
|
474
480
|
observations may be silent; merged Slack fixes still get the reply above.
|
|
475
481
|
**Shipped** is for upvoted improvements.
|
|
476
482
|
- **In progress** — name continuing work and its owner; ask nothing.
|
|
477
|
-
- **A question** —
|
|
483
|
+
- **A question** — follow the rules below.
|
|
478
484
|
|
|
479
|
-
Unclaimed scope/noise gets an internal recap row.
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
ownership gate; stay out of marked messages and active human work.
|
|
485
|
+
Unclaimed scope/noise gets an internal recap row. Cluster duplicates. Before
|
|
486
|
+
replying, apply the Slack ownership gate; stay out of marked messages and active
|
|
487
|
+
human work.
|
|
483
488
|
|
|
484
|
-
###
|
|
489
|
+
### Ask only answerable questions
|
|
485
490
|
|
|
486
|
-
|
|
487
|
-
|
|
491
|
+
Ask one direct question for each distinct blocked defect when the reporter's
|
|
492
|
+
answer or action changes reproduction or unblocks the fix. There is no per-run
|
|
493
|
+
cap; do not replace a useful question with **Open** or an in-progress status.
|
|
494
|
+
Keep one pending question per thread. After an answer, try the fix before asking
|
|
495
|
+
anything else. Never ask for supplied logs/IDs, internal access/config/tooling,
|
|
496
|
+
subjective choices, or details that do not change the next step. If a
|
|
497
|
+
user-visible link or ID alone blocks reproduction, ask for it and say where to
|
|
498
|
+
find it.
|
|
488
499
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
item, not a message.
|
|
493
|
-
|
|
494
|
-
Never ask for supplied/inspectable evidence, irrelevant IDs/build numbers,
|
|
495
|
-
subjective choices, or internal blockers. If a user-visible link or ID is the
|
|
496
|
-
sole blocker, ask plainly and say where to find it.
|
|
497
|
-
|
|
498
|
-
At most one clarification question may be pending per thread at a time. Once it
|
|
499
|
-
is answered or resolved, attempt the fix; if that exposes a different required
|
|
500
|
-
detail, ask at most one new, non-repeating question. Never stack questions or
|
|
501
|
-
repeat a pending one. If a needed artifact is inaccessible to you, ask for a
|
|
502
|
-
fresh link - not for its contents again.
|
|
500
|
+
If an answer exposes a different required detail, ask at most one new,
|
|
501
|
+
non-repeating question. If an artifact is inaccessible, request a fresh link,
|
|
502
|
+
not its contents.
|
|
503
503
|
|
|
504
504
|
## Verification and identity
|
|
505
505
|
|
|
@@ -563,7 +563,7 @@ Messages: product N · QA N · dev N (total N)
|
|
|
563
563
|
Deployment cursor: <timestamp> · carried active run IDs/rows: <ids/count>
|
|
564
564
|
Release lanes: N inspected · failed/stale N · target verified N
|
|
565
565
|
Reaction-gated skips: N · claimed N · answered N
|
|
566
|
-
Questions asked: N
|
|
566
|
+
Questions asked: N · Dropped at 4 days: N
|
|
567
567
|
Repeats of a prior Fixed claim: N (each with its earlier thread and failed fix)
|
|
568
568
|
Upvoted items in scope: N (built: N)
|
|
569
569
|
|
|
@@ -576,12 +576,11 @@ Tracker: <sheet/export and bounded range> - N rows enumerated, N ledgers complet
|
|
|
576
576
|
Unavailable or unverified: ...
|
|
577
577
|
```
|
|
578
578
|
|
|
579
|
-
`Open - no question`
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
cursor stated.
|
|
579
|
+
`Open - no question` follows reproduction when there is no safe fix and no
|
|
580
|
+
reporter answer or action that changes the next step. Ask when reporter input
|
|
581
|
+
unblocks the fix; keep internal access/tooling blockers internal. Mostly open
|
|
582
|
+
ledgers mean under-asking. Keep `👀`, no `✅`. "Nothing matched" is valid only
|
|
583
|
+
after every source was queried successfully and the cursor is stated.
|
|
585
584
|
|
|
586
585
|
## Related skills
|
|
587
586
|
|
|
@@ -13,8 +13,6 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
13
13
|
executionEngine?: string;
|
|
14
14
|
executionCwd?: string;
|
|
15
15
|
}, {
|
|
16
|
-
deleted?: undefined;
|
|
17
|
-
enabled?: undefined;
|
|
18
16
|
created: boolean;
|
|
19
17
|
name: string;
|
|
20
18
|
scope: "organization" | "personal";
|
|
@@ -25,31 +23,33 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
25
23
|
reasoningEffort: "auto" | "high" | "low" | "max" | "medium" | "minimal" | "none" | "xhigh";
|
|
26
24
|
webhookPath: string;
|
|
27
25
|
nextRun: string;
|
|
26
|
+
deleted?: undefined;
|
|
27
|
+
enabled?: undefined;
|
|
28
28
|
executionHostId?: undefined;
|
|
29
29
|
executionEngine?: undefined;
|
|
30
30
|
executionCwd?: undefined;
|
|
31
31
|
} | {
|
|
32
32
|
scope?: undefined;
|
|
33
|
-
enabled?: undefined;
|
|
34
|
-
nextRun?: undefined;
|
|
35
33
|
created?: undefined;
|
|
36
34
|
triggerType?: undefined;
|
|
37
35
|
event?: undefined;
|
|
38
36
|
deleted: boolean;
|
|
39
37
|
name: string;
|
|
38
|
+
enabled?: undefined;
|
|
40
39
|
schedule?: undefined;
|
|
41
40
|
timezone?: undefined;
|
|
42
41
|
reasoningEffort?: undefined;
|
|
43
42
|
executionHostId?: undefined;
|
|
44
43
|
executionEngine?: undefined;
|
|
45
44
|
executionCwd?: undefined;
|
|
45
|
+
nextRun?: undefined;
|
|
46
46
|
webhookPath?: undefined;
|
|
47
47
|
} | {
|
|
48
48
|
scope?: undefined;
|
|
49
|
-
deleted?: undefined;
|
|
50
49
|
created?: undefined;
|
|
51
50
|
triggerType?: undefined;
|
|
52
51
|
event?: undefined;
|
|
52
|
+
deleted?: undefined;
|
|
53
53
|
name: string;
|
|
54
54
|
enabled: boolean;
|
|
55
55
|
schedule: string;
|
package/dist/vite/client.js
CHANGED
|
@@ -29,6 +29,7 @@ import { actionTypesPlugin } from "./action-types-plugin.js";
|
|
|
29
29
|
import { createAgentNativeConfigContext, loadAgentNativeConfigFile, loadWorkspaceAgentNativeConfigFile, readAgentNativeJsonConfig, resolveFirstRunOnboardingBuildReplacement, resolveHarnessBuildReplacement, writeAgentNativeBuildConfigMarker, } from "./agent-native-config-loader.js";
|
|
30
30
|
import { agentsBundlePlugin } from "./agents-bundle-plugin.js";
|
|
31
31
|
import { migrationDiagnosticPlugin } from "./migration-diagnostic-plugin.js";
|
|
32
|
+
import { motionSourceProvenancePlugin } from "./motion-source-provenance-plugin.js";
|
|
32
33
|
import { resolveAgentNativePackageVersions } from "./package-versions.js";
|
|
33
34
|
import { createSentrySourceMapUploadPlugin, isSentrySourceMapUploadEnabled, } from "./sentry-source-maps.js";
|
|
34
35
|
const require = createRequire(import.meta.url);
|
|
@@ -3603,6 +3604,7 @@ function createAgentNativePlugins(options, { command, includeReactTransform, use
|
|
|
3603
3604
|
: [];
|
|
3604
3605
|
return [
|
|
3605
3606
|
migrationDiagnosticPlugin(),
|
|
3607
|
+
motionSourceProvenancePlugin(),
|
|
3606
3608
|
persistent5xxRecovery(),
|
|
3607
3609
|
presetMarkerPlugin,
|
|
3608
3610
|
ssrStubPlugin([
|