experimental-a2 0.20.0 → 0.22.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 +55 -0
- package/README.md +1 -1
- package/dist/{actor-C7b-1arn.d.ts → actor-CqibLgjQ.d.ts} +15 -7
- package/dist/actor-CqibLgjQ.d.ts.map +1 -0
- package/dist/actor-client.d.ts +1 -1
- package/dist/actor-client.js +2 -2
- package/dist/actor-react.d.ts +3 -3
- package/dist/actor-react.js +5 -5
- package/dist/{actor-shared-t7w8xIKP.js → actor-shared-DFET5q16.js} +3 -3
- package/dist/actor-shared-DFET5q16.js.map +1 -0
- package/dist/actor.d.ts +1 -1
- package/dist/actor.js +54 -43
- package/dist/actor.js.map +1 -1
- package/dist/{ai-Cz3hqVhk.d.ts → ai-DAu77CDr.d.ts} +8 -8
- package/dist/{ai-Cz3hqVhk.d.ts.map → ai-DAu77CDr.d.ts.map} +1 -1
- package/dist/{ai-mMiWul1T.js → ai-EEfKyc-z.js} +9 -9
- package/dist/ai-EEfKyc-z.js.map +1 -0
- package/dist/ai-client.d.ts +2 -2
- package/dist/ai-client.js +2 -2
- package/dist/ai-fx.d.ts +4 -2
- package/dist/ai-fx.d.ts.map +1 -1
- package/dist/ai-fx.js +214 -67
- package/dist/ai-fx.js.map +1 -1
- package/dist/{ai-harness-CV6rXbB3.d.ts → ai-harness-DTjkAr2T.d.ts} +2 -2
- package/dist/{ai-harness-CV6rXbB3.d.ts.map → ai-harness-DTjkAr2T.d.ts.map} +1 -1
- package/dist/{ai-harness-Clbg5ei7.js → ai-harness-dQeJaR1t.js} +7 -3
- package/dist/ai-harness-dQeJaR1t.js.map +1 -0
- package/dist/ai-pi.d.ts +1 -1
- package/dist/ai-pi.js +3 -3
- package/dist/ai-pi.js.map +1 -1
- package/dist/ai-react.d.ts +5 -5
- package/dist/ai-react.js +2 -2
- package/dist/ai-server.d.ts +14 -17
- package/dist/ai-server.d.ts.map +1 -1
- package/dist/ai-server.js +86 -73
- package/dist/ai-server.js.map +1 -1
- package/dist/ai.d.ts +2 -2
- package/dist/ai.js +2 -2
- package/dist/{client-BhHLoNKF.js → client-BQS4i_V9.js} +29 -6
- package/dist/client-BQS4i_V9.js.map +1 -0
- package/dist/{client-h_DKFAjj.d.ts → client-CUMbS_38.d.ts} +3 -3
- package/dist/{client-h_DKFAjj.d.ts.map → client-CUMbS_38.d.ts.map} +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/{contract-BYKASlCV.js → contract-CWukt01d.js} +2 -2
- package/dist/contract-CWukt01d.js.map +1 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +3 -3
- package/dist/{initial-snapshot-Bx-c0pDP.d.ts → initial-snapshot-D3Lve43o.d.ts} +4 -4
- package/dist/initial-snapshot-D3Lve43o.d.ts.map +1 -0
- package/dist/{internal-CscSY7K_.js → internal-CvsrprnU.js} +40 -16
- package/dist/internal-CvsrprnU.js.map +1 -0
- package/dist/otel.d.ts +1 -1
- package/dist/otel.js +1 -1
- package/dist/otel.js.map +1 -1
- package/dist/{react-BBXgHWFc.d.ts → react-BoHvC3v9.d.ts} +4 -4
- package/dist/{react-BBXgHWFc.d.ts.map → react-BoHvC3v9.d.ts.map} +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{reducer-CqA59Q6U.d.ts → reducer-CYPHsSmd.d.ts} +2 -2
- package/dist/{reducer-CqA59Q6U.d.ts.map → reducer-CYPHsSmd.d.ts.map} +1 -1
- package/dist/{reducer-BAXc8JyF.js → reducer-CjmvZSAb.js} +2 -2
- package/dist/{reducer-BAXc8JyF.js.map → reducer-CjmvZSAb.js.map} +1 -1
- package/dist/runtime-consumer-CIeL33wj.js +12 -0
- package/dist/runtime-consumer-CIeL33wj.js.map +1 -0
- package/dist/scheduler-qstash.d.ts +2 -2
- package/dist/scheduler-qstash.js +3 -3
- package/dist/scheduler-task-X1SToDjP.js.map +1 -1
- package/dist/scheduler-vercel.d.ts +2 -2
- package/dist/scheduler-vercel.js +3 -3
- package/dist/scheduler-vercel.js.map +1 -1
- package/dist/{server-qyb5aJJG.js → server-DtFrWxi3.js} +412 -116
- package/dist/server-DtFrWxi3.js.map +1 -0
- package/dist/{server-DYAATFuT.d.ts → server-qgez0Xny.d.ts} +108 -41
- package/dist/server-qgez0Xny.d.ts.map +1 -0
- package/dist/server.browser.js +1 -1
- package/dist/server.browser.js.map +1 -1
- package/dist/server.d.ts +4 -4
- package/dist/server.js +2 -2
- package/dist/{session-clear-C-QwTXV1.d.ts → session-clear-D1PFe7xl.d.ts} +2 -2
- package/dist/session-clear-D1PFe7xl.d.ts.map +1 -0
- package/dist/{session-clear-DGI4jTQ5.js → session-clear-wHd5GCpZ.js} +5 -4
- package/dist/session-clear-wHd5GCpZ.js.map +1 -0
- package/dist/store-D0MhBvg6.d.ts +532 -0
- package/dist/store-D0MhBvg6.d.ts.map +1 -0
- package/dist/store-N8PXxDAS.js.map +1 -1
- package/dist/store-codec-DwrWlgQx.js +65 -0
- package/dist/store-codec-DwrWlgQx.js.map +1 -0
- package/dist/store-memory.d.ts +1 -1
- package/dist/store-memory.d.ts.map +1 -1
- package/dist/store-memory.js +406 -225
- package/dist/store-memory.js.map +1 -1
- package/dist/{store-polling-7WJV0YWP.js → store-polling-BZt2Rf3D.js} +2 -2
- package/dist/{store-polling-7WJV0YWP.js.map → store-polling-BZt2Rf3D.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 +1598 -587
- package/dist/store-postgres.js.map +1 -1
- package/dist/store-presence-polling-JuAy2Ck2.js +111 -0
- package/dist/store-presence-polling-JuAy2Ck2.js.map +1 -0
- package/dist/store-redis-http.d.ts +1 -1
- package/dist/store-redis-http.js +4 -4
- package/dist/store-redis-notify-CsJw_hfD.js +3060 -0
- package/dist/store-redis-notify-CsJw_hfD.js.map +1 -0
- package/dist/store-redis.d.ts +1 -1
- package/dist/store-redis.d.ts.map +1 -1
- package/dist/store-redis.js +4 -5
- package/dist/store-redis.js.map +1 -1
- package/dist/store-sqlite.d.ts +1 -1
- package/dist/store-sqlite.d.ts.map +1 -1
- package/dist/store-sqlite.js +527 -299
- package/dist/store-sqlite.js.map +1 -1
- package/dist/stream-buffer-DrTyiIuo.js +57 -0
- package/dist/stream-buffer-DrTyiIuo.js.map +1 -0
- package/dist/{telemetry-Cyfqo6Qt.d.ts → telemetry-CWwsh-Gx.d.ts} +3 -3
- package/dist/telemetry-CWwsh-Gx.d.ts.map +1 -0
- package/dist/{wire-BKxH1vbP.js → wire-CV-Z7wz-.js} +6 -5
- package/dist/wire-CV-Z7wz-.js.map +1 -0
- package/docs/01-quickstart.mdx +21 -15
- package/docs/02-examples.mdx +1 -1
- package/docs/actors/01-introduction.mdx +13 -2
- package/docs/actors/02-concurrency.mdx +1 -1
- package/docs/agents/01-introduction.mdx +1 -1
- package/docs/agents/02-tools.mdx +12 -11
- package/docs/agents/03-conversations.mdx +36 -25
- package/docs/agents/04-harnesses.mdx +14 -7
- package/docs/client/03-presence.mdx +18 -14
- package/docs/contract/01-events.mdx +2 -2
- package/docs/contract/02-state.mdx +18 -14
- package/docs/contract/03-sessions.mdx +32 -25
- package/docs/index.mdx +29 -24
- package/docs/reference/01-core.mdx +7 -6
- package/docs/reference/02-server.mdx +250 -191
- package/docs/reference/04-ai.mdx +33 -23
- package/docs/reference/05-telemetry.mdx +27 -13
- package/docs/reference/06-errors.mdx +25 -19
- package/docs/reference/meta.ts +1 -1
- package/docs/schedulers/01-overview.mdx +8 -8
- package/docs/schedulers/02-vercel-queues.mdx +2 -2
- package/docs/schedulers/03-qstash.mdx +4 -4
- package/docs/server/01-consumers.mdx +418 -0
- package/docs/server/02-timers.mdx +31 -21
- package/docs/server/03-cancellation.mdx +52 -44
- package/docs/server/04-routes.mdx +4 -1
- package/docs/server/05-sql-projections.mdx +391 -0
- package/docs/server/06-guarantees.mdx +61 -51
- package/docs/stores/01-overview.mdx +3 -3
- package/docs/stores/02-redis.mdx +24 -10
- package/docs/stores/03-redis-http.mdx +8 -6
- package/docs/stores/04-postgres.mdx +65 -14
- package/docs/stores/05-sqlite.mdx +5 -3
- package/docs/upgrades/01-overview.mdx +31 -0
- package/docs/upgrades/78-0-22.mdx +115 -0
- package/docs/upgrades/79-0-21.mdx +165 -0
- package/docs/upgrades/80-0-20.mdx +43 -0
- package/docs/upgrades/81-0-19.mdx +33 -0
- package/docs/upgrades/82-0-18.mdx +33 -0
- package/docs/upgrades/83-0-17.mdx +69 -0
- package/docs/upgrades/meta.ts +3 -0
- package/examples/playground/DEPLOY.md +39 -7
- package/examples/playground/app/a0/chat.test.tsx +2 -2
- package/examples/playground/app/a0/sandbox-log.ts +17 -15
- package/examples/playground/app/a0/sandbox.ts +58 -13
- package/examples/playground/app/a0/server.ts +4 -4
- package/examples/playground/app/a2slack/a2slack.css +1067 -0
- package/examples/playground/app/a2slack/c/[channel]/page.tsx +20 -0
- package/examples/playground/app/a2slack/consumers/agent.ts +63 -0
- package/examples/playground/app/a2slack/consumers/feed.ts +164 -0
- package/examples/playground/app/a2slack/consumers/notify.ts +116 -0
- package/examples/playground/app/a2slack/consumers/search.ts +37 -0
- package/examples/playground/app/a2slack/consumers/triage.ts +31 -0
- package/examples/playground/app/a2slack/consumers/welcome.ts +25 -0
- package/examples/playground/app/a2slack/db/a2.ts +209 -0
- package/examples/playground/app/a2slack/db/index.ts +73 -0
- package/examples/playground/app/a2slack/db/migrations/0000_extensions.sql +4 -0
- package/examples/playground/app/a2slack/db/migrations/0001_workspace.sql +74 -0
- package/examples/playground/app/a2slack/db/migrations/0002_a2.sql +215 -0
- package/examples/playground/app/a2slack/db/migrations/0003_a2_batch.sql +67 -0
- package/examples/playground/app/a2slack/db/migrations/0004_a2_session_event_ids.sql +2 -0
- package/examples/playground/app/a2slack/db/migrations/meta/0000_snapshot.json +18 -0
- package/examples/playground/app/a2slack/db/migrations/meta/0001_snapshot.json +500 -0
- package/examples/playground/app/a2slack/db/migrations/meta/0002_snapshot.json +1159 -0
- package/examples/playground/app/a2slack/db/migrations/meta/0003_snapshot.json +1159 -0
- package/examples/playground/app/a2slack/db/migrations/meta/0004_snapshot.json +1165 -0
- package/examples/playground/app/a2slack/db/migrations/meta/_journal.json +41 -0
- package/examples/playground/app/a2slack/db/queries.ts +263 -0
- package/examples/playground/app/a2slack/db/schema.ts +145 -0
- package/examples/playground/app/a2slack/drills/a2slack.drill.ts +708 -0
- package/examples/playground/app/a2slack/drills/harness.ts +244 -0
- package/examples/playground/app/a2slack/events/route.ts +36 -0
- package/examples/playground/app/a2slack/identity.ts +44 -0
- package/examples/playground/app/a2slack/inbox/route.ts +8 -0
- package/examples/playground/app/a2slack/lag/data/route.ts +8 -0
- package/examples/playground/app/a2slack/lag/page.tsx +101 -0
- package/examples/playground/app/a2slack/lag.ts +73 -0
- package/examples/playground/app/a2slack/layout.tsx +43 -0
- package/examples/playground/app/a2slack/messages/route.ts +17 -0
- package/examples/playground/app/a2slack/model.test.ts +208 -0
- package/examples/playground/app/a2slack/model.ts +369 -0
- package/examples/playground/app/a2slack/models.test.ts +72 -0
- package/examples/playground/app/a2slack/page.tsx +10 -0
- package/examples/playground/app/a2slack/scheduler/route.ts +5 -0
- package/examples/playground/app/a2slack/search/route.ts +40 -0
- package/examples/playground/app/a2slack/search-index.ts +108 -0
- package/examples/playground/app/a2slack/server.test.ts +315 -0
- package/examples/playground/app/a2slack/server.ts +55 -0
- package/examples/playground/app/a2slack/sessions.ts +50 -0
- package/examples/playground/app/a2slack/thread/route.ts +8 -0
- package/examples/playground/app/a2slack/ui/ChannelView.tsx +87 -0
- package/examples/playground/app/a2slack/ui/Composer.tsx +117 -0
- package/examples/playground/app/a2slack/ui/DotsShadow.tsx +42 -0
- package/examples/playground/app/a2slack/ui/Feed.tsx +157 -0
- package/examples/playground/app/a2slack/ui/InboxContext.tsx +63 -0
- package/examples/playground/app/a2slack/ui/InboxView.tsx +82 -0
- package/examples/playground/app/a2slack/ui/Menu.tsx +128 -0
- package/examples/playground/app/a2slack/ui/MessageRow.tsx +314 -0
- package/examples/playground/app/a2slack/ui/NameGate.tsx +35 -0
- package/examples/playground/app/a2slack/ui/SearchContext.tsx +146 -0
- package/examples/playground/app/a2slack/ui/SearchResults.tsx +97 -0
- package/examples/playground/app/a2slack/ui/Shell.tsx +34 -0
- package/examples/playground/app/a2slack/ui/Sidebar.tsx +199 -0
- package/examples/playground/app/a2slack/ui/ThreadPanel.tsx +134 -0
- package/examples/playground/app/a2slack/ui/useInbox.ts +71 -0
- package/examples/playground/app/agent/server.ts +3 -3
- package/examples/playground/app/chat/[chatId]/chat-client.tsx +1 -1
- package/examples/playground/app/chat/server.ts +45 -35
- package/examples/playground/app/components/demo-icons.tsx +7 -0
- package/examples/playground/app/components/demos.tsx +7 -0
- package/examples/playground/app/orders/[orderId]/order-client.tsx +2 -2
- package/examples/playground/app/orders/page.tsx +1 -1
- package/examples/playground/app/orders/server.ts +49 -30
- package/examples/playground/app/recovery/[recoveryId]/recovery-client.tsx +14 -15
- package/examples/playground/app/recovery/page.tsx +4 -4
- package/examples/playground/app/recovery/server.ts +23 -32
- package/examples/playground/drizzle.config.ts +14 -0
- package/examples/playground/lib/store.ts +1 -1
- package/examples/playground/next.config.ts +6 -1
- package/examples/playground/package.json +12 -1
- package/examples/playground/scripts/migrate.mjs +31 -0
- package/examples/playground/vercel.json +9 -0
- package/examples/playground/vitest.drills.config.ts +32 -0
- package/package.json +5 -2
- package/sql/postgres/drizzle-schema.ts +209 -0
- package/sql/postgres/schema.sql +227 -67
- package/src/actor-shared.ts +10 -2
- package/src/actor.ts +101 -71
- package/src/ai-agent.ts +162 -111
- package/src/ai-control-server.ts +8 -8
- package/src/ai-fx.ts +324 -82
- package/src/ai-harness.ts +17 -2
- package/src/ai-pi.ts +2 -2
- package/src/ai-server.ts +2 -2
- package/src/ai.ts +7 -7
- package/src/client.ts +19 -2
- package/src/contract.ts +1 -1
- package/src/deterministic-id.ts +27 -4
- package/src/errors.ts +8 -5
- package/src/idempotent-replay.ts +0 -1
- package/src/index.ts +1 -1
- package/src/internal.ts +57 -16
- package/src/otel.ts +1 -1
- package/src/postgres-schema.ts +98 -57
- package/src/presence-recovery.ts +18 -11
- package/src/presence-tombstones.ts +52 -0
- package/src/push-envelope.ts +20 -0
- package/src/runtime-consumer.ts +10 -0
- package/src/scheduler-task.ts +2 -2
- package/src/scheduler-vercel.ts +1 -1
- package/src/server.browser.ts +1 -1
- package/src/server.ts +819 -218
- package/src/session-socket.ts +1 -1
- package/src/store-codec.ts +66 -0
- package/src/store-memory.ts +604 -286
- package/src/store-postgres.ts +2006 -857
- package/src/store-presence-polling.ts +59 -34
- package/src/store-redis-core.ts +1961 -1333
- package/src/store-redis-notify.ts +76 -26
- package/src/store-redis.ts +2 -3
- package/src/store-sqlite.ts +915 -516
- package/src/store.ts +241 -102
- package/src/telemetry.ts +2 -1
- package/src/wire.ts +1 -0
- package/dist/actor-C7b-1arn.d.ts.map +0 -1
- package/dist/actor-shared-t7w8xIKP.js.map +0 -1
- package/dist/ai-harness-Clbg5ei7.js.map +0 -1
- package/dist/ai-mMiWul1T.js.map +0 -1
- package/dist/client-BhHLoNKF.js.map +0 -1
- package/dist/contract-BYKASlCV.js.map +0 -1
- package/dist/idempotent-replay-JdgMQRRm.js +0 -21
- package/dist/idempotent-replay-JdgMQRRm.js.map +0 -1
- package/dist/initial-snapshot-Bx-c0pDP.d.ts.map +0 -1
- package/dist/internal-CscSY7K_.js.map +0 -1
- package/dist/server-DYAATFuT.d.ts.map +0 -1
- package/dist/server-qyb5aJJG.js.map +0 -1
- package/dist/session-clear-C-QwTXV1.d.ts.map +0 -1
- package/dist/session-clear-DGI4jTQ5.js.map +0 -1
- package/dist/store-CyLUy86v.d.ts +0 -404
- package/dist/store-CyLUy86v.d.ts.map +0 -1
- package/dist/store-codec-DTG0Ftek.js +0 -10
- package/dist/store-codec-DTG0Ftek.js.map +0 -1
- package/dist/store-presence-polling-B1ixeqIS.js +0 -94
- package/dist/store-presence-polling-B1ixeqIS.js.map +0 -1
- package/dist/store-redis-notify-CM0AfLY0.js +0 -2544
- package/dist/store-redis-notify-CM0AfLY0.js.map +0 -1
- package/dist/stream-buffer-Cx7AAPGq.js +0 -23
- package/dist/stream-buffer-Cx7AAPGq.js.map +0 -1
- package/dist/telemetry-Cyfqo6Qt.d.ts.map +0 -1
- package/dist/wire-BKxH1vbP.js.map +0 -1
- package/docs/server/01-handlers.mdx +0 -227
package/dist/ai-client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { s as CreateClientOptions, t as A2Client } from "./client-
|
|
2
|
-
import { a as AI_STATE_REDUCER, i as AIState, r as AIMessageOf, t as AIEventDefs } from "./ai-
|
|
1
|
+
import { s as CreateClientOptions, t as A2Client } from "./client-CUMbS_38.js";
|
|
2
|
+
import { a as AI_STATE_REDUCER, i as AIState, r as AIMessageOf, t as AIEventDefs } from "./ai-DAu77CDr.js";
|
|
3
3
|
//#region src/ai-client.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* The structural shape of `typeof` an `agent({ name })` server: one whose
|
package/dist/ai-client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as createClient } from "./client-
|
|
2
|
-
import { n as agentContract } from "./ai-
|
|
1
|
+
import { t as createClient } from "./client-BQS4i_V9.js";
|
|
2
|
+
import { n as agentContract } from "./ai-EEfKyc-z.js";
|
|
3
3
|
//#region src/ai-client.ts
|
|
4
4
|
/**
|
|
5
5
|
* experimental-a2/ai/client — a client for an `agent()` route that needs no
|
package/dist/ai-fx.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { t as Harness } from "./ai-harness-
|
|
1
|
+
import { t as Harness } from "./ai-harness-DTjkAr2T.js";
|
|
2
2
|
//#region src/ai-fx.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* The FX harness. Every model call FX makes is one durable step; A2 rebuilds
|
|
5
|
-
* the kernel for each step from its latest checkpoint and the log since
|
|
5
|
+
* the kernel for each step from its latest checkpoint and the log since,
|
|
6
|
+
* unless this process holds the kernel the step before left waiting on its
|
|
7
|
+
* tool calls.
|
|
6
8
|
*/
|
|
7
9
|
declare function fx(): Harness<"fx", never>;
|
|
8
10
|
//#endregion
|
package/dist/ai-fx.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-fx.d.ts","names":[],"sources":["../src/ai-fx.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ai-fx.d.ts","names":[],"sources":["../src/ai-fx.ts"],"mappings":";;;;;;;;iBA+CgB,MAAM"}
|
package/dist/ai-fx.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { n as HARNESS_PARKING } from "./internal-CvsrprnU.js";
|
|
1
2
|
import { t as boundedCache } from "./bounded-cache-CPHWF-8h.js";
|
|
2
|
-
import { a as gatewaySessionAffinity, d as readHarness, i as gatewayCredential, n as deferred, p as saveHarness, r as defineHarness, s as harnessImages, t as Divergence, u as pending } from "./ai-harness-
|
|
3
|
+
import { a as gatewaySessionAffinity, d as readHarness, i as gatewayCredential, n as deferred, p as saveHarness, r as defineHarness, s as harnessImages, t as Divergence, u as pending } from "./ai-harness-dQeJaR1t.js";
|
|
3
4
|
import { t as schemaInput } from "./ai-tool-input-DmSqMUQi.js";
|
|
4
5
|
import { asSchema } from "ai";
|
|
5
6
|
//#region src/ai-fx.ts
|
|
@@ -9,12 +10,27 @@ import { asSchema } from "ai";
|
|
|
9
10
|
*/
|
|
10
11
|
/**
|
|
11
12
|
* The FX harness. Every model call FX makes is one durable step; A2 rebuilds
|
|
12
|
-
* the kernel for each step from its latest checkpoint and the log since
|
|
13
|
+
* the kernel for each step from its latest checkpoint and the log since,
|
|
14
|
+
* unless this process holds the kernel the step before left waiting on its
|
|
15
|
+
* tool calls.
|
|
13
16
|
*/
|
|
14
17
|
function fx() {
|
|
18
|
+
const lots = /* @__PURE__ */ new WeakMap();
|
|
19
|
+
const lotOf = (scope) => {
|
|
20
|
+
let lot = lots.get(scope);
|
|
21
|
+
if (lot === void 0) {
|
|
22
|
+
lot = parkingLot();
|
|
23
|
+
lots.set(scope, lot);
|
|
24
|
+
}
|
|
25
|
+
return lot;
|
|
26
|
+
};
|
|
15
27
|
return defineHarness("fx", {
|
|
16
28
|
tools: {},
|
|
17
|
-
step: runStep
|
|
29
|
+
step: (step) => runStep(step, lotOf(step.scope)),
|
|
30
|
+
release: ({ scope, sessionId }) => {
|
|
31
|
+
const entry = lots.get(scope)?.take(sessionId);
|
|
32
|
+
if (entry !== void 0) closeParked(entry);
|
|
33
|
+
}
|
|
18
34
|
});
|
|
19
35
|
}
|
|
20
36
|
const SNAPSHOT_VERSION = 1;
|
|
@@ -27,10 +43,52 @@ function fail(state, error) {
|
|
|
27
43
|
throw state.failure;
|
|
28
44
|
}
|
|
29
45
|
const diverged = (message) => new Divergence("FX", message);
|
|
30
|
-
|
|
46
|
+
function closeParked(entry) {
|
|
47
|
+
entry.fxTurn.cancel();
|
|
48
|
+
entry.kernel.agent.close().catch(() => {});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* One agent's parked kernels: one per session, at most `maxKernels`. Each is
|
|
52
|
+
* closed when its session has nothing left to run in this process (the
|
|
53
|
+
* agent's release), when its turn ends, or when another takes its place.
|
|
54
|
+
*/
|
|
55
|
+
function parkingLot() {
|
|
56
|
+
const held = /* @__PURE__ */ new Map();
|
|
57
|
+
const take = (sessionId) => {
|
|
58
|
+
const entry = held.get(sessionId);
|
|
59
|
+
held.delete(sessionId);
|
|
60
|
+
return entry;
|
|
61
|
+
};
|
|
62
|
+
return {
|
|
63
|
+
take,
|
|
64
|
+
park(sessionId, entry) {
|
|
65
|
+
const replaced = take(sessionId);
|
|
66
|
+
if (replaced !== void 0) closeParked(replaced);
|
|
67
|
+
held.set(sessionId, entry);
|
|
68
|
+
const ended = () => {
|
|
69
|
+
if (held.get(sessionId) !== entry) return;
|
|
70
|
+
held.delete(sessionId);
|
|
71
|
+
closeParked(entry);
|
|
72
|
+
};
|
|
73
|
+
entry.fxTurn.result.then(ended, ended);
|
|
74
|
+
const oldest = held.keys().next().value;
|
|
75
|
+
if (held.size > HARNESS_PARKING.maxKernels && oldest !== void 0) {
|
|
76
|
+
const evicted = take(oldest);
|
|
77
|
+
if (evicted !== void 0) closeParked(evicted);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function runStep(step, lot) {
|
|
31
83
|
const { createFxAgent } = await loadLibfx();
|
|
32
84
|
const credential = gatewayCredential("fx");
|
|
33
85
|
const name = `${step.agentName}.a2.harness.fx`;
|
|
86
|
+
const definitions = await toolDefinitions(step.tools);
|
|
87
|
+
const settings = JSON.stringify([
|
|
88
|
+
kernelModel(step),
|
|
89
|
+
step.instructions,
|
|
90
|
+
definitions
|
|
91
|
+
]);
|
|
34
92
|
const { replayAll, ...first } = await readHarness({
|
|
35
93
|
step,
|
|
36
94
|
name,
|
|
@@ -41,16 +99,22 @@ async function runStep(step) {
|
|
|
41
99
|
let stopped = false;
|
|
42
100
|
const released = new AbortController();
|
|
43
101
|
const network = AbortSignal.any([step.signal, released.signal]);
|
|
44
|
-
let
|
|
102
|
+
let kernel;
|
|
103
|
+
/** Whether this step left its kernel for the next one. */
|
|
104
|
+
let parked = false;
|
|
45
105
|
let turn;
|
|
46
|
-
const run = async (controller, turns) => {
|
|
106
|
+
const run = async (controller, turns, adopted) => {
|
|
47
107
|
controller.enqueue({
|
|
48
108
|
type: "start",
|
|
49
109
|
messageId: step.responseMessageId
|
|
50
110
|
});
|
|
111
|
+
if (adopted !== void 0) {
|
|
112
|
+
await resume(controller, turns.at(-1), adopted);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
51
115
|
for (const plan of turns) {
|
|
52
|
-
if (stopped) return;
|
|
53
|
-
const fxTurn = agent.prompt(plan.prompt
|
|
116
|
+
if (stopped || step.signal.aborted) return;
|
|
117
|
+
const fxTurn = kernel.agent.prompt(plan.prompt);
|
|
54
118
|
const state = {
|
|
55
119
|
plan,
|
|
56
120
|
fxTurn,
|
|
@@ -76,29 +140,82 @@ async function runStep(step) {
|
|
|
76
140
|
if (result.stopReason !== expected) throw diverged(`a recorded turn ended with ${result.stopReason}, not ${expected}`);
|
|
77
141
|
continue;
|
|
78
142
|
}
|
|
79
|
-
|
|
80
|
-
ended: true,
|
|
81
|
-
result
|
|
82
|
-
})), state.toolsRequested.promise.then(() => ({ ended: false }))]).catch((error) => {
|
|
83
|
-
throw state.failure ?? error;
|
|
84
|
-
});
|
|
85
|
-
if (state.failure) throw state.failure;
|
|
86
|
-
await state.parsed;
|
|
87
|
-
if (outcome.ended) {
|
|
88
|
-
await drained;
|
|
89
|
-
if (outcome.result.stopReason === "end_turn" && !step.signal.aborted) await saveCheckpoint();
|
|
90
|
-
} else fxTurn.cancel();
|
|
91
|
-
controller.enqueue({ type: "finish-step" });
|
|
92
|
-
controller.enqueue({
|
|
93
|
-
type: "finish",
|
|
94
|
-
...completion.finishReason === void 0 ? {} : { finishReason: completion.finishReason }
|
|
95
|
-
});
|
|
143
|
+
await finishLive(controller, state, drained);
|
|
96
144
|
}
|
|
97
145
|
};
|
|
146
|
+
/** Continues a parked kernel: the results it waits on are in the log. */
|
|
147
|
+
const resume = async (controller, plan, adopted) => {
|
|
148
|
+
const state = {
|
|
149
|
+
plan,
|
|
150
|
+
fxTurn: adopted.fxTurn,
|
|
151
|
+
next: plan.calls.length,
|
|
152
|
+
served: plan.calls.at(-1).toolCalls,
|
|
153
|
+
answered: /* @__PURE__ */ new Set(),
|
|
154
|
+
live: false,
|
|
155
|
+
liveStep: false,
|
|
156
|
+
toolsRequested: deferred()
|
|
157
|
+
};
|
|
158
|
+
turn = state;
|
|
159
|
+
for (const text of plan.steers.get(plan.calls.length - 1) ?? []) await adopted.fxTurn.steer(text);
|
|
160
|
+
for (const waiting of kernel.waiting.splice(0)) try {
|
|
161
|
+
const answered = answer(state, waiting.toolName, waiting.input);
|
|
162
|
+
if (answered === void 0) fail(state, diverged(`no recorded result for ${waiting.toolName}`));
|
|
163
|
+
waiting.resolve(answered.output);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
waiting.reject(error);
|
|
166
|
+
}
|
|
167
|
+
await finishLive(controller, state, adopted.drained);
|
|
168
|
+
};
|
|
169
|
+
const finishLive = async (controller, state, drained) => {
|
|
170
|
+
const outcome = await Promise.race([state.fxTurn.result.then((result) => ({
|
|
171
|
+
ended: true,
|
|
172
|
+
result
|
|
173
|
+
})), state.toolsRequested.promise.then(() => ({ ended: false }))]).catch((error) => {
|
|
174
|
+
throw state.failure ?? error;
|
|
175
|
+
});
|
|
176
|
+
if (state.failure) throw state.failure;
|
|
177
|
+
await state.parsed;
|
|
178
|
+
if (outcome.ended) {
|
|
179
|
+
if (outcome.result.stopReason === "cancelled" && !stopped && !step.signal.aborted) throw diverged("the turn was cancelled while this step ran it");
|
|
180
|
+
await drained;
|
|
181
|
+
if (outcome.result.stopReason === "end_turn" && !step.signal.aborted) await saveCheckpoint();
|
|
182
|
+
} else if (kernel.waiting.length > 0 && !stopped && !closed) {
|
|
183
|
+
lot.park(step.sessionId, {
|
|
184
|
+
kernel,
|
|
185
|
+
fxTurn: state.fxTurn,
|
|
186
|
+
drained,
|
|
187
|
+
generationId: step.generationId,
|
|
188
|
+
settings
|
|
189
|
+
});
|
|
190
|
+
parked = true;
|
|
191
|
+
} else state.fxTurn.cancel();
|
|
192
|
+
controller.enqueue({ type: "finish-step" });
|
|
193
|
+
controller.enqueue({
|
|
194
|
+
type: "finish",
|
|
195
|
+
...completion.finishReason === void 0 ? {} : { finishReason: completion.finishReason }
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Whether a parked kernel stands where this step's log does: made the same
|
|
200
|
+
* way, its model call the last one the log's live turn committed, and a
|
|
201
|
+
* recorded result for each tool call it waits on. A steered response
|
|
202
|
+
* continues the same turn, so its steps qualify too.
|
|
203
|
+
*/
|
|
204
|
+
const adoptable = (entry, turns) => {
|
|
205
|
+
const plan = turns.at(-1);
|
|
206
|
+
if (entry.settings !== settings || plan?.end !== "live" || plan.generationId !== entry.generationId) return false;
|
|
207
|
+
const unanswered = [...plan.calls.at(-1)?.toolCalls ?? []];
|
|
208
|
+
return entry.kernel.waiting.every((waiting) => {
|
|
209
|
+
const at = unanswered.findIndex((call) => call.toolName === waiting.toolName && sameJson(call.input, waiting.input) && results.has(call.toolCallId));
|
|
210
|
+
if (at === -1) return false;
|
|
211
|
+
unanswered.splice(at, 1);
|
|
212
|
+
return true;
|
|
213
|
+
});
|
|
214
|
+
};
|
|
98
215
|
const saveCheckpoint = async () => {
|
|
99
216
|
let checkpoint;
|
|
100
217
|
try {
|
|
101
|
-
checkpoint = await agent.checkpoint();
|
|
218
|
+
checkpoint = await kernel.agent.checkpoint();
|
|
102
219
|
} catch {
|
|
103
220
|
return;
|
|
104
221
|
}
|
|
@@ -119,7 +236,8 @@ async function runStep(step) {
|
|
|
119
236
|
const state = turn;
|
|
120
237
|
if (state.failure) throw state.failure;
|
|
121
238
|
const body = decodeBody(init.body);
|
|
122
|
-
const
|
|
239
|
+
const request = JSON.parse(body);
|
|
240
|
+
const compaction = request.toolChoice?.type === "none";
|
|
123
241
|
const recorded = state.plan.calls[state.next];
|
|
124
242
|
if (recorded !== void 0) {
|
|
125
243
|
if (recorded.kind === "compaction" !== compaction) fail(state, diverged(`request ${state.next} is not a ${recorded.kind}`));
|
|
@@ -145,7 +263,7 @@ async function runStep(step) {
|
|
|
145
263
|
state.live = true;
|
|
146
264
|
return live(state, url, {
|
|
147
265
|
...init,
|
|
148
|
-
body
|
|
266
|
+
body: withGatewayCaching(body, request)
|
|
149
267
|
}, compaction);
|
|
150
268
|
};
|
|
151
269
|
const affinity = gatewaySessionAffinity({
|
|
@@ -158,7 +276,6 @@ async function runStep(step) {
|
|
|
158
276
|
headers.set("x-session-affinity", affinity);
|
|
159
277
|
const response = await fetch(url, {
|
|
160
278
|
...init,
|
|
161
|
-
body: withGatewayCaching(init.body),
|
|
162
279
|
headers,
|
|
163
280
|
signal: network
|
|
164
281
|
});
|
|
@@ -202,42 +319,67 @@ async function runStep(step) {
|
|
|
202
319
|
headers: response.headers
|
|
203
320
|
});
|
|
204
321
|
};
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (state.failure) throw state.failure;
|
|
322
|
+
/** The recorded result of a call from the step the kernel was served. */
|
|
323
|
+
const answer = (state, toolName, toolInput) => {
|
|
208
324
|
const call = state.served.find((candidate) => candidate.toolName === toolName && !state.answered.has(candidate.toolCallId) && sameJson(candidate.input, toolInput));
|
|
209
325
|
const result = call === void 0 ? void 0 : results.get(call.toolCallId);
|
|
210
|
-
if (call
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
326
|
+
if (call === void 0 || result === void 0) return void 0;
|
|
327
|
+
state.answered.add(call.toolCallId);
|
|
328
|
+
if (result.error !== void 0) throw new Error(result.error);
|
|
329
|
+
if (result.denied === true) throw new Error("The tool call was denied.");
|
|
330
|
+
return { output: result.output ?? null };
|
|
331
|
+
};
|
|
332
|
+
const hostTool = (toolName, toolInput) => {
|
|
333
|
+
const state = turn;
|
|
334
|
+
if (state.failure) throw state.failure;
|
|
335
|
+
const answered = answer(state, toolName, toolInput);
|
|
336
|
+
if (answered !== void 0) return answered.output;
|
|
216
337
|
if (state.live) {
|
|
217
338
|
state.toolsRequested.resolve();
|
|
218
|
-
return
|
|
339
|
+
return new Promise((resolve, reject) => {
|
|
340
|
+
kernel.waiting.push({
|
|
341
|
+
toolName,
|
|
342
|
+
input: toolInput,
|
|
343
|
+
resolve,
|
|
344
|
+
reject
|
|
345
|
+
});
|
|
346
|
+
});
|
|
219
347
|
}
|
|
220
348
|
if (state.plan.end === "interrupted") {
|
|
221
349
|
state.fxTurn.cancel();
|
|
222
350
|
return pending(void 0);
|
|
223
351
|
}
|
|
224
352
|
return fail(state, diverged(`no recorded result for ${toolName}`));
|
|
225
|
-
}
|
|
226
|
-
const
|
|
353
|
+
};
|
|
354
|
+
const hooks = {
|
|
355
|
+
fetch: hostFetch,
|
|
356
|
+
tool: hostTool
|
|
357
|
+
};
|
|
358
|
+
const planTurns = (turns) => Promise.all(turns.map((recorded) => turnPlan(recorded, step.signal)));
|
|
227
359
|
let results = read.results;
|
|
228
360
|
let controller;
|
|
229
361
|
let closed = false;
|
|
230
362
|
const emit = (chunk) => {
|
|
231
363
|
if (!closed) controller.enqueue(chunk);
|
|
232
364
|
};
|
|
233
|
-
const create = (checkpoint) =>
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
365
|
+
const create = async (checkpoint) => {
|
|
366
|
+
const created = {
|
|
367
|
+
hooks,
|
|
368
|
+
waiting: []
|
|
369
|
+
};
|
|
370
|
+
const agent = await createFxAgent({
|
|
371
|
+
apiKey: credential.token,
|
|
372
|
+
model: kernelModel(step),
|
|
373
|
+
...step.instructions.length === 0 ? {} : { instructions: step.instructions },
|
|
374
|
+
tools: definitions.map((definition) => ({
|
|
375
|
+
...definition,
|
|
376
|
+
execute: (toolInput) => created.hooks.tool(definition.name, toolInput)
|
|
377
|
+
})),
|
|
378
|
+
...checkpoint === void 0 ? {} : { checkpoint },
|
|
379
|
+
fetch: (input, init) => created.hooks.fetch(input, init)
|
|
380
|
+
});
|
|
381
|
+
return Object.assign(created, { agent });
|
|
382
|
+
};
|
|
241
383
|
return {
|
|
242
384
|
stream: new ReadableStream({
|
|
243
385
|
start(streamController) {
|
|
@@ -249,15 +391,23 @@ async function runStep(step) {
|
|
|
249
391
|
step.signal.addEventListener("abort", abort, { once: true });
|
|
250
392
|
(async () => {
|
|
251
393
|
try {
|
|
252
|
-
|
|
253
|
-
|
|
394
|
+
let turns = await planTurns(read.turns);
|
|
395
|
+
const candidate = step.signal.aborted ? void 0 : lot.take(step.sessionId);
|
|
396
|
+
const adopted = candidate !== void 0 && adoptable(candidate, turns) ? candidate : void 0;
|
|
397
|
+
if (candidate !== void 0 && adopted === void 0) closeParked(candidate);
|
|
398
|
+
if (adopted !== void 0) {
|
|
399
|
+
kernel = adopted.kernel;
|
|
400
|
+
kernel.hooks = hooks;
|
|
401
|
+
} else try {
|
|
402
|
+
kernel = await create(read.saved);
|
|
254
403
|
} catch (error) {
|
|
255
404
|
if (read.saved === void 0) throw error;
|
|
256
405
|
read = await replayAll();
|
|
257
406
|
results = read.results;
|
|
258
|
-
|
|
407
|
+
kernel = await create(void 0);
|
|
408
|
+
turns = await planTurns(read.turns);
|
|
259
409
|
}
|
|
260
|
-
await run(streamController,
|
|
410
|
+
await run(streamController, turns, adopted);
|
|
261
411
|
closed = true;
|
|
262
412
|
streamController.close();
|
|
263
413
|
} catch (error) {
|
|
@@ -266,7 +416,7 @@ async function runStep(step) {
|
|
|
266
416
|
} finally {
|
|
267
417
|
released.abort();
|
|
268
418
|
step.signal.removeEventListener("abort", abort);
|
|
269
|
-
await agent
|
|
419
|
+
if (!parked) await kernel?.agent.close().catch(() => {});
|
|
270
420
|
}
|
|
271
421
|
})();
|
|
272
422
|
},
|
|
@@ -283,20 +433,19 @@ async function runStep(step) {
|
|
|
283
433
|
async function turnPlan(turn, signal) {
|
|
284
434
|
const calls = [];
|
|
285
435
|
const steers = /* @__PURE__ */ new Map();
|
|
286
|
-
const steer = (at, inputs) => {
|
|
287
|
-
if (inputs !== void 0) steers.set(Math.max(0, at), inputs.map(steerText));
|
|
288
|
-
};
|
|
289
|
-
steer(0, turn.generations.length === 0 ? turn.steers.get(0) : void 0);
|
|
290
436
|
turn.generations.forEach((generation, index) => {
|
|
291
437
|
calls.push(...recordedCalls(generation.chunks, generation.completed));
|
|
292
|
-
|
|
438
|
+
const inputs = turn.steers.get(index);
|
|
439
|
+
if (inputs !== void 0) steers.set(calls.length - 1, inputs.map(steerText));
|
|
293
440
|
});
|
|
294
441
|
const images = await harnessImages({
|
|
295
442
|
harness: "fx()",
|
|
296
443
|
input: turn.prompt,
|
|
297
444
|
signal
|
|
298
445
|
});
|
|
446
|
+
const generationId = turn.generations.at(-1)?.completed.generationId;
|
|
299
447
|
return {
|
|
448
|
+
...generationId === void 0 ? {} : { generationId },
|
|
300
449
|
prompt: images.length === 0 ? turn.prompt.text : [...images.map((image) => ({
|
|
301
450
|
type: "image",
|
|
302
451
|
data: image.data,
|
|
@@ -605,8 +754,8 @@ async function loadLibfx() {
|
|
|
605
754
|
* asks for it; options the request already has take precedence. Every other
|
|
606
755
|
* byte stays as the kernel wrote it, a tool input's spacing included.
|
|
607
756
|
*/
|
|
608
|
-
function withGatewayCaching(body) {
|
|
609
|
-
const options =
|
|
757
|
+
function withGatewayCaching(body, request) {
|
|
758
|
+
const options = request.providerOptions;
|
|
610
759
|
if (options === void 0) return body.replace(/^\{/, "{\"providerOptions\":{\"gateway\":{\"caching\":\"auto\"}},");
|
|
611
760
|
const own = `"providerOptions":${JSON.stringify(options)}}`;
|
|
612
761
|
if (!body.endsWith(own)) return body;
|
|
@@ -622,6 +771,7 @@ function withGatewayCaching(body) {
|
|
|
622
771
|
function withAuth(headers, credential) {
|
|
623
772
|
const result = new Headers(headers);
|
|
624
773
|
result.set("ai-gateway-auth-method", credential.method);
|
|
774
|
+
if (result.has("authorization")) result.set("authorization", `Bearer ${credential.token}`);
|
|
625
775
|
return result;
|
|
626
776
|
}
|
|
627
777
|
function kernelModel(step) {
|
|
@@ -634,12 +784,12 @@ function kernelModel(step) {
|
|
|
634
784
|
...fast ? { fast } : {}
|
|
635
785
|
};
|
|
636
786
|
}
|
|
637
|
-
|
|
787
|
+
/** The agent's tools as the kernel takes them, without their execution. */
|
|
788
|
+
async function toolDefinitions(tools) {
|
|
638
789
|
return Promise.all(Object.entries(tools).map(async ([toolName, tool]) => ({
|
|
639
790
|
name: toolName,
|
|
640
791
|
description: typeof tool.description === "string" ? tool.description : toolName,
|
|
641
|
-
inputSchema: await asSchema(tool.inputSchema).jsonSchema
|
|
642
|
-
execute: (input) => execute(toolName, input)
|
|
792
|
+
inputSchema: await asSchema(tool.inputSchema).jsonSchema
|
|
643
793
|
})));
|
|
644
794
|
}
|
|
645
795
|
const catalogCache = boundedCache({
|
|
@@ -674,9 +824,6 @@ function savedCheckpoint(state) {
|
|
|
674
824
|
if (version !== SNAPSHOT_VERSION || typeof checkpoint !== "string") return void 0;
|
|
675
825
|
return new Uint8Array(Buffer.from(checkpoint, "base64"));
|
|
676
826
|
}
|
|
677
|
-
function isCompaction(body) {
|
|
678
|
-
return JSON.parse(body).toolChoice?.type === "none";
|
|
679
|
-
}
|
|
680
827
|
function decodeBody(body) {
|
|
681
828
|
if (typeof body === "string") return body;
|
|
682
829
|
if (body instanceof Uint8Array || body instanceof ArrayBuffer) return new TextDecoder().decode(body);
|