@rivus/agent 0.5.1 → 0.6.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/acp.js +11 -1
- package/dist/cli.js +2 -1
- package/dist/index.d.ts +254 -32
- package/dist/index.js +429 -187
- package/dist/rivus-daemon-cli.js +333 -2
- package/examples/pi-feishu-deployment.bootstrap.ts +16 -12
- package/package.json +1 -1
package/dist/rivus-daemon-cli.js
CHANGED
|
@@ -313,6 +313,331 @@ function required$1(env, variable) {
|
|
|
313
313
|
return value;
|
|
314
314
|
}
|
|
315
315
|
//#endregion
|
|
316
|
+
//#region src/domain/card-presentation.ts
|
|
317
|
+
var CardPresentationTransitionDenied = class extends Error {
|
|
318
|
+
name = "CardPresentationTransitionDenied";
|
|
319
|
+
};
|
|
320
|
+
const STREAMING_STATUSES = /* @__PURE__ */ new Set(["streaming", "active"]);
|
|
321
|
+
function createCardPresentationChain(binding) {
|
|
322
|
+
assertTimestamp(binding.createdAt, "presentation creation time");
|
|
323
|
+
assertTimestamp(binding.leaseDeadlineAt, "presentation lease deadline");
|
|
324
|
+
return {
|
|
325
|
+
activeGeneration: 0,
|
|
326
|
+
activePresentationId: binding.presentationId,
|
|
327
|
+
presentations: [{
|
|
328
|
+
cardId: binding.cardId,
|
|
329
|
+
createdAt: binding.createdAt,
|
|
330
|
+
...binding.elementId === void 0 ? {} : { elementId: binding.elementId },
|
|
331
|
+
generation: 0,
|
|
332
|
+
leaseDeadlineAt: binding.leaseDeadlineAt,
|
|
333
|
+
presentationId: binding.presentationId,
|
|
334
|
+
runId: binding.runId,
|
|
335
|
+
sourceMessageId: binding.sourceMessageId,
|
|
336
|
+
status: "streaming"
|
|
337
|
+
}],
|
|
338
|
+
revision: 1,
|
|
339
|
+
runId: binding.runId
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
function activeCardPresentation(chain) {
|
|
343
|
+
const presentation = chain.presentations.find((candidate) => candidate.presentationId === chain.activePresentationId);
|
|
344
|
+
if (!presentation) throw new CardPresentationTransitionDenied(`presentation chain ${chain.runId} has no active presentation`);
|
|
345
|
+
return presentation;
|
|
346
|
+
}
|
|
347
|
+
function acceptsCardPresentationProgress(chain) {
|
|
348
|
+
return STREAMING_STATUSES.has(activeCardPresentation(chain).status);
|
|
349
|
+
}
|
|
350
|
+
function isCardPresentationHandoffDue(chain, now) {
|
|
351
|
+
const presentation = activeCardPresentation(chain);
|
|
352
|
+
return STREAMING_STATUSES.has(presentation.status) && Date.parse(presentation.leaseDeadlineAt) <= Date.parse(now);
|
|
353
|
+
}
|
|
354
|
+
function beginCardPresentationHandoff(chain, handoffAt) {
|
|
355
|
+
assertTimestamp(handoffAt, "handoff time");
|
|
356
|
+
const presentation = activeCardPresentation(chain);
|
|
357
|
+
if (presentation.status === "handoff-pending") return chain;
|
|
358
|
+
if (!STREAMING_STATUSES.has(presentation.status)) throw new CardPresentationTransitionDenied(`presentation ${presentation.presentationId} is ${presentation.status} and cannot start a handoff`);
|
|
359
|
+
return replaceActivePresentation(chain, {
|
|
360
|
+
...presentation,
|
|
361
|
+
handoffAt,
|
|
362
|
+
status: "handoff-pending"
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
function completeCardPresentationHandoff(chain, successor) {
|
|
366
|
+
assertTimestamp(successor.createdAt, "successor creation time");
|
|
367
|
+
assertTimestamp(successor.leaseDeadlineAt, "successor lease deadline");
|
|
368
|
+
const predecessor = activeCardPresentation(chain);
|
|
369
|
+
if (predecessor.status !== "handoff-pending") throw new CardPresentationTransitionDenied(`presentation ${predecessor.presentationId} is ${predecessor.status} and cannot adopt a successor`);
|
|
370
|
+
if (predecessor.successorPresentationId !== void 0) throw new CardPresentationTransitionDenied(`presentation ${predecessor.presentationId} already has successor ${predecessor.successorPresentationId}`);
|
|
371
|
+
const generation = chain.activeGeneration + 1;
|
|
372
|
+
return {
|
|
373
|
+
...chain,
|
|
374
|
+
activeGeneration: generation,
|
|
375
|
+
activePresentationId: successor.presentationId,
|
|
376
|
+
presentations: [...chain.presentations.map((candidate) => candidate.presentationId === predecessor.presentationId ? {
|
|
377
|
+
...predecessor,
|
|
378
|
+
status: "closed",
|
|
379
|
+
successorPresentationId: successor.presentationId
|
|
380
|
+
} : candidate), {
|
|
381
|
+
cardId: successor.cardId,
|
|
382
|
+
createdAt: successor.createdAt,
|
|
383
|
+
...successor.elementId === void 0 ? {} : { elementId: successor.elementId },
|
|
384
|
+
generation,
|
|
385
|
+
leaseDeadlineAt: successor.leaseDeadlineAt,
|
|
386
|
+
predecessorPresentationId: predecessor.presentationId,
|
|
387
|
+
presentationId: successor.presentationId,
|
|
388
|
+
runId: chain.runId,
|
|
389
|
+
sourceMessageId: predecessor.sourceMessageId,
|
|
390
|
+
status: "active"
|
|
391
|
+
}],
|
|
392
|
+
revision: chain.revision + 1
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
function failCardPresentationHandoff(chain, failedAt) {
|
|
396
|
+
assertTimestamp(failedAt, "handoff failure time");
|
|
397
|
+
const presentation = activeCardPresentation(chain);
|
|
398
|
+
if (presentation.status !== "handoff-pending") throw new CardPresentationTransitionDenied(`presentation ${presentation.presentationId} is ${presentation.status} and has no pending handoff`);
|
|
399
|
+
return replaceActivePresentation(chain, {
|
|
400
|
+
...presentation,
|
|
401
|
+
handoffFailedAt: failedAt,
|
|
402
|
+
status: "closed"
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
function compensateCardPresentationHandoff(chain, compensatedAt) {
|
|
406
|
+
return activeCardPresentation(chain).status === "handoff-pending" ? failCardPresentationHandoff(chain, compensatedAt) : chain;
|
|
407
|
+
}
|
|
408
|
+
function markCardPresentationTerminal(chain, terminalReceiptId) {
|
|
409
|
+
if (terminalReceiptId.trim().length === 0) throw new CardPresentationTransitionDenied("terminal receipt id must not be empty");
|
|
410
|
+
const presentation = activeCardPresentation(chain);
|
|
411
|
+
if (presentation.status === "terminal") return chain;
|
|
412
|
+
return replaceActivePresentation(chain, {
|
|
413
|
+
...presentation,
|
|
414
|
+
status: "terminal",
|
|
415
|
+
terminalReceiptId
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
function replaceActivePresentation(chain, presentation) {
|
|
419
|
+
return {
|
|
420
|
+
...chain,
|
|
421
|
+
presentations: chain.presentations.map((candidate) => candidate.presentationId === presentation.presentationId ? presentation : candidate),
|
|
422
|
+
revision: chain.revision + 1
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
function assertTimestamp(value, label) {
|
|
426
|
+
if (Number.isNaN(Date.parse(value))) throw new CardPresentationTransitionDenied(`${label} must be an ISO timestamp`);
|
|
427
|
+
}
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/application/feishu/feishu-card-rollover.ts
|
|
430
|
+
const DEFAULT_CARD_STREAM_LEASE_MS = 51e4;
|
|
431
|
+
function createFeishuCardRollover(options) {
|
|
432
|
+
const leaseMs = options.leaseMs ?? 51e4;
|
|
433
|
+
if (!Number.isSafeInteger(leaseMs) || leaseMs < 1) throw new Error("Feishu card stream lease must be a positive integer");
|
|
434
|
+
const counters = createCounters();
|
|
435
|
+
const liveRuns = /* @__PURE__ */ new Map();
|
|
436
|
+
const semaphore = Effect.unsafeMakeSemaphore(1);
|
|
437
|
+
const exclusive = (effect) => semaphore.withPermits(1)(effect);
|
|
438
|
+
const record = (event, at) => {
|
|
439
|
+
counters[event.type] += 1;
|
|
440
|
+
options.observe?.({
|
|
441
|
+
...event,
|
|
442
|
+
at: at.toISOString()
|
|
443
|
+
});
|
|
444
|
+
};
|
|
445
|
+
const recordNow = (event) => options.clock.now.pipe(Effect.map((at) => record(event, at)));
|
|
446
|
+
const leaseDeadline = (at) => new Date(at.getTime() + leaseMs).toISOString();
|
|
447
|
+
const presentationId = (runId, generation) => `${runId}#${generation}`;
|
|
448
|
+
const publishProgress = (action) => Effect.suspend(() => {
|
|
449
|
+
const chain = options.store.chain(action.runId);
|
|
450
|
+
if (chain && acceptsCardPresentationProgress(chain)) return options.publisher.publish(action);
|
|
451
|
+
return recordNow({
|
|
452
|
+
...chain ? {
|
|
453
|
+
generation: chain.activeGeneration,
|
|
454
|
+
presentationId: chain.activePresentationId
|
|
455
|
+
} : {},
|
|
456
|
+
runId: action.runId,
|
|
457
|
+
type: "stale_update_dropped"
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
const publishTerminal = (action) => options.publisher.publish(action).pipe(Effect.tapError((error) => recordNow({
|
|
461
|
+
error,
|
|
462
|
+
runId: action.runId,
|
|
463
|
+
type: "terminal_delivery_failed"
|
|
464
|
+
})), Effect.tap(() => options.store.markTerminal({
|
|
465
|
+
runId: action.runId,
|
|
466
|
+
terminalReceiptId: `${action.runId}:${action.type}`
|
|
467
|
+
}).pipe(Effect.catchAll((error) => recordNow({
|
|
468
|
+
error,
|
|
469
|
+
runId: action.runId,
|
|
470
|
+
type: "presentation_write_failed"
|
|
471
|
+
})))), Effect.ensuring(Effect.sync(() => {
|
|
472
|
+
liveRuns.delete(action.runId);
|
|
473
|
+
})));
|
|
474
|
+
const publishAction = (action) => {
|
|
475
|
+
switch (action.type) {
|
|
476
|
+
case "update_text": return publishProgress(action);
|
|
477
|
+
case "handoff": return options.publisher.publish(action);
|
|
478
|
+
default: return publishTerminal(action);
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
const runHandoff = (runId) => Effect.gen(function* () {
|
|
482
|
+
const run = liveRuns.get(runId);
|
|
483
|
+
if (!run) return {
|
|
484
|
+
reason: "not-live",
|
|
485
|
+
status: "skipped"
|
|
486
|
+
};
|
|
487
|
+
const startedAt = yield* options.clock.now;
|
|
488
|
+
const chain = options.store.chain(runId);
|
|
489
|
+
if (!chain || !isCardPresentationHandoffDue(chain, startedAt.toISOString())) return {
|
|
490
|
+
reason: "not-due",
|
|
491
|
+
status: "skipped"
|
|
492
|
+
};
|
|
493
|
+
const start = yield* options.store.beginHandoff({
|
|
494
|
+
handoffAt: startedAt.toISOString(),
|
|
495
|
+
runId
|
|
496
|
+
}).pipe(Effect.catchAll(() => Effect.succeed(void 0)));
|
|
497
|
+
if (!start) return {
|
|
498
|
+
reason: "not-streaming",
|
|
499
|
+
status: "skipped"
|
|
500
|
+
};
|
|
501
|
+
if (!start.started) return {
|
|
502
|
+
reason: "already-pending",
|
|
503
|
+
status: "skipped"
|
|
504
|
+
};
|
|
505
|
+
const predecessor = start.presentation;
|
|
506
|
+
const generation = predecessor.generation + 1;
|
|
507
|
+
record({
|
|
508
|
+
cardId: predecessor.cardId,
|
|
509
|
+
generation,
|
|
510
|
+
presentationId: predecessor.presentationId,
|
|
511
|
+
runId,
|
|
512
|
+
sourceMessageId: predecessor.sourceMessageId,
|
|
513
|
+
type: "handoff_started"
|
|
514
|
+
}, startedAt);
|
|
515
|
+
const successorId = presentationId(runId, generation);
|
|
516
|
+
const created = yield* options.createSuccessor({
|
|
517
|
+
generation,
|
|
518
|
+
presentationId: successorId,
|
|
519
|
+
run
|
|
520
|
+
}).pipe(Effect.map((target) => ({ target })), Effect.catchAll((error) => options.store.failHandoff({
|
|
521
|
+
failedAt: startedAt.toISOString(),
|
|
522
|
+
runId
|
|
523
|
+
}).pipe(Effect.catchAll((storeError) => recordNow({
|
|
524
|
+
error: storeError,
|
|
525
|
+
runId,
|
|
526
|
+
type: "presentation_write_failed"
|
|
527
|
+
})), Effect.flatMap(() => recordNow({
|
|
528
|
+
cardId: predecessor.cardId,
|
|
529
|
+
error,
|
|
530
|
+
generation,
|
|
531
|
+
presentationId: predecessor.presentationId,
|
|
532
|
+
runId,
|
|
533
|
+
type: "handoff_failed"
|
|
534
|
+
})), Effect.as({ error }))));
|
|
535
|
+
if ("error" in created) return {
|
|
536
|
+
error: created.error,
|
|
537
|
+
status: "failed"
|
|
538
|
+
};
|
|
539
|
+
yield* options.publisher.publish({
|
|
540
|
+
runId,
|
|
541
|
+
type: "handoff"
|
|
542
|
+
}).pipe(Effect.catchAll((error) => recordNow({
|
|
543
|
+
cardId: predecessor.cardId,
|
|
544
|
+
error,
|
|
545
|
+
generation,
|
|
546
|
+
runId,
|
|
547
|
+
type: "handoff_notice_failed"
|
|
548
|
+
})));
|
|
549
|
+
const adoptedAt = yield* options.clock.now;
|
|
550
|
+
const presentation = yield* options.store.completeHandoff({
|
|
551
|
+
runId,
|
|
552
|
+
successor: {
|
|
553
|
+
cardId: created.target.cardId,
|
|
554
|
+
createdAt: adoptedAt.toISOString(),
|
|
555
|
+
...created.target.elementId === void 0 ? {} : { elementId: created.target.elementId },
|
|
556
|
+
leaseDeadlineAt: leaseDeadline(adoptedAt),
|
|
557
|
+
presentationId: successorId
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
record({
|
|
561
|
+
cardId: predecessor.cardId,
|
|
562
|
+
generation,
|
|
563
|
+
presentationId: successorId,
|
|
564
|
+
runId,
|
|
565
|
+
sourceMessageId: predecessor.sourceMessageId,
|
|
566
|
+
successorCardId: created.target.cardId,
|
|
567
|
+
type: "handoff_succeeded"
|
|
568
|
+
}, adoptedAt);
|
|
569
|
+
return {
|
|
570
|
+
presentation,
|
|
571
|
+
status: "rolled-over"
|
|
572
|
+
};
|
|
573
|
+
});
|
|
574
|
+
return {
|
|
575
|
+
bindRun: (run, target) => exclusive(Effect.gen(function* () {
|
|
576
|
+
const createdAt = yield* options.clock.now;
|
|
577
|
+
const presentation = yield* options.store.bind({
|
|
578
|
+
cardId: target.cardId,
|
|
579
|
+
createdAt: createdAt.toISOString(),
|
|
580
|
+
...target.elementId === void 0 ? {} : { elementId: target.elementId },
|
|
581
|
+
leaseDeadlineAt: leaseDeadline(createdAt),
|
|
582
|
+
presentationId: presentationId(run.runId, 0),
|
|
583
|
+
runId: run.runId,
|
|
584
|
+
sourceMessageId: run.messageId
|
|
585
|
+
});
|
|
586
|
+
liveRuns.set(run.runId, run);
|
|
587
|
+
return presentation;
|
|
588
|
+
})),
|
|
589
|
+
dueRunIds: (now) => {
|
|
590
|
+
const nowIso = now.toISOString();
|
|
591
|
+
return [...liveRuns.keys()].filter((runId) => {
|
|
592
|
+
const chain = options.store.chain(runId);
|
|
593
|
+
return chain !== void 0 && isCardPresentationHandoffDue(chain, nowIso);
|
|
594
|
+
});
|
|
595
|
+
},
|
|
596
|
+
flush: (runId) => exclusive(options.publisher.flush(runId)),
|
|
597
|
+
handoff: (runId) => exclusive(runHandoff(runId)),
|
|
598
|
+
observeStreamClosed: (cardId) => {
|
|
599
|
+
counters.stream_closed += 1;
|
|
600
|
+
options.observe?.({
|
|
601
|
+
cardId,
|
|
602
|
+
type: "stream_closed"
|
|
603
|
+
});
|
|
604
|
+
},
|
|
605
|
+
publish: (action) => exclusive(publishAction(action)),
|
|
606
|
+
recover: () => exclusive(Effect.gen(function* () {
|
|
607
|
+
const compensatedAt = yield* options.clock.now;
|
|
608
|
+
const compensated = yield* options.store.compensateInterruptedHandoffs(compensatedAt.toISOString());
|
|
609
|
+
for (const chain of compensated) record({
|
|
610
|
+
generation: chain.activeGeneration,
|
|
611
|
+
presentationId: chain.activePresentationId,
|
|
612
|
+
runId: chain.runId,
|
|
613
|
+
type: "handoff_failed"
|
|
614
|
+
}, compensatedAt);
|
|
615
|
+
return { compensated: compensated.length };
|
|
616
|
+
})),
|
|
617
|
+
status: () => ({
|
|
618
|
+
counters: { ...counters },
|
|
619
|
+
leaseMs,
|
|
620
|
+
live: [...liveRuns.keys()].flatMap((runId) => {
|
|
621
|
+
const chain = options.store.chain(runId);
|
|
622
|
+
if (!chain) return [];
|
|
623
|
+
return chain.presentations.filter((presentation) => presentation.presentationId === chain.activePresentationId);
|
|
624
|
+
})
|
|
625
|
+
})
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
function createCounters() {
|
|
629
|
+
return {
|
|
630
|
+
handoff_failed: 0,
|
|
631
|
+
handoff_notice_failed: 0,
|
|
632
|
+
handoff_started: 0,
|
|
633
|
+
handoff_succeeded: 0,
|
|
634
|
+
presentation_write_failed: 0,
|
|
635
|
+
stale_update_dropped: 0,
|
|
636
|
+
stream_closed: 0,
|
|
637
|
+
terminal_delivery_failed: 0
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
//#endregion
|
|
316
641
|
//#region src/infrastructure/config/rivus-deployment-manifest.ts
|
|
317
642
|
var RivusDeploymentManifestError = class extends Error {
|
|
318
643
|
manifestPath;
|
|
@@ -397,6 +722,7 @@ function parseManifest(value) {
|
|
|
397
722
|
exactKeys(endpoint, [
|
|
398
723
|
"agentId",
|
|
399
724
|
"baseUrl",
|
|
725
|
+
"cardStreamLeaseMs",
|
|
400
726
|
"credentialRef",
|
|
401
727
|
"enabled",
|
|
402
728
|
"experimental",
|
|
@@ -405,12 +731,13 @@ function parseManifest(value) {
|
|
|
405
731
|
"required",
|
|
406
732
|
"sessionNamespace",
|
|
407
733
|
"streamMinIntervalMs"
|
|
408
|
-
], `manifest.endpoints[${index}]`, ["experimental"]);
|
|
734
|
+
], `manifest.endpoints[${index}]`, ["cardStreamLeaseMs", "experimental"]);
|
|
409
735
|
const experimental = endpoint.experimental === void 0 ? void 0 : record(endpoint.experimental, `manifest.endpoints[${index}].experimental`);
|
|
410
736
|
if (experimental) exactKeys(experimental, ["cotMessages"], `manifest.endpoints[${index}].experimental`);
|
|
411
737
|
return Object.freeze({
|
|
412
738
|
agentId: string(endpoint.agentId, `manifest.endpoints[${index}].agentId`),
|
|
413
739
|
baseUrl: string(endpoint.baseUrl, `manifest.endpoints[${index}].baseUrl`),
|
|
740
|
+
cardStreamLeaseMs: endpoint.cardStreamLeaseMs === void 0 ? DEFAULT_CARD_STREAM_LEASE_MS : positiveInteger(endpoint.cardStreamLeaseMs, `manifest.endpoints[${index}].cardStreamLeaseMs`),
|
|
414
741
|
credentialRef: string(endpoint.credentialRef, `manifest.endpoints[${index}].credentialRef`),
|
|
415
742
|
enabled: boolean(endpoint.enabled, `manifest.endpoints[${index}].enabled`),
|
|
416
743
|
...experimental ? { experimental: Object.freeze({ cotMessages: boolean(experimental.cotMessages, `manifest.endpoints[${index}].experimental.cotMessages`) }) } : {},
|
|
@@ -561,6 +888,7 @@ function loadRivusDaemonConfig(env, options = {}) {
|
|
|
561
888
|
const appId = yield* required(env, "FEISHU_APP_ID");
|
|
562
889
|
const appSecret = yield* required(env, "FEISHU_APP_SECRET");
|
|
563
890
|
const streamMinIntervalMs = yield* optionalPositiveInteger(env.FEISHU_STREAM_MIN_INTERVAL_MS, "FEISHU_STREAM_MIN_INTERVAL_MS", DEFAULT_STREAM_MIN_INTERVAL_MS$1);
|
|
891
|
+
const cardStreamLeaseMs = yield* optionalPositiveInteger(env.FEISHU_CARD_STREAM_LEASE_MS, "FEISHU_CARD_STREAM_LEASE_MS", DEFAULT_CARD_STREAM_LEASE_MS);
|
|
564
892
|
const thinkingLevel = yield* optionalThinkingLevel(env.PI_THINKING_LEVEL);
|
|
565
893
|
const apiKey = yield* optionalPiApiKey(env, options.readTextFile ?? readUtf8File);
|
|
566
894
|
const baseUrl = optional(env.PI_BASE_URL);
|
|
@@ -571,6 +899,7 @@ function loadRivusDaemonConfig(env, options = {}) {
|
|
|
571
899
|
appId,
|
|
572
900
|
appSecret,
|
|
573
901
|
baseUrl: optional(env.FEISHU_BASE_URL) ?? DEFAULT_FEISHU_BASE_URL$1,
|
|
902
|
+
cardStreamLeaseMs,
|
|
574
903
|
streamMinIntervalMs
|
|
575
904
|
},
|
|
576
905
|
pi: {
|
|
@@ -1670,6 +1999,7 @@ Options:
|
|
|
1670
1999
|
Environment:
|
|
1671
2000
|
RIVUS_BOOTSTRAP_MODULE may be used instead of --bootstrap.
|
|
1672
2001
|
FEISHU_APP_ID and FEISHU_APP_SECRET are required by the default config loader.
|
|
2002
|
+
FEISHU_CARD_STREAM_LEASE_MS shortens or extends the proactive CardKit rollover threshold.
|
|
1673
2003
|
PI_API_KEY_FILE may point to a local BYOK key file instead of PI_API_KEY.
|
|
1674
2004
|
`;
|
|
1675
2005
|
const DEFAULT_WAIT_RECEIVE_TIMEOUT_MS = 3e4;
|
|
@@ -2587,6 +2917,7 @@ function toRedactedConfig(config) {
|
|
|
2587
2917
|
appIdPresent: Boolean(config.feishu.appId),
|
|
2588
2918
|
appSecretPresent: Boolean(config.feishu.appSecret),
|
|
2589
2919
|
baseUrl: config.feishu.baseUrl,
|
|
2920
|
+
cardStreamLeaseMs: config.feishu.cardStreamLeaseMs,
|
|
2590
2921
|
streamMinIntervalMs: config.feishu.streamMinIntervalMs
|
|
2591
2922
|
},
|
|
2592
2923
|
pi: {
|
|
@@ -2760,4 +3091,4 @@ function hasRecoveryRunner(daemon) {
|
|
|
2760
3091
|
return typeof daemon.openRecoveryControl === "function";
|
|
2761
3092
|
}
|
|
2762
3093
|
//#endregion
|
|
2763
|
-
export {
|
|
3094
|
+
export { CardPresentationTransitionDenied as A, FeishuEndpointCredentialError as B, loadRivusDaemonConfig as C, loadRivusDeploymentManifest as D, RivusDeploymentManifestError as E, completeCardPresentationHandoff as F, validateRivusDeploymentManifest as G, loadMergedLocalEnvFile as H, createCardPresentationChain as I, failCardPresentationHandoff as L, activeCardPresentation as M, beginCardPresentationHandoff as N, DEFAULT_CARD_STREAM_LEASE_MS as O, compensateCardPresentationHandoff as P, isCardPresentationHandoffDue as R, RivusDaemonConfigError as S, resolveNodeRivusPluginModulePath as T, RivusPluginLoadError as U, resolveFeishuEndpointCredentials as V, loadRivusDeployment as W, createStableId as _, InvalidRivusProjectSpace as a, createRivusEnvFromOpenClawConfig as b, RivusDeploymentReadinessError as c, createRivusAgentHost as d, AgentInstanceBusy as f, createAgentInstanceRegistry as g, AgentInstanceConflict as h, resolveRivusProjectSpace as i, acceptsCardPresentationProgress as j, createFeishuCardRollover as k, createRivusDeploymentDaemon as l, createAgentRuntimePool as m, createRivusDeploymentCliProcess as n, RivusDeploymentAutomationReadinessError as o, AgentRuntimeDisposed as p, createConfiguredRivusDeploymentDaemon as r, RivusDeploymentDaemonLifecycleError as s, runRivusDaemonCli as t, InvalidRivusEndpointBinding as u, createRivusDaemonShutdownController as v, loadNodeRivusPluginModule as w, formatRivusEnvFile as x, OpenClawEnvImportError as y, markCardPresentationTerminal as z };
|
|
@@ -16,14 +16,14 @@ import {
|
|
|
16
16
|
createAgentHarnessPooledRuntime,
|
|
17
17
|
createRivusMemoryToolDescriptor,
|
|
18
18
|
createConfiguredFeishuAutomationCardSender,
|
|
19
|
-
|
|
20
|
-
createConfiguredFeishuCardKitTargetPreparation,
|
|
19
|
+
createConfiguredFeishuCardRolloverRuntime,
|
|
21
20
|
createConfiguredFeishuHumanInteractionPresenter,
|
|
22
21
|
createConfiguredFeishuOpenApiClient,
|
|
23
22
|
createConfiguredFeishuTextReplySender,
|
|
24
23
|
createFeishuCotPublisher,
|
|
25
24
|
createFeishuDeploymentEndpoint,
|
|
26
25
|
createFeishuPresentationPreparation,
|
|
26
|
+
createSystemClock,
|
|
27
27
|
createFeishuCardDeliveryReconciler,
|
|
28
28
|
createHumanInteractionEndpointRegistry,
|
|
29
29
|
createHumanInteractionService,
|
|
@@ -43,7 +43,6 @@ import {
|
|
|
43
43
|
createRoutedHumanInteractionToolApprovalService,
|
|
44
44
|
createSessionScheduler,
|
|
45
45
|
createScheduledAutomation,
|
|
46
|
-
createSystemClock,
|
|
47
46
|
createToolBroker,
|
|
48
47
|
createUuidRunIds,
|
|
49
48
|
createWorkspaceRootHandle,
|
|
@@ -61,6 +60,7 @@ import {
|
|
|
61
60
|
type CreateRivusDeploymentAutomationInput,
|
|
62
61
|
type CreateRivusDeploymentRuntimeInput,
|
|
63
62
|
type ConfiguredFeishuOpenApiResponse,
|
|
63
|
+
type FeishuAgentRunPreparation,
|
|
64
64
|
type FeishuWebSocketClient,
|
|
65
65
|
type RivusDaemonConfig,
|
|
66
66
|
type RivusDeploymentBootstrapContext,
|
|
@@ -106,6 +106,7 @@ export async function createRivusDeploymentAdapters(context: RivusDeploymentBoot
|
|
|
106
106
|
feishu: {
|
|
107
107
|
...credentials,
|
|
108
108
|
baseUrl: input.deliveryEndpoint.baseUrl,
|
|
109
|
+
cardStreamLeaseMs: input.deliveryEndpoint.cardStreamLeaseMs,
|
|
109
110
|
streamMinIntervalMs: input.deliveryEndpoint.streamMinIntervalMs
|
|
110
111
|
},
|
|
111
112
|
pi: {}
|
|
@@ -176,6 +177,7 @@ export async function createRivusDeploymentAdapters(context: RivusDeploymentBoot
|
|
|
176
177
|
feishu: {
|
|
177
178
|
...credentials,
|
|
178
179
|
baseUrl: input.definition.baseUrl,
|
|
180
|
+
cardStreamLeaseMs: input.definition.cardStreamLeaseMs,
|
|
179
181
|
streamMinIntervalMs: input.definition.streamMinIntervalMs
|
|
180
182
|
},
|
|
181
183
|
pi: {}
|
|
@@ -198,14 +200,20 @@ export async function createRivusDeploymentAdapters(context: RivusDeploymentBoot
|
|
|
198
200
|
filePath: join(endpointState, "human-interactions.jsonl")
|
|
199
201
|
})
|
|
200
202
|
});
|
|
201
|
-
const
|
|
203
|
+
const cardRollover = createConfiguredFeishuCardRolloverRuntime({
|
|
202
204
|
agentName: input.agentId,
|
|
205
|
+
cardTargets,
|
|
203
206
|
client: openApiClient,
|
|
207
|
+
clock: createSystemClock(),
|
|
204
208
|
config,
|
|
205
209
|
ledger: cardLedger,
|
|
206
|
-
|
|
207
|
-
|
|
210
|
+
onError: (error) => {
|
|
211
|
+
console.error(`Feishu card rollover failed for endpoint ${input.endpointId}`, error);
|
|
212
|
+
},
|
|
213
|
+
sleep,
|
|
214
|
+
title: input.agentId
|
|
208
215
|
});
|
|
216
|
+
const publisher = cardRollover.rollover;
|
|
209
217
|
const endpointEvents = createJsonlAgentEventLog({
|
|
210
218
|
filePath: join(STATE_DIR, "instances", input.instanceId, "agent-events.jsonl")
|
|
211
219
|
});
|
|
@@ -220,15 +228,11 @@ export async function createRivusDeploymentAdapters(context: RivusDeploymentBoot
|
|
|
220
228
|
client: openApiClient,
|
|
221
229
|
config
|
|
222
230
|
});
|
|
223
|
-
const prepareCardTarget =
|
|
224
|
-
client: openApiClient,
|
|
225
|
-
config,
|
|
226
|
-
registry: cardTargets,
|
|
227
|
-
title: input.agentId
|
|
228
|
-
});
|
|
231
|
+
const prepareCardTarget = (run: FeishuAgentRunPreparation) => cardRollover.prepareRun(run);
|
|
229
232
|
const endpoint = createFeishuDeploymentEndpoint({
|
|
230
233
|
agentId: input.agentId,
|
|
231
234
|
botOpenId,
|
|
235
|
+
cardRollover: cardRollover.transport,
|
|
232
236
|
cancel: input.cancel,
|
|
233
237
|
endpointId: input.endpointId,
|
|
234
238
|
eventDispatcher: createLazyFeishuWebSocketEventDispatcher(() => new Lark.EventDispatcher({})),
|