@rivus/gateway 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -0
  3. package/dist/bootstrap/pi-feishu.d.ts +20 -0
  4. package/dist/bootstrap/pi-feishu.js +671 -0
  5. package/dist/chunks/background-session-authority.js +230 -0
  6. package/dist/chunks/background-session-control-input.js +45 -0
  7. package/dist/chunks/background-session-service.d.ts +390 -0
  8. package/dist/chunks/index.d.ts +4703 -0
  9. package/dist/chunks/node-rivus-deployment-manifest.js +1650 -0
  10. package/dist/chunks/rivus-node-entrypoint.js +4464 -0
  11. package/dist/chunks/service.js +12112 -0
  12. package/dist/cli.d.ts +1 -0
  13. package/dist/cli.js +16 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.js +1215 -0
  16. package/dist/mcp.d.ts +92 -0
  17. package/dist/mcp.js +455 -0
  18. package/package.json +64 -0
  19. package/skills/runtime-management/SKILL.md +65 -0
  20. package/templates/a-share-briefing-analysis.mjs +93 -0
  21. package/templates/a-share-briefing-renderer.mjs +257 -0
  22. package/templates/a-share-index-evidence.mjs +99 -0
  23. package/templates/a-share-market-briefing.mjs +83 -0
  24. package/templates/a-share-market-date.mjs +10 -0
  25. package/templates/a-share-overseas-evidence.mjs +86 -0
  26. package/templates/a-share-policy-evidence.mjs +145 -0
  27. package/templates/a-share-provider-response.mjs +21 -0
  28. package/templates/a-share-sector-evidence.mjs +70 -0
  29. package/templates/acp-stdio-proxy.mjs +58 -0
  30. package/templates/current-weather.mjs +117 -0
  31. package/templates/html-drive-tools.mjs +262 -0
  32. package/templates/https-response-reader.mjs +36 -0
  33. package/templates/langfuse-drive-e2e.mjs +175 -0
  34. package/templates/pi-feishu-deployment.bootstrap.ts +3 -0
  35. package/templates/pi-feishu.bootstrap.ts +242 -0
  36. package/templates/rivus-agents.plugin.mjs +290 -0
  37. package/templates/rivus-langfuse-demo.config.json +37 -0
  38. package/templates/rivus-starter.plugin.mjs +47 -0
  39. package/templates/rivus.config.json +114 -0
@@ -0,0 +1,4464 @@
1
+ import { l as narrowBackgroundSessionDefinition, o as createBackgroundSessionToolContracts } from "./background-session-authority.js";
2
+ import { C as parseRivusModelCliArguments, D as deepFreeze, E as runDeploymentProcessEffect, M as disposeRuntimeCacheEntries, N as invokeRuntimeControl, O as toEffectAgentRuntime, S as createRivusModelManagementWireRequest, T as renderRivusModelCliHelp, a as InvalidRivusProjectSpace, c as RIVUS_RELEASE_DESCRIPTOR, f as gatewayTemplateDirectory, i as resolveFeishuEndpointCredentials, j as createRuntimeCache, k as toEffectAgentRuntimeInput, m as loadRivusDaemonConfig, n as loadRivusDeploymentManifest, o as validateRivusDeploymentManifest, s as validateRivusProjectSpaceDeployment, u as gatewayPackageManifestPath, w as renderRivusModelCliArgumentError, y as loadMergedLocalEnvFile } from "./node-rivus-deployment-manifest.js";
3
+ import { createRequire } from "node:module";
4
+ import { Cause, Effect, Either, Exit } from "effect";
5
+ import { RIVUS_MEMORY_TOOL_PLUGIN_ID, RIVUS_RUNTIME_TOOL_IDS, createRivusMemoryToolContract, isRivusRuntimeToolId } from "@rivus/runtime";
6
+ import { createSha256Digest, createStableId } from "@rivus/platform/identity";
7
+ import { randomUUID } from "node:crypto";
8
+ import { lstat, mkdir, open, readFile, readdir, realpath, rmdir, stat, unlink, writeFile } from "node:fs/promises";
9
+ import { createConnection } from "node:net";
10
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
11
+ import { homedir } from "node:os";
12
+ import { fileURLToPath, pathToFileURL } from "node:url";
13
+ import { assertPathWithin, isPathWithin } from "@rivus/platform/filesystem";
14
+ import { constants as constants$1 } from "node:fs";
15
+ //#region src/core/application/agent-host/registry/agent-instance-registry.ts
16
+ var AgentInstanceConflict = class extends Error {
17
+ name = "AgentInstanceConflict";
18
+ };
19
+ function createEffectAgentInstanceRegistry(identity, options = {}) {
20
+ const records = /* @__PURE__ */ new Map();
21
+ for (const record of options.initialRecords ?? []) {
22
+ if (bindingKey(record.binding, record.agentId) !== record.bindingKey) throw new AgentInstanceConflict(`invalid binding key: ${record.bindingKey}`);
23
+ if (records.has(record.bindingKey)) throw new AgentInstanceConflict(`duplicate binding: ${record.bindingKey}`);
24
+ records.set(record.bindingKey, freezeRecord(record));
25
+ }
26
+ const resolveBinding = (instanceBinding, definition) => Effect.try({
27
+ try: () => {
28
+ const runtimeGenerationId = identity.createRuntimeGenerationId({
29
+ agentId: definition.agentId,
30
+ profileRevision: definition.profileRevision,
31
+ projectSpaceId: definition.projectSpaceId ?? null,
32
+ projectSpaceRevision: definition.projectSpaceRevision ?? null,
33
+ runtimeToolGrantRevision: definition.runtimeToolGrantSet.revision,
34
+ skillGrantRevision: definition.skillGrantSet.revision,
35
+ toolGrantRevision: definition.toolGrantSet.revision
36
+ });
37
+ const key = bindingKey(instanceBinding, definition.agentId);
38
+ const existing = records.get(key);
39
+ if (existing) {
40
+ if (existing.runtimeGenerationId !== runtimeGenerationId) throw new AgentInstanceConflict(`binding ${key} belongs to a different runtime generation`);
41
+ return existing;
42
+ }
43
+ const record = freezeRecord({
44
+ agentId: definition.agentId,
45
+ binding: instanceBinding,
46
+ bindingKey: key,
47
+ instanceId: identity.createInstanceId({
48
+ bindingKey: key,
49
+ runtimeGenerationId
50
+ }),
51
+ runtimeGenerationId
52
+ });
53
+ records.set(key, record);
54
+ return record;
55
+ },
56
+ catch: (error) => error instanceof AgentInstanceConflict ? error : new AgentInstanceConflict(String(error))
57
+ });
58
+ return {
59
+ resolveAutomation: (automationId, definition) => resolveBinding({
60
+ automationId,
61
+ kind: "automation"
62
+ }, definition),
63
+ resolveBackgroundSession: (agentId, definition) => resolveBinding({
64
+ agentId,
65
+ kind: "background-session"
66
+ }, definition),
67
+ resolveEndpoint: (endpointId, definition) => resolveBinding({
68
+ endpointId,
69
+ kind: "endpoint"
70
+ }, definition),
71
+ snapshot: () => Effect.sync(() => Object.freeze([...records.values()]))
72
+ };
73
+ }
74
+ function bindingKey(binding, agentId) {
75
+ const bindingId = binding.kind === "endpoint" ? binding.endpointId : binding.kind === "automation" ? binding.automationId : binding.agentId;
76
+ return `${binding.kind}:${bindingId}:${agentId}`;
77
+ }
78
+ function freezeRecord(record) {
79
+ return Object.freeze({
80
+ ...record,
81
+ binding: Object.freeze({ ...record.binding })
82
+ });
83
+ }
84
+ //#endregion
85
+ //#region src/core/application/agent-host/routing/agent-host.ts
86
+ var InvalidAgentHostBinding = class extends Error {
87
+ name = "InvalidAgentHostBinding";
88
+ };
89
+ function createEffectAgentHost(options) {
90
+ return Effect.gen(function* () {
91
+ const definitions = new Map(options.definitions.map((definition) => [definition.agentId, definition]));
92
+ const endpoints = /* @__PURE__ */ new Map();
93
+ const automations = /* @__PURE__ */ new Map();
94
+ const backgroundSessions = /* @__PURE__ */ new Map();
95
+ for (const endpoint of options.endpoints) {
96
+ if (endpoints.has(endpoint.id)) return yield* Effect.fail(new InvalidAgentHostBinding(`duplicate endpoint: ${endpoint.id}`));
97
+ const definition = definitions.get(endpoint.agentId);
98
+ if (!definition) return yield* Effect.fail(new InvalidAgentHostBinding(`unknown endpoint agent: ${endpoint.agentId}`));
99
+ if (!definition.endpointIds.includes(endpoint.id)) return yield* Effect.fail(new InvalidAgentHostBinding(`endpoint ${endpoint.id} is not declared by ${endpoint.agentId}`));
100
+ endpoints.set(endpoint.id, yield* options.registry.resolveEndpoint(endpoint.id, definition));
101
+ }
102
+ for (const automation of options.automations ?? []) {
103
+ if (automations.has(automation.id)) return yield* Effect.fail(new InvalidAgentHostBinding(`duplicate automation: ${automation.id}`));
104
+ if (!definitions.has(automation.definition.agentId)) return yield* Effect.fail(new InvalidAgentHostBinding(`unknown automation agent: ${automation.definition.agentId}`));
105
+ automations.set(automation.id, yield* options.registry.resolveAutomation(automation.id, automation.definition));
106
+ }
107
+ for (const backgroundSession of options.backgroundSessions ?? []) {
108
+ if (backgroundSession.definition.agentId !== backgroundSession.agentId) return yield* Effect.fail(new InvalidAgentHostBinding(`background session ${backgroundSession.agentId} cannot bind definition ${backgroundSession.definition.agentId}`));
109
+ if (backgroundSessions.has(backgroundSession.agentId)) return yield* Effect.fail(new InvalidAgentHostBinding(`duplicate background session agent: ${backgroundSession.agentId}`));
110
+ if (!definitions.has(backgroundSession.agentId)) return yield* Effect.fail(new InvalidAgentHostBinding(`unknown background session agent: ${backgroundSession.agentId}`));
111
+ backgroundSessions.set(backgroundSession.agentId, yield* options.registry.resolveBackgroundSession(backgroundSession.agentId, backgroundSession.definition));
112
+ }
113
+ const resolve = (records, id, message) => {
114
+ const instance = records.get(id);
115
+ return instance ? Effect.succeed(instance) : Effect.fail(new InvalidAgentHostBinding(message));
116
+ };
117
+ const resolveEndpoint = (endpointId) => resolve(endpoints, endpointId, `unknown endpoint: ${endpointId}`);
118
+ const resolveAutomation = (automationId) => resolve(automations, automationId, `unknown automation: ${automationId}`);
119
+ const resolveBackgroundSession = (agentId) => resolve(backgroundSessions, agentId, `unknown background session agent: ${agentId}`);
120
+ return {
121
+ cancelBackgroundSession: (agentId, input) => resolveBackgroundSession(agentId).pipe(Effect.flatMap((instance) => options.runtime.cancel(instance, input))),
122
+ cancelEndpoint: (endpointId, input) => resolveEndpoint(endpointId).pipe(Effect.flatMap((instance) => options.runtime.cancel(instance, input))),
123
+ dispose: () => options.runtime.disposeAll(),
124
+ handleAutomation: (automationId, input) => resolveAutomation(automationId).pipe(Effect.flatMap((instance) => options.runtime.run(instance, input))),
125
+ handleBackgroundSession: (agentId, input) => resolveBackgroundSession(agentId).pipe(Effect.flatMap((instance) => options.runtime.run(instance, input))),
126
+ handleEndpoint: (endpointId, input) => resolveEndpoint(endpointId).pipe(Effect.flatMap((instance) => options.runtime.run(instance, input))),
127
+ resolveAutomation,
128
+ resolveBackgroundSession,
129
+ resolveEndpoint,
130
+ steerEndpoint: (endpointId, input) => resolveEndpoint(endpointId).pipe(Effect.flatMap((instance) => options.runtime.steer(instance, input)))
131
+ };
132
+ });
133
+ }
134
+ //#endregion
135
+ //#region src/platform/runtime-pool/runtime-pool.ts
136
+ var RuntimeResourceBusy = class extends Error {
137
+ name = "RuntimeResourceBusy";
138
+ };
139
+ var RuntimeResourceDisposed = class extends Error {
140
+ name = "RuntimeResourceDisposed";
141
+ };
142
+ var RuntimePoolDisposalTimedOut = class extends Error {
143
+ name = "RuntimePoolDisposalTimedOut";
144
+ };
145
+ const DEFAULT_RUNTIME_DISPOSE_TIMEOUT_MS = 1e4;
146
+ function createEffectRuntimePool(options) {
147
+ const runtimes = createRuntimeCache();
148
+ const active = /* @__PURE__ */ new Map();
149
+ const lifecycle = Effect.unsafeMakeSemaphore(1);
150
+ const existingRuntime = (instance) => Effect.gen(function* () {
151
+ const selected = yield* runtimes.getExisting(instance.instanceId);
152
+ if (!selected || !(yield* runtimes.isCurrent(instance.instanceId, selected.entry))) return void 0;
153
+ return selected.runtime;
154
+ });
155
+ return {
156
+ cancel: (instance, input) => invokeRuntimeControl(existingRuntime(instance), (runtime) => runtime.cancel?.(input)),
157
+ disposeAll: () => Effect.gen(function* () {
158
+ const entries = yield* runtimes.drain();
159
+ yield* lifecycle.withPermits(1)(Effect.sync(() => active.clear()));
160
+ yield* disposeRuntimeCacheEntries({
161
+ dispose: (runtime) => runtime.dispose?.() ?? Effect.void,
162
+ entries,
163
+ failureMessage: "runtime pool disposal failed",
164
+ timeout: {
165
+ milliseconds: options.disposeTimeoutMs ?? DEFAULT_RUNTIME_DISPOSE_TIMEOUT_MS,
166
+ onTimeout: () => new RuntimePoolDisposalTimedOut(`runtime pool disposal timed out after ${options.disposeTimeoutMs ?? DEFAULT_RUNTIME_DISPOSE_TIMEOUT_MS}ms`)
167
+ }
168
+ });
169
+ }),
170
+ run: (instance, input) => Effect.gen(function* () {
171
+ const selected = yield* runtimes.getOrCreate(instance.instanceId, () => options.createRuntime(instance));
172
+ if (!(yield* runtimes.isCurrent(instance.instanceId, selected.entry))) return yield* Effect.fail(new RuntimeResourceDisposed(`runtime was disposed before run start: ${instance.instanceId}`));
173
+ if (selected.runtime.concurrency === "managed") return yield* selected.runtime.run(input);
174
+ const token = yield* lifecycle.withPermits(1)(Effect.gen(function* () {
175
+ if (!(yield* runtimes.isCurrent(instance.instanceId, selected.entry))) return yield* Effect.fail(new RuntimeResourceDisposed(`runtime was disposed before run start: ${instance.instanceId}`));
176
+ if (active.has(instance.instanceId)) return yield* Effect.fail(new RuntimeResourceBusy(`runtime already has an active run: ${instance.instanceId}`));
177
+ const activeToken = Symbol(instance.instanceId);
178
+ active.set(instance.instanceId, activeToken);
179
+ return activeToken;
180
+ }));
181
+ return yield* selected.runtime.run(input).pipe(Effect.ensuring(lifecycle.withPermits(1)(Effect.sync(() => {
182
+ if (active.get(instance.instanceId) === token) active.delete(instance.instanceId);
183
+ }))));
184
+ }),
185
+ steer: (instance, input) => invokeRuntimeControl(existingRuntime(instance), (runtime) => runtime.steer?.(input))
186
+ };
187
+ }
188
+ //#endregion
189
+ //#region src/adapters/agent/runtime/effect-agent-runtime-pool.ts
190
+ var AgentInstanceBusy = class extends Error {
191
+ name = "AgentInstanceBusy";
192
+ };
193
+ var AgentRuntimeDisposed = class extends Error {
194
+ name = "AgentRuntimeDisposed";
195
+ };
196
+ function createAgentHostRuntimePool(factory, disposeTimeoutMs) {
197
+ const pool = createEffectRuntimePool({
198
+ createRuntime: (instance) => factory.create(instance),
199
+ ...disposeTimeoutMs === void 0 ? {} : { disposeTimeoutMs }
200
+ });
201
+ return {
202
+ cancel: (instance, input) => pool.cancel(instance, input),
203
+ disposeAll: () => pool.disposeAll().pipe(Effect.mapError(mapRuntimePoolError)),
204
+ run: (instance, input) => pool.run(instance, input).pipe(Effect.mapError(mapRuntimePoolError)),
205
+ steer: (instance, steering) => pool.steer(instance, steering)
206
+ };
207
+ }
208
+ function mapRuntimePoolError(error) {
209
+ if (error instanceof RuntimeResourceBusy) return new AgentInstanceBusy(error.message.replace(/^runtime /, "agent instance "));
210
+ if (error instanceof RuntimeResourceDisposed) return new AgentRuntimeDisposed(error.message.replace(/^runtime /, "agent runtime "));
211
+ if (error instanceof RuntimePoolDisposalTimedOut) return new AgentRuntimeDisposed(error.message.replace(/^runtime pool /, "agent runtime "));
212
+ return error;
213
+ }
214
+ //#endregion
215
+ //#region src/core/application/agent-catalog/contracts/rivus-plugin.ts
216
+ const RIVUS_PLUGIN_API_VERSION = "1";
217
+ var InvalidRivusPlugin = class extends Error {
218
+ name = "InvalidRivusPlugin";
219
+ };
220
+ //#endregion
221
+ //#region src/core/application/agent-catalog/catalog/rivus-catalog-validation.ts
222
+ const MEMORY_SCOPES = [
223
+ "conversation",
224
+ "agent-private",
225
+ "project",
226
+ "shared-user-profile"
227
+ ];
228
+ function validateRivusPluginManifest(manifest) {
229
+ validateRivusCatalogIdentifier(manifest.id, "plugin");
230
+ if (manifest.apiVersion !== "1") throw new InvalidRivusPlugin(`unsupported plugin API version ${manifest.apiVersion}; expected 1`);
231
+ if (manifest.version.trim() === "") throw new InvalidRivusPlugin("plugin version must not be empty");
232
+ }
233
+ function validateRivusCatalogRegistration(item, existing, pending) {
234
+ validateRivusCatalogIdentifier(item.id, item.kind);
235
+ if (item.namespaced && !item.id.startsWith(`${item.pluginId}/`)) throw new InvalidRivusPlugin(`${item.kind} id ${item.id} must use plugin namespace ${item.pluginId}/`);
236
+ const key = `${item.kind}:${item.id}`;
237
+ if (pending.has(key) || existing.has(item.id)) throw new InvalidRivusPlugin(`duplicate ${item.kind} id: ${item.id}`);
238
+ }
239
+ function validateRivusCatalogIdentifier(id, kind) {
240
+ if (!/^[a-z0-9][a-z0-9._/-]*$/.test(id) || id.includes("*") || id.includes("//")) throw new InvalidRivusPlugin(`invalid ${kind} id: ${id}`);
241
+ }
242
+ function uniqueRivusCatalogIds(ids, label) {
243
+ const result = /* @__PURE__ */ new Set();
244
+ for (const id of ids) {
245
+ if (id.includes("*")) throw new InvalidRivusPlugin(`${label} does not support wildcard id: ${id}`);
246
+ validateRivusCatalogIdentifier(id, label);
247
+ if (result.has(id)) throw new InvalidRivusPlugin(`duplicate id in ${label}: ${id}`);
248
+ result.add(id);
249
+ }
250
+ return [...result];
251
+ }
252
+ function validateRivusCatalogReferences(ids, available, owner, kind) {
253
+ for (const id of uniqueRivusCatalogIds(ids, `${owner} ${kind} references`)) validateRivusCatalogReference(id, available, owner, kind);
254
+ }
255
+ function validateRivusCatalogReference(id, available, owner, kind) {
256
+ if (!available.has(id)) throw new InvalidRivusPlugin(`${owner} references unknown ${kind}: ${id}`);
257
+ }
258
+ function validateRivusMemoryScopes(scopes, owner) {
259
+ const result = /* @__PURE__ */ new Set();
260
+ for (const scope of scopes) {
261
+ if (!MEMORY_SCOPES.includes(scope)) throw new InvalidRivusPlugin(`${owner} references unsupported Memory scope: ${String(scope)}`);
262
+ if (result.has(scope)) throw new InvalidRivusPlugin(`${owner} contains duplicate Memory scope: ${scope}`);
263
+ result.add(scope);
264
+ }
265
+ return [...result];
266
+ }
267
+ function uniqueRivusRuntimeToolIds(ids, owner) {
268
+ const result = /* @__PURE__ */ new Set();
269
+ for (const id of ids) {
270
+ if (typeof id === "string" && id.includes("*")) throw new InvalidRivusPlugin(`${owner} does not support wildcard Runtime Tool: ${id}`);
271
+ if (typeof id !== "string" || !isRivusRuntimeToolId(id)) throw new InvalidRivusPlugin(`${owner} references unknown Runtime Tool: ${String(id)}`);
272
+ if (result.has(id)) throw new InvalidRivusPlugin(`${owner} contains duplicate Runtime Tool: ${id}`);
273
+ result.add(id);
274
+ }
275
+ return [...result];
276
+ }
277
+ //#endregion
278
+ //#region src/core/application/agent-catalog/catalog/rivus-plugin-catalog.ts
279
+ function createRivusPluginCatalog(runtime) {
280
+ const plugins = /* @__PURE__ */ new Map();
281
+ const profiles = /* @__PURE__ */ new Map();
282
+ const tools = /* @__PURE__ */ new Map();
283
+ const skills = /* @__PURE__ */ new Map();
284
+ const automations = /* @__PURE__ */ new Map();
285
+ return {
286
+ registerPlugin: (plugin) => {
287
+ validateRivusPluginManifest(plugin.manifest);
288
+ if (plugins.has(plugin.manifest.id)) throw new InvalidRivusPlugin(`duplicate plugin id: ${plugin.manifest.id}`);
289
+ const pendingProfiles = [];
290
+ const pendingTools = [];
291
+ const pendingSkills = [];
292
+ const pendingAutomations = [];
293
+ const pendingIds = /* @__PURE__ */ new Set();
294
+ const register = (kind, definition, catalog, destination, namespaced) => {
295
+ validateRivusCatalogRegistration({
296
+ id: definition.id,
297
+ kind,
298
+ namespaced,
299
+ pluginId: plugin.manifest.id
300
+ }, catalog, pendingIds);
301
+ const key = `${kind}:${definition.id}`;
302
+ pendingIds.add(key);
303
+ destination.push(runtime.deepFreeze({
304
+ ...definition,
305
+ pluginId: plugin.manifest.id
306
+ }));
307
+ };
308
+ plugin.register({
309
+ registerAgentProfile: (profile) => register("profile", profile, profiles, pendingProfiles, false),
310
+ registerAutomation: (automation) => register("automation", automation, automations, pendingAutomations, true),
311
+ registerSkill: (skill) => register("skill", skill, skills, pendingSkills, true),
312
+ registerTool: (tool) => register("tool", tool, tools, pendingTools, true)
313
+ });
314
+ const availableToolIds = /* @__PURE__ */ new Set([...tools.keys(), ...pendingTools.map(({ id }) => id)]);
315
+ const availableSkillIds = /* @__PURE__ */ new Set([...skills.keys(), ...pendingSkills.map(({ id }) => id)]);
316
+ const availableProfileIds = /* @__PURE__ */ new Set([...profiles.keys(), ...pendingProfiles.map(({ id }) => id)]);
317
+ for (const profile of pendingProfiles) {
318
+ validateRivusMemoryScopes(profile.memory.scopes, `profile ${profile.id}`);
319
+ uniqueRivusRuntimeToolIds(profile.runtimeTools?.allow ?? [], `profile ${profile.id}`);
320
+ validateRivusCatalogReferences(profile.tools.allow, availableToolIds, `profile ${profile.id}`, "tool");
321
+ validateRivusCatalogReferences(profile.skills.allow, availableSkillIds, `profile ${profile.id}`, "skill");
322
+ }
323
+ for (const automation of pendingAutomations) {
324
+ validateRivusCatalogReference(automation.profileId, availableProfileIds, `automation ${automation.id}`, "profile");
325
+ validateRivusCatalogReferences(automation.requestedToolIds, availableToolIds, `automation ${automation.id}`, "tool");
326
+ validateRivusCatalogReferences(automation.requestedSkillIds, availableSkillIds, `automation ${automation.id}`, "skill");
327
+ }
328
+ plugins.set(plugin.manifest.id, runtime.deepFreeze({ ...plugin.manifest }));
329
+ for (const profile of pendingProfiles) profiles.set(profile.id, profile);
330
+ for (const tool of pendingTools) tools.set(tool.id, tool);
331
+ for (const skill of pendingSkills) skills.set(skill.id, skill);
332
+ for (const automation of pendingAutomations) automations.set(automation.id, automation);
333
+ },
334
+ snapshot: () => runtime.deepFreeze({
335
+ automations: [...automations.values()],
336
+ plugins: [...plugins.values()],
337
+ profiles: [...profiles.values()],
338
+ skills: [...skills.values()],
339
+ tools: [...tools.values()]
340
+ })
341
+ };
342
+ }
343
+ //#endregion
344
+ //#region src/core/application/agent-catalog/resolution/rivus-tool-grant-set.ts
345
+ function narrowRivusToolGrantSet(parent, restrictions, runtime) {
346
+ const toolIds = intersectToolIds([parent.toolIds, ...restrictions]);
347
+ return runtime.deepFreeze({
348
+ revision: runtime.digest(JSON.stringify({
349
+ parentRevision: parent.revision,
350
+ toolIds
351
+ })),
352
+ toolIds
353
+ });
354
+ }
355
+ function intersectRivusToolIds(sets, runtime) {
356
+ const toolIds = intersectToolIds(sets);
357
+ return runtime.deepFreeze({
358
+ revision: runtime.digest(JSON.stringify(toolIds)),
359
+ toolIds
360
+ });
361
+ }
362
+ function createRivusToolGrantSetOperations(runtime) {
363
+ return Object.freeze({
364
+ intersect: (sets) => intersectRivusToolIds(sets, runtime),
365
+ narrow: (parent, restrictions) => narrowRivusToolGrantSet(parent, restrictions, runtime)
366
+ });
367
+ }
368
+ function intersectToolIds(sets) {
369
+ const [first = [], ...rest] = sets;
370
+ return [...new Set(first)].filter((id) => rest.every((set) => set.includes(id))).sort();
371
+ }
372
+ //#endregion
373
+ //#region src/core/application/agent-catalog/resolution/rivus-agent-grant-restriction.ts
374
+ function restrictRivusAgentDefinitionGrants(definition, restriction, runtime) {
375
+ const toolIds = uniqueIds(restriction.toolIds);
376
+ const skillIds = uniqueIds(restriction.skillIds);
377
+ const runtimeToolIds = uniqueRuntimeToolIds(restriction.runtimeToolIds);
378
+ const memoryScopes = uniqueScopes(restriction.memory.scopes);
379
+ const toolsById = new Map(definition.tools.map((tool) => [tool.id, tool]));
380
+ const skillsById = new Map(definition.skills.map((skill) => [skill.id, skill]));
381
+ const tools = toolIds.map((toolId) => {
382
+ const tool = toolsById.get(toolId);
383
+ if (!tool) throw new Error(`Agent grant restriction requests ungranted Tool: ${toolId}`);
384
+ return tool;
385
+ });
386
+ const skills = skillIds.map((skillId) => {
387
+ const skill = skillsById.get(skillId);
388
+ if (!skill) throw new Error(`Agent grant restriction requests ungranted Skill: ${skillId}`);
389
+ return skill;
390
+ });
391
+ for (const scope of memoryScopes) if (!definition.memory.scopes.includes(scope)) throw new Error(`Agent grant restriction requests ungranted Memory scope: ${scope}`);
392
+ for (const runtimeToolId of runtimeToolIds) if (!definition.runtimeToolGrantSet.toolIds.includes(runtimeToolId)) throw new Error(`Agent grant restriction requests ungranted Runtime Tool: ${runtimeToolId}`);
393
+ if (restriction.memory.tool && !definition.memory.tool) throw new Error("Agent grant restriction cannot enable an ungranted Memory Tool");
394
+ const skillGrantSet = runtime.deepFreeze({
395
+ revision: runtime.digest(JSON.stringify({
396
+ parentRevision: definition.skillGrantSet.revision,
397
+ skillIds
398
+ })),
399
+ skillIds
400
+ });
401
+ const runtimeToolGrantSet = runtime.deepFreeze({
402
+ revision: runtime.digest(JSON.stringify({
403
+ parentRevision: definition.runtimeToolGrantSet.revision,
404
+ toolIds: runtimeToolIds
405
+ })),
406
+ toolIds: runtimeToolIds
407
+ });
408
+ return runtime.deepFreeze({
409
+ ...definition,
410
+ memory: {
411
+ scopes: memoryScopes,
412
+ tool: restriction.memory.tool
413
+ },
414
+ runtimeToolGrantSet,
415
+ skillGrantSet,
416
+ skills,
417
+ toolGrantSet: narrowRivusToolGrantSet(definition.toolGrantSet, [toolIds], runtime),
418
+ tools
419
+ });
420
+ }
421
+ function uniqueRuntimeToolIds(ids) {
422
+ const requested = /* @__PURE__ */ new Set();
423
+ for (const id of ids) {
424
+ if (!isRivusRuntimeToolId(id)) throw new Error(`Agent grant restriction requests unknown Runtime Tool: ${id}`);
425
+ requested.add(id);
426
+ }
427
+ return RIVUS_RUNTIME_TOOL_IDS.filter((id) => requested.has(id));
428
+ }
429
+ function uniqueIds(ids) {
430
+ return [...new Set(ids)].sort();
431
+ }
432
+ function uniqueScopes(scopes) {
433
+ return [...new Set(scopes)].sort();
434
+ }
435
+ //#endregion
436
+ //#region src/core/application/agent-catalog/resolution/rivus-agent-definition-resolver.ts
437
+ function createRivusAgentDefinitionResolver(providers, runtime) {
438
+ return Object.freeze({ resolve: (catalog, deployment) => resolveRivusAgentDefinition(catalog, deployment, providers, runtime) });
439
+ }
440
+ function createRivusAgentCatalog(providers, runtime) {
441
+ const resolver = createRivusAgentDefinitionResolver(providers, runtime);
442
+ return Object.freeze({
443
+ createPluginCatalog: () => createRivusPluginCatalog(runtime),
444
+ resolve: (catalog, deployment) => resolver.resolve(catalog, deployment),
445
+ restrictGrants: (definition, restriction) => restrictRivusAgentDefinitionGrants(definition, restriction, runtime)
446
+ });
447
+ }
448
+ function resolveRivusAgentDefinition(catalog, deployment, providers, runtime) {
449
+ const snapshot = catalog.snapshot();
450
+ const plugin = snapshot.plugins.find((candidate) => candidate.id === deployment.pluginId);
451
+ if (!plugin) throw new InvalidRivusPlugin(`unknown deployment plugin: ${deployment.pluginId}`);
452
+ const profile = snapshot.profiles.find((candidate) => candidate.id === deployment.profileId && candidate.pluginId === deployment.pluginId);
453
+ if (!profile) throw new InvalidRivusPlugin(`unknown profile ${deployment.profileId} for plugin ${deployment.pluginId}`);
454
+ const memoryScopes = resolveMemoryScopes(profile, deployment);
455
+ const runtimeToolIds = resolveRuntimeTools(profile, deployment);
456
+ const memoryTool = deployment.memory?.tool === true;
457
+ if (memoryTool && memoryScopes.length === 0) throw new InvalidRivusPlugin(`deployment ${deployment.agentId} Memory Tool requires at least one granted scope`);
458
+ const contributions = providers.flatMap((provider) => provider.provide({
459
+ deployment,
460
+ memoryScopes,
461
+ profile
462
+ }));
463
+ const profileContributions = contributions.filter(({ scope }) => scope === "profile");
464
+ const runtimeContributions = contributions.filter(({ scope }) => scope === "runtime");
465
+ validateToolContributions(snapshot.tools, contributions);
466
+ if (memoryTool && !profileContributions.some(({ tool }) => tool.id === "memory")) throw new InvalidRivusPlugin(`deployment ${deployment.agentId} Memory Tool descriptor is unavailable`);
467
+ const pluginTools = resolvePluginTools(snapshot.tools, profile, deployment);
468
+ const profileToolsById = new Map(profileContributions.map(({ tool }) => [tool.id, runtime.deepFreeze({ ...tool })]));
469
+ const resolvedProfileToolIds = [...pluginTools.keys(), ...profileToolsById.keys()].sort();
470
+ const tools = resolvedProfileToolIds.map((id) => pluginTools.get(id) ?? profileToolsById.get(id));
471
+ const skills = resolveSkills(snapshot.skills, profile, deployment);
472
+ const skillIds = skills.map(({ id }) => id);
473
+ const profileRevision = digest(runtime, {
474
+ memory: {
475
+ scopes: memoryScopes,
476
+ tool: memoryTool
477
+ },
478
+ model: profile.model,
479
+ plugin,
480
+ profileId: profile.id,
481
+ runtimeTools: runtimeToolIds,
482
+ skills: skills.map(({ content, digest: skillDigest, id, pluginId, title, version }) => ({
483
+ content,
484
+ digest: skillDigest,
485
+ id,
486
+ pluginId,
487
+ title,
488
+ version
489
+ })),
490
+ systemPrompt: profile.systemPrompt,
491
+ tools
492
+ });
493
+ const toolGrantSet = runtime.deepFreeze({
494
+ revision: digest(runtime, {
495
+ profileRevision,
496
+ toolIds: resolvedProfileToolIds
497
+ }),
498
+ toolIds: resolvedProfileToolIds
499
+ });
500
+ const skillGrantSet = runtime.deepFreeze({
501
+ revision: digest(runtime, {
502
+ profileRevision,
503
+ skillIds
504
+ }),
505
+ skillIds
506
+ });
507
+ const runtimeToolGrantSet = runtime.deepFreeze({
508
+ revision: digest(runtime, {
509
+ profileRevision,
510
+ toolIds: runtimeToolIds
511
+ }),
512
+ toolIds: runtimeToolIds
513
+ });
514
+ return extendRuntimeTools(runtime.deepFreeze({
515
+ agentId: deployment.agentId,
516
+ endpointIds: [...deployment.endpointIds],
517
+ memory: {
518
+ scopes: memoryScopes,
519
+ tool: memoryTool
520
+ },
521
+ model: profile.model,
522
+ pluginId: deployment.pluginId,
523
+ profileId: deployment.profileId,
524
+ ...deployment.projectSpaceId ? { projectSpaceId: deployment.projectSpaceId } : {},
525
+ profileRevision,
526
+ runtimeToolGrantSet,
527
+ skillGrantSet,
528
+ skills,
529
+ systemPrompt: profile.systemPrompt,
530
+ toolGrantSet,
531
+ tools
532
+ }), runtimeContributions, runtime);
533
+ }
534
+ function resolveRuntimeTools(profile, deployment) {
535
+ const profileToolIds = uniqueRivusRuntimeToolIds(profile.runtimeTools?.allow ?? [], `profile ${profile.id}`);
536
+ const requestedToolIds = uniqueRivusRuntimeToolIds(deployment.runtimeTools?.allow ?? [], `deployment ${deployment.agentId}`);
537
+ const profileToolIdSet = new Set(profileToolIds);
538
+ const requestedToolIdSet = new Set(requestedToolIds);
539
+ return RIVUS_RUNTIME_TOOL_IDS.filter((id) => profileToolIdSet.has(id) && requestedToolIdSet.has(id));
540
+ }
541
+ function resolveMemoryScopes(profile, deployment) {
542
+ const profileScopes = validateRivusMemoryScopes(profile.memory.scopes, `profile ${profile.id}`);
543
+ const requestedScopes = validateRivusMemoryScopes(deployment.memory?.scopes ?? [], `deployment ${deployment.agentId}`);
544
+ return profileScopes.filter((scope) => requestedScopes.includes(scope));
545
+ }
546
+ function resolvePluginTools(registeredTools, profile, deployment) {
547
+ const requestedTools = uniqueRivusCatalogIds(deployment.tools.allow, "deployment tool allowlist");
548
+ const catalogTools = new Map(registeredTools.map((tool) => [tool.id, tool]));
549
+ for (const id of requestedTools) if (!catalogTools.has(id)) throw new InvalidRivusPlugin(`unknown deployment tool: ${id}`);
550
+ const profileToolIds = uniqueRivusCatalogIds(profile.tools.allow, "profile tool allowlist");
551
+ for (const id of profileToolIds) if (!catalogTools.has(id)) throw new InvalidRivusPlugin(`profile ${profile.id} references unknown tool: ${id}`);
552
+ const grantedIds = profileToolIds.filter((id) => requestedTools.includes(id)).sort();
553
+ return new Map(grantedIds.map((id) => [id, toResolvedTool(catalogTools.get(id))]));
554
+ }
555
+ function resolveSkills(registeredSkills, profile, deployment) {
556
+ const requestedSkills = uniqueRivusCatalogIds(deployment.skills.allow, "deployment skill allowlist");
557
+ const catalogSkills = new Map(registeredSkills.map((skill) => [skill.id, skill]));
558
+ for (const id of requestedSkills) if (!catalogSkills.has(id)) throw new InvalidRivusPlugin(`unknown deployment skill: ${id}`);
559
+ return uniqueRivusCatalogIds(profile.skills.allow, "profile skill allowlist").filter((id) => requestedSkills.includes(id)).sort().map((id) => {
560
+ const skill = catalogSkills.get(id);
561
+ if (!skill) throw new InvalidRivusPlugin(`profile ${profile.id} references unknown skill: ${id}`);
562
+ return skill;
563
+ });
564
+ }
565
+ function validateToolContributions(registeredTools, contributions) {
566
+ const knownIds = new Set(registeredTools.map(({ id }) => id));
567
+ for (const { tool } of contributions) {
568
+ validateRivusCatalogIdentifier(tool.id, "contributed tool");
569
+ validateRivusCatalogIdentifier(tool.pluginId, "contributed tool plugin");
570
+ if (knownIds.has(tool.id)) throw new InvalidRivusPlugin(`duplicate contributed tool id: ${tool.id}`);
571
+ if (tool.version.trim() === "" || tool.digest.trim() === "") throw new InvalidRivusPlugin(`contributed tool ${tool.id} requires a version and digest`);
572
+ knownIds.add(tool.id);
573
+ }
574
+ }
575
+ function extendRuntimeTools(definition, contributions, runtime) {
576
+ if (contributions.length === 0) return definition;
577
+ const additions = contributions.map(({ tool }) => runtime.deepFreeze({ ...tool }));
578
+ const additionIds = additions.map(({ id }) => id).sort();
579
+ return runtime.deepFreeze({
580
+ ...definition,
581
+ toolGrantSet: {
582
+ revision: digest(runtime, {
583
+ parentRevision: definition.toolGrantSet.revision,
584
+ toolIds: additionIds
585
+ }),
586
+ toolIds: [...definition.toolGrantSet.toolIds, ...additionIds].sort()
587
+ },
588
+ tools: [...definition.tools, ...additions]
589
+ });
590
+ }
591
+ function toResolvedTool(tool) {
592
+ const { createExecutor: _createExecutor, description, digest: toolDigest, id, idempotency, inputSchema, pluginId, risk, version } = tool;
593
+ return {
594
+ description,
595
+ digest: toolDigest,
596
+ id,
597
+ idempotency,
598
+ inputSchema,
599
+ pluginId,
600
+ risk,
601
+ version
602
+ };
603
+ }
604
+ function digest(runtime, value) {
605
+ return runtime.digest(stableJson(value));
606
+ }
607
+ function stableJson(value) {
608
+ if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
609
+ if (value !== null && typeof value === "object") return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => `${JSON.stringify(key)}:${stableJson(child)}`).join(",")}}`;
610
+ return JSON.stringify(value);
611
+ }
612
+ //#endregion
613
+ //#region src/adapters/agent/catalog/rivus-host-tool-descriptor-provider.ts
614
+ function createRivusHostToolDescriptorProvider(options) {
615
+ return Object.freeze({ provide: ({ deployment, memoryScopes }) => {
616
+ const contributions = [];
617
+ if (deployment.memory?.tool === true) contributions.push({
618
+ scope: "profile",
619
+ tool: Object.freeze({
620
+ ...createRivusMemoryToolContract(memoryScopes),
621
+ pluginId: RIVUS_MEMORY_TOOL_PLUGIN_ID
622
+ })
623
+ });
624
+ if (options.backgroundSessions) contributions.push(...createBackgroundSessionToolContracts().map(toRuntimeContribution));
625
+ return Object.freeze(contributions);
626
+ } });
627
+ }
628
+ function toRuntimeContribution(tool) {
629
+ return Object.freeze({
630
+ scope: "runtime",
631
+ tool: Object.freeze({ ...tool })
632
+ });
633
+ }
634
+ //#endregion
635
+ //#region src/platform/project/setup/rivus-project-initializer.ts
636
+ const TEMPLATE_FILES = Object.freeze({
637
+ "current-weather.mjs": "current-weather.mjs",
638
+ "https-response-reader.mjs": "https-response-reader.mjs",
639
+ "rivus-agents.plugin.mjs": "rivus-starter.plugin.mjs",
640
+ "rivus.bootstrap.ts": "pi-feishu-deployment.bootstrap.ts"
641
+ });
642
+ async function initializeRivusProject(options) {
643
+ const directory = resolve(options.directory);
644
+ const descriptor = options.releaseDescriptor ?? RIVUS_RELEASE_DESCRIPTOR;
645
+ const files = /* @__PURE__ */ new Map([
646
+ [".env.example", environmentTemplate$1()],
647
+ [".gitignore", ".env.local\n.rivus/\nnode_modules/\n"],
648
+ ["deploy/launchd/com.rivus.agent.plist", launchdService(directory, options.nodeExecutable)],
649
+ ["deploy/systemd/rivus.service", systemdService(directory, options.nodeExecutable)],
650
+ ["package.json", projectPackageJson(directory, descriptor)],
651
+ ["rivus.config.json", deploymentManifest$1()]
652
+ ]);
653
+ for (const [target, source] of Object.entries(TEMPLATE_FILES)) files.set(target, await readFile(join(options.templateDirectory, source), "utf8"));
654
+ const paths = [...files.keys()].sort();
655
+ await assertSafeProjectAncestors(directory, paths);
656
+ const conflicts = await findConflicts(directory, paths);
657
+ if (conflicts.length > 0) throw new Error(`Rivus project initialization refused; refusing to overwrite: ${conflicts.join(", ")}`);
658
+ const createdDirectories = [];
659
+ const createdFiles = [];
660
+ const writeProjectFile = options.writeProjectFile ?? writeExclusiveProjectFile;
661
+ try {
662
+ for (const path of paths) {
663
+ const destination = join(directory, path);
664
+ await ensureDirectory(dirname(destination), directory, createdDirectories);
665
+ await assertSafeProjectAncestors(directory, [path]);
666
+ await writeProjectFile(destination, files.get(path));
667
+ createdFiles.push(destination);
668
+ }
669
+ } catch (error) {
670
+ const rollbackErrors = await rollbackCreatedPaths(createdFiles, createdDirectories);
671
+ if (rollbackErrors.length > 0) throw new AggregateError([error, ...rollbackErrors], "Rivus project initialization failed and rollback was incomplete");
672
+ throw error;
673
+ }
674
+ return {
675
+ directory,
676
+ files: Object.freeze(paths)
677
+ };
678
+ }
679
+ async function writeExclusiveProjectFile(path, contents) {
680
+ await writeFile(path, contents, {
681
+ encoding: "utf8",
682
+ flag: "wx"
683
+ });
684
+ }
685
+ async function assertSafeProjectAncestors(directory, paths) {
686
+ const rootState = await lstatOrUndefined(directory);
687
+ if (rootState?.isSymbolicLink()) throw new Error("Rivus project initialization refused; symbolic link ancestor: .");
688
+ if (rootState && !rootState.isDirectory()) throw new Error("Rivus project initialization refused; project path is not a directory");
689
+ if (!rootState) return;
690
+ for (const path of paths) {
691
+ let current = directory;
692
+ for (const segment of path.split("/").slice(0, -1)) {
693
+ current = join(current, segment);
694
+ const state = await lstatOrUndefined(current);
695
+ if (!state) break;
696
+ if (state.isSymbolicLink()) throw new Error(`Rivus project initialization refused; symbolic link ancestor: ${relative(directory, current)}`);
697
+ if (!state.isDirectory()) throw new Error(`Rivus project initialization refused; non-directory ancestor: ${relative(directory, current)}`);
698
+ }
699
+ }
700
+ }
701
+ async function ensureDirectory(path, projectRoot, createdDirectories) {
702
+ try {
703
+ await mkdir(path);
704
+ createdDirectories.push(path);
705
+ } catch (error) {
706
+ if (isMissingPath$1(error)) {
707
+ const parent = dirname(path);
708
+ if (parent === path) throw error;
709
+ await ensureDirectory(parent, projectRoot, createdDirectories);
710
+ await ensureDirectory(path, projectRoot, createdDirectories);
711
+ return;
712
+ }
713
+ if (!isAlreadyExists(error)) throw error;
714
+ const state = await lstat(path);
715
+ if (state.isSymbolicLink()) {
716
+ if (isPathWithin(projectRoot, path)) throw new Error(`Rivus project initialization refused; symbolic link ancestor: ${relative(projectRoot, path) || "."}`);
717
+ if ((await stat(path)).isDirectory()) return;
718
+ }
719
+ if (!state.isDirectory()) throw new Error(`Rivus project initialization refused; non-directory ancestor: ${path}`);
720
+ }
721
+ }
722
+ async function rollbackCreatedPaths(files, directories) {
723
+ const errors = [];
724
+ for (const path of files.reverse()) try {
725
+ await unlink(path);
726
+ } catch (error) {
727
+ if (!isMissingPath$1(error)) errors.push(asError$1(error));
728
+ }
729
+ for (const path of directories.reverse()) try {
730
+ await rmdir(path);
731
+ } catch (error) {
732
+ if (!isMissingPath$1(error) && !isDirectoryNotEmpty(error)) errors.push(asError$1(error));
733
+ }
734
+ return errors;
735
+ }
736
+ async function lstatOrUndefined(path) {
737
+ try {
738
+ return await lstat(path);
739
+ } catch (error) {
740
+ if (isMissingPath$1(error)) return void 0;
741
+ throw error;
742
+ }
743
+ }
744
+ function isAlreadyExists(error) {
745
+ return error instanceof Error && "code" in error && error.code === "EEXIST";
746
+ }
747
+ function isDirectoryNotEmpty(error) {
748
+ return error instanceof Error && "code" in error && error.code === "ENOTEMPTY";
749
+ }
750
+ function asError$1(error) {
751
+ return error instanceof Error ? error : new Error(String(error));
752
+ }
753
+ async function findConflicts(directory, paths) {
754
+ const conflicts = [];
755
+ for (const path of paths) try {
756
+ await lstat(join(directory, path));
757
+ conflicts.push(path);
758
+ } catch (error) {
759
+ if (!isMissingPath$1(error)) throw error;
760
+ }
761
+ return conflicts;
762
+ }
763
+ function isMissingPath$1(error) {
764
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
765
+ }
766
+ function projectPackageJson(directory, descriptor) {
767
+ const { dependencies, version } = descriptor;
768
+ const projectName = sanitizePackageName(basename(directory));
769
+ return `${JSON.stringify({
770
+ name: projectName,
771
+ private: true,
772
+ type: "module",
773
+ scripts: {
774
+ "check-config": "rivus --manifest ./rivus.config.json --check-config",
775
+ doctor: "rivus doctor .",
776
+ start: "rivus --env-file .env.local --bootstrap ./rivus.bootstrap.ts --manifest ./rivus.config.json"
777
+ },
778
+ dependencies: {
779
+ "@earendil-works/pi-coding-agent": dependencies["@earendil-works/pi-coding-agent"],
780
+ "@larksuiteoapi/node-sdk": dependencies["@larksuiteoapi/node-sdk"],
781
+ "@rivus/agent": `^${version}`,
782
+ effect: dependencies.effect
783
+ }
784
+ }, null, 2)}\n`;
785
+ }
786
+ function sanitizePackageName(value) {
787
+ return value.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^[._-]+|[._-]+$/g, "") || "rivus-app";
788
+ }
789
+ function deploymentManifest$1() {
790
+ return `${JSON.stringify({
791
+ plugins: [{
792
+ id: "rivus-starter",
793
+ module: "./rivus-agents.plugin.mjs",
794
+ required: true
795
+ }],
796
+ agents: [{
797
+ agentId: "agent-a",
798
+ endpointIds: ["feishu-agent-a"],
799
+ pluginId: "rivus-starter",
800
+ profileId: "agent-a",
801
+ skills: { allow: [] },
802
+ tools: { allow: ["rivus-starter/current-weather"] }
803
+ }],
804
+ defaultAgentId: "agent-a",
805
+ defaultEndpointId: "feishu-agent-a",
806
+ endpoints: [{
807
+ agentId: "agent-a",
808
+ baseUrl: "https://open.feishu.cn",
809
+ cardStreamLeaseMs: 51e4,
810
+ credentialRef: "env:RIVUS_FEISHU",
811
+ enabled: true,
812
+ experimental: { cotMessages: false },
813
+ groupPolicy: "mention-only",
814
+ id: "feishu-agent-a",
815
+ progressDisplay: "collapsed",
816
+ required: true,
817
+ sessionNamespace: "rivus-starter",
818
+ streamMinIntervalMs: 200
819
+ }]
820
+ }, null, 2)}\n`;
821
+ }
822
+ function environmentTemplate$1() {
823
+ return [
824
+ "# Copy this file to .env.local and keep the real values untracked.",
825
+ "RIVUS_FEISHU_APP_ID=",
826
+ "RIVUS_FEISHU_APP_SECRET=",
827
+ "PI_MODEL=",
828
+ "PI_API_KEY=",
829
+ "# PI_BASE_URL=",
830
+ "RIVUS_WEATHER_DEFAULT_LOCATION=上海",
831
+ "# LANGFUSE_BASE_URL=https://jp.cloud.langfuse.com",
832
+ "# LANGFUSE_PUBLIC_KEY=",
833
+ "# LANGFUSE_SECRET_KEY=",
834
+ "# RIVUS_TELEMETRY_CONTENT=redacted",
835
+ ""
836
+ ].join("\n");
837
+ }
838
+ function systemdService(directory, nodeExecutable) {
839
+ const cli = join(directory, "node_modules", "@rivus", "agent", "dist", "cli.js");
840
+ return `[Unit]\nDescription=Rivus Agent\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nWorkingDirectory=${systemdPath(directory)}\nExecStart=${systemdQuote(nodeExecutable)} ${systemdQuote(cli)} --env-file .env.local --bootstrap ./rivus.bootstrap.ts --manifest ./rivus.config.json\nRestart=on-failure\nRestartSec=5\nEnvironment=NODE_ENV=production\n\n[Install]\nWantedBy=default.target\n`;
841
+ }
842
+ function systemdPath(value) {
843
+ return value.replaceAll("%", "%%");
844
+ }
845
+ function systemdQuote(value) {
846
+ return `"${value.replace(/%/g, "%%").replace(/\$/g, () => "$$").replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
847
+ }
848
+ function launchdService(directory, nodeExecutable) {
849
+ return `<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0">\n<dict>\n <key>Label</key>\n <string>com.rivus.agent</string>\n <key>ProgramArguments</key>\n <array>\n${[
850
+ nodeExecutable,
851
+ join(directory, "node_modules", "@rivus", "agent", "dist", "cli.js"),
852
+ "--env-file",
853
+ ".env.local",
854
+ "--bootstrap",
855
+ "./rivus.bootstrap.ts",
856
+ "--manifest",
857
+ "./rivus.config.json"
858
+ ].map((value) => ` <string>${xmlEscape(value)}</string>`).join("\n")}\n </array>\n <key>WorkingDirectory</key>\n <string>${xmlEscape(directory)}</string>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <dict>\n <key>SuccessfulExit</key>\n <false/>\n </dict>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n</dict>\n</plist>\n`;
859
+ }
860
+ function xmlEscape(value) {
861
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
862
+ }
863
+ //#endregion
864
+ //#region src/adapters/deployment/plugin/rivus-builtin-specifiers.ts
865
+ const RIVUS_BUILTIN_SPECIFIERS = /* @__PURE__ */ new Map([["@rivus/agent/bootstrap/pi-feishu", "@rivus/gateway/bootstrap/pi-feishu"], ["@rivus/agent/plugin/starter", "@rivus/gateway/plugin/starter"]]);
866
+ function resolveRivusBuiltinSpecifier(specifier) {
867
+ return RIVUS_BUILTIN_SPECIFIERS.get(specifier) ?? specifier;
868
+ }
869
+ //#endregion
870
+ //#region src/adapters/deployment/plugin/rivus-plugin-module.ts
871
+ function resolveRivusPluginModule(module) {
872
+ const candidate = "default" in module ? module.default : module;
873
+ return (typeof candidate === "function" ? Effect.tryPromise({
874
+ try: () => Promise.resolve(candidate()),
875
+ catch: toError$5
876
+ }) : Effect.succeed(candidate)).pipe(Effect.flatMap((plugin) => isRivusPlugin(plugin) ? Effect.succeed(plugin) : Effect.fail(/* @__PURE__ */ new Error("plugin module default export is not a RivusPlugin or factory"))));
877
+ }
878
+ function isRivusPlugin(value) {
879
+ return value !== null && typeof value === "object" && "manifest" in value && "register" in value && typeof value.register === "function";
880
+ }
881
+ function toError$5(error) {
882
+ return error instanceof Error ? error : new Error(String(error));
883
+ }
884
+ //#endregion
885
+ //#region src/adapters/deployment/plugin/trusted-package-root.ts
886
+ function findTrustedPackageRoot(packageManifestPath) {
887
+ return Effect.tryPromise({
888
+ try: async () => {
889
+ const packageRoot = dirname(await realpath(packageManifestPath));
890
+ let current = packageRoot;
891
+ for (;;) {
892
+ if (basename(current) === "node_modules") return current;
893
+ const parent = dirname(current);
894
+ if (parent === current) return packageRoot;
895
+ current = parent;
896
+ }
897
+ },
898
+ catch: (error) => error instanceof Error ? error : new Error(String(error))
899
+ });
900
+ }
901
+ //#endregion
902
+ //#region src/adapters/deployment/plugin/trusted-module-path.ts
903
+ function validateTrustedModulePath(trustedRoot, resolvedPath, subject) {
904
+ return Effect.try({
905
+ try: () => {
906
+ assertPathWithin(trustedRoot, resolvedPath, `${subject} resolves outside trusted module root: ${resolvedPath}`);
907
+ return resolvedPath;
908
+ },
909
+ catch: (failure) => failure instanceof Error ? failure : new Error(String(failure))
910
+ });
911
+ }
912
+ //#endregion
913
+ //#region src/adapters/deployment/plugin/node-rivus-plugin-module-loader.ts
914
+ function createNodeRivusPluginModuleLoader(options = {}) {
915
+ return { load: (request) => loadNodeRivusPluginModule(request, options).pipe(Effect.flatMap(resolveRivusPluginModule)) };
916
+ }
917
+ function loadNodeRivusPluginModule(request, options = {}) {
918
+ return resolveNodeRivusPluginModulePath(request, options).pipe(Effect.flatMap((resolvedRealpath) => Effect.tryPromise({
919
+ try: () => import(pathToFileURL(resolvedRealpath).href),
920
+ catch: toError$4
921
+ })));
922
+ }
923
+ function resolveNodeRivusPluginModulePath(request, options = {}) {
924
+ return Effect.gen(function* () {
925
+ const deploymentRoot = yield* Effect.tryPromise({
926
+ try: () => realpath(request.deploymentRoot),
927
+ catch: toError$4
928
+ });
929
+ const moduleSpecifier = resolveRivusBuiltinSpecifier(request.module);
930
+ const relativeModule = moduleSpecifier.startsWith("./") || moduleSpecifier.startsWith("../");
931
+ const resolutionManifest = relativeModule ? join(deploymentRoot, "package.json") : options.packageManifestPath ?? join(deploymentRoot, "package.json");
932
+ const resolved = yield* Effect.try({
933
+ try: () => createRequire(resolutionManifest).resolve(moduleSpecifier),
934
+ catch: toError$4
935
+ });
936
+ const resolvedRealpath = yield* Effect.tryPromise({
937
+ try: () => realpath(resolved),
938
+ catch: toError$4
939
+ });
940
+ return yield* validateTrustedModulePath(relativeModule ? deploymentRoot : options.packageManifestPath ? yield* findTrustedPackageRoot(options.packageManifestPath) : deploymentRoot, resolvedRealpath, `plugin module ${request.module}`);
941
+ });
942
+ }
943
+ function toError$4(error) {
944
+ return error instanceof Error ? error : new Error(String(error));
945
+ }
946
+ //#endregion
947
+ //#region src/adapters/deployment/inspection/rivus-project-doctor.ts
948
+ const REQUIRED_FILES = Object.freeze([
949
+ "package.json",
950
+ "rivus.bootstrap.ts",
951
+ "rivus.config.json"
952
+ ]);
953
+ const REQUIRED_DEPENDENCIES = Object.freeze([
954
+ "@rivus/agent",
955
+ "@earendil-works/pi-coding-agent",
956
+ "@larksuiteoapi/node-sdk",
957
+ "effect"
958
+ ]);
959
+ function diagnoseRivusProject(options) {
960
+ return Effect.gen(function* () {
961
+ const directory = resolve(options.directory);
962
+ const checks = [checkNode$1(options.nodeVersion)];
963
+ checks.push(yield* Effect.tryPromise({
964
+ try: () => checkFiles(directory),
965
+ catch: toError$3
966
+ }));
967
+ checks.push(yield* Effect.tryPromise({
968
+ try: () => checkDependencies(directory),
969
+ catch: toError$3
970
+ }));
971
+ const manifestResult = yield* checkManifest$1(directory);
972
+ checks.push(manifestResult.check);
973
+ const envFilePath = resolve(directory, options.envFilePath ?? ".env.local");
974
+ checks.push(yield* Effect.tryPromise({
975
+ try: () => checkCredentials$1(manifestResult.manifest, envFilePath, options.env),
976
+ catch: toError$3
977
+ }));
978
+ return Object.freeze({
979
+ checks: Object.freeze(checks),
980
+ directory,
981
+ ready: checks.every(({ status }) => status === "pass")
982
+ });
983
+ });
984
+ }
985
+ function checkNode$1(version) {
986
+ const [major, minor] = version.split(".").map(Number);
987
+ if (major === 24 && Number.isInteger(minor) && minor >= 11) return {
988
+ message: `Node.js ${version} satisfies the supported ^24.11 runtime`,
989
+ name: "node",
990
+ status: "pass"
991
+ };
992
+ return {
993
+ message: `Node.js 24.11 or newer on major 24 is required; current version is ${version}`,
994
+ name: "node",
995
+ status: "fail"
996
+ };
997
+ }
998
+ async function checkFiles(directory) {
999
+ const missing = await missingRegularFiles(directory, REQUIRED_FILES);
1000
+ return missing.length === 0 ? {
1001
+ message: "required project files are present",
1002
+ name: "files",
1003
+ status: "pass"
1004
+ } : {
1005
+ message: `required project files are missing: ${missing.join(", ")}`,
1006
+ name: "files",
1007
+ status: "fail"
1008
+ };
1009
+ }
1010
+ async function checkDependencies(directory) {
1011
+ const packageFiles = REQUIRED_DEPENDENCIES.map((name) => join("node_modules", ...name.split("/"), "package.json"));
1012
+ const missingIndexes = new Set((await missingRegularFiles(directory, packageFiles)).map((path) => packageFiles.indexOf(path)));
1013
+ const missing = REQUIRED_DEPENDENCIES.filter((_, index) => missingIndexes.has(index));
1014
+ return missing.length === 0 ? {
1015
+ message: "Rivus, Pi, Feishu, and Effect dependencies are installed",
1016
+ name: "dependencies",
1017
+ status: "pass"
1018
+ } : {
1019
+ message: `run npm install; missing local dependencies: ${missing.join(", ")}`,
1020
+ name: "dependencies",
1021
+ status: "fail"
1022
+ };
1023
+ }
1024
+ function checkManifest$1(directory) {
1025
+ return loadRivusDeploymentManifest(join(directory, "rivus.config.json")).pipe(Effect.flatMap((manifest) => Effect.gen(function* () {
1026
+ validateRivusDeploymentManifest(manifest);
1027
+ const missingModules = [];
1028
+ for (const plugin of manifest.plugins) {
1029
+ const result = yield* resolveNodeRivusPluginModulePath({
1030
+ deploymentRoot: directory,
1031
+ module: plugin.module,
1032
+ pluginId: plugin.id
1033
+ }).pipe(Effect.either);
1034
+ if (Either.isLeft(result)) missingModules.push(plugin.module);
1035
+ }
1036
+ if (missingModules.length > 0) return { check: {
1037
+ message: `manifest Plugin modules are missing: ${missingModules.join(", ")}`,
1038
+ name: "manifest",
1039
+ status: "fail"
1040
+ } };
1041
+ return {
1042
+ check: {
1043
+ message: "deployment manifest is valid",
1044
+ name: "manifest",
1045
+ status: "pass"
1046
+ },
1047
+ manifest
1048
+ };
1049
+ })), Effect.catchAll((error) => Effect.succeed({ check: {
1050
+ message: `deployment manifest is invalid: ${error.message}`,
1051
+ name: "manifest",
1052
+ status: "fail"
1053
+ } })));
1054
+ }
1055
+ async function checkCredentials$1(manifest, envFilePath, env) {
1056
+ let mergedEnv;
1057
+ try {
1058
+ mergedEnv = await loadMergedLocalEnvFile(envFilePath, env);
1059
+ } catch (error) {
1060
+ return {
1061
+ message: `required env file is unavailable at ${envFilePath}: ${error instanceof Error ? error.message : String(error)}`,
1062
+ name: "credentials",
1063
+ status: "fail"
1064
+ };
1065
+ }
1066
+ if (!manifest) return {
1067
+ message: "enabled Endpoint credentials cannot be checked until the deployment manifest is valid",
1068
+ name: "credentials",
1069
+ status: "fail"
1070
+ };
1071
+ try {
1072
+ for (const endpoint of manifest.endpoints.filter(({ enabled }) => enabled)) resolveFeishuEndpointCredentials(endpoint.credentialRef, mergedEnv);
1073
+ return {
1074
+ message: "enabled Endpoint credential references resolve",
1075
+ name: "credentials",
1076
+ status: "pass"
1077
+ };
1078
+ } catch (error) {
1079
+ return {
1080
+ message: `enabled Endpoint credentials are incomplete: ${error instanceof Error ? error.message : String(error)}`,
1081
+ name: "credentials",
1082
+ status: "fail"
1083
+ };
1084
+ }
1085
+ }
1086
+ async function missingRegularFiles(directory, paths) {
1087
+ const missing = [];
1088
+ for (const path of paths) try {
1089
+ if (!(await stat(resolve(directory, path))).isFile()) missing.push(path);
1090
+ } catch (error) {
1091
+ if (!isMissingPath(error)) throw error;
1092
+ missing.push(path);
1093
+ }
1094
+ return missing;
1095
+ }
1096
+ function isMissingPath(error) {
1097
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
1098
+ }
1099
+ function toError$3(error) {
1100
+ return error instanceof Error ? error : new Error(String(error));
1101
+ }
1102
+ //#endregion
1103
+ //#region src/adapters/deployment/inspection/rivus-home-deployment-inspector.ts
1104
+ const DEFAULT_BOOTSTRAP_PEERS = Object.freeze(["@earendil-works/pi-coding-agent", "@larksuiteoapi/node-sdk"]);
1105
+ function createRivusHomeDeploymentInspector(options = {}) {
1106
+ const resolveModule = options.resolveModule ?? ((specifier) => defaultResolveModule(specifier, options.packageManifestPath));
1107
+ const resolvePluginModule = options.resolvePluginModule ?? ((request) => resolveNodeRivusPluginModulePath(request, options.packageManifestPath ? { packageManifestPath: options.packageManifestPath } : {}));
1108
+ return { inspect: (input) => Effect.gen(function* () {
1109
+ const manifestResult = yield* checkManifest(input.home);
1110
+ const credentials = yield* checkCredentials(input.home, manifestResult.manifest, input.env, input.envFilePath);
1111
+ const modules = yield* checkModules(input.home, manifestResult.manifest, resolveModule, resolvePluginModule);
1112
+ return {
1113
+ credentials,
1114
+ manifest: manifestResult.check,
1115
+ modules
1116
+ };
1117
+ }) };
1118
+ }
1119
+ function checkManifest(home) {
1120
+ return loadRivusDeploymentManifest(home.manifestPath).pipe(Effect.map((manifest) => {
1121
+ validateRivusDeploymentManifest(manifest);
1122
+ return {
1123
+ check: {
1124
+ message: "deployment manifest is valid",
1125
+ name: "manifest",
1126
+ status: "pass"
1127
+ },
1128
+ manifest
1129
+ };
1130
+ }), Effect.catchAll((error) => Effect.succeed({ check: {
1131
+ message: `deployment manifest is invalid: ${formatError(error)}`,
1132
+ name: "manifest",
1133
+ status: "fail"
1134
+ } })));
1135
+ }
1136
+ function checkModules(home, manifest, resolveModule, resolvePluginModule) {
1137
+ if (!manifest) return Effect.succeed({
1138
+ message: "modules cannot be checked until manifest is valid",
1139
+ name: "modules",
1140
+ status: "fail"
1141
+ });
1142
+ const specifiers = [resolveRivusBuiltinSpecifier(home.bootstrap), ...home.bootstrap === "@rivus/agent/bootstrap/pi-feishu" || home.bootstrap === "@rivus/gateway/bootstrap/pi-feishu" ? DEFAULT_BOOTSTRAP_PEERS : []];
1143
+ return Effect.gen(function* () {
1144
+ const missing = [];
1145
+ for (const specifier of specifiers) {
1146
+ const result = yield* toEffect(() => resolveModule(specifier)).pipe(Effect.either);
1147
+ if (result._tag === "Left") missing.push(`${specifier} (${formatError(result.left)})`);
1148
+ }
1149
+ for (const plugin of manifest.plugins) {
1150
+ const result = yield* toEffect(() => resolvePluginModule({
1151
+ deploymentRoot: home.directory,
1152
+ module: resolveRivusBuiltinSpecifier(plugin.module),
1153
+ pluginId: plugin.id
1154
+ })).pipe(Effect.either);
1155
+ if (result._tag === "Left") missing.push(`${plugin.module} (${formatError(result.left)})`);
1156
+ }
1157
+ return missing.length === 0 ? {
1158
+ message: "Bootstrap, Plugin, Pi, and Feishu modules resolve from the global installation",
1159
+ name: "modules",
1160
+ status: "pass"
1161
+ } : {
1162
+ message: `global npm modules are unavailable: ${missing.join(", ")}`,
1163
+ name: "modules",
1164
+ status: "fail"
1165
+ };
1166
+ });
1167
+ }
1168
+ function toEffect(read) {
1169
+ return Effect.suspend(() => {
1170
+ try {
1171
+ const value = read();
1172
+ if (Effect.isEffect(value)) return value;
1173
+ return Effect.tryPromise({
1174
+ try: () => Promise.resolve(value),
1175
+ catch: toError$2
1176
+ });
1177
+ } catch (error) {
1178
+ return Effect.fail(toError$2(error));
1179
+ }
1180
+ });
1181
+ }
1182
+ function checkCredentials(home, manifest, env, envFilePath) {
1183
+ if (!manifest) return Effect.succeed({
1184
+ message: "credentials cannot be checked until manifest is valid",
1185
+ name: "credentials",
1186
+ status: "fail"
1187
+ });
1188
+ return Effect.tryPromise({
1189
+ try: async () => {
1190
+ const merged = await loadMergedLocalEnvFile(envFilePath ? resolve(home.directory, envFilePath) : home.envFilePath, env);
1191
+ for (const endpoint of manifest.endpoints.filter(({ enabled }) => enabled)) resolveFeishuEndpointCredentials(endpoint.credentialRef, merged);
1192
+ return {
1193
+ message: "enabled Endpoint credential references resolve",
1194
+ name: "credentials",
1195
+ status: "pass"
1196
+ };
1197
+ },
1198
+ catch: toError$2
1199
+ }).pipe(Effect.catchAll((error) => Effect.succeed({
1200
+ message: `enabled Endpoint credentials are incomplete: ${formatError(error)}`,
1201
+ name: "credentials",
1202
+ status: "fail"
1203
+ })));
1204
+ }
1205
+ function defaultResolveModule(specifier, packageManifestPath) {
1206
+ if (!packageManifestPath) return Effect.fail(/* @__PURE__ */ new Error("Rivus package manifest path is required for trusted module resolution"));
1207
+ return Effect.gen(function* () {
1208
+ const resolvedRealpath = yield* Effect.tryPromise({
1209
+ try: () => realpath(fileURLToPath(import.meta.resolve(specifier))),
1210
+ catch: toError$2
1211
+ });
1212
+ return yield* validateTrustedModulePath(yield* findTrustedPackageRoot(packageManifestPath), resolvedRealpath, `module ${specifier}`);
1213
+ });
1214
+ }
1215
+ function toError$2(error) {
1216
+ return error instanceof Error ? error : new Error(String(error));
1217
+ }
1218
+ function formatError(error) {
1219
+ return error instanceof Error ? error.message : String(error);
1220
+ }
1221
+ //#endregion
1222
+ //#region src/platform/home/config/rivus-home-config.ts
1223
+ /** Loads and validates the operator-owned Home config file. */
1224
+ function loadRivusHome(directoryPath) {
1225
+ const directory = resolve(directoryPath);
1226
+ const configPath = resolve(directory, "config.json");
1227
+ return Effect.tryPromise({
1228
+ try: async () => {
1229
+ const config = parseRivusHomeConfig(JSON.parse(await readFile(configPath, "utf8")));
1230
+ return {
1231
+ bootstrap: resolveBootstrap(directory, config.bootstrap),
1232
+ config,
1233
+ configPath,
1234
+ directory,
1235
+ envFilePath: resolveHomePath(directory, config.envFile, "envFile"),
1236
+ logsDirectory: resolveHomePath(directory, config.logs, "logs"),
1237
+ manifestPath: resolveHomePath(directory, config.manifest, "manifest"),
1238
+ stateDirectory: resolveHomePath(directory, config.state, "state"),
1239
+ workspaceDirectory: resolveHomePath(directory, config.workspace, "workspace")
1240
+ };
1241
+ },
1242
+ catch: asError
1243
+ });
1244
+ }
1245
+ function parseRivusHomeConfig(value) {
1246
+ const config = record(value, "Rivus Home config");
1247
+ if (config.version !== 1) throw new Error("Rivus Home config version must be 1");
1248
+ return {
1249
+ bootstrap: nonEmptyString(config.bootstrap, "bootstrap"),
1250
+ envFile: relativePath(config.envFile, "envFile"),
1251
+ logs: relativePath(config.logs, "logs"),
1252
+ manifest: relativePath(config.manifest, "manifest"),
1253
+ state: relativePath(config.state, "state"),
1254
+ version: 1,
1255
+ workspace: relativePath(config.workspace, "workspace")
1256
+ };
1257
+ }
1258
+ function resolveBootstrap(directory, value) {
1259
+ if (value.startsWith("./") || value.startsWith("../")) return resolveHomePath(directory, value, "bootstrap");
1260
+ if (isAbsolute(value)) throw new Error("Rivus Home bootstrap must be a package specifier or a relative path inside Rivus Home");
1261
+ return value;
1262
+ }
1263
+ function resolveHomePath(directory, value, owner) {
1264
+ const candidate = resolve(directory, value);
1265
+ const relation = relative(directory, candidate);
1266
+ if (relation === "" || !relation.startsWith(`..${sep}`) && relation !== ".." && !isAbsolute(relation)) return candidate;
1267
+ throw new Error(`Rivus Home ${owner} escapes the Home directory`);
1268
+ }
1269
+ function relativePath(value, owner) {
1270
+ const path = nonEmptyString(value, owner);
1271
+ if (isAbsolute(path)) throw new Error(`Rivus Home ${owner} must be a relative path`);
1272
+ return path;
1273
+ }
1274
+ function nonEmptyString(value, owner) {
1275
+ if (typeof value !== "string" || !value.trim()) throw new Error(`Rivus Home ${owner} must be a non-empty string`);
1276
+ return value;
1277
+ }
1278
+ function record(value, owner) {
1279
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${owner} must be an object`);
1280
+ return value;
1281
+ }
1282
+ function asError(error) {
1283
+ return error instanceof Error ? error : new Error(String(error));
1284
+ }
1285
+ //#endregion
1286
+ //#region src/platform/home/doctor/rivus-home-doctor.ts
1287
+ function diagnoseRivusHome(input, options) {
1288
+ return Effect.gen(function* () {
1289
+ const checks = [checkNode(input.nodeVersion)];
1290
+ const loaded = yield* options.load(input.directory).pipe(Effect.either);
1291
+ if (Either.isLeft(loaded)) {
1292
+ checks.push({
1293
+ message: `Rivus Home is invalid: ${loaded.left.message}`,
1294
+ name: "home",
1295
+ status: "fail"
1296
+ }, blockedCheck("workspace", "Workspace"), blockedCheck("manifest", "manifest"), blockedCheck("modules", "modules"), blockedCheck("credentials", "credentials"));
1297
+ return report(input.directory, checks);
1298
+ }
1299
+ const home = loaded.right;
1300
+ checks.push({
1301
+ message: "config.json is valid and contained in Rivus Home",
1302
+ name: "home",
1303
+ status: "pass"
1304
+ });
1305
+ checks.push(yield* checkWorkspace(home, options.findMissingWorkspacePaths));
1306
+ const deployment = yield* options.deploymentInspector.inspect({
1307
+ env: input.env,
1308
+ ...input.envFilePath ? { envFilePath: input.envFilePath } : {},
1309
+ home
1310
+ });
1311
+ checks.push(deployment.manifest, deployment.modules, deployment.credentials);
1312
+ return report(input.directory, checks);
1313
+ });
1314
+ }
1315
+ function checkNode(version) {
1316
+ const [major, minor] = version.split(".").map(Number);
1317
+ return major === 24 && Number.isInteger(minor) && minor >= 11 ? {
1318
+ message: `Node.js ${version} satisfies the supported ^24.11 runtime`,
1319
+ name: "node",
1320
+ status: "pass"
1321
+ } : {
1322
+ message: `Node.js 24.11 or newer on major 24 is required; current version is ${version}`,
1323
+ name: "node",
1324
+ status: "fail"
1325
+ };
1326
+ }
1327
+ function checkWorkspace(home, findMissingWorkspacePaths) {
1328
+ return findMissingWorkspacePaths(home).pipe(Effect.map((missing) => missing.length === 0 ? {
1329
+ message: "Workspace instructions, Memory, Skills, and work directories are present",
1330
+ name: "workspace",
1331
+ status: "pass"
1332
+ } : {
1333
+ message: `Workspace paths are missing: ${missing.join(", ")}`,
1334
+ name: "workspace",
1335
+ status: "fail"
1336
+ }));
1337
+ }
1338
+ function blockedCheck(name, owner) {
1339
+ return {
1340
+ message: `${owner} cannot be checked until config.json is valid`,
1341
+ name,
1342
+ status: "fail"
1343
+ };
1344
+ }
1345
+ function report(directory, checks) {
1346
+ return {
1347
+ checks,
1348
+ directory,
1349
+ ready: checks.every(({ status }) => status === "pass")
1350
+ };
1351
+ }
1352
+ //#endregion
1353
+ //#region src/platform/home/setup/rivus-home-layout.ts
1354
+ const HOME_DIRECTORIES = Object.freeze([
1355
+ "logs",
1356
+ "plugins",
1357
+ "state",
1358
+ "workspace/memory",
1359
+ "workspace/skills",
1360
+ "workspace/work/artifacts",
1361
+ "workspace/work/drafts",
1362
+ "workspace/work/inbox",
1363
+ "workspace/work/tmp"
1364
+ ]);
1365
+ function createRivusHomeLayout() {
1366
+ return {
1367
+ directories: HOME_DIRECTORIES,
1368
+ files: /* @__PURE__ */ new Map([
1369
+ [".env.example", environmentTemplate()],
1370
+ [".gitignore", ".DS_Store\n.env\nlogs/\nstate/\nworkspace/work/tmp/\n"],
1371
+ ["config.json", homeConfig()],
1372
+ ["rivus.config.json", deploymentManifest()],
1373
+ ["workspace/AGENTS.md", agentsTemplate()],
1374
+ ["workspace/IDENTITY.md", "# Identity\n\nName: Rivus\n\nRole: Personal agent\n"],
1375
+ ["workspace/MEMORY.md", "# Curated Memory\n\nStore confirmed, durable facts and decisions here.\n"],
1376
+ ["workspace/SOUL.md", "# Character\n\nBe direct, thoughtful, and evidence-led.\n"],
1377
+ ["workspace/USER.md", "# User\n\nRecord stable user preferences here.\n"],
1378
+ ["plugins/.gitkeep", ""],
1379
+ ["workspace/memory/.gitkeep", ""],
1380
+ ["workspace/skills/.gitkeep", ""],
1381
+ ["workspace/work/artifacts/.gitkeep", ""],
1382
+ ["workspace/work/drafts/.gitkeep", ""],
1383
+ ["workspace/work/inbox/.gitkeep", ""]
1384
+ ])
1385
+ };
1386
+ }
1387
+ function homeConfig() {
1388
+ return `${JSON.stringify({
1389
+ bootstrap: "@rivus/gateway/bootstrap/pi-feishu",
1390
+ envFile: ".env",
1391
+ logs: "logs",
1392
+ manifest: "rivus.config.json",
1393
+ state: "state",
1394
+ version: 1,
1395
+ workspace: "workspace"
1396
+ }, null, 2)}\n`;
1397
+ }
1398
+ function deploymentManifest() {
1399
+ return `${JSON.stringify({
1400
+ agents: [{
1401
+ agentId: "personal",
1402
+ endpointIds: ["personal-feishu"],
1403
+ memory: {
1404
+ scopes: ["agent-private"],
1405
+ tool: true
1406
+ },
1407
+ pluginId: "rivus-starter",
1408
+ profileId: "agent-a",
1409
+ projectSpaceId: "personal-home",
1410
+ runtimeTools: { allow: [
1411
+ "read",
1412
+ "bash",
1413
+ "edit",
1414
+ "write",
1415
+ "grep",
1416
+ "find",
1417
+ "ls"
1418
+ ] },
1419
+ skills: { allow: [] },
1420
+ tools: { allow: ["rivus-starter/current-weather"] }
1421
+ }],
1422
+ defaultAgentId: "personal",
1423
+ defaultEndpointId: "personal-feishu",
1424
+ endpoints: [{
1425
+ agentId: "personal",
1426
+ baseUrl: "https://open.feishu.cn",
1427
+ cardStreamLeaseMs: 51e4,
1428
+ credentialRef: "env:RIVUS_FEISHU",
1429
+ enabled: true,
1430
+ experimental: { cotMessages: false },
1431
+ groupPolicy: "mention-only",
1432
+ id: "personal-feishu",
1433
+ progressDisplay: "collapsed",
1434
+ required: true,
1435
+ sessionNamespace: "rivus-home-v1",
1436
+ streamMinIntervalMs: 200
1437
+ }],
1438
+ plugins: [{
1439
+ id: "rivus-starter",
1440
+ module: "@rivus/gateway/plugin/starter",
1441
+ required: true
1442
+ }],
1443
+ projectSpaces: [{
1444
+ id: "personal-home",
1445
+ root: "workspace",
1446
+ skills: { sources: ["skills"] },
1447
+ workingDirectory: "."
1448
+ }]
1449
+ }, null, 2)}\n`;
1450
+ }
1451
+ function environmentTemplate() {
1452
+ return [
1453
+ "# Copy this file to .env and keep the real values untracked.",
1454
+ "RIVUS_FEISHU_APP_ID=",
1455
+ "RIVUS_FEISHU_APP_SECRET=",
1456
+ "PI_MODEL=",
1457
+ "PI_API_KEY=",
1458
+ "# PI_BASE_URL=",
1459
+ "RIVUS_WEATHER_DEFAULT_LOCATION=上海",
1460
+ ""
1461
+ ].join("\n");
1462
+ }
1463
+ function agentsTemplate() {
1464
+ return [
1465
+ "# Personal Workspace",
1466
+ "",
1467
+ "Use this directory as the default home for personal work.",
1468
+ "",
1469
+ "- Read `SOUL.md` and `IDENTITY.md` when identity or tone matters.",
1470
+ "- Read `USER.md` when stable user preferences affect the task.",
1471
+ "- Search `MEMORY.md` and dated files under `memory/` when prior facts or decisions matter.",
1472
+ "- Read the selected `skills/<name>/SKILL.md` before following a Workspace Skill.",
1473
+ "- Put incoming material in `work/inbox/`, drafts in `work/drafts/`, and durable general outputs in `work/artifacts/`.",
1474
+ "- Put disposable files in `work/tmp/`.",
1475
+ "- Store only confirmed durable facts in Memory; keep credentials and raw private transcripts out of tracked files.",
1476
+ ""
1477
+ ].join("\n");
1478
+ }
1479
+ //#endregion
1480
+ //#region src/platform/home/setup/rivus-home-initializer.ts
1481
+ function initializeRivusHome(directoryPath) {
1482
+ const directory = resolve(directoryPath);
1483
+ const { directories, files } = createRivusHomeLayout();
1484
+ const paths = [...files.keys()].sort();
1485
+ return Effect.tryPromise({
1486
+ try: async () => {
1487
+ for (const path of [...directories].sort()) await mkdir(join(directory, path), { recursive: true });
1488
+ for (const path of paths) {
1489
+ const destination = join(directory, path);
1490
+ await mkdir(dirname(destination), { recursive: true });
1491
+ await writeFile(destination, files.get(path), {
1492
+ encoding: "utf8",
1493
+ flag: "wx"
1494
+ });
1495
+ }
1496
+ return {
1497
+ directory,
1498
+ files: paths
1499
+ };
1500
+ },
1501
+ catch: (error) => error instanceof Error ? error : new Error(String(error))
1502
+ });
1503
+ }
1504
+ //#endregion
1505
+ //#region src/platform/home/workspace/rivus-home-workspace.ts
1506
+ function findMissingRivusHomeWorkspacePaths(home) {
1507
+ const required = [
1508
+ home.workspaceDirectory,
1509
+ resolve(home.workspaceDirectory, "AGENTS.md"),
1510
+ resolve(home.workspaceDirectory, "MEMORY.md"),
1511
+ resolve(home.workspaceDirectory, "memory"),
1512
+ resolve(home.workspaceDirectory, "skills"),
1513
+ resolve(home.workspaceDirectory, "work")
1514
+ ];
1515
+ return Effect.tryPromise({
1516
+ try: async () => {
1517
+ const missing = [];
1518
+ for (const path of required) try {
1519
+ await stat(path);
1520
+ } catch (error) {
1521
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") missing.push(path);
1522
+ else throw error;
1523
+ }
1524
+ return missing;
1525
+ },
1526
+ catch: (error) => error instanceof Error ? error : new Error(String(error))
1527
+ });
1528
+ }
1529
+ //#endregion
1530
+ //#region src/platform/home/node/node-rivus-home.ts
1531
+ function createNodeRivusHome(options) {
1532
+ return {
1533
+ diagnose: (input) => diagnoseRivusHome(input, {
1534
+ deploymentInspector: options.deploymentInspector,
1535
+ findMissingWorkspacePaths: findMissingRivusHomeWorkspacePaths,
1536
+ load: loadRivusHome
1537
+ }),
1538
+ load: loadRivusHome,
1539
+ setup: initializeRivusHome
1540
+ };
1541
+ }
1542
+ //#endregion
1543
+ //#region src/adapters/cli/command/rivus-cli-protocol.ts
1544
+ const RIVUS_CLI_USAGE = `Usage:
1545
+ rivus setup [directory]
1546
+ rivus start
1547
+ rivus status
1548
+ rivus check-config
1549
+ rivus init [directory]
1550
+ rivus doctor [directory] [--env-file <path>]
1551
+ rivus model <status|set|rollback> ...
1552
+ rivus --bootstrap <module> [--manifest <rivus.config.json>] [options]
1553
+
1554
+ Commands:
1555
+ setup Create Rivus Home (default ~/.rivus-agent) without overwriting files
1556
+ start Start the Rivus Home deployment in the foreground
1557
+ status Print Rivus Home deployment status without activating Endpoints
1558
+ check-config
1559
+ Validate and print the redacted Rivus Home manifest
1560
+ init Create a standalone local Rivus project without overwriting files
1561
+ doctor Check Rivus Home by default, or an explicit standalone project directory
1562
+ model Query or change the managed default model through the current Home
1563
+
1564
+ Run rivus --help for the complete daemon option list.
1565
+ `;
1566
+ function renderRivusCliError(error) {
1567
+ return `${error instanceof Error ? error.message : String(error)}\n`;
1568
+ }
1569
+ function renderRivusCliUnknownCommand(command) {
1570
+ return `Unknown command: ${command}\n\n${RIVUS_CLI_USAGE}`;
1571
+ }
1572
+ function renderRivusDirectoryCommandUsage(command) {
1573
+ return `Usage: rivus ${command} [directory]\n`;
1574
+ }
1575
+ function renderRivusHomeCommandUsage(command) {
1576
+ return `Usage: rivus ${command}\n`;
1577
+ }
1578
+ function renderRivusDoctorUsage() {
1579
+ return "Usage: rivus doctor [directory] [--env-file <path>]\n";
1580
+ }
1581
+ function renderRivusDoctorArgumentError(error) {
1582
+ return `${error}\n${renderRivusDoctorUsage()}`;
1583
+ }
1584
+ function renderRivusSetupSuccess(directory) {
1585
+ return `Initialized Rivus Home in ${directory}\n\nNext:\n cp ${shellQuote(`${directory}/.env.example`)} ${shellQuote(`${directory}/.env`)}\n rivus doctor\n rivus start\n`;
1586
+ }
1587
+ function renderRivusProjectInitializationSuccess(directory) {
1588
+ return `Initialized Rivus project in ${directory}\n\nNext:\n cd ${shellQuote(directory)}\n npm install\n cp .env.example .env.local\n npm run doctor\n npm start\n`;
1589
+ }
1590
+ function* renderRivusDoctorReport(report, owner) {
1591
+ yield `Rivus doctor: ${report.directory}\n`;
1592
+ for (const check of report.checks) yield `${check.status === "pass" ? "PASS" : "FAIL"} ${check.name}: ${check.message}\n`;
1593
+ yield report.ready ? `Rivus ${owner} is ready\n` : `Rivus ${owner} is not ready\n`;
1594
+ }
1595
+ function parseRivusDirectoryArguments(argv) {
1596
+ if (argv.includes("--help") || argv.includes("-h")) return { help: true };
1597
+ if (argv.length > 1 || argv[0]?.startsWith("-")) return { error: "invalid directory arguments" };
1598
+ return argv[0] === void 0 ? {} : { directory: argv[0] };
1599
+ }
1600
+ function hasRivusHomeCommandArguments(argv) {
1601
+ return argv.length > 0;
1602
+ }
1603
+ function parseRivusDoctorArguments(argv) {
1604
+ let directory;
1605
+ let envFilePath;
1606
+ for (let index = 0; index < argv.length; index += 1) {
1607
+ const argument = argv[index];
1608
+ if (argument === "--help" || argument === "-h") return { help: true };
1609
+ if (argument === "--env-file") {
1610
+ const value = argv[index + 1];
1611
+ if (!value) return { error: "--env-file requires a path" };
1612
+ envFilePath = value;
1613
+ index += 1;
1614
+ continue;
1615
+ }
1616
+ if (argument.startsWith("--env-file=")) {
1617
+ envFilePath = argument.slice(11);
1618
+ if (!envFilePath) return { error: "--env-file requires a path" };
1619
+ continue;
1620
+ }
1621
+ if (argument.startsWith("-")) return { error: `Unknown doctor option: ${argument}` };
1622
+ if (directory !== void 0) return { error: "doctor accepts at most one directory" };
1623
+ directory = argument;
1624
+ }
1625
+ return {
1626
+ ...directory !== void 0 ? { directory } : {},
1627
+ ...envFilePath !== void 0 ? { envFilePath } : {}
1628
+ };
1629
+ }
1630
+ function shellQuote(value) {
1631
+ return `'${value.replaceAll("'", "'\\''")}'`;
1632
+ }
1633
+ //#endregion
1634
+ //#region src/adapters/cli/model/rivus-model-management-socket-client.ts
1635
+ const MAX_FRAME_BYTES = 64 * 1024;
1636
+ const DEFAULT_TIMEOUT_MS = 1e4;
1637
+ var RivusModelManagementTransportError = class extends Error {
1638
+ code;
1639
+ constructor(code, message, options) {
1640
+ super(message, options);
1641
+ this.name = "RivusModelManagementTransportError";
1642
+ this.code = code;
1643
+ }
1644
+ };
1645
+ function createRivusModelManagementSocketClient(options) {
1646
+ if (!isAbsolute(options.socketPath)) throw new Error("model socket path must be absolute");
1647
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1648
+ return { execute: (command) => request(options.socketPath, options.env, command, timeoutMs) };
1649
+ }
1650
+ async function request(socketPath, env, command, timeoutMs) {
1651
+ const payload = createRivusModelManagementWireRequest(command, env);
1652
+ return new Promise((resolve, reject) => {
1653
+ const socket = createConnection(socketPath);
1654
+ let response = "";
1655
+ let settled = false;
1656
+ const finish = (callback) => {
1657
+ if (settled) return;
1658
+ settled = true;
1659
+ callback();
1660
+ };
1661
+ socket.setEncoding("utf8");
1662
+ socket.setTimeout(timeoutMs, () => {
1663
+ finish(() => reject(new RivusModelManagementTransportError("timeout", "model management socket timed out")));
1664
+ socket.destroy();
1665
+ });
1666
+ socket.on("connect", () => socket.write(`${JSON.stringify(payload)}\n`));
1667
+ socket.on("data", (chunk) => {
1668
+ response += chunk;
1669
+ if (Buffer.byteLength(response, "utf8") > MAX_FRAME_BYTES) {
1670
+ finish(() => reject(new RivusModelManagementTransportError("invalid_response", "model response is too large")));
1671
+ socket.destroy();
1672
+ }
1673
+ });
1674
+ socket.on("error", (error) => {
1675
+ finish(() => reject(new RivusModelManagementTransportError("socket_error", "model management socket is unavailable", { cause: error })));
1676
+ });
1677
+ socket.on("end", () => {
1678
+ const line = response.split("\n", 1)[0]?.trim();
1679
+ if (!line) {
1680
+ finish(() => reject(new RivusModelManagementTransportError("invalid_response", "model response was empty")));
1681
+ return;
1682
+ }
1683
+ try {
1684
+ const parsed = JSON.parse(line);
1685
+ if (!isResponse(parsed)) throw new Error("model response must be a JSON object");
1686
+ finish(() => resolve(parsed));
1687
+ } catch (error) {
1688
+ finish(() => reject(new RivusModelManagementTransportError("invalid_response", "model response was not valid JSON", { cause: error })));
1689
+ }
1690
+ });
1691
+ });
1692
+ }
1693
+ function isResponse(value) {
1694
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1695
+ }
1696
+ //#endregion
1697
+ //#region src/adapters/cli/model/rivus-model-socket.ts
1698
+ const RIVUS_MODEL_SOCKET_ENV = "RIVUS_MODEL_SOCKET";
1699
+ const RIVUS_MODEL_MANAGEMENT_ENABLED_ENV = "RIVUS_MODEL_MANAGEMENT_ENABLED";
1700
+ const RIVUS_MODEL_SOCKET_RELATIVE_PATH = "state/model-management/control.sock";
1701
+ function resolveRivusModelSocketPath(options) {
1702
+ const configured = optional(options.env[RIVUS_MODEL_SOCKET_ENV]);
1703
+ if (configured) {
1704
+ if (!isAbsolute(configured)) throw new Error(`${RIVUS_MODEL_SOCKET_ENV} must be an absolute path`);
1705
+ return resolve(configured);
1706
+ }
1707
+ const configuredHome = optional(options.env.RIVUS_HOME);
1708
+ return join(configuredHome ? resolveAbsoluteHome(configuredHome) : resolve(options.homeDirectory, ".rivus-agent"), RIVUS_MODEL_SOCKET_RELATIVE_PATH);
1709
+ }
1710
+ function isRivusModelManagementEnabled(env) {
1711
+ const value = optional(env[RIVUS_MODEL_MANAGEMENT_ENABLED_ENV]);
1712
+ return value === "1" || value === "true";
1713
+ }
1714
+ function resolveAbsoluteHome(value) {
1715
+ if (!isAbsolute(value)) throw new Error("RIVUS_HOME must be an absolute path");
1716
+ return resolve(value);
1717
+ }
1718
+ function optional(value) {
1719
+ return value?.trim() || void 0;
1720
+ }
1721
+ //#endregion
1722
+ //#region src/adapters/openclaw/config/openclaw-env-import.ts
1723
+ var OpenClawEnvImportError = class extends Error {
1724
+ constructor(message) {
1725
+ super(message);
1726
+ this.name = "OpenClawEnvImportError";
1727
+ }
1728
+ };
1729
+ const DEFAULT_AGENT_ID = "main";
1730
+ const DEFAULT_FEISHU_BASE_URL = "https://open.feishu.cn";
1731
+ const DEFAULT_LARK_BASE_URL = "https://open.larksuite.com";
1732
+ const DEFAULT_STREAM_MIN_INTERVAL_MS = 200;
1733
+ const THINKING_LEVELS = /* @__PURE__ */ new Set([
1734
+ "off",
1735
+ "minimal",
1736
+ "low",
1737
+ "medium",
1738
+ "high",
1739
+ "xhigh"
1740
+ ]);
1741
+ const ENV_FILE_ORDER = [
1742
+ "FEISHU_APP_ID",
1743
+ "FEISHU_APP_SECRET",
1744
+ "FEISHU_BASE_URL",
1745
+ "FEISHU_STREAM_MIN_INTERVAL_MS",
1746
+ "RIVUS_AGENT_ID",
1747
+ "PI_API_KEY_FILE",
1748
+ "PI_BASE_URL",
1749
+ "PI_MODEL",
1750
+ "PI_THINKING_LEVEL"
1751
+ ];
1752
+ function createRivusEnvFromOpenClawConfig(openClawConfig, options = {}) {
1753
+ const config = asRecord(openClawConfig, "OpenClaw config");
1754
+ const feishu = asRecord(readPath(config, ["channels", "feishu"]), "channels.feishu");
1755
+ const appId = requiredString(feishu, "appId", "channels.feishu.appId");
1756
+ const appSecret = requiredString(feishu, "appSecret", "channels.feishu.appSecret");
1757
+ const modelReference = findPrimaryModelReference(config);
1758
+ const providerId = modelReference ? parseProviderId(modelReference) : void 0;
1759
+ const provider = providerId ? optionalRecord(readPath(config, [
1760
+ "models",
1761
+ "providers",
1762
+ providerId
1763
+ ])) : void 0;
1764
+ const providerBaseUrl = provider ? optionalString(provider.baseUrl) : void 0;
1765
+ const thinkingLevel = modelReference ? findThinkingLevel(config, modelReference) : void 0;
1766
+ const warnings = thinkingLevel?.warning ? [thinkingLevel.warning] : [];
1767
+ return {
1768
+ env: {
1769
+ FEISHU_APP_ID: appId,
1770
+ FEISHU_APP_SECRET: appSecret,
1771
+ FEISHU_BASE_URL: options.feishuBaseUrl ?? inferFeishuBaseUrl(optionalString(feishu.domain)),
1772
+ FEISHU_STREAM_MIN_INTERVAL_MS: String(options.streamMinIntervalMs ?? DEFAULT_STREAM_MIN_INTERVAL_MS),
1773
+ RIVUS_AGENT_ID: findAgentId(config),
1774
+ ...options.piApiKeyFile ? { PI_API_KEY_FILE: options.piApiKeyFile } : {},
1775
+ ...providerBaseUrl ? { PI_BASE_URL: providerBaseUrl } : {},
1776
+ ...modelReference ? { PI_MODEL: modelReference } : {},
1777
+ ...thinkingLevel?.level ? { PI_THINKING_LEVEL: thinkingLevel.level } : {}
1778
+ },
1779
+ warnings
1780
+ };
1781
+ }
1782
+ function formatRivusEnvFile(env) {
1783
+ return `${[...ENV_FILE_ORDER.filter((key) => Object.hasOwn(env, key)), ...Object.keys(env).filter((key) => !ENV_FILE_ORDER.includes(key)).sort()].map((key) => `${key}=${quoteEnvValue(env[key] ?? "")}`).join("\n")}\n`;
1784
+ }
1785
+ function findAgentId(config) {
1786
+ const agents = optionalRecord(config.agents);
1787
+ return optionalString(optionalRecord((Array.isArray(agents?.list) ? agents.list : [])[0])?.id) ?? DEFAULT_AGENT_ID;
1788
+ }
1789
+ function findPrimaryModelReference(config) {
1790
+ const primary = optionalString(readPath(config, [
1791
+ "agents",
1792
+ "defaults",
1793
+ "model",
1794
+ "primary"
1795
+ ]));
1796
+ if (primary) return primary;
1797
+ const providers = optionalRecord(readPath(config, ["models", "providers"]));
1798
+ if (!providers) return;
1799
+ for (const [providerId, provider] of Object.entries(providers)) {
1800
+ const model = firstModelId(optionalRecord(provider));
1801
+ if (model) return `${providerId}/${model}`;
1802
+ }
1803
+ }
1804
+ function firstModelId(provider) {
1805
+ return optionalString(optionalRecord((Array.isArray(provider?.models) ? provider.models : [])[0])?.id);
1806
+ }
1807
+ function parseProviderId(modelReference) {
1808
+ const separator = modelReference.indexOf("/");
1809
+ return separator > 0 ? modelReference.slice(0, separator) : void 0;
1810
+ }
1811
+ function findThinkingLevel(config, modelReference) {
1812
+ const providerId = parseProviderId(modelReference);
1813
+ const modelId = readModelId(modelReference);
1814
+ const rawLevel = [
1815
+ readPath(config, [
1816
+ "agents",
1817
+ "defaults",
1818
+ "models",
1819
+ modelReference,
1820
+ "thinkingLevel"
1821
+ ]),
1822
+ readPath(config, [
1823
+ "agents",
1824
+ "defaults",
1825
+ "models",
1826
+ modelReference,
1827
+ "thinkLevel"
1828
+ ]),
1829
+ readPath(config, [
1830
+ "agents",
1831
+ "defaults",
1832
+ "models",
1833
+ modelReference,
1834
+ "reasoningLevel"
1835
+ ]),
1836
+ ...providerId && modelId ? readProviderModelThinkingCandidates(config, providerId, modelId) : []
1837
+ ].map(optionalString).find(Boolean);
1838
+ if (!rawLevel) return;
1839
+ if (THINKING_LEVELS.has(rawLevel)) return { level: rawLevel };
1840
+ return { warning: `Unsupported OpenClaw thinking level '${rawLevel}' was ignored` };
1841
+ }
1842
+ function readProviderModelThinkingCandidates(config, providerId, modelId) {
1843
+ const providerModels = readPath(config, [
1844
+ "models",
1845
+ "providers",
1846
+ providerId,
1847
+ "models"
1848
+ ]);
1849
+ if (!Array.isArray(providerModels)) return [];
1850
+ const model = providerModels.map(optionalRecord).find((candidate) => optionalString(candidate?.id) === modelId);
1851
+ if (!model) return [];
1852
+ return [
1853
+ model.thinkingLevel,
1854
+ model.thinkLevel,
1855
+ model.reasoningLevel,
1856
+ readPath(model, ["reasoning", "level"]),
1857
+ readPath(model, ["reasoning", "thinkingLevel"]),
1858
+ readPath(model, ["reasoning", "thinkLevel"])
1859
+ ];
1860
+ }
1861
+ function readModelId(modelReference) {
1862
+ const separator = modelReference.indexOf("/");
1863
+ return separator >= 0 && separator < modelReference.length - 1 ? modelReference.slice(separator + 1) : void 0;
1864
+ }
1865
+ function inferFeishuBaseUrl(domain) {
1866
+ return domain === "lark" ? DEFAULT_LARK_BASE_URL : DEFAULT_FEISHU_BASE_URL;
1867
+ }
1868
+ function quoteEnvValue(value) {
1869
+ return `'${value.replaceAll("'", "'\\''")}'`;
1870
+ }
1871
+ function requiredString(record, key, path) {
1872
+ const value = optionalString(record[key]);
1873
+ if (!value) throw new OpenClawEnvImportError(`${path} is required`);
1874
+ return value;
1875
+ }
1876
+ function optionalString(value) {
1877
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
1878
+ }
1879
+ function asRecord(value, path) {
1880
+ const record = optionalRecord(value);
1881
+ if (!record) throw new OpenClawEnvImportError(`${path} must be an object`);
1882
+ return record;
1883
+ }
1884
+ function optionalRecord(value) {
1885
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
1886
+ }
1887
+ function readPath(record, path) {
1888
+ let value = record;
1889
+ for (const segment of path) {
1890
+ const current = optionalRecord(value);
1891
+ if (!current) return;
1892
+ value = current[segment];
1893
+ }
1894
+ return value;
1895
+ }
1896
+ //#endregion
1897
+ //#region src/adapters/cli/config/rivus-daemon-config.ts
1898
+ async function loadRivusEnvFromOpenClawConfig(filePath, piApiKeyFile) {
1899
+ return createRivusEnvFromOpenClawConfig(JSON.parse(await readFile(filePath, "utf8")), piApiKeyFile ? { piApiKeyFile } : {});
1900
+ }
1901
+ function toRedactedConfig(config) {
1902
+ return {
1903
+ agentId: config.agentId,
1904
+ feishu: {
1905
+ appIdPresent: Boolean(config.feishu.appId),
1906
+ appSecretPresent: Boolean(config.feishu.appSecret),
1907
+ baseUrl: config.feishu.baseUrl,
1908
+ cardStreamLeaseMs: config.feishu.cardStreamLeaseMs,
1909
+ streamMinIntervalMs: config.feishu.streamMinIntervalMs
1910
+ },
1911
+ pi: {
1912
+ apiKeyPresent: Boolean(config.pi.apiKey),
1913
+ ...config.pi.baseUrl ? { baseUrl: config.pi.baseUrl } : {},
1914
+ ...config.pi.model ? { model: config.pi.model } : {},
1915
+ ...config.pi.thinkingLevel ? { thinkingLevel: config.pi.thinkingLevel } : {}
1916
+ }
1917
+ };
1918
+ }
1919
+ function toRedactedDeploymentManifest(manifest) {
1920
+ return {
1921
+ agents: manifest.agents.map(({ agentId, endpointIds, pluginId, profileId }) => ({
1922
+ agentId,
1923
+ endpointIds,
1924
+ pluginId,
1925
+ profileId
1926
+ })),
1927
+ automations: (manifest.automations ?? []).map(({ agentId, delivery, enabled, id, required, schedule, templateId, timeZone }) => ({
1928
+ agentId,
1929
+ delivery: {
1930
+ endpointId: delivery.endpointId,
1931
+ targetRef: delivery.targetRef,
1932
+ targetType: delivery.targetType
1933
+ },
1934
+ enabled,
1935
+ id,
1936
+ required,
1937
+ schedule,
1938
+ templateId,
1939
+ timeZone
1940
+ })),
1941
+ ...manifest.backgroundSessions ? { backgroundSessions: {
1942
+ enabled: manifest.backgroundSessions.enabled,
1943
+ leaseMs: manifest.backgroundSessions.leaseMs,
1944
+ leaseRenewalIntervalMs: manifest.backgroundSessions.leaseRenewalIntervalMs,
1945
+ maxConsecutiveFailures: manifest.backgroundSessions.maxConsecutiveFailures,
1946
+ maxConcurrentSessions: manifest.backgroundSessions.maxConcurrentSessions,
1947
+ required: manifest.backgroundSessions.required,
1948
+ retryBackoffMs: manifest.backgroundSessions.retryBackoffMs,
1949
+ sessionLifetimeMs: manifest.backgroundSessions.sessionLifetimeMs,
1950
+ stepTimeoutMs: manifest.backgroundSessions.stepTimeoutMs
1951
+ } } : {},
1952
+ defaultAgentId: manifest.defaultAgentId,
1953
+ defaultEndpointId: manifest.defaultEndpointId,
1954
+ endpoints: manifest.endpoints.map(({ agentId, credentialRef, enabled, id, required, sessionNamespace }) => ({
1955
+ agentId,
1956
+ credentialRef,
1957
+ enabled,
1958
+ id,
1959
+ required,
1960
+ sessionNamespace
1961
+ })),
1962
+ plugins: manifest.plugins.map(({ id, module, required }) => ({
1963
+ id,
1964
+ module,
1965
+ required
1966
+ }))
1967
+ };
1968
+ }
1969
+ async function loadCliEnv(envFilePath, overrideEnv) {
1970
+ if (!envFilePath) return overrideEnv;
1971
+ return loadMergedLocalEnvFile(envFilePath, overrideEnv);
1972
+ }
1973
+ //#endregion
1974
+ //#region src/adapters/cli/recovery/rivus-recovery-cli.ts
1975
+ function createRivusRecoveryCliParser() {
1976
+ const input = { recoveryList: false };
1977
+ return {
1978
+ build: () => buildCommand(input),
1979
+ consume: (argument, next) => consumeArgument(input, argument, next)
1980
+ };
1981
+ }
1982
+ async function runRivusRecoveryCliCommand(control, command) {
1983
+ switch (command.type) {
1984
+ case "inspect": return Effect.runPromise(control.inspect());
1985
+ case "requeue-dead-letter": return Effect.runPromise(control.requeueDeadLetter({
1986
+ actorId: "local-cli",
1987
+ deliveryId: command.deliveryId,
1988
+ endpointId: command.endpointId,
1989
+ expectedRevision: command.expectedRevision,
1990
+ note: await readPrivateTextFile(command.noteFilePath, "Recovery note", 16 * 1024)
1991
+ }));
1992
+ case "resolve-tool-operation": {
1993
+ const note = await readPrivateTextFile(command.noteFilePath, "Recovery note", 16 * 1024);
1994
+ const outcome = command.outcome.status === "applied" ? {
1995
+ result: parseToolResult(await readPrivateTextFile(command.outcome.resultFilePath, "Tool result", 1024 * 1024)),
1996
+ status: "applied"
1997
+ } : command.outcome;
1998
+ return Effect.runPromise(control.resolveToolOperation({
1999
+ actorId: "local-cli",
2000
+ expectedRevision: command.expectedRevision,
2001
+ instanceId: command.instanceId,
2002
+ note,
2003
+ operationId: command.operationId,
2004
+ outcome
2005
+ }));
2006
+ }
2007
+ }
2008
+ }
2009
+ function consumeArgument(input, argument, next) {
2010
+ if (argument === "--recovery-list") {
2011
+ input.recoveryList = true;
2012
+ return {
2013
+ consumed: 0,
2014
+ handled: true
2015
+ };
2016
+ }
2017
+ for (const [flag, key] of [
2018
+ ["--requeue-dead-letter", "requeueDeadLetterId"],
2019
+ ["--resolve-tool-operation", "resolveToolOperationId"],
2020
+ ["--endpoint-id", "endpointId"],
2021
+ ["--instance-id", "instanceId"],
2022
+ ["--expected-revision", "expectedRevision"],
2023
+ ["--recovery-note-file", "recoveryNoteFile"],
2024
+ ["--tool-outcome", "toolOutcome"],
2025
+ ["--tool-result-file", "toolResultFile"]
2026
+ ]) {
2027
+ if (argument === flag) {
2028
+ if (!next) return {
2029
+ consumed: 0,
2030
+ error: `${flag} requires a value`,
2031
+ handled: true
2032
+ };
2033
+ input[key] = next;
2034
+ return {
2035
+ consumed: 1,
2036
+ handled: true
2037
+ };
2038
+ }
2039
+ if (argument?.startsWith(`${flag}=`)) {
2040
+ const value = argument.slice(flag.length + 1);
2041
+ if (!value) return {
2042
+ consumed: 0,
2043
+ error: `${flag} requires a value`,
2044
+ handled: true
2045
+ };
2046
+ input[key] = value;
2047
+ return {
2048
+ consumed: 0,
2049
+ handled: true
2050
+ };
2051
+ }
2052
+ }
2053
+ return {
2054
+ consumed: 0,
2055
+ handled: false
2056
+ };
2057
+ }
2058
+ function buildCommand(input) {
2059
+ const actionCount = Number(input.recoveryList) + Number(input.requeueDeadLetterId !== void 0) + Number(input.resolveToolOperationId !== void 0);
2060
+ const hasOptions = input.endpointId !== void 0 || input.expectedRevision !== void 0 || input.instanceId !== void 0 || input.recoveryNoteFile !== void 0 || input.toolOutcome !== void 0 || input.toolResultFile !== void 0;
2061
+ if (actionCount === 0) return hasOptions ? { error: "Recovery options require --recovery-list, --requeue-dead-letter, or --resolve-tool-operation" } : {};
2062
+ if (actionCount > 1) return { error: "Choose only one recovery command" };
2063
+ if (input.recoveryList) return hasOptions ? { error: "--recovery-list does not accept mutation options" } : { command: { type: "inspect" } };
2064
+ const expectedRevision = parsePositiveInteger(input.expectedRevision);
2065
+ if (expectedRevision === void 0) return { error: "Recovery mutations require --expected-revision with a positive integer" };
2066
+ const noteFilePath = input.recoveryNoteFile?.trim();
2067
+ if (!noteFilePath) return { error: "Recovery mutations require --recovery-note-file" };
2068
+ if (input.requeueDeadLetterId !== void 0) return buildDeadLetterCommand(input, expectedRevision, noteFilePath);
2069
+ return buildToolOperationCommand(input, expectedRevision, noteFilePath);
2070
+ }
2071
+ function buildDeadLetterCommand(input, expectedRevision, noteFilePath) {
2072
+ const endpointId = input.endpointId?.trim();
2073
+ if (!endpointId) return { error: "--requeue-dead-letter requires --endpoint-id" };
2074
+ if (input.instanceId !== void 0 || input.toolOutcome !== void 0 || input.toolResultFile !== void 0) return { error: "--requeue-dead-letter cannot use Tool reconciliation options" };
2075
+ return { command: {
2076
+ deliveryId: input.requeueDeadLetterId,
2077
+ endpointId,
2078
+ expectedRevision,
2079
+ noteFilePath,
2080
+ type: "requeue-dead-letter"
2081
+ } };
2082
+ }
2083
+ function buildToolOperationCommand(input, expectedRevision, noteFilePath) {
2084
+ const instanceId = input.instanceId?.trim();
2085
+ if (!instanceId) return { error: "--resolve-tool-operation requires --instance-id" };
2086
+ if (input.endpointId !== void 0) return { error: "--resolve-tool-operation cannot use --endpoint-id" };
2087
+ if (input.toolOutcome !== "applied" && input.toolOutcome !== "not-applied") return { error: "--resolve-tool-operation requires --tool-outcome applied or not-applied" };
2088
+ if (input.toolOutcome === "not-applied") {
2089
+ if (input.toolResultFile !== void 0) return { error: "--tool-result-file is only valid when --tool-outcome is applied" };
2090
+ return { command: {
2091
+ expectedRevision,
2092
+ instanceId,
2093
+ noteFilePath,
2094
+ operationId: input.resolveToolOperationId,
2095
+ outcome: { status: "not-applied" },
2096
+ type: "resolve-tool-operation"
2097
+ } };
2098
+ }
2099
+ const resultFilePath = input.toolResultFile?.trim();
2100
+ if (!resultFilePath) return { error: "--tool-outcome applied requires --tool-result-file" };
2101
+ return { command: {
2102
+ expectedRevision,
2103
+ instanceId,
2104
+ noteFilePath,
2105
+ operationId: input.resolveToolOperationId,
2106
+ outcome: {
2107
+ resultFilePath,
2108
+ status: "applied"
2109
+ },
2110
+ type: "resolve-tool-operation"
2111
+ } };
2112
+ }
2113
+ function parsePositiveInteger(value) {
2114
+ return value && /^[1-9]\d*$/.test(value) ? Number(value) : void 0;
2115
+ }
2116
+ async function readPrivateTextFile(filePath, label, maxBytes) {
2117
+ const handle = await open(filePath, constants$1.O_RDONLY | constants$1.O_NOFOLLOW);
2118
+ try {
2119
+ const metadata = await handle.stat();
2120
+ if (!metadata.isFile()) throw new Error(`${label} must be a regular file`);
2121
+ if ((metadata.mode & 63) !== 0) throw new Error(`${label} file permissions must be 0600 or stricter`);
2122
+ if (metadata.size > maxBytes) throw new Error(`${label} file exceeds ${maxBytes} bytes`);
2123
+ return (await handle.readFile("utf8")).trim();
2124
+ } finally {
2125
+ await handle.close();
2126
+ }
2127
+ }
2128
+ function parseToolResult(value) {
2129
+ try {
2130
+ return JSON.parse(value);
2131
+ } catch {
2132
+ throw new Error("Tool result file must contain valid JSON");
2133
+ }
2134
+ }
2135
+ //#endregion
2136
+ //#region src/adapters/cli/command/rivus-daemon-arguments.ts
2137
+ const RIVUS_DAEMON_USAGE = `Usage: rivus --bootstrap <module> [--manifest <rivus.config.json>]
2138
+
2139
+ Starts a local Rivus Agent daemon from an injected bootstrap module.
2140
+
2141
+ Project commands:
2142
+ rivus setup [directory]
2143
+ rivus start
2144
+ rivus status
2145
+ rivus check-config
2146
+ rivus init [directory]
2147
+ rivus doctor [directory] [--env-file <path>]
2148
+ rivus model <status|set|rollback> ...
2149
+
2150
+ Options:
2151
+ --bootstrap <module> Module exporting createRivusDaemonProcess(context)
2152
+ --manifest <path> Start the manifest-driven multi-agent deployment; bootstrap exports createRivusDeploymentAdapters(context)
2153
+ --env-file <path> Load local KEY=value config before reading environment
2154
+ --check-config Print redacted local config JSON and exit
2155
+ --prompt <text> Run one local prompt through bootstrap promptText() and exit
2156
+ --replay-feishu-event <json>
2157
+ Replay one Feishu receive-message payload through bootstrap replayReceiveMessage() and exit
2158
+ --replay-feishu-text <text>
2159
+ Replay one synthetic Feishu receive-message text payload without Feishu side effects and exit
2160
+ --feishu-message-id <id>
2161
+ Message id for --replay-feishu-text (default om_cli_<timestamp>)
2162
+ --feishu-chat-id <id> Chat id for --replay-feishu-text (default oc_cli)
2163
+ --feishu-thread-id <id>
2164
+ Thread id for --replay-feishu-text (default omt_cli)
2165
+ --feishu-tenant-key <key>
2166
+ Tenant key for --replay-feishu-text (default tenant_cli)
2167
+ --print-openclaw-env <json>
2168
+ Print a Rivus env file from an OpenClaw config JSON and exit
2169
+ --pi-api-key-file <path>
2170
+ Add PI_API_KEY_FILE when using --print-openclaw-env
2171
+ --session-key <key> Session key for --prompt (default local:<agent-id>:cli)
2172
+ --status Print bootstrap status JSON without starting the daemon
2173
+ --recovery-list List Dead Letters and Tool operations requiring reconciliation
2174
+ --requeue-dead-letter <message-id>
2175
+ Requeue one Dead Letter; requires --endpoint-id, --expected-revision, and --recovery-note-file
2176
+ --resolve-tool-operation <operation-id>
2177
+ Resolve one uncertain Tool operation; requires --instance-id, --expected-revision,
2178
+ --tool-outcome, and --recovery-note-file
2179
+ --endpoint-id <id> Endpoint owning the Dead Letter
2180
+ --instance-id <id> Agent Instance owning the Tool operation
2181
+ --expected-revision <n>
2182
+ Exact record revision required by a recovery mutation
2183
+ --recovery-note-file <path>
2184
+ Private (0600) file containing the required audit note
2185
+ --tool-outcome <applied|not-applied>
2186
+ Confirm whether the external Tool effect occurred
2187
+ --tool-result-file <path>
2188
+ Private (0600) JSON file required when --tool-outcome is applied
2189
+ --status-url <url> Print live daemon status JSON from a running daemon
2190
+ --wait-receive <kind> Wait with --status-url or a started bootstrap daemon until receive.lastAccepted or receive.lastHandled exists
2191
+ --wait-receive-text <text>
2192
+ With --wait-receive handled, wait until receive.lastHandled.intake.text contains text
2193
+ --wait-receive-message-id <id>
2194
+ With --wait-receive, wait until the accepted or handled receive observation has this Feishu message id
2195
+ --wait-receive-observed-after <iso>
2196
+ With --wait-receive, ignore receive observations at or before this ISO timestamp
2197
+ --wait-timeout-ms <n> Timeout for --wait-receive (default 30000)
2198
+ --wait-poll-ms <n> Poll interval for --wait-receive (default 500)
2199
+ --help Show this help
2200
+
2201
+ Environment:
2202
+ RIVUS_HOME selects Rivus Home (default ~/.rivus-agent) for Home commands.
2203
+ RIVUS_BOOTSTRAP_MODULE may be used instead of --bootstrap.
2204
+ FEISHU_APP_ID and FEISHU_APP_SECRET are required by the default config loader.
2205
+ FEISHU_CARD_STREAM_LEASE_MS shortens or extends the proactive CardKit rollover threshold.
2206
+ PI_API_KEY_FILE may point to a local BYOK key file instead of PI_API_KEY.
2207
+ `;
2208
+ function parseRivusDaemonArguments(argv) {
2209
+ let bootstrap;
2210
+ let checkConfig = false;
2211
+ let envFilePath;
2212
+ let feishuReplayChatId;
2213
+ let feishuReplayMessageId;
2214
+ let feishuReplayTenantKey;
2215
+ let feishuReplayThreadId;
2216
+ let manifestPath;
2217
+ let piApiKeyFile;
2218
+ let prompt;
2219
+ let printOpenClawEnvPath;
2220
+ let replayFeishuEventPath;
2221
+ let replayFeishuText;
2222
+ const recoveryCli = createRivusRecoveryCliParser();
2223
+ let sessionKey;
2224
+ let status = false;
2225
+ let statusUrl;
2226
+ let waitPollMs;
2227
+ let waitReceive;
2228
+ let waitReceiveMessageId;
2229
+ let waitReceiveObservedAfter;
2230
+ let waitReceiveText;
2231
+ let waitTimeoutMs;
2232
+ for (let index = 0; index < argv.length; index += 1) {
2233
+ const arg = argv[index];
2234
+ if (arg === "--help" || arg === "-h") return {
2235
+ help: true,
2236
+ status,
2237
+ ...statusUrl ? { statusUrl } : {}
2238
+ };
2239
+ if (arg === "--status") {
2240
+ status = true;
2241
+ continue;
2242
+ }
2243
+ const recoveryArgument = recoveryCli.consume(arg, argv[index + 1]);
2244
+ if (recoveryArgument.handled) {
2245
+ if (recoveryArgument.error) return {
2246
+ error: recoveryArgument.error,
2247
+ help: false,
2248
+ status
2249
+ };
2250
+ index += recoveryArgument.consumed;
2251
+ continue;
2252
+ }
2253
+ if (arg === "--check-config") {
2254
+ checkConfig = true;
2255
+ continue;
2256
+ }
2257
+ if (arg === "--env-file") {
2258
+ const value = argv[index + 1];
2259
+ if (!value) return {
2260
+ error: "--env-file requires a path",
2261
+ help: false,
2262
+ status
2263
+ };
2264
+ envFilePath = value;
2265
+ index += 1;
2266
+ continue;
2267
+ }
2268
+ if (arg?.startsWith("--env-file=")) {
2269
+ envFilePath = arg.slice(11);
2270
+ if (!envFilePath) return {
2271
+ error: "--env-file requires a path",
2272
+ help: false,
2273
+ status
2274
+ };
2275
+ continue;
2276
+ }
2277
+ if (arg === "--prompt") {
2278
+ const value = argv[index + 1];
2279
+ if (!value) return {
2280
+ error: "--prompt requires text",
2281
+ help: false,
2282
+ status
2283
+ };
2284
+ prompt = value;
2285
+ index += 1;
2286
+ continue;
2287
+ }
2288
+ if (arg?.startsWith("--prompt=")) {
2289
+ prompt = arg.slice(9);
2290
+ if (!prompt) return {
2291
+ error: "--prompt requires text",
2292
+ help: false,
2293
+ status
2294
+ };
2295
+ continue;
2296
+ }
2297
+ if (arg === "--session-key") {
2298
+ const value = argv[index + 1];
2299
+ if (!value) return {
2300
+ error: "--session-key requires a value",
2301
+ help: false,
2302
+ status
2303
+ };
2304
+ sessionKey = value;
2305
+ index += 1;
2306
+ continue;
2307
+ }
2308
+ if (arg === "--print-openclaw-env") {
2309
+ const value = argv[index + 1];
2310
+ if (!value) return {
2311
+ error: "--print-openclaw-env requires a JSON file path",
2312
+ help: false,
2313
+ status
2314
+ };
2315
+ printOpenClawEnvPath = value;
2316
+ index += 1;
2317
+ continue;
2318
+ }
2319
+ if (arg?.startsWith("--print-openclaw-env=")) {
2320
+ printOpenClawEnvPath = arg.slice(21);
2321
+ if (!printOpenClawEnvPath) return {
2322
+ error: "--print-openclaw-env requires a JSON file path",
2323
+ help: false,
2324
+ status
2325
+ };
2326
+ continue;
2327
+ }
2328
+ if (arg === "--pi-api-key-file") {
2329
+ const value = argv[index + 1];
2330
+ if (!value) return {
2331
+ error: "--pi-api-key-file requires a path",
2332
+ help: false,
2333
+ status
2334
+ };
2335
+ piApiKeyFile = value;
2336
+ index += 1;
2337
+ continue;
2338
+ }
2339
+ if (arg?.startsWith("--pi-api-key-file=")) {
2340
+ piApiKeyFile = arg.slice(18);
2341
+ if (!piApiKeyFile) return {
2342
+ error: "--pi-api-key-file requires a path",
2343
+ help: false,
2344
+ status
2345
+ };
2346
+ continue;
2347
+ }
2348
+ if (arg === "--replay-feishu-event") {
2349
+ const value = argv[index + 1];
2350
+ if (!value) return {
2351
+ error: "--replay-feishu-event requires a JSON file path",
2352
+ help: false,
2353
+ status
2354
+ };
2355
+ replayFeishuEventPath = value;
2356
+ index += 1;
2357
+ continue;
2358
+ }
2359
+ if (arg?.startsWith("--replay-feishu-event=")) {
2360
+ replayFeishuEventPath = arg.slice(22);
2361
+ if (!replayFeishuEventPath) return {
2362
+ error: "--replay-feishu-event requires a JSON file path",
2363
+ help: false,
2364
+ status
2365
+ };
2366
+ continue;
2367
+ }
2368
+ if (arg === "--replay-feishu-text") {
2369
+ const value = argv[index + 1];
2370
+ if (!value) return {
2371
+ error: "--replay-feishu-text requires text",
2372
+ help: false,
2373
+ status
2374
+ };
2375
+ replayFeishuText = value;
2376
+ index += 1;
2377
+ continue;
2378
+ }
2379
+ if (arg?.startsWith("--replay-feishu-text=")) {
2380
+ replayFeishuText = arg.slice(21);
2381
+ if (!replayFeishuText) return {
2382
+ error: "--replay-feishu-text requires text",
2383
+ help: false,
2384
+ status
2385
+ };
2386
+ continue;
2387
+ }
2388
+ if (arg === "--feishu-message-id") {
2389
+ const value = argv[index + 1];
2390
+ if (!value) return {
2391
+ error: "--feishu-message-id requires a value",
2392
+ help: false,
2393
+ status
2394
+ };
2395
+ feishuReplayMessageId = value;
2396
+ index += 1;
2397
+ continue;
2398
+ }
2399
+ if (arg?.startsWith("--feishu-message-id=")) {
2400
+ feishuReplayMessageId = arg.slice(20);
2401
+ if (!feishuReplayMessageId) return {
2402
+ error: "--feishu-message-id requires a value",
2403
+ help: false,
2404
+ status
2405
+ };
2406
+ continue;
2407
+ }
2408
+ if (arg === "--feishu-chat-id") {
2409
+ const value = argv[index + 1];
2410
+ if (!value) return {
2411
+ error: "--feishu-chat-id requires a value",
2412
+ help: false,
2413
+ status
2414
+ };
2415
+ feishuReplayChatId = value;
2416
+ index += 1;
2417
+ continue;
2418
+ }
2419
+ if (arg?.startsWith("--feishu-chat-id=")) {
2420
+ feishuReplayChatId = arg.slice(17);
2421
+ if (!feishuReplayChatId) return {
2422
+ error: "--feishu-chat-id requires a value",
2423
+ help: false,
2424
+ status
2425
+ };
2426
+ continue;
2427
+ }
2428
+ if (arg === "--feishu-thread-id") {
2429
+ const value = argv[index + 1];
2430
+ if (!value) return {
2431
+ error: "--feishu-thread-id requires a value",
2432
+ help: false,
2433
+ status
2434
+ };
2435
+ feishuReplayThreadId = value;
2436
+ index += 1;
2437
+ continue;
2438
+ }
2439
+ if (arg?.startsWith("--feishu-thread-id=")) {
2440
+ feishuReplayThreadId = arg.slice(19);
2441
+ if (!feishuReplayThreadId) return {
2442
+ error: "--feishu-thread-id requires a value",
2443
+ help: false,
2444
+ status
2445
+ };
2446
+ continue;
2447
+ }
2448
+ if (arg === "--feishu-tenant-key") {
2449
+ const value = argv[index + 1];
2450
+ if (!value) return {
2451
+ error: "--feishu-tenant-key requires a value",
2452
+ help: false,
2453
+ status
2454
+ };
2455
+ feishuReplayTenantKey = value;
2456
+ index += 1;
2457
+ continue;
2458
+ }
2459
+ if (arg?.startsWith("--feishu-tenant-key=")) {
2460
+ feishuReplayTenantKey = arg.slice(20);
2461
+ if (!feishuReplayTenantKey) return {
2462
+ error: "--feishu-tenant-key requires a value",
2463
+ help: false,
2464
+ status
2465
+ };
2466
+ continue;
2467
+ }
2468
+ if (arg?.startsWith("--session-key=")) {
2469
+ sessionKey = arg.slice(14);
2470
+ if (!sessionKey) return {
2471
+ error: "--session-key requires a value",
2472
+ help: false,
2473
+ status
2474
+ };
2475
+ continue;
2476
+ }
2477
+ if (arg === "--status-url") {
2478
+ const value = argv[index + 1];
2479
+ if (!value) return {
2480
+ error: "--status-url requires a URL",
2481
+ help: false,
2482
+ status
2483
+ };
2484
+ statusUrl = value;
2485
+ index += 1;
2486
+ continue;
2487
+ }
2488
+ if (arg?.startsWith("--status-url=")) {
2489
+ statusUrl = arg.slice(13);
2490
+ if (!statusUrl) return {
2491
+ error: "--status-url requires a URL",
2492
+ help: false,
2493
+ status
2494
+ };
2495
+ continue;
2496
+ }
2497
+ if (arg === "--wait-receive") {
2498
+ const parsedWait = parseWaitReceive(argv[index + 1]);
2499
+ if (!parsedWait) return {
2500
+ error: "--wait-receive requires accepted or handled",
2501
+ help: false,
2502
+ status
2503
+ };
2504
+ waitReceive = parsedWait;
2505
+ index += 1;
2506
+ continue;
2507
+ }
2508
+ if (arg?.startsWith("--wait-receive=")) {
2509
+ const parsedWait = parseWaitReceive(arg.slice(15));
2510
+ if (!parsedWait) return {
2511
+ error: "--wait-receive requires accepted or handled",
2512
+ help: false,
2513
+ status
2514
+ };
2515
+ waitReceive = parsedWait;
2516
+ continue;
2517
+ }
2518
+ if (arg === "--wait-receive-text") {
2519
+ const value = argv[index + 1];
2520
+ if (!value) return {
2521
+ error: "--wait-receive-text requires text",
2522
+ help: false,
2523
+ status
2524
+ };
2525
+ waitReceiveText = value;
2526
+ index += 1;
2527
+ continue;
2528
+ }
2529
+ if (arg?.startsWith("--wait-receive-text=")) {
2530
+ waitReceiveText = arg.slice(20);
2531
+ if (!waitReceiveText) return {
2532
+ error: "--wait-receive-text requires text",
2533
+ help: false,
2534
+ status
2535
+ };
2536
+ continue;
2537
+ }
2538
+ if (arg === "--wait-receive-message-id") {
2539
+ const value = argv[index + 1];
2540
+ if (!value) return {
2541
+ error: "--wait-receive-message-id requires a message id",
2542
+ help: false,
2543
+ status
2544
+ };
2545
+ waitReceiveMessageId = value;
2546
+ index += 1;
2547
+ continue;
2548
+ }
2549
+ if (arg?.startsWith("--wait-receive-message-id=")) {
2550
+ waitReceiveMessageId = arg.slice(26);
2551
+ if (!waitReceiveMessageId) return {
2552
+ error: "--wait-receive-message-id requires a message id",
2553
+ help: false,
2554
+ status
2555
+ };
2556
+ continue;
2557
+ }
2558
+ if (arg === "--wait-receive-observed-after") {
2559
+ const value = parseIsoTimestampArgument(argv[index + 1]);
2560
+ if (!value) return {
2561
+ error: "--wait-receive-observed-after requires an ISO timestamp",
2562
+ help: false,
2563
+ status
2564
+ };
2565
+ waitReceiveObservedAfter = value;
2566
+ index += 1;
2567
+ continue;
2568
+ }
2569
+ if (arg?.startsWith("--wait-receive-observed-after=")) {
2570
+ const value = parseIsoTimestampArgument(arg.slice(30));
2571
+ if (!value) return {
2572
+ error: "--wait-receive-observed-after requires an ISO timestamp",
2573
+ help: false,
2574
+ status
2575
+ };
2576
+ waitReceiveObservedAfter = value;
2577
+ continue;
2578
+ }
2579
+ if (arg === "--wait-timeout-ms") {
2580
+ const parsedMs = parsePositiveIntegerArgument(argv[index + 1]);
2581
+ if (parsedMs === void 0) return {
2582
+ error: "--wait-timeout-ms requires a positive integer",
2583
+ help: false,
2584
+ status
2585
+ };
2586
+ waitTimeoutMs = parsedMs;
2587
+ index += 1;
2588
+ continue;
2589
+ }
2590
+ if (arg?.startsWith("--wait-timeout-ms=")) {
2591
+ const parsedMs = parsePositiveIntegerArgument(arg.slice(18));
2592
+ if (parsedMs === void 0) return {
2593
+ error: "--wait-timeout-ms requires a positive integer",
2594
+ help: false,
2595
+ status
2596
+ };
2597
+ waitTimeoutMs = parsedMs;
2598
+ continue;
2599
+ }
2600
+ if (arg === "--wait-poll-ms") {
2601
+ const parsedMs = parsePositiveIntegerArgument(argv[index + 1]);
2602
+ if (parsedMs === void 0) return {
2603
+ error: "--wait-poll-ms requires a positive integer",
2604
+ help: false,
2605
+ status
2606
+ };
2607
+ waitPollMs = parsedMs;
2608
+ index += 1;
2609
+ continue;
2610
+ }
2611
+ if (arg?.startsWith("--wait-poll-ms=")) {
2612
+ const parsedMs = parsePositiveIntegerArgument(arg.slice(15));
2613
+ if (parsedMs === void 0) return {
2614
+ error: "--wait-poll-ms requires a positive integer",
2615
+ help: false,
2616
+ status
2617
+ };
2618
+ waitPollMs = parsedMs;
2619
+ continue;
2620
+ }
2621
+ if (arg === "--bootstrap") {
2622
+ const value = argv[index + 1];
2623
+ if (!value) return {
2624
+ error: "--bootstrap requires a module specifier",
2625
+ help: false,
2626
+ status
2627
+ };
2628
+ bootstrap = value;
2629
+ index += 1;
2630
+ continue;
2631
+ }
2632
+ if (arg === "--manifest") {
2633
+ const value = argv[index + 1];
2634
+ if (!value) return {
2635
+ error: "--manifest requires a path",
2636
+ help: false,
2637
+ status
2638
+ };
2639
+ manifestPath = value;
2640
+ index += 1;
2641
+ continue;
2642
+ }
2643
+ if (arg?.startsWith("--manifest=")) {
2644
+ manifestPath = arg.slice(11);
2645
+ if (!manifestPath) return {
2646
+ error: "--manifest requires a path",
2647
+ help: false,
2648
+ status
2649
+ };
2650
+ continue;
2651
+ }
2652
+ if (arg?.startsWith("--bootstrap=")) {
2653
+ bootstrap = arg.slice(12);
2654
+ if (!bootstrap) return {
2655
+ error: "--bootstrap requires a module specifier",
2656
+ help: false,
2657
+ status
2658
+ };
2659
+ continue;
2660
+ }
2661
+ return {
2662
+ error: `Unknown argument: ${arg}`,
2663
+ help: false,
2664
+ status
2665
+ };
2666
+ }
2667
+ if (prompt !== void 0 && status) return {
2668
+ error: "--prompt cannot be combined with --status",
2669
+ help: false,
2670
+ status
2671
+ };
2672
+ if (checkConfig && status) return {
2673
+ error: "--check-config cannot be combined with --status",
2674
+ help: false,
2675
+ status,
2676
+ checkConfig
2677
+ };
2678
+ if (checkConfig && prompt !== void 0) return {
2679
+ error: "--check-config cannot be combined with --prompt",
2680
+ help: false,
2681
+ status,
2682
+ checkConfig
2683
+ };
2684
+ if (checkConfig && replayFeishuEventPath !== void 0) return {
2685
+ error: "--check-config cannot be combined with --replay-feishu-event",
2686
+ help: false,
2687
+ status,
2688
+ checkConfig
2689
+ };
2690
+ if (checkConfig && replayFeishuText !== void 0) return {
2691
+ error: "--check-config cannot be combined with --replay-feishu-text",
2692
+ help: false,
2693
+ status,
2694
+ checkConfig
2695
+ };
2696
+ if (checkConfig && printOpenClawEnvPath !== void 0) return {
2697
+ error: "--check-config cannot be combined with --print-openclaw-env",
2698
+ help: false,
2699
+ status,
2700
+ checkConfig
2701
+ };
2702
+ if (checkConfig && statusUrl) return {
2703
+ error: "--check-config cannot be combined with --status-url",
2704
+ help: false,
2705
+ status,
2706
+ checkConfig
2707
+ };
2708
+ if (prompt !== void 0 && statusUrl) return {
2709
+ error: "--prompt cannot be combined with --status-url",
2710
+ help: false,
2711
+ status
2712
+ };
2713
+ if (printOpenClawEnvPath !== void 0 && prompt !== void 0) return {
2714
+ error: "--print-openclaw-env cannot be combined with --prompt",
2715
+ help: false,
2716
+ status
2717
+ };
2718
+ if (printOpenClawEnvPath !== void 0 && replayFeishuEventPath !== void 0) return {
2719
+ error: "--print-openclaw-env cannot be combined with --replay-feishu-event",
2720
+ help: false,
2721
+ status
2722
+ };
2723
+ if (printOpenClawEnvPath !== void 0 && replayFeishuText !== void 0) return {
2724
+ error: "--print-openclaw-env cannot be combined with --replay-feishu-text",
2725
+ help: false,
2726
+ status
2727
+ };
2728
+ if (printOpenClawEnvPath !== void 0 && status) return {
2729
+ error: "--print-openclaw-env cannot be combined with --status",
2730
+ help: false,
2731
+ status
2732
+ };
2733
+ if (printOpenClawEnvPath !== void 0 && statusUrl) return {
2734
+ error: "--print-openclaw-env cannot be combined with --status-url",
2735
+ help: false,
2736
+ status
2737
+ };
2738
+ if (piApiKeyFile !== void 0 && printOpenClawEnvPath === void 0) return {
2739
+ error: "--pi-api-key-file requires --print-openclaw-env",
2740
+ help: false,
2741
+ status
2742
+ };
2743
+ if (replayFeishuEventPath !== void 0 && prompt !== void 0) return {
2744
+ error: "--replay-feishu-event cannot be combined with --prompt",
2745
+ help: false,
2746
+ status
2747
+ };
2748
+ if (replayFeishuEventPath !== void 0 && replayFeishuText !== void 0) return {
2749
+ error: "--replay-feishu-event cannot be combined with --replay-feishu-text",
2750
+ help: false,
2751
+ status
2752
+ };
2753
+ if (replayFeishuEventPath !== void 0 && status) return {
2754
+ error: "--replay-feishu-event cannot be combined with --status",
2755
+ help: false,
2756
+ status
2757
+ };
2758
+ if (replayFeishuEventPath !== void 0 && statusUrl) return {
2759
+ error: "--replay-feishu-event cannot be combined with --status-url",
2760
+ help: false,
2761
+ status
2762
+ };
2763
+ if (replayFeishuText !== void 0 && prompt !== void 0) return {
2764
+ error: "--replay-feishu-text cannot be combined with --prompt",
2765
+ help: false,
2766
+ status
2767
+ };
2768
+ if (replayFeishuText !== void 0 && status) return {
2769
+ error: "--replay-feishu-text cannot be combined with --status",
2770
+ help: false,
2771
+ status
2772
+ };
2773
+ if (replayFeishuText !== void 0 && statusUrl) return {
2774
+ error: "--replay-feishu-text cannot be combined with --status-url",
2775
+ help: false,
2776
+ status
2777
+ };
2778
+ if (feishuReplayMessageId !== void 0 && replayFeishuText === void 0) return {
2779
+ error: "--feishu-message-id requires --replay-feishu-text",
2780
+ help: false,
2781
+ status
2782
+ };
2783
+ if (feishuReplayChatId !== void 0 && replayFeishuText === void 0) return {
2784
+ error: "--feishu-chat-id requires --replay-feishu-text",
2785
+ help: false,
2786
+ status
2787
+ };
2788
+ if (feishuReplayThreadId !== void 0 && replayFeishuText === void 0) return {
2789
+ error: "--feishu-thread-id requires --replay-feishu-text",
2790
+ help: false,
2791
+ status
2792
+ };
2793
+ if (feishuReplayTenantKey !== void 0 && replayFeishuText === void 0) return {
2794
+ error: "--feishu-tenant-key requires --replay-feishu-text",
2795
+ help: false,
2796
+ status
2797
+ };
2798
+ if (sessionKey !== void 0 && prompt === void 0) return {
2799
+ error: "--session-key requires --prompt",
2800
+ help: false,
2801
+ status
2802
+ };
2803
+ if (waitReceive !== void 0 && status) return {
2804
+ error: "--wait-receive cannot be combined with --status",
2805
+ help: false,
2806
+ status
2807
+ };
2808
+ if (waitReceive !== void 0 && checkConfig) return {
2809
+ error: "--wait-receive cannot be combined with --check-config",
2810
+ help: false,
2811
+ status,
2812
+ checkConfig
2813
+ };
2814
+ if (waitReceive !== void 0 && prompt !== void 0) return {
2815
+ error: "--wait-receive cannot be combined with --prompt",
2816
+ help: false,
2817
+ status
2818
+ };
2819
+ if (waitReceive !== void 0 && replayFeishuEventPath !== void 0) return {
2820
+ error: "--wait-receive cannot be combined with --replay-feishu-event",
2821
+ help: false,
2822
+ status
2823
+ };
2824
+ if (waitReceive !== void 0 && replayFeishuText !== void 0) return {
2825
+ error: "--wait-receive cannot be combined with --replay-feishu-text",
2826
+ help: false,
2827
+ status
2828
+ };
2829
+ if (waitReceive !== void 0 && printOpenClawEnvPath !== void 0) return {
2830
+ error: "--wait-receive cannot be combined with --print-openclaw-env",
2831
+ help: false,
2832
+ status
2833
+ };
2834
+ if (waitTimeoutMs !== void 0 && waitReceive === void 0) return {
2835
+ error: "--wait-timeout-ms requires --wait-receive",
2836
+ help: false,
2837
+ status
2838
+ };
2839
+ if (waitPollMs !== void 0 && waitReceive === void 0) return {
2840
+ error: "--wait-poll-ms requires --wait-receive",
2841
+ help: false,
2842
+ status
2843
+ };
2844
+ if (waitReceiveText !== void 0 && waitReceive !== "handled") return {
2845
+ error: "--wait-receive-text requires --wait-receive handled",
2846
+ help: false,
2847
+ status
2848
+ };
2849
+ if (waitReceiveMessageId !== void 0 && waitReceive === void 0) return {
2850
+ error: "--wait-receive-message-id requires --wait-receive",
2851
+ help: false,
2852
+ status
2853
+ };
2854
+ if (waitReceiveObservedAfter !== void 0 && waitReceive === void 0) return {
2855
+ error: "--wait-receive-observed-after requires --wait-receive",
2856
+ help: false,
2857
+ status
2858
+ };
2859
+ const recovery = recoveryCli.build();
2860
+ if (recovery.error) return {
2861
+ error: recovery.error,
2862
+ help: false,
2863
+ status
2864
+ };
2865
+ if (recovery.command) {
2866
+ if (!manifestPath) return {
2867
+ error: "Recovery commands require --manifest",
2868
+ help: false,
2869
+ status
2870
+ };
2871
+ if (checkConfig || prompt !== void 0 || printOpenClawEnvPath !== void 0 || replayFeishuEventPath !== void 0 || replayFeishuText !== void 0 || status || statusUrl !== void 0 || waitReceive !== void 0) return {
2872
+ error: "Recovery commands cannot be combined with another one-shot command",
2873
+ help: false,
2874
+ status
2875
+ };
2876
+ }
2877
+ return {
2878
+ ...bootstrap ? { bootstrap } : {},
2879
+ checkConfig,
2880
+ ...envFilePath ? { envFilePath } : {},
2881
+ ...feishuReplayChatId !== void 0 ? { feishuReplayChatId } : {},
2882
+ ...feishuReplayMessageId !== void 0 ? { feishuReplayMessageId } : {},
2883
+ ...feishuReplayTenantKey !== void 0 ? { feishuReplayTenantKey } : {},
2884
+ ...feishuReplayThreadId !== void 0 ? { feishuReplayThreadId } : {},
2885
+ help: false,
2886
+ ...manifestPath ? { manifestPath } : {},
2887
+ ...piApiKeyFile !== void 0 ? { piApiKeyFile } : {},
2888
+ ...prompt !== void 0 ? { prompt } : {},
2889
+ ...printOpenClawEnvPath !== void 0 ? { printOpenClawEnvPath } : {},
2890
+ ...replayFeishuEventPath !== void 0 ? { replayFeishuEventPath } : {},
2891
+ ...replayFeishuText !== void 0 ? { replayFeishuText } : {},
2892
+ ...recovery.command ? { recoveryCommand: recovery.command } : {},
2893
+ ...sessionKey ? { sessionKey } : {},
2894
+ status,
2895
+ ...statusUrl ? { statusUrl } : {},
2896
+ ...waitPollMs !== void 0 ? { waitPollMs } : {},
2897
+ ...waitReceive !== void 0 ? { waitReceive } : {},
2898
+ ...waitReceiveMessageId !== void 0 ? { waitReceiveMessageId } : {},
2899
+ ...waitReceiveObservedAfter !== void 0 ? { waitReceiveObservedAfter } : {},
2900
+ ...waitReceiveText !== void 0 ? { waitReceiveText } : {},
2901
+ ...waitTimeoutMs !== void 0 ? { waitTimeoutMs } : {}
2902
+ };
2903
+ }
2904
+ function parseWaitReceive(value) {
2905
+ return value === "accepted" || value === "handled" ? value : void 0;
2906
+ }
2907
+ function parsePositiveIntegerArgument(value) {
2908
+ return value && /^[1-9]\d*$/.test(value) ? Number(value) : void 0;
2909
+ }
2910
+ function parseIsoTimestampArgument(value) {
2911
+ if (!value) return;
2912
+ const time = Date.parse(value);
2913
+ return Number.isNaN(time) ? void 0 : new Date(time).toISOString();
2914
+ }
2915
+ //#endregion
2916
+ //#region src/adapters/cli/command/rivus-daemon-output.ts
2917
+ const RIVUS_DAEMON_STARTED_MESSAGE = "Rivus Agent daemon started\n";
2918
+ function formatRivusDaemonUsageError(error) {
2919
+ return `${error}\n\n${RIVUS_DAEMON_USAGE}`;
2920
+ }
2921
+ function formatRivusDaemonJson(value) {
2922
+ return `${JSON.stringify(value, null, 2)}\n`;
2923
+ }
2924
+ function formatRivusDaemonLine(text) {
2925
+ return `${text}\n`;
2926
+ }
2927
+ function formatRivusDaemonWarning(warning) {
2928
+ return `Warning: ${warning}\n`;
2929
+ }
2930
+ function formatRivusDaemonCapabilityError(capability) {
2931
+ return `${{
2932
+ recovery: "Bootstrap daemon does not expose openRecoveryControl()",
2933
+ status: "Bootstrap daemon does not expose status()",
2934
+ prompt: "Bootstrap daemon does not expose promptText(command)",
2935
+ replay: "Bootstrap daemon does not expose replayReceiveMessage(payload)"
2936
+ }[capability]}\n`;
2937
+ }
2938
+ function formatRivusDaemonShutdownFailure(signal, error) {
2939
+ return `Failed to stop daemon after ${signal}: ${error}\n`;
2940
+ }
2941
+ //#endregion
2942
+ //#region src/adapters/cli/replay/rivus-daemon-replay.ts
2943
+ async function readFeishuReceiveMessagePayload(filePath) {
2944
+ return JSON.parse(await readFile(filePath, "utf8"));
2945
+ }
2946
+ function createSyntheticFeishuTextReplayPayload(text, options) {
2947
+ return { event: {
2948
+ message: {
2949
+ chat_id: options.chatId ?? "oc_cli",
2950
+ content: JSON.stringify({ text }),
2951
+ message_id: options.messageId ?? `om_cli_${Date.now()}`,
2952
+ message_type: "text",
2953
+ thread_id: options.threadId ?? "omt_cli"
2954
+ },
2955
+ sender: { tenant_key: options.tenantKey ?? "tenant_cli" }
2956
+ } };
2957
+ }
2958
+ function formatRivusDaemonError(error) {
2959
+ if (error instanceof ReceiveWaitTimeoutError) return `${error.message}\nLast status:\n${JSON.stringify(error.lastStatus, null, 2)}`;
2960
+ return error instanceof Error ? error.message : String(error);
2961
+ }
2962
+ var ReceiveWaitTimeoutError = class extends Error {
2963
+ target;
2964
+ lastStatus;
2965
+ messageId;
2966
+ observedAfter;
2967
+ text;
2968
+ constructor(target, lastStatus, messageId, observedAfter, text) {
2969
+ super(`Timed out waiting for ${target === "accepted" ? "receive.lastAccepted" : "receive.lastHandled"}${messageId ? ` with message id ${JSON.stringify(messageId)}` : ""}${observedAfter ? ` observed after ${JSON.stringify(observedAfter)}` : ""}${text ? ` containing text ${JSON.stringify(text)}` : ""}`);
2970
+ this.target = target;
2971
+ this.lastStatus = lastStatus;
2972
+ this.messageId = messageId;
2973
+ this.observedAfter = observedAfter;
2974
+ this.text = text;
2975
+ this.name = "ReceiveWaitTimeoutError";
2976
+ }
2977
+ };
2978
+ async function fetchLiveStatus(url) {
2979
+ const response = await fetch(url, { headers: { accept: "application/json" } });
2980
+ if (!response.ok) throw new Error(`Status request failed with HTTP ${response.status}`);
2981
+ return response.json();
2982
+ }
2983
+ function waitForReceiveStatus(readStatus, target, options) {
2984
+ return Effect.suspend(() => {
2985
+ const startedAt = Date.now();
2986
+ let lastStatus;
2987
+ const poll = () => readStatus().pipe(Effect.flatMap((status) => {
2988
+ lastStatus = status;
2989
+ if (hasReceiveObservation(status, target, {
2990
+ ...options.messageId ? { messageId: options.messageId } : {},
2991
+ ...options.observedAfter ? { observedAfter: options.observedAfter } : {},
2992
+ ...options.text ? { text: options.text } : {}
2993
+ })) return Effect.succeed(status);
2994
+ if (Date.now() - startedAt >= options.timeoutMs) return Effect.fail(new ReceiveWaitTimeoutError(target, lastStatus, options.messageId, options.observedAfter, options.text));
2995
+ return Effect.sleep(options.pollMs).pipe(Effect.flatMap(poll));
2996
+ }));
2997
+ return poll();
2998
+ });
2999
+ }
3000
+ function hasReceiveObservation(status, target, criteria) {
3001
+ const receive = isStatusRecord(status) ? status.receive : void 0;
3002
+ if (!isStatusRecord(receive)) return false;
3003
+ if (target === "accepted") {
3004
+ const lastAccepted = receive.lastAccepted;
3005
+ if (!isStatusRecord(lastAccepted)) return false;
3006
+ if (criteria.messageId === void 0) return observedAfterMatches(lastAccepted, criteria.observedAfter);
3007
+ const message = lastAccepted.message;
3008
+ return isStatusRecord(message) && message.messageId === criteria.messageId && observedAfterMatches(lastAccepted, criteria.observedAfter);
3009
+ }
3010
+ const lastHandled = receive.lastHandled;
3011
+ if (!isStatusRecord(lastHandled)) return false;
3012
+ if (criteria.messageId !== void 0 && lastHandled.messageId !== criteria.messageId) return false;
3013
+ if (!observedAfterMatches(lastHandled, criteria.observedAfter)) return false;
3014
+ if (criteria.text === void 0) return true;
3015
+ const intake = lastHandled.intake;
3016
+ return isStatusRecord(intake) && typeof intake.text === "string" && intake.text.includes(criteria.text);
3017
+ }
3018
+ function isStatusRecord(value) {
3019
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3020
+ }
3021
+ function observedAfterMatches(observation, observedAfter) {
3022
+ if (observedAfter === void 0) return true;
3023
+ const observedAtMs = readObservedAtMs(observation.observedAt);
3024
+ return observedAtMs !== void 0 && observedAtMs > Date.parse(observedAfter);
3025
+ }
3026
+ function readObservedAtMs(value) {
3027
+ if (value instanceof Date) {
3028
+ const time = value.getTime();
3029
+ return Number.isNaN(time) ? void 0 : time;
3030
+ }
3031
+ if (typeof value === "string") {
3032
+ const time = Date.parse(value);
3033
+ return Number.isNaN(time) ? void 0 : time;
3034
+ }
3035
+ }
3036
+ //#endregion
3037
+ //#region src/platform/daemon/process/rivus-daemon-shutdown-controller.ts
3038
+ const DEFAULT_SIGNALS = ["SIGINT", "SIGTERM"];
3039
+ function createRivusDaemonShutdownController(options) {
3040
+ let shutdown;
3041
+ const handle = (signal) => {
3042
+ shutdown ??= Effect.runPromise(options.daemon.stop()).then(() => options.onStopped?.(signal)).catch(async (error) => {
3043
+ await options.onError?.(error, signal);
3044
+ throw error;
3045
+ });
3046
+ return shutdown;
3047
+ };
3048
+ return {
3049
+ handle,
3050
+ install: () => {
3051
+ for (const signal of options.signals ?? DEFAULT_SIGNALS) options.signalSource.on(signal, () => {
3052
+ handle(signal);
3053
+ });
3054
+ },
3055
+ stopping: () => shutdown !== void 0
3056
+ };
3057
+ }
3058
+ //#endregion
3059
+ //#region src/adapters/deployment/process/process-deployment-adapters.ts
3060
+ function createProcessDeploymentAdapterPorts(factories, runEffect) {
3061
+ return {
3062
+ ...factories.createAutomation ? { automationFactory: { create: (input) => adaptAutomationFactory(factories.createAutomation, input, runEffect) } } : {},
3063
+ ...factories.createBackgroundSession ? { backgroundSessionFactory: { create: (input) => adaptBackgroundSessionFactory(factories.createBackgroundSession, input, runEffect) } } : {},
3064
+ endpointFactory: { create: (input) => adaptEndpointFactory(factories.createEndpoint, input, runEffect) },
3065
+ runtimeFactory: { create: (input) => Effect.tryPromise({
3066
+ try: () => Promise.resolve(factories.createRuntime(input)),
3067
+ catch: toError$1
3068
+ }).pipe(Effect.map((runtime) => toEffectAgentRuntime(runtime, runEffect))) }
3069
+ };
3070
+ }
3071
+ function adaptEndpointFactory(create, input, runEffect) {
3072
+ return Effect.tryPromise({
3073
+ try: async () => {
3074
+ return toLifecycleAdapter(await create({
3075
+ agentId: input.agentId,
3076
+ cancel: (request) => runEffect(input.cancel(request)),
3077
+ definition: input.definition,
3078
+ endpointId: input.endpointId,
3079
+ handle: (request) => runEffect(input.handle(toEffectAgentRuntimeInput(request))),
3080
+ instanceId: input.instanceId,
3081
+ ...input.projectSpaceId ? { projectSpaceId: input.projectSpaceId } : {},
3082
+ steer: (request) => runEffect(input.steer(request))
3083
+ }));
3084
+ },
3085
+ catch: toError$1
3086
+ });
3087
+ }
3088
+ function adaptAutomationFactory(create, input, runEffect) {
3089
+ return Effect.tryPromise({
3090
+ try: async () => toLifecycleAdapter(await create({
3091
+ automationId: input.automationId,
3092
+ definition: input.definition,
3093
+ deliveryEndpoint: input.deliveryEndpoint,
3094
+ instanceId: input.instanceId,
3095
+ run: (request) => runEffect(input.run(request))
3096
+ })),
3097
+ catch: toError$1
3098
+ });
3099
+ }
3100
+ function adaptBackgroundSessionFactory(create, input, runEffect) {
3101
+ return Effect.tryPromise({
3102
+ try: async () => {
3103
+ const adapter = await create({
3104
+ agentIds: input.agentIds,
3105
+ cancel: (request) => runEffect(input.cancel(request)),
3106
+ config: input.config,
3107
+ run: (request) => runEffect(input.run({
3108
+ agentId: request.agentId,
3109
+ invocation: request.invocation,
3110
+ ...request.onUpdate ? { onUpdate: (update) => Effect.tryPromise({
3111
+ try: async () => request.onUpdate(update),
3112
+ catch: toError$1
3113
+ }) } : {},
3114
+ sessionKey: request.sessionKey,
3115
+ text: request.text
3116
+ }))
3117
+ });
3118
+ return {
3119
+ ...toLifecycleAdapter(adapter),
3120
+ ...adapter.status ? { status: () => adapter.status() } : {}
3121
+ };
3122
+ },
3123
+ catch: toError$1
3124
+ });
3125
+ }
3126
+ function toLifecycleAdapter(adapter) {
3127
+ return {
3128
+ running: () => adapter.running(),
3129
+ start: () => Effect.tryPromise({
3130
+ try: () => Promise.resolve(adapter.start()),
3131
+ catch: toError$1
3132
+ }),
3133
+ stop: () => Effect.tryPromise({
3134
+ try: () => Promise.resolve(adapter.stop()),
3135
+ catch: toError$1
3136
+ })
3137
+ };
3138
+ }
3139
+ function toError$1(error) {
3140
+ return error instanceof Error ? error : new Error(String(error));
3141
+ }
3142
+ //#endregion
3143
+ //#region src/bootstrap/deployment/deployment-control-ports.ts
3144
+ const agentCatalogRuntime = Object.freeze({
3145
+ digest: createSha256Digest,
3146
+ deepFreeze
3147
+ });
3148
+ function createProcessDeploymentControlPorts(factories, backgroundSessions, runEffect) {
3149
+ return {
3150
+ agentCatalog: createRivusAgentCatalog([createRivusHostToolDescriptorProvider({ backgroundSessions })], agentCatalogRuntime),
3151
+ agentHostFactory: { create: (input) => {
3152
+ const registry = createEffectAgentInstanceRegistry({
3153
+ createInstanceId: (identity) => createStableId("instance", identity),
3154
+ createRuntimeGenerationId: (identity) => createStableId("generation", identity)
3155
+ }, input.initialInstanceRecords ? { initialRecords: input.initialInstanceRecords } : {});
3156
+ const runtime = createAgentHostRuntimePool(input.runtimeFactory);
3157
+ return createEffectAgentHost({
3158
+ automations: input.automations,
3159
+ backgroundSessions: input.backgroundSessions,
3160
+ definitions: input.definitions,
3161
+ endpoints: input.endpoints,
3162
+ registry,
3163
+ runtime
3164
+ });
3165
+ } },
3166
+ ...createProcessDeploymentAdapterPorts(factories, runEffect)
3167
+ };
3168
+ }
3169
+ //#endregion
3170
+ //#region src/core/application/deployment/failure/deployment-failure.ts
3171
+ function formatDeploymentFailure(failure) {
3172
+ return failure instanceof Error ? failure.message : String(failure);
3173
+ }
3174
+ function toDeploymentFailure(failure) {
3175
+ return failure instanceof Error ? failure : new Error(String(failure));
3176
+ }
3177
+ //#endregion
3178
+ //#region src/core/application/deployment/resolution/deployment-resolution.ts
3179
+ var RivusPluginLoadError = class extends Error {
3180
+ pluginId;
3181
+ moduleSpecifier;
3182
+ name = "RivusPluginLoadError";
3183
+ constructor(pluginId, moduleSpecifier, message, options) {
3184
+ super(message, options);
3185
+ this.pluginId = pluginId;
3186
+ this.moduleSpecifier = moduleSpecifier;
3187
+ }
3188
+ };
3189
+ function resolveRivusDeployment(input) {
3190
+ return Effect.gen(function* () {
3191
+ yield* Effect.try({
3192
+ try: () => validateRivusDeploymentManifest(input.manifest),
3193
+ catch: toDeploymentFailure
3194
+ });
3195
+ const catalog = input.agentCatalog.createPluginCatalog();
3196
+ const pluginStatuses = [];
3197
+ const statusByPlugin = /* @__PURE__ */ new Map();
3198
+ for (const declaration of input.manifest.plugins) {
3199
+ const loaded = yield* input.pluginLoader.load({
3200
+ deploymentRoot: input.deploymentRoot,
3201
+ module: declaration.module,
3202
+ pluginId: declaration.id
3203
+ }).pipe(Effect.flatMap((plugin) => Effect.try({
3204
+ try: () => {
3205
+ if (plugin.manifest.id !== declaration.id) throw new Error(`plugin manifest id ${plugin.manifest.id} does not match declaration ${declaration.id}`);
3206
+ catalog.registerPlugin(plugin);
3207
+ return plugin;
3208
+ },
3209
+ catch: toDeploymentFailure
3210
+ })), Effect.either);
3211
+ if (Either.isLeft(loaded)) {
3212
+ const message = formatDeploymentFailure(loaded.left);
3213
+ if (declaration.required) return yield* Effect.fail(new RivusPluginLoadError(declaration.id, declaration.module, `required plugin ${declaration.id} failed to load: ${message}`, { cause: loaded.left }));
3214
+ const status = Object.freeze({
3215
+ error: message,
3216
+ id: declaration.id,
3217
+ module: declaration.module,
3218
+ required: false,
3219
+ status: "failed"
3220
+ });
3221
+ pluginStatuses.push(status);
3222
+ statusByPlugin.set(declaration.id, status);
3223
+ continue;
3224
+ }
3225
+ const status = Object.freeze({
3226
+ id: declaration.id,
3227
+ module: declaration.module,
3228
+ required: declaration.required,
3229
+ status: "loaded",
3230
+ version: loaded.right.manifest.version
3231
+ });
3232
+ pluginStatuses.push(status);
3233
+ statusByPlugin.set(declaration.id, status);
3234
+ }
3235
+ const agentStatuses = [];
3236
+ const definitions = [];
3237
+ for (const agent of input.manifest.agents) {
3238
+ const pluginStatus = statusByPlugin.get(agent.pluginId);
3239
+ if (pluginStatus.status === "failed") {
3240
+ agentStatuses.push(Object.freeze({
3241
+ agentId: agent.agentId,
3242
+ pluginId: agent.pluginId,
3243
+ profileId: agent.profileId,
3244
+ reason: `plugin ${agent.pluginId} is unavailable: ${pluginStatus.error}`,
3245
+ status: "disabled"
3246
+ }));
3247
+ continue;
3248
+ }
3249
+ const resolved = yield* Effect.try({
3250
+ try: () => {
3251
+ const baseDefinition = input.agentCatalog.resolve(catalog, agent);
3252
+ const projectSpace = agent.projectSpaceId ? input.manifest.projectSpaces?.find(({ id }) => id === agent.projectSpaceId) : void 0;
3253
+ return projectSpace ? input.deepFreeze({
3254
+ ...baseDefinition,
3255
+ projectSpaceRevision: input.createStableId("project-space-declaration", {
3256
+ id: projectSpace.id,
3257
+ root: projectSpace.root,
3258
+ skills: { sources: projectSpace.skills.sources },
3259
+ workingDirectory: projectSpace.workingDirectory
3260
+ })
3261
+ }) : baseDefinition;
3262
+ },
3263
+ catch: toDeploymentFailure
3264
+ }).pipe(Effect.either);
3265
+ if (Either.isLeft(resolved)) {
3266
+ const declaration = input.manifest.plugins.find(({ id }) => id === agent.pluginId);
3267
+ if (declaration.required) return yield* Effect.fail(new RivusPluginLoadError(declaration.id, declaration.module, `deployment ${agent.agentId} failed to resolve: ${resolved.left.message}`, { cause: resolved.left }));
3268
+ agentStatuses.push(Object.freeze({
3269
+ agentId: agent.agentId,
3270
+ pluginId: agent.pluginId,
3271
+ profileId: agent.profileId,
3272
+ reason: resolved.left.message,
3273
+ status: "disabled"
3274
+ }));
3275
+ continue;
3276
+ }
3277
+ definitions.push(resolved.right);
3278
+ agentStatuses.push(Object.freeze({
3279
+ agentId: agent.agentId,
3280
+ definition: resolved.right,
3281
+ pluginId: agent.pluginId,
3282
+ profileId: agent.profileId,
3283
+ status: "enabled"
3284
+ }));
3285
+ }
3286
+ const agentStatusById = new Map(agentStatuses.map((agent) => [agent.agentId, agent]));
3287
+ const automationTemplates = new Map(catalog.snapshot().automations.map((template) => [template.id, template]));
3288
+ const automationDefinitions = [];
3289
+ for (const automation of input.manifest.automations ?? []) {
3290
+ const agent = agentStatusById.get(automation.agentId);
3291
+ if (!agent || agent.status === "disabled" || !agent.definition) continue;
3292
+ const deliveryEndpoint = input.manifest.endpoints.find(({ id }) => id === automation.delivery.endpointId);
3293
+ const presentationAgent = agentStatusById.get(deliveryEndpoint.agentId);
3294
+ if (!presentationAgent || presentationAgent.status === "disabled" || !presentationAgent.definition) continue;
3295
+ const template = automationTemplates.get(automation.templateId);
3296
+ if (!template) return yield* Effect.fail(/* @__PURE__ */ new Error(`automation ${automation.id} references unknown template: ${automation.templateId}`));
3297
+ if (template.pluginId !== agent.pluginId || template.profileId !== agent.profileId) return yield* Effect.fail(/* @__PURE__ */ new Error(`automation ${automation.id} template is not owned by agent profile ${agent.profileId}`));
3298
+ const definition = yield* Effect.try({
3299
+ try: () => input.deepFreeze({
3300
+ ...automation,
3301
+ runtimeDefinition: input.agentCatalog.restrictGrants(agent.definition, {
3302
+ memory: {
3303
+ scopes: [],
3304
+ tool: false
3305
+ },
3306
+ runtimeToolIds: [],
3307
+ skillIds: template.requestedSkillIds,
3308
+ toolIds: template.requestedToolIds
3309
+ }),
3310
+ template
3311
+ }),
3312
+ catch: toDeploymentFailure
3313
+ });
3314
+ automationDefinitions.push(definition);
3315
+ }
3316
+ return Object.freeze({
3317
+ agents: Object.freeze(agentStatuses),
3318
+ automationDefinitions: Object.freeze(automationDefinitions),
3319
+ catalog,
3320
+ definitions: Object.freeze(definitions),
3321
+ manifest: input.manifest,
3322
+ plugins: Object.freeze(pluginStatuses)
3323
+ });
3324
+ });
3325
+ }
3326
+ //#endregion
3327
+ //#region src/core/application/deployment/lifecycle/deployment-lifecycle.ts
3328
+ var InvalidDeploymentLifecycleTransition = class extends Error {
3329
+ name = "InvalidDeploymentLifecycleTransition";
3330
+ };
3331
+ var RivusDeploymentDaemonLifecycleError = class extends Error {
3332
+ name = "RivusDeploymentDaemonLifecycleError";
3333
+ };
3334
+ const componentTransitions = Object.freeze({
3335
+ "cleanup-required": ["cleanup-required", "stopping"],
3336
+ degraded: ["degraded", "stopping"],
3337
+ disabled: ["disabled"],
3338
+ running: [
3339
+ "degraded",
3340
+ "running",
3341
+ "stopping"
3342
+ ],
3343
+ starting: ["degraded", "running"],
3344
+ stopped: ["starting", "stopped"],
3345
+ stopping: [
3346
+ "cleanup-required",
3347
+ "disabled",
3348
+ "stopped"
3349
+ ]
3350
+ });
3351
+ const controlTransitions = Object.freeze({
3352
+ "cleanup-required": ["cleanup-required", "stopping"],
3353
+ degraded: ["degraded", "stopping"],
3354
+ running: [
3355
+ "degraded",
3356
+ "running",
3357
+ "stopping"
3358
+ ],
3359
+ starting: ["degraded", "running"],
3360
+ stopped: [
3361
+ "starting",
3362
+ "stopped",
3363
+ "stopping"
3364
+ ],
3365
+ stopping: ["cleanup-required", "stopped"]
3366
+ });
3367
+ function transitionDeploymentComponentLifecycle(current, next) {
3368
+ if (!componentTransitions[current].includes(next)) throw new InvalidDeploymentLifecycleTransition(`cannot transition deployment component from ${current} to ${next}`);
3369
+ return next;
3370
+ }
3371
+ function transitionDeploymentControlLifecycle(current, next) {
3372
+ if (!controlTransitions[current].includes(next)) throw new InvalidDeploymentLifecycleTransition(`cannot transition Deployment Control from ${current} to ${next}`);
3373
+ return next;
3374
+ }
3375
+ function isRequiredDeploymentComponentReady(input) {
3376
+ return !input.enabled || !input.required || input.lifecycle === "running" && input.running;
3377
+ }
3378
+ //#endregion
3379
+ //#region src/core/application/deployment/lifecycle/deployment-preparation.ts
3380
+ function prepareDeployment(input) {
3381
+ return Effect.gen(function* () {
3382
+ const deployment = input.deployment;
3383
+ if ((deployment.manifest.projectSpaces?.length ?? 0) > 0 && !input.projectSpaceResolver) return yield* Effect.fail(new RivusDeploymentDaemonLifecycleError("deployment bootstrap does not provide a Project Space resolver"));
3384
+ const projectSpaces = /* @__PURE__ */ new Map();
3385
+ for (const declaration of deployment.manifest.projectSpaces ?? []) {
3386
+ const resolved = yield* input.projectSpaceResolver.resolve({
3387
+ declaration,
3388
+ deploymentRoot: input.deploymentRoot
3389
+ }).pipe(Effect.mapError(toDeploymentFailure));
3390
+ projectSpaces.set(resolved.id, resolved);
3391
+ }
3392
+ const definitions = yield* Effect.try({
3393
+ try: () => new Map(deployment.definitions.map((definition) => {
3394
+ const resolved = bindResolvedProjectSpaceRevision(definition, projectSpaces);
3395
+ return [resolved.agentId, resolved];
3396
+ })),
3397
+ catch: toDeploymentFailure
3398
+ });
3399
+ const automationDefinitions = yield* Effect.try({
3400
+ try: () => new Map(deployment.automationDefinitions.map((definition) => [definition.id, Object.freeze({
3401
+ ...definition,
3402
+ runtimeDefinition: bindResolvedProjectSpaceRevision(definition.runtimeDefinition, projectSpaces)
3403
+ })])),
3404
+ catch: toDeploymentFailure
3405
+ });
3406
+ const effectiveDeployment = Object.freeze({
3407
+ ...deployment,
3408
+ agents: Object.freeze(deployment.agents.map((agent) => {
3409
+ if (!agent.definition) return agent;
3410
+ const definition = definitions.get(agent.agentId);
3411
+ return definition ? Object.freeze({
3412
+ ...agent,
3413
+ definition
3414
+ }) : agent;
3415
+ })),
3416
+ automationDefinitions: Object.freeze([...automationDefinitions.values()]),
3417
+ definitions: Object.freeze([...definitions.values()])
3418
+ });
3419
+ const backgroundConfig = deployment.manifest.backgroundSessions;
3420
+ const backgroundDefinitions = /* @__PURE__ */ new Map();
3421
+ if (backgroundConfig?.enabled) for (const agent of effectiveDeployment.agents) {
3422
+ if (agent.status !== "enabled" || !agent.definition) continue;
3423
+ const narrowed = yield* Effect.try({
3424
+ try: () => narrowBackgroundSessionDefinition(definitions.get(agent.agentId), input.digest),
3425
+ catch: toDeploymentFailure
3426
+ });
3427
+ backgroundDefinitions.set(agent.agentId, narrowed);
3428
+ }
3429
+ const agentStatuses = new Map(effectiveDeployment.agents.map((agent) => [agent.agentId, agent]));
3430
+ const endpointSlots = deployment.manifest.endpoints.map((definition) => {
3431
+ return createSlot(definition, agentStatuses.get(definition.agentId)?.status === "enabled");
3432
+ });
3433
+ const automationSlots = (deployment.manifest.automations ?? []).map((definition) => {
3434
+ const agentEnabled = agentStatuses.get(definition.agentId)?.status === "enabled";
3435
+ const resolvedDefinition = automationDefinitions.get(definition.id);
3436
+ return {
3437
+ ...createSlot(definition, agentEnabled && resolvedDefinition !== void 0),
3438
+ agentEnabled,
3439
+ ...resolvedDefinition ? { resolvedDefinition } : {}
3440
+ };
3441
+ });
3442
+ const backgroundSessionSlot = backgroundConfig ? createSlot(backgroundConfig, backgroundDefinitions.size > 0) : void 0;
3443
+ const host = yield* input.agentHostFactory.create({
3444
+ automations: automationSlots.filter((slot) => slot.definition.enabled && slot.agentEnabled && slot.resolvedDefinition !== void 0).map((slot) => ({
3445
+ definition: slot.resolvedDefinition.runtimeDefinition,
3446
+ id: slot.definition.id
3447
+ })),
3448
+ backgroundSessions: [...backgroundDefinitions].map(([agentId, definition]) => ({
3449
+ agentId,
3450
+ definition
3451
+ })),
3452
+ definitions: [...definitions.values()],
3453
+ endpoints: endpointSlots.filter((slot) => slot.definition.enabled && slot.agentEnabled).map((slot) => ({
3454
+ agentId: slot.definition.agentId,
3455
+ id: slot.definition.id
3456
+ })),
3457
+ ...input.initialInstanceRecords ? { initialInstanceRecords: input.initialInstanceRecords } : {},
3458
+ runtimeFactory: { create: (instance) => {
3459
+ const definition = instance.binding.kind === "automation" ? automationDefinitions.get(instance.binding.automationId)?.runtimeDefinition : instance.binding.kind === "background-session" ? backgroundDefinitions.get(instance.agentId) : definitions.get(instance.agentId);
3460
+ if (!definition) return Effect.fail(new RivusDeploymentDaemonLifecycleError(`runtime instance references unknown agent: ${instance.agentId}`));
3461
+ const projectSpace = definition.projectSpaceId ? projectSpaces.get(definition.projectSpaceId) : void 0;
3462
+ return input.runtimeFactory.create({
3463
+ ...instance,
3464
+ catalog: effectiveDeployment.catalog,
3465
+ definition,
3466
+ ...projectSpace ? { projectSpace } : {}
3467
+ });
3468
+ } }
3469
+ }).pipe(Effect.mapError(toDeploymentFailure));
3470
+ return {
3471
+ automationSlots,
3472
+ ...backgroundSessionSlot ? { backgroundSessionSlot } : {},
3473
+ definitions,
3474
+ deployment: effectiveDeployment,
3475
+ endpointSlots,
3476
+ host
3477
+ };
3478
+ });
3479
+ }
3480
+ function createSlot(definition, agentEnabled) {
3481
+ return {
3482
+ agentEnabled,
3483
+ definition,
3484
+ ...!definition.enabled ? { lifecycle: "disabled" } : agentEnabled ? { lifecycle: "stopped" } : {
3485
+ error: "component is unavailable",
3486
+ lifecycle: "degraded"
3487
+ }
3488
+ };
3489
+ }
3490
+ function bindResolvedProjectSpaceRevision(definition, projectSpaces) {
3491
+ if (!definition.projectSpaceId) return definition;
3492
+ const projectSpace = projectSpaces.get(definition.projectSpaceId);
3493
+ if (!projectSpace) throw new RivusDeploymentDaemonLifecycleError(`agent ${definition.agentId} references unresolved Project Space: ${definition.projectSpaceId}`);
3494
+ return Object.freeze({
3495
+ ...definition,
3496
+ projectSpaceRevision: projectSpace.revision
3497
+ });
3498
+ }
3499
+ //#endregion
3500
+ //#region src/core/application/deployment/lifecycle/deployment-control.ts
3501
+ var RivusDeploymentReadinessError = class extends Error {
3502
+ endpointIds;
3503
+ name = "RivusDeploymentReadinessError";
3504
+ constructor(endpointIds) {
3505
+ super(`required endpoint startup failed: ${endpointIds.join(", ")}`);
3506
+ this.endpointIds = endpointIds;
3507
+ }
3508
+ };
3509
+ var RivusDeploymentAutomationReadinessError = class extends Error {
3510
+ automationIds;
3511
+ name = "RivusDeploymentAutomationReadinessError";
3512
+ constructor(automationIds) {
3513
+ super(`required automation startup failed: ${automationIds.join(", ")}`);
3514
+ this.automationIds = automationIds;
3515
+ }
3516
+ };
3517
+ var RivusDeploymentBackgroundSessionReadinessError = class extends Error {
3518
+ name = "RivusDeploymentBackgroundSessionReadinessError";
3519
+ constructor() {
3520
+ super("required Background Session startup failed");
3521
+ }
3522
+ };
3523
+ function createRivusDeploymentControl(input) {
3524
+ return Effect.gen(function* () {
3525
+ return makeDeploymentControl({
3526
+ ...yield* prepareDeployment(input),
3527
+ ...input.automationFactory ? { automationFactory: input.automationFactory } : {},
3528
+ ...input.backgroundSessionFactory ? { backgroundSessionFactory: input.backgroundSessionFactory } : {},
3529
+ endpointFactory: input.endpointFactory
3530
+ });
3531
+ });
3532
+ }
3533
+ function makeDeploymentControl(input) {
3534
+ const endpointById = new Map(input.endpointSlots.map((slot) => [slot.definition.id, slot]));
3535
+ const allSlots = [
3536
+ ...input.endpointSlots,
3537
+ ...input.automationSlots,
3538
+ ...input.backgroundSessionSlot ? [input.backgroundSessionSlot] : []
3539
+ ];
3540
+ let lifecycle = "stopped";
3541
+ const refreshObservedState = () => {
3542
+ let degraded = false;
3543
+ for (const slot of allSlots) {
3544
+ if (slot.lifecycle !== "running") continue;
3545
+ const observed = observeRunning(slot);
3546
+ if (!observed.running) {
3547
+ slot.lifecycle = transitionDeploymentComponentLifecycle(slot.lifecycle, "degraded");
3548
+ slot.error = observed.error ?? "component stopped running after startup";
3549
+ degraded = true;
3550
+ }
3551
+ }
3552
+ if (degraded && lifecycle === "running") lifecycle = transitionDeploymentControlLifecycle(lifecycle, "degraded");
3553
+ };
3554
+ const canRunIntake = () => {
3555
+ refreshObservedState();
3556
+ return lifecycle === "running" || lifecycle === "degraded";
3557
+ };
3558
+ const handleEndpoint = (endpointId, request) => Effect.suspend(() => {
3559
+ const slot = endpointById.get(endpointId);
3560
+ if (!slot) return Effect.fail(new RivusDeploymentDaemonLifecycleError(`unknown endpoint: ${endpointId}`));
3561
+ const observed = observeRunning(slot);
3562
+ if (!canRunIntake() || slot.lifecycle !== "running" || !observed.running) return Effect.fail(new RivusDeploymentDaemonLifecycleError(`endpoint ${endpointId} cannot accept intake while Deployment Control is ${lifecycle} and endpoint is ${slot.lifecycle}`));
3563
+ return input.host.handleEndpoint(endpointId, request);
3564
+ });
3565
+ const isReady = () => allSlots.every((slot) => isSlotReady(slot));
3566
+ const readinessFailure = () => {
3567
+ const endpointIds = input.endpointSlots.filter((slot) => slot.definition.enabled && slot.definition.required && !isSlotReady(slot)).map((slot) => slot.definition.id);
3568
+ if (endpointIds.length > 0) return new RivusDeploymentReadinessError(Object.freeze(endpointIds));
3569
+ const automationIds = input.automationSlots.filter((slot) => slot.definition.enabled && slot.definition.required && !isSlotReady(slot)).map((slot) => slot.definition.id);
3570
+ if (automationIds.length > 0) return new RivusDeploymentAutomationReadinessError(Object.freeze(automationIds));
3571
+ if (input.backgroundSessionSlot?.definition.enabled && input.backgroundSessionSlot.definition.required && !isSlotReady(input.backgroundSessionSlot)) return new RivusDeploymentBackgroundSessionReadinessError();
3572
+ };
3573
+ const status = () => {
3574
+ refreshObservedState();
3575
+ return Object.freeze({
3576
+ agents: input.deployment.agents,
3577
+ automations: Object.freeze(input.automationSlots.map((slot) => ({
3578
+ ...componentStatus(slot),
3579
+ agentId: slot.definition.agentId,
3580
+ automationId: slot.definition.id
3581
+ }))),
3582
+ ...input.backgroundSessionSlot ? { backgroundSessions: backgroundStatus(input.backgroundSessionSlot) } : {},
3583
+ defaultAgentId: input.deployment.manifest.defaultAgentId,
3584
+ defaultEndpointId: input.deployment.manifest.defaultEndpointId,
3585
+ endpoints: Object.freeze(input.endpointSlots.map((slot) => ({
3586
+ ...componentStatus(slot),
3587
+ agentId: slot.definition.agentId,
3588
+ endpointId: slot.definition.id
3589
+ }))),
3590
+ lifecycle,
3591
+ plugins: input.deployment.plugins,
3592
+ ready: isReady(),
3593
+ running: lifecycle === "running" || lifecycle === "degraded"
3594
+ });
3595
+ };
3596
+ return {
3597
+ deployment: input.deployment,
3598
+ handleDefault: (request) => handleEndpoint(input.deployment.manifest.defaultEndpointId, request),
3599
+ handleEndpoint,
3600
+ runDefaultAgent: (request) => input.host.handleEndpoint(input.deployment.manifest.defaultEndpointId, request),
3601
+ running: canRunIntake,
3602
+ start: () => Effect.suspend(() => {
3603
+ refreshObservedState();
3604
+ if (lifecycle === "running") return Effect.void;
3605
+ if (lifecycle === "degraded") {
3606
+ const failure = readinessFailure();
3607
+ return failure ? Effect.fail(failure) : Effect.void;
3608
+ }
3609
+ if (lifecycle !== "stopped") return Effect.fail(new RivusDeploymentDaemonLifecycleError(`cannot start deployment daemon while ${lifecycle}`));
3610
+ lifecycle = transitionDeploymentControlLifecycle(lifecycle, "starting");
3611
+ return Effect.gen(function* () {
3612
+ let degraded = input.deployment.plugins.some(({ status: pluginStatus }) => pluginStatus === "failed");
3613
+ for (const slot of input.endpointSlots) degraded = (yield* startSlot(slot, slot.agentEnabled, `endpoint ${slot.definition.id}`, () => Effect.gen(function* () {
3614
+ const instance = yield* input.host.resolveEndpoint(slot.definition.id);
3615
+ return yield* input.endpointFactory.create({
3616
+ agentId: slot.definition.agentId,
3617
+ cancel: (request) => input.host.cancelEndpoint(slot.definition.id, request),
3618
+ definition: slot.definition,
3619
+ endpointId: slot.definition.id,
3620
+ handle: (request) => handleEndpoint(slot.definition.id, request),
3621
+ instanceId: instance.instanceId,
3622
+ ...input.definitions.get(slot.definition.agentId)?.projectSpaceId ? { projectSpaceId: input.definitions.get(slot.definition.agentId).projectSpaceId } : {},
3623
+ steer: (request) => input.host.steerEndpoint(slot.definition.id, request)
3624
+ });
3625
+ }))) || degraded;
3626
+ for (const slot of input.automationSlots) {
3627
+ const resolvedDefinition = slot.resolvedDefinition;
3628
+ const deliverySlot = endpointById.get(slot.definition.delivery.endpointId);
3629
+ const deliveryRunning = observeRunning(deliverySlot).running && deliverySlot.lifecycle === "running";
3630
+ degraded = (yield* startSlot(slot, slot.agentEnabled && resolvedDefinition !== void 0 && deliveryRunning, `automation ${slot.definition.id}`, () => Effect.gen(function* () {
3631
+ if (!input.automationFactory) return yield* Effect.fail(new RivusDeploymentDaemonLifecycleError("deployment bootstrap does not provide Automation adapters"));
3632
+ if (!resolvedDefinition) return yield* Effect.fail(new RivusDeploymentDaemonLifecycleError(`automation definition not resolved: ${slot.definition.id}`));
3633
+ const instance = yield* input.host.resolveAutomation(slot.definition.id);
3634
+ return yield* input.automationFactory.create({
3635
+ automationId: slot.definition.id,
3636
+ definition: resolvedDefinition,
3637
+ deliveryEndpoint: deliverySlot.definition,
3638
+ instanceId: instance.instanceId,
3639
+ run: (request) => input.host.handleAutomation(slot.definition.id, {
3640
+ invocation: {
3641
+ allowedActorOpenIds: [],
3642
+ automationId: slot.definition.id,
3643
+ endpointId: slot.definition.delivery.endpointId,
3644
+ kind: "automation",
3645
+ sourceMessageId: request.tickId,
3646
+ tenantKey: "automation",
3647
+ tickId: request.tickId
3648
+ },
3649
+ sessionKey: request.sessionKey,
3650
+ text: request.text
3651
+ })
3652
+ });
3653
+ }))) || degraded;
3654
+ }
3655
+ if (input.backgroundSessionSlot) {
3656
+ const slot = input.backgroundSessionSlot;
3657
+ degraded = (yield* startSlot(slot, slot.agentEnabled, "Background Session", () => Effect.gen(function* () {
3658
+ if (!input.backgroundSessionFactory) return yield* Effect.fail(new RivusDeploymentDaemonLifecycleError("deployment bootstrap does not provide Background Session adapters"));
3659
+ return yield* input.backgroundSessionFactory.create({
3660
+ agentIds: [...input.definitions.keys()].filter((agentId) => input.deployment.agents.some((agent) => agent.agentId === agentId && agent.status === "enabled")),
3661
+ cancel: (request) => input.host.cancelBackgroundSession(request.agentId, request),
3662
+ config: slot.definition,
3663
+ run: (request) => input.host.handleBackgroundSession(request.agentId, {
3664
+ ...request.invocation ? { invocation: request.invocation } : {},
3665
+ ...request.onUpdate ? { onUpdate: request.onUpdate } : {},
3666
+ sessionKey: request.sessionKey,
3667
+ text: request.text
3668
+ })
3669
+ });
3670
+ }))) || degraded;
3671
+ }
3672
+ lifecycle = transitionDeploymentControlLifecycle(lifecycle, degraded ? "degraded" : "running");
3673
+ const failure = readinessFailure();
3674
+ if (failure) return yield* Effect.fail(failure);
3675
+ });
3676
+ }),
3677
+ status,
3678
+ stop: () => Effect.suspend(() => {
3679
+ if (lifecycle !== "stopped" && lifecycle !== "running" && lifecycle !== "degraded" && lifecycle !== "cleanup-required") return Effect.fail(new RivusDeploymentDaemonLifecycleError(`cannot stop deployment daemon while ${lifecycle}`));
3680
+ lifecycle = transitionDeploymentControlLifecycle(lifecycle, "stopping");
3681
+ return Effect.gen(function* () {
3682
+ const errors = [];
3683
+ yield* stopSlots(input.automationSlots, errors);
3684
+ if (input.backgroundSessionSlot) yield* stopSlots([input.backgroundSessionSlot], errors);
3685
+ yield* stopSlots(input.endpointSlots, errors);
3686
+ const hostExit = yield* Effect.exit(input.host.dispose());
3687
+ if (Exit.isFailure(hostExit)) errors.push(Cause.squash(hostExit.cause));
3688
+ lifecycle = transitionDeploymentControlLifecycle(lifecycle, errors.length === 0 ? "stopped" : "cleanup-required");
3689
+ if (errors.length === 1) return yield* Effect.fail(errors[0]);
3690
+ if (errors.length > 1) return yield* Effect.fail(new AggregateError(errors, "deployment daemon cleanup failed"));
3691
+ });
3692
+ })
3693
+ };
3694
+ }
3695
+ function startSlot(slot, available, label, create) {
3696
+ return Effect.gen(function* () {
3697
+ if (!slot.definition.enabled) {
3698
+ slot.lifecycle = "disabled";
3699
+ return false;
3700
+ }
3701
+ if (!available) {
3702
+ slot.lifecycle = "degraded";
3703
+ slot.error = `${label} is unavailable`;
3704
+ return true;
3705
+ }
3706
+ if (slot.lifecycle !== "stopped") return yield* Effect.fail(new RivusDeploymentDaemonLifecycleError(`cannot start ${label} while ${slot.lifecycle}`));
3707
+ slot.lifecycle = transitionDeploymentComponentLifecycle(slot.lifecycle, "starting");
3708
+ delete slot.error;
3709
+ const started = yield* Effect.gen(function* () {
3710
+ slot.adapter ??= yield* create();
3711
+ yield* slot.adapter.start();
3712
+ if (!(yield* Effect.try({
3713
+ try: () => slot.adapter.running(),
3714
+ catch: toDeploymentFailure
3715
+ }))) return yield* Effect.fail(/* @__PURE__ */ new Error(`${label} start completed but the adapter is not running`));
3716
+ }).pipe(Effect.exit);
3717
+ if (Exit.isFailure(started)) {
3718
+ slot.error = formatDeploymentFailure(Cause.squash(started.cause));
3719
+ slot.lifecycle = transitionDeploymentComponentLifecycle(slot.lifecycle, "degraded");
3720
+ return true;
3721
+ }
3722
+ slot.lifecycle = transitionDeploymentComponentLifecycle(slot.lifecycle, "running");
3723
+ return false;
3724
+ });
3725
+ }
3726
+ function stopSlots(slots, errors) {
3727
+ return Effect.gen(function* () {
3728
+ for (const slot of [...slots].reverse()) {
3729
+ if (slot.lifecycle === "stopped" || slot.lifecycle === "disabled") continue;
3730
+ slot.lifecycle = transitionDeploymentComponentLifecycle(slot.lifecycle, "stopping");
3731
+ if (!slot.adapter) {
3732
+ slot.lifecycle = transitionDeploymentComponentLifecycle(slot.lifecycle, slot.definition.enabled && slot.agentEnabled ? "stopped" : "disabled");
3733
+ delete slot.error;
3734
+ continue;
3735
+ }
3736
+ const stopped = yield* Effect.gen(function* () {
3737
+ yield* slot.adapter.stop();
3738
+ if (yield* Effect.try({
3739
+ try: () => slot.adapter.running(),
3740
+ catch: toDeploymentFailure
3741
+ })) return yield* Effect.fail(/* @__PURE__ */ new Error("component stop completed but the adapter is still running"));
3742
+ }).pipe(Effect.exit);
3743
+ if (Exit.isFailure(stopped)) {
3744
+ const error = Cause.squash(stopped.cause);
3745
+ errors.push(error);
3746
+ slot.error = formatDeploymentFailure(error);
3747
+ slot.lifecycle = transitionDeploymentComponentLifecycle(slot.lifecycle, "cleanup-required");
3748
+ continue;
3749
+ }
3750
+ slot.lifecycle = transitionDeploymentComponentLifecycle(slot.lifecycle, slot.definition.enabled && slot.agentEnabled ? "stopped" : "disabled");
3751
+ delete slot.error;
3752
+ }
3753
+ });
3754
+ }
3755
+ function componentStatus(slot) {
3756
+ const observed = observeRunning(slot);
3757
+ return Object.freeze({
3758
+ enabled: slot.definition.enabled,
3759
+ ...slot.error ? { error: slot.error } : {},
3760
+ lifecycle: slot.lifecycle,
3761
+ required: slot.definition.required,
3762
+ running: slot.lifecycle === "running" && observed.running
3763
+ });
3764
+ }
3765
+ function backgroundStatus(slot) {
3766
+ let supervisor;
3767
+ try {
3768
+ supervisor = slot.adapter?.status?.();
3769
+ } catch (error) {
3770
+ slot.error = formatDeploymentFailure(error);
3771
+ }
3772
+ return Object.freeze({
3773
+ ...componentStatus(slot),
3774
+ ...supervisor ? { supervisor } : {}
3775
+ });
3776
+ }
3777
+ function isSlotReady(slot) {
3778
+ return isRequiredDeploymentComponentReady({
3779
+ enabled: slot.definition.enabled,
3780
+ lifecycle: slot.lifecycle,
3781
+ required: slot.definition.required,
3782
+ running: observeRunning(slot).running
3783
+ });
3784
+ }
3785
+ function observeRunning(slot) {
3786
+ if (!slot.adapter) return { running: false };
3787
+ try {
3788
+ return { running: slot.adapter.running() };
3789
+ } catch (error) {
3790
+ return {
3791
+ error: formatDeploymentFailure(error),
3792
+ running: false
3793
+ };
3794
+ }
3795
+ }
3796
+ //#endregion
3797
+ //#region src/adapters/deployment/project-space/node-project-space-resolver.ts
3798
+ async function resolveRivusProjectSpace(input) {
3799
+ validateRivusProjectSpaceDeployment(input.declaration);
3800
+ const root = await resolveContainedDirectory(await resolveExistingDirectory(input.deploymentRoot, "deployment root"), input.declaration.root, "Project Space root");
3801
+ const workingDirectory = await resolveContainedDirectory(root, input.declaration.workingDirectory, "Project Space working directory");
3802
+ const skillPaths = await Promise.all(input.declaration.skills.sources.map((source) => resolveContainedPath(root, source, "Project Space Skill source")));
3803
+ await Promise.all(skillPaths.map((path) => assertTreeContainsNoSymbolicLinks(path)));
3804
+ return Object.freeze({
3805
+ id: input.declaration.id,
3806
+ revision: createStableId("project-space", {
3807
+ id: input.declaration.id,
3808
+ root,
3809
+ skillPaths,
3810
+ workingDirectory
3811
+ }),
3812
+ root,
3813
+ skillPaths: Object.freeze(skillPaths),
3814
+ workingDirectory
3815
+ });
3816
+ }
3817
+ async function assertTreeContainsNoSymbolicLinks(path) {
3818
+ const metadata = await lstat(path);
3819
+ if (metadata.isSymbolicLink()) throw new InvalidRivusProjectSpace(`Project Space Skill source contains a symbolic link: ${path}`);
3820
+ if (!metadata.isDirectory()) return;
3821
+ for (const entry of await readdir(path, { withFileTypes: true })) {
3822
+ const child = resolve(path, entry.name);
3823
+ if (entry.isSymbolicLink()) throw new InvalidRivusProjectSpace(`Project Space Skill source contains a symbolic link: ${child}`);
3824
+ if (entry.isDirectory()) await assertTreeContainsNoSymbolicLinks(child);
3825
+ }
3826
+ }
3827
+ async function resolveContainedDirectory(base, path, owner) {
3828
+ const resolved = await resolveContainedPath(base, path, owner);
3829
+ if (!(await stat(resolved)).isDirectory()) throw new InvalidRivusProjectSpace(`${owner} must be a directory: ${path}`);
3830
+ return resolved;
3831
+ }
3832
+ async function resolveContainedPath(base, path, owner) {
3833
+ validateRelativePath(path, owner);
3834
+ const candidate = resolve(base, path);
3835
+ assertContained(base, candidate, owner);
3836
+ let resolved;
3837
+ try {
3838
+ resolved = await realpath(candidate);
3839
+ } catch (cause) {
3840
+ throw new InvalidRivusProjectSpace(`${owner} does not exist: ${path}`, { cause });
3841
+ }
3842
+ assertContained(base, resolved, owner);
3843
+ const metadata = await stat(resolved);
3844
+ if (!metadata.isDirectory() && !metadata.isFile()) throw new InvalidRivusProjectSpace(`${owner} must be a file or directory: ${path}`);
3845
+ return resolved;
3846
+ }
3847
+ async function resolveExistingDirectory(path, owner) {
3848
+ let resolved;
3849
+ try {
3850
+ resolved = await realpath(path);
3851
+ } catch (cause) {
3852
+ throw new InvalidRivusProjectSpace(`${owner} does not exist`, { cause });
3853
+ }
3854
+ if (!(await stat(resolved)).isDirectory()) throw new InvalidRivusProjectSpace(`${owner} must be a directory`);
3855
+ return resolved;
3856
+ }
3857
+ function validateRelativePath(path, owner) {
3858
+ if (!path.trim() || path.includes("\0") || isAbsolute(path)) throw new InvalidRivusProjectSpace(`${owner} must be a non-empty relative path`);
3859
+ }
3860
+ function assertContained(base, candidate, owner) {
3861
+ if (isPathWithin(base, candidate)) return;
3862
+ throw new InvalidRivusProjectSpace(`${owner} escapes its trusted root`);
3863
+ }
3864
+ //#endregion
3865
+ //#region src/adapters/cli/prompt/local-cli-invocation.ts
3866
+ function createLocalCliAgentInvocation(input) {
3867
+ const conversationId = trimOptional(input.env.RIVUS_LOCAL_CONVERSATION_ID);
3868
+ return {
3869
+ allowedActorOpenIds: [],
3870
+ endpointId: input.endpointId,
3871
+ kind: "local-cli",
3872
+ memory: {
3873
+ audience: "private",
3874
+ ...conversationId ? { conversationId } : {},
3875
+ ...input.projectSpaceId ? { projectId: input.projectSpaceId } : {},
3876
+ subjectId: trimOptional(input.env.RIVUS_LOCAL_SUBJECT_ID) ?? "local-operator",
3877
+ tenantId: trimOptional(input.env.RIVUS_MEMORY_TENANT_ID) ?? "local"
3878
+ },
3879
+ sourceMessageId: `cli:${randomUUID()}`,
3880
+ tenantKey: "local"
3881
+ };
3882
+ }
3883
+ function trimOptional(value) {
3884
+ return value?.trim() || void 0;
3885
+ }
3886
+ //#endregion
3887
+ //#region src/bootstrap/deployment/rivus-deployment-cli-process.ts
3888
+ async function createRivusDeploymentCliProcess(factory, context) {
3889
+ const adapters = await factory(context);
3890
+ let adaptersDisposed = false;
3891
+ let recoveryControlPromise;
3892
+ const disposeAdapters = async () => {
3893
+ if (adaptersDisposed) return;
3894
+ adaptersDisposed = true;
3895
+ await adapters.dispose?.();
3896
+ };
3897
+ let daemon;
3898
+ try {
3899
+ daemon = await runDeploymentProcessEffect(loadRivusDeploymentManifest(context.manifestPath).pipe(Effect.flatMap((manifest) => {
3900
+ const assemblyInput = {
3901
+ ...createProcessDeploymentControlPorts({
3902
+ ...adapters.createAutomation ? { createAutomation: adapters.createAutomation } : {},
3903
+ ...adapters.createBackgroundSession ? { createBackgroundSession: adapters.createBackgroundSession } : {},
3904
+ createEndpoint: adapters.createEndpoint,
3905
+ createRuntime: adapters.createRuntime
3906
+ }, manifest.backgroundSessions?.enabled === true, runDeploymentProcessEffect),
3907
+ deploymentRoot: dirname(context.manifestPath),
3908
+ ...adapters.initialInstanceRecords ? { initialInstanceRecords: adapters.initialInstanceRecords } : {},
3909
+ manifest,
3910
+ pluginLoader: createNodeRivusPluginModuleLoader(context.pluginPackageManifestPath ? { packageManifestPath: context.pluginPackageManifestPath } : {}),
3911
+ projectSpaceResolver: { resolve: (input) => Effect.tryPromise({
3912
+ try: () => resolveRivusProjectSpace(input),
3913
+ catch: toError
3914
+ }) }
3915
+ };
3916
+ return resolveRivusDeployment({
3917
+ ...assemblyInput,
3918
+ createStableId,
3919
+ deepFreeze
3920
+ }).pipe(Effect.flatMap((deployment) => createRivusDeploymentControl({
3921
+ ...assemblyInput,
3922
+ deployment,
3923
+ digest: createSha256Digest
3924
+ })));
3925
+ })));
3926
+ } catch (constructionError) {
3927
+ try {
3928
+ await disposeAdapters();
3929
+ } catch (disposeError) {
3930
+ throw new AggregateError([constructionError, disposeError], "deployment construction and cleanup failed");
3931
+ }
3932
+ throw constructionError;
3933
+ }
3934
+ const start = async () => {
3935
+ if (adaptersDisposed) throw new Error("Rivus deployment process cannot restart after its adapters have been disposed");
3936
+ try {
3937
+ await runDeploymentProcessEffect(daemon.start());
3938
+ } catch (startError) {
3939
+ const cleanupErrors = [];
3940
+ try {
3941
+ await runDeploymentProcessEffect(daemon.stop());
3942
+ } catch (error) {
3943
+ cleanupErrors.push(error);
3944
+ }
3945
+ try {
3946
+ await disposeAdapters();
3947
+ } catch (error) {
3948
+ cleanupErrors.push(error);
3949
+ }
3950
+ if (cleanupErrors.length > 0) throw new AggregateError([startError, ...cleanupErrors], "deployment startup and cleanup failed");
3951
+ throw startError;
3952
+ }
3953
+ };
3954
+ const stop = async () => {
3955
+ const errors = [];
3956
+ try {
3957
+ await runDeploymentProcessEffect(daemon.stop());
3958
+ } catch (error) {
3959
+ errors.push(error);
3960
+ }
3961
+ try {
3962
+ await disposeAdapters();
3963
+ } catch (error) {
3964
+ errors.push(error);
3965
+ }
3966
+ if (errors.length === 1) throw errors[0];
3967
+ if (errors.length > 1) throw new AggregateError(errors, "deployment and adapter cleanup failed");
3968
+ };
3969
+ const process = {
3970
+ defaultSessionKey: `local:${daemon.deployment.manifest.defaultAgentId}:cli`,
3971
+ openRecoveryControl: () => Effect.tryPromise({
3972
+ try: async () => {
3973
+ if (adaptersDisposed) throw new Error("Rivus deployment process cannot open Recovery Control after disposal");
3974
+ if (!adapters.createRecoveryControl) throw new Error("Deployment bootstrap does not expose Recovery Control");
3975
+ recoveryControlPromise ??= Promise.resolve().then(() => adapters.createRecoveryControl());
3976
+ try {
3977
+ return await recoveryControlPromise;
3978
+ } catch (error) {
3979
+ recoveryControlPromise = void 0;
3980
+ throw error;
3981
+ }
3982
+ },
3983
+ catch: (error) => error
3984
+ }),
3985
+ running: () => daemon.running(),
3986
+ start: () => Effect.tryPromise({
3987
+ try: start,
3988
+ catch: (error) => error
3989
+ }),
3990
+ status: () => Effect.sync(() => daemon.status()),
3991
+ stop: () => Effect.tryPromise({
3992
+ try: stop,
3993
+ catch: (error) => error
3994
+ }),
3995
+ promptText: (command) => Effect.tryPromise({
3996
+ try: async () => {
3997
+ if (adaptersDisposed) throw new Error("Rivus deployment process cannot restart after its adapters have been disposed");
3998
+ const projectSpaceId = daemon.deployment.definitions.find(({ agentId }) => agentId === daemon.deployment.manifest.defaultAgentId)?.projectSpaceId;
3999
+ return readPromptFinalText(await runDeploymentProcessEffect(daemon.runDefaultAgent({
4000
+ invocation: createLocalCliAgentInvocation({
4001
+ endpointId: daemon.deployment.manifest.defaultEndpointId,
4002
+ env: context.env,
4003
+ ...projectSpaceId ? { projectSpaceId } : {}
4004
+ }),
4005
+ sessionKey: command.sessionKey,
4006
+ text: command.text
4007
+ })));
4008
+ },
4009
+ catch: (error) => error
4010
+ })
4011
+ };
4012
+ const replayReceiveMessage = adapters.replayReceiveMessage;
4013
+ if (replayReceiveMessage) process.replayReceiveMessage = (payload, options) => Effect.tryPromise({
4014
+ try: async () => {
4015
+ if (!daemon.running()) await start();
4016
+ },
4017
+ catch: (error) => error
4018
+ }).pipe(Effect.flatMap(() => replayReceiveMessage((input) => runDeploymentProcessEffect(daemon.handleDefault(toEffectAgentRuntimeInput(input))), payload, options)));
4019
+ return process;
4020
+ }
4021
+ function readPromptFinalText(result) {
4022
+ if (typeof result === "string") return result;
4023
+ if (typeof result === "object" && result !== null && "finalText" in result && typeof result.finalText === "string") return result.finalText;
4024
+ throw new Error("Default deployment prompt result must be a string or contain finalText");
4025
+ }
4026
+ function toError(error) {
4027
+ return error instanceof Error ? error : new Error(String(error));
4028
+ }
4029
+ //#endregion
4030
+ //#region src/bootstrap/daemon/rivus-daemon-cli.ts
4031
+ function runRivusDaemonCli(options) {
4032
+ return Effect.gen(function* () {
4033
+ const parsed = parseRivusDaemonArguments(options.argv);
4034
+ if (parsed.help) {
4035
+ options.stdout.write(RIVUS_DAEMON_USAGE);
4036
+ return 0;
4037
+ }
4038
+ if (parsed.error) {
4039
+ options.stderr.write(formatRivusDaemonUsageError(parsed.error));
4040
+ return 1;
4041
+ }
4042
+ if (parsed.statusUrl) {
4043
+ const statusUrl = parsed.statusUrl;
4044
+ const readStatus = () => Effect.tryPromise({
4045
+ try: () => fetchLiveStatus(statusUrl),
4046
+ catch: (error) => error
4047
+ });
4048
+ const status = parsed.waitReceive ? yield* waitForReceiveStatus(readStatus, parsed.waitReceive, createWaitReceiveOptions(parsed)) : yield* readStatus();
4049
+ options.stdout.write(formatRivusDaemonJson(status));
4050
+ return 0;
4051
+ }
4052
+ if (parsed.printOpenClawEnvPath) {
4053
+ const openClawConfigPath = parsed.printOpenClawEnvPath;
4054
+ const result = yield* Effect.tryPromise({
4055
+ try: () => loadRivusEnvFromOpenClawConfig(openClawConfigPath, parsed.piApiKeyFile),
4056
+ catch: (error) => error
4057
+ });
4058
+ for (const warning of result.warnings) options.stderr.write(formatRivusDaemonWarning(warning));
4059
+ options.stdout.write(formatRivusEnvFile(result.env));
4060
+ return 0;
4061
+ }
4062
+ const env = yield* Effect.tryPromise({
4063
+ try: () => loadCliEnv(parsed.envFilePath, options.env),
4064
+ catch: (error) => error
4065
+ });
4066
+ const configuredBootstrapSpecifier = parsed.bootstrap ?? env.RIVUS_BOOTSTRAP_MODULE?.trim();
4067
+ const bootstrapSpecifier = configuredBootstrapSpecifier ? resolveRivusBuiltinSpecifier(configuredBootstrapSpecifier) : void 0;
4068
+ if (!parsed.checkConfig && !bootstrapSpecifier) {
4069
+ options.stderr.write(formatRivusDaemonUsageError("Missing --bootstrap <module> or RIVUS_BOOTSTRAP_MODULE"));
4070
+ return 1;
4071
+ }
4072
+ let legacyConfig;
4073
+ if (parsed.manifestPath) {
4074
+ if (parsed.checkConfig) {
4075
+ const manifestPath = parsed.manifestPath;
4076
+ const manifest = yield* loadRivusDeploymentManifest(manifestPath);
4077
+ yield* Effect.try({
4078
+ try: () => validateRivusDeploymentManifest(manifest),
4079
+ catch: (error) => error
4080
+ });
4081
+ options.stdout.write(formatRivusDaemonJson(toRedactedDeploymentManifest(manifest)));
4082
+ return 0;
4083
+ }
4084
+ } else {
4085
+ const configExit = yield* Effect.exit(loadRivusDaemonConfig(env));
4086
+ if (configExit._tag === "Failure") {
4087
+ options.stderr.write(formatRivusDaemonLine(configExit.cause.toString()));
4088
+ return 1;
4089
+ }
4090
+ legacyConfig = configExit.value;
4091
+ if (parsed.checkConfig) {
4092
+ options.stdout.write(formatRivusDaemonJson(toRedactedConfig(legacyConfig)));
4093
+ return 0;
4094
+ }
4095
+ }
4096
+ if (!bootstrapSpecifier) {
4097
+ options.stderr.write(formatRivusDaemonUsageError("Missing --bootstrap <module> or RIVUS_BOOTSTRAP_MODULE"));
4098
+ return 1;
4099
+ }
4100
+ const loadBootstrap = options.loadBootstrap ?? ((specifier) => import(specifier));
4101
+ const module = yield* Effect.tryPromise({
4102
+ try: () => loadBootstrap(bootstrapSpecifier),
4103
+ catch: (error) => error
4104
+ });
4105
+ const daemon = yield* Effect.tryPromise({
4106
+ try: () => parsed.manifestPath ? createCliDeploymentDaemon(module.createRivusDeploymentAdapters, {
4107
+ argv: options.argv,
4108
+ env,
4109
+ ...parsed.envFilePath ? { envFilePath: parsed.envFilePath } : {},
4110
+ environmentOverrides: options.env,
4111
+ manifestPath: parsed.manifestPath,
4112
+ ...options.pluginPackageManifestPath ? { pluginPackageManifestPath: options.pluginPackageManifestPath } : {}
4113
+ }) : createCliLegacyDaemon(module, {
4114
+ argv: options.argv,
4115
+ config: legacyConfig,
4116
+ env
4117
+ }),
4118
+ catch: (error) => error
4119
+ });
4120
+ if (parsed.recoveryCommand) {
4121
+ const recoveryCommand = parsed.recoveryCommand;
4122
+ return yield* runOneShotDaemon(daemon, () => Effect.gen(function* () {
4123
+ if (!hasRecoveryRunner(daemon)) {
4124
+ options.stderr.write(formatRivusDaemonCapabilityError("recovery"));
4125
+ return 1;
4126
+ }
4127
+ const control = yield* daemon.openRecoveryControl();
4128
+ const result = yield* Effect.tryPromise({
4129
+ try: () => runRivusRecoveryCliCommand(control, recoveryCommand),
4130
+ catch: (error) => error
4131
+ });
4132
+ options.stdout.write(formatRivusDaemonJson(result));
4133
+ return 0;
4134
+ }));
4135
+ }
4136
+ if (parsed.status) return yield* runStatusOneShot(options, daemon, (statusDaemon) => Effect.gen(function* () {
4137
+ const status = yield* statusDaemon.status();
4138
+ options.stdout.write(formatRivusDaemonJson(status));
4139
+ return 0;
4140
+ }));
4141
+ if (parsed.prompt !== void 0) {
4142
+ const prompt = parsed.prompt;
4143
+ return yield* runOneShotDaemon(daemon, () => Effect.gen(function* () {
4144
+ if (!hasPromptRunner(daemon)) {
4145
+ options.stderr.write(formatRivusDaemonCapabilityError("prompt"));
4146
+ return 1;
4147
+ }
4148
+ const text = yield* daemon.promptText({
4149
+ sessionKey: parsed.sessionKey ?? daemon.defaultSessionKey ?? `local:${legacyConfig.agentId}:cli`,
4150
+ text: prompt
4151
+ });
4152
+ options.stdout.write(formatRivusDaemonLine(text));
4153
+ return 0;
4154
+ }));
4155
+ }
4156
+ if (parsed.replayFeishuText !== void 0) {
4157
+ const replayFeishuText = parsed.replayFeishuText;
4158
+ return yield* runReplayOneShot(options, daemon, () => Effect.sync(() => createSyntheticFeishuTextReplayPayload(replayFeishuText, {
4159
+ ...parsed.feishuReplayChatId !== void 0 ? { chatId: parsed.feishuReplayChatId } : {},
4160
+ ...parsed.feishuReplayMessageId !== void 0 ? { messageId: parsed.feishuReplayMessageId } : {},
4161
+ ...parsed.feishuReplayTenantKey !== void 0 ? { tenantKey: parsed.feishuReplayTenantKey } : {},
4162
+ ...parsed.feishuReplayThreadId !== void 0 ? { threadId: parsed.feishuReplayThreadId } : {}
4163
+ })), { sideEffects: "disabled" });
4164
+ }
4165
+ if (parsed.replayFeishuEventPath !== void 0) {
4166
+ const replayFeishuEventPath = parsed.replayFeishuEventPath;
4167
+ return yield* runReplayOneShot(options, daemon, () => Effect.tryPromise({
4168
+ try: () => readFeishuReceiveMessagePayload(replayFeishuEventPath),
4169
+ catch: (error) => error
4170
+ }));
4171
+ }
4172
+ if (parsed.waitReceive) {
4173
+ const waitReceive = parsed.waitReceive;
4174
+ return yield* runStatusOneShot(options, daemon, (statusDaemon) => Effect.gen(function* () {
4175
+ yield* Effect.try({
4176
+ try: () => installCliShutdownController(options, statusDaemon),
4177
+ catch: (error) => error
4178
+ });
4179
+ yield* statusDaemon.start();
4180
+ const status = yield* waitForReceiveStatus(() => statusDaemon.status(), waitReceive, createWaitReceiveOptions(parsed));
4181
+ options.stdout.write(formatRivusDaemonJson(status));
4182
+ return 0;
4183
+ }));
4184
+ }
4185
+ yield* Effect.try({
4186
+ try: () => installCliShutdownController(options, daemon),
4187
+ catch: (error) => error
4188
+ });
4189
+ yield* daemon.start();
4190
+ options.stdout.write(RIVUS_DAEMON_STARTED_MESSAGE);
4191
+ return 0;
4192
+ }).pipe(Effect.catchAll((error) => Effect.sync(() => {
4193
+ options.stderr.write(formatRivusDaemonLine(formatRivusDaemonError(error)));
4194
+ return 1;
4195
+ })));
4196
+ }
4197
+ async function createCliLegacyDaemon(module, context) {
4198
+ const factory = module.createRivusDaemonProcess ?? module.default;
4199
+ if (!factory) throw new Error("Bootstrap module must export createRivusDaemonProcess(context) or a default factory");
4200
+ return factory(context);
4201
+ }
4202
+ async function createCliDeploymentDaemon(factory, context) {
4203
+ if (!factory) throw new Error("Manifest bootstrap module must export createRivusDeploymentAdapters(context)");
4204
+ return createRivusDeploymentCliProcess(factory, context);
4205
+ }
4206
+ function runOneShotDaemon(daemon, action) {
4207
+ return Effect.exit(Effect.suspend(action)).pipe(Effect.flatMap((exit) => daemon.stop().pipe(Effect.flatMap(() => exit._tag === "Success" ? Effect.succeed(exit.value) : Effect.failCause(exit.cause)))));
4208
+ }
4209
+ function runStatusOneShot(options, daemon, action) {
4210
+ return runOneShotDaemon(daemon, () => Effect.gen(function* () {
4211
+ if (!hasStatusReporter(daemon)) {
4212
+ options.stderr.write(formatRivusDaemonCapabilityError("status"));
4213
+ return 1;
4214
+ }
4215
+ return yield* action(daemon);
4216
+ }));
4217
+ }
4218
+ function runReplayOneShot(options, daemon, createPayload, replayOptions) {
4219
+ return runOneShotDaemon(daemon, () => Effect.gen(function* () {
4220
+ if (!hasFeishuReplayRunner(daemon)) {
4221
+ options.stderr.write(formatRivusDaemonCapabilityError("replay"));
4222
+ return 1;
4223
+ }
4224
+ const payload = yield* createPayload();
4225
+ const result = replayOptions === void 0 ? yield* daemon.replayReceiveMessage(payload) : yield* daemon.replayReceiveMessage(payload, replayOptions);
4226
+ options.stdout.write(formatRivusDaemonJson(result));
4227
+ return 0;
4228
+ }));
4229
+ }
4230
+ function createWaitReceiveOptions(parsed) {
4231
+ return {
4232
+ ...parsed.waitReceiveMessageId ? { messageId: parsed.waitReceiveMessageId } : {},
4233
+ ...parsed.waitReceiveObservedAfter ? { observedAfter: parsed.waitReceiveObservedAfter } : {},
4234
+ pollMs: parsed.waitPollMs ?? 500,
4235
+ ...parsed.waitReceiveText ? { text: parsed.waitReceiveText } : {},
4236
+ timeoutMs: parsed.waitTimeoutMs ?? 3e4
4237
+ };
4238
+ }
4239
+ function installCliShutdownController(options, daemon) {
4240
+ createRivusDaemonShutdownController({
4241
+ daemon,
4242
+ onError: (error, signal) => {
4243
+ options.stderr.write(formatRivusDaemonShutdownFailure(signal, formatRivusDaemonError(error)));
4244
+ options.exitAfterSignal?.(1);
4245
+ },
4246
+ onStopped: () => {
4247
+ options.exitAfterSignal?.(0);
4248
+ },
4249
+ signalSource: options.signalSource
4250
+ }).install();
4251
+ }
4252
+ function hasStatusReporter(daemon) {
4253
+ return typeof daemon.status === "function";
4254
+ }
4255
+ function hasPromptRunner(daemon) {
4256
+ return typeof daemon.promptText === "function";
4257
+ }
4258
+ function hasFeishuReplayRunner(daemon) {
4259
+ return typeof daemon.replayReceiveMessage === "function";
4260
+ }
4261
+ function hasRecoveryRunner(daemon) {
4262
+ return typeof daemon.openRecoveryControl === "function";
4263
+ }
4264
+ //#endregion
4265
+ //#region src/bootstrap/cli/rivus-cli.ts
4266
+ function runRivusCli(options) {
4267
+ const command = options.argv[0];
4268
+ if (command === "setup") return runSetupCommand(options);
4269
+ if (command === "start") return runHomeDaemonCommand(options, "start", []);
4270
+ if (command === "status") return runHomeDaemonCommand(options, "status", ["--status"]);
4271
+ if (command === "check-config") return runHomeDaemonCommand(options, "check-config", ["--check-config"]);
4272
+ if (command === "init") return runInitCommand(options);
4273
+ if (command === "doctor") return runDoctorCommand(options);
4274
+ if (command === "model") return runModelCommand(options);
4275
+ if (command && !command.startsWith("-")) return Effect.sync(() => {
4276
+ options.stderr.write(renderRivusCliUnknownCommand(command));
4277
+ return 1;
4278
+ });
4279
+ return runRivusDaemonCli(options);
4280
+ }
4281
+ function runModelCommand(options) {
4282
+ const parsed = parseRivusModelCliArguments(options.argv.slice(1));
4283
+ if ("help" in parsed) return Effect.sync(() => {
4284
+ options.stdout.write(renderRivusModelCliHelp());
4285
+ return 0;
4286
+ });
4287
+ if ("error" in parsed) return Effect.sync(() => {
4288
+ options.stderr.write(renderRivusModelCliArgumentError(parsed.error));
4289
+ return 1;
4290
+ });
4291
+ if (parsed.operation !== "status" && !isRivusModelManagementEnabled(options.env)) return Effect.sync(() => {
4292
+ writeModelResponse(options.stdout, {
4293
+ error: {
4294
+ code: "management_disabled",
4295
+ message: "model management is not enabled for this Home"
4296
+ },
4297
+ schemaVersion: 1,
4298
+ status: "failed"
4299
+ });
4300
+ return 1;
4301
+ });
4302
+ const client = options.modelManagementClient ?? createRivusModelManagementSocketClient({
4303
+ env: options.env,
4304
+ socketPath: resolveRivusModelSocketPath({
4305
+ env: options.env,
4306
+ homeDirectory: options.homeDirectory
4307
+ })
4308
+ });
4309
+ return Effect.tryPromise({
4310
+ try: () => client.execute(parsed),
4311
+ catch: (error) => error
4312
+ }).pipe(Effect.tap((response) => Effect.sync(() => writeModelResponse(options.stdout, response))), Effect.map((response) => modelManagementExitCode(response)), Effect.catchAll((error) => Effect.sync(() => {
4313
+ writeModelResponse(options.stdout, modelTransportFailure(error));
4314
+ return 1;
4315
+ })));
4316
+ }
4317
+ function modelManagementExitCode(response) {
4318
+ if (response.status !== "failed") return 0;
4319
+ if (typeof response.requestId === "string" && response.requestId.trim()) return 0;
4320
+ const request = response.request;
4321
+ if (typeof request !== "object" || request === null || Array.isArray(request)) return 1;
4322
+ const requestId = request.requestId;
4323
+ return typeof requestId === "string" && requestId.trim() ? 0 : 1;
4324
+ }
4325
+ function writeModelResponse(stdout, response) {
4326
+ stdout.write(`${JSON.stringify(response)}\n`);
4327
+ }
4328
+ function modelTransportFailure(error) {
4329
+ const code = error instanceof RivusModelManagementTransportError ? error.code : "socket_error";
4330
+ return {
4331
+ error: {
4332
+ code,
4333
+ message: code === "timeout" ? "model management service timed out" : code === "invalid_response" ? "model management returned an invalid response" : "model management service is unavailable"
4334
+ },
4335
+ schemaVersion: 1,
4336
+ status: "failed"
4337
+ };
4338
+ }
4339
+ function runSetupCommand(options) {
4340
+ return withOptionalDirectoryArgument(options, "setup", (argument) => resolveHomeDirectoryEffect(options, argument).pipe(Effect.flatMap((directory) => options.homeApi.setup(directory).pipe(Effect.tap(() => Effect.sync(() => options.stdout.write(renderRivusSetupSuccess(directory)))), Effect.as(0))), Effect.catchAll((error) => writeError(options, error))));
4341
+ }
4342
+ function runHomeDaemonCommand(options, command, daemonArgs) {
4343
+ if (hasRivusHomeCommandArguments(options.argv.slice(1))) return Effect.sync(() => {
4344
+ options.stderr.write(renderRivusHomeCommandUsage(command));
4345
+ return 1;
4346
+ });
4347
+ return resolveHomeDirectoryEffect(options).pipe(Effect.flatMap((directory) => options.homeApi.load(directory)), Effect.tap((home) => Effect.sync(() => options.changeWorkingDirectory(home.workspaceDirectory))), Effect.flatMap((home) => runRivusDaemonCli({
4348
+ ...options,
4349
+ argv: [
4350
+ "--env-file",
4351
+ home.envFilePath,
4352
+ "--bootstrap",
4353
+ home.bootstrap,
4354
+ "--manifest",
4355
+ home.manifestPath,
4356
+ ...daemonArgs
4357
+ ],
4358
+ env: {
4359
+ ...options.env,
4360
+ RIVUS_DEPLOYMENT_STATE_DIR: home.stateDirectory,
4361
+ RIVUS_HOME: home.directory
4362
+ },
4363
+ pluginPackageManifestPath: options.pluginPackageManifestPath ?? gatewayPackageManifestPath
4364
+ })), Effect.catchAll((error) => writeError(options, error)));
4365
+ }
4366
+ function runInitCommand(options) {
4367
+ return withOptionalDirectoryArgument(options, "init", (argument) => {
4368
+ const directory = resolve(options.cwd, argument ?? ".");
4369
+ return Effect.tryPromise({
4370
+ try: () => initializeRivusProject({
4371
+ directory,
4372
+ nodeExecutable: options.nodeExecutable,
4373
+ templateDirectory: gatewayTemplateDirectory
4374
+ }),
4375
+ catch: (error) => error
4376
+ }).pipe(Effect.tap((result) => Effect.sync(() => options.stdout.write(renderRivusProjectInitializationSuccess(result.directory)))), Effect.as(0), Effect.catchAll((error) => writeError(options, error)));
4377
+ });
4378
+ }
4379
+ function withOptionalDirectoryArgument(options, command, run) {
4380
+ const parsed = parseRivusDirectoryArguments(options.argv.slice(1));
4381
+ if (parsed.help) return Effect.sync(() => {
4382
+ options.stdout.write(renderRivusDirectoryCommandUsage(command));
4383
+ return 0;
4384
+ });
4385
+ if (parsed.error) return Effect.sync(() => {
4386
+ options.stderr.write(renderRivusDirectoryCommandUsage(command));
4387
+ return 1;
4388
+ });
4389
+ return run(parsed.directory);
4390
+ }
4391
+ function runDoctorCommand(options) {
4392
+ const parsed = parseRivusDoctorArguments(options.argv.slice(1));
4393
+ if (parsed.help) return Effect.sync(() => {
4394
+ options.stdout.write(renderRivusDoctorUsage());
4395
+ return 0;
4396
+ });
4397
+ if (parsed.error) {
4398
+ const error = parsed.error;
4399
+ return Effect.sync(() => {
4400
+ options.stderr.write(renderRivusDoctorArgumentError(error));
4401
+ return 1;
4402
+ });
4403
+ }
4404
+ if (parsed.directory === void 0) return resolveHomeDirectoryEffect(options).pipe(Effect.flatMap((directory) => options.homeApi.diagnose({
4405
+ directory,
4406
+ env: options.env,
4407
+ ...parsed.envFilePath ? { envFilePath: parsed.envFilePath } : {},
4408
+ nodeVersion: options.nodeVersion
4409
+ })), Effect.map((report) => writeDoctorReport(options.stdout, report, "Home")), Effect.catchAll((error) => writeError(options, error)));
4410
+ const projectDirectory = parsed.directory;
4411
+ return diagnoseRivusProject({
4412
+ directory: resolve(options.cwd, projectDirectory),
4413
+ env: options.env,
4414
+ ...parsed.envFilePath ? { envFilePath: parsed.envFilePath } : {},
4415
+ nodeVersion: options.nodeVersion
4416
+ }).pipe(Effect.map((report) => writeDoctorReport(options.stdout, report, "project")), Effect.catchAll((error) => writeError(options, error)));
4417
+ }
4418
+ function resolveHomeDirectoryEffect(options, argument) {
4419
+ return Effect.try({
4420
+ try: () => {
4421
+ if (argument) return resolve(options.cwd, argument);
4422
+ const configured = options.env.RIVUS_HOME?.trim();
4423
+ if (!configured) return resolve(options.homeDirectory, ".rivus-agent");
4424
+ if (!isAbsolute(configured)) throw new Error("RIVUS_HOME must be an absolute path");
4425
+ return resolve(configured);
4426
+ },
4427
+ catch: (error) => error instanceof Error ? error : new Error(String(error))
4428
+ });
4429
+ }
4430
+ function writeDoctorReport(stdout, report, owner) {
4431
+ for (const chunk of renderRivusDoctorReport(report, owner)) stdout.write(chunk);
4432
+ return report.ready ? 0 : 1;
4433
+ }
4434
+ function writeError(options, error) {
4435
+ return Effect.sync(() => {
4436
+ options.stderr.write(renderRivusCliError(error));
4437
+ return 1;
4438
+ });
4439
+ }
4440
+ //#endregion
4441
+ //#region src/bootstrap/cli/rivus-node-entrypoint.ts
4442
+ function runRivusNodeEntrypoint(options) {
4443
+ return runRivusCli({
4444
+ argv: options.argv,
4445
+ changeWorkingDirectory: options.changeWorkingDirectory,
4446
+ cwd: options.cwd,
4447
+ env: options.env,
4448
+ ...options.exitAfterSignal !== void 0 ? { exitAfterSignal: options.exitAfterSignal } : {},
4449
+ homeApi: createNodeRivusHome({ deploymentInspector: createRivusHomeDeploymentInspector({ packageManifestPath: gatewayPackageManifestPath }) }),
4450
+ homeDirectory: homedir(),
4451
+ loadBootstrap: (specifier) => import(toImportSpecifier(specifier)),
4452
+ nodeExecutable: process.execPath,
4453
+ nodeVersion: process.versions.node,
4454
+ signalSource: options.signalSource,
4455
+ stderr: options.stderr,
4456
+ stdout: options.stdout
4457
+ });
4458
+ }
4459
+ function toImportSpecifier(specifier) {
4460
+ if (specifier.startsWith(".") || specifier.startsWith("/")) return pathToFileURL(resolve(specifier)).href;
4461
+ return specifier;
4462
+ }
4463
+ //#endregion
4464
+ export { InvalidRivusPlugin as A, createRivusHostToolDescriptorProvider as C, validateRivusCatalogIdentifier as D, createRivusPluginCatalog as E, InvalidAgentHostBinding as F, createEffectAgentHost as I, AgentInstanceConflict as L, AgentInstanceBusy as M, AgentRuntimeDisposed as N, validateRivusCatalogRegistration as O, createAgentHostRuntimePool as P, createEffectAgentInstanceRegistry as R, initializeRivusProject as S, createRivusToolGrantSetOperations as T, formatRivusEnvFile as _, resolveRivusProjectSpace as a, loadNodeRivusPluginModule as b, RivusDeploymentReadinessError as c, RivusPluginLoadError as d, resolveRivusDeployment as f, createRivusEnvFromOpenClawConfig as g, OpenClawEnvImportError as h, createRivusDeploymentCliProcess as i, RIVUS_PLUGIN_API_VERSION as j, validateRivusPluginManifest as k, createRivusDeploymentControl as l, createRivusDaemonShutdownController as m, runRivusCli as n, RivusDeploymentAutomationReadinessError as o, createProcessDeploymentControlPorts as p, runRivusDaemonCli as r, RivusDeploymentBackgroundSessionReadinessError as s, runRivusNodeEntrypoint as t, RivusDeploymentDaemonLifecycleError as u, diagnoseRivusProject as v, createRivusAgentCatalog as w, resolveRivusPluginModule as x, createNodeRivusPluginModuleLoader as y };