@holon-run/agentinbox 0.7.0 → 1.0.0-beta.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.
Files changed (33) hide show
  1. package/README.md +36 -7
  2. package/dist/src/adapters.js +55 -0
  3. package/dist/src/backend.js +4 -16
  4. package/dist/src/cli.js +329 -52
  5. package/dist/src/client.js +2 -2
  6. package/dist/src/http.js +479 -55
  7. package/dist/src/runtime_gate.js +49 -41
  8. package/dist/src/service.js +922 -200
  9. package/dist/src/source_hosts.js +75 -0
  10. package/dist/src/source_resolution.js +2 -2
  11. package/dist/src/source_schema.js +2 -2
  12. package/dist/src/sources/feishu.js +66 -28
  13. package/dist/src/sources/github.js +222 -36
  14. package/dist/src/sources/remote.js +50 -3
  15. package/dist/src/sources/remote_modules.js +100 -15
  16. package/dist/src/store.js +875 -110
  17. package/dist/src/terminal.js +33 -7
  18. package/dist/src/util.js +46 -1
  19. package/drizzle/migrations/{0000_initial.sql → 0000_v1_initial.sql} +182 -6
  20. package/drizzle/migrations/0002_host_scoped_lifecycle_retirements.sql +42 -0
  21. package/drizzle/migrations/0003_subscription_tracked_resource_indexes.sql +5 -0
  22. package/drizzle/schema.ts +98 -3
  23. package/package.json +2 -1
  24. package/scripts/release_smoke.sh +123 -0
  25. package/dist/src/sources/remote_profiles.js +0 -13
  26. package/drizzle/migrations/0001_inbox_items_source_occurred_at_idx.sql +0 -3
  27. package/drizzle/migrations/0002_subscription_cleanup_policy.sql +0 -45
  28. package/drizzle/migrations/0003_subscription_lifecycle_retirements.sql +0 -14
  29. package/drizzle/migrations/0004_source_idle_states.sql +0 -10
  30. package/drizzle/migrations/0005_timers.sql +0 -22
  31. package/drizzle/migrations/0006_terminal_runtime_pid.sql +0 -1
  32. package/drizzle/migrations/0007_activation_dispatch_last_notified_fingerprint.sql +0 -2
  33. package/drizzle/migrations/0008_inbox_item_sequence.sql +0 -21
package/dist/src/http.js CHANGED
@@ -29,6 +29,14 @@ const errorResponseSchema = {
29
29
  error: { type: "string" },
30
30
  },
31
31
  };
32
+ const subscriptionCollectionSchema = {
33
+ type: "object",
34
+ required: ["subscriptions"],
35
+ additionalProperties: false,
36
+ properties: {
37
+ subscriptions: { type: "array", items: jsonObjectSchema },
38
+ },
39
+ };
32
40
  const deliveryHandleSchema = {
33
41
  type: "object",
34
42
  additionalProperties: false,
@@ -41,6 +49,28 @@ const deliveryHandleSchema = {
41
49
  replyMode: { type: "string" },
42
50
  },
43
51
  };
52
+ const deliveryTargetByHandleSchema = {
53
+ type: "object",
54
+ additionalProperties: false,
55
+ required: ["deliveryHandle"],
56
+ properties: {
57
+ sourceId: { type: "string", minLength: 1 },
58
+ deliveryHandle: deliveryHandleSchema,
59
+ },
60
+ };
61
+ const deliveryTargetByFieldsSchema = {
62
+ type: "object",
63
+ additionalProperties: false,
64
+ required: ["provider", "surface", "targetRef"],
65
+ properties: {
66
+ sourceId: { type: "string", minLength: 1 },
67
+ provider: { type: "string", minLength: 1 },
68
+ surface: { type: "string", minLength: 1 },
69
+ targetRef: { type: "string", minLength: 1 },
70
+ threadRef: { type: "string" },
71
+ replyMode: { type: "string" },
72
+ },
73
+ };
44
74
  function buildFastifyServer(service) {
45
75
  const app = (0, fastify_1.default)({
46
76
  logger: false,
@@ -96,6 +126,153 @@ function buildFastifyServer(service) {
96
126
  },
97
127
  },
98
128
  }, async () => service.gc());
129
+ app.get("/hosts", {
130
+ schema: {
131
+ tags: ["sources"],
132
+ response: {
133
+ 200: {
134
+ type: "object",
135
+ required: ["hosts"],
136
+ properties: {
137
+ hosts: { type: "array", items: jsonObjectSchema },
138
+ },
139
+ },
140
+ },
141
+ },
142
+ }, async () => ({ hosts: service.listHosts() }));
143
+ app.post("/hosts", {
144
+ schema: {
145
+ tags: ["sources"],
146
+ body: {
147
+ type: "object",
148
+ additionalProperties: false,
149
+ required: ["hostType", "hostKey"],
150
+ properties: {
151
+ hostType: { type: "string", minLength: 1 },
152
+ hostKey: { type: "string", minLength: 1 },
153
+ configRef: { anyOf: [{ type: "string" }, { type: "null" }] },
154
+ config: jsonObjectSchema,
155
+ },
156
+ },
157
+ response: {
158
+ 200: jsonObjectSchema,
159
+ 400: errorResponseSchema,
160
+ },
161
+ },
162
+ }, async (request) => service.registerHost(request.body));
163
+ app.get("/hosts/:hostId", {
164
+ schema: {
165
+ tags: ["sources"],
166
+ params: {
167
+ type: "object",
168
+ required: ["hostId"],
169
+ properties: {
170
+ hostId: { type: "string", minLength: 1 },
171
+ },
172
+ },
173
+ response: {
174
+ 200: jsonObjectSchema,
175
+ 404: errorResponseSchema,
176
+ },
177
+ },
178
+ }, async (request) => {
179
+ const params = request.params;
180
+ return service.getHostDetails(decodeURIComponent(params.hostId));
181
+ });
182
+ app.get("/hosts/:hostId/schema", {
183
+ schema: {
184
+ tags: ["sources"],
185
+ params: {
186
+ type: "object",
187
+ required: ["hostId"],
188
+ properties: {
189
+ hostId: { type: "string", minLength: 1 },
190
+ },
191
+ },
192
+ response: {
193
+ 200: jsonObjectSchema,
194
+ 404: errorResponseSchema,
195
+ },
196
+ },
197
+ }, async (request) => {
198
+ const params = request.params;
199
+ const host = service.getHost(decodeURIComponent(params.hostId));
200
+ return service.getHostSchema(host.hostType);
201
+ });
202
+ app.get("/streams", {
203
+ schema: {
204
+ tags: ["sources"],
205
+ response: {
206
+ 200: {
207
+ type: "object",
208
+ required: ["streams"],
209
+ properties: {
210
+ streams: { type: "array", items: jsonObjectSchema },
211
+ },
212
+ },
213
+ },
214
+ },
215
+ }, async () => ({ streams: service.listStreams() }));
216
+ app.post("/streams", {
217
+ schema: {
218
+ tags: ["sources"],
219
+ body: {
220
+ type: "object",
221
+ additionalProperties: false,
222
+ required: ["hostId", "streamKind", "streamKey"],
223
+ properties: {
224
+ hostId: { type: "string", minLength: 1 },
225
+ streamKind: { type: "string", minLength: 1 },
226
+ streamKey: { type: "string", minLength: 1 },
227
+ configRef: { anyOf: [{ type: "string" }, { type: "null" }] },
228
+ config: jsonObjectSchema,
229
+ },
230
+ },
231
+ response: {
232
+ 200: jsonObjectSchema,
233
+ 400: errorResponseSchema,
234
+ },
235
+ },
236
+ }, async (request) => service.registerStream(request.body));
237
+ app.get("/streams/:streamId", {
238
+ schema: {
239
+ tags: ["sources"],
240
+ params: {
241
+ type: "object",
242
+ required: ["streamId"],
243
+ properties: {
244
+ streamId: { type: "string", minLength: 1 },
245
+ },
246
+ },
247
+ response: {
248
+ 200: jsonObjectSchema,
249
+ 404: errorResponseSchema,
250
+ },
251
+ },
252
+ }, async (request) => {
253
+ const params = request.params;
254
+ return service.getStreamDetails(decodeURIComponent(params.streamId));
255
+ });
256
+ app.get("/streams/:streamId/schema", {
257
+ schema: {
258
+ tags: ["sources"],
259
+ params: {
260
+ type: "object",
261
+ required: ["streamId"],
262
+ properties: {
263
+ streamId: { type: "string", minLength: 1 },
264
+ },
265
+ },
266
+ response: {
267
+ 200: jsonObjectSchema,
268
+ 400: errorResponseSchema,
269
+ 404: errorResponseSchema,
270
+ },
271
+ },
272
+ }, async (request) => {
273
+ const params = request.params;
274
+ return service.getResolvedSourceSchema(decodeURIComponent(params.streamId));
275
+ });
99
276
  app.get("/sources", {
100
277
  schema: {
101
278
  tags: ["sources"],
@@ -116,10 +293,11 @@ function buildFastifyServer(service) {
116
293
  body: {
117
294
  type: "object",
118
295
  additionalProperties: false,
119
- required: ["sourceType", "sourceKey"],
296
+ required: ["hostId", "streamKind", "streamKey"],
120
297
  properties: {
121
- sourceType: { type: "string", minLength: 1 },
122
- sourceKey: { type: "string", minLength: 1 },
298
+ hostId: { type: "string", minLength: 1 },
299
+ streamKind: { type: "string", minLength: 1 },
300
+ streamKey: { type: "string", minLength: 1 },
123
301
  configRef: { anyOf: [{ type: "string" }, { type: "null" }] },
124
302
  config: jsonObjectSchema,
125
303
  },
@@ -129,7 +307,7 @@ function buildFastifyServer(service) {
129
307
  400: errorResponseSchema,
130
308
  },
131
309
  },
132
- }, async (request) => service.registerSource(request.body));
310
+ }, async (request) => service.registerStream(request.body));
133
311
  app.get("/sources/:sourceId", {
134
312
  schema: {
135
313
  tags: ["sources"],
@@ -169,14 +347,42 @@ function buildFastifyServer(service) {
169
347
  const params = request.params;
170
348
  return service.getResolvedSourceSchema(decodeURIComponent(params.sourceId));
171
349
  });
172
- app.delete("/sources/:sourceId", {
350
+ app.patch("/streams/:streamId", {
173
351
  schema: {
174
352
  tags: ["sources"],
175
353
  params: {
176
354
  type: "object",
177
- required: ["sourceId"],
355
+ required: ["streamId"],
178
356
  properties: {
179
- sourceId: { type: "string", minLength: 1 },
357
+ streamId: { type: "string", minLength: 1 },
358
+ },
359
+ },
360
+ body: {
361
+ type: "object",
362
+ additionalProperties: false,
363
+ minProperties: 1,
364
+ properties: {
365
+ configRef: { anyOf: [{ type: "string" }, { type: "null" }] },
366
+ config: jsonObjectSchema,
367
+ },
368
+ },
369
+ response: {
370
+ 200: jsonObjectSchema,
371
+ 400: errorResponseSchema,
372
+ },
373
+ },
374
+ }, async (request) => {
375
+ const params = request.params;
376
+ return service.updateSource(decodeURIComponent(params.streamId), request.body);
377
+ });
378
+ app.delete("/streams/:streamId", {
379
+ schema: {
380
+ tags: ["sources"],
381
+ params: {
382
+ type: "object",
383
+ required: ["streamId"],
384
+ properties: {
385
+ streamId: { type: "string", minLength: 1 },
180
386
  },
181
387
  },
182
388
  querystring: {
@@ -199,25 +405,55 @@ function buildFastifyServer(service) {
199
405
  }, async (request) => {
200
406
  const params = request.params;
201
407
  const query = request.query;
202
- return service.removeSource(decodeURIComponent(params.sourceId), {
408
+ return service.removeSource(decodeURIComponent(params.streamId), {
203
409
  withSubscriptions: query.with_subscriptions === true || query.with_subscriptions === "true" || query.with_subscriptions === "1",
204
410
  });
205
411
  });
206
- app.patch("/sources/:sourceId", {
412
+ app.post("/streams/:streamId/pause", {
207
413
  schema: {
208
414
  tags: ["sources"],
209
415
  params: {
210
416
  type: "object",
211
- required: ["sourceId"],
417
+ required: ["streamId"],
212
418
  properties: {
213
- sourceId: { type: "string", minLength: 1 },
419
+ streamId: { type: "string", minLength: 1 },
420
+ },
421
+ },
422
+ response: {
423
+ 200: jsonObjectSchema,
424
+ },
425
+ },
426
+ }, async (request) => {
427
+ const params = request.params;
428
+ return service.pauseSource(decodeURIComponent(params.streamId));
429
+ });
430
+ app.post("/streams/:streamId/resume", {
431
+ schema: {
432
+ tags: ["sources"],
433
+ params: {
434
+ type: "object",
435
+ required: ["streamId"],
436
+ properties: {
437
+ streamId: { type: "string", minLength: 1 },
214
438
  },
215
439
  },
440
+ response: {
441
+ 200: jsonObjectSchema,
442
+ },
443
+ },
444
+ }, async (request) => {
445
+ const params = request.params;
446
+ return service.resumeSource(decodeURIComponent(params.streamId));
447
+ });
448
+ app.post("/streams/schema-preview", {
449
+ schema: {
450
+ tags: ["sources"],
216
451
  body: {
217
452
  type: "object",
218
453
  additionalProperties: false,
219
- minProperties: 1,
454
+ required: ["sourceRef"],
220
455
  properties: {
456
+ sourceRef: { type: "string", minLength: 1 },
221
457
  configRef: { anyOf: [{ type: "string" }, { type: "null" }] },
222
458
  config: jsonObjectSchema,
223
459
  },
@@ -227,11 +463,64 @@ function buildFastifyServer(service) {
227
463
  400: errorResponseSchema,
228
464
  },
229
465
  },
466
+ }, async (request) => service.previewSourceSchema(request.body));
467
+ app.post("/streams/:streamId/poll", {
468
+ schema: {
469
+ tags: ["sources"],
470
+ params: {
471
+ type: "object",
472
+ required: ["streamId"],
473
+ properties: {
474
+ streamId: { type: "string", minLength: 1 },
475
+ },
476
+ },
477
+ response: {
478
+ 200: jsonObjectSchema,
479
+ },
480
+ },
230
481
  }, async (request) => {
231
482
  const params = request.params;
232
- return service.updateSource(decodeURIComponent(params.sourceId), request.body);
483
+ return service.pollSource(decodeURIComponent(params.streamId));
233
484
  });
234
- app.post("/sources/:sourceId/pause", {
485
+ app.post("/streams/:streamId/events", {
486
+ schema: {
487
+ tags: ["sources"],
488
+ params: {
489
+ type: "object",
490
+ required: ["streamId"],
491
+ properties: {
492
+ streamId: { type: "string", minLength: 1 },
493
+ },
494
+ },
495
+ body: {
496
+ type: "object",
497
+ additionalProperties: false,
498
+ required: ["sourceNativeId", "eventVariant"],
499
+ properties: {
500
+ sourceNativeId: { type: "string", minLength: 1 },
501
+ eventVariant: { type: "string", minLength: 1 },
502
+ occurredAt: { type: "string", minLength: 1 },
503
+ metadata: jsonObjectSchema,
504
+ rawPayload: jsonObjectSchema,
505
+ },
506
+ },
507
+ response: {
508
+ 200: jsonObjectSchema,
509
+ },
510
+ },
511
+ }, async (request) => {
512
+ const params = request.params;
513
+ const body = request.body;
514
+ return service.appendSourceEvent({
515
+ sourceId: decodeURIComponent(params.streamId),
516
+ sourceNativeId: body.sourceNativeId,
517
+ eventVariant: body.eventVariant,
518
+ occurredAt: body.occurredAt,
519
+ metadata: body.metadata ?? {},
520
+ rawPayload: body.rawPayload ?? {},
521
+ });
522
+ });
523
+ app.delete("/sources/:sourceId", {
235
524
  schema: {
236
525
  tags: ["sources"],
237
526
  params: {
@@ -241,15 +530,31 @@ function buildFastifyServer(service) {
241
530
  sourceId: { type: "string", minLength: 1 },
242
531
  },
243
532
  },
533
+ querystring: {
534
+ type: "object",
535
+ additionalProperties: false,
536
+ properties: {
537
+ with_subscriptions: {
538
+ anyOf: [
539
+ { type: "boolean" },
540
+ { type: "string", enum: ["true", "false", "1", "0"] },
541
+ ],
542
+ },
543
+ },
544
+ },
244
545
  response: {
245
546
  200: jsonObjectSchema,
547
+ 400: errorResponseSchema,
246
548
  },
247
549
  },
248
550
  }, async (request) => {
249
551
  const params = request.params;
250
- return service.pauseSource(decodeURIComponent(params.sourceId));
552
+ const query = request.query;
553
+ return service.removeSource(decodeURIComponent(params.sourceId), {
554
+ withSubscriptions: query.with_subscriptions === true || query.with_subscriptions === "true" || query.with_subscriptions === "1",
555
+ });
251
556
  });
252
- app.post("/sources/:sourceId/resume", {
557
+ app.patch("/sources/:sourceId", {
253
558
  schema: {
254
559
  tags: ["sources"],
255
560
  params: {
@@ -259,22 +564,32 @@ function buildFastifyServer(service) {
259
564
  sourceId: { type: "string", minLength: 1 },
260
565
  },
261
566
  },
567
+ body: {
568
+ type: "object",
569
+ additionalProperties: false,
570
+ minProperties: 1,
571
+ properties: {
572
+ configRef: { anyOf: [{ type: "string" }, { type: "null" }] },
573
+ config: jsonObjectSchema,
574
+ },
575
+ },
262
576
  response: {
263
577
  200: jsonObjectSchema,
578
+ 400: errorResponseSchema,
264
579
  },
265
580
  },
266
581
  }, async (request) => {
267
582
  const params = request.params;
268
- return service.resumeSource(decodeURIComponent(params.sourceId));
583
+ return service.updateSource(decodeURIComponent(params.sourceId), request.body);
269
584
  });
270
- app.get("/source-types/:sourceType/schema", {
585
+ app.post("/sources/:sourceId/pause", {
271
586
  schema: {
272
587
  tags: ["sources"],
273
588
  params: {
274
589
  type: "object",
275
- required: ["sourceType"],
590
+ required: ["sourceId"],
276
591
  properties: {
277
- sourceType: { type: "string", minLength: 1 },
592
+ sourceId: { type: "string", minLength: 1 },
278
593
  },
279
594
  },
280
595
  response: {
@@ -283,27 +598,26 @@ function buildFastifyServer(service) {
283
598
  },
284
599
  }, async (request) => {
285
600
  const params = request.params;
286
- return service.getSourceSchema(decodeURIComponent(params.sourceType));
601
+ return service.pauseSource(decodeURIComponent(params.sourceId));
287
602
  });
288
- app.post("/sources/schema-preview", {
603
+ app.post("/sources/:sourceId/resume", {
289
604
  schema: {
290
605
  tags: ["sources"],
291
- body: {
606
+ params: {
292
607
  type: "object",
293
- additionalProperties: false,
294
- required: ["sourceRef"],
608
+ required: ["sourceId"],
295
609
  properties: {
296
- sourceRef: { type: "string", minLength: 1 },
297
- configRef: { anyOf: [{ type: "string" }, { type: "null" }] },
298
- config: jsonObjectSchema,
610
+ sourceId: { type: "string", minLength: 1 },
299
611
  },
300
612
  },
301
613
  response: {
302
614
  200: jsonObjectSchema,
303
- 400: errorResponseSchema,
304
615
  },
305
616
  },
306
- }, async (request) => service.previewSourceSchema(request.body));
617
+ }, async (request) => {
618
+ const params = request.params;
619
+ return service.resumeSource(decodeURIComponent(params.sourceId));
620
+ });
307
621
  app.post("/sources/:sourceId/poll", {
308
622
  schema: {
309
623
  tags: ["sources"],
@@ -425,6 +739,7 @@ function buildFastifyServer(service) {
425
739
  termProgram: { type: "string" },
426
740
  itermSessionId: { type: "string" },
427
741
  notifyLeaseMs: { type: "integer", minimum: 1 },
742
+ minUnackedItems: { type: "integer", minimum: 1 },
428
743
  },
429
744
  },
430
745
  response: {
@@ -447,6 +762,7 @@ function buildFastifyServer(service) {
447
762
  termProgram: optionalString(body.termProgram),
448
763
  itermSessionId: optionalString(body.itermSessionId),
449
764
  notifyLeaseMs: typeof body.notifyLeaseMs === "number" ? body.notifyLeaseMs : null,
765
+ minUnackedItems: typeof body.minUnackedItems === "number" ? body.minUnackedItems : null,
450
766
  });
451
767
  });
452
768
  app.get("/agents/:agentId", {
@@ -548,6 +864,7 @@ function buildFastifyServer(service) {
548
864
  url: { type: "string", minLength: 1 },
549
865
  activationMode: { type: "string" },
550
866
  notifyLeaseMs: { type: "integer", minimum: 1 },
867
+ minUnackedItems: { type: "integer", minimum: 1 },
551
868
  },
552
869
  },
553
870
  response: {
@@ -562,6 +879,7 @@ function buildFastifyServer(service) {
562
879
  url: body.url,
563
880
  activationMode: body.activationMode,
564
881
  notifyLeaseMs: body.notifyLeaseMs ?? null,
882
+ minUnackedItems: body.minUnackedItems ?? null,
565
883
  });
566
884
  });
567
885
  app.delete("/agents/:agentId/targets/:targetId", {
@@ -731,13 +1049,7 @@ function buildFastifyServer(service) {
731
1049
  },
732
1050
  },
733
1051
  response: {
734
- 200: {
735
- type: "object",
736
- required: ["subscriptions"],
737
- properties: {
738
- subscriptions: { type: "array", items: jsonObjectSchema },
739
- },
740
- },
1052
+ 200: subscriptionCollectionSchema,
741
1053
  },
742
1054
  },
743
1055
  }, async (request) => {
@@ -777,13 +1089,13 @@ function buildFastifyServer(service) {
777
1089
  },
778
1090
  },
779
1091
  response: {
780
- 200: jsonObjectSchema,
1092
+ 200: subscriptionCollectionSchema,
781
1093
  400: errorResponseSchema,
782
1094
  },
783
1095
  },
784
1096
  }, async (request) => {
785
1097
  const body = request.body;
786
- return service.registerSubscription({
1098
+ const input = {
787
1099
  agentId: String(body.agentId),
788
1100
  sourceId: String(body.sourceId),
789
1101
  shortcut: body.shortcut && typeof body.shortcut === "object"
@@ -800,7 +1112,8 @@ function buildFastifyServer(service) {
800
1112
  startPolicy: optionalString(body.startPolicy),
801
1113
  startOffset: typeof body.startOffset === "number" ? body.startOffset : undefined,
802
1114
  startTime: optionalString(body.startTime) ?? undefined,
803
- });
1115
+ };
1116
+ return { subscriptions: await service.registerSubscriptions(input) };
804
1117
  });
805
1118
  app.get("/subscriptions/:subscriptionId", {
806
1119
  schema: {
@@ -930,7 +1243,7 @@ function buildFastifyServer(service) {
930
1243
  const params = request.params;
931
1244
  return service.getInboxDetailsByAgent(decodeURIComponent(params.agentId));
932
1245
  });
933
- app.get("/agents/:agentId/inbox/items", {
1246
+ app.get("/agents/:agentId/inbox/entries", {
934
1247
  schema: {
935
1248
  tags: ["inbox"],
936
1249
  params: {
@@ -944,16 +1257,16 @@ function buildFastifyServer(service) {
944
1257
  type: "object",
945
1258
  additionalProperties: false,
946
1259
  properties: {
947
- after_item_id: { type: "string" },
1260
+ after_entry_id: { type: "string" },
948
1261
  include_acked: { type: "string", enum: ["true", "false"] },
949
1262
  },
950
1263
  },
951
1264
  response: {
952
1265
  200: {
953
1266
  type: "object",
954
- required: ["items"],
1267
+ required: ["entries"],
955
1268
  properties: {
956
- items: { type: "array", items: jsonObjectSchema },
1269
+ entries: { type: "array", items: jsonObjectSchema },
957
1270
  },
958
1271
  },
959
1272
  },
@@ -962,8 +1275,8 @@ function buildFastifyServer(service) {
962
1275
  const params = request.params;
963
1276
  const query = request.query;
964
1277
  return {
965
- items: service.listInboxItems(decodeURIComponent(params.agentId), {
966
- afterItemId: query.after_item_id,
1278
+ entries: service.listInboxItems(decodeURIComponent(params.agentId), {
1279
+ afterEntryId: query.after_entry_id,
967
1280
  includeAcked: query.include_acked ? query.include_acked === "true" : undefined,
968
1281
  }),
969
1282
  };
@@ -1015,7 +1328,7 @@ function buildFastifyServer(service) {
1015
1328
  type: "object",
1016
1329
  additionalProperties: false,
1017
1330
  properties: {
1018
- after_item_id: { type: "string" },
1331
+ after_entry_id: { type: "string" },
1019
1332
  include_acked: { type: "string", enum: ["true", "false"] },
1020
1333
  heartbeat_ms: { type: "string", pattern: "^[1-9][0-9]*$" },
1021
1334
  },
@@ -1029,7 +1342,7 @@ function buildFastifyServer(service) {
1029
1342
  const query = request.query;
1030
1343
  const agentId = decodeURIComponent(params.agentId);
1031
1344
  const watchOptions = {
1032
- afterItemId: query.after_item_id,
1345
+ afterEntryId: query.after_entry_id,
1033
1346
  includeAcked: query.include_acked ? query.include_acked === "true" : undefined,
1034
1347
  heartbeatMs: query.heartbeat_ms ? Number(query.heartbeat_ms) : undefined,
1035
1348
  };
@@ -1046,7 +1359,7 @@ function buildFastifyServer(service) {
1046
1359
  sendSse(raw, "items", {
1047
1360
  event: "items",
1048
1361
  agentId,
1049
- items: session.initialItems,
1362
+ entries: session.initialItems,
1050
1363
  });
1051
1364
  session.start();
1052
1365
  const heartbeatMs = watchOptions.heartbeatMs ?? 15_000;
@@ -1098,9 +1411,9 @@ function buildFastifyServer(service) {
1098
1411
  {
1099
1412
  type: "object",
1100
1413
  additionalProperties: false,
1101
- required: ["itemIds"],
1414
+ required: ["entryIds"],
1102
1415
  properties: {
1103
- itemIds: {
1416
+ entryIds: {
1104
1417
  type: "array",
1105
1418
  minItems: 1,
1106
1419
  items: { type: "string", minLength: 1 },
@@ -1110,9 +1423,9 @@ function buildFastifyServer(service) {
1110
1423
  {
1111
1424
  type: "object",
1112
1425
  additionalProperties: false,
1113
- required: ["throughItemId"],
1426
+ required: ["throughEntryId"],
1114
1427
  properties: {
1115
- throughItemId: { type: "string", minLength: 1 },
1428
+ throughEntryId: { type: "string", minLength: 1 },
1116
1429
  },
1117
1430
  },
1118
1431
  {
@@ -1134,11 +1447,58 @@ function buildFastifyServer(service) {
1134
1447
  const params = request.params;
1135
1448
  const body = request.body;
1136
1449
  return service.ackInbox(decodeURIComponent(params.agentId), {
1137
- itemIds: body.itemIds ?? [],
1138
- throughItemId: body.throughItemId ?? null,
1450
+ entryIds: body.entryIds ?? [],
1451
+ throughEntryId: body.throughEntryId ?? null,
1139
1452
  all: body.all ?? false,
1140
1453
  });
1141
1454
  });
1455
+ app.get("/agents/:agentId/inbox/policy", {
1456
+ schema: {
1457
+ tags: ["inbox"],
1458
+ params: {
1459
+ type: "object",
1460
+ required: ["agentId"],
1461
+ properties: {
1462
+ agentId: { type: "string", minLength: 1 },
1463
+ },
1464
+ },
1465
+ response: {
1466
+ 200: jsonObjectSchema,
1467
+ },
1468
+ },
1469
+ }, async (request) => {
1470
+ const params = request.params;
1471
+ return service.getInboxAggregationPolicy(decodeURIComponent(params.agentId));
1472
+ });
1473
+ app.post("/agents/:agentId/inbox/policy", {
1474
+ schema: {
1475
+ tags: ["inbox"],
1476
+ params: {
1477
+ type: "object",
1478
+ required: ["agentId"],
1479
+ properties: {
1480
+ agentId: { type: "string", minLength: 1 },
1481
+ },
1482
+ },
1483
+ body: {
1484
+ type: "object",
1485
+ additionalProperties: false,
1486
+ properties: {
1487
+ enabled: { type: "boolean" },
1488
+ windowMs: { type: "integer", minimum: 1 },
1489
+ maxItems: { type: "integer", minimum: 1 },
1490
+ maxThreadAgeMs: { type: "integer", minimum: 1 },
1491
+ },
1492
+ },
1493
+ response: {
1494
+ 200: jsonObjectSchema,
1495
+ },
1496
+ },
1497
+ }, async (request) => {
1498
+ const params = request.params;
1499
+ const body = request.body;
1500
+ return service.updateInboxAggregationPolicy(decodeURIComponent(params.agentId), body);
1501
+ });
1142
1502
  app.post("/deliveries/send", {
1143
1503
  schema: {
1144
1504
  tags: ["deliveries"],
@@ -1149,6 +1509,7 @@ function buildFastifyServer(service) {
1149
1509
  additionalProperties: false,
1150
1510
  required: ["kind", "payload", "deliveryHandle"],
1151
1511
  properties: {
1512
+ sourceId: { type: "string", minLength: 1 },
1152
1513
  kind: { type: "string", minLength: 1 },
1153
1514
  payload: jsonObjectSchema,
1154
1515
  deliveryHandle: deliveryHandleSchema,
@@ -1159,6 +1520,7 @@ function buildFastifyServer(service) {
1159
1520
  additionalProperties: false,
1160
1521
  required: ["kind", "payload", "provider", "surface", "targetRef"],
1161
1522
  properties: {
1523
+ sourceId: { type: "string", minLength: 1 },
1162
1524
  kind: { type: "string", minLength: 1 },
1163
1525
  payload: jsonObjectSchema,
1164
1526
  provider: { type: "string", minLength: 1 },
@@ -1176,6 +1538,57 @@ function buildFastifyServer(service) {
1176
1538
  },
1177
1539
  },
1178
1540
  }, async (request) => service.sendDelivery(request.body));
1541
+ app.post("/deliveries/actions", {
1542
+ schema: {
1543
+ tags: ["deliveries"],
1544
+ body: {
1545
+ oneOf: [deliveryTargetByHandleSchema, deliveryTargetByFieldsSchema],
1546
+ },
1547
+ response: {
1548
+ 200: jsonObjectSchema,
1549
+ 400: errorResponseSchema,
1550
+ },
1551
+ },
1552
+ }, async (request) => service.listDeliveryActions(request.body));
1553
+ app.post("/deliveries/invoke", {
1554
+ schema: {
1555
+ tags: ["deliveries"],
1556
+ body: {
1557
+ oneOf: [
1558
+ {
1559
+ type: "object",
1560
+ additionalProperties: false,
1561
+ required: ["deliveryHandle", "operation", "input"],
1562
+ properties: {
1563
+ sourceId: { type: "string", minLength: 1 },
1564
+ deliveryHandle: deliveryHandleSchema,
1565
+ operation: { type: "string", minLength: 1 },
1566
+ input: jsonObjectSchema,
1567
+ },
1568
+ },
1569
+ {
1570
+ type: "object",
1571
+ additionalProperties: false,
1572
+ required: ["provider", "surface", "targetRef", "operation", "input"],
1573
+ properties: {
1574
+ sourceId: { type: "string", minLength: 1 },
1575
+ provider: { type: "string", minLength: 1 },
1576
+ surface: { type: "string", minLength: 1 },
1577
+ targetRef: { type: "string", minLength: 1 },
1578
+ threadRef: { type: "string" },
1579
+ replyMode: { type: "string" },
1580
+ operation: { type: "string", minLength: 1 },
1581
+ input: jsonObjectSchema,
1582
+ },
1583
+ },
1584
+ ],
1585
+ },
1586
+ response: {
1587
+ 200: jsonObjectSchema,
1588
+ 400: errorResponseSchema,
1589
+ },
1590
+ },
1591
+ }, async (request) => service.invokeDelivery(request.body));
1179
1592
  app.setNotFoundHandler((_request, reply) => {
1180
1593
  void reply.code(404).send({ error: "not found" });
1181
1594
  });
@@ -1256,7 +1669,15 @@ function isBadRequestError(message) {
1256
1669
  message.startsWith("manual append is not supported") ||
1257
1670
  message.startsWith("sources/events requires") ||
1258
1671
  message.startsWith("source remove requires") ||
1672
+ message.startsWith("delivery requires") ||
1673
+ message.startsWith("deliver send is not supported") ||
1259
1674
  message.startsWith("deliveryHandle requires") ||
1675
+ message.startsWith("delivery operations are not supported") ||
1676
+ message.startsWith("unknown GitHub delivery operation") ||
1677
+ message.startsWith("unknown Feishu delivery operation") ||
1678
+ message.startsWith("invalid GitHub targetRef") ||
1679
+ message.includes("requires input.text") ||
1680
+ message.includes("requires input.body") ||
1260
1681
  message.startsWith("subscriptions/reset requires") ||
1261
1682
  message.startsWith("agents requires") ||
1262
1683
  message.startsWith("agents/targets requires") ||
@@ -1277,10 +1698,13 @@ function isBadRequestError(message) {
1277
1698
  message.startsWith("expected integer") ||
1278
1699
  message.startsWith("expected positive integer") ||
1279
1700
  message.startsWith("notifyLeaseMs must be a positive integer") ||
1701
+ message.startsWith("minUnackedItems must be a positive integer") ||
1280
1702
  message.startsWith("invalid webhook activation target") ||
1281
1703
  message.startsWith("remote_source requires") ||
1282
1704
  message.startsWith("remote_source profile") ||
1283
1705
  message.startsWith("remote_source module") ||
1706
+ message.startsWith("reply_in_review_thread requires") ||
1707
+ message.includes("does not match delivery provider") ||
1284
1708
  message.includes("requires tmuxPaneId") ||
1285
1709
  message.includes("requires iTerm2 session identity") ||
1286
1710
  message.includes("requires a supported terminal context") ||