experimental-a2 0.18.0 → 0.19.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/CHANGELOG.md +39 -0
- package/dist/{actor-Bjce9_5U.d.ts → actor-C7b-1arn.d.ts} +3 -3
- package/dist/{actor-Bjce9_5U.d.ts.map → actor-C7b-1arn.d.ts.map} +1 -1
- package/dist/actor-client.d.ts +1 -1
- package/dist/actor-react.d.ts +1 -1
- package/dist/actor-react.js +1 -1
- package/dist/actor.d.ts +1 -1
- package/dist/actor.js +2 -2
- package/dist/{ai-DrUaMyRt.d.ts → ai-Cz3hqVhk.d.ts} +34 -17
- package/dist/ai-Cz3hqVhk.d.ts.map +1 -0
- package/dist/ai-client.d.ts +1 -1
- package/dist/ai-client.js +2 -2
- package/dist/ai-control-CvLbW10B.js +46 -0
- package/dist/ai-control-CvLbW10B.js.map +1 -0
- package/dist/ai-fx.d.ts +1 -1
- package/dist/ai-fx.d.ts.map +1 -1
- package/dist/ai-fx.js +122 -44
- package/dist/ai-fx.js.map +1 -1
- package/dist/{ai-harness-BuLh_EYi.js → ai-harness-BuuC-gJ3.js} +79 -15
- package/dist/ai-harness-BuuC-gJ3.js.map +1 -0
- package/dist/{ai-harness-DvsPeJeB.d.ts → ai-harness-CV6rXbB3.d.ts} +2 -2
- package/dist/ai-harness-CV6rXbB3.d.ts.map +1 -0
- package/dist/{ai-BpOGm-zB.js → ai-mMiWul1T.js} +117 -78
- package/dist/ai-mMiWul1T.js.map +1 -0
- package/dist/ai-pi.d.ts +1 -1
- package/dist/ai-pi.d.ts.map +1 -1
- package/dist/ai-pi.js +114 -23
- package/dist/ai-pi.js.map +1 -1
- package/dist/ai-react.d.ts +1 -1
- package/dist/ai-react.js +2 -2
- package/dist/ai-server.d.ts +3 -3
- package/dist/ai-server.d.ts.map +1 -1
- package/dist/ai-server.js +127 -55
- package/dist/ai-server.js.map +1 -1
- package/dist/ai-tool-input-DmSqMUQi.js +40 -0
- package/dist/ai-tool-input-DmSqMUQi.js.map +1 -0
- package/dist/ai.d.ts +2 -2
- package/dist/ai.js +1 -1
- package/dist/{client-BReKqwZC.js → client-BhHLoNKF.js} +3 -3
- package/dist/{client-BReKqwZC.js.map → client-BhHLoNKF.js.map} +1 -1
- package/dist/client.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/{internal-B2T3U4Rq.js → internal-CscSY7K_.js} +4 -2
- package/dist/{internal-B2T3U4Rq.js.map → internal-CscSY7K_.js.map} +1 -1
- package/dist/react.js +1 -1
- package/dist/scheduler-qstash.d.ts +2 -2
- package/dist/scheduler-qstash.js +3 -3
- package/dist/scheduler-qstash.js.map +1 -1
- package/dist/scheduler-vercel.d.ts +7 -7
- package/dist/scheduler-vercel.d.ts.map +1 -1
- package/dist/scheduler-vercel.js +10 -14
- package/dist/scheduler-vercel.js.map +1 -1
- package/dist/{server-Dw_k_7kO.js → server-D-Y4pqwu.js} +37 -11
- package/dist/server-D-Y4pqwu.js.map +1 -0
- package/dist/{server-En7cbi3v.d.ts → server-DYAATFuT.d.ts} +11 -5
- package/dist/server-DYAATFuT.d.ts.map +1 -0
- package/dist/server.d.ts +2 -2
- package/dist/server.js +1 -1
- package/dist/{session-clear-Bo-XTFEy.d.ts → session-clear-C-QwTXV1.d.ts} +2 -2
- package/dist/session-clear-C-QwTXV1.d.ts.map +1 -0
- package/dist/{store-Djdv0bnZ.d.ts → store-CyLUy86v.d.ts} +23 -4
- package/dist/store-CyLUy86v.d.ts.map +1 -0
- package/dist/store-N8PXxDAS.js.map +1 -1
- package/dist/store-memory.d.ts +1 -1
- package/dist/store-memory.js +25 -6
- package/dist/store-memory.js.map +1 -1
- package/dist/{store-polling-B5FcwJfo.js → store-polling-7WJV0YWP.js} +2 -2
- package/dist/{store-polling-B5FcwJfo.js.map → store-polling-7WJV0YWP.js.map} +1 -1
- package/dist/store-postgres.d.ts +1 -1
- package/dist/store-postgres.d.ts.map +1 -1
- package/dist/store-postgres.js +55 -25
- package/dist/store-postgres.js.map +1 -1
- package/dist/{store-presence-polling-BAwS8RWn.js → store-presence-polling-B1ixeqIS.js} +3 -3
- package/dist/{store-presence-polling-BAwS8RWn.js.map → store-presence-polling-B1ixeqIS.js.map} +1 -1
- package/dist/store-redis-http.d.ts +1 -1
- package/dist/store-redis-http.js +3 -3
- package/dist/{store-redis-notify-BRITti_o.js → store-redis-notify-CM0AfLY0.js} +88 -37
- package/dist/store-redis-notify-CM0AfLY0.js.map +1 -0
- package/dist/store-redis.d.ts +1 -1
- package/dist/store-redis.js +1 -1
- package/dist/store-sqlite.d.ts +1 -1
- package/dist/store-sqlite.js +35 -20
- package/dist/store-sqlite.js.map +1 -1
- package/dist/{wire-rSUglYo8.js → wire-BKxH1vbP.js} +2 -2
- package/dist/{wire-rSUglYo8.js.map → wire-BKxH1vbP.js.map} +1 -1
- package/docs/agents/03-conversations.mdx +27 -15
- package/docs/agents/04-harnesses.mdx +51 -5
- package/docs/contract/03-sessions.mdx +1 -1
- package/docs/index.mdx +3 -3
- package/docs/reference/02-server.mdx +12 -7
- package/docs/reference/04-ai.mdx +41 -23
- package/docs/reference/05-adapters.mdx +6 -6
- package/docs/server/01-handlers.mdx +1 -1
- package/docs/server/02-timers.mdx +1 -1
- package/docs/server/03-cancellation.mdx +3 -2
- package/docs/server/05-production.mdx +4 -3
- package/docs/server/06-guarantees.mdx +20 -11
- package/examples/playground/DEPLOY.md +11 -4
- package/examples/playground/app/a0/[appId]/page.tsx +2 -8
- package/examples/playground/app/a0/a0.css +244 -5
- package/examples/playground/app/a0/app-view.tsx +2 -1
- package/examples/playground/app/a0/attachments.ts +133 -0
- package/examples/playground/app/a0/chat.test.tsx +504 -0
- package/examples/playground/app/a0/chat.tsx +623 -63
- package/examples/playground/app/a0/context-menu.tsx +38 -11
- package/examples/playground/app/a0/devtools.tsx +2 -8
- package/examples/playground/app/a0/model.test.ts +28 -0
- package/examples/playground/app/a0/model.ts +30 -0
- package/examples/playground/app/a0/server.ts +13 -19
- package/examples/playground/app/a0/uploads/route.ts +29 -0
- package/examples/playground/app/agent/[agentId]/agent-client.tsx +2 -1
- package/examples/playground/app/agent/[agentId]/agent-queue.test.tsx +1 -0
- package/examples/playground/app/agent/model.test.ts +12 -3
- package/examples/playground/app/chat/[chatId]/agent-state.test.ts +1 -5
- package/examples/playground/next.config.ts +7 -4
- package/examples/playground/package.json +3 -1
- package/package.json +1 -1
- package/src/ai-agent.ts +14 -3
- package/src/ai-client-state.ts +21 -9
- package/src/ai-context-schema.ts +28 -4
- package/src/ai-context.ts +83 -3
- package/src/ai-control-server.ts +70 -43
- package/src/ai-control-state.ts +3 -4
- package/src/ai-control.ts +59 -10
- package/src/ai-coordinator.ts +7 -6
- package/src/ai-fx.ts +184 -67
- package/src/ai-harness.ts +153 -29
- package/src/ai-message-shape.ts +41 -0
- package/src/ai-pi.ts +161 -46
- package/src/ai-stored-state.ts +1 -3
- package/src/ai-tool-input.ts +45 -0
- package/src/ai.ts +116 -77
- package/src/internal.ts +6 -0
- package/src/libfx.d.ts +8 -1
- package/src/scheduler-qstash.ts +5 -5
- package/src/scheduler-vercel.ts +15 -27
- package/src/server.ts +58 -12
- package/src/store-memory.ts +50 -9
- package/src/store-postgres.ts +79 -28
- package/src/store-redis-core.ts +112 -31
- package/src/store-sqlite.ts +61 -28
- package/src/store.ts +22 -3
- package/dist/ai-BpOGm-zB.js.map +0 -1
- package/dist/ai-DrUaMyRt.d.ts.map +0 -1
- package/dist/ai-harness-BuLh_EYi.js.map +0 -1
- package/dist/ai-harness-DvsPeJeB.d.ts.map +0 -1
- package/dist/server-Dw_k_7kO.js.map +0 -1
- package/dist/server-En7cbi3v.d.ts.map +0 -1
- package/dist/session-clear-Bo-XTFEy.d.ts.map +0 -1
- package/dist/store-Djdv0bnZ.d.ts.map +0 -1
- package/dist/store-redis-notify-BRITti_o.js.map +0 -1
- package/examples/playground/app/a0/no-photon.cjs +0 -4
|
@@ -2,7 +2,8 @@ import { a as reducer, o as assertSyncSchema, s as validateSync } from "./reduce
|
|
|
2
2
|
import { t as contract } from "./contract-BYKASlCV.js";
|
|
3
3
|
import { t as idempotentId } from "./idempotent-id-BRJVeylj.js";
|
|
4
4
|
import { i as withReducerRuntime } from "./reducer-runtime-DQwz_J59.js";
|
|
5
|
-
import { u as ambientToolScopeStorage } from "./internal-
|
|
5
|
+
import { u as ambientToolScopeStorage } from "./internal-CscSY7K_.js";
|
|
6
|
+
import { a as unexplainedAdmission, i as steersOn, r as steeringEnd, t as STEERED_REASON } from "./ai-control-CvLbW10B.js";
|
|
6
7
|
//#region src/equal-json.ts
|
|
7
8
|
const sameValue = (left, right) => {
|
|
8
9
|
if (Object.is(left, right)) return true;
|
|
@@ -1318,10 +1319,10 @@ function projectAIClientState(state) {
|
|
|
1318
1319
|
const admit = () => {
|
|
1319
1320
|
if (turnId !== null || paused || items.length === 0) return;
|
|
1320
1321
|
let count = 0;
|
|
1321
|
-
for (const item of items) {
|
|
1322
|
+
for (const [index, item] of items.entries()) {
|
|
1322
1323
|
count += 1;
|
|
1323
1324
|
show(item.message);
|
|
1324
|
-
if (item.generate) {
|
|
1325
|
+
if (item.generate && !steersOn(item, items.slice(index + 1))) {
|
|
1325
1326
|
turnId = item.id;
|
|
1326
1327
|
starting = true;
|
|
1327
1328
|
suspended = false;
|
|
@@ -1338,14 +1339,22 @@ function projectAIClientState(state) {
|
|
|
1338
1339
|
const item = {
|
|
1339
1340
|
...command.action === "steer" ? { afterStepOf: command.turnId } : {},
|
|
1340
1341
|
id: command.message.id,
|
|
1342
|
+
role: command.message.role,
|
|
1341
1343
|
message: command.message,
|
|
1342
1344
|
generate: command.message.role === "user" && (command.action === "steer" || command.generate !== false)
|
|
1343
1345
|
};
|
|
1344
|
-
|
|
1346
|
+
if (command.action === "steer") {
|
|
1347
|
+
const at = steeringEnd(items, command.turnId);
|
|
1348
|
+
items = [
|
|
1349
|
+
...items.slice(0, at),
|
|
1350
|
+
item,
|
|
1351
|
+
...items.slice(at)
|
|
1352
|
+
];
|
|
1353
|
+
} else items = [...items, item];
|
|
1345
1354
|
break;
|
|
1346
1355
|
}
|
|
1347
1356
|
case "edit":
|
|
1348
|
-
items = items.map((item) => item.id === command.message.id && item.
|
|
1357
|
+
items = items.map((item) => item.id === command.message.id && item.role === command.message.role ? {
|
|
1349
1358
|
...item,
|
|
1350
1359
|
message: command.message
|
|
1351
1360
|
} : item);
|
|
@@ -1363,16 +1372,18 @@ function projectAIClientState(state) {
|
|
|
1363
1372
|
case "send-now": {
|
|
1364
1373
|
if (turnId !== command.turnId) break;
|
|
1365
1374
|
const selected = items.find((item) => item.id === command.inputId);
|
|
1366
|
-
if (!selected || selected.
|
|
1375
|
+
if (!selected || selected.role !== "user") break;
|
|
1376
|
+
const { afterStepOf: _, ...promoted } = selected;
|
|
1367
1377
|
items = items.map((item) => item.id === selected.id ? {
|
|
1368
|
-
...
|
|
1378
|
+
...promoted,
|
|
1369
1379
|
generate: true,
|
|
1370
1380
|
...turnId === null ? {} : { afterStepOf: turnId }
|
|
1371
1381
|
} : item);
|
|
1382
|
+
const others = items.filter((item) => item.id !== selected.id);
|
|
1372
1383
|
items = moveItem({
|
|
1373
1384
|
items,
|
|
1374
1385
|
inputId: command.inputId,
|
|
1375
|
-
beforeId:
|
|
1386
|
+
beforeId: others[turnId === null ? 0 : steeringEnd(others, turnId)]?.id ?? null
|
|
1376
1387
|
});
|
|
1377
1388
|
break;
|
|
1378
1389
|
}
|
|
@@ -1533,29 +1544,31 @@ const controlCommit = (options) => {
|
|
|
1533
1544
|
};
|
|
1534
1545
|
};
|
|
1535
1546
|
//#endregion
|
|
1536
|
-
//#region src/ai-
|
|
1537
|
-
const
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
}
|
|
1547
|
+
//#region src/ai-message-shape.ts
|
|
1548
|
+
const isRecord$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1549
|
+
const isJSONCompatible = (value, seen = /* @__PURE__ */ new Set()) => {
|
|
1550
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
1551
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
1552
|
+
if (typeof value === "undefined") return true;
|
|
1553
|
+
if (typeof value !== "object") return false;
|
|
1554
|
+
if (seen.has(value)) return false;
|
|
1555
|
+
seen.add(value);
|
|
1556
|
+
const valid = Array.isArray(value) ? value.every((item) => isJSONCompatible(item, seen)) : Object.getPrototypeOf(value) === Object.prototype && Object.values(value).every((item) => isJSONCompatible(item, seen));
|
|
1557
|
+
seen.delete(value);
|
|
1558
|
+
return valid;
|
|
1559
|
+
};
|
|
1560
|
+
/** Whether a value has an AI SDK `UIMessage`'s shape. */
|
|
1561
|
+
const isUIMessage = (value) => isRecord$1(value) && typeof value["id"] === "string" && (value["role"] === "user" || value["role"] === "assistant" || value["role"] === "system") && Array.isArray(value["parts"]) && value["parts"].every((part) => isRecord$1(part) && typeof part["type"] === "string") && isJSONCompatible(value);
|
|
1549
1562
|
//#endregion
|
|
1550
1563
|
//#region src/ai-id.ts
|
|
1551
1564
|
const AI_EVENT_ID_PREFIX = "a2.ai:";
|
|
1552
1565
|
const aiEventId = async (...parts) => `${AI_EVENT_ID_PREFIX}${await idempotentId(...parts)}`;
|
|
1553
1566
|
//#endregion
|
|
1554
1567
|
//#region src/ai-stored-state.ts
|
|
1555
|
-
const isRecord
|
|
1556
|
-
const hasKeys = (value, { required, optional = [] }) => isRecord
|
|
1568
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1569
|
+
const hasKeys = (value, { required, optional = [] }) => isRecord(value) && required.every((key) => Object.hasOwn(value, key)) && Object.keys(value).every((key) => required.includes(key) || optional.includes(key));
|
|
1557
1570
|
const reference = (value) => {
|
|
1558
|
-
if (!isRecord
|
|
1571
|
+
if (!isRecord(value) || !Object.hasOwn(value, "$a2Value")) return void 0;
|
|
1559
1572
|
const id = value["$a2Value"];
|
|
1560
1573
|
if (typeof id !== "number" || !Number.isSafeInteger(id) || id < 0 || Object.keys(value).length !== 1) throw new TypeError("invalid AI payload reference");
|
|
1561
1574
|
return id;
|
|
@@ -1574,13 +1587,13 @@ const payloadFields = /* @__PURE__ */ new Set([
|
|
|
1574
1587
|
const keyFor = (value) => value === void 0 ? "undefined" : JSON.stringify(value);
|
|
1575
1588
|
const restore = (current, undo) => {
|
|
1576
1589
|
if (undo === void 0) return current;
|
|
1577
|
-
if (!isRecord
|
|
1590
|
+
if (!isRecord(undo)) throw new TypeError("invalid AI recovery change");
|
|
1578
1591
|
if ("value" in undo) {
|
|
1579
1592
|
if (!hasKeys(undo, { required: ["value"] })) throw new TypeError("invalid AI replacement recovery");
|
|
1580
1593
|
return undo.value;
|
|
1581
1594
|
}
|
|
1582
1595
|
if ("length" in undo) {
|
|
1583
|
-
if (!hasKeys(undo, { required: ["length", "items"] }) || !Number.isSafeInteger(undo.length) || undo.length < 0 || undo.length > 4294967295 || !isRecord
|
|
1596
|
+
if (!hasKeys(undo, { required: ["length", "items"] }) || !Number.isSafeInteger(undo.length) || undo.length < 0 || undo.length > 4294967295 || !isRecord(undo.items) || !Array.isArray(current)) throw new TypeError("invalid AI array recovery");
|
|
1584
1597
|
const items = Object.entries(undo.items);
|
|
1585
1598
|
let added = 0;
|
|
1586
1599
|
for (const [key, patch] of items) {
|
|
@@ -1594,7 +1607,7 @@ const restore = (current, undo) => {
|
|
|
1594
1607
|
for (const [index, patch] of items) result[Number(index)] = restore(current[Number(index)] ?? null, patch);
|
|
1595
1608
|
return result;
|
|
1596
1609
|
}
|
|
1597
|
-
if (!hasKeys(undo, { required: ["fields", "remove"] }) || !isRecord
|
|
1610
|
+
if (!hasKeys(undo, { required: ["fields", "remove"] }) || !isRecord(undo.fields) || !Array.isArray(undo.remove) || Object.keys(undo.remove).length !== undo.remove.length || Array.from(undo.remove).some((key) => typeof key !== "string") || new Set(undo.remove).size !== undo.remove.length || !isRecord(current) || reference(current) !== void 0) throw new TypeError("invalid AI object recovery");
|
|
1598
1611
|
const result = { ...current };
|
|
1599
1612
|
for (const key of undo.remove) delete result[key];
|
|
1600
1613
|
for (const [key, patch] of Object.entries(undo.fields)) {
|
|
@@ -1622,7 +1635,7 @@ const difference = (current, before) => {
|
|
|
1622
1635
|
items
|
|
1623
1636
|
};
|
|
1624
1637
|
}
|
|
1625
|
-
if (isRecord
|
|
1638
|
+
if (isRecord(current) && isRecord(before)) {
|
|
1626
1639
|
const fields = {};
|
|
1627
1640
|
const remove = Object.keys(current).filter((key) => !Object.hasOwn(before, key));
|
|
1628
1641
|
for (const [key, value] of Object.entries(before)) {
|
|
@@ -1661,7 +1674,7 @@ const storeState = (state) => {
|
|
|
1661
1674
|
return { $a2Value: id };
|
|
1662
1675
|
};
|
|
1663
1676
|
const pack = (value, field) => {
|
|
1664
|
-
if (value === void 0 || typeof value === "string" && value.length > 80 || field !== void 0 && payloadFields.has(field)
|
|
1677
|
+
if (value === void 0 || typeof value === "string" && value.length > 80 || field !== void 0 && payloadFields.has(field) || isRecord(value) && Object.hasOwn(value, "$a2Value")) return intern(value);
|
|
1665
1678
|
if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number") return value;
|
|
1666
1679
|
if (typeof value !== "object") throw new TypeError("AI state must contain JSON values");
|
|
1667
1680
|
const cached = packed.get(value);
|
|
@@ -1698,7 +1711,7 @@ const loadState = (stored) => {
|
|
|
1698
1711
|
if (Object.keys(value).length !== value.length) throw new TypeError("invalid AI stored array");
|
|
1699
1712
|
return Array.from(value, unpack);
|
|
1700
1713
|
}
|
|
1701
|
-
if (isRecord
|
|
1714
|
+
if (isRecord(value)) return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, unpack(item)]));
|
|
1702
1715
|
if (value === null || typeof value === "boolean" || typeof value === "string" || typeof value === "number" && Number.isFinite(value)) return value;
|
|
1703
1716
|
throw new TypeError("invalid AI stored value");
|
|
1704
1717
|
};
|
|
@@ -1708,7 +1721,7 @@ const loadState = (stored) => {
|
|
|
1708
1721
|
if (!hasKeys(saved, {
|
|
1709
1722
|
required: ["fields"],
|
|
1710
1723
|
optional: ["tools"]
|
|
1711
|
-
}) || !isRecord
|
|
1724
|
+
}) || !isRecord(saved.fields) || "tools" in saved && saved.tools === void 0) throw new TypeError("invalid AI projection recovery");
|
|
1712
1725
|
const projection = unpack(saved.fields);
|
|
1713
1726
|
if (projection.base !== void 0) {
|
|
1714
1727
|
assertMessageBase(projection.base);
|
|
@@ -1735,7 +1748,7 @@ const withAIStorage = (source) => withReducerRuntime({
|
|
|
1735
1748
|
"fields",
|
|
1736
1749
|
"projection",
|
|
1737
1750
|
"values"
|
|
1738
|
-
] }) || value["version"] !== 3 || !Array.isArray(value["values"]) || !isRecord
|
|
1751
|
+
] }) || value["version"] !== 3 || !Array.isArray(value["values"]) || !isRecord(value["fields"]) || value["projection"] !== null && !isRecord(value["projection"])) throw new TypeError("invalid AI stored state");
|
|
1739
1752
|
const state = value;
|
|
1740
1753
|
if (Object.keys(state.values).length !== state.values.length) throw new TypeError("invalid AI payload table");
|
|
1741
1754
|
for (const payload of state.values) if (!hasKeys(payload, {
|
|
@@ -1824,52 +1837,36 @@ const schema = (label, parse) => ({ "~standard": {
|
|
|
1824
1837
|
}
|
|
1825
1838
|
}
|
|
1826
1839
|
} });
|
|
1827
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1828
|
-
const isJSONCompatible = (value, seen = /* @__PURE__ */ new Set()) => {
|
|
1829
|
-
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
1830
|
-
if (typeof value === "number") return Number.isFinite(value);
|
|
1831
|
-
if (typeof value === "undefined") return true;
|
|
1832
|
-
if (typeof value !== "object") return false;
|
|
1833
|
-
if (seen.has(value)) return false;
|
|
1834
|
-
seen.add(value);
|
|
1835
|
-
const valid = Array.isArray(value) ? value.every((item) => isJSONCompatible(item, seen)) : Object.getPrototypeOf(value) === Object.prototype && Object.values(value).every((item) => isJSONCompatible(item, seen));
|
|
1836
|
-
seen.delete(value);
|
|
1837
|
-
return valid;
|
|
1838
|
-
};
|
|
1839
1840
|
const jsonObject = (label, check) => schema(label, (value) => {
|
|
1840
|
-
if (!isRecord(value) || !isJSONCompatible(value) || !check(value)) return issue(`invalid ${label}`);
|
|
1841
|
+
if (!isRecord$1(value) || !isJSONCompatible(value) || !check(value)) return issue(`invalid ${label}`);
|
|
1841
1842
|
return { value };
|
|
1842
1843
|
});
|
|
1843
1844
|
const stringField = (value, key) => typeof value[key] === "string" && value[key].length > 0;
|
|
1844
1845
|
const optionalIndexField = (value, key) => value[key] === void 0 || typeof value[key] === "number" && Number.isSafeInteger(value[key]) && value[key] >= 0;
|
|
1845
1846
|
const optionalStringField = (value, key) => value[key] === void 0 || typeof value[key] === "string";
|
|
1846
|
-
const messageValue = (value) => isRecord(value) && typeof value["id"] === "string" && (value["role"] === "user" || value["role"] === "assistant" || value["role"] === "system") && Array.isArray(value["parts"]) && value["parts"].every((part) => isRecord(part) && typeof part["type"] === "string") && isJSONCompatible(value);
|
|
1847
1847
|
const validateMessage = (value, messageSchema) => {
|
|
1848
|
-
if (!
|
|
1848
|
+
if (!isUIMessage(value)) return issue("invalid AI SDK UIMessage");
|
|
1849
1849
|
if (!messageSchema) return { value };
|
|
1850
1850
|
return validateSync(messageSchema, value, "the AI message");
|
|
1851
1851
|
};
|
|
1852
|
-
const
|
|
1853
|
-
if (!isRecord(value)) return issue("invalid ai.message.created payload");
|
|
1854
|
-
const message = validateMessage(value["message"], messageSchema);
|
|
1855
|
-
if (message.issues) return { issues: message.issues };
|
|
1856
|
-
const generate = value["generate"];
|
|
1857
|
-
if (generate !== void 0 && typeof generate !== "boolean") return issue("invalid ai.message.created generate flag");
|
|
1852
|
+
const messageCreatedSchema = schema("ai.message.created", (value) => {
|
|
1853
|
+
if (!isRecord$1(value) || Object.keys(value).some((key) => key !== "messageId" && key !== "role" && key !== "generate") || !stringField(value, "messageId") || value["role"] !== "user" && value["role"] !== "assistant" && value["role"] !== "system" || value["generate"] !== void 0 && value["generate"] !== false) return issue("invalid ai.message.created payload");
|
|
1858
1854
|
return { value: {
|
|
1859
|
-
|
|
1860
|
-
|
|
1855
|
+
messageId: value["messageId"],
|
|
1856
|
+
role: value["role"],
|
|
1857
|
+
...value["generate"] === false ? { generate: false } : {}
|
|
1861
1858
|
} };
|
|
1862
1859
|
});
|
|
1863
1860
|
const progressPayloadSchema = schema("ai.generation.progress", (value) => {
|
|
1864
|
-
if (!isRecord(value) || !isJSONCompatible(value) || typeof value["startIndex"] !== "number" || !optionalIndexField(value, "startIndex") || !Array.isArray(value["chunks"]) || !value["chunks"].every((chunk) => isRecord(chunk) && typeof chunk["type"] === "string")) return issue("invalid ai.generation.progress payload");
|
|
1861
|
+
if (!isRecord$1(value) || !isJSONCompatible(value) || typeof value["startIndex"] !== "number" || !optionalIndexField(value, "startIndex") || !Array.isArray(value["chunks"]) || !value["chunks"].every((chunk) => isRecord$1(chunk) && typeof chunk["type"] === "string")) return issue("invalid ai.generation.progress payload");
|
|
1865
1862
|
return { value };
|
|
1866
1863
|
});
|
|
1867
1864
|
const completedPayloadSchema = schema("ai.generation.completed", (value) => {
|
|
1868
|
-
if (!isRecord(value) || !isJSONCompatible(value) || !stringField(value, "requestId") || !stringField(value, "messageId") || !stringField(value, "generationId") || !stringField(value, "responseMessageId") || !optionalIndexField(value, "inputTokenEstimate") || !optionalStringField(value, "finishReason")) return issue("invalid ai.generation.completed payload");
|
|
1865
|
+
if (!isRecord$1(value) || !isJSONCompatible(value) || !stringField(value, "requestId") || !stringField(value, "messageId") || !stringField(value, "generationId") || !stringField(value, "responseMessageId") || !optionalIndexField(value, "inputTokenEstimate") || !optionalStringField(value, "finishReason")) return issue("invalid ai.generation.completed payload");
|
|
1869
1866
|
return { value };
|
|
1870
1867
|
});
|
|
1871
1868
|
const compactionPayloadSchema = (messageSchema) => schema("ai.compaction.completed", (value) => {
|
|
1872
|
-
if (!isRecord(value) || !isJSONCompatible(value) || !stringField(value, "generationId") || !stringField(value, "throughMessageId") || !optionalIndexField(value, "throughIndex") || !optionalStringField(value, "summary") || !Array.isArray(value["messages"]) || value["retainedMessageIds"] !== void 0 && (!Array.isArray(value["retainedMessageIds"]) || !value["retainedMessageIds"].every((candidate) => typeof candidate === "string"))) return issue("invalid ai.compaction.completed payload");
|
|
1869
|
+
if (!isRecord$1(value) || !isJSONCompatible(value) || !stringField(value, "generationId") || !stringField(value, "throughMessageId") || !optionalIndexField(value, "throughIndex") || !optionalStringField(value, "summary") || !Array.isArray(value["messages"]) || value["retainedMessageIds"] !== void 0 && (!Array.isArray(value["retainedMessageIds"]) || !value["retainedMessageIds"].every((candidate) => typeof candidate === "string"))) return issue("invalid ai.compaction.completed payload");
|
|
1873
1870
|
const messages = [];
|
|
1874
1871
|
for (const candidate of value["messages"]) {
|
|
1875
1872
|
const result = validateMessage(candidate, messageSchema);
|
|
@@ -1891,7 +1888,7 @@ function createEvents(options) {
|
|
|
1891
1888
|
if (messageSchema) assertSyncSchema(messageSchema, "the AI message schema");
|
|
1892
1889
|
const definition = {
|
|
1893
1890
|
"ai.control.requested": schema("ai.control.requested", (value) => {
|
|
1894
|
-
if (!isRecord(value) || !isJSONCompatible(value)) return issue("invalid AI command");
|
|
1891
|
+
if (!isRecord$1(value) || !isJSONCompatible(value)) return issue("invalid AI command");
|
|
1895
1892
|
const action = value["action"];
|
|
1896
1893
|
const forwarded = {
|
|
1897
1894
|
approval: ["ai.approval.responded", "response"],
|
|
@@ -1905,6 +1902,7 @@ function createEvents(options) {
|
|
|
1905
1902
|
const [type, key] = forwarded[action];
|
|
1906
1903
|
const payload = validateSync(definition[type], value[key], "AI command");
|
|
1907
1904
|
if (payload.issues) return { issues: payload.issues };
|
|
1905
|
+
if (action === "interrupt" && isRecord$1(payload.value) && payload.value["reason"] === "steered after step") return issue(`the interruption reason "${STEERED_REASON}" is reserved for steering`);
|
|
1908
1906
|
return { value: {
|
|
1909
1907
|
action,
|
|
1910
1908
|
[key]: payload.value
|
|
@@ -1923,10 +1921,10 @@ function createEvents(options) {
|
|
|
1923
1921
|
if (action === "remove" && stringField(value, "inputId") || action === "send-now" && stringField(value, "inputId") && (value["turnId"] === null || stringField(value, "turnId")) && optionalIndexField(value, "lastSeenIndex") || action === "move" && stringField(value, "inputId") && (value["beforeId"] === null || stringField(value, "beforeId")) || action === "stop" && stringField(value, "turnId") && optionalIndexField(value, "lastSeenIndex") || action === "pause" && (value["when"] === "now" || value["when"] === "after-turn") || action === "resume") return { value };
|
|
1924
1922
|
return issue("invalid AI command");
|
|
1925
1923
|
}),
|
|
1926
|
-
"ai.control.committed": jsonObject("ai.control.committed", (value) => Array.isArray(value["changes"]) && isRecord(value["view"])),
|
|
1924
|
+
"ai.control.committed": jsonObject("ai.control.committed", (value) => Array.isArray(value["changes"]) && isRecord$1(value["view"])),
|
|
1927
1925
|
"ai.control.decided": jsonObject("ai.control.decided", (value) => stringField(value, "commandId") && (value["outcome"] === "applied" || value["outcome"] === "rejected")),
|
|
1928
1926
|
"ai.work.reported": schema("ai.work.reported", (value) => {
|
|
1929
|
-
if (!isRecord(value) || !isJSONCompatible(value) || !stringField(value, "workId") || !stringField(value, "turnId") || typeof value["version"] !== "number" || !optionalIndexField(value, "version") || typeof value["attempt"] !== "number" || !Number.isSafeInteger(value["attempt"]) || value["attempt"] < 1 || typeof value["settled"] !== "boolean" || value["kind"] !== "model" && value["kind"] !== "tool" || !Array.isArray(value["events"])) return issue("invalid AI work report");
|
|
1927
|
+
if (!isRecord$1(value) || !isJSONCompatible(value) || !stringField(value, "workId") || !stringField(value, "turnId") || typeof value["version"] !== "number" || !optionalIndexField(value, "version") || typeof value["attempt"] !== "number" || !Number.isSafeInteger(value["attempt"]) || value["attempt"] < 1 || typeof value["settled"] !== "boolean" || value["kind"] !== "model" && value["kind"] !== "tool" || !Array.isArray(value["events"])) return issue("invalid AI work report");
|
|
1930
1928
|
const allowed = /* @__PURE__ */ new Set([
|
|
1931
1929
|
"ai.generation.started",
|
|
1932
1930
|
"ai.generation.completed",
|
|
@@ -1941,7 +1939,7 @@ function createEvents(options) {
|
|
|
1941
1939
|
]);
|
|
1942
1940
|
const events = [];
|
|
1943
1941
|
for (const event of value["events"]) {
|
|
1944
|
-
if (!isRecord(event) || !stringField(event, "id") || typeof event["type"] !== "string" || !allowed.has(event["type"]) || value["kind"] === "tool" && event["type"] !== "ai.tool.result") return issue("invalid AI work fact");
|
|
1942
|
+
if (!isRecord$1(event) || !stringField(event, "id") || typeof event["type"] !== "string" || !allowed.has(event["type"]) || value["kind"] === "tool" && event["type"] !== "ai.tool.result") return issue("invalid AI work fact");
|
|
1945
1943
|
const parsed = validateSync(definition[event["type"]], event["payload"], "AI work fact");
|
|
1946
1944
|
if (parsed.issues) return { issues: parsed.issues };
|
|
1947
1945
|
events.push({
|
|
@@ -1955,11 +1953,11 @@ function createEvents(options) {
|
|
|
1955
1953
|
events
|
|
1956
1954
|
} };
|
|
1957
1955
|
}),
|
|
1958
|
-
"ai.tool.execution.requested": jsonObject("ai.tool.execution.requested", (value) => stringField(value, "turnId") && optionalIndexField(value, "version") && isRecord(value["call"]) && isRecord(value["generation"])),
|
|
1956
|
+
"ai.tool.execution.requested": jsonObject("ai.tool.execution.requested", (value) => stringField(value, "turnId") && optionalIndexField(value, "version") && isRecord$1(value["call"]) && isRecord$1(value["generation"])),
|
|
1959
1957
|
"ai.generation.paused": jsonObject("ai.generation.paused", (value) => stringField(value, "generationId") && stringField(value, "messageId")),
|
|
1960
1958
|
"ai.session.created": jsonObject("ai.session.created", () => true),
|
|
1961
1959
|
"ai.session.closed": jsonObject("ai.session.closed", (value) => optionalStringField(value, "reason")),
|
|
1962
|
-
"ai.message.created":
|
|
1960
|
+
"ai.message.created": messageCreatedSchema,
|
|
1963
1961
|
"ai.message.completed": jsonObject("ai.message.completed", (value) => stringField(value, "messageId")),
|
|
1964
1962
|
"ai.message.interrupted": jsonObject("ai.message.interrupted", (value) => stringField(value, "messageId") && (stringField(value, "generationId") && value["requestId"] === void 0 || stringField(value, "requestId") && value["generationId"] === void 0) && optionalStringField(value, "reason") && (value["lastSeenIndex"] === void 0 || typeof value["lastSeenIndex"] === "number" && Number.isInteger(value["lastSeenIndex"]) && value["lastSeenIndex"] >= 0)),
|
|
1965
1963
|
"ai.generation.requested": jsonObject("ai.generation.requested", (value) => stringField(value, "messageId") && stringField(value, "responseMessageId") && optionalStringField(value, "sourceGenerationId") && (value["reason"] !== "tool" || stringField(value, "sourceGenerationId")) && (value["reason"] === "message" || value["reason"] === "tool" || value["reason"] === "input" || value["reason"] === "retry" || value["reason"] === "resume")),
|
|
@@ -1977,13 +1975,16 @@ function createEvents(options) {
|
|
|
1977
1975
|
"ai.compaction.requested": jsonObject("ai.compaction.requested", (value) => stringField(value, "generationId") && stringField(value, "throughMessageId") && optionalIndexField(value, "throughIndex") && optionalIndexField(value, "inputTokenEstimate") && optionalIndexField(value, "inputTokens") && optionalIndexField(value, "thresholdTokens")),
|
|
1978
1976
|
"ai.compaction.completed": compactionPayloadSchema(messageSchema),
|
|
1979
1977
|
"ai.model.metadata.requested": jsonObject("ai.model.metadata.requested", (value) => stringField(value, "modelId")),
|
|
1980
|
-
"ai.model.metadata.resolved": jsonObject("ai.model.metadata.resolved", (value) => stringField(value, "modelId") && (value["limits"] === null || isRecord(value["limits"]) && typeof value["limits"]["contextWindow"] === "number" && Number.isSafeInteger(value["limits"]["contextWindow"]) && value["limits"]["contextWindow"] > 0 && typeof value["limits"]["maxOutputTokens"] === "number" && Number.isSafeInteger(value["limits"]["maxOutputTokens"]) && value["limits"]["maxOutputTokens"] > 0))
|
|
1978
|
+
"ai.model.metadata.resolved": jsonObject("ai.model.metadata.resolved", (value) => stringField(value, "modelId") && (value["limits"] === null || isRecord$1(value["limits"]) && typeof value["limits"]["contextWindow"] === "number" && Number.isSafeInteger(value["limits"]["contextWindow"]) && value["limits"]["contextWindow"] > 0 && typeof value["limits"]["maxOutputTokens"] === "number" && Number.isSafeInteger(value["limits"]["maxOutputTokens"]) && value["limits"]["maxOutputTokens"] > 0))
|
|
1981
1979
|
};
|
|
1982
1980
|
return definition;
|
|
1983
1981
|
}
|
|
1984
1982
|
const events = createEvents();
|
|
1985
1983
|
const initialState = () => ({
|
|
1986
|
-
inbox:
|
|
1984
|
+
inbox: {
|
|
1985
|
+
paused: false,
|
|
1986
|
+
items: []
|
|
1987
|
+
},
|
|
1987
1988
|
pendingQueueCommands: [],
|
|
1988
1989
|
active: null,
|
|
1989
1990
|
starting: false,
|
|
@@ -2045,6 +2046,18 @@ function reduceAIState(state, event) {
|
|
|
2045
2046
|
after: reduceAIEvent(state, event)
|
|
2046
2047
|
}));
|
|
2047
2048
|
}
|
|
2049
|
+
/**
|
|
2050
|
+
* An input's content, while it is queued or about to enter the transcript:
|
|
2051
|
+
* its inbox item's, or its pending send's or steer's, whose command id is the
|
|
2052
|
+
* input's id.
|
|
2053
|
+
*/
|
|
2054
|
+
function inputContent(state, id) {
|
|
2055
|
+
const queued = state.inbox.items.find((item) => item.id === id)?.message;
|
|
2056
|
+
if (queued !== void 0) return queued;
|
|
2057
|
+
const command = state.pendingQueueCommands?.find((item) => item.commandId === id)?.command;
|
|
2058
|
+
if (command?.action === "send" || command?.action === "steer") return command.message;
|
|
2059
|
+
throw unexplainedAdmission(id);
|
|
2060
|
+
}
|
|
2048
2061
|
function reduceAIEvent(state, event) {
|
|
2049
2062
|
if (state.status === "closed") return state;
|
|
2050
2063
|
switch (event.type) {
|
|
@@ -2064,18 +2077,35 @@ function reduceAIEvent(state, event) {
|
|
|
2064
2077
|
}
|
|
2065
2078
|
case "ai.control.committed": {
|
|
2066
2079
|
const commit = event.payload;
|
|
2067
|
-
const
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2080
|
+
const changes = commit.changes.filter((change) => change.path[0] === "inbox" || change.path[0] === "active");
|
|
2081
|
+
let { inbox, active } = state;
|
|
2082
|
+
if (changes.length > 0) {
|
|
2083
|
+
const visible = applyControlChanges({
|
|
2084
|
+
state: {
|
|
2085
|
+
inbox: {
|
|
2086
|
+
...inbox,
|
|
2087
|
+
items: inbox.items.map(({ message: _, ...input }) => input)
|
|
2088
|
+
},
|
|
2089
|
+
active
|
|
2090
|
+
},
|
|
2091
|
+
changes
|
|
2092
|
+
});
|
|
2093
|
+
const queued = new Map(inbox.items.map((item) => [item.id, item]));
|
|
2094
|
+
inbox = {
|
|
2095
|
+
...visible.inbox,
|
|
2096
|
+
items: visible.inbox.items.map((input) => ({
|
|
2097
|
+
...input,
|
|
2098
|
+
message: queued.get(input.id)?.message ?? inputContent(state, input.id)
|
|
2099
|
+
}))
|
|
2100
|
+
};
|
|
2101
|
+
active = visible.active;
|
|
2102
|
+
}
|
|
2074
2103
|
const { phase } = commit.view;
|
|
2075
2104
|
const status = commit.view.closed ? "closed" : phase === "paused" || phase === "pausing" || commit.view.paused && phase === null ? "paused" : phase === "failed" ? "failed" : phase === "starting" || phase === "generating" ? "generating" : phase ? "waiting" : "idle";
|
|
2076
2105
|
return {
|
|
2077
2106
|
...state,
|
|
2078
|
-
|
|
2107
|
+
inbox,
|
|
2108
|
+
active,
|
|
2079
2109
|
status,
|
|
2080
2110
|
activeRequestId: commit.view.requestId,
|
|
2081
2111
|
activeRequestReason: commit.view.requestReason,
|
|
@@ -2088,9 +2118,17 @@ function reduceAIEvent(state, event) {
|
|
|
2088
2118
|
if (receipt.work) return state;
|
|
2089
2119
|
const pending = state.pendingQueueCommands ?? [];
|
|
2090
2120
|
const settled = pending.find((item) => item.commandId === receipt.commandId);
|
|
2121
|
+
const edited = receipt.outcome === "applied" && settled?.command.action === "edit" ? settled.command.message : void 0;
|
|
2091
2122
|
return {
|
|
2092
2123
|
...state,
|
|
2093
2124
|
receipt,
|
|
2125
|
+
...edited === void 0 ? {} : { inbox: {
|
|
2126
|
+
...state.inbox,
|
|
2127
|
+
items: state.inbox.items.map((item) => item.id === edited.id ? {
|
|
2128
|
+
...item,
|
|
2129
|
+
message: edited
|
|
2130
|
+
} : item)
|
|
2131
|
+
} },
|
|
2094
2132
|
...settled === void 0 ? {} : { pendingQueueCommands: pending.filter((item) => item.commandId !== receipt.commandId) }
|
|
2095
2133
|
};
|
|
2096
2134
|
}
|
|
@@ -2172,7 +2210,8 @@ function reduceAIEvent(state, event) {
|
|
|
2172
2210
|
activeProjection: null
|
|
2173
2211
|
};
|
|
2174
2212
|
case "ai.message.created": {
|
|
2175
|
-
const {
|
|
2213
|
+
const { messageId } = event.payload;
|
|
2214
|
+
const message = inputContent(state, messageId);
|
|
2176
2215
|
return {
|
|
2177
2216
|
...state,
|
|
2178
2217
|
messages: upsertMessage(state.messages, message),
|
|
@@ -2804,7 +2843,7 @@ function handlerContext(contract) {
|
|
|
2804
2843
|
return scope.context;
|
|
2805
2844
|
}
|
|
2806
2845
|
/** The built-in AI reducer's name, and so its checkpoint identity. */
|
|
2807
|
-
const AI_STATE_REDUCER = "a2.ai.state.
|
|
2846
|
+
const AI_STATE_REDUCER = "a2.ai.state.v27";
|
|
2808
2847
|
/**
|
|
2809
2848
|
* The built-in AI protocol plus application events, as a core contract whose
|
|
2810
2849
|
* reducer folds `AIState`. Isomorphic: share it when a client needs
|
|
@@ -2851,6 +2890,6 @@ function agentContract(options) {
|
|
|
2851
2890
|
return shared;
|
|
2852
2891
|
}
|
|
2853
2892
|
//#endregion
|
|
2854
|
-
export { interruptUIMessage as A, reduceToolActivity as C, flattenProgressBatches as D, upsertResponse as E, assertMessageBase as M, restoreMessageBase as N, progressBatches as O, projectedMessage as S, upsertMessage as T, applyControlChanges as _, events as a, findMessage as b, reasoningLevels as c, appSlice as d, isAgentContract as f,
|
|
2893
|
+
export { interruptUIMessage as A, reduceToolActivity as C, flattenProgressBatches as D, upsertResponse as E, assertMessageBase as M, restoreMessageBase as N, progressBatches as O, projectedMessage as S, upsertMessage as T, applyControlChanges as _, events as a, findMessage as b, reasoningLevels as c, appSlice as d, isAgentContract as f, isUIMessage as g, aiEventId as h, deriveUIMessages as i, pauseUIMessage as j, progressOwnedBy as k, reduceAIState as l, AI_EVENT_ID_PREFIX as m, agentContract as n, handlerContext as o, withAIStorage as p, createEvents as r, inputs as s, AI_STATE_REDUCER as t, appReducerOf as u, controlCommit as v, retainMessageBase as w, isCompactionPart as x, advanceProjection as y };
|
|
2855
2894
|
|
|
2856
|
-
//# sourceMappingURL=ai-
|
|
2895
|
+
//# sourceMappingURL=ai-mMiWul1T.js.map
|