@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,339 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { parse } from "@babel/parser";
|
|
5
|
+
import MagicString from "magic-string";
|
|
6
|
+
import { parse as parseHtml } from "parse5";
|
|
7
|
+
import { generatedMotionNodeId, isMotionSourceHostElementTag, } from "../shared/motion-source-node-id.js";
|
|
8
|
+
const NODE_ID_ATTRIBUTE = "data-agent-native-node-id";
|
|
9
|
+
const SOURCE_FILE_ATTRIBUTE = "data-agent-native-motion-source-file";
|
|
10
|
+
const SOURCE_HASH_ATTRIBUTE = "data-agent-native-motion-source-hash";
|
|
11
|
+
const HTML_NODE_ID_ATTRIBUTE = "data-agent-native-node-id";
|
|
12
|
+
function escapeHtmlAttribute(value) {
|
|
13
|
+
return value
|
|
14
|
+
.replaceAll("&", "&")
|
|
15
|
+
.replaceAll('"', """)
|
|
16
|
+
.replaceAll("<", "<")
|
|
17
|
+
.replaceAll(">", ">");
|
|
18
|
+
}
|
|
19
|
+
function instrumentMotionHtmlProvenance(args) {
|
|
20
|
+
const parseErrors = [];
|
|
21
|
+
const document = parseHtml(args.html, {
|
|
22
|
+
sourceCodeLocationInfo: true,
|
|
23
|
+
onParseError(error) {
|
|
24
|
+
parseErrors.push(error);
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
if (parseErrors.length > 0)
|
|
28
|
+
return null;
|
|
29
|
+
const hostNodes = [];
|
|
30
|
+
const visit = (node) => {
|
|
31
|
+
if (node.tagName && isMotionSourceHostElementTag(node.tagName)) {
|
|
32
|
+
hostNodes.push({ node, ordinal: hostNodes.length });
|
|
33
|
+
}
|
|
34
|
+
for (const child of node.childNodes ?? [])
|
|
35
|
+
visit(child);
|
|
36
|
+
};
|
|
37
|
+
visit(document);
|
|
38
|
+
const nodeIds = hostNodes.map(({ node, ordinal }) => {
|
|
39
|
+
const matches = (node.attrs ?? []).filter((attribute) => attribute.name === HTML_NODE_ID_ATTRIBUTE);
|
|
40
|
+
if (matches.length > 1)
|
|
41
|
+
return null;
|
|
42
|
+
const authoredId = matches[0]?.value;
|
|
43
|
+
const nodeId = authoredId ?? generatedMotionNodeId(args.modulePath, ordinal);
|
|
44
|
+
return /^[A-Za-z0-9_-]+$/.test(nodeId) ? nodeId : null;
|
|
45
|
+
});
|
|
46
|
+
const counts = new Map();
|
|
47
|
+
for (const nodeId of nodeIds) {
|
|
48
|
+
if (nodeId)
|
|
49
|
+
counts.set(nodeId, (counts.get(nodeId) ?? 0) + 1);
|
|
50
|
+
}
|
|
51
|
+
const edits = [];
|
|
52
|
+
for (const [index, { node }] of hostNodes.entries()) {
|
|
53
|
+
const nodeId = nodeIds[index];
|
|
54
|
+
const tag = node.sourceCodeLocation?.startTag;
|
|
55
|
+
if (!nodeId || counts.get(nodeId) !== 1 || !tag)
|
|
56
|
+
continue;
|
|
57
|
+
const attrs = new Map((node.attrs ?? []).map((attribute) => [attribute.name, attribute.value]));
|
|
58
|
+
const values = [
|
|
59
|
+
[HTML_NODE_ID_ATTRIBUTE, nodeId],
|
|
60
|
+
[SOURCE_FILE_ATTRIBUTE, args.modulePath],
|
|
61
|
+
[SOURCE_HASH_ATTRIBUTE, args.moduleVersionHash],
|
|
62
|
+
];
|
|
63
|
+
const additions = [];
|
|
64
|
+
for (const [name, value] of values) {
|
|
65
|
+
const existingValue = attrs.get(name);
|
|
66
|
+
if (existingValue === value)
|
|
67
|
+
continue;
|
|
68
|
+
const location = tag.attrs?.[name];
|
|
69
|
+
const attribute = `${name}="${escapeHtmlAttribute(value)}"`;
|
|
70
|
+
if (location) {
|
|
71
|
+
edits.push({
|
|
72
|
+
start: location.startOffset,
|
|
73
|
+
end: location.endOffset,
|
|
74
|
+
text: attribute,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
if (name === HTML_NODE_ID_ATTRIBUTE &&
|
|
79
|
+
node.attrs?.some((entry) => entry.name === HTML_NODE_ID_ATTRIBUTE)) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
additions.push(attribute);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (additions.length === 0)
|
|
86
|
+
continue;
|
|
87
|
+
const tagEnd = args.html[tag.endOffset - 2] === "/"
|
|
88
|
+
? tag.endOffset - 2
|
|
89
|
+
: tag.endOffset - 1;
|
|
90
|
+
edits.push({ start: tagEnd, end: tagEnd, text: ` ${additions.join(" ")}` });
|
|
91
|
+
}
|
|
92
|
+
if (edits.length === 0)
|
|
93
|
+
return null;
|
|
94
|
+
const ordered = [...edits].sort((left, right) => right.start - left.start || right.end - left.end);
|
|
95
|
+
let result = args.html;
|
|
96
|
+
let previousStart = args.html.length + 1;
|
|
97
|
+
for (const edit of ordered) {
|
|
98
|
+
if (edit.end > previousStart || edit.end > args.html.length)
|
|
99
|
+
return null;
|
|
100
|
+
result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
|
|
101
|
+
previousStart = edit.start;
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
/** Adds dev-only JSX identity evidence so source edits follow rendered nodes. */
|
|
106
|
+
export function motionSourceProvenancePlugin() {
|
|
107
|
+
let root = process.cwd();
|
|
108
|
+
let command = "serve";
|
|
109
|
+
return {
|
|
110
|
+
name: "agent-native-motion-source-provenance",
|
|
111
|
+
enforce: "pre",
|
|
112
|
+
configResolved(config) {
|
|
113
|
+
root = path.resolve(config.root);
|
|
114
|
+
command = config.command;
|
|
115
|
+
},
|
|
116
|
+
transformIndexHtml: {
|
|
117
|
+
order: "pre",
|
|
118
|
+
handler(html, context) {
|
|
119
|
+
if (command !== "serve" || !context.filename)
|
|
120
|
+
return;
|
|
121
|
+
const absolutePath = path.resolve(context.filename);
|
|
122
|
+
const modulePath = path
|
|
123
|
+
.relative(root, absolutePath)
|
|
124
|
+
.split(path.sep)
|
|
125
|
+
.join("/");
|
|
126
|
+
const extension = path.extname(modulePath).toLowerCase();
|
|
127
|
+
if (!modulePath ||
|
|
128
|
+
path.isAbsolute(modulePath) ||
|
|
129
|
+
modulePath === ".." ||
|
|
130
|
+
modulePath.startsWith("../") ||
|
|
131
|
+
![".html", ".htm"].includes(extension) ||
|
|
132
|
+
modulePath
|
|
133
|
+
.split("/")
|
|
134
|
+
.some((segment) => ["node_modules", ".vite", "dist", "build"].includes(segment))) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
let diskSource;
|
|
138
|
+
try {
|
|
139
|
+
diskSource = readFileSync(absolutePath, "utf8");
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
throw new Error(`Unable to read the Motion HTML source at ${absolutePath}.`, { cause: error });
|
|
143
|
+
}
|
|
144
|
+
if (diskSource !== html)
|
|
145
|
+
return;
|
|
146
|
+
const moduleVersionHash = createHash("sha256")
|
|
147
|
+
.update(diskSource)
|
|
148
|
+
.digest("hex");
|
|
149
|
+
return (instrumentMotionHtmlProvenance({
|
|
150
|
+
html,
|
|
151
|
+
modulePath,
|
|
152
|
+
moduleVersionHash,
|
|
153
|
+
}) ?? undefined);
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
transform(code, id) {
|
|
157
|
+
if (command !== "serve" || !id || id.startsWith("\0"))
|
|
158
|
+
return null;
|
|
159
|
+
const fileName = id.split("?", 1)[0];
|
|
160
|
+
const extension = path.extname(fileName).toLowerCase();
|
|
161
|
+
if (extension !== ".tsx" && extension !== ".jsx")
|
|
162
|
+
return null;
|
|
163
|
+
const absolutePath = path.resolve(fileName);
|
|
164
|
+
let diskSource;
|
|
165
|
+
try {
|
|
166
|
+
diskSource = readFileSync(absolutePath, "utf8");
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
throw new Error(`Unable to read the Motion source module at ${absolutePath}.`, { cause: error });
|
|
170
|
+
}
|
|
171
|
+
if (diskSource !== code)
|
|
172
|
+
return null;
|
|
173
|
+
const modulePath = path
|
|
174
|
+
.relative(root, absolutePath)
|
|
175
|
+
.split(path.sep)
|
|
176
|
+
.join("/");
|
|
177
|
+
if (!modulePath ||
|
|
178
|
+
modulePath === ".." ||
|
|
179
|
+
modulePath.startsWith("../") ||
|
|
180
|
+
modulePath
|
|
181
|
+
.split("/")
|
|
182
|
+
.some((segment) => ["node_modules", ".vite", "dist", "build"].includes(segment))) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
if (!code.includes("<"))
|
|
186
|
+
return null;
|
|
187
|
+
let syntaxTree;
|
|
188
|
+
try {
|
|
189
|
+
syntaxTree = parse(code, {
|
|
190
|
+
plugins: extension === ".tsx" ? ["jsx", "typescript"] : ["jsx"],
|
|
191
|
+
sourceType: "unambiguous",
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
if (error instanceof SyntaxError)
|
|
196
|
+
return null;
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
const sourceHash = createHash("sha256").update(diskSource).digest("hex");
|
|
200
|
+
const magic = new MagicString(code, { filename: absolutePath });
|
|
201
|
+
let hostElementOrdinal = 0;
|
|
202
|
+
let changed = false;
|
|
203
|
+
const visit = (node) => {
|
|
204
|
+
if (node.type === "JSXElement") {
|
|
205
|
+
const opening = asBabelNode(node.openingElement);
|
|
206
|
+
const tag = asBabelNode(opening?.name);
|
|
207
|
+
if (opening?.type === "JSXOpeningElement" &&
|
|
208
|
+
tag?.type === "JSXIdentifier" &&
|
|
209
|
+
typeof tag.name === "string" &&
|
|
210
|
+
isMotionSourceHostElementTag(tag.name)) {
|
|
211
|
+
const ordinal = hostElementOrdinal++;
|
|
212
|
+
const properties = Array.isArray(opening.attributes)
|
|
213
|
+
? opening.attributes
|
|
214
|
+
.map(asBabelNode)
|
|
215
|
+
.filter((property) => property !== null)
|
|
216
|
+
: [];
|
|
217
|
+
const hasSpread = properties.some((property) => property.type === "JSXSpreadAttribute");
|
|
218
|
+
const attributes = new Map();
|
|
219
|
+
for (const property of properties) {
|
|
220
|
+
if (property.type !== "JSXAttribute")
|
|
221
|
+
continue;
|
|
222
|
+
const name = asBabelNode(property.name);
|
|
223
|
+
if (name?.type !== "JSXIdentifier" ||
|
|
224
|
+
typeof name.name !== "string") {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
const matching = attributes.get(name.name) ?? [];
|
|
228
|
+
matching.push(property);
|
|
229
|
+
attributes.set(name.name, matching);
|
|
230
|
+
}
|
|
231
|
+
const isStaticStringAttribute = (property) => {
|
|
232
|
+
const value = asBabelNode(property.value);
|
|
233
|
+
return (value?.type === "StringLiteral" &&
|
|
234
|
+
typeof value.value === "string");
|
|
235
|
+
};
|
|
236
|
+
const staticStringValue = (property) => {
|
|
237
|
+
const value = property ? asBabelNode(property.value) : null;
|
|
238
|
+
return value?.type === "StringLiteral" &&
|
|
239
|
+
typeof value.value === "string"
|
|
240
|
+
? value.value
|
|
241
|
+
: undefined;
|
|
242
|
+
};
|
|
243
|
+
const idAttributes = attributes.get(NODE_ID_ATTRIBUTE) ?? [];
|
|
244
|
+
const hasDynamicNodeId = idAttributes.length > 0 &&
|
|
245
|
+
(idAttributes.length !== 1 ||
|
|
246
|
+
!isStaticStringAttribute(idAttributes[0]));
|
|
247
|
+
const authoredNodeId = idAttributes.length === 1 && !hasDynamicNodeId
|
|
248
|
+
? staticStringValue(idAttributes[0])
|
|
249
|
+
: undefined;
|
|
250
|
+
const nodeId = authoredNodeId ?? generatedMotionNodeId(modulePath, ordinal);
|
|
251
|
+
const malformedReservedAttribute = [
|
|
252
|
+
NODE_ID_ATTRIBUTE,
|
|
253
|
+
SOURCE_FILE_ATTRIBUTE,
|
|
254
|
+
SOURCE_HASH_ATTRIBUTE,
|
|
255
|
+
].some((name) => {
|
|
256
|
+
const matches = attributes.get(name) ?? [];
|
|
257
|
+
return (matches.length > 1 ||
|
|
258
|
+
(matches.length === 1 && !isStaticStringAttribute(matches[0])));
|
|
259
|
+
});
|
|
260
|
+
if (!hasSpread &&
|
|
261
|
+
!hasDynamicNodeId &&
|
|
262
|
+
!malformedReservedAttribute &&
|
|
263
|
+
/^[A-Za-z0-9_-]+$/.test(nodeId)) {
|
|
264
|
+
const expectedAttributes = [
|
|
265
|
+
...(!authoredNodeId
|
|
266
|
+
? [[NODE_ID_ATTRIBUTE, nodeId]]
|
|
267
|
+
: []),
|
|
268
|
+
[SOURCE_FILE_ATTRIBUTE, modulePath],
|
|
269
|
+
[SOURCE_HASH_ATTRIBUTE, sourceHash],
|
|
270
|
+
];
|
|
271
|
+
for (const [name, value] of expectedAttributes) {
|
|
272
|
+
const existing = attributes.get(name) ?? [];
|
|
273
|
+
if (existing.length === 0) {
|
|
274
|
+
const insertionPoint = properties.at(-1)?.end ?? tag.end;
|
|
275
|
+
if (typeof insertionPoint !== "number") {
|
|
276
|
+
throw new Error(`Unable to locate JSX attributes in ${absolutePath}.`);
|
|
277
|
+
}
|
|
278
|
+
magic.appendLeft(insertionPoint, ` ${name}=${JSON.stringify(value)}`);
|
|
279
|
+
changed = true;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
const attribute = existing[0];
|
|
283
|
+
const start = attribute.start;
|
|
284
|
+
const end = attribute.end;
|
|
285
|
+
if (existing.length !== 1 ||
|
|
286
|
+
!isStaticStringAttribute(attribute) ||
|
|
287
|
+
typeof start !== "number" ||
|
|
288
|
+
typeof end !== "number") {
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
if (staticStringValue(attribute) !== value) {
|
|
292
|
+
magic.update(start, end, `${name}=${JSON.stringify(value)}`);
|
|
293
|
+
changed = true;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
for (const value of Object.values(node)) {
|
|
300
|
+
if (Array.isArray(value)) {
|
|
301
|
+
for (const child of value) {
|
|
302
|
+
const astChild = asBabelNode(child);
|
|
303
|
+
if (astChild)
|
|
304
|
+
visit(astChild);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
const astChild = asBabelNode(value);
|
|
309
|
+
if (astChild)
|
|
310
|
+
visit(astChild);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
const program = asBabelNode(syntaxTree.program);
|
|
315
|
+
if (!program)
|
|
316
|
+
return null;
|
|
317
|
+
visit(program);
|
|
318
|
+
if (!changed)
|
|
319
|
+
return null;
|
|
320
|
+
return {
|
|
321
|
+
code: magic.toString(),
|
|
322
|
+
map: magic.generateMap({
|
|
323
|
+
hires: "boundary",
|
|
324
|
+
includeContent: true,
|
|
325
|
+
source: modulePath,
|
|
326
|
+
}),
|
|
327
|
+
};
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function asBabelNode(value) {
|
|
332
|
+
if (!value ||
|
|
333
|
+
typeof value !== "object" ||
|
|
334
|
+
!("type" in value) ||
|
|
335
|
+
typeof value.type !== "string") {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
return value;
|
|
339
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.207.
|
|
3
|
+
"version": "0.207.2-nightly-20261013011333",
|
|
4
4
|
"description": "The agentic application framework for building autonomous agents with intuitive UIs",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
"./server/interval-job": "./dist/server/interval-job.js",
|
|
110
110
|
"./server/sse": "./dist/server/sse.js",
|
|
111
111
|
"./server/short-lived-token": "./dist/server/short-lived-token.js",
|
|
112
|
+
"./visual-edit-bridge-capability": "./dist/server/visual-edit-bridge-capability.js",
|
|
112
113
|
"./integrations": "./dist/integrations/index.js",
|
|
113
114
|
"./integrations/computer-supervision": "./dist/integrations/computer-supervision.js",
|
|
114
115
|
"./integrations/runtime": "./dist/integrations/runtime.js",
|
|
@@ -523,6 +524,8 @@
|
|
|
523
524
|
"./client/integrations/webhook-url": "./dist/client/integrations/webhook-url.js",
|
|
524
525
|
"./client/labs/use-lab": "./dist/client/labs/use-lab.js",
|
|
525
526
|
"./client/mcp-app-host": "./dist/client/mcp-app-host.js",
|
|
527
|
+
"./client/motion-text": "./dist/client/motion-text.js",
|
|
528
|
+
"./client/motion-text.css": "./dist/client/motion-text.css",
|
|
526
529
|
"./client/onboarding/first-run-enabled": "./dist/client/onboarding/first-run-enabled.js",
|
|
527
530
|
"./client/onboarding/first-run-registry": "./dist/client/onboarding/first-run-registry.js",
|
|
528
531
|
"./client/onboarding/first-run-status": "./dist/client/onboarding/first-run-status.js",
|
|
@@ -609,6 +612,8 @@
|
|
|
609
612
|
"./shared/loading-labels": "./dist/shared/loading-labels.js",
|
|
610
613
|
"./shared/mcp-app-widget-embed": "./dist/shared/mcp-app-widget-embed.js",
|
|
611
614
|
"./shared/mcp-connect-content": "./dist/shared/mcp-connect-content.js",
|
|
615
|
+
"./shared/motion-easing": "./dist/shared/motion-easing.js",
|
|
616
|
+
"./shared/motion-source-node-id": "./dist/shared/motion-source-node-id.js",
|
|
612
617
|
"./shared/password-policy": "./dist/shared/password-policy.js",
|
|
613
618
|
"./shared/qa-test-email": "./dist/shared/qa-test-email.js",
|
|
614
619
|
"./shared/runtime-config": "./dist/shared/runtime-config.js",
|
|
@@ -653,6 +658,7 @@
|
|
|
653
658
|
},
|
|
654
659
|
"dependencies": {
|
|
655
660
|
"@anthropic-ai/sdk": "^0.90.0",
|
|
661
|
+
"@babel/parser": "8.0.7",
|
|
656
662
|
"@clack/prompts": "^1.7.0",
|
|
657
663
|
"@mcp-b/webmcp-polyfill": "^5.1.0",
|
|
658
664
|
"@modelcontextprotocol/client": "2.0.0",
|
|
@@ -681,8 +687,10 @@
|
|
|
681
687
|
"jiti": "^2.7.0",
|
|
682
688
|
"jose": "^6.2.2",
|
|
683
689
|
"linkedom": "^0.18.13",
|
|
690
|
+
"magic-string": "^1.4.3",
|
|
684
691
|
"minimatch": "^10.0.0",
|
|
685
692
|
"nitro": "3.0.260903-beta",
|
|
693
|
+
"parse5": "8.0.1",
|
|
686
694
|
"postgres": "^3.4.9",
|
|
687
695
|
"react-i18next": "17.0.8",
|
|
688
696
|
"run": "2.0.1",
|
|
@@ -694,8 +702,8 @@
|
|
|
694
702
|
"yaml": "^2.9.0",
|
|
695
703
|
"yjs": "^13.6.33",
|
|
696
704
|
"zod": "^4.3.6",
|
|
697
|
-
"@agent-native/
|
|
698
|
-
"@agent-native/
|
|
705
|
+
"@agent-native/recap-cli": "^0.5.70",
|
|
706
|
+
"@agent-native/agentkit": "^0.207.2-nightly-20261013011333"
|
|
699
707
|
},
|
|
700
708
|
"devDependencies": {
|
|
701
709
|
"@ai-sdk/anthropic": "^3.0.71",
|
|
@@ -765,7 +773,7 @@
|
|
|
765
773
|
"xlsx": "^0.18.5"
|
|
766
774
|
},
|
|
767
775
|
"peerDependencies": {
|
|
768
|
-
"@agent-native/core-corpus": "
|
|
776
|
+
"@agent-native/core-corpus": "0.207.2-nightly-20261013011333",
|
|
769
777
|
"@ai-sdk/anthropic": ">=3",
|
|
770
778
|
"@ai-sdk/cohere": ">=3",
|
|
771
779
|
"@ai-sdk/google": ">=3",
|
|
@@ -951,6 +959,7 @@
|
|
|
951
959
|
"build": "tsc && tsc -p tsconfig.cli.json && node scripts/finalize-build.mjs && node scripts/check-dist-imports.mjs",
|
|
952
960
|
"dev": "tsc --watch",
|
|
953
961
|
"typecheck": "tsc --noEmit",
|
|
954
|
-
"test": "vitest --run --dir src"
|
|
962
|
+
"test": "vitest --run --dir src",
|
|
963
|
+
"test:motion-text-package": "vitest --run scripts/motion-text-package.spec.ts"
|
|
955
964
|
}
|
|
956
965
|
}
|
|
@@ -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
|
|