experimental-a2 0.16.0 → 0.16.1

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/ai-server.js CHANGED
@@ -2,7 +2,7 @@ import { n as validateSync } from "./validate-XKT4FSNn.js";
2
2
  import { t as A2Error } from "./errors-DCk6ch5n.js";
3
3
  import { f as consumeSchedulerSendFailure, p as installAmbientToolScopeStorage } from "./internal-Dq2qYxou.js";
4
4
  import { i as setServerFetchHooks, t as createServer } from "./server-BD5ckxZb.js";
5
- import { C as applyControlChanges, S as initialControlState, _ as progressBatches, a as events, b as AI_EVENT_ID_PREFIX, d as advanceProjection, f as projectedMessage, g as flattenProgressBatches, h as upsertResponse, l as aiStateReducer, m as upsertMessage, p as reduceToolActivity, u as storedAIReducer, v as interruptUIMessage, w as controlCommit, x as aiEventId, y as pauseUIMessage } from "./ai-CrLYwNEx.js";
5
+ import { C as interruptUIMessage, S as progressBatches, _ as projectedMessage, a as events, b as upsertResponse, d as AI_EVENT_ID_PREFIX, f as aiEventId, g as advanceProjection, h as controlCommit, l as aiStateReducer, m as applyControlChanges, p as initialControlState, u as storedAIReducer, v as reduceToolActivity, w as pauseUIMessage, x as flattenProgressBatches, y as upsertMessage } from "./ai-DgOBltJ_.js";
6
6
  import { AsyncLocalStorage } from "node:async_hooks";
7
7
  import { createHash } from "node:crypto";
8
8
  import { asSchema, convertToModelMessages, isToolUIPart, stepCountIs, streamText, toUIMessageStream } from "ai";
@@ -239,12 +239,35 @@ const callReadyForModel = (call) => call.terminal || call.call.providerExecuted
239
239
  const approvalBlocksExecution = (call) => call.approval !== void 0 && call.response?.approved !== true;
240
240
  const createControlRuntime = (options) => {
241
241
  const reducer = options.agent.contract.reducer({
242
- name: "a2.ai.control.v4",
242
+ name: "a2.ai.control.v5",
243
243
  initialState: initialControlState()
244
- }).fold((state, event) => event.type === "ai.control.committed" ? applyControlChanges({
245
- state,
246
- changes: event.payload.changes
247
- }) : state);
244
+ }).fold((state, event) => {
245
+ if (event.type === "ai.control.requested") {
246
+ const command = event.payload;
247
+ if (command.action === "stop") return {
248
+ ...state,
249
+ pendingStops: {
250
+ ...state.pendingStops,
251
+ [event.id]: command.turnId
252
+ }
253
+ };
254
+ }
255
+ if (event.type === "ai.control.decided") {
256
+ const receipt = event.payload;
257
+ if (Object.hasOwn(state.pendingStops, receipt.commandId)) {
258
+ const pendingStops = { ...state.pendingStops };
259
+ delete pendingStops[receipt.commandId];
260
+ return {
261
+ ...state,
262
+ pendingStops
263
+ };
264
+ }
265
+ }
266
+ return event.type === "ai.control.committed" ? applyControlChanges({
267
+ state,
268
+ changes: event.payload.changes
269
+ }) : state;
270
+ });
248
271
  const coordinator = aiCoordinatorReducer(options.agent.contract);
249
272
  const handler = async (ctx) => {
250
273
  const snapshot = await ctx.session.state(reducer, { through: "latest" });
@@ -2042,7 +2065,7 @@ function createHandlers(options) {
2042
2065
  const state = (await ctx.session.state(control.reducer, { through: "latest" })).state;
2043
2066
  const request = ctx.event.payload;
2044
2067
  const call = state.coordinator.response?.calls.find((candidate) => candidate.work?.id === ctx.event.id);
2045
- if (state.active?.turnId !== request.turnId || state.active.suspended || state.active.version !== request.version || state.coordinator.response?.failure !== void 0 || !call || call.terminal || call.work?.settled) return control.settled({
2068
+ if (state.active?.turnId !== request.turnId || Object.values(state.pendingStops).includes(request.turnId) || state.active.suspended || state.active.version !== request.version || state.coordinator.response?.failure !== void 0 || !call || call.terminal || call.work?.settled) return control.settled({
2046
2069
  ctx,
2047
2070
  events: void 0
2048
2071
  });
@@ -2071,7 +2094,9 @@ function createHandlers(options) {
2071
2094
  const request = ctx.event.payload;
2072
2095
  const snapshot = await readContext(ctx.session, "latest");
2073
2096
  if (snapshot.state.closed || snapshot.state.authority?.requestId !== requestId || snapshot.state.authority?.phase === "paused" || snapshot.state.authority?.phase === "pausing") return;
2074
- const coordinatorState = (await ctx.session.state(coordinator, { through: snapshot.index })).state;
2097
+ const controlState = (await ctx.session.state(control.reducer, { through: snapshot.index })).state;
2098
+ if (request.control !== void 0 && Object.values(controlState.pendingStops).includes(request.control.turnId)) return;
2099
+ const coordinatorState = controlState.coordinator;
2075
2100
  if (coordinatorState.closed || coordinatorState.response?.activeRequestId !== requestId) return;
2076
2101
  const response = coordinatorState.response;
2077
2102
  const current = response.generation?.requestId === requestId ? response.generation : void 0;
@@ -2475,6 +2500,7 @@ function createHandlers(options) {
2475
2500
  "ai.generation.requested": {
2476
2501
  lane: "a2.ai.model",
2477
2502
  abortOn: {
2503
+ "ai.control.requested": (event, trigger) => event.payload.action === "stop" && event.payload.turnId === trigger.payload.control?.turnId,
2478
2504
  "ai.control.committed": (event, trigger) => {
2479
2505
  const active = event.payload.view;
2480
2506
  return active?.turnId !== trigger.payload.control?.turnId || active?.version !== trigger.payload.control?.version;
@@ -2501,6 +2527,7 @@ function createHandlers(options) {
2501
2527
  },
2502
2528
  "ai.tool.execution.requested": {
2503
2529
  abortOn: {
2530
+ "ai.control.requested": (event, trigger) => event.payload.action === "stop" && event.payload.turnId === trigger.payload.turnId,
2504
2531
  "ai.generation.failed": (event, trigger) => event.payload.generationId === trigger.payload.call.generationId,
2505
2532
  "ai.control.committed": (event, trigger) => {
2506
2533
  const active = event.payload.view;