@agent-native/core 0.203.1 → 0.203.2-nightly-20261007213109
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/thread-message-projection.d.ts +1 -0
- package/dist/agent/thread-message-projection.js +56 -6
- package/dist/client/chat/agentkit-agent-native.js +104 -24
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +4 -4
- package/dist/observability/store.js +11 -5
- package/dist/observability/traces.js +6 -0
- package/dist/observability/types.d.ts +2 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.js +14 -6
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +34 -44
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/reproduction-and-verification.md +46 -0
- package/dist/templates/factory/.agents/skills/review-prs/SKILL.md +5 -3
- package/dist/triggers/actions/manage-automation.d.ts +2 -2
- package/package.json +3 -3
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +34 -44
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/reproduction-and-verification.md +46 -0
- package/src/templates/factory/.agents/skills/review-prs/SKILL.md +5 -3
|
@@ -9,6 +9,7 @@ export declare function projectRootAssistantMessages(input: {
|
|
|
9
9
|
}): {
|
|
10
10
|
representedRootMessageIds: Set<string>;
|
|
11
11
|
snapshotMessageIdsByRootMessageId: Map<string, string>;
|
|
12
|
+
snapshotRunIdsByMessageId: Map<string, string>;
|
|
12
13
|
};
|
|
13
14
|
/** Root assistant IDs represented by the AgentKit snapshot. */
|
|
14
15
|
export declare function representedRootAssistantMessageIds(input: {
|
|
@@ -80,11 +80,13 @@ function eventMessageIdsByRun(runIdsByMessageId) {
|
|
|
80
80
|
}
|
|
81
81
|
return result;
|
|
82
82
|
}
|
|
83
|
-
function assistantRunId(value, runIdsByMessageId) {
|
|
83
|
+
function assistantRunId(value, runIdsByMessageId, inferredRunId) {
|
|
84
84
|
if (value.role !== "assistant")
|
|
85
85
|
return undefined;
|
|
86
86
|
const eventRunIds = typeof value.id === "string" ? runIdsByMessageId.get(value.id) : undefined;
|
|
87
|
-
return eventRunIds?.size === 1 ? [...eventRunIds][0] :
|
|
87
|
+
return ((eventRunIds?.size === 1 ? [...eventRunIds][0] : undefined) ??
|
|
88
|
+
explicitRunId(value) ??
|
|
89
|
+
(eventRunIds?.size ? undefined : inferredRunId));
|
|
88
90
|
}
|
|
89
91
|
function text(value, ignoreNonTextParts = false) {
|
|
90
92
|
if (value.role !== "assistant")
|
|
@@ -231,11 +233,57 @@ export function projectRootAssistantMessages(input) {
|
|
|
231
233
|
: [];
|
|
232
234
|
const runIdsByMessageId = eventRunIds(input.events, input.runs);
|
|
233
235
|
const messageIdsByRun = eventMessageIdsByRun(runIdsByMessageId);
|
|
236
|
+
const snapshotUserIdsByRun = new Map();
|
|
237
|
+
for (const root of rootMessages) {
|
|
238
|
+
if (root.role !== "user")
|
|
239
|
+
continue;
|
|
240
|
+
const custom = record(record(root.metadata)?.custom);
|
|
241
|
+
const snapshotId = typeof custom?.agentKitMessageId === "string"
|
|
242
|
+
? custom.agentKitMessageId
|
|
243
|
+
: typeof root.id === "string"
|
|
244
|
+
? root.id
|
|
245
|
+
: undefined;
|
|
246
|
+
const runId = custom?.submittedRunId;
|
|
247
|
+
if (!snapshotId || typeof runId !== "string")
|
|
248
|
+
continue;
|
|
249
|
+
snapshotUserIdsByRun.set(snapshotId, snapshotUserIdsByRun.has(snapshotId) ? null : runId);
|
|
250
|
+
}
|
|
251
|
+
const snapshotUserCounts = new Map();
|
|
252
|
+
for (const candidate of snapshotMessages) {
|
|
253
|
+
if (candidate.role !== "user" || typeof candidate.id !== "string")
|
|
254
|
+
continue;
|
|
255
|
+
snapshotUserCounts.set(candidate.id, (snapshotUserCounts.get(candidate.id) ?? 0) + 1);
|
|
256
|
+
}
|
|
257
|
+
for (const [snapshotId, runId] of snapshotUserIdsByRun) {
|
|
258
|
+
if (snapshotUserCounts.get(snapshotId) !== 1 || runId === null) {
|
|
259
|
+
snapshotUserIdsByRun.delete(snapshotId);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
234
262
|
const snapshotMessagesByRunId = new Map();
|
|
263
|
+
const snapshotRunIdsByMessageId = new Map();
|
|
264
|
+
let submittedRunId;
|
|
235
265
|
for (const candidate of snapshotMessages) {
|
|
236
|
-
|
|
237
|
-
|
|
266
|
+
if (candidate.role === "user") {
|
|
267
|
+
const candidateRunId = typeof candidate.id === "string"
|
|
268
|
+
? snapshotUserIdsByRun.get(candidate.id)
|
|
269
|
+
: undefined;
|
|
270
|
+
submittedRunId =
|
|
271
|
+
typeof candidateRunId === "string" ? candidateRunId : undefined;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (candidate.role !== "assistant")
|
|
275
|
+
continue;
|
|
276
|
+
const eventRunIds = typeof candidate.id === "string"
|
|
277
|
+
? runIdsByMessageId.get(candidate.id)
|
|
278
|
+
: undefined;
|
|
279
|
+
const inferredRunId = !eventRunIds?.size && !explicitRunId(candidate)
|
|
280
|
+
? submittedRunId
|
|
281
|
+
: undefined;
|
|
282
|
+
const runId = assistantRunId(candidate, runIdsByMessageId, inferredRunId);
|
|
283
|
+
if (!runId || typeof candidate.id !== "string")
|
|
238
284
|
continue;
|
|
285
|
+
if (inferredRunId)
|
|
286
|
+
snapshotRunIdsByMessageId.set(candidate.id, runId);
|
|
239
287
|
const candidates = snapshotMessagesByRunId.get(runId);
|
|
240
288
|
if (candidates)
|
|
241
289
|
candidates.push(candidate);
|
|
@@ -261,8 +309,9 @@ export function projectRootAssistantMessages(input) {
|
|
|
261
309
|
const clientCanMatchPartial = matchingCandidate !== undefined &&
|
|
262
310
|
(explicitRunId(matchingCandidate) === runId ||
|
|
263
311
|
(typeof matchingCandidate.id === "string" &&
|
|
264
|
-
|
|
265
|
-
|
|
312
|
+
(snapshotRunIdsByMessageId.get(matchingCandidate.id) === runId ||
|
|
313
|
+
(runIdsByMessageId.get(matchingCandidate.id)?.size === 1 &&
|
|
314
|
+
messageIdsByRun.get(runId)?.size === 1))));
|
|
266
315
|
if (sameRunMatches.length === 1 &&
|
|
267
316
|
(exactTextMatch ||
|
|
268
317
|
(sameRunCandidates.length === 1 && clientCanMatchPartial))) {
|
|
@@ -292,6 +341,7 @@ export function projectRootAssistantMessages(input) {
|
|
|
292
341
|
return {
|
|
293
342
|
representedRootMessageIds: represented,
|
|
294
343
|
snapshotMessageIdsByRootMessageId,
|
|
344
|
+
snapshotRunIdsByMessageId,
|
|
295
345
|
};
|
|
296
346
|
}
|
|
297
347
|
/** Root assistant IDs represented by the AgentKit snapshot. */
|
|
@@ -412,6 +412,80 @@ function withRefusedTurnMetadata(message, stored) {
|
|
|
412
412
|
},
|
|
413
413
|
};
|
|
414
414
|
}
|
|
415
|
+
function orderMessagesByDurableSequence(snapshotMessages, missingMessages, durableMessages, durableIndexById, durableIdBySnapshotId) {
|
|
416
|
+
const messageByDurableId = new Map(missingMessages.map((message) => [message.id, message]));
|
|
417
|
+
const snapshotIdByDurableId = new Map();
|
|
418
|
+
const durableIndexBySnapshotId = new Map();
|
|
419
|
+
for (const message of snapshotMessages) {
|
|
420
|
+
const durableId = durableIdBySnapshotId.get(message.id) ??
|
|
421
|
+
(durableIndexById.has(message.id) ? message.id : undefined);
|
|
422
|
+
const durableIndex = durableId
|
|
423
|
+
? durableIndexById.get(durableId)
|
|
424
|
+
: undefined;
|
|
425
|
+
if (!durableId ||
|
|
426
|
+
durableIndex === undefined ||
|
|
427
|
+
snapshotIdByDurableId.has(durableId)) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
snapshotIdByDurableId.set(durableId, message.id);
|
|
431
|
+
durableIndexBySnapshotId.set(message.id, durableIndex);
|
|
432
|
+
messageByDurableId.set(durableId, message);
|
|
433
|
+
}
|
|
434
|
+
if (snapshotIdByDurableId.size === 0) {
|
|
435
|
+
return [...snapshotMessages, ...missingMessages]
|
|
436
|
+
.map((message, index) => ({ message, index }))
|
|
437
|
+
.sort((left, right) => {
|
|
438
|
+
const leftCreatedAt = Date.parse(left.message.createdAt ?? "");
|
|
439
|
+
const rightCreatedAt = Date.parse(right.message.createdAt ?? "");
|
|
440
|
+
if (Number.isFinite(leftCreatedAt) &&
|
|
441
|
+
Number.isFinite(rightCreatedAt) &&
|
|
442
|
+
leftCreatedAt !== rightCreatedAt) {
|
|
443
|
+
return leftCreatedAt - rightCreatedAt;
|
|
444
|
+
}
|
|
445
|
+
return left.index - right.index;
|
|
446
|
+
})
|
|
447
|
+
.map(({ message }) => message);
|
|
448
|
+
}
|
|
449
|
+
const insertions = new Map();
|
|
450
|
+
for (let index = 0; index < snapshotMessages.length; index += 1) {
|
|
451
|
+
const message = snapshotMessages[index];
|
|
452
|
+
if (durableIndexBySnapshotId.has(message.id))
|
|
453
|
+
continue;
|
|
454
|
+
let insertionIndex;
|
|
455
|
+
for (let next = index + 1; next < snapshotMessages.length; next += 1) {
|
|
456
|
+
const durableIndex = durableIndexBySnapshotId.get(snapshotMessages[next].id);
|
|
457
|
+
if (durableIndex !== undefined) {
|
|
458
|
+
insertionIndex = durableIndex;
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (insertionIndex === undefined) {
|
|
463
|
+
for (let previous = index - 1; previous >= 0; previous -= 1) {
|
|
464
|
+
const durableIndex = durableIndexBySnapshotId.get(snapshotMessages[previous].id);
|
|
465
|
+
if (durableIndex !== undefined) {
|
|
466
|
+
insertionIndex = durableIndex + 1;
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (insertionIndex === undefined)
|
|
472
|
+
continue;
|
|
473
|
+
const messages = insertions.get(insertionIndex) ?? [];
|
|
474
|
+
messages.push(message);
|
|
475
|
+
insertions.set(insertionIndex, messages);
|
|
476
|
+
}
|
|
477
|
+
const ordered = [];
|
|
478
|
+
for (let index = 0; index <= durableMessages.length; index += 1) {
|
|
479
|
+
ordered.push(...(insertions.get(index) ?? []));
|
|
480
|
+
const durableMessage = durableMessages[index];
|
|
481
|
+
if (!durableMessage)
|
|
482
|
+
continue;
|
|
483
|
+
const projected = messageByDurableId.get(durableMessage.id);
|
|
484
|
+
if (projected)
|
|
485
|
+
ordered.push(projected);
|
|
486
|
+
}
|
|
487
|
+
return ordered;
|
|
488
|
+
}
|
|
415
489
|
function reconcileDurableMessages(messages, durable, events, runs, toolCalls) {
|
|
416
490
|
const submittedRunId = (message) => {
|
|
417
491
|
const value = asRecord(asRecord(message.metadata)?.custom)?.submittedRunId;
|
|
@@ -495,6 +569,7 @@ function reconcileDurableMessages(messages, durable, events, runs, toolCalls) {
|
|
|
495
569
|
toolCalls,
|
|
496
570
|
});
|
|
497
571
|
const representedDurableAssistantIds = rootAssistantProjection.representedRootMessageIds;
|
|
572
|
+
const snapshotRunIdsByMessageId = rootAssistantProjection.snapshotRunIdsByMessageId;
|
|
498
573
|
const rootMessageIdsBySnapshotMessageId = new Map([...rootAssistantProjection.snapshotMessageIdsByRootMessageId].map(([rootId, snapshotId]) => [snapshotId, rootId]));
|
|
499
574
|
const deduplicatedMessages = messages.filter((message) => !representedDurableAssistantIds.has(message.id));
|
|
500
575
|
const representedSubmittedUserIds = new Set();
|
|
@@ -526,7 +601,8 @@ function reconcileDurableMessages(messages, durable, events, runs, toolCalls) {
|
|
|
526
601
|
const metadataRunId = asRecord(message.metadata)?.runId;
|
|
527
602
|
const runId = typeof metadataRunId === "string"
|
|
528
603
|
? metadataRunId
|
|
529
|
-
:
|
|
604
|
+
: (snapshotRunIdsByMessageId.get(message.id) ??
|
|
605
|
+
runByAssistantId.get(message.id));
|
|
530
606
|
if (runId)
|
|
531
607
|
snapshotAssistantRunIds.add(runId);
|
|
532
608
|
}
|
|
@@ -565,6 +641,9 @@ function reconcileDurableMessages(messages, durable, events, runs, toolCalls) {
|
|
|
565
641
|
for (const message of matchingSnapshots) {
|
|
566
642
|
matchedSnapshotUserIds.add(message.id);
|
|
567
643
|
}
|
|
644
|
+
for (let index = 0; index < matchingSnapshots.length; index += 1) {
|
|
645
|
+
storedUserBySnapshotId.set(matchingSnapshots[index].id, candidates[index]);
|
|
646
|
+
}
|
|
568
647
|
}
|
|
569
648
|
const missingMessages = submittedUsers.filter((message) => !representedSubmittedUserIds.has(message.id));
|
|
570
649
|
const completedRunIds = new Set([
|
|
@@ -600,39 +679,35 @@ function reconcileDurableMessages(messages, durable, events, runs, toolCalls) {
|
|
|
600
679
|
missingMessages.push(message);
|
|
601
680
|
representedAssistantIds.add(message.id);
|
|
602
681
|
}
|
|
603
|
-
const
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
]
|
|
608
|
-
.
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
.sort((left, right) => {
|
|
613
|
-
const leftCreatedAt = Date.parse(left.message.createdAt ?? "");
|
|
614
|
-
const rightCreatedAt = Date.parse(right.message.createdAt ?? "");
|
|
615
|
-
if (Number.isFinite(leftCreatedAt) &&
|
|
616
|
-
Number.isFinite(rightCreatedAt) &&
|
|
617
|
-
leftCreatedAt !== rightCreatedAt) {
|
|
618
|
-
return leftCreatedAt - rightCreatedAt;
|
|
619
|
-
}
|
|
620
|
-
return left.index - right.index;
|
|
621
|
-
})
|
|
622
|
-
.map(({ message }) => message);
|
|
682
|
+
const durableIdBySnapshotId = new Map();
|
|
683
|
+
for (const [snapshotId, stored] of storedUserBySnapshotId) {
|
|
684
|
+
durableIdBySnapshotId.set(snapshotId, stored.id);
|
|
685
|
+
}
|
|
686
|
+
for (const [snapshotId, rootId] of rootMessageIdsBySnapshotMessageId) {
|
|
687
|
+
durableIdBySnapshotId.set(snapshotId, rootId);
|
|
688
|
+
}
|
|
689
|
+
const projectedMessages = orderMessagesByDurableSequence(deduplicatedMessages, missingMessages.sort((left, right) => (durableIndexById.get(left.id) ?? 0) -
|
|
690
|
+
(durableIndexById.get(right.id) ?? 0)), durable, durableIndexById, durableIdBySnapshotId);
|
|
623
691
|
const snapshotRunId = (message) => {
|
|
624
692
|
const metadataRunId = asRecord(message.metadata)?.runId;
|
|
625
693
|
return (runByAssistantId.get(message.id) ??
|
|
694
|
+
snapshotRunIdsByMessageId.get(message.id) ??
|
|
626
695
|
(typeof metadataRunId === "string" ? metadataRunId : undefined));
|
|
627
696
|
};
|
|
628
697
|
const textOf = (parts) => parts
|
|
629
698
|
.filter((part) => part.type === "text")
|
|
630
699
|
.map((part) => part.text)
|
|
631
700
|
.join("");
|
|
632
|
-
|
|
701
|
+
const reconciledMessages = projectedMessages.map((message) => {
|
|
633
702
|
if (message.role === "user") {
|
|
634
703
|
const stored = storedUserBySnapshotId.get(message.id);
|
|
635
|
-
|
|
704
|
+
if (!stored)
|
|
705
|
+
return message;
|
|
706
|
+
const createdAt = message.createdAt ?? stored.createdAt;
|
|
707
|
+
const reconciled = createdAt === message.createdAt
|
|
708
|
+
? message
|
|
709
|
+
: { ...message, ...(createdAt ? { createdAt } : {}) };
|
|
710
|
+
return withRefusedTurnMetadata(reconciled, stored);
|
|
636
711
|
}
|
|
637
712
|
if (message.role !== "assistant")
|
|
638
713
|
return message;
|
|
@@ -646,10 +721,14 @@ function reconcileDurableMessages(messages, durable, events, runs, toolCalls) {
|
|
|
646
721
|
representedRoot.status === "error"
|
|
647
722
|
? representedRoot.status
|
|
648
723
|
: undefined;
|
|
649
|
-
|
|
724
|
+
const createdAt = message.createdAt ?? representedRoot.createdAt;
|
|
725
|
+
if (parts !== message.parts ||
|
|
726
|
+
terminalStatus !== undefined ||
|
|
727
|
+
createdAt !== message.createdAt) {
|
|
650
728
|
message = {
|
|
651
729
|
...message,
|
|
652
730
|
...(parts !== message.parts ? { parts } : {}),
|
|
731
|
+
...(createdAt ? { createdAt } : {}),
|
|
653
732
|
...(terminalStatus ? { status: terminalStatus } : {}),
|
|
654
733
|
};
|
|
655
734
|
}
|
|
@@ -759,6 +838,7 @@ function reconcileDurableMessages(messages, durable, events, runs, toolCalls) {
|
|
|
759
838
|
}
|
|
760
839
|
return { ...reconciled, parts };
|
|
761
840
|
});
|
|
841
|
+
return reconciledMessages;
|
|
762
842
|
}
|
|
763
843
|
function messageStatus(value) {
|
|
764
844
|
const status = asRecord(value)?.type ?? value;
|
|
@@ -38,19 +38,19 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
38
38
|
error: string;
|
|
39
39
|
states?: undefined;
|
|
40
40
|
} | {
|
|
41
|
-
error?: undefined;
|
|
42
41
|
states: {
|
|
43
42
|
clientId: number;
|
|
44
43
|
state: string;
|
|
45
44
|
}[];
|
|
45
|
+
error?: undefined;
|
|
46
46
|
}>>;
|
|
47
47
|
export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
48
48
|
error: string;
|
|
49
49
|
users?: undefined;
|
|
50
50
|
} | {
|
|
51
|
-
error?: undefined;
|
|
52
51
|
users: {
|
|
53
52
|
clientId: number;
|
|
54
53
|
lastSeen: number;
|
|
55
54
|
}[];
|
|
55
|
+
error?: undefined;
|
|
56
56
|
}>>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
2
|
+
error?: undefined;
|
|
2
3
|
count: number;
|
|
3
4
|
updated?: undefined;
|
|
4
|
-
error?: undefined;
|
|
5
5
|
ok?: undefined;
|
|
6
6
|
} | {
|
|
7
|
+
error?: undefined;
|
|
7
8
|
count?: undefined;
|
|
8
9
|
updated: number;
|
|
9
|
-
error?: undefined;
|
|
10
10
|
ok?: undefined;
|
|
11
11
|
} | {
|
|
12
12
|
count?: undefined;
|
|
@@ -14,8 +14,8 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
|
|
|
14
14
|
error: string;
|
|
15
15
|
ok?: undefined;
|
|
16
16
|
} | {
|
|
17
|
+
error?: undefined;
|
|
17
18
|
count?: undefined;
|
|
18
19
|
updated?: undefined;
|
|
19
|
-
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
21
21
|
}>>;
|
|
@@ -28,32 +28,32 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
28
28
|
avgEvalScore: number;
|
|
29
29
|
} | {
|
|
30
30
|
id?: undefined;
|
|
31
|
-
ok?: undefined;
|
|
32
31
|
error: string;
|
|
33
32
|
message: string;
|
|
34
33
|
summary?: undefined;
|
|
35
34
|
spans?: undefined;
|
|
35
|
+
ok?: undefined;
|
|
36
36
|
} | {
|
|
37
37
|
id?: undefined;
|
|
38
38
|
error?: undefined;
|
|
39
|
-
ok?: undefined;
|
|
40
39
|
message?: undefined;
|
|
41
40
|
summary: import("./types.js").TraceSummary;
|
|
42
41
|
spans: import("./types.js").TraceSpan[];
|
|
42
|
+
ok?: undefined;
|
|
43
43
|
} | {
|
|
44
44
|
error?: undefined;
|
|
45
|
-
ok?: undefined;
|
|
46
45
|
message?: undefined;
|
|
47
46
|
summary?: undefined;
|
|
48
47
|
spans?: undefined;
|
|
49
48
|
id: string;
|
|
49
|
+
ok?: undefined;
|
|
50
50
|
} | {
|
|
51
51
|
id?: undefined;
|
|
52
|
-
ok?: undefined;
|
|
53
52
|
message?: undefined;
|
|
54
53
|
summary?: undefined;
|
|
55
54
|
spans?: undefined;
|
|
56
55
|
error: any;
|
|
56
|
+
ok?: undefined;
|
|
57
57
|
} | {
|
|
58
58
|
id?: undefined;
|
|
59
59
|
error?: undefined;
|
|
@@ -138,7 +138,8 @@ export async function ensureObservabilityTables() {
|
|
|
138
138
|
status TEXT NOT NULL DEFAULT 'success',
|
|
139
139
|
error_message TEXT,
|
|
140
140
|
metadata TEXT,
|
|
141
|
-
created_at BIGINT NOT NULL
|
|
141
|
+
created_at BIGINT NOT NULL,
|
|
142
|
+
ended_at BIGINT
|
|
142
143
|
)
|
|
143
144
|
`;
|
|
144
145
|
const traceSummariesCreateSql = `
|
|
@@ -290,6 +291,7 @@ export async function ensureObservabilityTables() {
|
|
|
290
291
|
await ensureTableExists("agent_experiment_assignments", experimentAssignmentsCreateSql);
|
|
291
292
|
await ensureTableExists("agent_experiment_results", experimentResultsCreateSql);
|
|
292
293
|
await ensureColumnExists("agent_experiments", "owner_email", `ALTER TABLE agent_experiments ADD COLUMN IF NOT EXISTS owner_email TEXT`);
|
|
294
|
+
await ensureColumnExists("agent_trace_spans", "ended_at", `ALTER TABLE agent_trace_spans ADD COLUMN IF NOT EXISTS ended_at BIGINT`);
|
|
293
295
|
for (const table of USER_SCOPED_TABLES) {
|
|
294
296
|
await ensureColumnExists(table, "user_id", `ALTER TABLE ${table} ADD COLUMN IF NOT EXISTS user_id TEXT`);
|
|
295
297
|
}
|
|
@@ -344,8 +346,8 @@ export async function insertTraceSpan(span) {
|
|
|
344
346
|
sql: `INSERT INTO agent_trace_spans
|
|
345
347
|
(id, run_id, thread_id, user_id, org_id, parent_span_id, span_type, name,
|
|
346
348
|
input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,
|
|
347
|
-
cost_cents_x100, duration_ms, status, error_message, metadata, created_at)
|
|
348
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
349
|
+
cost_cents_x100, duration_ms, status, error_message, metadata, created_at, ended_at)
|
|
350
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
349
351
|
args: [
|
|
350
352
|
span.id,
|
|
351
353
|
span.runId,
|
|
@@ -365,6 +367,7 @@ export async function insertTraceSpan(span) {
|
|
|
365
367
|
span.errorMessage,
|
|
366
368
|
span.metadata ? JSON.stringify(span.metadata) : null,
|
|
367
369
|
span.createdAt,
|
|
370
|
+
span.endedAt ?? span.createdAt + span.durationMs,
|
|
368
371
|
],
|
|
369
372
|
});
|
|
370
373
|
}
|
|
@@ -1733,6 +1736,8 @@ function rowToTraceSpan(row) {
|
|
|
1733
1736
|
const exposesErrorText = row.span_type !== "tool_call" ||
|
|
1734
1737
|
errorDetail === "full" ||
|
|
1735
1738
|
errorDetail === "signature";
|
|
1739
|
+
const createdAt = Number(row.created_at);
|
|
1740
|
+
const durationMs = Number(row.duration_ms ?? 0);
|
|
1736
1741
|
return {
|
|
1737
1742
|
id: String(row.id),
|
|
1738
1743
|
runId: String(row.run_id),
|
|
@@ -1747,14 +1752,15 @@ function rowToTraceSpan(row) {
|
|
|
1747
1752
|
cacheReadTokens: Number(row.cache_read_tokens ?? 0),
|
|
1748
1753
|
cacheWriteTokens: Number(row.cache_write_tokens ?? 0),
|
|
1749
1754
|
costCentsX100: Number(row.cost_cents_x100 ?? 0),
|
|
1750
|
-
durationMs
|
|
1755
|
+
durationMs,
|
|
1751
1756
|
status: row.status,
|
|
1752
1757
|
errorMessage: errorMessage && exposesErrorText
|
|
1753
1758
|
? sanitizeToolErrorMessage(errorMessage)
|
|
1754
1759
|
: null,
|
|
1755
1760
|
...(errorDetail ? { errorDetail } : {}),
|
|
1756
1761
|
metadata,
|
|
1757
|
-
createdAt
|
|
1762
|
+
createdAt,
|
|
1763
|
+
endedAt: row.ended_at == null ? createdAt + durationMs : Number(row.ended_at),
|
|
1758
1764
|
};
|
|
1759
1765
|
}
|
|
1760
1766
|
function rowToTraceSummary(row) {
|
|
@@ -219,6 +219,8 @@ function emitLlmGenerationTrackingEvent(args) {
|
|
|
219
219
|
model_selection_source: args.modelSelectionSource,
|
|
220
220
|
created_at: new Date(args.createdAt).toISOString(),
|
|
221
221
|
created_at_ms: args.createdAt,
|
|
222
|
+
ended_at: new Date(args.endedAt).toISOString(),
|
|
223
|
+
ended_at_ms: args.endedAt,
|
|
222
224
|
$ai_trace_id: args.runId,
|
|
223
225
|
$ai_session_id: args.threadId ?? undefined,
|
|
224
226
|
$ai_span_id: args.llmSpanId,
|
|
@@ -1004,6 +1006,7 @@ export async function instrumentAgentLoop(opts) {
|
|
|
1004
1006
|
spanId: trip.spanId,
|
|
1005
1007
|
model: trip.usage?.model ?? runUsage.model,
|
|
1006
1008
|
createdAt: trip.start,
|
|
1009
|
+
endedAt: trip.end,
|
|
1007
1010
|
latencyMs: Math.max(0, trip.end - trip.start),
|
|
1008
1011
|
callUsage: trip.usage,
|
|
1009
1012
|
stopReason: trip.stopReason,
|
|
@@ -1025,6 +1028,7 @@ export async function instrumentAgentLoop(opts) {
|
|
|
1025
1028
|
spanId: spanId(),
|
|
1026
1029
|
model: runUsage.model,
|
|
1027
1030
|
createdAt: runStart,
|
|
1031
|
+
endedAt: runStart + derivedLlmDurationMs,
|
|
1028
1032
|
latencyMs: derivedLlmDurationMs,
|
|
1029
1033
|
callUsage: usage,
|
|
1030
1034
|
stopReason: undefined,
|
|
@@ -1113,6 +1117,7 @@ export async function instrumentAgentLoop(opts) {
|
|
|
1113
1117
|
? capturedContent
|
|
1114
1118
|
: null,
|
|
1115
1119
|
createdAt: generation.createdAt,
|
|
1120
|
+
endedAt: generation.endedAt,
|
|
1116
1121
|
});
|
|
1117
1122
|
emitLlmGenerationTrackingEvent({
|
|
1118
1123
|
runId,
|
|
@@ -1154,6 +1159,7 @@ export async function instrumentAgentLoop(opts) {
|
|
|
1154
1159
|
: undefined,
|
|
1155
1160
|
delegation: opts.delegation,
|
|
1156
1161
|
createdAt: generation.createdAt,
|
|
1162
|
+
endedAt: generation.endedAt,
|
|
1157
1163
|
experimentAssignments: opts.experimentAssignments,
|
|
1158
1164
|
modelSelectionSource: opts.modelSelectionSource,
|
|
1159
1165
|
browserSessionId,
|
|
@@ -36,6 +36,8 @@ export interface TraceSpan {
|
|
|
36
36
|
errorDetail?: SpanErrorDetail;
|
|
37
37
|
metadata: Record<string, unknown> | null;
|
|
38
38
|
createdAt: number;
|
|
39
|
+
/** Request/span end time in epoch milliseconds. Older rows derive this from duration. */
|
|
40
|
+
endedAt?: number;
|
|
39
41
|
}
|
|
40
42
|
export interface TraceSummary {
|
|
41
43
|
runId: string;
|
|
@@ -39,8 +39,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
|
|
|
39
39
|
error: string;
|
|
40
40
|
}>;
|
|
41
41
|
export declare function handleDeleteResource(event: any): Promise<{
|
|
42
|
-
error: string;
|
|
43
42
|
ok?: undefined;
|
|
43
|
+
error: string;
|
|
44
44
|
} | {
|
|
45
45
|
error?: undefined;
|
|
46
46
|
ok: boolean;
|
|
@@ -66,12 +66,12 @@ export declare function createAgentEngineApiKeyHandler(): import("h3").EventHand
|
|
|
66
66
|
code: any;
|
|
67
67
|
} | {
|
|
68
68
|
errorCode?: undefined;
|
|
69
|
-
error?: undefined;
|
|
70
69
|
code?: undefined;
|
|
71
70
|
ok: boolean;
|
|
72
71
|
key: string;
|
|
73
72
|
baseUrlKey?: string;
|
|
74
73
|
scope: AgentEngineApiKeyScope;
|
|
75
74
|
defaultModel?: import("./agent-engine-default-model-route.js").SavedKeyDefaultModelOutcome;
|
|
75
|
+
error?: undefined;
|
|
76
76
|
}>>;
|
|
77
77
|
export {};
|
|
@@ -9,8 +9,8 @@ export declare const AGENT_ENGINE_API_KEY_ACTION_NAME = "agent-engine-api-key";
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function createAgentEngineDisconnectHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
11
11
|
error: string;
|
|
12
|
-
scope?: undefined;
|
|
13
12
|
ok?: undefined;
|
|
13
|
+
scope?: undefined;
|
|
14
14
|
} | {
|
|
15
15
|
ok: boolean;
|
|
16
16
|
error: any;
|
|
@@ -724,12 +724,14 @@ const BUILDER_WAITLIST_DEFAULT_USE_CASE = "builder_agent_background_coding";
|
|
|
724
724
|
const BUILDER_WAITLIST_USE_CASES = new Set([
|
|
725
725
|
BUILDER_WAITLIST_DEFAULT_USE_CASE,
|
|
726
726
|
"design_publish_app",
|
|
727
|
-
"design_make_real_waitlist",
|
|
728
|
-
"design_system_workflows_waitlist",
|
|
729
|
-
"design_system_waitlist",
|
|
730
727
|
"docs_build_online_waitlist",
|
|
731
728
|
"docs_edit_online_waitlist",
|
|
732
729
|
]);
|
|
730
|
+
const BUILDER_WAITLIST_USE_CASE_GROUPS = new Map([
|
|
731
|
+
["design_make_real_waitlist", "design_publish_app"],
|
|
732
|
+
["design_system_workflows_waitlist", "design_publish_app"],
|
|
733
|
+
["design_system_waitlist", "design_publish_app"],
|
|
734
|
+
]);
|
|
733
735
|
const BUILDER_WAITLIST_FORM_TIMEOUT_MS = 8000;
|
|
734
736
|
const BUILDER_WAITLIST_TEXT_LIMIT = 4000;
|
|
735
737
|
const BUILDER_WAITLIST_RATE_LIMIT_WINDOW_MS = 60_000;
|
|
@@ -766,9 +768,15 @@ function cleanBuilderWaitlistText(value, maxLength = BUILDER_WAITLIST_TEXT_LIMIT
|
|
|
766
768
|
}
|
|
767
769
|
function normalizeBuilderWaitlistUseCase(value) {
|
|
768
770
|
const useCase = cleanBuilderWaitlistText(value, 100);
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
771
|
+
if (!useCase)
|
|
772
|
+
return BUILDER_WAITLIST_DEFAULT_USE_CASE;
|
|
773
|
+
if (BUILDER_WAITLIST_USE_CASES.has(useCase))
|
|
774
|
+
return useCase;
|
|
775
|
+
// The published waitlist form validates this select against its own option
|
|
776
|
+
// list. Keep new Design entry points in the existing Design category; their
|
|
777
|
+
// exact surfaces remain in the text `source` field.
|
|
778
|
+
return (BUILDER_WAITLIST_USE_CASE_GROUPS.get(useCase) ??
|
|
779
|
+
BUILDER_WAITLIST_DEFAULT_USE_CASE);
|
|
772
780
|
}
|
|
773
781
|
function normalizeBuilderWaitlistTemplate(value) {
|
|
774
782
|
const template = cleanBuilderWaitlistText(value, 100);
|
|
@@ -54,8 +54,8 @@ export declare function createRealtimeTokenHandler(): import("h3").EventHandlerW
|
|
|
54
54
|
expiresAt?: undefined;
|
|
55
55
|
ttlSeconds?: undefined;
|
|
56
56
|
} | {
|
|
57
|
-
error?: undefined;
|
|
58
57
|
token: string;
|
|
59
58
|
expiresAt: string;
|
|
60
59
|
ttlSeconds: number;
|
|
60
|
+
error?: undefined;
|
|
61
61
|
}>>;
|
|
@@ -2,7 +2,6 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
2
2
|
resourceType: string;
|
|
3
3
|
resourceId: string;
|
|
4
4
|
}, {
|
|
5
|
-
role?: undefined;
|
|
6
5
|
ownerEmail: any;
|
|
7
6
|
visibility: any;
|
|
8
7
|
shares: any[];
|
|
@@ -12,6 +11,7 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
12
11
|
supportsGroupShares?: boolean;
|
|
13
12
|
};
|
|
14
13
|
orgId?: undefined;
|
|
14
|
+
role?: undefined;
|
|
15
15
|
agentReadable?: undefined;
|
|
16
16
|
} | {
|
|
17
17
|
ownerEmail: string;
|
|
@@ -70,9 +70,16 @@ unapproved work. Pair `✅` + `🎫` only for distinct scopes; name the fixed
|
|
|
70
70
|
behavior and ticket action. **Shipped**/**Live verified** alone don't earn
|
|
71
71
|
`✅`. Never remove reactions.
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
For every concrete objective defect, attempt to reproduce it before recording
|
|
74
|
+
an evidence limit or asking the reporter for more information. A screenshot,
|
|
75
|
+
error message, URL, or visible flow is enough to start tracing its owner; don't
|
|
76
|
+
wait for details that would not change the reproduction attempt. Phase 2's
|
|
77
|
+
local reproduction procedure applies to all defect reports, not only bashes.
|
|
78
|
+
|
|
79
|
+
If no safe repo-owned fix is evident after that attempt, record the specific
|
|
80
|
+
evidence limit. Ask only a question whose answer could change the reproduction
|
|
81
|
+
or unblock a fix; after four days without an answer, record **Abandoned - no
|
|
82
|
+
answer in 4 days**.
|
|
76
83
|
|
|
77
84
|
Use **Skipped** only for non-defects, never breakage. **Open - no question**
|
|
78
85
|
means you found neither a fix nor a useful question; state why in the thread.
|
|
@@ -340,6 +347,26 @@ screenshot is usually the whole diagnosis. Track an artifact that is
|
|
|
340
347
|
permission-gated or expired separately from one that was never provided —
|
|
341
348
|
inaccessible is not absent.
|
|
342
349
|
|
|
350
|
+
### Attempt local reproduction before evidence-limiting
|
|
351
|
+
|
|
352
|
+
For each concrete objective defect, try the reported flow before deciding it
|
|
353
|
+
cannot be reproduced or fixed. Trace the screenshot, URL, visible action, and
|
|
354
|
+
error through the app to its route, action, provider, or form contract; use
|
|
355
|
+
those clues to choose the closest runnable local seam. Exercise the flow with
|
|
356
|
+
a local build and synthetic fixtures. If its external dependency is unavailable,
|
|
357
|
+
mock that boundary or submit the same shape to a local validator. Do not use a
|
|
358
|
+
reporter's real email or create a real external record merely to prove a
|
|
359
|
+
failure.
|
|
360
|
+
|
|
361
|
+
Record the route or action, build, fixture, steps, expected and actual result,
|
|
362
|
+
and error. Code inspection alone is not a reproduction attempt, and
|
|
363
|
+
**Not reproducible - attempted** requires an actual flow attempt. Ask the
|
|
364
|
+
reporter only when a specific missing detail would change the attempt or fix;
|
|
365
|
+
otherwise make the best local attempt with the evidence already available.
|
|
366
|
+
If the attempt stops at a concrete access or environment limit, name what was
|
|
367
|
+
tried and what exact behavior remains untested. Measure misses with
|
|
368
|
+
`feedback-no-local-repro`.
|
|
369
|
+
|
|
343
370
|
**Sweep siblings before you claim anything is fixed.** Derive the fingerprint
|
|
344
371
|
from the symptom, not the file — the exact crashing token, call shape, or
|
|
345
372
|
literal — then search the repo for it and enumerate every hit in your recap
|
|
@@ -384,47 +411,10 @@ Measure this gate with friction keys `false-done` and
|
|
|
384
411
|
--pattern <key>` for each before changing it and again later. A climbing count
|
|
385
412
|
requires a mechanical proof or release gate, not more prose.
|
|
386
413
|
|
|
387
|
-
###
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
1. **Reproduce before editing.** Use the exact URL/route, app/template,
|
|
393
|
-
account/workspace/role, build/package, browser/device, fixture, and inputs;
|
|
394
|
-
record expected/actual, errors, and attached artifacts.
|
|
395
|
-
2. **Sweep siblings and boundaries.** Test a negative control plus empty, wrong,
|
|
396
|
-
whitespace, case, and permission variants; enumerate every shared fingerprint.
|
|
397
|
-
3. **Repeat on the changed running artifact.** Rerun the flow, refresh/navigate,
|
|
398
|
-
read UI and persisted state, and cover failure/retry/cancel/async paths.
|
|
399
|
-
Destructive flows require wrong/partial/exact confirmation and recovery;
|
|
400
|
-
do not delete unless needed.
|
|
401
|
-
4. **Test release/race layers when needed.** Use concurrency/10 runs, a clean
|
|
402
|
-
scaffold, and the exact package for package reports. Reproduce and verify
|
|
403
|
-
locally by default; use beta only if the full symptom cannot be reproduced
|
|
404
|
-
locally and hosted behavior is needed. Record why. These checks support
|
|
405
|
-
**Shipped**/**Live verified**, not a merged **Fixed** claim.
|
|
406
|
-
5. Record untested layers. Before merge, use an evidence-limited status. After
|
|
407
|
-
verified source merge, mark **Fixed** even if release/live layers remain;
|
|
408
|
-
routine rollout and optional beta checks aren't ticketed follow-ups.
|
|
409
|
-
**Shipped**/**Live verified** need their own bars. Don't mark **Fixed**/`✅`
|
|
410
|
-
without merged-source proof. Reopen repeats only with a fresh failing
|
|
411
|
-
pre-change reproduction.
|
|
412
|
-
|
|
413
|
-
### Reproduction ledger - required for every row
|
|
414
|
-
|
|
415
|
-
For each row, record symptom/surface, reproduction steps and account, expected
|
|
416
|
-
and pre/post behavior, tested commit/build, sibling results, untested layers,
|
|
417
|
-
and runtime layer (`local`, `source-only`, `built`, `deployed`, `observed-live`).
|
|
418
|
-
|
|
419
|
-
Without merged source proof, use an active or waiting disposition above. After
|
|
420
|
-
merge, **Fixed** may coexist with release follow-up; **Live verified** requires
|
|
421
|
-
all four bars. Status labels, reactions, and tests alone do not prove closure.
|
|
422
|
-
Repeats require a new pre-change failure and link the earlier false claim.
|
|
423
|
-
|
|
424
|
-
Regression claims require Red/Green proof: reverse-apply hunk with
|
|
425
|
-
`git apply -R`, record failure, reapply, record pass. Repeat timing checks 10x.
|
|
426
|
-
If output missing, build it and rerun on `origin/main` before calling them
|
|
427
|
-
pre-existing.
|
|
414
|
+
### Reproduction and verification detail
|
|
415
|
+
|
|
416
|
+
Use [`reproduction-and-verification.md`](references/reproduction-and-verification.md)
|
|
417
|
+
for the bug-bash contract, reproduction ledger, and regression proof.
|
|
428
418
|
|
|
429
419
|
### Npx and package reports have a release follow-up
|
|
430
420
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Reproduction and verification
|
|
2
|
+
|
|
3
|
+
Use this reference for the detailed reproduction ledger and deeper verification
|
|
4
|
+
contract. The skill's general rule still applies to every objective defect.
|
|
5
|
+
|
|
6
|
+
## Bug-bash reproduction contract
|
|
7
|
+
|
|
8
|
+
For Design, Slides, Core/framework, and template bashes, the reachable reported
|
|
9
|
+
surface is the contract:
|
|
10
|
+
|
|
11
|
+
1. **Reproduce before editing.** Use the exact URL/route, app/template,
|
|
12
|
+
account/workspace/role, build/package, browser/device, fixture, and inputs;
|
|
13
|
+
record expected/actual, errors, and attached artifacts.
|
|
14
|
+
2. **Sweep siblings and boundaries.** Test a negative control plus empty, wrong,
|
|
15
|
+
whitespace, case, and permission variants; enumerate every shared fingerprint.
|
|
16
|
+
3. **Repeat on the changed running artifact.** Rerun the flow, refresh/navigate,
|
|
17
|
+
read UI and persisted state, and cover failure/retry/cancel/async paths.
|
|
18
|
+
Destructive flows require wrong/partial/exact confirmation and recovery;
|
|
19
|
+
do not delete unless needed.
|
|
20
|
+
4. **Test release/race layers when needed.** Use concurrency/10 runs, a clean
|
|
21
|
+
scaffold, and the exact package for package reports. Reproduce and verify
|
|
22
|
+
locally by default; use beta only if the full symptom cannot be reproduced
|
|
23
|
+
locally and hosted behavior is needed. Record why. These checks support
|
|
24
|
+
**Shipped**/**Live verified**, not a merged **Fixed** claim.
|
|
25
|
+
5. Record untested layers. Before merge, use an evidence-limited status. After
|
|
26
|
+
verified source merge, mark **Fixed** even if release/live layers remain;
|
|
27
|
+
routine rollout and optional beta checks aren't ticketed follow-ups.
|
|
28
|
+
**Shipped**/**Live verified** need their own bars. Don't mark **Fixed**/`✅`
|
|
29
|
+
without merged-source proof. Reopen repeats only with a fresh failing
|
|
30
|
+
pre-change reproduction.
|
|
31
|
+
|
|
32
|
+
## Reproduction ledger
|
|
33
|
+
|
|
34
|
+
For each row, record symptom/surface, reproduction steps and account, expected
|
|
35
|
+
and pre/post behavior, tested commit/build, sibling results, untested layers,
|
|
36
|
+
and runtime layer (`local`, `source-only`, `built`, `deployed`, `observed-live`).
|
|
37
|
+
|
|
38
|
+
Without merged source proof, use an active or waiting disposition above. After
|
|
39
|
+
merge, **Fixed** may coexist with release follow-up; **Live verified** requires
|
|
40
|
+
all four bars. Status labels, reactions, and tests alone do not prove closure.
|
|
41
|
+
Repeats require a new pre-change failure and link the earlier false claim.
|
|
42
|
+
|
|
43
|
+
Regression claims require Red/Green proof: reverse-apply the hunk with
|
|
44
|
+
`git apply -R`, record failure, reapply, and record pass. Repeat timing checks
|
|
45
|
+
10x. If output is missing, build it and rerun on `origin/main` before calling
|
|
46
|
+
the behavior pre-existing.
|
|
@@ -284,9 +284,11 @@ the major product/UX decision above.
|
|
|
284
284
|
|
|
285
285
|
For a PR that passes the applicable gate and lacks a current-head approval,
|
|
286
286
|
submit one GitHub approval review and record the approval URL in the recap.
|
|
287
|
-
Do not duplicate an existing current-head approval.
|
|
288
|
-
assignment, mention, or explanatory comment
|
|
289
|
-
|
|
287
|
+
Do not duplicate an existing current-head approval. This skill reviews other
|
|
288
|
+
people's PRs: do not add a tag, assignment, mention, or explanatory comment
|
|
289
|
+
unless the current invocation explicitly authorizes that communication on the
|
|
290
|
+
exact PR. This does not add a separate authorization step for replies required
|
|
291
|
+
on the active user's own PR under `/ship`, `/ship-now`, or `/babysit-pr`.
|
|
290
292
|
|
|
291
293
|
Bot-authored PRs, including Dependabot, are outside this skill's review and
|
|
292
294
|
merge scope and must remain completely untouched.
|
|
@@ -29,8 +29,8 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
29
29
|
executionEngine?: undefined;
|
|
30
30
|
executionCwd?: undefined;
|
|
31
31
|
} | {
|
|
32
|
-
created?: undefined;
|
|
33
32
|
scope?: undefined;
|
|
33
|
+
created?: undefined;
|
|
34
34
|
triggerType?: undefined;
|
|
35
35
|
event?: undefined;
|
|
36
36
|
deleted: boolean;
|
|
@@ -45,8 +45,8 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
45
45
|
nextRun?: undefined;
|
|
46
46
|
webhookPath?: undefined;
|
|
47
47
|
} | {
|
|
48
|
-
created?: undefined;
|
|
49
48
|
scope?: undefined;
|
|
49
|
+
created?: undefined;
|
|
50
50
|
triggerType?: undefined;
|
|
51
51
|
event?: undefined;
|
|
52
52
|
deleted?: undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.203.
|
|
3
|
+
"version": "0.203.2-nightly-20261007213109",
|
|
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": {
|
|
@@ -682,7 +682,7 @@
|
|
|
682
682
|
"yaml": "^2.9.0",
|
|
683
683
|
"yjs": "^13.6.33",
|
|
684
684
|
"zod": "^4.3.6",
|
|
685
|
-
"@agent-native/agentkit": "^0.203.
|
|
685
|
+
"@agent-native/agentkit": "^0.203.2-nightly-20261007213109",
|
|
686
686
|
"@agent-native/recap-cli": "^0.5.65"
|
|
687
687
|
},
|
|
688
688
|
"devDependencies": {
|
|
@@ -753,7 +753,7 @@
|
|
|
753
753
|
"xlsx": "^0.18.5"
|
|
754
754
|
},
|
|
755
755
|
"peerDependencies": {
|
|
756
|
-
"@agent-native/core-corpus": "
|
|
756
|
+
"@agent-native/core-corpus": "0.203.2-nightly-20261007213109",
|
|
757
757
|
"@ai-sdk/anthropic": ">=3",
|
|
758
758
|
"@ai-sdk/cohere": ">=3",
|
|
759
759
|
"@ai-sdk/google": ">=3",
|
|
@@ -70,9 +70,16 @@ unapproved work. Pair `✅` + `🎫` only for distinct scopes; name the fixed
|
|
|
70
70
|
behavior and ticket action. **Shipped**/**Live verified** alone don't earn
|
|
71
71
|
`✅`. Never remove reactions.
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
For every concrete objective defect, attempt to reproduce it before recording
|
|
74
|
+
an evidence limit or asking the reporter for more information. A screenshot,
|
|
75
|
+
error message, URL, or visible flow is enough to start tracing its owner; don't
|
|
76
|
+
wait for details that would not change the reproduction attempt. Phase 2's
|
|
77
|
+
local reproduction procedure applies to all defect reports, not only bashes.
|
|
78
|
+
|
|
79
|
+
If no safe repo-owned fix is evident after that attempt, record the specific
|
|
80
|
+
evidence limit. Ask only a question whose answer could change the reproduction
|
|
81
|
+
or unblock a fix; after four days without an answer, record **Abandoned - no
|
|
82
|
+
answer in 4 days**.
|
|
76
83
|
|
|
77
84
|
Use **Skipped** only for non-defects, never breakage. **Open - no question**
|
|
78
85
|
means you found neither a fix nor a useful question; state why in the thread.
|
|
@@ -340,6 +347,26 @@ screenshot is usually the whole diagnosis. Track an artifact that is
|
|
|
340
347
|
permission-gated or expired separately from one that was never provided —
|
|
341
348
|
inaccessible is not absent.
|
|
342
349
|
|
|
350
|
+
### Attempt local reproduction before evidence-limiting
|
|
351
|
+
|
|
352
|
+
For each concrete objective defect, try the reported flow before deciding it
|
|
353
|
+
cannot be reproduced or fixed. Trace the screenshot, URL, visible action, and
|
|
354
|
+
error through the app to its route, action, provider, or form contract; use
|
|
355
|
+
those clues to choose the closest runnable local seam. Exercise the flow with
|
|
356
|
+
a local build and synthetic fixtures. If its external dependency is unavailable,
|
|
357
|
+
mock that boundary or submit the same shape to a local validator. Do not use a
|
|
358
|
+
reporter's real email or create a real external record merely to prove a
|
|
359
|
+
failure.
|
|
360
|
+
|
|
361
|
+
Record the route or action, build, fixture, steps, expected and actual result,
|
|
362
|
+
and error. Code inspection alone is not a reproduction attempt, and
|
|
363
|
+
**Not reproducible - attempted** requires an actual flow attempt. Ask the
|
|
364
|
+
reporter only when a specific missing detail would change the attempt or fix;
|
|
365
|
+
otherwise make the best local attempt with the evidence already available.
|
|
366
|
+
If the attempt stops at a concrete access or environment limit, name what was
|
|
367
|
+
tried and what exact behavior remains untested. Measure misses with
|
|
368
|
+
`feedback-no-local-repro`.
|
|
369
|
+
|
|
343
370
|
**Sweep siblings before you claim anything is fixed.** Derive the fingerprint
|
|
344
371
|
from the symptom, not the file — the exact crashing token, call shape, or
|
|
345
372
|
literal — then search the repo for it and enumerate every hit in your recap
|
|
@@ -384,47 +411,10 @@ Measure this gate with friction keys `false-done` and
|
|
|
384
411
|
--pattern <key>` for each before changing it and again later. A climbing count
|
|
385
412
|
requires a mechanical proof or release gate, not more prose.
|
|
386
413
|
|
|
387
|
-
###
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
1. **Reproduce before editing.** Use the exact URL/route, app/template,
|
|
393
|
-
account/workspace/role, build/package, browser/device, fixture, and inputs;
|
|
394
|
-
record expected/actual, errors, and attached artifacts.
|
|
395
|
-
2. **Sweep siblings and boundaries.** Test a negative control plus empty, wrong,
|
|
396
|
-
whitespace, case, and permission variants; enumerate every shared fingerprint.
|
|
397
|
-
3. **Repeat on the changed running artifact.** Rerun the flow, refresh/navigate,
|
|
398
|
-
read UI and persisted state, and cover failure/retry/cancel/async paths.
|
|
399
|
-
Destructive flows require wrong/partial/exact confirmation and recovery;
|
|
400
|
-
do not delete unless needed.
|
|
401
|
-
4. **Test release/race layers when needed.** Use concurrency/10 runs, a clean
|
|
402
|
-
scaffold, and the exact package for package reports. Reproduce and verify
|
|
403
|
-
locally by default; use beta only if the full symptom cannot be reproduced
|
|
404
|
-
locally and hosted behavior is needed. Record why. These checks support
|
|
405
|
-
**Shipped**/**Live verified**, not a merged **Fixed** claim.
|
|
406
|
-
5. Record untested layers. Before merge, use an evidence-limited status. After
|
|
407
|
-
verified source merge, mark **Fixed** even if release/live layers remain;
|
|
408
|
-
routine rollout and optional beta checks aren't ticketed follow-ups.
|
|
409
|
-
**Shipped**/**Live verified** need their own bars. Don't mark **Fixed**/`✅`
|
|
410
|
-
without merged-source proof. Reopen repeats only with a fresh failing
|
|
411
|
-
pre-change reproduction.
|
|
412
|
-
|
|
413
|
-
### Reproduction ledger - required for every row
|
|
414
|
-
|
|
415
|
-
For each row, record symptom/surface, reproduction steps and account, expected
|
|
416
|
-
and pre/post behavior, tested commit/build, sibling results, untested layers,
|
|
417
|
-
and runtime layer (`local`, `source-only`, `built`, `deployed`, `observed-live`).
|
|
418
|
-
|
|
419
|
-
Without merged source proof, use an active or waiting disposition above. After
|
|
420
|
-
merge, **Fixed** may coexist with release follow-up; **Live verified** requires
|
|
421
|
-
all four bars. Status labels, reactions, and tests alone do not prove closure.
|
|
422
|
-
Repeats require a new pre-change failure and link the earlier false claim.
|
|
423
|
-
|
|
424
|
-
Regression claims require Red/Green proof: reverse-apply hunk with
|
|
425
|
-
`git apply -R`, record failure, reapply, record pass. Repeat timing checks 10x.
|
|
426
|
-
If output missing, build it and rerun on `origin/main` before calling them
|
|
427
|
-
pre-existing.
|
|
414
|
+
### Reproduction and verification detail
|
|
415
|
+
|
|
416
|
+
Use [`reproduction-and-verification.md`](references/reproduction-and-verification.md)
|
|
417
|
+
for the bug-bash contract, reproduction ledger, and regression proof.
|
|
428
418
|
|
|
429
419
|
### Npx and package reports have a release follow-up
|
|
430
420
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Reproduction and verification
|
|
2
|
+
|
|
3
|
+
Use this reference for the detailed reproduction ledger and deeper verification
|
|
4
|
+
contract. The skill's general rule still applies to every objective defect.
|
|
5
|
+
|
|
6
|
+
## Bug-bash reproduction contract
|
|
7
|
+
|
|
8
|
+
For Design, Slides, Core/framework, and template bashes, the reachable reported
|
|
9
|
+
surface is the contract:
|
|
10
|
+
|
|
11
|
+
1. **Reproduce before editing.** Use the exact URL/route, app/template,
|
|
12
|
+
account/workspace/role, build/package, browser/device, fixture, and inputs;
|
|
13
|
+
record expected/actual, errors, and attached artifacts.
|
|
14
|
+
2. **Sweep siblings and boundaries.** Test a negative control plus empty, wrong,
|
|
15
|
+
whitespace, case, and permission variants; enumerate every shared fingerprint.
|
|
16
|
+
3. **Repeat on the changed running artifact.** Rerun the flow, refresh/navigate,
|
|
17
|
+
read UI and persisted state, and cover failure/retry/cancel/async paths.
|
|
18
|
+
Destructive flows require wrong/partial/exact confirmation and recovery;
|
|
19
|
+
do not delete unless needed.
|
|
20
|
+
4. **Test release/race layers when needed.** Use concurrency/10 runs, a clean
|
|
21
|
+
scaffold, and the exact package for package reports. Reproduce and verify
|
|
22
|
+
locally by default; use beta only if the full symptom cannot be reproduced
|
|
23
|
+
locally and hosted behavior is needed. Record why. These checks support
|
|
24
|
+
**Shipped**/**Live verified**, not a merged **Fixed** claim.
|
|
25
|
+
5. Record untested layers. Before merge, use an evidence-limited status. After
|
|
26
|
+
verified source merge, mark **Fixed** even if release/live layers remain;
|
|
27
|
+
routine rollout and optional beta checks aren't ticketed follow-ups.
|
|
28
|
+
**Shipped**/**Live verified** need their own bars. Don't mark **Fixed**/`✅`
|
|
29
|
+
without merged-source proof. Reopen repeats only with a fresh failing
|
|
30
|
+
pre-change reproduction.
|
|
31
|
+
|
|
32
|
+
## Reproduction ledger
|
|
33
|
+
|
|
34
|
+
For each row, record symptom/surface, reproduction steps and account, expected
|
|
35
|
+
and pre/post behavior, tested commit/build, sibling results, untested layers,
|
|
36
|
+
and runtime layer (`local`, `source-only`, `built`, `deployed`, `observed-live`).
|
|
37
|
+
|
|
38
|
+
Without merged source proof, use an active or waiting disposition above. After
|
|
39
|
+
merge, **Fixed** may coexist with release follow-up; **Live verified** requires
|
|
40
|
+
all four bars. Status labels, reactions, and tests alone do not prove closure.
|
|
41
|
+
Repeats require a new pre-change failure and link the earlier false claim.
|
|
42
|
+
|
|
43
|
+
Regression claims require Red/Green proof: reverse-apply the hunk with
|
|
44
|
+
`git apply -R`, record failure, reapply, and record pass. Repeat timing checks
|
|
45
|
+
10x. If output is missing, build it and rerun on `origin/main` before calling
|
|
46
|
+
the behavior pre-existing.
|
|
@@ -284,9 +284,11 @@ the major product/UX decision above.
|
|
|
284
284
|
|
|
285
285
|
For a PR that passes the applicable gate and lacks a current-head approval,
|
|
286
286
|
submit one GitHub approval review and record the approval URL in the recap.
|
|
287
|
-
Do not duplicate an existing current-head approval.
|
|
288
|
-
assignment, mention, or explanatory comment
|
|
289
|
-
|
|
287
|
+
Do not duplicate an existing current-head approval. This skill reviews other
|
|
288
|
+
people's PRs: do not add a tag, assignment, mention, or explanatory comment
|
|
289
|
+
unless the current invocation explicitly authorizes that communication on the
|
|
290
|
+
exact PR. This does not add a separate authorization step for replies required
|
|
291
|
+
on the active user's own PR under `/ship`, `/ship-now`, or `/babysit-pr`.
|
|
290
292
|
|
|
291
293
|
Bot-authored PRs, including Dependabot, are outside this skill's review and
|
|
292
294
|
merge scope and must remain completely untouched.
|