@rivus/agent 0.5.2 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import { a as createAgentLoopSkillExecutionStart, c as createAgentLoopToolExecutionEnd, d as createAsyncIterableAgentLoop, f as createEventAgentLoop, i as createAgentLoopSkillExecutionEnd, l as createAgentLoopToolExecutionStart, m as createTextAgentLoopFromCallback, n as createAgentLoopModelExecutionEnd, o as createAgentLoopTextDelta, p as createTextAgentLoop, r as createAgentLoopModelExecutionStart, s as createAgentLoopThinkingDelta, t as createAgentLoopFromCallback, u as createAgentLoopToolExecutionUpdate } from "./agent-loop.js";
2
- import { a as RIVUS_MEMORY_TOOL_ID, c as createMemoryNamespace, d as InvalidRivusPlugin, f as RIVUS_PLUGIN_API_VERSION, i as MEMORY_SCOPES, l as createRivusMemoryToolContract, m as requiresToolApproval, n as resolveRivusAgentDefinition, o as RIVUS_MEMORY_TOOL_PLUGIN_ID, p as RivusToolInputRejected, s as RIVUS_MEMORY_TOOL_VERSION, t as createRivusPluginCatalog, u as restrictMemoryScopesForAudience } from "./rivus-plugin-registry.js";
3
- import { C as loadRivusDaemonConfig, D as loadRivusDeploymentManifest, E as RivusDeploymentManifestError, M as loadRivusDeployment, N as validateRivusDeploymentManifest, O as FeishuEndpointCredentialError, S as RivusDaemonConfigError, _ as createStableId, a as InvalidRivusProjectSpace, b as createRivusEnvFromOpenClawConfig, c as RivusDeploymentReadinessError, d as createRivusAgentHost, f as AgentInstanceBusy, g as createAgentInstanceRegistry, h as AgentInstanceConflict, i as resolveRivusProjectSpace, j as RivusPluginLoadError, k as resolveFeishuEndpointCredentials, l as createRivusDeploymentDaemon, m as createAgentRuntimePool, n as createRivusDeploymentCliProcess, o as RivusDeploymentAutomationReadinessError, p as AgentRuntimeDisposed, r as createConfiguredRivusDeploymentDaemon, s as RivusDeploymentDaemonLifecycleError, t as runRivusDaemonCli, u as InvalidRivusEndpointBinding, v as createRivusDaemonShutdownController, w as loadNodeRivusPluginModule, x as formatRivusEnvFile, y as OpenClawEnvImportError } from "./rivus-daemon-cli.js";
2
+ import { a as createMemoryNamespace, c as InvalidRivusPlugin, d as requiresToolApproval, i as RIVUS_MEMORY_TOOL_VERSION, l as RIVUS_PLUGIN_API_VERSION, n as RIVUS_MEMORY_TOOL_ID, o as createRivusMemoryToolContract, r as RIVUS_MEMORY_TOOL_PLUGIN_ID, s as restrictMemoryScopesForAudience, t as MEMORY_SCOPES, u as RivusToolInputRejected } from "./agent-memory.js";
3
+ import { n as resolveRivusAgentDefinition, t as createRivusPluginCatalog } from "./rivus-plugin-registry.js";
4
+ import { A as CardPresentationTransitionDenied, B as FeishuEndpointCredentialError, C as loadRivusDaemonConfig, D as loadRivusDeploymentManifest, E as RivusDeploymentManifestError, F as completeCardPresentationHandoff, G as validateRivusDeploymentManifest, I as createCardPresentationChain, L as failCardPresentationHandoff, M as activeCardPresentation, N as beginCardPresentationHandoff, O as DEFAULT_CARD_STREAM_LEASE_MS, P as compensateCardPresentationHandoff, R as isCardPresentationHandoffDue, S as RivusDaemonConfigError, U as RivusPluginLoadError, V as resolveFeishuEndpointCredentials, W as loadRivusDeployment, _ as createStableId, a as InvalidRivusProjectSpace, b as createRivusEnvFromOpenClawConfig, c as RivusDeploymentReadinessError, d as createRivusAgentHost, f as AgentInstanceBusy, g as createAgentInstanceRegistry, h as AgentInstanceConflict, i as resolveRivusProjectSpace, j as acceptsCardPresentationProgress, k as createFeishuCardRollover, l as createRivusDeploymentDaemon, m as createAgentRuntimePool, n as createRivusDeploymentCliProcess, o as RivusDeploymentAutomationReadinessError, p as AgentRuntimeDisposed, r as createConfiguredRivusDeploymentDaemon, s as RivusDeploymentDaemonLifecycleError, t as runRivusDaemonCli, u as InvalidRivusEndpointBinding, v as createRivusDaemonShutdownController, w as loadNodeRivusPluginModule, x as formatRivusEnvFile, y as OpenClawEnvImportError, z as markCardPresentationTerminal } from "./rivus-daemon-cli.js";
5
+ import { a as InvalidInvocationAuthority, i as normalizeStableJson, n as InvalidToolInput, o as createInvocationAuthority, r as createToolInputDigest, s as resolveInvocationAuthority, t as InvalidStableJson } from "./tool-input-digest.js";
4
6
  import { n as assertRivusPluginConforms, r as createFakeRivusPlugin, t as RivusPluginConformanceError } from "./rivus-plugin-testkit.js";
5
- import { Cause, Deferred, Effect, Exit, Fiber, Option, Stream } from "effect";
7
+ import { Cause, Deferred, Effect, Either, Exit, Fiber, Option, Stream } from "effect";
6
8
  import { createHash, randomUUID } from "node:crypto";
7
9
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
8
10
  import { appendFile, lstat, mkdir, readFile, readdir, realpath, rename, stat, unlink, writeFile } from "node:fs/promises";
@@ -14,7 +16,6 @@ import { resourceFromAttributes } from "@opentelemetry/resources";
14
16
  import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
15
17
  import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
16
18
  import { ROOT_CONTEXT, SpanStatusCode, trace } from "@opentelemetry/api";
17
- import { Unsafe } from "typebox";
18
19
  //#region src/application/support/serial-executor.ts
19
20
  function createSerialExecutor() {
20
21
  let tail = Promise.resolve();
@@ -134,7 +135,7 @@ function createFeishuCardDeliveryReconciler(options) {
134
135
  return { reconcile: () => Effect.gen(function* () {
135
136
  const projector = createFeishuStreamProjector();
136
137
  const terminalByRun = /* @__PURE__ */ new Map();
137
- for (const event of options.events) for (const action of projector.apply(event)) if (action.type !== "update_text") terminalByRun.set(action.runId, action);
138
+ for (const event of options.events) for (const action of projector.apply(event)) if (action.type !== "update_text" && action.type !== "handoff") terminalByRun.set(action.runId, action);
138
139
  let repaired = 0;
139
140
  for (const [runId, action] of terminalByRun) {
140
141
  if (options.ledger.isTerminalPublished(runId)) continue;
@@ -1935,6 +1936,9 @@ function encodeSegment(value) {
1935
1936
  }
1936
1937
  //#endregion
1937
1938
  //#region src/application/feishu/feishu-message-intake.ts
1939
+ function readTenantKey(payload) {
1940
+ return payload.event.sender?.tenant_key ?? payload.header?.tenant_key ?? "";
1941
+ }
1938
1942
  var UnsupportedFeishuMessage = class extends Error {
1939
1943
  messageType;
1940
1944
  name = "UnsupportedFeishuMessage";
@@ -2011,7 +2015,7 @@ function toSessionReference(payload, options) {
2011
2015
  return {
2012
2016
  agentId: options.agentId,
2013
2017
  chatId: payload.event.message.chat_id,
2014
- tenantKey: payload.event.sender?.tenant_key ?? payload.header?.tenant_key ?? "",
2018
+ tenantKey: readTenantKey(payload),
2015
2019
  ...payload.event.message.thread_id ? { threadId: payload.event.message.thread_id } : {}
2016
2020
  };
2017
2021
  }
@@ -2092,6 +2096,7 @@ function createFeishuAgentDaemon(options) {
2092
2096
  handleMessage: (payload, handleOptions) => {
2093
2097
  let dedupeMessageId;
2094
2098
  const sideEffectsDisabled = handleOptions?.sideEffects === "disabled";
2099
+ const finalizeRun = options.finalizeRun ?? (() => Effect.void);
2095
2100
  const prepareRun = sideEffectsDisabled ? void 0 : options.prepareRun;
2096
2101
  const publish = sideEffectsDisabled ? () => Effect.void : options.publish;
2097
2102
  const publishRunUpdate = sideEffectsDisabled ? void 0 : options.publishRunUpdate;
@@ -2111,12 +2116,14 @@ function createFeishuAgentDaemon(options) {
2111
2116
  }
2112
2117
  if (inbound.type === "cancel_run") return yield* cancelRun(inbound);
2113
2118
  const projector = createFeishuStreamProjector();
2119
+ const acceptedRunIds = /* @__PURE__ */ new Set();
2114
2120
  const command = {
2115
2121
  ...inbound.command,
2116
2122
  ...options.resolveInvocation ? { invocation: options.resolveInvocation(payload, inbound.conversationId) } : {}
2117
2123
  };
2118
2124
  const result = yield* execution.promptWithUpdates(command, (update) => Effect.gen(function* () {
2119
2125
  const event = update.event;
2126
+ if (event.type === "agent_run_accepted") acceptedRunIds.add(event.runId);
2120
2127
  if (event.type === "agent_run_accepted" && prepareRun) yield* prepareRun({
2121
2128
  messageId: inbound.messageId,
2122
2129
  prompt: event.prompt,
@@ -2126,7 +2133,7 @@ function createFeishuAgentDaemon(options) {
2126
2133
  });
2127
2134
  if (publishRunUpdate) yield* publishRunUpdate(update);
2128
2135
  for (const action of projector.applyUpdate(update)) yield* publish(action);
2129
- }));
2136
+ })).pipe(Effect.ensuring(Effect.forEach(acceptedRunIds, (runId) => finalizeRun(runId), { discard: true })));
2130
2137
  return {
2131
2138
  finalText: result.finalText,
2132
2139
  messageId: inbound.messageId,
@@ -2226,9 +2233,8 @@ function createFeishuMessageQueue(options) {
2226
2233
  };
2227
2234
  }
2228
2235
  function createLaneKey(payload) {
2229
- const tenantKey = payload.event.sender?.tenant_key ?? payload.header?.tenant_key ?? "unknown-tenant";
2230
2236
  const message = payload.event.message;
2231
- return `${tenantKey}:${message.chat_id}:${message.thread_id ?? message.chat_id}`;
2237
+ return `${readTenantKey(payload)}:${message.chat_id}:${message.thread_id ?? message.chat_id}`;
2232
2238
  }
2233
2239
  //#endregion
2234
2240
  //#region src/application/feishu/feishu-group-policy.ts
@@ -2250,7 +2256,10 @@ function createFeishuMessageWorker(options) {
2250
2256
  const results = [];
2251
2257
  while (options.queue.pending() > 0) {
2252
2258
  const batchSize = Math.min(concurrency, options.queue.pending());
2253
- const batch = yield* Effect.all(Array.from({ length: batchSize }, () => options.queue.drainOne()), { concurrency: "unbounded" });
2259
+ const outcomes = yield* Effect.all(Array.from({ length: batchSize }, () => options.queue.drainOne().pipe(Effect.either)), { concurrency: "unbounded" });
2260
+ const failures = outcomes.filter(Either.isLeft).map((outcome) => outcome.left);
2261
+ if (failures.length > 0) yield* Effect.fail(failures.length === 1 ? failures[0] : new AggregateError(failures, "Feishu message batch failed"));
2262
+ const batch = outcomes.filter(Either.isRight).map((outcome) => outcome.right);
2254
2263
  if (batch.every((result) => !result.handled)) break;
2255
2264
  for (const result of batch) if (result.handled) results.push(result);
2256
2265
  }
@@ -2261,8 +2270,8 @@ function createFeishuMessageWorker(options) {
2261
2270
  }) };
2262
2271
  }
2263
2272
  //#endregion
2264
- //#region src/application/feishu/feishu-worker-loop.ts
2265
- function createFeishuWorkerLoop(options) {
2273
+ //#region src/application/support/periodic-effect-loop.ts
2274
+ function createPeriodicEffectLoop(options) {
2266
2275
  let running = false;
2267
2276
  let fiber;
2268
2277
  const reportError = (error) => {
@@ -2270,7 +2279,7 @@ function createFeishuWorkerLoop(options) {
2270
2279
  return reported instanceof Promise ? Effect.promise(() => reported) : Effect.void;
2271
2280
  };
2272
2281
  const continueAfterReporting = (effect) => effect.pipe(Effect.asVoid, Effect.catchAll((error) => reportError(error)));
2273
- const cycle = Effect.suspend(() => continueAfterReporting(options.drainAvailable()).pipe(Effect.flatMap(() => continueAfterReporting(options.sleep(options.intervalMs))), Effect.flatMap(() => cycle)));
2282
+ const cycle = Effect.suspend(() => continueAfterReporting(options.run()).pipe(Effect.flatMap(() => continueAfterReporting(options.sleep(options.intervalMs))), Effect.flatMap(() => cycle)));
2274
2283
  return {
2275
2284
  running: () => running,
2276
2285
  start: () => {
@@ -2287,6 +2296,16 @@ function createFeishuWorkerLoop(options) {
2287
2296
  };
2288
2297
  }
2289
2298
  //#endregion
2299
+ //#region src/application/feishu/feishu-worker-loop.ts
2300
+ function createFeishuWorkerLoop(options) {
2301
+ return createPeriodicEffectLoop({
2302
+ intervalMs: options.intervalMs,
2303
+ ...options.onError ? { onError: options.onError } : {},
2304
+ run: () => options.drainAvailable(),
2305
+ sleep: options.sleep
2306
+ });
2307
+ }
2308
+ //#endregion
2290
2309
  //#region src/application/daemon/rivus-daemon-process.ts
2291
2310
  function createRivusDaemonProcess(options) {
2292
2311
  let running = false;
@@ -2364,6 +2383,7 @@ function createRivusDaemonStatusReporter(options) {
2364
2383
  const activeSessionKey = availability?.busy ? availability.activeSessionKey : activeRun?.sessionKey;
2365
2384
  return {
2366
2385
  agentId: options.agentId,
2386
+ ...options.cardPresentations ? { cards: options.cardPresentations() } : {},
2367
2387
  harness: {
2368
2388
  ...activeRunId !== void 0 ? { activeRunId } : {},
2369
2389
  ...activeRunState !== void 0 ? { activeRunState } : {},
@@ -2643,6 +2663,7 @@ function createFeishuAgentRuntime(options) {
2643
2663
  const daemon = createFeishuAgentDaemon({
2644
2664
  agentId: options.agentId,
2645
2665
  ...options.botOpenId ? { botOpenId: options.botOpenId } : {},
2666
+ ...options.finalizeRun ? { finalizeRun: options.finalizeRun } : {},
2646
2667
  harness,
2647
2668
  ...options.prepareRun ? { prepareRun: options.prepareRun } : {},
2648
2669
  publish: options.publish
@@ -2709,7 +2730,7 @@ function isRetryableFeishuMessageError(error) {
2709
2730
  return !(error instanceof AgentRunCancelled || error instanceof UnsupportedFeishuMessage || error instanceof InvalidFeishuMessageContent || error instanceof InvalidFeishuSessionReference);
2710
2731
  }
2711
2732
  function summarizeReceiveMessage(payload) {
2712
- const tenantKey = payload.event.sender?.tenant_key ?? payload.header?.tenant_key;
2733
+ const tenantKey = readTenantKey(payload);
2713
2734
  return {
2714
2735
  chatId: payload.event.message.chat_id,
2715
2736
  messageId: payload.event.message.message_id,
@@ -2764,14 +2785,41 @@ async function stopWebSocketClient(client) {
2764
2785
  else await client.disconnect?.();
2765
2786
  }
2766
2787
  //#endregion
2788
+ //#region src/application/feishu/feishu-card-rollover-supervisor.ts
2789
+ const DEFAULT_INTERVAL_MS = 1e3;
2790
+ function createFeishuCardRolloverSupervisor(options) {
2791
+ const intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;
2792
+ if (!Number.isSafeInteger(intervalMs) || intervalMs < 1) throw new Error("Feishu card rollover supervisor interval must be a positive integer");
2793
+ const tick = () => Effect.gen(function* () {
2794
+ const now = yield* options.clock.now;
2795
+ const results = [];
2796
+ for (const runId of options.rollover.dueRunIds(now)) results.push(yield* options.rollover.handoff(runId));
2797
+ return { results };
2798
+ });
2799
+ const loop = createPeriodicEffectLoop({
2800
+ intervalMs,
2801
+ ...options.onError ? { onError: options.onError } : {},
2802
+ run: tick,
2803
+ sleep: options.sleep
2804
+ });
2805
+ return {
2806
+ recover: () => options.rollover.recover().pipe(Effect.asVoid),
2807
+ running: () => loop.running(),
2808
+ start: () => loop.start(),
2809
+ stop: () => loop.stop(),
2810
+ tick
2811
+ };
2812
+ }
2813
+ //#endregion
2767
2814
  //#region src/infrastructure/feishu/feishu-agent-run-card.ts
2815
+ const FEISHU_AGENT_CARD_ELEMENT_ID = "rivus_agent_answer";
2768
2816
  function createFeishuAgentRunCard(input) {
2769
2817
  const presentation = resolveRunPresentation(input);
2770
2818
  return {
2771
2819
  body: { elements: [
2772
2820
  {
2773
2821
  content: presentation.content,
2774
- element_id: input.status === "running" ? input.elementId ?? "rivus_agent_answer" : "rivus_agent_answer",
2822
+ element_id: input.status === "running" ? input.elementId ?? "rivus_agent_answer" : FEISHU_AGENT_CARD_ELEMENT_ID,
2775
2823
  tag: "markdown"
2776
2824
  },
2777
2825
  {
@@ -2813,9 +2861,15 @@ function resolveRunPresentation(input) {
2813
2861
  switch (input.status) {
2814
2862
  case "running": return {
2815
2863
  content: input.text || "正在思考…",
2816
- note: "回答将实时更新",
2864
+ note: input.generation ? "接续上一条消息,回答将实时更新" : "回答将实时更新",
2817
2865
  template: "blue",
2818
- title: "正在处理"
2866
+ title: input.generation ? "正在处理(续)" : "正在处理"
2867
+ };
2868
+ case "handoff": return {
2869
+ content: "任务仍在后台处理,进度将继续显示在下一条消息。",
2870
+ note: "本卡片的流式窗口已交接",
2871
+ template: "blue",
2872
+ title: "已转到新消息"
2819
2873
  };
2820
2874
  case "completed": return {
2821
2875
  content: input.text || "已完成。",
@@ -2921,11 +2975,12 @@ function createFeishuCardKitOpenApiClient(options) {
2921
2975
  const agentName = options.agentName ?? "Rivus Agent";
2922
2976
  const streamingClosedCards = /* @__PURE__ */ new Set();
2923
2977
  const call = (request) => options.client.request(request).pipe(Effect.asVoid);
2924
- const updateTerminal = (request, status) => updateTerminalCard(baseUrl, agentName, request, status, call).pipe(Effect.tap(() => Effect.sync(() => streamingClosedCards.delete(request.cardId))));
2978
+ const updateTerminal = (request, status) => updateWholeCard(baseUrl, agentName, request, status, call).pipe(Effect.tap(() => Effect.sync(() => streamingClosedCards.delete(request.cardId))));
2925
2979
  return {
2926
2980
  cancel: (request) => updateTerminal(request, "cancelled"),
2927
2981
  fail: (request) => updateTerminal(request, "failed"),
2928
2982
  finish: (request) => updateTerminal(request, "completed"),
2983
+ handoff: (request) => Effect.sync(() => streamingClosedCards.add(request.cardId)).pipe(Effect.flatMap(() => updateWholeCard(baseUrl, agentName, request, "handoff", call))),
2929
2984
  updateText: (request) => {
2930
2985
  if (streamingClosedCards.has(request.cardId)) return Effect.void;
2931
2986
  return call({
@@ -2937,7 +2992,10 @@ function createFeishuCardKitOpenApiClient(options) {
2937
2992
  url: `${baseUrl}/open-apis/cardkit/v1/cards/${encodeURIComponent(request.cardId)}/elements/${encodeURIComponent(request.elementId)}/content`
2938
2993
  }).pipe(Effect.catchAll((error) => {
2939
2994
  if (!isStreamingClosed(error)) return Effect.fail(error);
2940
- return Effect.sync(() => streamingClosedCards.add(request.cardId));
2995
+ return Effect.sync(() => {
2996
+ streamingClosedCards.add(request.cardId);
2997
+ options.onStreamingClosed?.(request.cardId);
2998
+ });
2941
2999
  }));
2942
3000
  }
2943
3001
  };
@@ -2945,17 +3003,14 @@ function createFeishuCardKitOpenApiClient(options) {
2945
3003
  function isStreamingClosed(error) {
2946
3004
  return error instanceof FeishuOpenApiError && (error.code === 200850 || error.code === 300309);
2947
3005
  }
2948
- function updateTerminalCard(baseUrl, agentName, request, status, call) {
2949
- const card = status === "completed" && "text" in request ? createFeishuAgentRunCard({
3006
+ function updateWholeCard(baseUrl, agentName, request, status, call) {
3007
+ const card = status === "completed" ? createFeishuAgentRunCard({
2950
3008
  agentName,
2951
- status: "completed",
2952
- text: request.text
2953
- }) : status === "cancelled" ? createFeishuAgentRunCard({
2954
- agentName,
2955
- status: "cancelled"
3009
+ status,
3010
+ text: "text" in request ? request.text : ""
2956
3011
  }) : createFeishuAgentRunCard({
2957
3012
  agentName,
2958
- status: "failed"
3013
+ status
2959
3014
  });
2960
3015
  return call({
2961
3016
  body: {
@@ -2983,6 +3038,10 @@ function createFeishuCardKitPublisher(options) {
2983
3038
  elementId: target.elementId,
2984
3039
  sequence
2985
3040
  });
3041
+ case "handoff": return yield* options.client.handoff({
3042
+ cardId: target.cardId,
3043
+ sequence
3044
+ });
2986
3045
  case "finish":
2987
3046
  yield* options.client.finish({
2988
3047
  cardId: target.cardId,
@@ -3032,6 +3091,7 @@ function createCoalescingFeishuPublisher(options) {
3032
3091
  case "update_text": return Effect.sync(() => {
3033
3092
  pendingTextByRun.set(action.runId, action.text);
3034
3093
  });
3094
+ case "handoff": return options.publisher.publish(action);
3035
3095
  case "finish": return Effect.gen(function* () {
3036
3096
  pendingTextByRun.set(action.runId, action.text);
3037
3097
  yield* flushRun(action.runId);
@@ -3064,7 +3124,8 @@ function createConfiguredFeishuCardKitPublisher(options) {
3064
3124
  client: createFeishuCardKitOpenApiClient({
3065
3125
  ...options.agentName === void 0 ? {} : { agentName: options.agentName },
3066
3126
  baseUrl: options.config.feishu.baseUrl,
3067
- client: options.client
3127
+ client: options.client,
3128
+ ...options.onStreamingClosed === void 0 ? {} : { onStreamingClosed: options.onStreamingClosed }
3068
3129
  }),
3069
3130
  ...options.ledger ? { ledger: options.ledger } : {},
3070
3131
  resolveTarget: options.resolveTarget
@@ -3077,36 +3138,33 @@ function createConfiguredFeishuCardKitPublisher(options) {
3077
3138
  }
3078
3139
  //#endregion
3079
3140
  //#region src/infrastructure/feishu/feishu-cardkit-target-preparation.ts
3080
- const DEFAULT_ELEMENT_ID = "rivus_agent_answer";
3141
+ const DEFAULT_ELEMENT_ID = FEISHU_AGENT_CARD_ELEMENT_ID;
3081
3142
  function createFeishuCardTargetPreparation(options) {
3082
3143
  return (run) => Effect.gen(function* () {
3083
3144
  const target = yield* options.createTarget(run);
3084
- yield* options.registry.bind(run.runId, target);
3145
+ yield* options.presentations.bindRun(run, target);
3085
3146
  });
3086
3147
  }
3087
- function createConfiguredFeishuCardKitTargetPreparation(options) {
3088
- const creator = createFeishuCardKitOpenApiTargetCreator({
3148
+ function createConfiguredFeishuCardKitTargetCreator(options) {
3149
+ return createFeishuCardKitOpenApiTargetCreator({
3089
3150
  baseUrl: options.config.feishu.baseUrl,
3090
3151
  client: options.client,
3091
3152
  elementId: options.elementId ?? DEFAULT_ELEMENT_ID,
3092
3153
  ...options.initialContent === void 0 ? {} : { initialContent: options.initialContent },
3093
3154
  ...options.title === void 0 ? {} : { title: options.title }
3094
3155
  });
3095
- return createFeishuCardTargetPreparation({
3096
- createTarget: (run) => creator.createTarget(run),
3097
- registry: options.registry
3098
- });
3099
3156
  }
3100
3157
  function createFeishuCardKitOpenApiTargetCreator(options) {
3101
3158
  const baseUrl = (options.baseUrl ?? "https://open.feishu.cn").replace(/\/$/, "");
3102
3159
  const title = options.title ?? "Rivus Agent";
3103
3160
  const initialContent = options.initialContent ?? "";
3104
- return { createTarget: (run) => Effect.gen(function* () {
3161
+ return { createTarget: (run, createOptions) => Effect.gen(function* () {
3105
3162
  const cardId = yield* readStringData(yield* options.client.request({
3106
3163
  body: {
3107
3164
  data: JSON.stringify(createFeishuAgentRunCard({
3108
3165
  agentName: title,
3109
3166
  elementId: options.elementId,
3167
+ ...createOptions?.generation === void 0 ? {} : { generation: createOptions.generation },
3110
3168
  runId: run.runId,
3111
3169
  sessionKey: run.sessionKey,
3112
3170
  status: "running",
@@ -3143,6 +3201,68 @@ function isRecord$2(value) {
3143
3201
  return typeof value === "object" && value !== null && !Array.isArray(value);
3144
3202
  }
3145
3203
  //#endregion
3204
+ //#region src/composition/feishu-card-rollover-runtime.ts
3205
+ const MIN_SUPERVISOR_INTERVAL_MS = 200;
3206
+ const MAX_SUPERVISOR_INTERVAL_MS = 5e3;
3207
+ function createConfiguredFeishuCardRolloverRuntime(options) {
3208
+ const leaseMs = options.config.feishu.cardStreamLeaseMs;
3209
+ let rollover;
3210
+ const publisher = createConfiguredFeishuCardKitPublisher({
3211
+ ...options.agentName === void 0 ? {} : { agentName: options.agentName },
3212
+ client: options.client,
3213
+ config: options.config,
3214
+ ...options.ledger ? { ledger: options.ledger } : {},
3215
+ onStreamingClosed: (cardId) => rollover?.observeStreamClosed(cardId),
3216
+ resolveTarget: (runId) => options.cardTargets.resolveTarget(runId),
3217
+ sleep: options.sleep
3218
+ });
3219
+ const creator = createConfiguredFeishuCardKitTargetCreator({
3220
+ client: options.client,
3221
+ config: options.config,
3222
+ ...options.elementId === void 0 ? {} : { elementId: options.elementId },
3223
+ ...options.initialContent === void 0 ? {} : { initialContent: options.initialContent },
3224
+ ...options.title === void 0 ? {} : { title: options.title }
3225
+ });
3226
+ const cardRollover = createFeishuCardRollover({
3227
+ clock: options.clock,
3228
+ createSuccessor: ({ generation, run }) => creator.createTarget(run, { generation }),
3229
+ leaseMs,
3230
+ ...options.observe ? { observe: options.observe } : {},
3231
+ publisher,
3232
+ store: options.cardTargets
3233
+ });
3234
+ rollover = cardRollover;
3235
+ const supervisor = createFeishuCardRolloverSupervisor({
3236
+ clock: options.clock,
3237
+ intervalMs: options.supervisorIntervalMs ?? resolveSupervisorInterval(leaseMs),
3238
+ ...options.onError ? { onError: options.onError } : {},
3239
+ rollover: cardRollover,
3240
+ sleep: options.sleep
3241
+ });
3242
+ return {
3243
+ prepareRun: createFeishuCardTargetPreparation({
3244
+ createTarget: (run) => creator.createTarget(run),
3245
+ presentations: cardRollover
3246
+ }),
3247
+ rollover: cardRollover,
3248
+ supervisor,
3249
+ transport: {
3250
+ running: () => supervisor.running(),
3251
+ start: async () => {
3252
+ await Effect.runPromise(supervisor.recover().pipe(Effect.catchAll((error) => {
3253
+ const reported = options.onError?.(error);
3254
+ return reported instanceof Promise ? Effect.promise(() => reported) : Effect.void;
3255
+ })));
3256
+ supervisor.start();
3257
+ },
3258
+ stop: () => supervisor.stop()
3259
+ }
3260
+ };
3261
+ }
3262
+ function resolveSupervisorInterval(leaseMs) {
3263
+ return Math.max(MIN_SUPERVISOR_INTERVAL_MS, Math.min(MAX_SUPERVISOR_INTERVAL_MS, Math.floor(leaseMs / 10)));
3264
+ }
3265
+ //#endregion
3146
3266
  //#region src/composition/rivus-daemon-bootstrap.ts
3147
3267
  const DEFAULT_WORKER_INTERVAL_MS$1 = 250;
3148
3268
  const DEFAULT_RUN_TIMEOUT_MS = 900 * 1e3;
@@ -3157,23 +3277,26 @@ function createConfiguredRivusDaemonBootstrap(options) {
3157
3277
  config: options.config,
3158
3278
  request: options.request
3159
3279
  });
3160
- const prepareRun = createConfiguredFeishuCardKitTargetPreparation({
3161
- client: openApiClient,
3162
- config: options.config,
3163
- registry: options.cardTargets
3164
- });
3165
- const publisher = createConfiguredFeishuCardKitPublisher({
3280
+ const cardRollover = createConfiguredFeishuCardRolloverRuntime({
3281
+ cardTargets: options.cardTargets,
3166
3282
  client: openApiClient,
3283
+ clock: options.clock,
3167
3284
  config: options.config,
3168
- resolveTarget: (runId) => options.cardTargets.resolveTarget(runId),
3169
- sleep: options.sleep
3285
+ ...options.cardLedger ? { ledger: options.cardLedger } : {},
3286
+ ...options.observeCardRollover ? { observe: options.observeCardRollover } : {},
3287
+ ...options.onWorkerError ? { onError: options.onWorkerError } : {},
3288
+ sleep: options.sleep,
3289
+ ...options.cardRolloverIntervalMs === void 0 ? {} : { supervisorIntervalMs: options.cardRolloverIntervalMs }
3170
3290
  });
3291
+ const publisher = cardRollover.rollover;
3292
+ const prepareRun = (run) => cardRollover.prepareRun(run);
3171
3293
  const periodicFlush = createPeriodicFlush(options, publisher);
3172
3294
  const runtime = createFeishuAgentRuntime({
3173
3295
  agentId: options.config.agentId,
3174
3296
  ...options.botOpenId ? { botOpenId: options.botOpenId } : {},
3175
3297
  clock: options.clock,
3176
3298
  eventSinks: [options.eventLog],
3299
+ finalizeRun: (runId) => cardRollover.rollover.releaseRun(runId),
3177
3300
  ...options.inboxRepository ? { inboxRepository: options.inboxRepository } : {},
3178
3301
  ...options.initialEvents ? { initialEvents: options.initialEvents } : {},
3179
3302
  ...options.initialRunStates ? { initialRunStates: options.initialRunStates } : {},
@@ -3197,25 +3320,31 @@ function createConfiguredRivusDaemonBootstrap(options) {
3197
3320
  });
3198
3321
  const restoreHistoryFromLog = () => restoreAgentHistory(options.eventLog);
3199
3322
  let processRef;
3200
- let transport = websocketTransport;
3323
+ let transport = createCompositeRivusDaemonTransport({ transports: [websocketTransport, cardRollover.transport] });
3201
3324
  const statusReporter = createRivusDaemonStatusReporter({
3202
3325
  agentId: options.config.agentId,
3203
3326
  availability: () => runtime.harness.getAvailability(),
3204
3327
  pending: () => runtime.pending(),
3205
3328
  processRunning: () => processRef?.running() ?? false,
3329
+ cardPresentations: () => cardRollover.rollover.status(),
3206
3330
  receiveStatus: () => runtime.receiveStatus(),
3207
3331
  restoreHistory: restoreHistoryFromLog,
3208
3332
  transportRunning: () => transport.running(),
3209
3333
  workerLoopRunning: () => workerLoop.running()
3210
3334
  });
3211
3335
  const statusTransport = options.createStatusTransport?.(statusReporter);
3212
- if (statusTransport) transport = createCompositeRivusDaemonTransport({ transports: [websocketTransport, statusTransport] });
3336
+ if (statusTransport) transport = createCompositeRivusDaemonTransport({ transports: [
3337
+ websocketTransport,
3338
+ cardRollover.transport,
3339
+ statusTransport
3340
+ ] });
3213
3341
  const process = createRivusDaemonProcess({
3214
3342
  transport,
3215
3343
  workerLoop
3216
3344
  });
3217
3345
  processRef = process;
3218
3346
  return {
3347
+ cardRollover,
3219
3348
  cardTargets: options.cardTargets,
3220
3349
  eventLog: options.eventLog,
3221
3350
  process,
@@ -3956,62 +4085,6 @@ function resolveContentMode(value) {
3956
4085
  throw new LangfuseTelemetryConfigError("RIVUS_TELEMETRY_CONTENT must be either \"metadata-only\" or \"redacted\"");
3957
4086
  }
3958
4087
  //#endregion
3959
- //#region src/infrastructure/pi/pi-skill-tool.ts
3960
- const PI_SKILL_READER_TOOL_NAME = "rivus_read_skill";
3961
- function createPiSkillRuntime(skills) {
3962
- if (skills.length === 0) return Object.freeze({ prompt: "" });
3963
- const skillsById = new Map(skills.map((skill) => [skill.id, skill]));
3964
- const prompt = [
3965
- "Granted Skills are versioned instructions loaded on demand.",
3966
- `Before following a Skill, call ${PI_SKILL_READER_TOOL_NAME} with its exact ID and follow the returned content.`,
3967
- "Granted Skill catalog:",
3968
- ...skills.map((skill) => `- ${skill.id} | ${skill.title} | v${skill.version} | ${skill.digest}`)
3969
- ].join("\n");
3970
- const tool = {
3971
- description: "Read the full versioned instructions for one Skill granted to this Agent Runtime.",
3972
- execute: async (_callId, input) => {
3973
- const skillId = readSkillId$1(input);
3974
- const skill = skillsById.get(skillId);
3975
- if (!skill) throw new Error(`Skill is not granted: ${skillId}`);
3976
- const details = {
3977
- contentLength: skill.content.length,
3978
- digest: skill.digest,
3979
- skillId: skill.id,
3980
- title: skill.title,
3981
- version: skill.version
3982
- };
3983
- return {
3984
- content: [{
3985
- text: skill.content,
3986
- type: "text"
3987
- }],
3988
- details
3989
- };
3990
- },
3991
- executionMode: "sequential",
3992
- label: "Read granted Skill",
3993
- name: PI_SKILL_READER_TOOL_NAME,
3994
- parameters: Unsafe({
3995
- additionalProperties: false,
3996
- properties: { skillId: {
3997
- description: "Exact Skill ID from the granted Skill catalog.",
3998
- type: "string"
3999
- } },
4000
- required: ["skillId"],
4001
- type: "object"
4002
- }),
4003
- promptSnippet: `${PI_SKILL_READER_TOOL_NAME}: read one granted Skill by exact ID`
4004
- };
4005
- return Object.freeze({
4006
- prompt,
4007
- tool
4008
- });
4009
- }
4010
- function readSkillId$1(input) {
4011
- if (input === null || typeof input !== "object" || Array.isArray(input) || typeof input.skillId !== "string") throw new Error("Skill reader input requires a string skillId");
4012
- return input.skillId;
4013
- }
4014
- //#endregion
4015
4088
  //#region src/infrastructure/pi/pi-agent-loop.ts
4016
4089
  function createPiAgentLoop(options) {
4017
4090
  return createAsyncIterableAgentLoop({ run: (input) => runPiSession(input, options) });
@@ -4346,6 +4419,79 @@ function createPiSessionRegistry(options) {
4346
4419
  };
4347
4420
  }
4348
4421
  //#endregion
4422
+ //#region src/application/feishu/feishu-card-presentation-store.ts
4423
+ var FeishuCardPresentationNotFound = class {
4424
+ runId;
4425
+ _tag = "FeishuCardPresentationNotFound";
4426
+ constructor(runId) {
4427
+ this.runId = runId;
4428
+ }
4429
+ };
4430
+ function createFeishuCardPresentationStore(options = {}) {
4431
+ const chains = new Map(options.initial?.map((chain) => [chain.runId, structuredClone(chain)]) ?? []);
4432
+ const serial = createSerialExecutor();
4433
+ const save = async (next) => {
4434
+ for (const chain of next) chains.set(chain.runId, structuredClone(chain));
4435
+ await options.persist?.([...chains.values()]);
4436
+ };
4437
+ const mutate = (operation) => Effect.tryPromise({
4438
+ try: () => serial.run(operation),
4439
+ catch: (error) => error
4440
+ });
4441
+ const transition = (runId, apply) => mutate(async () => {
4442
+ const current = chains.get(runId);
4443
+ if (!current) throw new FeishuCardPresentationNotFound(runId);
4444
+ const next = apply(current);
4445
+ if (next !== current) await save([next]);
4446
+ return activeCardPresentation(next);
4447
+ });
4448
+ return {
4449
+ bind: (binding) => mutate(async () => {
4450
+ const current = chains.get(binding.runId);
4451
+ if (current && activeCardPresentation(current).cardId === binding.cardId) return activeCardPresentation(current);
4452
+ const created = createCardPresentationChain(binding);
4453
+ await save([created]);
4454
+ return activeCardPresentation(created);
4455
+ }),
4456
+ beginHandoff: ({ handoffAt, runId }) => mutate(async () => {
4457
+ const current = chains.get(runId);
4458
+ if (!current) throw new FeishuCardPresentationNotFound(runId);
4459
+ const next = beginCardPresentationHandoff(current, handoffAt);
4460
+ if (next === current) return {
4461
+ presentation: activeCardPresentation(current),
4462
+ started: false
4463
+ };
4464
+ await save([next]);
4465
+ return {
4466
+ presentation: activeCardPresentation(next),
4467
+ started: true
4468
+ };
4469
+ }),
4470
+ chain: (runId) => {
4471
+ const current = chains.get(runId);
4472
+ return current ? structuredClone(current) : void 0;
4473
+ },
4474
+ chains: () => [...chains.values()].map((chain) => structuredClone(chain)),
4475
+ compensateInterruptedHandoffs: (compensatedAt) => mutate(async () => {
4476
+ const compensated = [...chains.values()].map((chain) => ({
4477
+ chain,
4478
+ next: compensateCardPresentationHandoff(chain, compensatedAt)
4479
+ })).filter(({ chain, next }) => next !== chain).map(({ next }) => next);
4480
+ if (compensated.length > 0) await save(compensated);
4481
+ return compensated.map((chain) => structuredClone(chain));
4482
+ }),
4483
+ completeHandoff: ({ runId, successor }) => transition(runId, (chain) => completeCardPresentationHandoff(chain, successor)),
4484
+ failHandoff: ({ failedAt, runId }) => transition(runId, (chain) => failCardPresentationHandoff(chain, failedAt)).pipe(Effect.asVoid),
4485
+ markTerminal: ({ runId, terminalReceiptId }) => transition(runId, (chain) => markCardPresentationTerminal(chain, terminalReceiptId)).pipe(Effect.asVoid),
4486
+ release: (runId) => mutate(async () => {
4487
+ if (!chains.has(runId)) return;
4488
+ chains.delete(runId);
4489
+ await options.persist?.([...chains.values()]);
4490
+ }),
4491
+ size: () => chains.size
4492
+ };
4493
+ }
4494
+ //#endregion
4349
4495
  //#region src/infrastructure/feishu/feishu-card-target-registry.ts
4350
4496
  var FeishuCardTargetNotFound = class {
4351
4497
  runId;
@@ -4363,74 +4509,101 @@ var FeishuCardTargetRegistryStoreError = class {
4363
4509
  this.cause = cause;
4364
4510
  }
4365
4511
  };
4366
- function createInMemoryFeishuCardTargetRegistry() {
4367
- const targets = /* @__PURE__ */ new Map();
4368
- return {
4369
- bind: (runId, target) => Effect.sync(() => {
4370
- targets.set(runId, target);
4371
- }),
4372
- release: (runId) => Effect.sync(() => {
4373
- targets.delete(runId);
4374
- }),
4375
- resolveTarget: (runId) => Effect.sync(() => targets.get(runId)).pipe(Effect.flatMap((target) => target ? Effect.succeed(target) : Effect.fail(new FeishuCardTargetNotFound(runId)))),
4376
- size: () => targets.size
4377
- };
4512
+ const PRESENTATION_FILE_VERSION = 2;
4513
+ const LEGACY_PRESENTATION_TIMESTAMP = (/* @__PURE__ */ new Date(0)).toISOString();
4514
+ function createInMemoryFeishuCardTargetRegistry(initial = []) {
4515
+ const store = createFeishuCardPresentationStore({ initial });
4516
+ return withTargetResolution(store, () => Effect.succeed(store));
4378
4517
  }
4379
4518
  function createJsonFileFeishuCardTargetRegistry(options) {
4380
- let lastKnownSize = 0;
4381
- const loadTargets = Effect.tryPromise({
4382
- try: async () => {
4383
- try {
4384
- const raw = await readFile(options.filePath, "utf8");
4385
- const targets = parseTargets(JSON.parse(raw));
4386
- lastKnownSize = Object.keys(targets).length;
4387
- return targets;
4388
- } catch (error) {
4389
- if (isNodeErrorWithCode(error, "ENOENT")) {
4390
- lastKnownSize = 0;
4391
- return {};
4392
- }
4393
- throw error;
4394
- }
4395
- },
4396
- catch: (error) => new FeishuCardTargetRegistryStoreError("load", error)
4397
- });
4398
- const saveTargets = (targets) => Effect.tryPromise({
4399
- try: async () => {
4400
- await mkdir(dirname(options.filePath), { recursive: true });
4401
- await writeFile(options.filePath, `${JSON.stringify(targets, null, 2)}\n`, "utf8");
4402
- lastKnownSize = Object.keys(targets).length;
4403
- },
4404
- catch: (error) => new FeishuCardTargetRegistryStoreError("save", error)
4519
+ let opened;
4520
+ let loaded;
4521
+ const open = async () => {
4522
+ const store = createFeishuCardPresentationStore({
4523
+ initial: await loadChains(options.filePath),
4524
+ persist: (chains) => saveChains(options.filePath, chains)
4525
+ });
4526
+ loaded = store;
4527
+ return store;
4528
+ };
4529
+ const ready = () => Effect.tryPromise({
4530
+ try: () => opened ??= open(),
4531
+ catch: (error) => error instanceof FeishuCardTargetRegistryStoreError ? error : new FeishuCardTargetRegistryStoreError("load", error)
4405
4532
  });
4533
+ const use = (operation) => ready().pipe(Effect.flatMap(operation));
4534
+ return withTargetResolution({
4535
+ bind: (binding) => use((current) => current.bind(binding)),
4536
+ beginHandoff: (input) => use((current) => current.beginHandoff(input)),
4537
+ chain: (runId) => loaded?.chain(runId),
4538
+ chains: () => loaded?.chains() ?? [],
4539
+ compensateInterruptedHandoffs: (compensatedAt) => use((current) => current.compensateInterruptedHandoffs(compensatedAt)),
4540
+ completeHandoff: (input) => use((current) => current.completeHandoff(input)),
4541
+ failHandoff: (input) => use((current) => current.failHandoff(input)),
4542
+ markTerminal: (input) => use((current) => current.markTerminal(input)),
4543
+ release: (runId) => use((current) => current.release(runId)),
4544
+ size: () => loaded?.size() ?? 0
4545
+ }, ready);
4546
+ }
4547
+ function withTargetResolution(store, ready) {
4406
4548
  return {
4407
- bind: (runId, target) => loadTargets.pipe(Effect.flatMap((targets) => saveTargets({
4408
- ...targets,
4409
- [runId]: target
4410
- }))),
4411
- release: (runId) => loadTargets.pipe(Effect.flatMap((targets) => {
4412
- const nextTargets = { ...targets };
4413
- delete nextTargets[runId];
4414
- return saveTargets(nextTargets);
4415
- })),
4416
- resolveTarget: (runId) => loadTargets.pipe(Effect.flatMap((targets) => {
4417
- const target = targets[runId];
4418
- return target ? Effect.succeed(target) : Effect.fail(new FeishuCardTargetNotFound(runId));
4419
- })),
4420
- size: () => lastKnownSize
4549
+ ...store,
4550
+ resolveTarget: (runId) => ready().pipe(Effect.flatMap((current) => {
4551
+ const chain = current.chain(runId);
4552
+ return chain ? Effect.succeed(toTarget(activeCardPresentation(chain))) : Effect.fail(new FeishuCardTargetNotFound(runId));
4553
+ }))
4421
4554
  };
4422
4555
  }
4423
- function parseTargets(value) {
4424
- if (!isRecord$4(value)) throw new Error("Feishu card target registry file must contain a JSON object.");
4425
- const targets = {};
4426
- for (const [runId, target] of Object.entries(value)) {
4427
- if (!isFeishuCardTarget(target)) throw new Error(`Invalid Feishu card target entry for run '${runId}'.`);
4428
- targets[runId] = target;
4556
+ function toTarget(presentation) {
4557
+ return {
4558
+ cardId: presentation.cardId,
4559
+ elementId: presentation.elementId ?? "rivus_agent_answer"
4560
+ };
4561
+ }
4562
+ async function loadChains(filePath) {
4563
+ try {
4564
+ const raw = await readFile(filePath, "utf8");
4565
+ return parseChains(JSON.parse(raw));
4566
+ } catch (error) {
4567
+ if (isNodeErrorWithCode(error, "ENOENT")) return [];
4568
+ throw new FeishuCardTargetRegistryStoreError("load", error);
4569
+ }
4570
+ }
4571
+ async function saveChains(filePath, chains) {
4572
+ try {
4573
+ await mkdir(dirname(filePath), { recursive: true });
4574
+ const runs = Object.fromEntries(chains.map((chain) => [chain.runId, chain]));
4575
+ await writeFile(filePath, `${JSON.stringify({
4576
+ runs,
4577
+ version: PRESENTATION_FILE_VERSION
4578
+ }, null, 2)}\n`, "utf8");
4579
+ } catch (error) {
4580
+ throw new FeishuCardTargetRegistryStoreError("save", error);
4429
4581
  }
4430
- return targets;
4431
4582
  }
4432
- function isFeishuCardTarget(value) {
4433
- return isRecord$4(value) && typeof value.cardId === "string" && typeof value.elementId === "string";
4583
+ function parseChains(value) {
4584
+ if (!isRecord$4(value)) throw new Error("Feishu card presentation file must contain a JSON object.");
4585
+ if (value.version === void 0) return Object.entries(value).map(([runId, target]) => parseLegacyChain(runId, target));
4586
+ if (value.version !== PRESENTATION_FILE_VERSION || !isRecord$4(value.runs)) throw new Error(`Unsupported Feishu card presentation file version: ${JSON.stringify(value.version)}`);
4587
+ return Object.entries(value.runs).map(([runId, chain]) => parseChain(runId, chain));
4588
+ }
4589
+ function parseLegacyChain(runId, target) {
4590
+ if (!isRecord$4(target) || typeof target.cardId !== "string" || typeof target.elementId !== "string") throw new Error(`Invalid Feishu card target entry for run '${runId}'.`);
4591
+ return createCardPresentationChain({
4592
+ cardId: target.cardId,
4593
+ createdAt: LEGACY_PRESENTATION_TIMESTAMP,
4594
+ elementId: target.elementId,
4595
+ leaseDeadlineAt: LEGACY_PRESENTATION_TIMESTAMP,
4596
+ presentationId: `${runId}#0`,
4597
+ runId,
4598
+ sourceMessageId: ""
4599
+ });
4600
+ }
4601
+ function parseChain(runId, value) {
4602
+ if (!isRecord$4(value) || value.runId !== runId || !Number.isInteger(value.activeGeneration) || typeof value.activePresentationId !== "string" || !Number.isInteger(value.revision) || !Array.isArray(value.presentations) || value.presentations.length === 0) throw new Error(`Invalid Feishu card presentation chain for run '${runId}'.`);
4603
+ const chain = value;
4604
+ for (const presentation of chain.presentations) if (!isRecord$4(presentation) || typeof presentation.cardId !== "string" || typeof presentation.presentationId !== "string" || typeof presentation.status !== "string" || !Number.isInteger(presentation.generation)) throw new Error(`Invalid Feishu card presentation entry for run '${runId}'.`);
4605
+ activeCardPresentation(chain);
4606
+ return chain;
4434
4607
  }
4435
4608
  //#endregion
4436
4609
  //#region src/infrastructure/feishu/feishu-cot-tool-presenter.ts
@@ -4804,6 +4977,15 @@ function readRedactedString(serialized) {
4804
4977
  function createFixedClock(now) {
4805
4978
  return { now: Effect.succeed(now) };
4806
4979
  }
4980
+ function createTestClock(initial) {
4981
+ let now = initial;
4982
+ return {
4983
+ advance: (ms) => {
4984
+ now = new Date(now.getTime() + ms);
4985
+ },
4986
+ now: Effect.suspend(() => Effect.succeed(now))
4987
+ };
4988
+ }
4807
4989
  function createSequenceRunIds(runIds) {
4808
4990
  let index = 0;
4809
4991
  return { next: Effect.sync(() => {
@@ -4977,72 +5159,6 @@ function freezeView(view) {
4977
5159
  return Object.freeze(view);
4978
5160
  }
4979
5161
  //#endregion
4980
- //#region src/application/delegation/tool-authority.ts
4981
- const authorities = /* @__PURE__ */ new WeakMap();
4982
- var InvalidInvocationAuthority = class extends Error {
4983
- name = "InvalidInvocationAuthority";
4984
- };
4985
- function createInvocationAuthority(authority) {
4986
- if (!authority.sourceMessageId.trim()) throw new InvalidInvocationAuthority("invocation authority requires a trusted source message id");
4987
- const reference = Object.freeze({ id: `authority:${randomUUID()}` });
4988
- const memory = authority.memory ? Object.freeze({
4989
- ...authority.memory,
4990
- scopes: Object.freeze(restrictMemoryScopesForAudience(authority.memory.scopes, authority.memory.audience))
4991
- }) : void 0;
4992
- authorities.set(reference, Object.freeze({
4993
- ...authority,
4994
- ...memory ? { memory } : {}
4995
- }));
4996
- return reference;
4997
- }
4998
- function resolveInvocationAuthority(reference) {
4999
- const authority = authorities.get(reference);
5000
- if (!authority) throw new InvalidInvocationAuthority("invocation authority was not issued by this host");
5001
- return authority;
5002
- }
5003
- //#endregion
5004
- //#region src/application/delegation/tool-input-digest.ts
5005
- var InvalidStableJson = class extends Error {
5006
- name = "InvalidStableJson";
5007
- };
5008
- var InvalidToolInput = class extends InvalidStableJson {
5009
- name = "InvalidToolInput";
5010
- };
5011
- function createToolInputDigest(input) {
5012
- let canonical;
5013
- try {
5014
- canonical = normalizeStableJson(input);
5015
- } catch (error) {
5016
- if (error instanceof InvalidStableJson) throw new InvalidToolInput(error.message);
5017
- throw error;
5018
- }
5019
- return `sha256:${createHash("sha256").update(JSON.stringify(canonical)).digest("hex")}`;
5020
- }
5021
- function normalizeStableJson(value) {
5022
- return canonicalize(value, /* @__PURE__ */ new Set());
5023
- }
5024
- function canonicalize(value, ancestors) {
5025
- if (value === null || typeof value === "string" || typeof value === "boolean") return value;
5026
- if (typeof value === "number") {
5027
- if (!Number.isFinite(value)) throw new InvalidStableJson("stable JSON numbers must be finite");
5028
- return Object.is(value, -0) ? 0 : value;
5029
- }
5030
- if (typeof value !== "object") throw new InvalidStableJson("value must contain only stable JSON values");
5031
- if (ancestors.has(value)) throw new InvalidStableJson("stable JSON must not contain cycles");
5032
- ancestors.add(value);
5033
- try {
5034
- if (Array.isArray(value)) return Array.from({ length: value.length }, (_, index) => {
5035
- if (!Object.hasOwn(value, index)) throw new InvalidStableJson("stable JSON arrays must not contain holes");
5036
- return canonicalize(value[index], ancestors);
5037
- });
5038
- const prototype = Object.getPrototypeOf(value);
5039
- if (prototype !== Object.prototype && prototype !== null) throw new InvalidStableJson("stable JSON objects must be plain objects");
5040
- return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([key, entry]) => [key, canonicalize(entry, ancestors)]));
5041
- } finally {
5042
- ancestors.delete(value);
5043
- }
5044
- }
5045
- //#endregion
5046
5162
  //#region src/application/delegation/tool-operation-ledger.ts
5047
5163
  function createToolOperationLedger(options = {}) {
5048
5164
  const records = new Map(options.initial?.map((record) => [record.operationId, structuredClone(record)]) ?? []);
@@ -5393,6 +5509,7 @@ function createFeishuDeploymentEndpoint(options) {
5393
5509
  agentId: options.agentId,
5394
5510
  botOpenId: options.botOpenId,
5395
5511
  execution: execution.port,
5512
+ ...options.finalizeRun ? { finalizeRun: options.finalizeRun } : {},
5396
5513
  ...options.interactions ? { interactions: options.interactions } : {},
5397
5514
  ...options.prepareRun ? { prepareRun: options.prepareRun } : {},
5398
5515
  publish: options.publish,
@@ -5431,14 +5548,19 @@ function createFeishuDeploymentEndpoint(options) {
5431
5548
  })
5432
5549
  });
5433
5550
  return {
5434
- running: () => websocket.running() && workerLoop.running(),
5551
+ running: () => websocket.running() && workerLoop.running() && (options.cardRollover?.running() ?? true),
5435
5552
  start: async () => {
5436
5553
  execution.beginStart();
5437
5554
  try {
5555
+ await options.cardRollover?.start();
5438
5556
  await websocket.start();
5439
5557
  workerLoop.start();
5440
5558
  } catch (startError) {
5441
- const cleanupErrors = await settleCleanup([() => websocket.stop(), () => workerLoop.stop()]);
5559
+ const cleanupErrors = await settleCleanup([
5560
+ () => websocket.stop(),
5561
+ () => workerLoop.stop(),
5562
+ () => options.cardRollover?.stop()
5563
+ ]);
5442
5564
  if (cleanupErrors.length > 0) throw new AggregateError([startError, ...cleanupErrors], "Feishu endpoint startup and cleanup failed");
5443
5565
  throw startError;
5444
5566
  }
@@ -5449,7 +5571,8 @@ function createFeishuDeploymentEndpoint(options) {
5449
5571
  const cleanupErrors = await settleCleanup([
5450
5572
  () => websocketStop,
5451
5573
  () => execution.cancelActiveAndWait(),
5452
- () => workerStop
5574
+ () => workerStop,
5575
+ () => options.cardRollover?.stop()
5453
5576
  ]);
5454
5577
  if (cleanupErrors.length === 1) throw cleanupErrors[0];
5455
5578
  if (cleanupErrors.length > 1) throw new AggregateError(cleanupErrors, "Feishu endpoint cleanup failed");
@@ -5560,7 +5683,7 @@ function createInvocation(payload, endpointId, memoryTenantId, conversationId, p
5560
5683
  tenantId: memoryTenantId
5561
5684
  } } : {},
5562
5685
  sourceMessageId: payload.event.message.message_id,
5563
- tenantKey: payload.event.sender?.tenant_key ?? payload.header?.tenant_key ?? ""
5686
+ tenantKey: readTenantKey(payload)
5564
5687
  };
5565
5688
  }
5566
5689
  function namespaceSessionKey(namespace, sessionKey) {
@@ -6787,112 +6910,6 @@ function assertTimestamp(value, label) {
6787
6910
  if (!Number.isFinite(Date.parse(value))) throw new HumanInteractionTransitionDenied(`${label} must be an ISO timestamp`);
6788
6911
  }
6789
6912
  //#endregion
6790
- //#region src/infrastructure/pi/pi-tool-proxy.ts
6791
- function createPiToolProxyDefinitions(options) {
6792
- const names = /* @__PURE__ */ new Set();
6793
- return options.tools.map((tool) => {
6794
- const name = toPiToolName(tool.id);
6795
- if (names.has(name)) throw new Error(`Pi tool name collision: ${name}`);
6796
- names.add(name);
6797
- return {
6798
- description: tool.description,
6799
- execute: async (callId, input, signal) => {
6800
- const activeInput = options.getActiveInput();
6801
- const invocation = activeInput?.invocation;
6802
- if (!activeInput || !invocation) throw new Error(`tool ${tool.id} requires an active agent run with a trusted invocation`);
6803
- if (!invocation.tenantKey) throw new Error(`tool ${tool.id} requires a trusted tenant identity`);
6804
- throwIfAborted(signal ?? activeInput.abortSignal);
6805
- const inputDigest = createToolInputDigest(input);
6806
- const operationId = createBoundId("operation", {
6807
- agentId: options.agentId,
6808
- inputDigest,
6809
- instanceId: options.instanceId,
6810
- sourceMessageId: invocation.sourceMessageId,
6811
- toolId: tool.id,
6812
- toolVersion: tool.version
6813
- });
6814
- const approvalId = createBoundId("approval", {
6815
- callId,
6816
- operationId,
6817
- runId: activeInput.runId
6818
- });
6819
- if (requiresToolApproval(tool.risk)) {
6820
- if (invocation.allowedActorOpenIds.length === 0) throw new Error(`tool ${tool.id} requires at least one trusted approval actor`);
6821
- await options.approvals.requestApproval({
6822
- agentId: options.agentId,
6823
- allowedActorOpenIds: invocation.allowedActorOpenIds,
6824
- approvalId,
6825
- callId,
6826
- endpointId: invocation.endpointId,
6827
- inputDigest,
6828
- instanceId: options.instanceId,
6829
- operationId,
6830
- risk: tool.risk,
6831
- runId: activeInput.runId,
6832
- sessionKey: activeInput.sessionKey,
6833
- signal: signal ?? activeInput.abortSignal,
6834
- sourceMessageId: invocation.sourceMessageId,
6835
- tenantKey: invocation.tenantKey,
6836
- toolId: tool.id,
6837
- toolVersion: tool.version
6838
- });
6839
- throwIfAborted(signal ?? activeInput.abortSignal);
6840
- }
6841
- const result = await options.broker.execute({
6842
- authority: createInvocationAuthority({
6843
- agentId: options.agentId,
6844
- instanceId: options.instanceId,
6845
- ...invocation.memory ? { memory: {
6846
- ...invocation.memory,
6847
- scopes: options.memoryScopes ?? []
6848
- } } : {},
6849
- runId: activeInput.runId,
6850
- sessionKey: activeInput.sessionKey,
6851
- sourceMessageId: invocation.sourceMessageId,
6852
- tenantKey: invocation.tenantKey,
6853
- toolGrantSet: options.toolGrantSet
6854
- }),
6855
- callId,
6856
- input,
6857
- operationId,
6858
- ...requiresToolApproval(tool.risk) ? { approvalId } : {},
6859
- toolId: tool.id,
6860
- version: tool.version
6861
- });
6862
- return {
6863
- content: [{
6864
- text: stringifyToolResult(result),
6865
- type: "text"
6866
- }],
6867
- details: result
6868
- };
6869
- },
6870
- executionMode: "sequential",
6871
- label: tool.id,
6872
- name,
6873
- parameters: Unsafe(tool.inputSchema),
6874
- promptSnippet: `${name}: ${tool.description}`
6875
- };
6876
- });
6877
- }
6878
- function createPiToolNameResolver(tools) {
6879
- const toolIdsByPiName = new Map(tools.map((tool) => [toPiToolName(tool.id), tool.id]));
6880
- return (toolName) => toolIdsByPiName.get(toolName) ?? toolName;
6881
- }
6882
- function toPiToolName(toolId) {
6883
- return `rivus_${toolId.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
6884
- }
6885
- function createBoundId(kind, binding) {
6886
- return `${kind}:${createHash("sha256").update(JSON.stringify(binding)).digest("hex")}`;
6887
- }
6888
- function throwIfAborted(signal) {
6889
- if (signal.aborted) throw signal.reason ?? /* @__PURE__ */ new Error("tool execution was aborted");
6890
- }
6891
- function stringifyToolResult(result) {
6892
- if (typeof result === "string") return result;
6893
- return JSON.stringify(result ?? null);
6894
- }
6895
- //#endregion
6896
6913
  //#region src/composition/human-interaction-tool-approval-gateway.ts
6897
6914
  function createHumanInteractionEndpointRegistry() {
6898
6915
  const services = /* @__PURE__ */ new Map();
@@ -7409,4 +7426,4 @@ function validateDecisionInput(input) {
7409
7426
  if (input.recommendedOptionId && !optionIds.includes(input.recommendedOptionId)) throw new Error("recommended user decision option must be available");
7410
7427
  }
7411
7428
  //#endregion
7412
- export { AgentContextBudgetExceeded, AgentEventHandlerFailed, AgentEventLogStoreError, AgentEventSinkFailed, AgentHarnessBusy, AgentInstanceBusy, AgentInstanceConflict, AgentLoopFailed, AgentMemoryError, AgentRunCancelled, AgentRuntimeDisposed, AutomationMandateError, CompactionError, DelegationDenied, DeliveryOutboxError, FeishuCardTargetNotFound, FeishuCardTargetRegistryStoreError, FeishuCotProtocolError, FeishuEndpointCredentialError, FeishuOpenApiError, FeishuTenantAccessTokenError, HumanInteractionRepositoryError, HumanInteractionTransitionDenied, InvalidFeishuCardAction, InvalidFeishuMessageContent, InvalidFeishuSessionReference, InvalidInvocationAuthority, InvalidProjectSkillCatalog, InvalidRecoveryAction, InvalidRivusEndpointBinding, InvalidRivusPlugin, InvalidRivusProjectSpace, InvalidStableJson, InvalidToolInput, InvalidWorkspaceRoot, LangfuseTelemetryConfigError, MEMORY_SCOPES, OpenClawEnvImportError, PluginStateConflict, RIVUS_MEMORY_TOOL_ID, RIVUS_MEMORY_TOOL_PLUGIN_ID, RIVUS_MEMORY_TOOL_VERSION, RIVUS_PLUGIN_API_VERSION, RivusDaemonConfigError, RivusDeploymentAutomationReadinessError, RivusDeploymentDaemonLifecycleError, RivusDeploymentManifestError, RivusDeploymentReadinessError, RivusPluginConformanceError, RivusPluginLoadError, RivusToolInputRejected, SessionSchedulerCapacityExceeded, SessionSchedulerDisposed, ToolInvocationDenied, UnsupportedFeishuCardAction, UnsupportedFeishuMessage, WorkspaceInstructionsSourceError, assembleAgentContext, assertRivusPluginConforms, commitAutomationOutcome, createAgentCommandFromFeishuCardAction, createAgentCommandFromFeishuMessage, createAgentConversationMessages, createAgentDomainEventHandler, createAgentDomainEventSink, createAgentDomainEventSinkFromCallback, createAgentHarness, createAgentHarnessClient, createAgentHarnessPooledRuntime, createAgentInstanceRegistry, createAgentLoopFromCallback, createAgentLoopModelExecutionEnd, createAgentLoopModelExecutionStart, createAgentLoopPromptTransformer, createAgentLoopSkillExecutionEnd, createAgentLoopSkillExecutionStart, createAgentLoopTextDelta, createAgentLoopThinkingDelta, createAgentLoopToolExecutionEnd, createAgentLoopToolExecutionStart, createAgentLoopToolExecutionUpdate, createAgentMemoryService, createAgentRunUpdateHandler, createAgentRuntime, createAgentRuntimePool, createAgentTranscriptMessages, createAgentTranscriptTurn, createAgentsMdInstructionsProvider, createAsyncIterableAgentLoop, createAutomationMandateStore, createCoalescingFeishuPublisher, createCompactionService, createCompositeRivusDaemonTransport, createConfiguredFeishuAutomationCardSender, createConfiguredFeishuCardKitPublisher, createConfiguredFeishuCardKitTargetPreparation, createConfiguredFeishuHumanInteractionPresenter, createConfiguredFeishuOpenApiClient, createConfiguredFeishuTextReplySender, createConfiguredRivusDaemonBootstrap, createConfiguredRivusDeploymentDaemon, createDailyAutomationSchedule, createDefaultAgentHarness, createDefaultAgentHarnessClient, createDefaultAgentHarnessClientFromCallback, createDefaultAgentHarnessClientFromTextCallback, createDefaultAgentHarnessFromCallback, createDefaultAgentHarnessFromTextCallback, createDefaultAgentRuntime, createDefaultAgentRuntimeFromCallback, createDefaultAgentRuntimeFromTextCallback, createDelegationService, createDeliveryOutbox, createEventAgentLoop, createFakeRivusPlugin, createFeishuAgentDaemon, createFeishuAgentRunCard, createFeishuAgentRuntime, createFeishuCardActionCallbackResponse, createFeishuCardActionErrorResponse, createFeishuCardDeliveryLedger, createFeishuCardDeliveryReconciler, createFeishuCardKitOpenApiClient, createFeishuCardKitOpenApiTargetCreator, createFeishuCardKitPublisher, createFeishuCardTargetPreparation, createFeishuConversationId, createFeishuCotPublisher, createFeishuDeploymentEndpoint, createFeishuEventHandlers, createFeishuHumanInteractionCard, createFeishuHumanInteractionPresenter, createFeishuInboxRepository, createFeishuMessageQueue, createFeishuMessageWorker, createFeishuOpenApiClient, createFeishuPeriodicFlush, createFeishuPresentationPreparation, createFeishuSessionKey, createFeishuStreamProjector, createFeishuTenantAccessTokenProvider, createFeishuWebSocketDaemon, createFeishuWorkerLoop, createFixedClock, createHumanInteractionEndpointRegistry, createHumanInteractionService, createHumanInteractionToolApprovalGateway, createInMemoryFeishuCardTargetRegistry, createInMemoryHumanInteractionRepository, createInvocationAuthority, createJsonFetchRequest, createJsonFileFeishuCardTargetRegistry, createJsonlAgentEventLog, createJsonlHumanInteractionRepository, createLangfuseAgentTelemetry, createLazyFeishuWebSocketEventDispatcher, createMemoryNamespace, createOpenTelemetryAgentEventSink, createOpenTelemetryAgentTelemetry, createPiAgentLoop, createPiSdkAgentLoop, createPiSessionRegistry, createPiSkillRuntime, createPiToolNameResolver, createPiToolProxyDefinitions, createPluginStateStore, createProjectMemoryPromptPreparer, createRateLimitedFeishuPublisher, createRecoveryAction, createRecoveryControl, createRivusAgentHost, createRivusDaemonProcess, createRivusDaemonShutdownController, createRivusDaemonStatusHttpServer, createRivusDaemonStatusReporter, createRivusDeploymentCliProcess, createRivusDeploymentDaemon, createRivusEnvFromOpenClawConfig, createRivusMemoryTool, createRivusMemoryToolContract, createRivusMemoryToolDescriptor, createRivusPluginCatalog, createRoutedHumanInteractionToolApprovalService, createScheduledAutomation, createSequenceRunIds, createSessionScheduler, createSubagentCoordinator, createSystemClock, createTelemetryContentRedactor, createTextAgentLoop, createTextAgentLoopFromCallback, createToolBroker, createToolInputDigest, createToolOperationLedger, createUuidRunIds, createWorkspaceRootHandle, describeFeishuMessageIntake, evolveAgentRun, formatRivusEnvFile, initialAgentRunState, intersectToolIds, isAgentToolExecutionEvent, isAssistantTextDeltaEvent, isAssistantThinkingDeltaEvent, isTerminalAgentDomainEvent, isTerminalAgentRunPhase, loadNodeRivusPluginModule, loadRivusDaemonConfig, loadRivusDeployment, loadRivusDeploymentManifest, normalizeStableJson, openJsonAutomationTickRepository, openJsonlAgentMemoryService, openJsonlFeishuCardDeliveryLedger, openJsonlFeishuInboxRepository, openJsonlRecoveryControl, openJsonlToolOperationLedger, replayAgentHistory, replayAgentTranscript, requiresToolApproval, resolveFeishuEndpointCredentials, resolveLangfuseTelemetryConfig, resolveRivusAgentDefinition, resolveRivusProjectSpace, restoreAgentHistory, restoreConfiguredRivusDaemonBootstrap, restrictMemoryScopesForAudience, runRivusDaemonCli, shouldAcceptFeishuEndpointMessage, transitionHumanInteraction, validateProjectSkillCatalog, validateProjectSkillCommand, validateRivusDeploymentManifest };
7429
+ export { AgentContextBudgetExceeded, AgentEventHandlerFailed, AgentEventLogStoreError, AgentEventSinkFailed, AgentHarnessBusy, AgentInstanceBusy, AgentInstanceConflict, AgentLoopFailed, AgentMemoryError, AgentRunCancelled, AgentRuntimeDisposed, AutomationMandateError, CardPresentationTransitionDenied, CompactionError, DEFAULT_CARD_STREAM_LEASE_MS, DelegationDenied, DeliveryOutboxError, FeishuCardPresentationNotFound, FeishuCardTargetNotFound, FeishuCardTargetRegistryStoreError, FeishuCotProtocolError, FeishuEndpointCredentialError, FeishuOpenApiError, FeishuTenantAccessTokenError, HumanInteractionRepositoryError, HumanInteractionTransitionDenied, InvalidFeishuCardAction, InvalidFeishuMessageContent, InvalidFeishuSessionReference, InvalidInvocationAuthority, InvalidProjectSkillCatalog, InvalidRecoveryAction, InvalidRivusEndpointBinding, InvalidRivusPlugin, InvalidRivusProjectSpace, InvalidStableJson, InvalidToolInput, InvalidWorkspaceRoot, LangfuseTelemetryConfigError, MEMORY_SCOPES, OpenClawEnvImportError, PluginStateConflict, RIVUS_MEMORY_TOOL_ID, RIVUS_MEMORY_TOOL_PLUGIN_ID, RIVUS_MEMORY_TOOL_VERSION, RIVUS_PLUGIN_API_VERSION, RivusDaemonConfigError, RivusDeploymentAutomationReadinessError, RivusDeploymentDaemonLifecycleError, RivusDeploymentManifestError, RivusDeploymentReadinessError, RivusPluginConformanceError, RivusPluginLoadError, RivusToolInputRejected, SessionSchedulerCapacityExceeded, SessionSchedulerDisposed, ToolInvocationDenied, UnsupportedFeishuCardAction, UnsupportedFeishuMessage, WorkspaceInstructionsSourceError, acceptsCardPresentationProgress, activeCardPresentation, assembleAgentContext, assertRivusPluginConforms, commitAutomationOutcome, createAgentCommandFromFeishuCardAction, createAgentCommandFromFeishuMessage, createAgentConversationMessages, createAgentDomainEventHandler, createAgentDomainEventSink, createAgentDomainEventSinkFromCallback, createAgentHarness, createAgentHarnessClient, createAgentHarnessPooledRuntime, createAgentInstanceRegistry, createAgentLoopFromCallback, createAgentLoopModelExecutionEnd, createAgentLoopModelExecutionStart, createAgentLoopPromptTransformer, createAgentLoopSkillExecutionEnd, createAgentLoopSkillExecutionStart, createAgentLoopTextDelta, createAgentLoopThinkingDelta, createAgentLoopToolExecutionEnd, createAgentLoopToolExecutionStart, createAgentLoopToolExecutionUpdate, createAgentMemoryService, createAgentRunUpdateHandler, createAgentRuntime, createAgentRuntimePool, createAgentTranscriptMessages, createAgentTranscriptTurn, createAgentsMdInstructionsProvider, createAsyncIterableAgentLoop, createAutomationMandateStore, createCoalescingFeishuPublisher, createCompactionService, createCompositeRivusDaemonTransport, createConfiguredFeishuAutomationCardSender, createConfiguredFeishuCardKitPublisher, createConfiguredFeishuCardKitTargetCreator, createConfiguredFeishuCardRolloverRuntime, createConfiguredFeishuHumanInteractionPresenter, createConfiguredFeishuOpenApiClient, createConfiguredFeishuTextReplySender, createConfiguredRivusDaemonBootstrap, createConfiguredRivusDeploymentDaemon, createDailyAutomationSchedule, createDefaultAgentHarness, createDefaultAgentHarnessClient, createDefaultAgentHarnessClientFromCallback, createDefaultAgentHarnessClientFromTextCallback, createDefaultAgentHarnessFromCallback, createDefaultAgentHarnessFromTextCallback, createDefaultAgentRuntime, createDefaultAgentRuntimeFromCallback, createDefaultAgentRuntimeFromTextCallback, createDelegationService, createDeliveryOutbox, createEventAgentLoop, createFakeRivusPlugin, createFeishuAgentDaemon, createFeishuAgentRunCard, createFeishuAgentRuntime, createFeishuCardActionCallbackResponse, createFeishuCardActionErrorResponse, createFeishuCardDeliveryLedger, createFeishuCardDeliveryReconciler, createFeishuCardKitOpenApiClient, createFeishuCardKitOpenApiTargetCreator, createFeishuCardKitPublisher, createFeishuCardPresentationStore, createFeishuCardRollover, createFeishuCardRolloverSupervisor, createFeishuCardTargetPreparation, createFeishuConversationId, createFeishuCotPublisher, createFeishuDeploymentEndpoint, createFeishuEventHandlers, createFeishuHumanInteractionCard, createFeishuHumanInteractionPresenter, createFeishuInboxRepository, createFeishuMessageQueue, createFeishuMessageWorker, createFeishuOpenApiClient, createFeishuPeriodicFlush, createFeishuPresentationPreparation, createFeishuSessionKey, createFeishuStreamProjector, createFeishuTenantAccessTokenProvider, createFeishuWebSocketDaemon, createFeishuWorkerLoop, createFixedClock, createHumanInteractionEndpointRegistry, createHumanInteractionService, createHumanInteractionToolApprovalGateway, createInMemoryFeishuCardTargetRegistry, createInMemoryHumanInteractionRepository, createInvocationAuthority, createJsonFetchRequest, createJsonFileFeishuCardTargetRegistry, createJsonlAgentEventLog, createJsonlHumanInteractionRepository, createLangfuseAgentTelemetry, createLazyFeishuWebSocketEventDispatcher, createMemoryNamespace, createOpenTelemetryAgentEventSink, createOpenTelemetryAgentTelemetry, createPiAgentLoop, createPiSdkAgentLoop, createPiSessionRegistry, createPluginStateStore, createProjectMemoryPromptPreparer, createRateLimitedFeishuPublisher, createRecoveryAction, createRecoveryControl, createRivusAgentHost, createRivusDaemonProcess, createRivusDaemonShutdownController, createRivusDaemonStatusHttpServer, createRivusDaemonStatusReporter, createRivusDeploymentCliProcess, createRivusDeploymentDaemon, createRivusEnvFromOpenClawConfig, createRivusMemoryTool, createRivusMemoryToolContract, createRivusMemoryToolDescriptor, createRivusPluginCatalog, createRoutedHumanInteractionToolApprovalService, createScheduledAutomation, createSequenceRunIds, createSessionScheduler, createSubagentCoordinator, createSystemClock, createTelemetryContentRedactor, createTestClock, createTextAgentLoop, createTextAgentLoopFromCallback, createToolBroker, createToolInputDigest, createToolOperationLedger, createUuidRunIds, createWorkspaceRootHandle, describeFeishuMessageIntake, evolveAgentRun, formatRivusEnvFile, initialAgentRunState, intersectToolIds, isAgentToolExecutionEvent, isAssistantTextDeltaEvent, isAssistantThinkingDeltaEvent, isCardPresentationHandoffDue, isTerminalAgentDomainEvent, isTerminalAgentRunPhase, loadNodeRivusPluginModule, loadRivusDaemonConfig, loadRivusDeployment, loadRivusDeploymentManifest, normalizeStableJson, openJsonAutomationTickRepository, openJsonlAgentMemoryService, openJsonlFeishuCardDeliveryLedger, openJsonlFeishuInboxRepository, openJsonlRecoveryControl, openJsonlToolOperationLedger, replayAgentHistory, replayAgentTranscript, requiresToolApproval, resolveFeishuEndpointCredentials, resolveLangfuseTelemetryConfig, resolveRivusAgentDefinition, resolveRivusProjectSpace, restoreAgentHistory, restoreConfiguredRivusDaemonBootstrap, restrictMemoryScopesForAudience, runRivusDaemonCli, shouldAcceptFeishuEndpointMessage, transitionHumanInteraction, validateProjectSkillCatalog, validateProjectSkillCommand, validateRivusDeploymentManifest };