@agent-native/core 0.203.0-nightly-20261007064822 → 0.203.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/engine/builder-engine.d.ts +1 -1
- package/dist/agent/model-config.d.ts +2 -2
- package/dist/agent/model-config.js +0 -2
- package/dist/agent/thread-data-builder.d.ts +6 -0
- package/dist/agent/thread-data-builder.js +747 -25
- package/dist/agent/thread-message-projection.d.ts +20 -0
- package/dist/agent/thread-message-projection.js +300 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/chat-threads/store.d.ts +4 -1
- package/dist/chat-threads/store.js +92 -17
- package/dist/cli/skills-content/turn-into-app-skill.d.ts +10 -4
- package/dist/cli/skills-content/turn-into-app-skill.js +2454 -705
- package/dist/cli/skills.d.ts +6 -0
- package/dist/cli/skills.js +8 -2
- package/dist/client/chat/agentkit-agent-native.js +839 -89
- package/dist/client/chat/agentkit-protocol.js +67 -17
- package/dist/collab/routes.d.ts +2 -2
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/mcp/build-server.d.ts +5 -1
- package/dist/mcp/build-server.js +56 -13
- package/dist/mcp/embed-app.js +6 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/index.d.ts +2 -2
- package/dist/provider-api/actions/provider-api.d.ts +4 -4
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-chat/mcp-options.d.ts +4 -0
- package/dist/server/agent-chat-plugin.js +97 -22
- package/dist/server/agent-engine-default-model-route.d.ts +2 -2
- package/dist/server/onboarding-html.js +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/embed-auth.js +5 -4
- package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +26 -24
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/deployment-recovery.md +53 -0
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/documentation-proof.md +7 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +284 -461
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +65 -90
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/local-run-and-deploy.md +161 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/review-loop.md +384 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/source-brief.md +116 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/spreadsheet-source.md +206 -190
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/ui-archetypes.md +381 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/ui-direction.md +323 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/ui-palettes.md +564 -0
- package/dist/triggers/actions/manage-automation.d.ts +7 -7
- package/docs/content/observability.mdx +136 -0
- package/package.json +4 -4
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +26 -24
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/deployment-recovery.md +53 -0
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/documentation-proof.md +7 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +284 -461
- package/src/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +65 -90
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/local-run-and-deploy.md +161 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/review-loop.md +384 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/source-brief.md +116 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/spreadsheet-source.md +206 -190
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/ui-archetypes.md +381 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/ui-direction.md +323 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/ui-palettes.md +564 -0
|
@@ -1165,11 +1165,8 @@ function snapshotEntryId(entry, kind) {
|
|
|
1165
1165
|
if (!entry || typeof entry !== "object")
|
|
1166
1166
|
return undefined;
|
|
1167
1167
|
if (kind === "widget") {
|
|
1168
|
-
const messageId = entry.messageId;
|
|
1169
1168
|
const widgetId = entry.widget?.id;
|
|
1170
|
-
return typeof
|
|
1171
|
-
? JSON.stringify([messageId, widgetId])
|
|
1172
|
-
: undefined;
|
|
1169
|
+
return typeof widgetId === "string" ? widgetId : undefined;
|
|
1173
1170
|
}
|
|
1174
1171
|
return typeof entry.id === "string" ? entry.id : undefined;
|
|
1175
1172
|
}
|
|
@@ -1384,6 +1381,9 @@ function latestSnapshotRun(runs) {
|
|
|
1384
1381
|
return latestTime && runTime && runTime < latestTime ? latest : run;
|
|
1385
1382
|
}, undefined);
|
|
1386
1383
|
}
|
|
1384
|
+
function isTerminalRunStatus(status) {
|
|
1385
|
+
return (status === "completed" || status === "failed" || status === "cancelled");
|
|
1386
|
+
}
|
|
1387
1387
|
function latestStoredUser(repo) {
|
|
1388
1388
|
return repo?.messages
|
|
1389
1389
|
?.map((entry) => getStoredMessage(entry))
|
|
@@ -1453,13 +1453,19 @@ export function foldThreadRunSuggestions(repo, run) {
|
|
|
1453
1453
|
? previous.runs
|
|
1454
1454
|
: [];
|
|
1455
1455
|
const oldRun = runs.find((entry) => entry.id === run.runId);
|
|
1456
|
+
const previousSequence = oldRun &&
|
|
1457
|
+
Number.isSafeInteger(oldRun.lastSequence) &&
|
|
1458
|
+
oldRun.lastSequence >= 0
|
|
1459
|
+
? oldRun.lastSequence
|
|
1460
|
+
: 0;
|
|
1461
|
+
const lastSequence = run.events.reduce((maximum, { seq }) => Number.isSafeInteger(seq) && seq >= 0 ? Math.max(maximum, seq) : maximum, previousSequence);
|
|
1456
1462
|
const snapshot = {
|
|
1457
1463
|
...oldRun,
|
|
1458
1464
|
id: run.runId,
|
|
1459
1465
|
threadId: run.threadId,
|
|
1460
1466
|
status,
|
|
1461
1467
|
startedAt,
|
|
1462
|
-
lastSequence
|
|
1468
|
+
lastSequence,
|
|
1463
1469
|
};
|
|
1464
1470
|
return {
|
|
1465
1471
|
...repo,
|
|
@@ -1471,17 +1477,600 @@ export function foldThreadRunSuggestions(repo, run) {
|
|
|
1471
1477
|
},
|
|
1472
1478
|
};
|
|
1473
1479
|
}
|
|
1474
|
-
function
|
|
1475
|
-
if (!existing
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1480
|
+
function mergeAgentKitEvents(existing, incoming, replacedRunIds = new Set(), staleRunIds = new Set()) {
|
|
1481
|
+
if (!Array.isArray(existing) && !Array.isArray(incoming))
|
|
1482
|
+
return undefined;
|
|
1483
|
+
const incomingEvents = Array.isArray(incoming)
|
|
1484
|
+
? incoming.filter((event) => typeof event?.runId !== "string" || !staleRunIds.has(event.runId))
|
|
1485
|
+
: [];
|
|
1486
|
+
const merged = Array.isArray(existing)
|
|
1487
|
+
? existing.filter((event) => typeof event?.runId !== "string" || !replacedRunIds.has(event.runId))
|
|
1488
|
+
: [];
|
|
1489
|
+
const positions = new Map();
|
|
1490
|
+
merged.forEach((event, index) => {
|
|
1491
|
+
if (typeof event?.id === "string" && !positions.has(event.id)) {
|
|
1492
|
+
positions.set(event.id, index);
|
|
1493
|
+
}
|
|
1494
|
+
});
|
|
1495
|
+
for (const event of incomingEvents) {
|
|
1496
|
+
if (typeof event?.id !== "string") {
|
|
1497
|
+
merged.push(event);
|
|
1498
|
+
continue;
|
|
1499
|
+
}
|
|
1500
|
+
const index = positions.get(event.id);
|
|
1501
|
+
if (index === undefined) {
|
|
1502
|
+
positions.set(event.id, merged.length);
|
|
1503
|
+
merged.push(event);
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
merged[index] = event;
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
const positionsByRun = new Map();
|
|
1510
|
+
merged.forEach((event, index) => {
|
|
1511
|
+
if (typeof event?.runId !== "string")
|
|
1512
|
+
return;
|
|
1513
|
+
const runPositions = positionsByRun.get(event.runId) ?? [];
|
|
1514
|
+
runPositions.push(index);
|
|
1515
|
+
positionsByRun.set(event.runId, runPositions);
|
|
1516
|
+
});
|
|
1517
|
+
for (const runPositions of positionsByRun.values()) {
|
|
1518
|
+
const runEvents = runPositions.map((index, order) => ({
|
|
1519
|
+
event: merged[index],
|
|
1520
|
+
index,
|
|
1521
|
+
order,
|
|
1522
|
+
sequence: typeof merged[index]?.sequence === "number" &&
|
|
1523
|
+
Number.isFinite(merged[index].sequence)
|
|
1524
|
+
? merged[index].sequence
|
|
1525
|
+
: Number.NaN,
|
|
1526
|
+
}));
|
|
1527
|
+
runEvents.sort((left, right) => {
|
|
1528
|
+
if (Number.isFinite(left.sequence) &&
|
|
1529
|
+
Number.isFinite(right.sequence) &&
|
|
1530
|
+
left.sequence !== right.sequence) {
|
|
1531
|
+
return left.sequence - right.sequence;
|
|
1532
|
+
}
|
|
1533
|
+
return left.order - right.order;
|
|
1534
|
+
});
|
|
1535
|
+
runPositions.forEach((index, order) => {
|
|
1536
|
+
merged[index] = { ...runEvents[order].event, sequence: order + 1 };
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1539
|
+
return merged;
|
|
1540
|
+
}
|
|
1541
|
+
function mergeAgentKitFullEventSnapshot(existingEvents, incomingEvents, incomingRuns, committedSnapshots) {
|
|
1542
|
+
if (!Array.isArray(incomingEvents))
|
|
1543
|
+
return undefined;
|
|
1544
|
+
const previousEvents = Array.isArray(existingEvents) ? existingEvents : [];
|
|
1545
|
+
const incomingRunSequences = new Map();
|
|
1546
|
+
for (const run of Array.isArray(incomingRuns) ? incomingRuns : []) {
|
|
1547
|
+
if (typeof run?.id === "string" &&
|
|
1548
|
+
typeof run.lastSequence === "number" &&
|
|
1549
|
+
Number.isSafeInteger(run.lastSequence) &&
|
|
1550
|
+
run.lastSequence >= 0) {
|
|
1551
|
+
incomingRunSequences.set(run.id, run.lastSequence);
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
const existingEventsByRun = new Map();
|
|
1555
|
+
for (const event of previousEvents) {
|
|
1556
|
+
if (typeof event?.runId !== "string")
|
|
1557
|
+
continue;
|
|
1558
|
+
const events = existingEventsByRun.get(event.runId) ?? [];
|
|
1559
|
+
events.push(event);
|
|
1560
|
+
existingEventsByRun.set(event.runId, events);
|
|
1561
|
+
}
|
|
1562
|
+
const incomingEventsByRun = new Map();
|
|
1563
|
+
for (const event of incomingEvents) {
|
|
1564
|
+
if (typeof event?.runId !== "string")
|
|
1565
|
+
continue;
|
|
1566
|
+
const events = incomingEventsByRun.get(event.runId) ?? [];
|
|
1567
|
+
events.push(event);
|
|
1568
|
+
incomingEventsByRun.set(event.runId, events);
|
|
1569
|
+
}
|
|
1570
|
+
const protectedRunIds = new Set();
|
|
1571
|
+
if (committedSnapshots &&
|
|
1572
|
+
typeof committedSnapshots === "object" &&
|
|
1573
|
+
!Array.isArray(committedSnapshots)) {
|
|
1574
|
+
for (const [runId, value] of Object.entries(committedSnapshots)) {
|
|
1575
|
+
if (!Array.isArray(value))
|
|
1576
|
+
continue;
|
|
1577
|
+
const committedSequence = value.reduce((maxSequence, entry) => {
|
|
1578
|
+
const sequence = entry?.lastSequence;
|
|
1579
|
+
return typeof sequence === "number" &&
|
|
1580
|
+
Number.isSafeInteger(sequence) &&
|
|
1581
|
+
sequence >= 0
|
|
1582
|
+
? Math.max(maxSequence, sequence)
|
|
1583
|
+
: maxSequence;
|
|
1584
|
+
}, -1);
|
|
1585
|
+
if (committedSequence < 0)
|
|
1586
|
+
continue;
|
|
1587
|
+
const runEvents = incomingEventsByRun.get(runId) ?? [];
|
|
1588
|
+
const incomingSequence = Math.max(incomingRunSequences.get(runId) ?? 0, ...runEvents.map((event) => {
|
|
1589
|
+
const sequence = event && typeof event === "object"
|
|
1590
|
+
? event.sequence
|
|
1591
|
+
: undefined;
|
|
1592
|
+
return typeof sequence === "number" &&
|
|
1593
|
+
Number.isSafeInteger(sequence) &&
|
|
1594
|
+
sequence >= 0
|
|
1595
|
+
? sequence
|
|
1596
|
+
: 0;
|
|
1597
|
+
}));
|
|
1598
|
+
if (runEvents.length === 0 || incomingSequence <= committedSequence) {
|
|
1599
|
+
protectedRunIds.add(runId);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
if (protectedRunIds.size === 0)
|
|
1604
|
+
return incomingEvents;
|
|
1605
|
+
const merged = [];
|
|
1606
|
+
const insertedProtectedRuns = new Set();
|
|
1607
|
+
for (const event of incomingEvents) {
|
|
1608
|
+
const runId = event?.runId;
|
|
1609
|
+
if (typeof runId === "string" && protectedRunIds.has(runId)) {
|
|
1610
|
+
if (!insertedProtectedRuns.has(runId)) {
|
|
1611
|
+
merged.push(...(existingEventsByRun.get(runId) ?? []));
|
|
1612
|
+
insertedProtectedRuns.add(runId);
|
|
1613
|
+
}
|
|
1614
|
+
continue;
|
|
1615
|
+
}
|
|
1616
|
+
merged.push(event);
|
|
1617
|
+
}
|
|
1618
|
+
for (const runId of protectedRunIds) {
|
|
1619
|
+
if (insertedProtectedRuns.has(runId))
|
|
1620
|
+
continue;
|
|
1621
|
+
merged.push(...(existingEventsByRun.get(runId) ?? []));
|
|
1622
|
+
}
|
|
1623
|
+
return merged;
|
|
1624
|
+
}
|
|
1625
|
+
const MAX_PENDING_EVENT_RUN_SNAPSHOTS_PER_RUN = 2;
|
|
1626
|
+
const MAX_COMMITTED_EVENT_RUN_SNAPSHOTS_PER_RUN = 8;
|
|
1627
|
+
function mergeAgentKitEventRunSnapshots(input) {
|
|
1628
|
+
const incomingEvents = Array.isArray(input.incomingEvents)
|
|
1629
|
+
? input.incomingEvents
|
|
1630
|
+
: [];
|
|
1631
|
+
const batchedRunIds = new Set(input.batches.keys());
|
|
1632
|
+
const unbatchedEvents = Array.isArray(input.incomingEvents)
|
|
1633
|
+
? incomingEvents.filter((event) => !batchedRunIds.has(event?.runId))
|
|
1634
|
+
: undefined;
|
|
1635
|
+
const previousEvents = Array.isArray(input.existingEvents)
|
|
1636
|
+
? input.existingEvents
|
|
1637
|
+
: [];
|
|
1638
|
+
const commits = {};
|
|
1639
|
+
if (input.existingCommits &&
|
|
1640
|
+
typeof input.existingCommits === "object" &&
|
|
1641
|
+
!Array.isArray(input.existingCommits)) {
|
|
1642
|
+
for (const [runId, value] of Object.entries(input.existingCommits)) {
|
|
1643
|
+
if (!Array.isArray(value))
|
|
1644
|
+
continue;
|
|
1645
|
+
const entries = value.flatMap((candidate) => {
|
|
1646
|
+
if (!candidate || typeof candidate !== "object")
|
|
1647
|
+
return [];
|
|
1648
|
+
const commit = candidate;
|
|
1649
|
+
if (typeof commit.snapshotId !== "string" ||
|
|
1650
|
+
typeof commit.lastSequence !== "number" ||
|
|
1651
|
+
!Number.isSafeInteger(commit.lastSequence) ||
|
|
1652
|
+
commit.lastSequence < 0 ||
|
|
1653
|
+
typeof commit.expectedEventCount !== "number" ||
|
|
1654
|
+
!Number.isSafeInteger(commit.expectedEventCount) ||
|
|
1655
|
+
commit.expectedEventCount < 1) {
|
|
1656
|
+
return [];
|
|
1657
|
+
}
|
|
1658
|
+
return [
|
|
1659
|
+
{
|
|
1660
|
+
snapshotId: commit.snapshotId,
|
|
1661
|
+
lastSequence: commit.lastSequence,
|
|
1662
|
+
expectedEventCount: commit.expectedEventCount,
|
|
1663
|
+
},
|
|
1664
|
+
];
|
|
1665
|
+
});
|
|
1666
|
+
if (entries.length > 0) {
|
|
1667
|
+
commits[runId] = entries.slice(-MAX_COMMITTED_EVENT_RUN_SNAPSHOTS_PER_RUN);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
const watermarks = new Map(input.existingWatermarks);
|
|
1672
|
+
const replacedRunIds = new Set();
|
|
1673
|
+
const staleRunIds = new Set();
|
|
1674
|
+
for (const [runId, lastSequence] of input.incomingWatermarks) {
|
|
1675
|
+
const storedWatermark = watermarks.get(runId);
|
|
1676
|
+
const storedRunSequence = input.existingRunSequences.get(runId);
|
|
1677
|
+
const hasCommittedSnapshot = (commits[runId]?.length ?? 0) > 0;
|
|
1678
|
+
const committedSequence = Math.max(0, ...(commits[runId] ?? []).map((entry) => entry.lastSequence));
|
|
1679
|
+
const knownSequence = Math.max(storedWatermark ?? 0, storedRunSequence ?? 0, committedSequence);
|
|
1680
|
+
const hasKnownSequence = storedWatermark !== undefined ||
|
|
1681
|
+
storedRunSequence !== undefined ||
|
|
1682
|
+
hasCommittedSnapshot;
|
|
1683
|
+
const hasStoredEvents = previousEvents.some((event) => event?.runId === runId);
|
|
1684
|
+
if ((hasKnownSequence && lastSequence < knownSequence) ||
|
|
1685
|
+
(hasCommittedSnapshot && lastSequence <= committedSequence)) {
|
|
1686
|
+
staleRunIds.add(runId);
|
|
1687
|
+
continue;
|
|
1688
|
+
}
|
|
1689
|
+
if (input.incomingReplacements.has(runId) &&
|
|
1690
|
+
(hasKnownSequence || !hasStoredEvents)) {
|
|
1691
|
+
replacedRunIds.add(runId);
|
|
1692
|
+
}
|
|
1693
|
+
watermarks.set(runId, Math.max(knownSequence, lastSequence));
|
|
1694
|
+
}
|
|
1695
|
+
let events = mergeAgentKitEvents(input.existingEvents, unbatchedEvents, replacedRunIds, staleRunIds);
|
|
1696
|
+
const pending = {};
|
|
1697
|
+
if (input.existingPending &&
|
|
1698
|
+
typeof input.existingPending === "object" &&
|
|
1699
|
+
!Array.isArray(input.existingPending)) {
|
|
1700
|
+
for (const [runId, value] of Object.entries(input.existingPending)) {
|
|
1701
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1702
|
+
continue;
|
|
1703
|
+
}
|
|
1704
|
+
const batches = {};
|
|
1705
|
+
for (const [snapshotId, candidate] of Object.entries(value)) {
|
|
1706
|
+
if (!candidate || typeof candidate !== "object")
|
|
1707
|
+
continue;
|
|
1708
|
+
const candidateRecord = candidate;
|
|
1709
|
+
if (Array.isArray(candidate) ||
|
|
1710
|
+
typeof candidateRecord.lastSequence !== "number" ||
|
|
1711
|
+
!Number.isSafeInteger(candidateRecord.lastSequence) ||
|
|
1712
|
+
candidateRecord.lastSequence < 0 ||
|
|
1713
|
+
typeof candidateRecord.expectedEventCount !== "number" ||
|
|
1714
|
+
!Number.isSafeInteger(candidateRecord.expectedEventCount) ||
|
|
1715
|
+
candidateRecord.expectedEventCount < 1 ||
|
|
1716
|
+
!Array.isArray(candidateRecord.events)) {
|
|
1717
|
+
continue;
|
|
1718
|
+
}
|
|
1719
|
+
batches[snapshotId] = {
|
|
1720
|
+
lastSequence: candidateRecord.lastSequence,
|
|
1721
|
+
expectedEventCount: candidateRecord.expectedEventCount,
|
|
1722
|
+
events: candidateRecord.events.filter((event) => event?.runId === runId),
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
if (Object.keys(batches).length > 0)
|
|
1726
|
+
pending[runId] = batches;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
for (const [runId, batches] of Object.entries(pending)) {
|
|
1730
|
+
const committedSequence = Math.max(watermarks.get(runId) ?? 0, input.existingRunSequences.get(runId) ?? 0);
|
|
1731
|
+
if (!watermarks.has(runId) && !input.existingRunSequences.has(runId)) {
|
|
1732
|
+
continue;
|
|
1733
|
+
}
|
|
1734
|
+
for (const [snapshotId, batch] of Object.entries(batches)) {
|
|
1735
|
+
const supersededByLegacySnapshot = (input.incomingWatermarks.get(runId) ?? -1) >= batch.lastSequence;
|
|
1736
|
+
if (batch.lastSequence < committedSequence ||
|
|
1737
|
+
supersededByLegacySnapshot) {
|
|
1738
|
+
delete batches[snapshotId];
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
if (Object.keys(batches).length === 0)
|
|
1742
|
+
delete pending[runId];
|
|
1743
|
+
}
|
|
1744
|
+
for (const [runId, batch] of input.batches) {
|
|
1745
|
+
const committed = commits[runId]?.find((entry) => entry.snapshotId === batch.snapshotId);
|
|
1746
|
+
if (committed) {
|
|
1747
|
+
if (committed.lastSequence !== batch.lastSequence ||
|
|
1748
|
+
committed.expectedEventCount !== batch.expectedEventCount) {
|
|
1749
|
+
throw new TypeError("Agent chat event snapshot id was reused.");
|
|
1750
|
+
}
|
|
1751
|
+
continue;
|
|
1752
|
+
}
|
|
1753
|
+
const knownSequence = Math.max(watermarks.get(runId) ?? 0, input.existingRunSequences.get(runId) ?? 0);
|
|
1754
|
+
const hasKnownSequence = watermarks.has(runId) || input.existingRunSequences.has(runId);
|
|
1755
|
+
const alreadyCommittedAtOrAfter = (commits[runId] ?? []).some((entry) => entry.lastSequence >= batch.lastSequence);
|
|
1756
|
+
if (hasKnownSequence &&
|
|
1757
|
+
(batch.lastSequence < knownSequence || alreadyCommittedAtOrAfter)) {
|
|
1758
|
+
if (pending[runId]) {
|
|
1759
|
+
delete pending[runId][batch.snapshotId];
|
|
1760
|
+
if (Object.keys(pending[runId]).length === 0)
|
|
1761
|
+
delete pending[runId];
|
|
1762
|
+
}
|
|
1763
|
+
continue;
|
|
1764
|
+
}
|
|
1765
|
+
const current = pending[runId]?.[batch.snapshotId];
|
|
1766
|
+
const matchingCurrent = current?.lastSequence === batch.lastSequence &&
|
|
1767
|
+
current.expectedEventCount === batch.expectedEventCount;
|
|
1768
|
+
const batchEvents = incomingEvents.filter((event) => event?.runId === runId);
|
|
1769
|
+
const stagedEvents = mergeAgentKitEvents(matchingCurrent ? current.events : [], batchEvents) ??
|
|
1770
|
+
[];
|
|
1771
|
+
if (stagedEvents.length > batch.expectedEventCount) {
|
|
1772
|
+
throw new TypeError("Agent chat event snapshot exceeded its event count.");
|
|
1773
|
+
}
|
|
1774
|
+
if (batch.complete && stagedEvents.length < batch.expectedEventCount) {
|
|
1775
|
+
throw new TypeError("Agent chat event snapshot ended before all events arrived.");
|
|
1776
|
+
}
|
|
1777
|
+
if (stagedEvents.length === batch.expectedEventCount) {
|
|
1778
|
+
events = mergeAgentKitEvents(events, stagedEvents, new Set([runId]));
|
|
1779
|
+
watermarks.set(runId, Math.max(knownSequence, batch.lastSequence));
|
|
1780
|
+
commits[runId] = [
|
|
1781
|
+
...(commits[runId] ?? []).filter((entry) => entry.snapshotId !== batch.snapshotId),
|
|
1782
|
+
{
|
|
1783
|
+
snapshotId: batch.snapshotId,
|
|
1784
|
+
lastSequence: batch.lastSequence,
|
|
1785
|
+
expectedEventCount: batch.expectedEventCount,
|
|
1786
|
+
},
|
|
1787
|
+
].slice(-MAX_COMMITTED_EVENT_RUN_SNAPSHOTS_PER_RUN);
|
|
1788
|
+
if (pending[runId]) {
|
|
1789
|
+
for (const [snapshotId, pendingBatch] of Object.entries(pending[runId])) {
|
|
1790
|
+
if (pendingBatch.lastSequence <= batch.lastSequence) {
|
|
1791
|
+
delete pending[runId][snapshotId];
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
if (Object.keys(pending[runId]).length === 0)
|
|
1795
|
+
delete pending[runId];
|
|
1796
|
+
}
|
|
1797
|
+
continue;
|
|
1798
|
+
}
|
|
1799
|
+
const runPending = { ...(pending[runId] ?? {}) };
|
|
1800
|
+
if (!matchingCurrent) {
|
|
1801
|
+
while (Object.keys(runPending).length >=
|
|
1802
|
+
MAX_PENDING_EVENT_RUN_SNAPSHOTS_PER_RUN) {
|
|
1803
|
+
const oldestSnapshotId = Object.keys(runPending)[0];
|
|
1804
|
+
if (oldestSnapshotId === undefined)
|
|
1805
|
+
break;
|
|
1806
|
+
delete runPending[oldestSnapshotId];
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
runPending[batch.snapshotId] = {
|
|
1810
|
+
lastSequence: batch.lastSequence,
|
|
1811
|
+
expectedEventCount: batch.expectedEventCount,
|
|
1812
|
+
events: stagedEvents,
|
|
1813
|
+
};
|
|
1814
|
+
pending[runId] = runPending;
|
|
1815
|
+
}
|
|
1816
|
+
return { events, watermarks, pending, commits };
|
|
1817
|
+
}
|
|
1818
|
+
function mergeAgentKitAnnotations(existing, incoming, replaceMessageIds, removalValuesByMessage, conditionalUpserts, onConflict) {
|
|
1819
|
+
if (!Array.isArray(existing) && !Array.isArray(incoming))
|
|
1820
|
+
return undefined;
|
|
1821
|
+
const annotationKey = (entry) => {
|
|
1822
|
+
const id = entry?.annotation?.id;
|
|
1823
|
+
return typeof id === "string"
|
|
1824
|
+
? JSON.stringify(["id", id])
|
|
1825
|
+
: JSON.stringify(["value", entry]);
|
|
1826
|
+
};
|
|
1827
|
+
const merged = (Array.isArray(existing) ? existing : []).filter((entry) => {
|
|
1828
|
+
const messageId = entry?.messageId;
|
|
1829
|
+
if (replaceMessageIds.has(messageId))
|
|
1830
|
+
return false;
|
|
1831
|
+
const removalValues = removalValuesByMessage.get(messageId);
|
|
1832
|
+
const baseline = removalValues?.get(annotationKey(entry));
|
|
1833
|
+
if (baseline === undefined)
|
|
1834
|
+
return true;
|
|
1835
|
+
if (JSON.stringify(entry) === baseline)
|
|
1836
|
+
return false;
|
|
1837
|
+
if (typeof messageId === "string") {
|
|
1838
|
+
const annotationId = entry?.annotation?.id;
|
|
1839
|
+
onConflict?.({
|
|
1840
|
+
messageId,
|
|
1841
|
+
...(typeof annotationId === "string" ? { annotationId } : {}),
|
|
1842
|
+
operation: "remove",
|
|
1843
|
+
});
|
|
1844
|
+
}
|
|
1845
|
+
return true;
|
|
1846
|
+
});
|
|
1847
|
+
const positions = new Map();
|
|
1848
|
+
merged.forEach((entry, index) => {
|
|
1849
|
+
if (typeof entry?.messageId !== "string")
|
|
1850
|
+
return;
|
|
1851
|
+
const key = JSON.stringify([entry.messageId, annotationKey(entry)]);
|
|
1852
|
+
if (!positions.has(key))
|
|
1853
|
+
positions.set(key, index);
|
|
1854
|
+
});
|
|
1855
|
+
if (Array.isArray(conditionalUpserts)) {
|
|
1856
|
+
for (const update of conditionalUpserts) {
|
|
1857
|
+
if (!update ||
|
|
1858
|
+
typeof update !== "object" ||
|
|
1859
|
+
!update.entry ||
|
|
1860
|
+
typeof update.entry !== "object" ||
|
|
1861
|
+
Array.isArray(update.entry) ||
|
|
1862
|
+
(update.baseline !== null &&
|
|
1863
|
+
(!update.baseline ||
|
|
1864
|
+
typeof update.baseline !== "object" ||
|
|
1865
|
+
Array.isArray(update.baseline)))) {
|
|
1866
|
+
continue;
|
|
1867
|
+
}
|
|
1868
|
+
const entry = update.entry;
|
|
1869
|
+
if (typeof entry.messageId !== "string") {
|
|
1870
|
+
merged.push(entry);
|
|
1871
|
+
continue;
|
|
1872
|
+
}
|
|
1873
|
+
const key = JSON.stringify([entry.messageId, annotationKey(entry)]);
|
|
1874
|
+
const index = positions.get(key);
|
|
1875
|
+
if (index === undefined) {
|
|
1876
|
+
if (update.baseline === null) {
|
|
1877
|
+
positions.set(key, merged.length);
|
|
1878
|
+
merged.push(entry);
|
|
1879
|
+
}
|
|
1880
|
+
else {
|
|
1881
|
+
const annotationId = entry.annotation?.id;
|
|
1882
|
+
onConflict?.({
|
|
1883
|
+
messageId: entry.messageId,
|
|
1884
|
+
...(typeof annotationId === "string" ? { annotationId } : {}),
|
|
1885
|
+
operation: "upsert",
|
|
1886
|
+
});
|
|
1887
|
+
}
|
|
1888
|
+
continue;
|
|
1889
|
+
}
|
|
1890
|
+
if (JSON.stringify(merged[index]) === JSON.stringify(entry))
|
|
1891
|
+
continue;
|
|
1892
|
+
if (update.baseline !== null &&
|
|
1893
|
+
JSON.stringify(merged[index]) === JSON.stringify(update.baseline)) {
|
|
1894
|
+
merged[index] = entry;
|
|
1895
|
+
}
|
|
1896
|
+
else {
|
|
1897
|
+
const annotationId = entry.annotation?.id;
|
|
1898
|
+
onConflict?.({
|
|
1899
|
+
messageId: entry.messageId,
|
|
1900
|
+
...(typeof annotationId === "string" ? { annotationId } : {}),
|
|
1901
|
+
operation: "upsert",
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
else
|
|
1907
|
+
for (const entry of Array.isArray(incoming) ? incoming : []) {
|
|
1908
|
+
if (typeof entry?.messageId !== "string") {
|
|
1909
|
+
merged.push(entry);
|
|
1910
|
+
continue;
|
|
1911
|
+
}
|
|
1912
|
+
const key = JSON.stringify([entry.messageId, annotationKey(entry)]);
|
|
1913
|
+
const index = positions.get(key);
|
|
1914
|
+
if (index === undefined) {
|
|
1915
|
+
positions.set(key, merged.length);
|
|
1916
|
+
merged.push(entry);
|
|
1917
|
+
}
|
|
1918
|
+
else {
|
|
1919
|
+
merged[index] = entry;
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
return merged;
|
|
1923
|
+
}
|
|
1924
|
+
function mergeAgentKitHistory(existing, incoming, promptRunIds, onAnnotationConflict) {
|
|
1925
|
+
const incomingIsRecord = incoming !== null &&
|
|
1926
|
+
typeof incoming === "object" &&
|
|
1927
|
+
!Array.isArray(incoming);
|
|
1928
|
+
if (!incomingIsRecord)
|
|
1481
1929
|
return incoming ?? existing;
|
|
1930
|
+
const next = incoming;
|
|
1931
|
+
const existingIsRecord = existing !== null &&
|
|
1932
|
+
typeof existing === "object" &&
|
|
1933
|
+
!Array.isArray(existing);
|
|
1934
|
+
const snapshotDelta = next._snapshotDelta === true;
|
|
1935
|
+
const incomingEventRunIds = new Set((Array.isArray(next.events) ? next.events : []).flatMap((event) => typeof event?.runId === "string" ? [event.runId] : []));
|
|
1936
|
+
const incomingRunStarts = new Set((Array.isArray(next.events) ? next.events : []).flatMap((event) => typeof event?.runId === "string" && event.sequence === 1
|
|
1937
|
+
? [event.runId]
|
|
1938
|
+
: []));
|
|
1939
|
+
const eventRunSnapshotBatches = new Map();
|
|
1940
|
+
for (const batch of Array.isArray(next.eventRunSnapshotBatches)
|
|
1941
|
+
? next.eventRunSnapshotBatches
|
|
1942
|
+
: []) {
|
|
1943
|
+
if (typeof batch?.runId === "string" &&
|
|
1944
|
+
typeof batch.snapshotId === "string" &&
|
|
1945
|
+
batch.snapshotId.length > 0 &&
|
|
1946
|
+
typeof batch.lastSequence === "number" &&
|
|
1947
|
+
Number.isSafeInteger(batch.lastSequence) &&
|
|
1948
|
+
batch.lastSequence >= 0 &&
|
|
1949
|
+
typeof batch.expectedEventCount === "number" &&
|
|
1950
|
+
Number.isSafeInteger(batch.expectedEventCount) &&
|
|
1951
|
+
batch.expectedEventCount > 0 &&
|
|
1952
|
+
typeof batch.complete === "boolean" &&
|
|
1953
|
+
incomingEventRunIds.has(batch.runId)) {
|
|
1954
|
+
eventRunSnapshotBatches.set(batch.runId, {
|
|
1955
|
+
runId: batch.runId,
|
|
1956
|
+
snapshotId: batch.snapshotId,
|
|
1957
|
+
lastSequence: batch.lastSequence,
|
|
1958
|
+
expectedEventCount: batch.expectedEventCount,
|
|
1959
|
+
complete: batch.complete,
|
|
1960
|
+
});
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
const eventRunSnapshotWatermarks = new Map();
|
|
1964
|
+
for (const watermark of Array.isArray(next.eventRunSnapshotWatermarks)
|
|
1965
|
+
? next.eventRunSnapshotWatermarks
|
|
1966
|
+
: []) {
|
|
1967
|
+
if (typeof watermark?.runId === "string" &&
|
|
1968
|
+
typeof watermark.lastSequence === "number" &&
|
|
1969
|
+
Number.isSafeInteger(watermark.lastSequence) &&
|
|
1970
|
+
watermark.lastSequence >= 0 &&
|
|
1971
|
+
incomingEventRunIds.has(watermark.runId) &&
|
|
1972
|
+
!eventRunSnapshotBatches.has(watermark.runId)) {
|
|
1973
|
+
eventRunSnapshotWatermarks.set(watermark.runId, Math.max(eventRunSnapshotWatermarks.get(watermark.runId) ?? 0, watermark.lastSequence));
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
const eventRunReplacements = new Map();
|
|
1977
|
+
for (const replacement of Array.isArray(next.eventRunReplacements)
|
|
1978
|
+
? next.eventRunReplacements
|
|
1979
|
+
: []) {
|
|
1980
|
+
if (typeof replacement?.runId === "string" &&
|
|
1981
|
+
typeof replacement.lastSequence === "number" &&
|
|
1982
|
+
Number.isSafeInteger(replacement.lastSequence) &&
|
|
1983
|
+
replacement.lastSequence >= 1 &&
|
|
1984
|
+
incomingRunStarts.has(replacement.runId) &&
|
|
1985
|
+
!eventRunSnapshotBatches.has(replacement.runId)) {
|
|
1986
|
+
eventRunReplacements.set(replacement.runId, Math.max(eventRunReplacements.get(replacement.runId) ?? 0, replacement.lastSequence));
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
for (const [runId, lastSequence] of eventRunReplacements) {
|
|
1990
|
+
eventRunSnapshotWatermarks.set(runId, Math.max(eventRunSnapshotWatermarks.get(runId) ?? 0, lastSequence));
|
|
1991
|
+
}
|
|
1992
|
+
const annotationMessageIdsToReplace = new Set();
|
|
1993
|
+
const annotationRemovalValuesByMessage = new Map();
|
|
1994
|
+
for (const replacement of Array.isArray(next.annotationMessageIdsToReplace)
|
|
1995
|
+
? next.annotationMessageIdsToReplace
|
|
1996
|
+
: []) {
|
|
1997
|
+
if (typeof replacement === "string") {
|
|
1998
|
+
annotationMessageIdsToReplace.add(replacement);
|
|
1999
|
+
continue;
|
|
2000
|
+
}
|
|
2001
|
+
if (!replacement ||
|
|
2002
|
+
typeof replacement !== "object" ||
|
|
2003
|
+
typeof replacement.messageId !== "string" ||
|
|
2004
|
+
!Array.isArray(replacement.annotationsToRemove)) {
|
|
2005
|
+
continue;
|
|
2006
|
+
}
|
|
2007
|
+
const removalValues = new Map();
|
|
2008
|
+
for (const removal of replacement.annotationsToRemove) {
|
|
2009
|
+
if (!removal ||
|
|
2010
|
+
typeof removal !== "object" ||
|
|
2011
|
+
typeof removal.key !== "string" ||
|
|
2012
|
+
!removal.baseline ||
|
|
2013
|
+
typeof removal.baseline !== "object" ||
|
|
2014
|
+
Array.isArray(removal.baseline)) {
|
|
2015
|
+
continue;
|
|
2016
|
+
}
|
|
2017
|
+
const baseline = JSON.stringify(removal.baseline);
|
|
2018
|
+
if (typeof baseline === "string") {
|
|
2019
|
+
removalValues.set(removal.key, baseline);
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
if (removalValues.size > 0) {
|
|
2023
|
+
annotationRemovalValuesByMessage.set(replacement.messageId, removalValues);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
if (!existingIsRecord) {
|
|
2027
|
+
const initial = { ...next };
|
|
2028
|
+
delete initial._eventRunWatermarks;
|
|
2029
|
+
if (snapshotDelta) {
|
|
2030
|
+
if (Array.isArray(initial.messages) && initial.messages.length === 0) {
|
|
2031
|
+
delete initial.messages;
|
|
2032
|
+
}
|
|
2033
|
+
const eventSnapshot = mergeAgentKitEventRunSnapshots({
|
|
2034
|
+
existingEvents: undefined,
|
|
2035
|
+
incomingEvents: next.events,
|
|
2036
|
+
existingWatermarks: new Map(),
|
|
2037
|
+
existingRunSequences: new Map(),
|
|
2038
|
+
incomingWatermarks: eventRunSnapshotWatermarks,
|
|
2039
|
+
incomingReplacements: eventRunReplacements,
|
|
2040
|
+
batches: eventRunSnapshotBatches,
|
|
2041
|
+
existingPending: undefined,
|
|
2042
|
+
existingCommits: undefined,
|
|
2043
|
+
});
|
|
2044
|
+
if (eventSnapshot.events)
|
|
2045
|
+
initial.events = eventSnapshot.events;
|
|
2046
|
+
if (eventSnapshot.watermarks.size > 0) {
|
|
2047
|
+
initial._eventRunWatermarks = Object.fromEntries(eventSnapshot.watermarks);
|
|
2048
|
+
}
|
|
2049
|
+
if (Object.keys(eventSnapshot.pending).length > 0) {
|
|
2050
|
+
initial._pendingEventRunSnapshots = eventSnapshot.pending;
|
|
2051
|
+
}
|
|
2052
|
+
else {
|
|
2053
|
+
delete initial._pendingEventRunSnapshots;
|
|
2054
|
+
}
|
|
2055
|
+
if (Object.keys(eventSnapshot.commits).length > 0) {
|
|
2056
|
+
initial._eventRunSnapshotCommits = eventSnapshot.commits;
|
|
2057
|
+
}
|
|
2058
|
+
else {
|
|
2059
|
+
delete initial._eventRunSnapshotCommits;
|
|
2060
|
+
}
|
|
2061
|
+
const annotations = mergeAgentKitAnnotations(undefined, next.annotations, annotationMessageIdsToReplace, annotationRemovalValuesByMessage, next.annotationUpserts, onAnnotationConflict);
|
|
2062
|
+
if (annotations)
|
|
2063
|
+
initial.annotations = annotations;
|
|
2064
|
+
}
|
|
2065
|
+
delete initial._snapshotDelta;
|
|
2066
|
+
delete initial.eventRunReplacements;
|
|
2067
|
+
delete initial.eventRunSnapshotWatermarks;
|
|
2068
|
+
delete initial.eventRunSnapshotBatches;
|
|
2069
|
+
delete initial.annotationMessageIdsToReplace;
|
|
2070
|
+
delete initial.annotationUpserts;
|
|
2071
|
+
return initial;
|
|
1482
2072
|
}
|
|
1483
2073
|
const previous = existing;
|
|
1484
|
-
const next = incoming;
|
|
1485
2074
|
const merged = { ...previous, ...next };
|
|
1486
2075
|
const runs = new Map();
|
|
1487
2076
|
for (const run of [
|
|
@@ -1496,29 +2085,76 @@ function mergeAgentKitHistory(existing, incoming, promptRunIds) {
|
|
|
1496
2085
|
continue;
|
|
1497
2086
|
}
|
|
1498
2087
|
const richer = newer.lastSequence >= run.lastSequence ? newer : run;
|
|
2088
|
+
const statusRun = run.lastSequence > newer.lastSequence
|
|
2089
|
+
? run
|
|
2090
|
+
: newer.lastSequence > run.lastSequence
|
|
2091
|
+
? newer
|
|
2092
|
+
: isTerminalRunStatus(run.status)
|
|
2093
|
+
? run
|
|
2094
|
+
: newer;
|
|
1499
2095
|
runs.set(run.id, {
|
|
1500
2096
|
...run,
|
|
1501
2097
|
...newer,
|
|
1502
2098
|
...richer,
|
|
1503
2099
|
metadata: { ...run.metadata, ...newer.metadata, ...richer.metadata },
|
|
1504
2100
|
lastSequence: Math.max(newer.lastSequence, run.lastSequence),
|
|
1505
|
-
status:
|
|
1506
|
-
? run.status
|
|
1507
|
-
: newer.status,
|
|
2101
|
+
status: statusRun.status,
|
|
1508
2102
|
});
|
|
1509
2103
|
}
|
|
1510
2104
|
if (runs.size > 0) {
|
|
1511
2105
|
merged.runs = [...runs.values()];
|
|
1512
2106
|
const latest = latestSnapshotRun(merged.runs);
|
|
2107
|
+
const incomingLatest = latestSnapshotRun(next.runs);
|
|
1513
2108
|
const previousLatest = latestSnapshotRun(previous.runs);
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
2109
|
+
const incomingLatestCompleted = incomingLatest?.status === "completed";
|
|
2110
|
+
const incomingLatestIsMergedLatest = incomingLatest?.id === latest?.id && incomingLatestCompleted;
|
|
2111
|
+
const newLatestRunCompletion = incomingLatestIsMergedLatest && latest?.id !== previousLatest?.id;
|
|
2112
|
+
const latestRunJustCompleted = incomingLatestIsMergedLatest &&
|
|
2113
|
+
incomingLatest !== undefined &&
|
|
2114
|
+
latest !== undefined &&
|
|
2115
|
+
previousLatest !== undefined &&
|
|
2116
|
+
previousLatest.id === latest.id &&
|
|
2117
|
+
previousLatest.status !== "completed" &&
|
|
2118
|
+
Number.isSafeInteger(incomingLatest.lastSequence) &&
|
|
2119
|
+
incomingLatest.lastSequence >= 0 &&
|
|
2120
|
+
Number.isSafeInteger(previousLatest.lastSequence) &&
|
|
2121
|
+
previousLatest.lastSequence >= 0 &&
|
|
2122
|
+
incomingLatest.lastSequence >= previousLatest.lastSequence;
|
|
2123
|
+
const sameCompletedRunAdvanced = incomingLatestIsMergedLatest &&
|
|
2124
|
+
incomingLatest !== undefined &&
|
|
2125
|
+
latest !== undefined &&
|
|
2126
|
+
previousLatest !== undefined &&
|
|
2127
|
+
incomingLatest.id === latest.id &&
|
|
2128
|
+
previousLatest.id === latest.id &&
|
|
2129
|
+
previousLatest.status === "completed" &&
|
|
2130
|
+
Number.isSafeInteger(incomingLatest.lastSequence) &&
|
|
2131
|
+
incomingLatest.lastSequence >= 0 &&
|
|
2132
|
+
Number.isSafeInteger(previousLatest.lastSequence) &&
|
|
2133
|
+
previousLatest.lastSequence >= 0 &&
|
|
2134
|
+
incomingLatest.lastSequence > previousLatest.lastSequence;
|
|
2135
|
+
const incomingSuggestionsAreCurrent = Object.prototype.hasOwnProperty.call(next, "suggestions") &&
|
|
2136
|
+
(newLatestRunCompletion ||
|
|
2137
|
+
latestRunJustCompleted ||
|
|
2138
|
+
sameCompletedRunAdvanced);
|
|
2139
|
+
if (latest?.status !== "completed") {
|
|
2140
|
+
merged.suggestions = [];
|
|
2141
|
+
}
|
|
2142
|
+
else if (incomingSuggestionsAreCurrent) {
|
|
2143
|
+
merged.suggestions = next.suggestions;
|
|
2144
|
+
}
|
|
2145
|
+
else if (previousLatest !== undefined &&
|
|
2146
|
+
latest.id === previousLatest.id &&
|
|
2147
|
+
previousLatest.status === "completed") {
|
|
2148
|
+
if (Object.prototype.hasOwnProperty.call(previous, "suggestions")) {
|
|
2149
|
+
merged.suggestions = previous.suggestions;
|
|
2150
|
+
}
|
|
2151
|
+
else {
|
|
2152
|
+
delete merged.suggestions;
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
else {
|
|
2156
|
+
merged.suggestions = [];
|
|
2157
|
+
}
|
|
1522
2158
|
if (Array.isArray(merged.suggestions)) {
|
|
1523
2159
|
merged.suggestions = merged.suggestions.filter((suggestion) => suggestion?.runId === latest?.id);
|
|
1524
2160
|
}
|
|
@@ -1537,6 +2173,92 @@ function mergeAgentKitHistory(existing, incoming, promptRunIds) {
|
|
|
1537
2173
|
if (entries)
|
|
1538
2174
|
merged[key] = entries;
|
|
1539
2175
|
}
|
|
2176
|
+
if (snapshotDelta &&
|
|
2177
|
+
Array.isArray(next.messages) &&
|
|
2178
|
+
next.messages.length === 0 &&
|
|
2179
|
+
!Array.isArray(previous.messages)) {
|
|
2180
|
+
delete merged.messages;
|
|
2181
|
+
}
|
|
2182
|
+
if (snapshotDelta) {
|
|
2183
|
+
const previousWatermarks = new Map();
|
|
2184
|
+
const previousWatermarkRecord = previous._eventRunWatermarks;
|
|
2185
|
+
if (previousWatermarkRecord &&
|
|
2186
|
+
typeof previousWatermarkRecord === "object" &&
|
|
2187
|
+
!Array.isArray(previousWatermarkRecord)) {
|
|
2188
|
+
for (const [runId, value] of Object.entries(previousWatermarkRecord)) {
|
|
2189
|
+
if (typeof value === "number" &&
|
|
2190
|
+
Number.isSafeInteger(value) &&
|
|
2191
|
+
value >= 0) {
|
|
2192
|
+
previousWatermarks.set(runId, value);
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
const previousRunSequences = new Map();
|
|
2197
|
+
for (const run of Array.isArray(previous.runs) ? previous.runs : []) {
|
|
2198
|
+
if (typeof run?.id === "string" &&
|
|
2199
|
+
typeof run.lastSequence === "number" &&
|
|
2200
|
+
Number.isSafeInteger(run.lastSequence) &&
|
|
2201
|
+
run.lastSequence >= 0) {
|
|
2202
|
+
previousRunSequences.set(run.id, run.lastSequence);
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
const eventSnapshot = mergeAgentKitEventRunSnapshots({
|
|
2206
|
+
existingEvents: previous.events,
|
|
2207
|
+
incomingEvents: next.events,
|
|
2208
|
+
existingWatermarks: previousWatermarks,
|
|
2209
|
+
existingRunSequences: previousRunSequences,
|
|
2210
|
+
incomingWatermarks: eventRunSnapshotWatermarks,
|
|
2211
|
+
incomingReplacements: eventRunReplacements,
|
|
2212
|
+
batches: eventRunSnapshotBatches,
|
|
2213
|
+
existingPending: previous._pendingEventRunSnapshots,
|
|
2214
|
+
existingCommits: previous._eventRunSnapshotCommits,
|
|
2215
|
+
});
|
|
2216
|
+
if (eventSnapshot.events)
|
|
2217
|
+
merged.events = eventSnapshot.events;
|
|
2218
|
+
delete merged._eventRunWatermarks;
|
|
2219
|
+
if (eventSnapshot.watermarks.size > 0) {
|
|
2220
|
+
merged._eventRunWatermarks = Object.fromEntries(eventSnapshot.watermarks);
|
|
2221
|
+
}
|
|
2222
|
+
if (Object.keys(eventSnapshot.pending).length > 0) {
|
|
2223
|
+
merged._pendingEventRunSnapshots = eventSnapshot.pending;
|
|
2224
|
+
}
|
|
2225
|
+
else {
|
|
2226
|
+
delete merged._pendingEventRunSnapshots;
|
|
2227
|
+
}
|
|
2228
|
+
if (Object.keys(eventSnapshot.commits).length > 0) {
|
|
2229
|
+
merged._eventRunSnapshotCommits = eventSnapshot.commits;
|
|
2230
|
+
}
|
|
2231
|
+
else {
|
|
2232
|
+
delete merged._eventRunSnapshotCommits;
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
else {
|
|
2236
|
+
const events = mergeAgentKitFullEventSnapshot(previous.events, next.events, next.runs, previous._eventRunSnapshotCommits);
|
|
2237
|
+
if (events)
|
|
2238
|
+
merged.events = events;
|
|
2239
|
+
if (previous._eventRunWatermarks === undefined) {
|
|
2240
|
+
delete merged._eventRunWatermarks;
|
|
2241
|
+
}
|
|
2242
|
+
else {
|
|
2243
|
+
merged._eventRunWatermarks = previous._eventRunWatermarks;
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
delete merged._snapshotDelta;
|
|
2247
|
+
delete merged.eventRunReplacements;
|
|
2248
|
+
delete merged.eventRunSnapshotWatermarks;
|
|
2249
|
+
delete merged.eventRunSnapshotBatches;
|
|
2250
|
+
if (snapshotDelta ||
|
|
2251
|
+
annotationMessageIdsToReplace.size > 0 ||
|
|
2252
|
+
annotationRemovalValuesByMessage.size > 0) {
|
|
2253
|
+
const annotations = mergeAgentKitAnnotations(previous.annotations, next.annotations, annotationMessageIdsToReplace, annotationRemovalValuesByMessage, next.annotationUpserts, onAnnotationConflict);
|
|
2254
|
+
if (annotations)
|
|
2255
|
+
merged.annotations = annotations;
|
|
2256
|
+
}
|
|
2257
|
+
else if (Array.isArray(next.annotations)) {
|
|
2258
|
+
merged.annotations = next.annotations;
|
|
2259
|
+
}
|
|
2260
|
+
delete merged.annotationMessageIdsToReplace;
|
|
2261
|
+
delete merged.annotationUpserts;
|
|
1540
2262
|
return merged;
|
|
1541
2263
|
}
|
|
1542
2264
|
function pruneClaimedQueuedMessages(repo) {
|
|
@@ -1579,7 +2301,7 @@ export function mergeThreadDataForClientSave(existingRepo, incomingRepo, options
|
|
|
1579
2301
|
}
|
|
1580
2302
|
const promptRunIds = submittedPromptRunIds(existingNormalized?.messages, incomingNormalized?.messages);
|
|
1581
2303
|
if (merged.agentKit !== undefined) {
|
|
1582
|
-
merged.agentKit = mergeAgentKitHistory(existingNormalized?.agentKit, merged.agentKit, promptRunIds);
|
|
2304
|
+
merged.agentKit = mergeAgentKitHistory(existingNormalized?.agentKit, merged.agentKit, promptRunIds, options.onAnnotationConflict);
|
|
1583
2305
|
}
|
|
1584
2306
|
const existingMessages = Array.isArray(existingNormalized?.messages)
|
|
1585
2307
|
? existingNormalized.messages
|