@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/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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
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
|
|
3
|
+
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";
|
|
4
4
|
import { n as assertRivusPluginConforms, r as createFakeRivusPlugin, t as RivusPluginConformanceError } from "./rivus-plugin-testkit.js";
|
|
5
5
|
import { Cause, Deferred, Effect, Exit, Fiber, Option, Stream } from "effect";
|
|
6
6
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -134,7 +134,7 @@ function createFeishuCardDeliveryReconciler(options) {
|
|
|
134
134
|
return { reconcile: () => Effect.gen(function* () {
|
|
135
135
|
const projector = createFeishuStreamProjector();
|
|
136
136
|
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);
|
|
137
|
+
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
138
|
let repaired = 0;
|
|
139
139
|
for (const [runId, action] of terminalByRun) {
|
|
140
140
|
if (options.ledger.isTerminalPublished(runId)) continue;
|
|
@@ -2261,8 +2261,8 @@ function createFeishuMessageWorker(options) {
|
|
|
2261
2261
|
}) };
|
|
2262
2262
|
}
|
|
2263
2263
|
//#endregion
|
|
2264
|
-
//#region src/application/
|
|
2265
|
-
function
|
|
2264
|
+
//#region src/application/support/periodic-effect-loop.ts
|
|
2265
|
+
function createPeriodicEffectLoop(options) {
|
|
2266
2266
|
let running = false;
|
|
2267
2267
|
let fiber;
|
|
2268
2268
|
const reportError = (error) => {
|
|
@@ -2270,7 +2270,7 @@ function createFeishuWorkerLoop(options) {
|
|
|
2270
2270
|
return reported instanceof Promise ? Effect.promise(() => reported) : Effect.void;
|
|
2271
2271
|
};
|
|
2272
2272
|
const continueAfterReporting = (effect) => effect.pipe(Effect.asVoid, Effect.catchAll((error) => reportError(error)));
|
|
2273
|
-
const cycle = Effect.suspend(() => continueAfterReporting(options.
|
|
2273
|
+
const cycle = Effect.suspend(() => continueAfterReporting(options.run()).pipe(Effect.flatMap(() => continueAfterReporting(options.sleep(options.intervalMs))), Effect.flatMap(() => cycle)));
|
|
2274
2274
|
return {
|
|
2275
2275
|
running: () => running,
|
|
2276
2276
|
start: () => {
|
|
@@ -2287,6 +2287,16 @@ function createFeishuWorkerLoop(options) {
|
|
|
2287
2287
|
};
|
|
2288
2288
|
}
|
|
2289
2289
|
//#endregion
|
|
2290
|
+
//#region src/application/feishu/feishu-worker-loop.ts
|
|
2291
|
+
function createFeishuWorkerLoop(options) {
|
|
2292
|
+
return createPeriodicEffectLoop({
|
|
2293
|
+
intervalMs: options.intervalMs,
|
|
2294
|
+
...options.onError ? { onError: options.onError } : {},
|
|
2295
|
+
run: () => options.drainAvailable(),
|
|
2296
|
+
sleep: options.sleep
|
|
2297
|
+
});
|
|
2298
|
+
}
|
|
2299
|
+
//#endregion
|
|
2290
2300
|
//#region src/application/daemon/rivus-daemon-process.ts
|
|
2291
2301
|
function createRivusDaemonProcess(options) {
|
|
2292
2302
|
let running = false;
|
|
@@ -2364,6 +2374,7 @@ function createRivusDaemonStatusReporter(options) {
|
|
|
2364
2374
|
const activeSessionKey = availability?.busy ? availability.activeSessionKey : activeRun?.sessionKey;
|
|
2365
2375
|
return {
|
|
2366
2376
|
agentId: options.agentId,
|
|
2377
|
+
...options.cardPresentations ? { cards: options.cardPresentations() } : {},
|
|
2367
2378
|
harness: {
|
|
2368
2379
|
...activeRunId !== void 0 ? { activeRunId } : {},
|
|
2369
2380
|
...activeRunState !== void 0 ? { activeRunState } : {},
|
|
@@ -2764,14 +2775,41 @@ async function stopWebSocketClient(client) {
|
|
|
2764
2775
|
else await client.disconnect?.();
|
|
2765
2776
|
}
|
|
2766
2777
|
//#endregion
|
|
2778
|
+
//#region src/application/feishu/feishu-card-rollover-supervisor.ts
|
|
2779
|
+
const DEFAULT_INTERVAL_MS = 1e3;
|
|
2780
|
+
function createFeishuCardRolloverSupervisor(options) {
|
|
2781
|
+
const intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;
|
|
2782
|
+
if (!Number.isSafeInteger(intervalMs) || intervalMs < 1) throw new Error("Feishu card rollover supervisor interval must be a positive integer");
|
|
2783
|
+
const tick = () => Effect.gen(function* () {
|
|
2784
|
+
const now = yield* options.clock.now;
|
|
2785
|
+
const results = [];
|
|
2786
|
+
for (const runId of options.rollover.dueRunIds(now)) results.push(yield* options.rollover.handoff(runId));
|
|
2787
|
+
return { results };
|
|
2788
|
+
});
|
|
2789
|
+
const loop = createPeriodicEffectLoop({
|
|
2790
|
+
intervalMs,
|
|
2791
|
+
...options.onError ? { onError: options.onError } : {},
|
|
2792
|
+
run: tick,
|
|
2793
|
+
sleep: options.sleep
|
|
2794
|
+
});
|
|
2795
|
+
return {
|
|
2796
|
+
recover: () => options.rollover.recover().pipe(Effect.asVoid),
|
|
2797
|
+
running: () => loop.running(),
|
|
2798
|
+
start: () => loop.start(),
|
|
2799
|
+
stop: () => loop.stop(),
|
|
2800
|
+
tick
|
|
2801
|
+
};
|
|
2802
|
+
}
|
|
2803
|
+
//#endregion
|
|
2767
2804
|
//#region src/infrastructure/feishu/feishu-agent-run-card.ts
|
|
2805
|
+
const FEISHU_AGENT_CARD_ELEMENT_ID = "rivus_agent_answer";
|
|
2768
2806
|
function createFeishuAgentRunCard(input) {
|
|
2769
2807
|
const presentation = resolveRunPresentation(input);
|
|
2770
2808
|
return {
|
|
2771
2809
|
body: { elements: [
|
|
2772
2810
|
{
|
|
2773
2811
|
content: presentation.content,
|
|
2774
|
-
element_id: input.status === "running" ? input.elementId ?? "rivus_agent_answer" :
|
|
2812
|
+
element_id: input.status === "running" ? input.elementId ?? "rivus_agent_answer" : FEISHU_AGENT_CARD_ELEMENT_ID,
|
|
2775
2813
|
tag: "markdown"
|
|
2776
2814
|
},
|
|
2777
2815
|
{
|
|
@@ -2813,9 +2851,15 @@ function resolveRunPresentation(input) {
|
|
|
2813
2851
|
switch (input.status) {
|
|
2814
2852
|
case "running": return {
|
|
2815
2853
|
content: input.text || "正在思考…",
|
|
2816
|
-
note: "回答将实时更新",
|
|
2854
|
+
note: input.generation ? "接续上一条消息,回答将实时更新" : "回答将实时更新",
|
|
2855
|
+
template: "blue",
|
|
2856
|
+
title: input.generation ? "正在处理(续)" : "正在处理"
|
|
2857
|
+
};
|
|
2858
|
+
case "handoff": return {
|
|
2859
|
+
content: "任务仍在后台处理,进度将继续显示在下一条消息。",
|
|
2860
|
+
note: "本卡片的流式窗口已交接",
|
|
2817
2861
|
template: "blue",
|
|
2818
|
-
title: "
|
|
2862
|
+
title: "已转到新消息"
|
|
2819
2863
|
};
|
|
2820
2864
|
case "completed": return {
|
|
2821
2865
|
content: input.text || "已完成。",
|
|
@@ -2838,36 +2882,125 @@ function resolveRunPresentation(input) {
|
|
|
2838
2882
|
}
|
|
2839
2883
|
}
|
|
2840
2884
|
//#endregion
|
|
2885
|
+
//#region src/infrastructure/feishu/feishu-tenant-token-provider.ts
|
|
2886
|
+
var FeishuTenantAccessTokenError = class {
|
|
2887
|
+
status;
|
|
2888
|
+
code;
|
|
2889
|
+
message;
|
|
2890
|
+
_tag = "FeishuTenantAccessTokenError";
|
|
2891
|
+
constructor(status, code, message) {
|
|
2892
|
+
this.status = status;
|
|
2893
|
+
this.code = code;
|
|
2894
|
+
this.message = message;
|
|
2895
|
+
}
|
|
2896
|
+
};
|
|
2897
|
+
const DEFAULT_REFRESH_WINDOW_MS = 1800 * 1e3;
|
|
2898
|
+
function createFeishuTenantAccessTokenProvider(options) {
|
|
2899
|
+
const baseUrl = (options.baseUrl ?? "https://open.feishu.cn").replace(/\/$/, "");
|
|
2900
|
+
const now = options.now ?? Date.now;
|
|
2901
|
+
const refreshWindowMs = options.refreshWindowMs ?? DEFAULT_REFRESH_WINDOW_MS;
|
|
2902
|
+
let cached;
|
|
2903
|
+
return { getTenantAccessToken: () => Effect.gen(function* () {
|
|
2904
|
+
if (cached && now() < cached.refreshAfterMs) return cached.token;
|
|
2905
|
+
const response = yield* options.request({
|
|
2906
|
+
body: {
|
|
2907
|
+
app_id: options.appId,
|
|
2908
|
+
app_secret: options.appSecret
|
|
2909
|
+
},
|
|
2910
|
+
headers: { "Content-Type": "application/json; charset=utf-8" },
|
|
2911
|
+
method: "POST",
|
|
2912
|
+
url: `${baseUrl}/open-apis/auth/v3/tenant_access_token/internal`
|
|
2913
|
+
});
|
|
2914
|
+
if (response.status < 200 || response.status >= 300 || response.body.code !== 0 || !response.body.tenant_access_token || typeof response.body.expire !== "number") return yield* Effect.fail(new FeishuTenantAccessTokenError(response.status, response.body.code, response.body.msg ?? "Failed to get tenant_access_token"));
|
|
2915
|
+
cached = {
|
|
2916
|
+
refreshAfterMs: now() + response.body.expire * 1e3 - refreshWindowMs,
|
|
2917
|
+
token: response.body.tenant_access_token
|
|
2918
|
+
};
|
|
2919
|
+
return cached.token;
|
|
2920
|
+
}) };
|
|
2921
|
+
}
|
|
2922
|
+
//#endregion
|
|
2923
|
+
//#region src/infrastructure/feishu/feishu-openapi-client.ts
|
|
2924
|
+
var FeishuOpenApiError = class extends Error {
|
|
2925
|
+
status;
|
|
2926
|
+
code;
|
|
2927
|
+
_tag = "FeishuOpenApiError";
|
|
2928
|
+
name = "FeishuOpenApiError";
|
|
2929
|
+
constructor(status, code, message) {
|
|
2930
|
+
super(message);
|
|
2931
|
+
this.status = status;
|
|
2932
|
+
this.code = code;
|
|
2933
|
+
}
|
|
2934
|
+
};
|
|
2935
|
+
function createFeishuOpenApiClient(options) {
|
|
2936
|
+
return { request: (request, errorMessage = "Feishu OpenAPI error") => Effect.gen(function* () {
|
|
2937
|
+
const token = yield* options.getTenantAccessToken();
|
|
2938
|
+
const response = yield* options.request({
|
|
2939
|
+
...request,
|
|
2940
|
+
headers: {
|
|
2941
|
+
Authorization: `Bearer ${token}`,
|
|
2942
|
+
"Content-Type": "application/json; charset=utf-8"
|
|
2943
|
+
}
|
|
2944
|
+
});
|
|
2945
|
+
if (response.status < 200 || response.status >= 300 || response.body.code !== 0) return yield* Effect.fail(new FeishuOpenApiError(response.status, response.body.code, response.body.msg ?? errorMessage));
|
|
2946
|
+
return response;
|
|
2947
|
+
}) };
|
|
2948
|
+
}
|
|
2949
|
+
function createConfiguredFeishuOpenApiClient(options) {
|
|
2950
|
+
const tokenProvider = createFeishuTenantAccessTokenProvider({
|
|
2951
|
+
appId: options.config.feishu.appId,
|
|
2952
|
+
appSecret: options.config.feishu.appSecret,
|
|
2953
|
+
baseUrl: options.config.feishu.baseUrl,
|
|
2954
|
+
request: (request) => options.request(request).pipe(Effect.map((response) => response))
|
|
2955
|
+
});
|
|
2956
|
+
return createFeishuOpenApiClient({
|
|
2957
|
+
getTenantAccessToken: () => tokenProvider.getTenantAccessToken(),
|
|
2958
|
+
request: (request) => options.request(request).pipe(Effect.map((response) => response))
|
|
2959
|
+
});
|
|
2960
|
+
}
|
|
2961
|
+
//#endregion
|
|
2841
2962
|
//#region src/infrastructure/feishu/feishu-cardkit-openapi-client.ts
|
|
2842
2963
|
function createFeishuCardKitOpenApiClient(options) {
|
|
2843
2964
|
const baseUrl = (options.baseUrl ?? "https://open.feishu.cn").replace(/\/$/, "");
|
|
2844
2965
|
const agentName = options.agentName ?? "Rivus Agent";
|
|
2966
|
+
const streamingClosedCards = /* @__PURE__ */ new Set();
|
|
2845
2967
|
const call = (request) => options.client.request(request).pipe(Effect.asVoid);
|
|
2968
|
+
const updateTerminal = (request, status) => updateWholeCard(baseUrl, agentName, request, status, call).pipe(Effect.tap(() => Effect.sync(() => streamingClosedCards.delete(request.cardId))));
|
|
2846
2969
|
return {
|
|
2847
|
-
cancel: (request) =>
|
|
2848
|
-
fail: (request) =>
|
|
2849
|
-
finish: (request) =>
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2970
|
+
cancel: (request) => updateTerminal(request, "cancelled"),
|
|
2971
|
+
fail: (request) => updateTerminal(request, "failed"),
|
|
2972
|
+
finish: (request) => updateTerminal(request, "completed"),
|
|
2973
|
+
handoff: (request) => Effect.sync(() => streamingClosedCards.add(request.cardId)).pipe(Effect.flatMap(() => updateWholeCard(baseUrl, agentName, request, "handoff", call))),
|
|
2974
|
+
updateText: (request) => {
|
|
2975
|
+
if (streamingClosedCards.has(request.cardId)) return Effect.void;
|
|
2976
|
+
return call({
|
|
2977
|
+
body: {
|
|
2978
|
+
content: request.content,
|
|
2979
|
+
sequence: request.sequence
|
|
2980
|
+
},
|
|
2981
|
+
method: "PUT",
|
|
2982
|
+
url: `${baseUrl}/open-apis/cardkit/v1/cards/${encodeURIComponent(request.cardId)}/elements/${encodeURIComponent(request.elementId)}/content`
|
|
2983
|
+
}).pipe(Effect.catchAll((error) => {
|
|
2984
|
+
if (!isStreamingClosed(error)) return Effect.fail(error);
|
|
2985
|
+
return Effect.sync(() => {
|
|
2986
|
+
streamingClosedCards.add(request.cardId);
|
|
2987
|
+
options.onStreamingClosed?.(request.cardId);
|
|
2988
|
+
});
|
|
2989
|
+
}));
|
|
2990
|
+
}
|
|
2858
2991
|
};
|
|
2859
2992
|
}
|
|
2860
|
-
function
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
}) : status === "cancelled" ? createFeishuAgentRunCard({
|
|
2993
|
+
function isStreamingClosed(error) {
|
|
2994
|
+
return error instanceof FeishuOpenApiError && (error.code === 200850 || error.code === 300309);
|
|
2995
|
+
}
|
|
2996
|
+
function updateWholeCard(baseUrl, agentName, request, status, call) {
|
|
2997
|
+
const card = status === "completed" ? createFeishuAgentRunCard({
|
|
2866
2998
|
agentName,
|
|
2867
|
-
status
|
|
2999
|
+
status,
|
|
3000
|
+
text: "text" in request ? request.text : ""
|
|
2868
3001
|
}) : createFeishuAgentRunCard({
|
|
2869
3002
|
agentName,
|
|
2870
|
-
status
|
|
3003
|
+
status
|
|
2871
3004
|
});
|
|
2872
3005
|
return call({
|
|
2873
3006
|
body: {
|
|
@@ -2895,6 +3028,10 @@ function createFeishuCardKitPublisher(options) {
|
|
|
2895
3028
|
elementId: target.elementId,
|
|
2896
3029
|
sequence
|
|
2897
3030
|
});
|
|
3031
|
+
case "handoff": return yield* options.client.handoff({
|
|
3032
|
+
cardId: target.cardId,
|
|
3033
|
+
sequence
|
|
3034
|
+
});
|
|
2898
3035
|
case "finish":
|
|
2899
3036
|
yield* options.client.finish({
|
|
2900
3037
|
cardId: target.cardId,
|
|
@@ -2944,6 +3081,7 @@ function createCoalescingFeishuPublisher(options) {
|
|
|
2944
3081
|
case "update_text": return Effect.sync(() => {
|
|
2945
3082
|
pendingTextByRun.set(action.runId, action.text);
|
|
2946
3083
|
});
|
|
3084
|
+
case "handoff": return options.publisher.publish(action);
|
|
2947
3085
|
case "finish": return Effect.gen(function* () {
|
|
2948
3086
|
pendingTextByRun.set(action.runId, action.text);
|
|
2949
3087
|
yield* flushRun(action.runId);
|
|
@@ -2976,7 +3114,8 @@ function createConfiguredFeishuCardKitPublisher(options) {
|
|
|
2976
3114
|
client: createFeishuCardKitOpenApiClient({
|
|
2977
3115
|
...options.agentName === void 0 ? {} : { agentName: options.agentName },
|
|
2978
3116
|
baseUrl: options.config.feishu.baseUrl,
|
|
2979
|
-
client: options.client
|
|
3117
|
+
client: options.client,
|
|
3118
|
+
...options.onStreamingClosed === void 0 ? {} : { onStreamingClosed: options.onStreamingClosed }
|
|
2980
3119
|
}),
|
|
2981
3120
|
...options.ledger ? { ledger: options.ledger } : {},
|
|
2982
3121
|
resolveTarget: options.resolveTarget
|
|
@@ -2988,114 +3127,41 @@ function createConfiguredFeishuCardKitPublisher(options) {
|
|
|
2988
3127
|
}) });
|
|
2989
3128
|
}
|
|
2990
3129
|
//#endregion
|
|
2991
|
-
//#region src/infrastructure/feishu/feishu-tenant-token-provider.ts
|
|
2992
|
-
var FeishuTenantAccessTokenError = class {
|
|
2993
|
-
status;
|
|
2994
|
-
code;
|
|
2995
|
-
message;
|
|
2996
|
-
_tag = "FeishuTenantAccessTokenError";
|
|
2997
|
-
constructor(status, code, message) {
|
|
2998
|
-
this.status = status;
|
|
2999
|
-
this.code = code;
|
|
3000
|
-
this.message = message;
|
|
3001
|
-
}
|
|
3002
|
-
};
|
|
3003
|
-
const DEFAULT_REFRESH_WINDOW_MS = 1800 * 1e3;
|
|
3004
|
-
function createFeishuTenantAccessTokenProvider(options) {
|
|
3005
|
-
const baseUrl = (options.baseUrl ?? "https://open.feishu.cn").replace(/\/$/, "");
|
|
3006
|
-
const now = options.now ?? Date.now;
|
|
3007
|
-
const refreshWindowMs = options.refreshWindowMs ?? DEFAULT_REFRESH_WINDOW_MS;
|
|
3008
|
-
let cached;
|
|
3009
|
-
return { getTenantAccessToken: () => Effect.gen(function* () {
|
|
3010
|
-
if (cached && now() < cached.refreshAfterMs) return cached.token;
|
|
3011
|
-
const response = yield* options.request({
|
|
3012
|
-
body: {
|
|
3013
|
-
app_id: options.appId,
|
|
3014
|
-
app_secret: options.appSecret
|
|
3015
|
-
},
|
|
3016
|
-
headers: { "Content-Type": "application/json; charset=utf-8" },
|
|
3017
|
-
method: "POST",
|
|
3018
|
-
url: `${baseUrl}/open-apis/auth/v3/tenant_access_token/internal`
|
|
3019
|
-
});
|
|
3020
|
-
if (response.status < 200 || response.status >= 300 || response.body.code !== 0 || !response.body.tenant_access_token || typeof response.body.expire !== "number") return yield* Effect.fail(new FeishuTenantAccessTokenError(response.status, response.body.code, response.body.msg ?? "Failed to get tenant_access_token"));
|
|
3021
|
-
cached = {
|
|
3022
|
-
refreshAfterMs: now() + response.body.expire * 1e3 - refreshWindowMs,
|
|
3023
|
-
token: response.body.tenant_access_token
|
|
3024
|
-
};
|
|
3025
|
-
return cached.token;
|
|
3026
|
-
}) };
|
|
3027
|
-
}
|
|
3028
|
-
//#endregion
|
|
3029
|
-
//#region src/infrastructure/feishu/feishu-openapi-client.ts
|
|
3030
|
-
var FeishuOpenApiError = class extends Error {
|
|
3031
|
-
status;
|
|
3032
|
-
code;
|
|
3033
|
-
_tag = "FeishuOpenApiError";
|
|
3034
|
-
name = "FeishuOpenApiError";
|
|
3035
|
-
constructor(status, code, message) {
|
|
3036
|
-
super(message);
|
|
3037
|
-
this.status = status;
|
|
3038
|
-
this.code = code;
|
|
3039
|
-
}
|
|
3040
|
-
};
|
|
3041
|
-
function createFeishuOpenApiClient(options) {
|
|
3042
|
-
return { request: (request, errorMessage = "Feishu OpenAPI error") => Effect.gen(function* () {
|
|
3043
|
-
const token = yield* options.getTenantAccessToken();
|
|
3044
|
-
const response = yield* options.request({
|
|
3045
|
-
...request,
|
|
3046
|
-
headers: {
|
|
3047
|
-
Authorization: `Bearer ${token}`,
|
|
3048
|
-
"Content-Type": "application/json; charset=utf-8"
|
|
3049
|
-
}
|
|
3050
|
-
});
|
|
3051
|
-
if (response.status < 200 || response.status >= 300 || response.body.code !== 0) return yield* Effect.fail(new FeishuOpenApiError(response.status, response.body.code, response.body.msg ?? errorMessage));
|
|
3052
|
-
return response;
|
|
3053
|
-
}) };
|
|
3054
|
-
}
|
|
3055
|
-
function createConfiguredFeishuOpenApiClient(options) {
|
|
3056
|
-
const tokenProvider = createFeishuTenantAccessTokenProvider({
|
|
3057
|
-
appId: options.config.feishu.appId,
|
|
3058
|
-
appSecret: options.config.feishu.appSecret,
|
|
3059
|
-
baseUrl: options.config.feishu.baseUrl,
|
|
3060
|
-
request: (request) => options.request(request).pipe(Effect.map((response) => response))
|
|
3061
|
-
});
|
|
3062
|
-
return createFeishuOpenApiClient({
|
|
3063
|
-
getTenantAccessToken: () => tokenProvider.getTenantAccessToken(),
|
|
3064
|
-
request: (request) => options.request(request).pipe(Effect.map((response) => response))
|
|
3065
|
-
});
|
|
3066
|
-
}
|
|
3067
|
-
//#endregion
|
|
3068
3130
|
//#region src/infrastructure/feishu/feishu-cardkit-target-preparation.ts
|
|
3069
|
-
const DEFAULT_ELEMENT_ID =
|
|
3131
|
+
const DEFAULT_ELEMENT_ID = FEISHU_AGENT_CARD_ELEMENT_ID;
|
|
3070
3132
|
function createFeishuCardTargetPreparation(options) {
|
|
3071
3133
|
return (run) => Effect.gen(function* () {
|
|
3072
3134
|
const target = yield* options.createTarget(run);
|
|
3073
|
-
yield* options.
|
|
3135
|
+
yield* options.presentations.bindRun(run, target);
|
|
3074
3136
|
});
|
|
3075
3137
|
}
|
|
3076
3138
|
function createConfiguredFeishuCardKitTargetPreparation(options) {
|
|
3077
|
-
const creator =
|
|
3139
|
+
const creator = createConfiguredFeishuCardKitTargetCreator(options);
|
|
3140
|
+
return createFeishuCardTargetPreparation({
|
|
3141
|
+
createTarget: (run) => creator.createTarget(run),
|
|
3142
|
+
presentations: options.presentations
|
|
3143
|
+
});
|
|
3144
|
+
}
|
|
3145
|
+
function createConfiguredFeishuCardKitTargetCreator(options) {
|
|
3146
|
+
return createFeishuCardKitOpenApiTargetCreator({
|
|
3078
3147
|
baseUrl: options.config.feishu.baseUrl,
|
|
3079
3148
|
client: options.client,
|
|
3080
3149
|
elementId: options.elementId ?? DEFAULT_ELEMENT_ID,
|
|
3081
3150
|
...options.initialContent === void 0 ? {} : { initialContent: options.initialContent },
|
|
3082
3151
|
...options.title === void 0 ? {} : { title: options.title }
|
|
3083
3152
|
});
|
|
3084
|
-
return createFeishuCardTargetPreparation({
|
|
3085
|
-
createTarget: (run) => creator.createTarget(run),
|
|
3086
|
-
registry: options.registry
|
|
3087
|
-
});
|
|
3088
3153
|
}
|
|
3089
3154
|
function createFeishuCardKitOpenApiTargetCreator(options) {
|
|
3090
3155
|
const baseUrl = (options.baseUrl ?? "https://open.feishu.cn").replace(/\/$/, "");
|
|
3091
3156
|
const title = options.title ?? "Rivus Agent";
|
|
3092
3157
|
const initialContent = options.initialContent ?? "";
|
|
3093
|
-
return { createTarget: (run) => Effect.gen(function* () {
|
|
3158
|
+
return { createTarget: (run, createOptions) => Effect.gen(function* () {
|
|
3094
3159
|
const cardId = yield* readStringData(yield* options.client.request({
|
|
3095
3160
|
body: {
|
|
3096
3161
|
data: JSON.stringify(createFeishuAgentRunCard({
|
|
3097
3162
|
agentName: title,
|
|
3098
3163
|
elementId: options.elementId,
|
|
3164
|
+
...createOptions?.generation === void 0 ? {} : { generation: createOptions.generation },
|
|
3099
3165
|
runId: run.runId,
|
|
3100
3166
|
sessionKey: run.sessionKey,
|
|
3101
3167
|
status: "running",
|
|
@@ -3132,6 +3198,68 @@ function isRecord$2(value) {
|
|
|
3132
3198
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3133
3199
|
}
|
|
3134
3200
|
//#endregion
|
|
3201
|
+
//#region src/composition/feishu-card-rollover-runtime.ts
|
|
3202
|
+
const MIN_SUPERVISOR_INTERVAL_MS = 200;
|
|
3203
|
+
const MAX_SUPERVISOR_INTERVAL_MS = 5e3;
|
|
3204
|
+
function createConfiguredFeishuCardRolloverRuntime(options) {
|
|
3205
|
+
const leaseMs = options.config.feishu.cardStreamLeaseMs;
|
|
3206
|
+
let rollover;
|
|
3207
|
+
const publisher = createConfiguredFeishuCardKitPublisher({
|
|
3208
|
+
...options.agentName === void 0 ? {} : { agentName: options.agentName },
|
|
3209
|
+
client: options.client,
|
|
3210
|
+
config: options.config,
|
|
3211
|
+
...options.ledger ? { ledger: options.ledger } : {},
|
|
3212
|
+
onStreamingClosed: (cardId) => rollover?.observeStreamClosed(cardId),
|
|
3213
|
+
resolveTarget: (runId) => options.cardTargets.resolveTarget(runId),
|
|
3214
|
+
sleep: options.sleep
|
|
3215
|
+
});
|
|
3216
|
+
const creator = createConfiguredFeishuCardKitTargetCreator({
|
|
3217
|
+
client: options.client,
|
|
3218
|
+
config: options.config,
|
|
3219
|
+
...options.elementId === void 0 ? {} : { elementId: options.elementId },
|
|
3220
|
+
...options.initialContent === void 0 ? {} : { initialContent: options.initialContent },
|
|
3221
|
+
...options.title === void 0 ? {} : { title: options.title }
|
|
3222
|
+
});
|
|
3223
|
+
const cardRollover = createFeishuCardRollover({
|
|
3224
|
+
clock: options.clock,
|
|
3225
|
+
createSuccessor: ({ generation, run }) => creator.createTarget(run, { generation }),
|
|
3226
|
+
leaseMs,
|
|
3227
|
+
...options.observe ? { observe: options.observe } : {},
|
|
3228
|
+
publisher,
|
|
3229
|
+
store: options.cardTargets
|
|
3230
|
+
});
|
|
3231
|
+
rollover = cardRollover;
|
|
3232
|
+
const supervisor = createFeishuCardRolloverSupervisor({
|
|
3233
|
+
clock: options.clock,
|
|
3234
|
+
intervalMs: options.supervisorIntervalMs ?? resolveSupervisorInterval(leaseMs),
|
|
3235
|
+
...options.onError ? { onError: options.onError } : {},
|
|
3236
|
+
rollover: cardRollover,
|
|
3237
|
+
sleep: options.sleep
|
|
3238
|
+
});
|
|
3239
|
+
return {
|
|
3240
|
+
prepareRun: createFeishuCardTargetPreparation({
|
|
3241
|
+
createTarget: (run) => creator.createTarget(run),
|
|
3242
|
+
presentations: cardRollover
|
|
3243
|
+
}),
|
|
3244
|
+
rollover: cardRollover,
|
|
3245
|
+
supervisor,
|
|
3246
|
+
transport: {
|
|
3247
|
+
running: () => supervisor.running(),
|
|
3248
|
+
start: async () => {
|
|
3249
|
+
await Effect.runPromise(supervisor.recover().pipe(Effect.catchAll((error) => {
|
|
3250
|
+
const reported = options.onError?.(error);
|
|
3251
|
+
return reported instanceof Promise ? Effect.promise(() => reported) : Effect.void;
|
|
3252
|
+
})));
|
|
3253
|
+
supervisor.start();
|
|
3254
|
+
},
|
|
3255
|
+
stop: () => supervisor.stop()
|
|
3256
|
+
}
|
|
3257
|
+
};
|
|
3258
|
+
}
|
|
3259
|
+
function resolveSupervisorInterval(leaseMs) {
|
|
3260
|
+
return Math.max(MIN_SUPERVISOR_INTERVAL_MS, Math.min(MAX_SUPERVISOR_INTERVAL_MS, Math.floor(leaseMs / 10)));
|
|
3261
|
+
}
|
|
3262
|
+
//#endregion
|
|
3135
3263
|
//#region src/composition/rivus-daemon-bootstrap.ts
|
|
3136
3264
|
const DEFAULT_WORKER_INTERVAL_MS$1 = 250;
|
|
3137
3265
|
const DEFAULT_RUN_TIMEOUT_MS = 900 * 1e3;
|
|
@@ -3146,17 +3274,19 @@ function createConfiguredRivusDaemonBootstrap(options) {
|
|
|
3146
3274
|
config: options.config,
|
|
3147
3275
|
request: options.request
|
|
3148
3276
|
});
|
|
3149
|
-
const
|
|
3150
|
-
|
|
3151
|
-
config: options.config,
|
|
3152
|
-
registry: options.cardTargets
|
|
3153
|
-
});
|
|
3154
|
-
const publisher = createConfiguredFeishuCardKitPublisher({
|
|
3277
|
+
const cardRollover = createConfiguredFeishuCardRolloverRuntime({
|
|
3278
|
+
cardTargets: options.cardTargets,
|
|
3155
3279
|
client: openApiClient,
|
|
3280
|
+
clock: options.clock,
|
|
3156
3281
|
config: options.config,
|
|
3157
|
-
|
|
3158
|
-
|
|
3282
|
+
...options.cardLedger ? { ledger: options.cardLedger } : {},
|
|
3283
|
+
...options.observeCardRollover ? { observe: options.observeCardRollover } : {},
|
|
3284
|
+
...options.onWorkerError ? { onError: options.onWorkerError } : {},
|
|
3285
|
+
sleep: options.sleep,
|
|
3286
|
+
...options.cardRolloverIntervalMs === void 0 ? {} : { supervisorIntervalMs: options.cardRolloverIntervalMs }
|
|
3159
3287
|
});
|
|
3288
|
+
const publisher = cardRollover.rollover;
|
|
3289
|
+
const prepareRun = (run) => cardRollover.prepareRun(run);
|
|
3160
3290
|
const periodicFlush = createPeriodicFlush(options, publisher);
|
|
3161
3291
|
const runtime = createFeishuAgentRuntime({
|
|
3162
3292
|
agentId: options.config.agentId,
|
|
@@ -3186,25 +3316,31 @@ function createConfiguredRivusDaemonBootstrap(options) {
|
|
|
3186
3316
|
});
|
|
3187
3317
|
const restoreHistoryFromLog = () => restoreAgentHistory(options.eventLog);
|
|
3188
3318
|
let processRef;
|
|
3189
|
-
let transport = websocketTransport;
|
|
3319
|
+
let transport = createCompositeRivusDaemonTransport({ transports: [websocketTransport, cardRollover.transport] });
|
|
3190
3320
|
const statusReporter = createRivusDaemonStatusReporter({
|
|
3191
3321
|
agentId: options.config.agentId,
|
|
3192
3322
|
availability: () => runtime.harness.getAvailability(),
|
|
3193
3323
|
pending: () => runtime.pending(),
|
|
3194
3324
|
processRunning: () => processRef?.running() ?? false,
|
|
3325
|
+
cardPresentations: () => cardRollover.rollover.status(),
|
|
3195
3326
|
receiveStatus: () => runtime.receiveStatus(),
|
|
3196
3327
|
restoreHistory: restoreHistoryFromLog,
|
|
3197
3328
|
transportRunning: () => transport.running(),
|
|
3198
3329
|
workerLoopRunning: () => workerLoop.running()
|
|
3199
3330
|
});
|
|
3200
3331
|
const statusTransport = options.createStatusTransport?.(statusReporter);
|
|
3201
|
-
if (statusTransport) transport = createCompositeRivusDaemonTransport({ transports: [
|
|
3332
|
+
if (statusTransport) transport = createCompositeRivusDaemonTransport({ transports: [
|
|
3333
|
+
websocketTransport,
|
|
3334
|
+
cardRollover.transport,
|
|
3335
|
+
statusTransport
|
|
3336
|
+
] });
|
|
3202
3337
|
const process = createRivusDaemonProcess({
|
|
3203
3338
|
transport,
|
|
3204
3339
|
workerLoop
|
|
3205
3340
|
});
|
|
3206
3341
|
processRef = process;
|
|
3207
3342
|
return {
|
|
3343
|
+
cardRollover,
|
|
3208
3344
|
cardTargets: options.cardTargets,
|
|
3209
3345
|
eventLog: options.eventLog,
|
|
3210
3346
|
process,
|
|
@@ -4335,6 +4471,79 @@ function createPiSessionRegistry(options) {
|
|
|
4335
4471
|
};
|
|
4336
4472
|
}
|
|
4337
4473
|
//#endregion
|
|
4474
|
+
//#region src/application/feishu/feishu-card-presentation-store.ts
|
|
4475
|
+
var FeishuCardPresentationNotFound = class {
|
|
4476
|
+
runId;
|
|
4477
|
+
_tag = "FeishuCardPresentationNotFound";
|
|
4478
|
+
constructor(runId) {
|
|
4479
|
+
this.runId = runId;
|
|
4480
|
+
}
|
|
4481
|
+
};
|
|
4482
|
+
function createFeishuCardPresentationStore(options = {}) {
|
|
4483
|
+
const chains = new Map(options.initial?.map((chain) => [chain.runId, structuredClone(chain)]) ?? []);
|
|
4484
|
+
const serial = createSerialExecutor();
|
|
4485
|
+
const save = async (next) => {
|
|
4486
|
+
for (const chain of next) chains.set(chain.runId, structuredClone(chain));
|
|
4487
|
+
await options.persist?.([...chains.values()]);
|
|
4488
|
+
};
|
|
4489
|
+
const mutate = (operation) => Effect.tryPromise({
|
|
4490
|
+
try: () => serial.run(operation),
|
|
4491
|
+
catch: (error) => error
|
|
4492
|
+
});
|
|
4493
|
+
const transition = (runId, apply) => mutate(async () => {
|
|
4494
|
+
const current = chains.get(runId);
|
|
4495
|
+
if (!current) throw new FeishuCardPresentationNotFound(runId);
|
|
4496
|
+
const next = apply(current);
|
|
4497
|
+
if (next !== current) await save([next]);
|
|
4498
|
+
return activeCardPresentation(next);
|
|
4499
|
+
});
|
|
4500
|
+
return {
|
|
4501
|
+
bind: (binding) => mutate(async () => {
|
|
4502
|
+
const current = chains.get(binding.runId);
|
|
4503
|
+
if (current && activeCardPresentation(current).cardId === binding.cardId) return activeCardPresentation(current);
|
|
4504
|
+
const created = createCardPresentationChain(binding);
|
|
4505
|
+
await save([created]);
|
|
4506
|
+
return activeCardPresentation(created);
|
|
4507
|
+
}),
|
|
4508
|
+
beginHandoff: ({ handoffAt, runId }) => mutate(async () => {
|
|
4509
|
+
const current = chains.get(runId);
|
|
4510
|
+
if (!current) throw new FeishuCardPresentationNotFound(runId);
|
|
4511
|
+
const next = beginCardPresentationHandoff(current, handoffAt);
|
|
4512
|
+
if (next === current) return {
|
|
4513
|
+
presentation: activeCardPresentation(current),
|
|
4514
|
+
started: false
|
|
4515
|
+
};
|
|
4516
|
+
await save([next]);
|
|
4517
|
+
return {
|
|
4518
|
+
presentation: activeCardPresentation(next),
|
|
4519
|
+
started: true
|
|
4520
|
+
};
|
|
4521
|
+
}),
|
|
4522
|
+
chain: (runId) => {
|
|
4523
|
+
const current = chains.get(runId);
|
|
4524
|
+
return current ? structuredClone(current) : void 0;
|
|
4525
|
+
},
|
|
4526
|
+
chains: () => [...chains.values()].map((chain) => structuredClone(chain)),
|
|
4527
|
+
compensateInterruptedHandoffs: (compensatedAt) => mutate(async () => {
|
|
4528
|
+
const compensated = [...chains.values()].map((chain) => ({
|
|
4529
|
+
chain,
|
|
4530
|
+
next: compensateCardPresentationHandoff(chain, compensatedAt)
|
|
4531
|
+
})).filter(({ chain, next }) => next !== chain).map(({ next }) => next);
|
|
4532
|
+
if (compensated.length > 0) await save(compensated);
|
|
4533
|
+
return compensated.map((chain) => structuredClone(chain));
|
|
4534
|
+
}),
|
|
4535
|
+
completeHandoff: ({ runId, successor }) => transition(runId, (chain) => completeCardPresentationHandoff(chain, successor)),
|
|
4536
|
+
failHandoff: ({ failedAt, runId }) => transition(runId, (chain) => failCardPresentationHandoff(chain, failedAt)).pipe(Effect.asVoid),
|
|
4537
|
+
markTerminal: ({ runId, terminalReceiptId }) => transition(runId, (chain) => markCardPresentationTerminal(chain, terminalReceiptId)).pipe(Effect.asVoid),
|
|
4538
|
+
release: (runId) => mutate(async () => {
|
|
4539
|
+
if (!chains.has(runId)) return;
|
|
4540
|
+
chains.delete(runId);
|
|
4541
|
+
await options.persist?.([...chains.values()]);
|
|
4542
|
+
}),
|
|
4543
|
+
size: () => chains.size
|
|
4544
|
+
};
|
|
4545
|
+
}
|
|
4546
|
+
//#endregion
|
|
4338
4547
|
//#region src/infrastructure/feishu/feishu-card-target-registry.ts
|
|
4339
4548
|
var FeishuCardTargetNotFound = class {
|
|
4340
4549
|
runId;
|
|
@@ -4352,74 +4561,101 @@ var FeishuCardTargetRegistryStoreError = class {
|
|
|
4352
4561
|
this.cause = cause;
|
|
4353
4562
|
}
|
|
4354
4563
|
};
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
}),
|
|
4361
|
-
release: (runId) => Effect.sync(() => {
|
|
4362
|
-
targets.delete(runId);
|
|
4363
|
-
}),
|
|
4364
|
-
resolveTarget: (runId) => Effect.sync(() => targets.get(runId)).pipe(Effect.flatMap((target) => target ? Effect.succeed(target) : Effect.fail(new FeishuCardTargetNotFound(runId)))),
|
|
4365
|
-
size: () => targets.size
|
|
4366
|
-
};
|
|
4564
|
+
const PRESENTATION_FILE_VERSION = 2;
|
|
4565
|
+
const LEGACY_PRESENTATION_TIMESTAMP = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
4566
|
+
function createInMemoryFeishuCardTargetRegistry(initial = []) {
|
|
4567
|
+
const store = createFeishuCardPresentationStore({ initial });
|
|
4568
|
+
return withTargetResolution(store, () => Effect.succeed(store));
|
|
4367
4569
|
}
|
|
4368
4570
|
function createJsonFileFeishuCardTargetRegistry(options) {
|
|
4369
|
-
let
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
throw error;
|
|
4383
|
-
}
|
|
4384
|
-
},
|
|
4385
|
-
catch: (error) => new FeishuCardTargetRegistryStoreError("load", error)
|
|
4386
|
-
});
|
|
4387
|
-
const saveTargets = (targets) => Effect.tryPromise({
|
|
4388
|
-
try: async () => {
|
|
4389
|
-
await mkdir(dirname(options.filePath), { recursive: true });
|
|
4390
|
-
await writeFile(options.filePath, `${JSON.stringify(targets, null, 2)}\n`, "utf8");
|
|
4391
|
-
lastKnownSize = Object.keys(targets).length;
|
|
4392
|
-
},
|
|
4393
|
-
catch: (error) => new FeishuCardTargetRegistryStoreError("save", error)
|
|
4571
|
+
let opened;
|
|
4572
|
+
let loaded;
|
|
4573
|
+
const open = async () => {
|
|
4574
|
+
const store = createFeishuCardPresentationStore({
|
|
4575
|
+
initial: await loadChains(options.filePath),
|
|
4576
|
+
persist: (chains) => saveChains(options.filePath, chains)
|
|
4577
|
+
});
|
|
4578
|
+
loaded = store;
|
|
4579
|
+
return store;
|
|
4580
|
+
};
|
|
4581
|
+
const ready = () => Effect.tryPromise({
|
|
4582
|
+
try: () => opened ??= open(),
|
|
4583
|
+
catch: (error) => error instanceof FeishuCardTargetRegistryStoreError ? error : new FeishuCardTargetRegistryStoreError("load", error)
|
|
4394
4584
|
});
|
|
4585
|
+
const use = (operation) => ready().pipe(Effect.flatMap(operation));
|
|
4586
|
+
return withTargetResolution({
|
|
4587
|
+
bind: (binding) => use((current) => current.bind(binding)),
|
|
4588
|
+
beginHandoff: (input) => use((current) => current.beginHandoff(input)),
|
|
4589
|
+
chain: (runId) => loaded?.chain(runId),
|
|
4590
|
+
chains: () => loaded?.chains() ?? [],
|
|
4591
|
+
compensateInterruptedHandoffs: (compensatedAt) => use((current) => current.compensateInterruptedHandoffs(compensatedAt)),
|
|
4592
|
+
completeHandoff: (input) => use((current) => current.completeHandoff(input)),
|
|
4593
|
+
failHandoff: (input) => use((current) => current.failHandoff(input)),
|
|
4594
|
+
markTerminal: (input) => use((current) => current.markTerminal(input)),
|
|
4595
|
+
release: (runId) => use((current) => current.release(runId)),
|
|
4596
|
+
size: () => loaded?.size() ?? 0
|
|
4597
|
+
}, ready);
|
|
4598
|
+
}
|
|
4599
|
+
function withTargetResolution(store, ready) {
|
|
4395
4600
|
return {
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
const nextTargets = { ...targets };
|
|
4402
|
-
delete nextTargets[runId];
|
|
4403
|
-
return saveTargets(nextTargets);
|
|
4404
|
-
})),
|
|
4405
|
-
resolveTarget: (runId) => loadTargets.pipe(Effect.flatMap((targets) => {
|
|
4406
|
-
const target = targets[runId];
|
|
4407
|
-
return target ? Effect.succeed(target) : Effect.fail(new FeishuCardTargetNotFound(runId));
|
|
4408
|
-
})),
|
|
4409
|
-
size: () => lastKnownSize
|
|
4601
|
+
...store,
|
|
4602
|
+
resolveTarget: (runId) => ready().pipe(Effect.flatMap((current) => {
|
|
4603
|
+
const chain = current.chain(runId);
|
|
4604
|
+
return chain ? Effect.succeed(toTarget(activeCardPresentation(chain))) : Effect.fail(new FeishuCardTargetNotFound(runId));
|
|
4605
|
+
}))
|
|
4410
4606
|
};
|
|
4411
4607
|
}
|
|
4412
|
-
function
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4608
|
+
function toTarget(presentation) {
|
|
4609
|
+
return {
|
|
4610
|
+
cardId: presentation.cardId,
|
|
4611
|
+
elementId: presentation.elementId ?? "rivus_agent_answer"
|
|
4612
|
+
};
|
|
4613
|
+
}
|
|
4614
|
+
async function loadChains(filePath) {
|
|
4615
|
+
try {
|
|
4616
|
+
const raw = await readFile(filePath, "utf8");
|
|
4617
|
+
return parseChains(JSON.parse(raw));
|
|
4618
|
+
} catch (error) {
|
|
4619
|
+
if (isNodeErrorWithCode(error, "ENOENT")) return [];
|
|
4620
|
+
throw new FeishuCardTargetRegistryStoreError("load", error);
|
|
4418
4621
|
}
|
|
4419
|
-
return targets;
|
|
4420
4622
|
}
|
|
4421
|
-
function
|
|
4422
|
-
|
|
4623
|
+
async function saveChains(filePath, chains) {
|
|
4624
|
+
try {
|
|
4625
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
4626
|
+
const runs = Object.fromEntries(chains.map((chain) => [chain.runId, chain]));
|
|
4627
|
+
await writeFile(filePath, `${JSON.stringify({
|
|
4628
|
+
runs,
|
|
4629
|
+
version: PRESENTATION_FILE_VERSION
|
|
4630
|
+
}, null, 2)}\n`, "utf8");
|
|
4631
|
+
} catch (error) {
|
|
4632
|
+
throw new FeishuCardTargetRegistryStoreError("save", error);
|
|
4633
|
+
}
|
|
4634
|
+
}
|
|
4635
|
+
function parseChains(value) {
|
|
4636
|
+
if (!isRecord$4(value)) throw new Error("Feishu card presentation file must contain a JSON object.");
|
|
4637
|
+
if (value.version === void 0) return Object.entries(value).map(([runId, target]) => parseLegacyChain(runId, target));
|
|
4638
|
+
if (value.version !== PRESENTATION_FILE_VERSION || !isRecord$4(value.runs)) throw new Error(`Unsupported Feishu card presentation file version: ${JSON.stringify(value.version)}`);
|
|
4639
|
+
return Object.entries(value.runs).map(([runId, chain]) => parseChain(runId, chain));
|
|
4640
|
+
}
|
|
4641
|
+
function parseLegacyChain(runId, target) {
|
|
4642
|
+
if (!isRecord$4(target) || typeof target.cardId !== "string" || typeof target.elementId !== "string") throw new Error(`Invalid Feishu card target entry for run '${runId}'.`);
|
|
4643
|
+
return createCardPresentationChain({
|
|
4644
|
+
cardId: target.cardId,
|
|
4645
|
+
createdAt: LEGACY_PRESENTATION_TIMESTAMP,
|
|
4646
|
+
elementId: target.elementId,
|
|
4647
|
+
leaseDeadlineAt: LEGACY_PRESENTATION_TIMESTAMP,
|
|
4648
|
+
presentationId: `${runId}#0`,
|
|
4649
|
+
runId,
|
|
4650
|
+
sourceMessageId: ""
|
|
4651
|
+
});
|
|
4652
|
+
}
|
|
4653
|
+
function parseChain(runId, value) {
|
|
4654
|
+
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}'.`);
|
|
4655
|
+
const chain = value;
|
|
4656
|
+
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}'.`);
|
|
4657
|
+
activeCardPresentation(chain);
|
|
4658
|
+
return chain;
|
|
4423
4659
|
}
|
|
4424
4660
|
//#endregion
|
|
4425
4661
|
//#region src/infrastructure/feishu/feishu-cot-tool-presenter.ts
|
|
@@ -5420,14 +5656,19 @@ function createFeishuDeploymentEndpoint(options) {
|
|
|
5420
5656
|
})
|
|
5421
5657
|
});
|
|
5422
5658
|
return {
|
|
5423
|
-
running: () => websocket.running() && workerLoop.running(),
|
|
5659
|
+
running: () => websocket.running() && workerLoop.running() && (options.cardRollover?.running() ?? true),
|
|
5424
5660
|
start: async () => {
|
|
5425
5661
|
execution.beginStart();
|
|
5426
5662
|
try {
|
|
5663
|
+
await options.cardRollover?.start();
|
|
5427
5664
|
await websocket.start();
|
|
5428
5665
|
workerLoop.start();
|
|
5429
5666
|
} catch (startError) {
|
|
5430
|
-
const cleanupErrors = await settleCleanup([
|
|
5667
|
+
const cleanupErrors = await settleCleanup([
|
|
5668
|
+
() => websocket.stop(),
|
|
5669
|
+
() => workerLoop.stop(),
|
|
5670
|
+
() => options.cardRollover?.stop()
|
|
5671
|
+
]);
|
|
5431
5672
|
if (cleanupErrors.length > 0) throw new AggregateError([startError, ...cleanupErrors], "Feishu endpoint startup and cleanup failed");
|
|
5432
5673
|
throw startError;
|
|
5433
5674
|
}
|
|
@@ -5438,7 +5679,8 @@ function createFeishuDeploymentEndpoint(options) {
|
|
|
5438
5679
|
const cleanupErrors = await settleCleanup([
|
|
5439
5680
|
() => websocketStop,
|
|
5440
5681
|
() => execution.cancelActiveAndWait(),
|
|
5441
|
-
() => workerStop
|
|
5682
|
+
() => workerStop,
|
|
5683
|
+
() => options.cardRollover?.stop()
|
|
5442
5684
|
]);
|
|
5443
5685
|
if (cleanupErrors.length === 1) throw cleanupErrors[0];
|
|
5444
5686
|
if (cleanupErrors.length > 1) throw new AggregateError(cleanupErrors, "Feishu endpoint cleanup failed");
|
|
@@ -7398,4 +7640,4 @@ function validateDecisionInput(input) {
|
|
|
7398
7640
|
if (input.recommendedOptionId && !optionIds.includes(input.recommendedOptionId)) throw new Error("recommended user decision option must be available");
|
|
7399
7641
|
}
|
|
7400
7642
|
//#endregion
|
|
7401
|
-
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 };
|
|
7643
|
+
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, createConfiguredFeishuCardKitTargetPreparation, 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, 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, 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 };
|