@parall/agent-core 1.42.1 → 1.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/channel-exec.d.ts +4 -0
- package/dist/bin/channel-exec.d.ts.map +1 -0
- package/dist/bin/channel-exec.js +246 -0
- package/dist/channel-capability.d.ts +16 -0
- package/dist/channel-capability.d.ts.map +1 -0
- package/dist/channel-capability.js +155 -0
- package/dist/channel-token.d.ts +19 -0
- package/dist/channel-token.d.ts.map +1 -0
- package/dist/channel-token.js +73 -0
- package/dist/event-format.d.ts.map +1 -1
- package/dist/event-format.js +21 -16
- package/dist/gateway-base.d.ts +37 -0
- package/dist/gateway-base.d.ts.map +1 -1
- package/dist/gateway-base.js +120 -12
- package/dist/gateway-lane-flow.d.ts +23 -2
- package/dist/gateway-lane-flow.d.ts.map +1 -1
- package/dist/gateway-lane-flow.js +118 -6
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/lane-ledger.d.ts +22 -0
- package/dist/lane-ledger.d.ts.map +1 -1
- package/dist/lane-ledger.js +36 -1
- package/dist/platform-config.d.ts +15 -0
- package/dist/platform-config.d.ts.map +1 -1
- package/dist/platform-config.js +28 -0
- package/dist/prompt-fragments.d.ts +1 -1
- package/dist/prompt-fragments.d.ts.map +1 -1
- package/dist/prompt-fragments.js +29 -7
- package/dist/skills/index.js +1 -1
- package/dist/skills/parall-platform.d.ts +1 -1
- package/dist/skills/parall-platform.d.ts.map +1 -1
- package/dist/skills/parall-platform.js +23 -4
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/bin/channel-exec.ts +262 -0
- package/src/channel-capability.ts +187 -0
- package/src/channel-token.ts +92 -0
- package/src/event-format.ts +21 -16
- package/src/gateway-base.ts +141 -19
- package/src/gateway-lane-flow.ts +132 -5
- package/src/index.ts +3 -0
- package/src/lane-ledger.ts +46 -3
- package/src/platform-config.ts +44 -0
- package/src/prompt-fragments.ts +29 -7
- package/src/skills/index.ts +1 -1
- package/src/skills/parall-platform.ts +23 -4
- package/src/types.ts +5 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-base.d.ts","sourceRoot":"","sources":["../src/gateway-base.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiC,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,KAAK,EACV,qBAAqB,EAkBtB,MAAM,aAAa,CAAC;AAOrB,OAAO,EAGL,KAAK,eAAe,EAGpB,KAAK,aAAa,EAEnB,MAAM,uBAAuB,CAAC;AAqC/B,OAAO,KAAK,EAAiB,WAAW,EAAE,MAAM,YAAY,CAAC;AAwB7D,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACtC,WAAW,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7F,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAC/B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GAC1C;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AAExB,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;IACrB,EAAE,EAAE,QAAQ,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE;QACN,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,eAAe,EAAE,eAAe,CAAC;IACjC,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,kGAAkG;IAClG,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAI3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACvE,0FAA0F;IAC1F,wBAAwB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACtE;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QACvB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,EAAE,EAAE,QAAQ,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;KACpB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;KACxB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAChD,YAAY,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACnE,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC/D,CAAC;AAkBF,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAKnF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAK/E;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAKnF;AAsFD,qBAAa,kBAAkB;
|
|
1
|
+
{"version":3,"file":"gateway-base.d.ts","sourceRoot":"","sources":["../src/gateway-base.ts"],"names":[],"mappings":"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"}
|
package/dist/gateway-base.js
CHANGED
|
@@ -125,6 +125,9 @@ export class ParallAgentGateway {
|
|
|
125
125
|
// (stable mapping; avoids one connection fetch per inbound message).
|
|
126
126
|
channelConnectionProviders = new Map();
|
|
127
127
|
dispatchedMessages = new Set();
|
|
128
|
+
// Per-WorkItem failure backoff for typed dispatch consumption — see
|
|
129
|
+
// LaneFlowHost.typedRedriveBackoff in gateway-lane-flow.ts.
|
|
130
|
+
typedRedriveBackoff = new Map();
|
|
128
131
|
forkStates = new Map();
|
|
129
132
|
dispatchState = {
|
|
130
133
|
mainDispatching: false,
|
|
@@ -264,7 +267,14 @@ export class ParallAgentGateway {
|
|
|
264
267
|
source_type: 'task_activity',
|
|
265
268
|
source_id: data.id,
|
|
266
269
|
})
|
|
267
|
-
.then(() =>
|
|
270
|
+
.then(() => true, (err) => {
|
|
271
|
+
// Same contract as ackDispatchEvent: a failed ack is a
|
|
272
|
+
// failed consume (arms backoff) and must free the hot-path
|
|
273
|
+
// dedupe so the re-drive isn't rejected by this pod forever.
|
|
274
|
+
this.dispatchedTasks.delete(`${data.id}:${data.updated_at}`);
|
|
275
|
+
this.opts.log?.warn(`dispatch ack failed for task ${data.id}, releasing for re-drive: ${String(err)}`);
|
|
276
|
+
return false;
|
|
277
|
+
});
|
|
268
278
|
});
|
|
269
279
|
}
|
|
270
280
|
catch (err) {
|
|
@@ -400,6 +410,44 @@ export class ParallAgentGateway {
|
|
|
400
410
|
this.dispatchedMessages.add(id);
|
|
401
411
|
return true;
|
|
402
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* Lane currently being dispatched per session — lets external activity
|
|
415
|
+
* signals renew exactly the caller's lane (renewing all lanes would keep
|
|
416
|
+
* an unrelated stalled fork's lane leased forever).
|
|
417
|
+
*/
|
|
418
|
+
sessionActiveLanes = new Map();
|
|
419
|
+
noteSessionLane(sessionKey, laneKey) {
|
|
420
|
+
if (laneKey == null)
|
|
421
|
+
this.sessionActiveLanes.delete(sessionKey);
|
|
422
|
+
else
|
|
423
|
+
this.sessionActiveLanes.set(sessionKey, laneKey);
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* External runtime-activity signal for adapters whose tool activity does
|
|
427
|
+
* not flow through the RuntimeEvent stream (openclaw hooks call this from
|
|
428
|
+
* the tool-call lifecycle): renews the session's OWN active ledger lane so
|
|
429
|
+
* a long tool call cannot outlive the lease and get dethroned mid-turn.
|
|
430
|
+
* No-op without an active ledger lane for the session.
|
|
431
|
+
*/
|
|
432
|
+
touchRuntimeActivity(sessionKey) {
|
|
433
|
+
if (this.ledgerDisabled)
|
|
434
|
+
return;
|
|
435
|
+
const laneKey = this.sessionActiveLanes.get(sessionKey);
|
|
436
|
+
if (laneKey)
|
|
437
|
+
this.laneLedger?.renewByKey(laneKey);
|
|
438
|
+
}
|
|
439
|
+
/** Sessions whose in-flight turn surfaced a runtime error event. */
|
|
440
|
+
turnErrorSessions = new Set();
|
|
441
|
+
/**
|
|
442
|
+
* Consume (read-and-clear) the error marker for sessionKey's last turn.
|
|
443
|
+
* Feeds complete's turn_outcome so an error turn's lane members are
|
|
444
|
+
* released for retry instead of no_action-swept (design §3). Consuming
|
|
445
|
+
* (rather than peeking) keeps one-shot fork session keys from accumulating
|
|
446
|
+
* in the set forever.
|
|
447
|
+
*/
|
|
448
|
+
consumeTurnError(sessionKey) {
|
|
449
|
+
return this.turnErrorSessions.delete(sessionKey);
|
|
450
|
+
}
|
|
403
451
|
async emitDispatchReceived(event) {
|
|
404
452
|
const sourceType = event.ackSourceType ?? (event.type === 'task' ? 'task_activity' : 'message');
|
|
405
453
|
const sourceId = event.ackSourceId ?? event.messageId;
|
|
@@ -447,14 +495,18 @@ export class ParallAgentGateway {
|
|
|
447
495
|
}
|
|
448
496
|
// Typed completion must wait until the administrative ack has either
|
|
449
497
|
// committed or failed. Errors stay best-effort: a failed ack leaves the row
|
|
450
|
-
// received, so Complete releases and re-drives it safely.
|
|
498
|
+
// received, so Complete releases and re-drives it safely. The boolean
|
|
499
|
+
// outcome feeds the typed-consume backoff — an ack that failed must count
|
|
500
|
+
// as a failed consume, or an ack outage would clear the backoff entry and
|
|
501
|
+
// let the release re-drive spin at wire speed.
|
|
451
502
|
ackDispatchEvent(dispatchEventId, onFailure) {
|
|
452
|
-
return this.opts.client.ackDispatchByID(this.opts.config.org_id, dispatchEventId).then(() =>
|
|
503
|
+
return this.opts.client.ackDispatchByID(this.opts.config.org_id, dispatchEventId).then(() => true, (err) => {
|
|
453
504
|
// Complete will return the still-received item to pending and publish
|
|
454
505
|
// an immediate hint. Free its hot-path claim first, otherwise that
|
|
455
506
|
// same-process re-drive is rejected forever by the local dedupe set.
|
|
456
507
|
onFailure?.();
|
|
457
508
|
this.opts.log?.warn(`dispatch ack failed for ${dispatchEventId}, releasing for re-drive: ${String(err)}`);
|
|
509
|
+
return false;
|
|
458
510
|
});
|
|
459
511
|
}
|
|
460
512
|
clearTypedDispatchDedupe(item) {
|
|
@@ -800,6 +852,7 @@ export class ParallAgentGateway {
|
|
|
800
852
|
this.pendingRestartNotification = null;
|
|
801
853
|
}
|
|
802
854
|
resetDispatchMetrics(sessionKey);
|
|
855
|
+
this.turnErrorSessions.delete(sessionKey);
|
|
803
856
|
return runWithSessionKey(sessionKey, async () => {
|
|
804
857
|
let dispatchSpan = null;
|
|
805
858
|
setSessionChatId(sessionKey, event.targetId);
|
|
@@ -936,6 +989,9 @@ export class ParallAgentGateway {
|
|
|
936
989
|
pendingSendCallIds.delete(runtimeEvent.callId)) {
|
|
937
990
|
recordMessageSend(sessionKey, !runtimeEvent.error);
|
|
938
991
|
}
|
|
992
|
+
if (runtimeEvent.type === 'error') {
|
|
993
|
+
this.turnErrorSessions.add(sessionKey);
|
|
994
|
+
}
|
|
939
995
|
await this.createRuntimeStep(binding.agentSessionId, event, runtimeEvent, stepIdFilePath, contextFilePath, laneContextFilePath);
|
|
940
996
|
}
|
|
941
997
|
if (!binding) {
|
|
@@ -1108,7 +1164,12 @@ export class ParallAgentGateway {
|
|
|
1108
1164
|
body: buildForkScopePrefix(last) + buildEventBody(last),
|
|
1109
1165
|
earlier,
|
|
1110
1166
|
captureText: batchText,
|
|
1111
|
-
|
|
1167
|
+
// Per-LANE residue check (parity with the main-buffer path):
|
|
1168
|
+
// the fork queue can hold several lanes (channel + thread of
|
|
1169
|
+
// the same chat). A whole-queue check would defer THIS lane's
|
|
1170
|
+
// complete behind another lane's items and never revisit it —
|
|
1171
|
+
// its members would sit received until lease expiry.
|
|
1172
|
+
hasMoreLocal: () => fork.queue.some((it) => this.dispatchGroupKey(it.event) === this.dispatchGroupKey(last)),
|
|
1112
1173
|
});
|
|
1113
1174
|
if (outcome === 'foreign') {
|
|
1114
1175
|
// Another pod owns the lane — the events stay pending server-side.
|
|
@@ -1116,6 +1177,15 @@ export class ParallAgentGateway {
|
|
|
1116
1177
|
item.resolve(false);
|
|
1117
1178
|
break;
|
|
1118
1179
|
}
|
|
1180
|
+
if (outcome === 'failed') {
|
|
1181
|
+
// Error turn: complete(error) already released the members for
|
|
1182
|
+
// redelivery. Do NOT push them to processedEvents — the redrive
|
|
1183
|
+
// must not arrive wearing an "already handled" prefix. Keep
|
|
1184
|
+
// draining; the released work rejoins the next claim.
|
|
1185
|
+
for (const item of items)
|
|
1186
|
+
item.resolve(false);
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1119
1189
|
dispatched = outcome === 'dispatched';
|
|
1120
1190
|
}
|
|
1121
1191
|
else {
|
|
@@ -1154,6 +1224,10 @@ export class ParallAgentGateway {
|
|
|
1154
1224
|
}
|
|
1155
1225
|
}
|
|
1156
1226
|
finally {
|
|
1227
|
+
// One-shot fork keys are never dispatched again — drop any error marker
|
|
1228
|
+
// the legacy (non-ledger) path left unconsumed, or the set grows with
|
|
1229
|
+
// every failed ephemeral fork.
|
|
1230
|
+
this.turnErrorSessions.delete(fork.fork.sessionKey);
|
|
1157
1231
|
if (fork.deadlineTimer) {
|
|
1158
1232
|
clearTimeout(fork.deadlineTimer);
|
|
1159
1233
|
fork.deadlineTimer = null;
|
|
@@ -1281,6 +1355,13 @@ export class ParallAgentGateway {
|
|
|
1281
1355
|
this.dispatchState.pendingForkResults.unshift(...pendingFork);
|
|
1282
1356
|
continue;
|
|
1283
1357
|
}
|
|
1358
|
+
if (outcome === 'failed') {
|
|
1359
|
+
// Error turn settled with complete(error) — members released for
|
|
1360
|
+
// redelivery. The fork results were not consumed by the failed
|
|
1361
|
+
// turn; keep them for the next real dispatch.
|
|
1362
|
+
this.dispatchState.pendingForkResults.unshift(...pendingFork);
|
|
1363
|
+
continue;
|
|
1364
|
+
}
|
|
1284
1365
|
// Dispatched — resolution happened server-side (reply cover or
|
|
1285
1366
|
// no_action sweep); no legacy acks.
|
|
1286
1367
|
continue;
|
|
@@ -1424,9 +1505,16 @@ export class ParallAgentGateway {
|
|
|
1424
1505
|
// fold leaves the event buffered — the drain claims it as its own
|
|
1425
1506
|
// turn. Injection requires an exact lane match (same chat AND same
|
|
1426
1507
|
// thread) — a thread message never rides a channel turn.
|
|
1508
|
+
// The adapter-capability check comes BEFORE the fold: on a
|
|
1509
|
+
// buffer-only adapter (openclaw — no enqueueDuringDispatch) a
|
|
1510
|
+
// folded-but-never-injected member would be broad-covered by the
|
|
1511
|
+
// current turn's reply without the model ever seeing it. Leaving
|
|
1512
|
+
// the event un-folded keeps it buffered; the drain claims it as
|
|
1513
|
+
// its own turn and folds it there.
|
|
1427
1514
|
if (this.mainCurrentGroupKey === this.dispatchGroupKey(event) &&
|
|
1515
|
+
this.opts.dispatchAdapter.enqueueDuringDispatch != null &&
|
|
1428
1516
|
(await this.laneLedger?.steerLive(event)) &&
|
|
1429
|
-
(await this.opts.dispatchAdapter.enqueueDuringDispatch
|
|
1517
|
+
(await this.opts.dispatchAdapter.enqueueDuringDispatch(this.opts.runtimeKey, buildEventBody(event)))) {
|
|
1430
1518
|
this.opts.log?.info(`steer folded+injected for ${event.messageId} (will drain for bookkeeping)`);
|
|
1431
1519
|
}
|
|
1432
1520
|
}
|
|
@@ -1460,13 +1548,20 @@ export class ParallAgentGateway {
|
|
|
1460
1548
|
this.dispatchState.mainBuffer.push(event);
|
|
1461
1549
|
return false;
|
|
1462
1550
|
}
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1551
|
+
// Ledger-managed events must never touch the legacy received surface
|
|
1552
|
+
// — the fork's lane claim marks them received. A mark-received here
|
|
1553
|
+
// outruns the claim, strands the row ownerless, and the chat goes
|
|
1554
|
+
// silent (the 0713 black hole; dispatch-convergence-design.md §6).
|
|
1555
|
+
// This was the only unguarded call site of the three.
|
|
1556
|
+
if (!this.usesLaneLedger(event)) {
|
|
1557
|
+
try {
|
|
1558
|
+
await this.emitDispatchReceived(event);
|
|
1559
|
+
}
|
|
1560
|
+
catch (err) {
|
|
1561
|
+
this.opts.log?.warn?.(`mark-received failed for fork dispatch, leaving unacked for retry: ${String(err)}`);
|
|
1562
|
+
this.dispatchState.mainBuffer.push(event);
|
|
1563
|
+
return false;
|
|
1564
|
+
}
|
|
1470
1565
|
}
|
|
1471
1566
|
const fork = await this.opts.dispatchAdapter.forkSession({
|
|
1472
1567
|
sessionKey: this.opts.runtimeKey,
|
|
@@ -1997,6 +2092,18 @@ export class ParallAgentGateway {
|
|
|
1997
2092
|
provider = undefined; // label degrades; reply hint still names the clip generically
|
|
1998
2093
|
}
|
|
1999
2094
|
}
|
|
2095
|
+
// The reply hint routes on the live capability grant: `<provider>-cli`
|
|
2096
|
+
// present → the vendor CLI is on PATH (broker shim) and is THE reply
|
|
2097
|
+
// path; absent → outbound is disabled for this org (flag/connection off)
|
|
2098
|
+
// and the hint must say so instead of pointing at a retired clip. The
|
|
2099
|
+
// provider label lookup above is best-effort/cosmetic — when it fails,
|
|
2100
|
+
// ANY granted `*-cli` capability keeps the hint on the CLI path: a
|
|
2101
|
+
// transient metadata miss must not flip an actively granted agent's
|
|
2102
|
+
// hint to "outbound disabled" and strand a valid external message.
|
|
2103
|
+
const keys = this.opts.getCapabilityKeys?.() ?? [];
|
|
2104
|
+
const cliCapable = provider
|
|
2105
|
+
? keys.includes(`${provider}-cli`)
|
|
2106
|
+
: keys.some((k) => k.endsWith('-cli'));
|
|
2000
2107
|
const event = {
|
|
2001
2108
|
type: 'channel_message',
|
|
2002
2109
|
targetId: conv.id,
|
|
@@ -2011,6 +2118,7 @@ export class ParallAgentGateway {
|
|
|
2011
2118
|
channelConversationType: conv.conversation_type || undefined,
|
|
2012
2119
|
channelExternalConversationId: conv.external_conversation_id,
|
|
2013
2120
|
channelExternalMessageId: msg.external_message_id,
|
|
2121
|
+
channelCliCapable: cliCapable,
|
|
2014
2122
|
ackSourceType: 'channel_message',
|
|
2015
2123
|
ackSourceId: msg.id,
|
|
2016
2124
|
};
|
|
@@ -15,6 +15,18 @@ export interface LaneFlowHost {
|
|
|
15
15
|
ledgerDisabled: boolean;
|
|
16
16
|
shuttingDown: boolean;
|
|
17
17
|
dispatchedMessages: Set<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Per-WorkItem failure backoff for typed dispatch consumption. A consume
|
|
20
|
+
* that ends without an ack re-arms the entry; the next attempt for the
|
|
21
|
+
* same WorkItem is delayed (not skipped — a skipped attempt would strand
|
|
22
|
+
* the pending row until reconnect catch-up) so a claim→fail→complete
|
|
23
|
+
* tight loop is throttled to exponential intervals instead of spinning at
|
|
24
|
+
* wire speed against the server's immediate re-drive (2026-07-11 OOM).
|
|
25
|
+
*/
|
|
26
|
+
typedRedriveBackoff: Map<string, {
|
|
27
|
+
failures: number;
|
|
28
|
+
until: number;
|
|
29
|
+
}>;
|
|
18
30
|
opts: {
|
|
19
31
|
client: ParallClient;
|
|
20
32
|
log?: GatewayLogger;
|
|
@@ -27,6 +39,8 @@ export interface LaneFlowHost {
|
|
|
27
39
|
disableLedger(reason: string): void;
|
|
28
40
|
usesLaneLedger(event: ParallEvent): boolean;
|
|
29
41
|
emitDispatchReceived(event: ParallEvent): Promise<void>;
|
|
42
|
+
consumeTurnError(sessionKey: string): boolean;
|
|
43
|
+
noteSessionLane(sessionKey: string, laneKey: string | null): void;
|
|
30
44
|
runDispatch(event: ParallEvent, sessionKey: string, bodyForAgent: string, earlierEvents?: ParallEvent[], captureText?: string[]): Promise<boolean>;
|
|
31
45
|
tryClaimMessage(id: string): boolean;
|
|
32
46
|
buildMessageDispatchDecision(chatId: string, message: DispatchableMessage): Promise<MessageDispatchDecision>;
|
|
@@ -45,19 +59,26 @@ export declare function dispatchLaneGroup(host: LaneFlowHost, opts: {
|
|
|
45
59
|
earlier: ParallEvent[];
|
|
46
60
|
captureText?: string[];
|
|
47
61
|
hasMoreLocal: () => boolean;
|
|
48
|
-
}): Promise<'dispatched' | 'foreign' | 'shutdown'>;
|
|
62
|
+
}): Promise<'dispatched' | 'foreign' | 'shutdown' | 'failed'>;
|
|
49
63
|
/**
|
|
50
64
|
* Consume one typed dispatch (task/comment/schedule/trigger/approval) under
|
|
51
65
|
* its typed-lane occupancy guard: claim the dsp:<id> lane (skip when another
|
|
52
66
|
* pod holds it or the WorkItem is already resolved), run the handler, ack on
|
|
53
67
|
* success (the doc's option (b): notification delivered, tracked elsewhere),
|
|
54
68
|
* then release the lane. Legacy run+ack flow when the ledger is unavailable.
|
|
69
|
+
*
|
|
70
|
+
* Repeated failures back off: a consume that ends un-acked re-arms the
|
|
71
|
+
* WorkItem's backoff entry, and the next attempt sleeps out the remaining
|
|
72
|
+
* window before claiming. Without this, complete's release re-drives the
|
|
73
|
+
* item instantly and a persistently-failing consume (e.g. buffered behind a
|
|
74
|
+
* saturated fork pool) spins at wire speed — the client half of the
|
|
75
|
+
* 2026-07-11 poison loop (the server half is the redrive budget).
|
|
55
76
|
*/
|
|
56
77
|
export declare function consumeTypedDispatch(host: LaneFlowHost, ref: {
|
|
57
78
|
dispatchEventId?: string;
|
|
58
79
|
sourceType?: string;
|
|
59
80
|
sourceId?: string;
|
|
60
|
-
}, run: (dispatchEventId?: string) => Promise<boolean>, ack: (dispatchEventId?: string) => void | Promise<void>): Promise<void>;
|
|
81
|
+
}, run: (dispatchEventId?: string) => Promise<boolean>, ack: (dispatchEventId?: string) => boolean | void | Promise<boolean | void>): Promise<void>;
|
|
61
82
|
/**
|
|
62
83
|
* Shared consumption of a message WorkItem referenced by id — the ONE
|
|
63
84
|
* protocol for dispatch catch-up pages and post-complete re-drive hints
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-lane-flow.d.ts","sourceRoot":"","sources":["../src/gateway-lane-flow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAEtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;GAKG;AAEH,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE;QACJ,MAAM,EAAE,YAAY,CAAC;QACrB,GAAG,CAAC,EAAE,aAAa,CAAC;QACpB,MAAM,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3B,eAAe,EAAE,eAAe,CAAC;QACjC,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC;IAC5C,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,WAAW,CACT,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,aAAa,CAAC,EAAE,WAAW,EAAE,EAC7B,WAAW,CAAC,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACrC,4BAA4B,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACpC,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1D;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE;IACJ,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,OAAO,CAAC;CAC7B,GACA,OAAO,CAAC,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"gateway-lane-flow.d.ts","sourceRoot":"","sources":["../src/gateway-lane-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,6 +40,9 @@ export async function dispatchLaneGroup(host, opts) {
|
|
|
40
40
|
}
|
|
41
41
|
return 'foreign';
|
|
42
42
|
}
|
|
43
|
+
// Register the session's active lane so external activity signals
|
|
44
|
+
// (touchRuntimeActivity from adapter hooks) renew exactly this lane.
|
|
45
|
+
host.noteSessionLane(opts.sessionKey, lane.laneKey);
|
|
43
46
|
let dispatched = false;
|
|
44
47
|
try {
|
|
45
48
|
dispatched = await host.runDispatch(event, opts.sessionKey, opts.body, opts.earlier, opts.captureText);
|
|
@@ -47,28 +50,133 @@ export async function dispatchLaneGroup(host, opts) {
|
|
|
47
50
|
catch (err) {
|
|
48
51
|
// Failed turn: hand the members back so the retry (this pod or the
|
|
49
52
|
// next) re-claims immediately instead of waiting out the lease.
|
|
53
|
+
host.noteSessionLane(opts.sessionKey, null);
|
|
50
54
|
await ledger.release(lane.laneKey).catch(() => { });
|
|
51
55
|
throw err;
|
|
52
56
|
}
|
|
57
|
+
finally {
|
|
58
|
+
if (dispatched)
|
|
59
|
+
host.noteSessionLane(opts.sessionKey, null);
|
|
60
|
+
}
|
|
53
61
|
if (!dispatched) {
|
|
54
62
|
// Shutdown short-circuit — shutdown() releases all active lanes.
|
|
55
63
|
return 'shutdown';
|
|
56
64
|
}
|
|
65
|
+
if (host.consumeTurnError(opts.sessionKey)) {
|
|
66
|
+
// An error turn must not no_action-sweep its members — settle the lane
|
|
67
|
+
// NOW with an error complete so they release for retry on the redrive
|
|
68
|
+
// budget (dispatch-convergence-design.md §3). Settling immediately (even
|
|
69
|
+
// with same-lane work still buffered) is deliberate: carrying the error
|
|
70
|
+
// across buffered turns would let a later reply broad-cover the failed
|
|
71
|
+
// member, or requeue the later turn's successful work. Released members
|
|
72
|
+
// rejoin the next claim, merged with whatever was buffered. Dropping the
|
|
73
|
+
// local dedupe claims lets the server's re-drive hint retrigger the
|
|
74
|
+
// messages immediately instead of waiting out the renotify pacing.
|
|
75
|
+
ledger.markTurnError(lane.laneKey);
|
|
76
|
+
// Clear dedupe for EVERY lane member, not just this batch: an earlier
|
|
77
|
+
// successful batch may have deferred its complete via hasMoreLocal, so
|
|
78
|
+
// the error complete below releases those members too — their redrive
|
|
79
|
+
// would be permanently blocked by a stale local claim.
|
|
80
|
+
for (const msgId of lane.folded.keys()) {
|
|
81
|
+
host.dispatchedMessages.delete(msgId);
|
|
82
|
+
}
|
|
83
|
+
// Invalidate any armed steer state before settling: a pending injection
|
|
84
|
+
// left over from the failed turn would make the retry claim enter the
|
|
85
|
+
// "already injected" path, produce an empty turn, and no_action-sweep the
|
|
86
|
+
// released members without ever retrying them. abortDispatch is the
|
|
87
|
+
// adapter contract's idempotent "clear pending steer state" hook.
|
|
88
|
+
try {
|
|
89
|
+
host.opts.dispatchAdapter.abortDispatch?.(opts.sessionKey);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// best-effort — a throwing abort must not block the error settlement
|
|
93
|
+
}
|
|
94
|
+
await ledger.completeIfIdle(lane.laneKey, false);
|
|
95
|
+
// 'failed' — callers must NOT record these events as handled: the server
|
|
96
|
+
// just released them for redelivery, and an "already handled" fork prefix
|
|
97
|
+
// (or a consumed fork summary) on the redrive would be a lie.
|
|
98
|
+
return 'failed';
|
|
99
|
+
}
|
|
57
100
|
const pendingInjections = host.opts.dispatchAdapter.hasPendingInjections?.(opts.sessionKey) ?? false;
|
|
58
101
|
await ledger.completeIfIdle(lane.laneKey, pendingInjections || opts.hasMoreLocal());
|
|
59
102
|
return 'dispatched';
|
|
60
103
|
}
|
|
104
|
+
/** Failure backoff pacing for typed dispatch retries (base 2s, cap 5min). */
|
|
105
|
+
const TYPED_BACKOFF_BASE_MS = 2_000;
|
|
106
|
+
const TYPED_BACKOFF_CAP_MS = 5 * 60_000;
|
|
107
|
+
const TYPED_BACKOFF_MAP_CAP = 512;
|
|
61
108
|
/**
|
|
62
109
|
* Consume one typed dispatch (task/comment/schedule/trigger/approval) under
|
|
63
110
|
* its typed-lane occupancy guard: claim the dsp:<id> lane (skip when another
|
|
64
111
|
* pod holds it or the WorkItem is already resolved), run the handler, ack on
|
|
65
112
|
* success (the doc's option (b): notification delivered, tracked elsewhere),
|
|
66
113
|
* then release the lane. Legacy run+ack flow when the ledger is unavailable.
|
|
114
|
+
*
|
|
115
|
+
* Repeated failures back off: a consume that ends un-acked re-arms the
|
|
116
|
+
* WorkItem's backoff entry, and the next attempt sleeps out the remaining
|
|
117
|
+
* window before claiming. Without this, complete's release re-drives the
|
|
118
|
+
* item instantly and a persistently-failing consume (e.g. buffered behind a
|
|
119
|
+
* saturated fork pool) spins at wire speed — the client half of the
|
|
120
|
+
* 2026-07-11 poison loop (the server half is the redrive budget).
|
|
67
121
|
*/
|
|
68
122
|
export async function consumeTypedDispatch(host, ref, run, ack) {
|
|
123
|
+
const backoffKey = ref.dispatchEventId ?? `${ref.sourceType}:${ref.sourceId}`;
|
|
124
|
+
const armed = host.typedRedriveBackoff.get(backoffKey);
|
|
125
|
+
if (armed) {
|
|
126
|
+
const waitMs = armed.until - Date.now();
|
|
127
|
+
if (waitMs > 0) {
|
|
128
|
+
host.opts.log?.info(`typed dispatch ${backoffKey} backing off ${Math.ceil(waitMs / 1000)}s after ${armed.failures} failed consume(s)`);
|
|
129
|
+
// unref: the wait must never be what keeps the process alive — on
|
|
130
|
+
// SIGTERM the gateway drains and exits while this timer is pending
|
|
131
|
+
// (the re-drive/renotify path re-delivers on the next pod).
|
|
132
|
+
await new Promise((resolve) => {
|
|
133
|
+
const timer = setTimeout(resolve, waitMs);
|
|
134
|
+
timer.unref?.();
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (host.shuttingDown)
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// An ack callback that returns void (legacy custom acks) counts as success;
|
|
141
|
+
// an explicit false (ackDispatchEvent's failed HTTP ack) is a failed
|
|
142
|
+
// consume — clearing backoff there would let an ack outage re-create the
|
|
143
|
+
// wire-speed release/re-drive loop against a pre-budget server.
|
|
144
|
+
const settleAck = (ackResult) => ackResult !== false;
|
|
145
|
+
const settle = (acked) => {
|
|
146
|
+
if (acked) {
|
|
147
|
+
host.typedRedriveBackoff.delete(backoffKey);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const failures = (host.typedRedriveBackoff.get(backoffKey)?.failures ?? 0) + 1;
|
|
151
|
+
const backoffMs = Math.min(TYPED_BACKOFF_CAP_MS, TYPED_BACKOFF_BASE_MS * 2 ** (failures - 1));
|
|
152
|
+
// True LRU: delete-then-set moves an updated key to the tail of the
|
|
153
|
+
// Map's insertion order, so capacity eviction always removes the
|
|
154
|
+
// least-recently-FAILING key — an actively-failing old key must not be
|
|
155
|
+
// evicted ahead of a quieter newer one. Evict only when inserting a new
|
|
156
|
+
// key at capacity (an in-place update never shrinks the map).
|
|
157
|
+
if (host.typedRedriveBackoff.delete(backoffKey) === false &&
|
|
158
|
+
host.typedRedriveBackoff.size >= TYPED_BACKOFF_MAP_CAP) {
|
|
159
|
+
const oldest = host.typedRedriveBackoff.keys().next().value;
|
|
160
|
+
if (oldest !== undefined)
|
|
161
|
+
host.typedRedriveBackoff.delete(oldest);
|
|
162
|
+
}
|
|
163
|
+
host.typedRedriveBackoff.set(backoffKey, { failures, until: Date.now() + backoffMs });
|
|
164
|
+
};
|
|
165
|
+
// Legacy run+ack (no ledger): same settle-in-finally contract as the lane
|
|
166
|
+
// path — a thrown run/ack must arm backoff, not skip it.
|
|
167
|
+
const runLegacy = async () => {
|
|
168
|
+
let acked = false;
|
|
169
|
+
try {
|
|
170
|
+
if (await run(ref.dispatchEventId)) {
|
|
171
|
+
acked = settleAck(await ack(ref.dispatchEventId));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
settle(acked);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
69
178
|
if (!host.laneLedger || host.ledgerDisabled) {
|
|
70
|
-
|
|
71
|
-
await ack(ref.dispatchEventId);
|
|
179
|
+
await runLegacy();
|
|
72
180
|
return;
|
|
73
181
|
}
|
|
74
182
|
let lane;
|
|
@@ -78,24 +186,28 @@ export async function consumeTypedDispatch(host, ref, run, ack) {
|
|
|
78
186
|
catch (err) {
|
|
79
187
|
if (err instanceof LedgerUnsupportedError) {
|
|
80
188
|
host.disableLedger('claim endpoint missing');
|
|
81
|
-
|
|
82
|
-
await ack(ref.dispatchEventId);
|
|
189
|
+
await runLegacy();
|
|
83
190
|
return;
|
|
84
191
|
}
|
|
85
192
|
throw err;
|
|
86
193
|
}
|
|
87
194
|
if (!lane) {
|
|
195
|
+
// Held elsewhere or already resolved — not a local failure; leave the
|
|
196
|
+
// backoff state as-is (a stale entry is cleared by the next local ack).
|
|
88
197
|
host.opts.log?.info(`typed dispatch ${ref.dispatchEventId ?? `${ref.sourceType}:${ref.sourceId}`} not claimable (held elsewhere or already resolved) — skipping`);
|
|
89
198
|
return;
|
|
90
199
|
}
|
|
200
|
+
let acked = false;
|
|
91
201
|
try {
|
|
92
202
|
// Ack must settle before Complete. A fire-and-forget ack races the lane
|
|
93
203
|
// release: Complete can return the still-received typed item to pending
|
|
94
204
|
// and publish a re-drive while its successful ack is still in flight.
|
|
95
|
-
if (await run(lane.typedDispatchEventId))
|
|
96
|
-
await ack(lane.typedDispatchEventId);
|
|
205
|
+
if (await run(lane.typedDispatchEventId)) {
|
|
206
|
+
acked = settleAck(await ack(lane.typedDispatchEventId));
|
|
207
|
+
}
|
|
97
208
|
}
|
|
98
209
|
finally {
|
|
210
|
+
settle(acked);
|
|
99
211
|
// Release the occupancy row. A buffered dispatch may outlive this guard
|
|
100
212
|
// (lane TTL) — acceptable at-least-once; the ledger's resolution paths
|
|
101
213
|
// still dedupe the persistent side effects.
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './provider-config.js';
|
|
|
2
2
|
export * from './types.js';
|
|
3
3
|
export * from './lane-key.js';
|
|
4
4
|
export type { LaneFlowHost } from './gateway-lane-flow.js';
|
|
5
|
+
export { consumeTypedDispatch } from './gateway-lane-flow.js';
|
|
5
6
|
export * from './session-state.js';
|
|
6
7
|
export * from './routing.js';
|
|
7
8
|
export * from './event-format.js';
|
|
@@ -11,6 +12,8 @@ export * from './dispatch-adapter.js';
|
|
|
11
12
|
export { createLogger, childLogger } from './logger.js';
|
|
12
13
|
export * from './gateway-base.js';
|
|
13
14
|
export * from './platform-config.js';
|
|
15
|
+
export * from './channel-capability.js';
|
|
16
|
+
export * from './channel-token.js';
|
|
14
17
|
export { writeSkillFiles, buildSkillReferences, SKILLS } from './skills/index.js';
|
|
15
18
|
export type { SkillMeta } from './skills/index.js';
|
|
16
19
|
export { initAgentTelemetry, createOtelLogger, runWithSessionKey, startDispatchSpan, endDispatchSpan, recordDispatchMetric, recordMissingReply, } from './telemetry.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './provider-config.js';
|
|
2
2
|
export * from './types.js';
|
|
3
3
|
export * from './lane-key.js';
|
|
4
|
+
export { consumeTypedDispatch } from './gateway-lane-flow.js';
|
|
4
5
|
export * from './session-state.js';
|
|
5
6
|
export * from './routing.js';
|
|
6
7
|
export * from './event-format.js';
|
|
@@ -10,5 +11,7 @@ export * from './dispatch-adapter.js';
|
|
|
10
11
|
export { createLogger, childLogger } from './logger.js';
|
|
11
12
|
export * from './gateway-base.js';
|
|
12
13
|
export * from './platform-config.js';
|
|
14
|
+
export * from './channel-capability.js';
|
|
15
|
+
export * from './channel-token.js';
|
|
13
16
|
export { writeSkillFiles, buildSkillReferences, SKILLS } from './skills/index.js';
|
|
14
17
|
export { initAgentTelemetry, createOtelLogger, runWithSessionKey, startDispatchSpan, endDispatchSpan, recordDispatchMetric, recordMissingReply, } from './telemetry.js';
|
package/dist/lane-ledger.d.ts
CHANGED
|
@@ -14,6 +14,13 @@ export type ActiveLane = {
|
|
|
14
14
|
/** Lease expiry (ms epoch) and TTL from the claim — renewal pacing state. */
|
|
15
15
|
leaseUntilMs?: number;
|
|
16
16
|
leaseTtlMs?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Sticky error bit: some turn on this lane surfaced a runtime error. Read
|
|
19
|
+
* (and only cleared) by the lane's final complete, so an error outcome
|
|
20
|
+
* survives buffered same-lane turns in between — a later successful turn
|
|
21
|
+
* must not no_action-sweep the failed turn's members.
|
|
22
|
+
*/
|
|
23
|
+
turnError?: boolean;
|
|
17
24
|
};
|
|
18
25
|
/**
|
|
19
26
|
* Thrown when the server predates the dispatch ledger (claim endpoint 404s
|
|
@@ -71,7 +78,22 @@ export declare class LaneLedger {
|
|
|
71
78
|
* re-drives any same-target pending work. A STALE_LANE answer means a
|
|
72
79
|
* takeover already owns the resource — local state is dropped either way.
|
|
73
80
|
*/
|
|
81
|
+
/**
|
|
82
|
+
* Record that the turn on this lane surfaced a runtime error. The flow
|
|
83
|
+
* settles an errored lane immediately (dispatchLaneGroup returns 'failed'
|
|
84
|
+
* after a forced complete), so the bit normally lives for one turn only —
|
|
85
|
+
* it is the transport between the gateway's per-session error signal and
|
|
86
|
+
* this lane's complete request.
|
|
87
|
+
*/
|
|
88
|
+
markTurnError(laneKey: string): void;
|
|
74
89
|
completeIfIdle(laneKey: string, hasMoreLocal: boolean): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Renew one lane by its key — the external runtime-activity hook for
|
|
92
|
+
* adapters whose tool traffic bypasses the RuntimeEvent stream (openclaw
|
|
93
|
+
* hooks). Scoped to the session's own lane: renewing every lane would let
|
|
94
|
+
* one busy fork keep an unrelated stalled fork's lane leased forever.
|
|
95
|
+
*/
|
|
96
|
+
renewByKey(laneKey: string): void;
|
|
75
97
|
/**
|
|
76
98
|
* Long-turn keepalive: renew the lane's lease on runtime activity, throttled
|
|
77
99
|
* so a chatty turn doesn't spam the server. Without this, a legitimately
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lane-ledger.d.ts","sourceRoot":"","sources":["../src/lane-ledger.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,sDAAsD;AACtD,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,6EAA6E;IAC7E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;GAIG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;CAAG;AAEpD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;AAqBrD;;;;;;;;;;;GAWG;AACH,qBAAa,UAAU;IAInB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;gBAGpC,IAAI,EAAE;QACrB,MAAM,EAAE,YAAY,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,CAAC,EAAE,aAAa,CAAC;KACrB;IAGH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,+FAA+F;IAC/F,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO;IAIpC,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM;IAOtC,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS;IAIvD,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAIzC;;;;;;OAMG;IACG,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"lane-ledger.d.ts","sourceRoot":"","sources":["../src/lane-ledger.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,sDAAsD;AACtD,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,6EAA6E;IAC7E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF;;;;GAIG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;CAAG;AAEpD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;AAqBrD;;;;;;;;;;;GAWG;AACH,qBAAa,UAAU;IAInB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;gBAGpC,IAAI,EAAE;QACrB,MAAM,EAAE,YAAY,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,CAAC,EAAE,aAAa,CAAC;KACrB;IAGH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,+FAA+F;IAC/F,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO;IAIpC,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM;IAOtC,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS;IAIvD,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAIzC;;;;;;OAMG;IACG,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAsFnE;;;;;OAKG;IACG,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IA0BrD;;;;;OAKG;IACH;;;;;;OAMG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK9B,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B3E;;;;;OAKG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKjC;;;;;;;OAOG;IACH,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IA6BlC;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAOjC,yEAAyE;IACzE,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;;;;OAKG;IACG,UAAU,CAAC,GAAG,EAAE;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA8B9B;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;CAW1B"}
|