@rivus/agent 0.5.2 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
- import { i as MEMORY_SCOPES, n as resolveRivusAgentDefinition, r as deepFreeze, t as createRivusPluginCatalog } from "./rivus-plugin-registry.js";
1
+ import { t as MEMORY_SCOPES } from "./agent-memory.js";
2
+ import { n as resolveRivusAgentDefinition, r as deepFreeze, t as createRivusPluginCatalog } from "./rivus-plugin-registry.js";
2
3
  import { createRequire } from "node:module";
3
4
  import { Effect } from "effect";
4
5
  import { createHash, randomUUID } from "node:crypto";
@@ -313,6 +314,334 @@ function required$1(env, variable) {
313
314
  return value;
314
315
  }
315
316
  //#endregion
317
+ //#region src/domain/card-presentation.ts
318
+ var CardPresentationTransitionDenied = class extends Error {
319
+ name = "CardPresentationTransitionDenied";
320
+ };
321
+ const STREAMING_STATUSES = /* @__PURE__ */ new Set(["streaming", "active"]);
322
+ function createCardPresentationChain(binding) {
323
+ assertTimestamp(binding.createdAt, "presentation creation time");
324
+ assertTimestamp(binding.leaseDeadlineAt, "presentation lease deadline");
325
+ return {
326
+ activeGeneration: 0,
327
+ activePresentationId: binding.presentationId,
328
+ presentations: [{
329
+ cardId: binding.cardId,
330
+ createdAt: binding.createdAt,
331
+ ...binding.elementId === void 0 ? {} : { elementId: binding.elementId },
332
+ generation: 0,
333
+ leaseDeadlineAt: binding.leaseDeadlineAt,
334
+ presentationId: binding.presentationId,
335
+ runId: binding.runId,
336
+ sourceMessageId: binding.sourceMessageId,
337
+ status: "streaming"
338
+ }],
339
+ revision: 1,
340
+ runId: binding.runId
341
+ };
342
+ }
343
+ function activeCardPresentation(chain) {
344
+ const presentation = chain.presentations.find((candidate) => candidate.presentationId === chain.activePresentationId);
345
+ if (!presentation) throw new CardPresentationTransitionDenied(`presentation chain ${chain.runId} has no active presentation`);
346
+ return presentation;
347
+ }
348
+ function acceptsCardPresentationProgress(chain) {
349
+ return STREAMING_STATUSES.has(activeCardPresentation(chain).status);
350
+ }
351
+ function isCardPresentationHandoffDue(chain, now) {
352
+ const presentation = activeCardPresentation(chain);
353
+ return STREAMING_STATUSES.has(presentation.status) && Date.parse(presentation.leaseDeadlineAt) <= Date.parse(now);
354
+ }
355
+ function beginCardPresentationHandoff(chain, handoffAt) {
356
+ assertTimestamp(handoffAt, "handoff time");
357
+ const presentation = activeCardPresentation(chain);
358
+ if (presentation.status === "handoff-pending") return chain;
359
+ if (!STREAMING_STATUSES.has(presentation.status)) throw new CardPresentationTransitionDenied(`presentation ${presentation.presentationId} is ${presentation.status} and cannot start a handoff`);
360
+ return replaceActivePresentation(chain, {
361
+ ...presentation,
362
+ handoffAt,
363
+ status: "handoff-pending"
364
+ });
365
+ }
366
+ function completeCardPresentationHandoff(chain, successor) {
367
+ assertTimestamp(successor.createdAt, "successor creation time");
368
+ assertTimestamp(successor.leaseDeadlineAt, "successor lease deadline");
369
+ const predecessor = activeCardPresentation(chain);
370
+ if (predecessor.status !== "handoff-pending") throw new CardPresentationTransitionDenied(`presentation ${predecessor.presentationId} is ${predecessor.status} and cannot adopt a successor`);
371
+ if (predecessor.successorPresentationId !== void 0) throw new CardPresentationTransitionDenied(`presentation ${predecessor.presentationId} already has successor ${predecessor.successorPresentationId}`);
372
+ const generation = chain.activeGeneration + 1;
373
+ return {
374
+ ...chain,
375
+ activeGeneration: generation,
376
+ activePresentationId: successor.presentationId,
377
+ presentations: [...chain.presentations.map((candidate) => candidate.presentationId === predecessor.presentationId ? {
378
+ ...predecessor,
379
+ status: "closed",
380
+ successorPresentationId: successor.presentationId
381
+ } : candidate), {
382
+ cardId: successor.cardId,
383
+ createdAt: successor.createdAt,
384
+ ...successor.elementId === void 0 ? {} : { elementId: successor.elementId },
385
+ generation,
386
+ leaseDeadlineAt: successor.leaseDeadlineAt,
387
+ predecessorPresentationId: predecessor.presentationId,
388
+ presentationId: successor.presentationId,
389
+ runId: chain.runId,
390
+ sourceMessageId: predecessor.sourceMessageId,
391
+ status: "active"
392
+ }],
393
+ revision: chain.revision + 1
394
+ };
395
+ }
396
+ function failCardPresentationHandoff(chain, failedAt) {
397
+ assertTimestamp(failedAt, "handoff failure time");
398
+ const presentation = activeCardPresentation(chain);
399
+ if (presentation.status !== "handoff-pending") throw new CardPresentationTransitionDenied(`presentation ${presentation.presentationId} is ${presentation.status} and has no pending handoff`);
400
+ return replaceActivePresentation(chain, {
401
+ ...presentation,
402
+ handoffFailedAt: failedAt,
403
+ status: "closed"
404
+ });
405
+ }
406
+ function compensateCardPresentationHandoff(chain, compensatedAt) {
407
+ return activeCardPresentation(chain).status === "handoff-pending" ? failCardPresentationHandoff(chain, compensatedAt) : chain;
408
+ }
409
+ function markCardPresentationTerminal(chain, terminalReceiptId) {
410
+ if (terminalReceiptId.trim().length === 0) throw new CardPresentationTransitionDenied("terminal receipt id must not be empty");
411
+ const presentation = activeCardPresentation(chain);
412
+ if (presentation.status === "terminal") return chain;
413
+ return replaceActivePresentation(chain, {
414
+ ...presentation,
415
+ status: "terminal",
416
+ terminalReceiptId
417
+ });
418
+ }
419
+ function replaceActivePresentation(chain, presentation) {
420
+ return {
421
+ ...chain,
422
+ presentations: chain.presentations.map((candidate) => candidate.presentationId === presentation.presentationId ? presentation : candidate),
423
+ revision: chain.revision + 1
424
+ };
425
+ }
426
+ function assertTimestamp(value, label) {
427
+ if (Number.isNaN(Date.parse(value))) throw new CardPresentationTransitionDenied(`${label} must be an ISO timestamp`);
428
+ }
429
+ //#endregion
430
+ //#region src/application/feishu/feishu-card-rollover.ts
431
+ const DEFAULT_CARD_STREAM_LEASE_MS = 51e4;
432
+ function createFeishuCardRollover(options) {
433
+ const leaseMs = options.leaseMs ?? 51e4;
434
+ if (!Number.isSafeInteger(leaseMs) || leaseMs < 1) throw new Error("Feishu card stream lease must be a positive integer");
435
+ const counters = createCounters();
436
+ const liveRuns = /* @__PURE__ */ new Map();
437
+ const semaphore = Effect.unsafeMakeSemaphore(1);
438
+ const exclusive = (effect) => semaphore.withPermits(1)(effect);
439
+ const record = (event, at) => {
440
+ counters[event.type] += 1;
441
+ options.observe?.({
442
+ ...event,
443
+ at: at.toISOString()
444
+ });
445
+ };
446
+ const recordNow = (event) => options.clock.now.pipe(Effect.map((at) => record(event, at)));
447
+ const leaseDeadline = (at) => new Date(at.getTime() + leaseMs).toISOString();
448
+ const presentationId = (runId, generation) => `${runId}#${generation}`;
449
+ const publishProgress = (action) => Effect.suspend(() => {
450
+ const chain = options.store.chain(action.runId);
451
+ if (chain && acceptsCardPresentationProgress(chain)) return options.publisher.publish(action);
452
+ return recordNow({
453
+ ...chain ? {
454
+ generation: chain.activeGeneration,
455
+ presentationId: chain.activePresentationId
456
+ } : {},
457
+ runId: action.runId,
458
+ type: "stale_update_dropped"
459
+ });
460
+ });
461
+ const publishTerminal = (action) => options.publisher.publish(action).pipe(Effect.tapError((error) => recordNow({
462
+ error,
463
+ runId: action.runId,
464
+ type: "terminal_delivery_failed"
465
+ })), Effect.tap(() => options.store.markTerminal({
466
+ runId: action.runId,
467
+ terminalReceiptId: `${action.runId}:${action.type}`
468
+ }).pipe(Effect.catchAll((error) => recordNow({
469
+ error,
470
+ runId: action.runId,
471
+ type: "presentation_write_failed"
472
+ })))), Effect.ensuring(Effect.sync(() => {
473
+ liveRuns.delete(action.runId);
474
+ })));
475
+ const publishAction = (action) => {
476
+ switch (action.type) {
477
+ case "update_text": return publishProgress(action);
478
+ case "handoff": return options.publisher.publish(action);
479
+ default: return publishTerminal(action);
480
+ }
481
+ };
482
+ const runHandoff = (runId) => Effect.gen(function* () {
483
+ const run = liveRuns.get(runId);
484
+ if (!run) return {
485
+ reason: "not-live",
486
+ status: "skipped"
487
+ };
488
+ const startedAt = yield* options.clock.now;
489
+ const chain = options.store.chain(runId);
490
+ if (!chain || !isCardPresentationHandoffDue(chain, startedAt.toISOString())) return {
491
+ reason: "not-due",
492
+ status: "skipped"
493
+ };
494
+ const start = yield* options.store.beginHandoff({
495
+ handoffAt: startedAt.toISOString(),
496
+ runId
497
+ }).pipe(Effect.catchAll(() => Effect.succeed(void 0)));
498
+ if (!start) return {
499
+ reason: "not-streaming",
500
+ status: "skipped"
501
+ };
502
+ if (!start.started) return {
503
+ reason: "already-pending",
504
+ status: "skipped"
505
+ };
506
+ const predecessor = start.presentation;
507
+ const generation = predecessor.generation + 1;
508
+ record({
509
+ cardId: predecessor.cardId,
510
+ generation,
511
+ presentationId: predecessor.presentationId,
512
+ runId,
513
+ sourceMessageId: predecessor.sourceMessageId,
514
+ type: "handoff_started"
515
+ }, startedAt);
516
+ const successorId = presentationId(runId, generation);
517
+ const created = yield* options.createSuccessor({
518
+ generation,
519
+ presentationId: successorId,
520
+ run
521
+ }).pipe(Effect.map((target) => ({ target })), Effect.catchAll((error) => options.store.failHandoff({
522
+ failedAt: startedAt.toISOString(),
523
+ runId
524
+ }).pipe(Effect.catchAll((storeError) => recordNow({
525
+ error: storeError,
526
+ runId,
527
+ type: "presentation_write_failed"
528
+ })), Effect.flatMap(() => recordNow({
529
+ cardId: predecessor.cardId,
530
+ error,
531
+ generation,
532
+ presentationId: predecessor.presentationId,
533
+ runId,
534
+ type: "handoff_failed"
535
+ })), Effect.as({ error }))));
536
+ if ("error" in created) return {
537
+ error: created.error,
538
+ status: "failed"
539
+ };
540
+ yield* options.publisher.publish({
541
+ runId,
542
+ type: "handoff"
543
+ }).pipe(Effect.catchAll((error) => recordNow({
544
+ cardId: predecessor.cardId,
545
+ error,
546
+ generation,
547
+ runId,
548
+ type: "handoff_notice_failed"
549
+ })));
550
+ const adoptedAt = yield* options.clock.now;
551
+ const presentation = yield* options.store.completeHandoff({
552
+ runId,
553
+ successor: {
554
+ cardId: created.target.cardId,
555
+ createdAt: adoptedAt.toISOString(),
556
+ ...created.target.elementId === void 0 ? {} : { elementId: created.target.elementId },
557
+ leaseDeadlineAt: leaseDeadline(adoptedAt),
558
+ presentationId: successorId
559
+ }
560
+ });
561
+ record({
562
+ cardId: predecessor.cardId,
563
+ generation,
564
+ presentationId: successorId,
565
+ runId,
566
+ sourceMessageId: predecessor.sourceMessageId,
567
+ successorCardId: created.target.cardId,
568
+ type: "handoff_succeeded"
569
+ }, adoptedAt);
570
+ return {
571
+ presentation,
572
+ status: "rolled-over"
573
+ };
574
+ });
575
+ return {
576
+ bindRun: (run, target) => exclusive(Effect.gen(function* () {
577
+ const createdAt = yield* options.clock.now;
578
+ const presentation = yield* options.store.bind({
579
+ cardId: target.cardId,
580
+ createdAt: createdAt.toISOString(),
581
+ ...target.elementId === void 0 ? {} : { elementId: target.elementId },
582
+ leaseDeadlineAt: leaseDeadline(createdAt),
583
+ presentationId: presentationId(run.runId, 0),
584
+ runId: run.runId,
585
+ sourceMessageId: run.messageId
586
+ });
587
+ liveRuns.set(run.runId, run);
588
+ return presentation;
589
+ })),
590
+ dueRunIds: (now) => {
591
+ const nowIso = now.toISOString();
592
+ return [...liveRuns.keys()].filter((runId) => {
593
+ const chain = options.store.chain(runId);
594
+ return chain !== void 0 && isCardPresentationHandoffDue(chain, nowIso);
595
+ });
596
+ },
597
+ flush: (runId) => exclusive(options.publisher.flush(runId)),
598
+ handoff: (runId) => exclusive(runHandoff(runId)),
599
+ observeStreamClosed: (cardId) => {
600
+ counters.stream_closed += 1;
601
+ options.observe?.({
602
+ cardId,
603
+ type: "stream_closed"
604
+ });
605
+ },
606
+ publish: (action) => exclusive(publishAction(action)),
607
+ releaseRun: (runId) => Effect.sync(() => {
608
+ liveRuns.delete(runId);
609
+ }),
610
+ recover: () => exclusive(Effect.gen(function* () {
611
+ const compensatedAt = yield* options.clock.now;
612
+ const compensated = yield* options.store.compensateInterruptedHandoffs(compensatedAt.toISOString());
613
+ for (const chain of compensated) record({
614
+ generation: chain.activeGeneration,
615
+ presentationId: chain.activePresentationId,
616
+ runId: chain.runId,
617
+ type: "handoff_failed"
618
+ }, compensatedAt);
619
+ return { compensated: compensated.length };
620
+ })),
621
+ status: () => ({
622
+ counters: { ...counters },
623
+ leaseMs,
624
+ live: [...liveRuns.keys()].flatMap((runId) => {
625
+ const chain = options.store.chain(runId);
626
+ if (!chain) return [];
627
+ return chain.presentations.filter((presentation) => presentation.presentationId === chain.activePresentationId);
628
+ })
629
+ })
630
+ };
631
+ }
632
+ function createCounters() {
633
+ return {
634
+ handoff_failed: 0,
635
+ handoff_notice_failed: 0,
636
+ handoff_started: 0,
637
+ handoff_succeeded: 0,
638
+ presentation_write_failed: 0,
639
+ stale_update_dropped: 0,
640
+ stream_closed: 0,
641
+ terminal_delivery_failed: 0
642
+ };
643
+ }
644
+ //#endregion
316
645
  //#region src/infrastructure/config/rivus-deployment-manifest.ts
317
646
  var RivusDeploymentManifestError = class extends Error {
318
647
  manifestPath;
@@ -397,6 +726,7 @@ function parseManifest(value) {
397
726
  exactKeys(endpoint, [
398
727
  "agentId",
399
728
  "baseUrl",
729
+ "cardStreamLeaseMs",
400
730
  "credentialRef",
401
731
  "enabled",
402
732
  "experimental",
@@ -405,12 +735,13 @@ function parseManifest(value) {
405
735
  "required",
406
736
  "sessionNamespace",
407
737
  "streamMinIntervalMs"
408
- ], `manifest.endpoints[${index}]`, ["experimental"]);
738
+ ], `manifest.endpoints[${index}]`, ["cardStreamLeaseMs", "experimental"]);
409
739
  const experimental = endpoint.experimental === void 0 ? void 0 : record(endpoint.experimental, `manifest.endpoints[${index}].experimental`);
410
740
  if (experimental) exactKeys(experimental, ["cotMessages"], `manifest.endpoints[${index}].experimental`);
411
741
  return Object.freeze({
412
742
  agentId: string(endpoint.agentId, `manifest.endpoints[${index}].agentId`),
413
743
  baseUrl: string(endpoint.baseUrl, `manifest.endpoints[${index}].baseUrl`),
744
+ cardStreamLeaseMs: endpoint.cardStreamLeaseMs === void 0 ? DEFAULT_CARD_STREAM_LEASE_MS : positiveInteger(endpoint.cardStreamLeaseMs, `manifest.endpoints[${index}].cardStreamLeaseMs`),
414
745
  credentialRef: string(endpoint.credentialRef, `manifest.endpoints[${index}].credentialRef`),
415
746
  enabled: boolean(endpoint.enabled, `manifest.endpoints[${index}].enabled`),
416
747
  ...experimental ? { experimental: Object.freeze({ cotMessages: boolean(experimental.cotMessages, `manifest.endpoints[${index}].experimental.cotMessages`) }) } : {},
@@ -561,6 +892,7 @@ function loadRivusDaemonConfig(env, options = {}) {
561
892
  const appId = yield* required(env, "FEISHU_APP_ID");
562
893
  const appSecret = yield* required(env, "FEISHU_APP_SECRET");
563
894
  const streamMinIntervalMs = yield* optionalPositiveInteger(env.FEISHU_STREAM_MIN_INTERVAL_MS, "FEISHU_STREAM_MIN_INTERVAL_MS", DEFAULT_STREAM_MIN_INTERVAL_MS$1);
895
+ const cardStreamLeaseMs = yield* optionalPositiveInteger(env.FEISHU_CARD_STREAM_LEASE_MS, "FEISHU_CARD_STREAM_LEASE_MS", DEFAULT_CARD_STREAM_LEASE_MS);
564
896
  const thinkingLevel = yield* optionalThinkingLevel(env.PI_THINKING_LEVEL);
565
897
  const apiKey = yield* optionalPiApiKey(env, options.readTextFile ?? readUtf8File);
566
898
  const baseUrl = optional(env.PI_BASE_URL);
@@ -571,6 +903,7 @@ function loadRivusDaemonConfig(env, options = {}) {
571
903
  appId,
572
904
  appSecret,
573
905
  baseUrl: optional(env.FEISHU_BASE_URL) ?? DEFAULT_FEISHU_BASE_URL$1,
906
+ cardStreamLeaseMs,
574
907
  streamMinIntervalMs
575
908
  },
576
909
  pi: {
@@ -1670,6 +2003,7 @@ Options:
1670
2003
  Environment:
1671
2004
  RIVUS_BOOTSTRAP_MODULE may be used instead of --bootstrap.
1672
2005
  FEISHU_APP_ID and FEISHU_APP_SECRET are required by the default config loader.
2006
+ FEISHU_CARD_STREAM_LEASE_MS shortens or extends the proactive CardKit rollover threshold.
1673
2007
  PI_API_KEY_FILE may point to a local BYOK key file instead of PI_API_KEY.
1674
2008
  `;
1675
2009
  const DEFAULT_WAIT_RECEIVE_TIMEOUT_MS = 3e4;
@@ -2587,6 +2921,7 @@ function toRedactedConfig(config) {
2587
2921
  appIdPresent: Boolean(config.feishu.appId),
2588
2922
  appSecretPresent: Boolean(config.feishu.appSecret),
2589
2923
  baseUrl: config.feishu.baseUrl,
2924
+ cardStreamLeaseMs: config.feishu.cardStreamLeaseMs,
2590
2925
  streamMinIntervalMs: config.feishu.streamMinIntervalMs
2591
2926
  },
2592
2927
  pi: {
@@ -2760,4 +3095,4 @@ function hasRecoveryRunner(daemon) {
2760
3095
  return typeof daemon.openRecoveryControl === "function";
2761
3096
  }
2762
3097
  //#endregion
2763
- export { loadMergedLocalEnvFile as A, loadRivusDaemonConfig as C, loadRivusDeploymentManifest as D, RivusDeploymentManifestError as E, loadRivusDeployment as M, validateRivusDeploymentManifest as N, FeishuEndpointCredentialError as O, RivusDaemonConfigError as S, resolveNodeRivusPluginModulePath as T, createStableId as _, InvalidRivusProjectSpace as a, createRivusEnvFromOpenClawConfig as b, RivusDeploymentReadinessError as c, createRivusAgentHost as d, AgentInstanceBusy as f, createAgentInstanceRegistry as g, AgentInstanceConflict as h, resolveRivusProjectSpace as i, RivusPluginLoadError as j, resolveFeishuEndpointCredentials as k, createRivusDeploymentDaemon as l, createAgentRuntimePool as m, createRivusDeploymentCliProcess as n, RivusDeploymentAutomationReadinessError as o, AgentRuntimeDisposed as p, createConfiguredRivusDeploymentDaemon as r, RivusDeploymentDaemonLifecycleError as s, runRivusDaemonCli as t, InvalidRivusEndpointBinding as u, createRivusDaemonShutdownController as v, loadNodeRivusPluginModule as w, formatRivusEnvFile as x, OpenClawEnvImportError as y };
3098
+ export { CardPresentationTransitionDenied as A, FeishuEndpointCredentialError as B, loadRivusDaemonConfig as C, loadRivusDeploymentManifest as D, RivusDeploymentManifestError as E, completeCardPresentationHandoff as F, validateRivusDeploymentManifest as G, loadMergedLocalEnvFile as H, createCardPresentationChain as I, failCardPresentationHandoff as L, activeCardPresentation as M, beginCardPresentationHandoff as N, DEFAULT_CARD_STREAM_LEASE_MS as O, compensateCardPresentationHandoff as P, isCardPresentationHandoffDue as R, RivusDaemonConfigError as S, resolveNodeRivusPluginModulePath as T, RivusPluginLoadError as U, resolveFeishuEndpointCredentials as V, loadRivusDeployment as W, createStableId as _, InvalidRivusProjectSpace as a, createRivusEnvFromOpenClawConfig as b, RivusDeploymentReadinessError as c, createRivusAgentHost as d, AgentInstanceBusy as f, createAgentInstanceRegistry as g, AgentInstanceConflict as h, resolveRivusProjectSpace as i, acceptsCardPresentationProgress as j, createFeishuCardRollover as k, createRivusDeploymentDaemon as l, createAgentRuntimePool as m, createRivusDeploymentCliProcess as n, RivusDeploymentAutomationReadinessError as o, AgentRuntimeDisposed as p, createConfiguredRivusDeploymentDaemon as r, RivusDeploymentDaemonLifecycleError as s, runRivusDaemonCli as t, InvalidRivusEndpointBinding as u, createRivusDaemonShutdownController as v, loadNodeRivusPluginModule as w, formatRivusEnvFile as x, OpenClawEnvImportError as y, markCardPresentationTerminal as z };
@@ -1,117 +1,5 @@
1
+ import { c as InvalidRivusPlugin, o as createRivusMemoryToolContract, r as RIVUS_MEMORY_TOOL_PLUGIN_ID, t as MEMORY_SCOPES } from "./agent-memory.js";
1
2
  import { createHash } from "node:crypto";
2
- //#region src/domain/rivus-plugin.ts
3
- const RIVUS_PLUGIN_API_VERSION = "1";
4
- function requiresToolApproval(risk) {
5
- return risk === "irreversible" || risk === "host-control";
6
- }
7
- var RivusToolInputRejected = class extends Error {
8
- name = "RivusToolInputRejected";
9
- };
10
- var InvalidRivusPlugin = class extends Error {
11
- name = "InvalidRivusPlugin";
12
- };
13
- //#endregion
14
- //#region src/domain/agent-memory.ts
15
- const MEMORY_SCOPES = [
16
- "conversation",
17
- "agent-private",
18
- "project",
19
- "shared-user-profile"
20
- ];
21
- const RIVUS_MEMORY_TOOL_ID = "memory";
22
- const RIVUS_MEMORY_TOOL_PLUGIN_ID = "rivus-core";
23
- const RIVUS_MEMORY_TOOL_VERSION = "1.0.0";
24
- function createMemoryNamespace(binding) {
25
- const encode = (value) => encodeURIComponent(value);
26
- switch (binding.scope) {
27
- case "conversation": return [
28
- binding.tenantId,
29
- binding.agentId,
30
- binding.subjectId,
31
- binding.conversationId ?? "",
32
- binding.scope
33
- ].map(encode).join("/");
34
- case "agent-private": return [
35
- binding.tenantId,
36
- binding.agentId,
37
- binding.subjectId,
38
- binding.scope
39
- ].map(encode).join("/");
40
- case "project": return [
41
- binding.tenantId,
42
- binding.agentId,
43
- binding.projectId ?? "",
44
- binding.scope
45
- ].map(encode).join("/");
46
- case "shared-user-profile": return [
47
- binding.tenantId,
48
- binding.subjectId,
49
- binding.scope
50
- ].map(encode).join("/");
51
- }
52
- }
53
- function restrictMemoryScopesForAudience(scopes, audience) {
54
- return audience === "group" ? scopes.filter((scope) => scope === "conversation" || scope === "project") : [...scopes];
55
- }
56
- function createRivusMemoryToolContract(scopes) {
57
- return Object.freeze({
58
- description: "Search and read Memory inside Host-bound scopes; propose or request forgetting only in writable private scopes.",
59
- digest: "sha256:rivus-memory-v3",
60
- id: RIVUS_MEMORY_TOOL_ID,
61
- idempotency: "required",
62
- inputSchema: Object.freeze({
63
- additionalProperties: false,
64
- properties: {
65
- command: {
66
- description: "One of search, read, propose, or forget_request.",
67
- enum: [
68
- "search",
69
- "read",
70
- "propose",
71
- "forget_request"
72
- ],
73
- type: "string"
74
- },
75
- id: {
76
- description: "Required for read and forget_request.",
77
- minLength: 1,
78
- type: "string"
79
- },
80
- input: {
81
- additionalProperties: false,
82
- description: "Required for propose.",
83
- properties: { content: {
84
- minLength: 1,
85
- type: "string"
86
- } },
87
- required: ["content"],
88
- type: "object"
89
- },
90
- query: {
91
- additionalProperties: false,
92
- description: "Required for search.",
93
- properties: { query: { type: "string" } },
94
- required: ["query"],
95
- type: "object"
96
- },
97
- reason: {
98
- description: "Optional reason for forget_request.",
99
- type: "string"
100
- },
101
- ...scopes.length === 0 ? {} : { scope: {
102
- description: "Optional Host-granted scope for search or propose. Confirmed Project and Shared User Profile Memory are read-only to the model.",
103
- enum: [...scopes],
104
- type: "string"
105
- } }
106
- },
107
- required: ["command"],
108
- type: "object"
109
- }),
110
- risk: "mutate",
111
- version: RIVUS_MEMORY_TOOL_VERSION
112
- });
113
- }
114
- //#endregion
115
3
  //#region src/application/plugin/deep-freeze.ts
116
4
  function deepFreeze(value) {
117
5
  if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
@@ -321,4 +209,4 @@ function stableJson(value) {
321
209
  return JSON.stringify(value);
322
210
  }
323
211
  //#endregion
324
- export { RIVUS_MEMORY_TOOL_ID as a, createMemoryNamespace as c, InvalidRivusPlugin as d, RIVUS_PLUGIN_API_VERSION as f, MEMORY_SCOPES as i, createRivusMemoryToolContract as l, requiresToolApproval as m, resolveRivusAgentDefinition as n, RIVUS_MEMORY_TOOL_PLUGIN_ID as o, RivusToolInputRejected as p, deepFreeze as r, RIVUS_MEMORY_TOOL_VERSION as s, createRivusPluginCatalog as t, restrictMemoryScopesForAudience as u };
212
+ export { resolveRivusAgentDefinition as n, deepFreeze as r, createRivusPluginCatalog as t };