@rivus/agent 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
+ import { a as createAgentLoopSkillExecutionStart, c as createAgentLoopToolExecutionEnd, d as createAsyncIterableAgentLoop, f as createEventAgentLoop, i as createAgentLoopSkillExecutionEnd, l as createAgentLoopToolExecutionStart, m as createTextAgentLoopFromCallback, n as createAgentLoopModelExecutionEnd, o as createAgentLoopTextDelta, p as createTextAgentLoop, r as createAgentLoopModelExecutionStart, s as createAgentLoopThinkingDelta, t as createAgentLoopFromCallback, u as createAgentLoopToolExecutionUpdate } from "./agent-loop.js";
1
2
  import { a as RIVUS_MEMORY_TOOL_ID, c as createMemoryNamespace, d as InvalidRivusPlugin, f as RIVUS_PLUGIN_API_VERSION, i as MEMORY_SCOPES, l as createRivusMemoryToolContract, m as requiresToolApproval, n as resolveRivusAgentDefinition, o as RIVUS_MEMORY_TOOL_PLUGIN_ID, p as RivusToolInputRejected, s as RIVUS_MEMORY_TOOL_VERSION, t as createRivusPluginCatalog, u as restrictMemoryScopesForAudience } from "./rivus-plugin-registry.js";
2
3
  import { A as loadRivusDeployment, D as resolveFeishuEndpointCredentials, E as FeishuEndpointCredentialError, S as loadNodeRivusPluginModule, T as loadRivusDeploymentManifest, _ as OpenClawEnvImportError, a as RivusDeploymentDaemonLifecycleError, b as RivusDaemonConfigError, c as InvalidRivusEndpointBinding, d as AgentRuntimeDisposed, f as createAgentRuntimePool, g as createRivusDaemonShutdownController, h as createStableId, i as RivusDeploymentAutomationReadinessError, j as validateRivusDeploymentManifest, k as RivusPluginLoadError, l as createRivusAgentHost, m as createAgentInstanceRegistry, n as createRivusDeploymentCliProcess, o as RivusDeploymentReadinessError, p as AgentInstanceConflict, r as createConfiguredRivusDeploymentDaemon, s as createRivusDeploymentDaemon, t as runRivusDaemonCli, u as AgentInstanceBusy, v as createRivusEnvFromOpenClawConfig, w as RivusDeploymentManifestError, x as loadRivusDaemonConfig, y as formatRivusEnvFile } from "./rivus-daemon-cli.js";
3
4
  import { n as assertRivusPluginConforms, r as createFakeRivusPlugin, t as RivusPluginConformanceError } from "./rivus-plugin-testkit.js";
4
- import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
5
5
  import { Cause, Deferred, Effect, Exit, Fiber, Option, Stream } from "effect";
6
- import { appendFile, lstat, mkdir, readFile, readdir, realpath, rename, stat, unlink, writeFile } from "node:fs/promises";
7
6
  import { createHash, randomUUID } from "node:crypto";
7
+ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
8
+ import { appendFile, lstat, mkdir, readFile, readdir, realpath, rename, stat, unlink, writeFile } from "node:fs/promises";
8
9
  import { isDeepStrictEqual } from "node:util";
9
10
  import { createServer } from "node:http";
10
11
  import { Buffer as Buffer$1 } from "node:buffer";
@@ -649,122 +650,6 @@ function assertNonNegativeInteger(value, name) {
649
650
  if (!Number.isSafeInteger(value) || value < 0) throw new Error(`${name} must be a non-negative integer`);
650
651
  }
651
652
  //#endregion
652
- //#region src/application/agent/agent-loop.ts
653
- function createAgentLoopTextDelta(delta) {
654
- return {
655
- delta,
656
- type: "assistant_text_delta"
657
- };
658
- }
659
- function normalizeAgentLoopEvent(event) {
660
- return typeof event === "string" ? createAgentLoopTextDelta(event) : event;
661
- }
662
- function createAgentLoopThinkingDelta(delta) {
663
- return {
664
- delta,
665
- type: "assistant_thinking_delta"
666
- };
667
- }
668
- function createAgentLoopModelExecutionStart(options) {
669
- return {
670
- ...options,
671
- type: "model_execution_start"
672
- };
673
- }
674
- function createAgentLoopModelExecutionEnd(options) {
675
- return {
676
- ...options,
677
- type: "model_execution_end"
678
- };
679
- }
680
- function createAgentLoopSkillExecutionStart(options) {
681
- return {
682
- ...options,
683
- type: "skill_execution_start"
684
- };
685
- }
686
- function createAgentLoopSkillExecutionEnd(options) {
687
- return {
688
- ...options,
689
- type: "skill_execution_end"
690
- };
691
- }
692
- function createAgentLoopToolExecutionStart(options) {
693
- return {
694
- input: options.input,
695
- toolCallId: options.toolCallId,
696
- toolName: options.toolName,
697
- type: "tool_execution_start"
698
- };
699
- }
700
- function createAgentLoopToolExecutionUpdate(options) {
701
- return {
702
- input: options.input,
703
- partialResult: options.partialResult,
704
- toolCallId: options.toolCallId,
705
- toolName: options.toolName,
706
- type: "tool_execution_update"
707
- };
708
- }
709
- function createAgentLoopToolExecutionEnd(options) {
710
- return {
711
- isError: options.isError,
712
- result: options.result,
713
- toolCallId: options.toolCallId,
714
- toolName: options.toolName,
715
- type: "tool_execution_end"
716
- };
717
- }
718
- function createEventAgentLoop(options) {
719
- return { run: (input) => {
720
- const events = typeof options.events === "function" ? options.events(input) : options.events;
721
- if (isPromiseLike(events)) return Stream.fromEffect(Effect.tryPromise({
722
- try: () => events,
723
- catch: (cause) => cause
724
- })).pipe(Stream.flatMap((resolvedEvents) => Stream.fromIterable(resolvedEvents)), Stream.map(normalizeAgentLoopEvent));
725
- return Stream.fromIterable(events).pipe(Stream.map(normalizeAgentLoopEvent));
726
- } };
727
- }
728
- function createAsyncIterableAgentLoop(options) {
729
- return { run: (input) => Stream.fromAsyncIterable(options.run(input), (error) => error).pipe(Stream.map(normalizeAgentLoopEvent)) };
730
- }
731
- function createAgentLoopFromCallback(run) {
732
- return { run: (input) => Stream.fromEffect(Effect.try({
733
- try: () => run(input),
734
- catch: (cause) => cause
735
- })).pipe(Stream.flatMap(streamFromAgentLoopCallbackResult)) };
736
- }
737
- function createTextAgentLoop(options) {
738
- return { run: (input) => Stream.fromEffect(options.generate(input)).pipe(Stream.map((delta) => createAgentLoopTextDelta(delta))) };
739
- }
740
- function createTextAgentLoopFromCallback(generate) {
741
- return createTextAgentLoop({ generate: (input) => Effect.tryPromise({
742
- try: async () => generate(input),
743
- catch: (cause) => cause
744
- }) });
745
- }
746
- function isPromiseLike(value) {
747
- return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
748
- }
749
- function streamFromAgentLoopCallbackResult(result) {
750
- if (Effect.isEffect(result)) return Stream.fromEffect(result).pipe(Stream.flatMap(streamFromAgentLoopCallbackOutput));
751
- if (isPromiseLike(result)) return Stream.fromEffect(Effect.tryPromise({
752
- try: () => Promise.resolve(result),
753
- catch: (cause) => cause
754
- })).pipe(Stream.flatMap(streamFromAgentLoopCallbackOutput));
755
- return streamFromAgentLoopCallbackOutput(result);
756
- }
757
- function streamFromAgentLoopCallbackOutput(output) {
758
- if (isEffectStream(output)) return output.pipe(Stream.map(normalizeAgentLoopEvent));
759
- return (isAsyncIterable(output) ? Stream.fromAsyncIterable(output, (error) => error) : Stream.fromIterable(output)).pipe(Stream.map(normalizeAgentLoopEvent));
760
- }
761
- function isAsyncIterable(value) {
762
- return Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
763
- }
764
- function isEffectStream(value) {
765
- return typeof value === "object" && value !== null && Stream.StreamTypeId in value;
766
- }
767
- //#endregion
768
653
  //#region src/infrastructure/http/json-fetch-request.ts
769
654
  function createJsonFetchRequest(options = {}) {
770
655
  const fetchImpl = options.fetch ?? globalThis.fetch;
@@ -6170,7 +6055,7 @@ function createAutomationMandateStore() {
6170
6055
  //#endregion
6171
6056
  //#region src/application/automation/daily-automation-schedule.ts
6172
6057
  function createDailyAutomationSchedule(expression, timeZone, now = /* @__PURE__ */ new Date()) {
6173
- const { hour, minute } = parseDailySchedule(expression);
6058
+ const { hour, minute, weekdays } = parseDailySchedule(expression);
6174
6059
  try {
6175
6060
  zonedParts(now, timeZone);
6176
6061
  } catch (cause) {
@@ -6179,6 +6064,7 @@ function createDailyAutomationSchedule(expression, timeZone, now = /* @__PURE__
6179
6064
  return Object.freeze({
6180
6065
  currentOccurrence: (at) => {
6181
6066
  const local = zonedParts(at, timeZone);
6067
+ if (!matchesWeekday(local, weekdays)) return void 0;
6182
6068
  const occurrence = zonedMinuteToInstant({
6183
6069
  day: local.day,
6184
6070
  hour,
@@ -6190,36 +6076,49 @@ function createDailyAutomationSchedule(expression, timeZone, now = /* @__PURE__
6190
6076
  },
6191
6077
  nextOccurrence: (at) => {
6192
6078
  const local = zonedParts(at, timeZone);
6193
- const today = zonedMinuteToInstant({
6194
- day: local.day,
6195
- hour,
6196
- minute,
6197
- month: local.month,
6198
- year: local.year
6199
- }, timeZone);
6200
- if (today.getTime() > at.getTime()) return today;
6201
- const nextDate = new Date(Date.UTC(local.year, local.month - 1, local.day) + 864e5);
6202
- return zonedMinuteToInstant({
6203
- day: nextDate.getUTCDate(),
6204
- hour,
6205
- minute,
6206
- month: nextDate.getUTCMonth() + 1,
6207
- year: nextDate.getUTCFullYear()
6208
- }, timeZone);
6079
+ const localDate = Date.UTC(local.year, local.month - 1, local.day);
6080
+ for (let offsetDays = 0; offsetDays <= 7; offsetDays += 1) {
6081
+ const date = new Date(localDate + offsetDays * 864e5);
6082
+ const candidateParts = {
6083
+ day: date.getUTCDate(),
6084
+ hour,
6085
+ minute,
6086
+ month: date.getUTCMonth() + 1,
6087
+ year: date.getUTCFullYear()
6088
+ };
6089
+ if (!matchesWeekday(candidateParts, weekdays)) continue;
6090
+ const candidate = zonedMinuteToInstant(candidateParts, timeZone);
6091
+ if (candidate.getTime() > at.getTime()) return candidate;
6092
+ }
6093
+ throw new Error(`Automation schedule does not resolve within one week: ${expression}`);
6209
6094
  }
6210
6095
  });
6211
6096
  }
6212
6097
  function parseDailySchedule(schedule) {
6213
- const match = /^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+\*$/.exec(schedule.trim());
6098
+ const match = /^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+(\*|1-5)$/.exec(schedule.trim());
6214
6099
  if (!match) throw new Error(`unsupported Automation schedule: ${schedule}`);
6215
6100
  const minute = Number(match[1]);
6216
6101
  const hour = Number(match[2]);
6217
6102
  if (!Number.isInteger(minute) || minute < 0 || minute > 59 || !Number.isInteger(hour) || hour < 0 || hour > 23) throw new Error(`invalid Automation schedule: ${schedule}`);
6218
- return {
6103
+ return match[3] === "1-5" ? {
6104
+ hour,
6105
+ minute,
6106
+ weekdays: /* @__PURE__ */ new Set([
6107
+ 1,
6108
+ 2,
6109
+ 3,
6110
+ 4,
6111
+ 5
6112
+ ])
6113
+ } : {
6219
6114
  hour,
6220
6115
  minute
6221
6116
  };
6222
6117
  }
6118
+ function matchesWeekday(parts, weekdays) {
6119
+ if (!weekdays) return true;
6120
+ return weekdays.has(new Date(Date.UTC(parts.year, parts.month - 1, parts.day)).getUTCDay());
6121
+ }
6223
6122
  function zonedParts(date, timeZone) {
6224
6123
  const parts = new Intl.DateTimeFormat("en-CA", {
6225
6124
  day: "2-digit",
@@ -6311,7 +6210,7 @@ async function executeDue(options, schedule, at, claim) {
6311
6210
  const occurrence = schedule.currentOccurrence(at);
6312
6211
  if (!occurrence) return void 0;
6313
6212
  const tick = claim(occurrence);
6314
- const existing = await options.repository.get(tick.mandateId, occurrence);
6213
+ const existing = await options.repository.get(options.automationId, occurrence);
6315
6214
  if (existing?.status === "delivered") return existing;
6316
6215
  let record = existing;
6317
6216
  if (record?.status !== "generated") {
@@ -6384,15 +6283,18 @@ const systemClock = {
6384
6283
  async function openJsonAutomationTickRepository(options) {
6385
6284
  const records = /* @__PURE__ */ new Map();
6386
6285
  const snapshot = await readSnapshot$1(options.filePath);
6387
- for (const record of snapshot.records) records.set(key(record.mandateId, record.occurrence), record);
6286
+ for (const record of snapshot.records) {
6287
+ const recordKey = key(record.automationId, record.occurrence);
6288
+ records.set(recordKey, preferRecoveryRecord(records.get(recordKey), record));
6289
+ }
6388
6290
  let pendingWrite = Promise.resolve();
6389
6291
  return {
6390
- get: async (mandateId, occurrence) => records.get(key(mandateId, occurrence)),
6292
+ get: async (automationId, occurrence) => records.get(key(automationId, occurrence)),
6391
6293
  put: async (record) => {
6392
6294
  const stored = Object.freeze({ ...record });
6393
6295
  const operation = pendingWrite.then(async () => {
6394
6296
  const next = new Map(records);
6395
- next.set(key(record.mandateId, record.occurrence), stored);
6297
+ next.set(key(record.automationId, record.occurrence), stored);
6396
6298
  await writeSnapshot(options.filePath, [...next.values()]);
6397
6299
  records.clear();
6398
6300
  for (const [recordKey, value] of next) records.set(recordKey, value);
@@ -6407,13 +6309,13 @@ async function readSnapshot$1(filePath) {
6407
6309
  const raw = await readPersistenceFile(filePath);
6408
6310
  if (raw === void 0) return Object.freeze({
6409
6311
  records: Object.freeze([]),
6410
- version: 2
6312
+ version: 3
6411
6313
  });
6412
6314
  const value = JSON.parse(raw);
6413
- if (!isRecord$4(value) || value.version !== 2 || !Array.isArray(value.records)) throw new Error("Automation Tick snapshot must contain version 2 records");
6315
+ if (!isRecord$4(value) || value.version !== 2 && value.version !== 3 || !Array.isArray(value.records)) throw new Error("Automation Tick snapshot must contain version 2 or 3 records");
6414
6316
  return Object.freeze({
6415
6317
  records: Object.freeze(value.records.map(readRecord)),
6416
- version: 2
6318
+ version: value.version
6417
6319
  });
6418
6320
  }
6419
6321
  async function writeSnapshot(filePath, records) {
@@ -6422,7 +6324,7 @@ async function writeSnapshot(filePath, records) {
6422
6324
  try {
6423
6325
  await writeFile(temporaryPath, `${JSON.stringify({
6424
6326
  records,
6425
- version: 2
6327
+ version: 3
6426
6328
  })}\n`, {
6427
6329
  encoding: "utf8",
6428
6330
  flag: "wx"
@@ -6463,8 +6365,20 @@ function readRecord(value) {
6463
6365
  tickId: value.tickId
6464
6366
  });
6465
6367
  }
6466
- function key(mandateId, occurrence) {
6467
- return `${mandateId}\0${occurrence}`;
6368
+ function key(automationId, occurrence) {
6369
+ return `${automationId}\0${occurrence}`;
6370
+ }
6371
+ function preferRecoveryRecord(current, candidate) {
6372
+ if (!current) return candidate;
6373
+ return recoveryRank(candidate.status) >= recoveryRank(current.status) ? candidate : current;
6374
+ }
6375
+ function recoveryRank(status) {
6376
+ switch (status) {
6377
+ case "delivered": return 4;
6378
+ case "generated": return 3;
6379
+ case "failed": return 2;
6380
+ case "running": return 1;
6381
+ }
6468
6382
  }
6469
6383
  function isStatus(value) {
6470
6384
  return value === "running" || value === "failed" || value === "generated" || value === "delivered";
@@ -1,10 +1,10 @@
1
1
  import { i as MEMORY_SCOPES, n as resolveRivusAgentDefinition, r as deepFreeze, t as createRivusPluginCatalog } from "./rivus-plugin-registry.js";
2
2
  import { createRequire } from "node:module";
3
+ import { Effect } from "effect";
4
+ import { createHash, randomUUID } from "node:crypto";
3
5
  import { pathToFileURL } from "node:url";
4
6
  import { dirname, isAbsolute, join, relative, sep } from "node:path";
5
- import { Effect } from "effect";
6
7
  import { open, readFile, realpath, stat } from "node:fs/promises";
7
- import { createHash, randomUUID } from "node:crypto";
8
8
  import { constants } from "node:fs";
9
9
  //#region src/application/plugin/rivus-automation-runtime-definition.ts
10
10
  function resolveRivusAutomationRuntimeDefinition(definition, requestedToolIds, requestedSkillIds) {
@@ -136,6 +136,9 @@ async function loadRivusDeployment(options) {
136
136
  for (const automation of options.manifest.automations ?? []) {
137
137
  const agent = agentStatusById.get(automation.agentId);
138
138
  if (!agent || agent.status === "disabled" || !agent.definition) continue;
139
+ const deliveryEndpoint = options.manifest.endpoints.find(({ id }) => id === automation.delivery.endpointId);
140
+ const presentationAgent = agentStatusById.get(deliveryEndpoint.agentId);
141
+ if (!presentationAgent || presentationAgent.status === "disabled" || !presentationAgent.definition) continue;
139
142
  const template = automationTemplates.get(automation.templateId);
140
143
  if (!template) throw new Error(`automation ${automation.id} references unknown template: ${automation.templateId}`);
141
144
  if (template.pluginId !== agent.pluginId || template.profileId !== agent.profileId) throw new Error(`automation ${automation.id} template is not owned by agent profile ${agent.profileId}`);
@@ -173,11 +176,10 @@ function validateRivusDeploymentManifest(manifest) {
173
176
  for (const automation of manifest.automations ?? []) {
174
177
  if (automationIds.has(automation.id)) throw new Error(`duplicate automation binding: ${automation.id}`);
175
178
  automationIds.add(automation.id);
176
- const agent = agentById.get(automation.agentId);
177
- if (!agent) throw new Error(`automation ${automation.id} references unknown agent: ${automation.agentId}`);
179
+ if (!agentById.get(automation.agentId)) throw new Error(`automation ${automation.id} references unknown agent: ${automation.agentId}`);
178
180
  const endpoint = manifest.endpoints.find(({ id }) => id === automation.delivery.endpointId);
179
181
  if (!endpoint) throw new Error(`automation ${automation.id} references unknown delivery endpoint: ${automation.delivery.endpointId}`);
180
- if (endpoint.agentId !== agent.agentId) throw new Error(`automation ${automation.id} delivery endpoint is bound to a different agent`);
182
+ if (automation.enabled && !endpoint.enabled) throw new Error(`automation ${automation.id} delivery endpoint must be enabled`);
181
183
  }
182
184
  const endpointIds = /* @__PURE__ */ new Set();
183
185
  const sessionNamespaces = /* @__PURE__ */ new Set();
@@ -1067,13 +1069,15 @@ async function createRivusDeploymentDaemon(options) {
1067
1069
  }
1068
1070
  for (const slot of automationSlots) {
1069
1071
  const resolvedDefinition = slot.resolvedDefinition;
1070
- const slotDegraded = await startSlot(slot, slot.agentEnabled && resolvedDefinition !== void 0, async () => {
1072
+ const deliverySlot = slotById.get(slot.definition.delivery.endpointId);
1073
+ const presentationReady = deliverySlot.lifecycle === "running" && (deliverySlot.adapter?.running() ?? false);
1074
+ const slotDegraded = await startSlot(slot, slot.agentEnabled && resolvedDefinition !== void 0 && presentationReady, async () => {
1071
1075
  if (!options.createAutomation) throw new RivusDeploymentDaemonLifecycleError("deployment bootstrap does not provide Automation adapters");
1072
1076
  if (!resolvedDefinition) throw new RivusDeploymentDaemonLifecycleError(`automation definition not resolved: ${slot.definition.id}`);
1073
1077
  return options.createAutomation({
1074
1078
  automationId: slot.definition.id,
1075
1079
  definition: resolvedDefinition,
1076
- deliveryEndpoint: slotById.get(slot.definition.delivery.endpointId).definition,
1080
+ deliveryEndpoint: deliverySlot.definition,
1077
1081
  instanceId: host.resolveAutomation(slot.definition.id).instanceId,
1078
1082
  run: (input) => host.handleAutomation(slot.definition.id, {
1079
1083
  invocation: {
@@ -1,100 +1,5 @@
1
- //#region src/domain/agent-memory.d.ts
2
- declare const MEMORY_SCOPES: readonly ["conversation", "agent-private", "shared-user-profile"];
3
- declare const RIVUS_MEMORY_TOOL_ID = "memory";
4
- declare const RIVUS_MEMORY_TOOL_PLUGIN_ID = "rivus-core";
5
- declare const RIVUS_MEMORY_TOOL_VERSION = "1.0.0";
6
- type MemoryScope = (typeof MEMORY_SCOPES)[number];
7
- type MemoryState = "proposed" | "confirmed" | "superseded" | "tombstoned";
8
- type MemoryInvocationAudience = "group" | "private";
9
- interface AgentMemoryIdentity {
10
- readonly audience: MemoryInvocationAudience;
11
- readonly conversationId?: string;
12
- readonly subjectId: string;
13
- readonly tenantId: string;
14
- }
15
- interface AgentMemoryAuthority extends AgentMemoryIdentity {
16
- readonly scopes: ReadonlyArray<MemoryScope>;
17
- }
18
- interface MemoryBinding {
19
- readonly agentId: string;
20
- readonly conversationId?: string;
21
- readonly scope: MemoryScope;
22
- readonly subjectId: string;
23
- readonly tenantId: string;
24
- }
25
- interface MemoryRecord {
26
- readonly content: string;
27
- readonly conversationSafe: boolean;
28
- readonly id: string;
29
- readonly revision: number;
30
- readonly scope: MemoryScope;
31
- readonly state: MemoryState;
32
- readonly tombstoneReason?: string;
33
- }
34
- interface AgentMemorySnapshot {
35
- readonly binding: MemoryBinding;
36
- readonly record: MemoryRecord;
37
- }
38
- declare function createMemoryNamespace(binding: MemoryBinding): string;
39
- declare function restrictMemoryScopesForAudience(scopes: ReadonlyArray<MemoryScope>, audience: MemoryInvocationAudience): ReadonlyArray<MemoryScope>;
40
- declare function createRivusMemoryToolContract(scopes: ReadonlyArray<MemoryScope>): Readonly<{
41
- description: "Search and read Memory inside Host-bound scopes; propose or request forgetting only in writable private scopes.";
42
- digest: "sha256:rivus-memory-v3";
43
- id: "memory";
44
- idempotency: "required";
45
- inputSchema: Readonly<{
46
- additionalProperties: false;
47
- properties: {
48
- scope?: {
49
- description: string;
50
- enum: ("conversation" | "agent-private" | "shared-user-profile")[];
51
- type: string;
52
- };
53
- command: {
54
- description: string;
55
- enum: string[];
56
- type: string;
57
- };
58
- id: {
59
- description: string;
60
- minLength: number;
61
- type: string;
62
- };
63
- input: {
64
- additionalProperties: boolean;
65
- description: string;
66
- properties: {
67
- content: {
68
- minLength: number;
69
- type: string;
70
- };
71
- };
72
- required: string[];
73
- type: string;
74
- };
75
- query: {
76
- additionalProperties: boolean;
77
- description: string;
78
- properties: {
79
- query: {
80
- type: string;
81
- };
82
- };
83
- required: string[];
84
- type: string;
85
- };
86
- reason: {
87
- description: string;
88
- type: string;
89
- };
90
- };
91
- required: string[];
92
- type: "object";
93
- }>;
94
- risk: "mutate";
95
- version: "1.0.0";
96
- }>;
97
- //#endregion
1
+ import { c as MemoryScope, t as AgentMemoryAuthority } from "./agent-memory.js";
2
+
98
3
  //#region src/domain/rivus-plugin.d.ts
99
4
  declare const RIVUS_PLUGIN_API_VERSION = "1";
100
5
  type RivusToolRisk = "observe" | "mutate" | "irreversible" | "host-control";
@@ -288,4 +193,4 @@ declare class RivusPluginConformanceError extends Error {
288
193
  declare function assertRivusPluginConforms(input: RivusPluginConformanceInput): Promise<RivusPluginConformanceReport>;
289
194
  declare function createFakeRivusPlugin(): RivusPlugin;
290
195
  //#endregion
291
- export { RivusToolExecutionContext as A, AgentMemorySnapshot as B, RivusPluginCatalogSnapshot as C, RivusSkillDescriptor as D, RivusResolvedToolDescriptor as E, RivusToolInputRejected as F, MemoryScope as G, MemoryBinding as H, RivusToolRisk as I, RIVUS_MEMORY_TOOL_PLUGIN_ID as J, MemoryState as K, requiresToolApproval as L, RivusToolFactoryContext as M, RivusToolGrantSet as N, RivusSkillGrantSet as O, RivusToolIdempotency as P, restrictMemoryScopesForAudience as Q, AgentMemoryAuthority as R, RivusPluginCatalog as S, RivusPluginRegistry as T, MemoryInvocationAudience as U, MEMORY_SCOPES as V, MemoryRecord as W, createMemoryNamespace as X, RIVUS_MEMORY_TOOL_VERSION as Y, createRivusMemoryToolContract as Z, RivusAutomationInput as _, assertRivusPluginConforms as a, RivusHostToolDescriptor as b, RIVUS_PLUGIN_API_VERSION as c, RegisteredRivusPlugin as d, RegisteredRivusSkill as f, RivusAgentProfile as g, RivusAgentDeployment as h, RivusPluginLifecycleProbe as i, RivusToolExecutor as j, RivusToolDescriptor as k, RegisteredRivusAgentProfile as l, ResolvedRivusAgentDefinition as m, RivusPluginConformanceInput as n, createFakeRivusPlugin as o, RegisteredRivusTool as p, RIVUS_MEMORY_TOOL_ID as q, RivusPluginConformanceReport as r, InvalidRivusPlugin as s, RivusPluginConformanceError as t, RegisteredRivusAutomation as u, RivusAutomationTemplate as v, RivusPluginManifest as w, RivusPlugin as x, RivusAutomationTickContext as y, AgentMemoryIdentity as z };
196
+ export { RivusToolExecutionContext as A, RivusPluginCatalogSnapshot as C, RivusSkillDescriptor as D, RivusResolvedToolDescriptor as E, RivusToolInputRejected as F, RivusToolRisk as I, requiresToolApproval as L, RivusToolFactoryContext as M, RivusToolGrantSet as N, RivusSkillGrantSet as O, RivusToolIdempotency as P, RivusPluginCatalog as S, RivusPluginRegistry as T, RivusAutomationInput as _, assertRivusPluginConforms as a, RivusHostToolDescriptor as b, RIVUS_PLUGIN_API_VERSION as c, RegisteredRivusPlugin as d, RegisteredRivusSkill as f, RivusAgentProfile as g, RivusAgentDeployment as h, RivusPluginLifecycleProbe as i, RivusToolExecutor as j, RivusToolDescriptor as k, RegisteredRivusAgentProfile as l, ResolvedRivusAgentDefinition as m, RivusPluginConformanceInput as n, createFakeRivusPlugin as o, RegisteredRivusTool as p, RivusPluginConformanceReport as r, InvalidRivusPlugin as s, RivusPluginConformanceError as t, RegisteredRivusAutomation as u, RivusAutomationTemplate as v, RivusPluginManifest as w, RivusPlugin as x, RivusAutomationTickContext as y };
@@ -0,0 +1,93 @@
1
+ export function analyzeAShareBriefing({ overseasEvidence, quotes, sectorEvidence }) {
2
+ return Object.freeze({
3
+ index: Object.freeze(analyzeIndexStructure(quotes)),
4
+ overseas: Object.freeze(analyzeOverseasStructure(overseasEvidence)),
5
+ sector: analyzeSectorStructure(sectorEvidence),
6
+ turnover: quotes
7
+ .filter(({ symbol }) => symbol === "sh000001" || symbol === "sz399001")
8
+ .reduce((sum, quote) => sum + quote.amount, 0)
9
+ });
10
+ }
11
+
12
+ function analyzeIndexStructure(quotes) {
13
+ const direction = readDirection(quotes);
14
+ const ranked = [...quotes].sort((left, right) => right.changePercent - left.changePercent);
15
+ const strongest = ranked[0];
16
+ const weakest = ranked.at(-1);
17
+ const spread = strongest.changePercent - weakest.changePercent;
18
+ const dispersion = spread >= 1.5 ? "结构分化较大" : spread >= 0.75 ? "存在一定分化" : "表现相对同步";
19
+ const average = quotes.reduce((sum, quote) => sum + quote.changePercent, 0) / quotes.length;
20
+ const positive = quotes.filter(({ changePercent }) => changePercent > 0).length;
21
+ const negative = quotes.filter(({ changePercent }) => changePercent < 0).length;
22
+ const strength =
23
+ positive === quotes.length
24
+ ? "四个指数一致收涨,指数层面的风险偏好偏强。"
25
+ : negative === quotes.length
26
+ ? "四个指数一致收跌,指数层面的风险偏好偏弱。"
27
+ : average >= 0.5
28
+ ? "多数指数收涨且平均涨幅偏强,但方向并不完全一致。"
29
+ : average <= -0.5
30
+ ? "多数指数承压且平均跌幅偏弱,仍需防范弱势扩散。"
31
+ : "指数涨跌互现,尚未形成一致的市场方向。";
32
+ const growth = quotes.find(({ name }) => name === "创业板指");
33
+ const largeCap = quotes.find(({ name }) => name === "沪深 300");
34
+ const styleGap = growth.changePercent - largeCap.changePercent;
35
+ const style =
36
+ styleGap >= 0.5
37
+ ? `创业板指较沪深 300 高 ${formatPercentagePoint(styleGap)},成长风格相对占优。`
38
+ : styleGap <= -0.5
39
+ ? `沪深 300 较创业板指高 ${formatPercentagePoint(-styleGap)},大盘风格相对占优。`
40
+ : "创业板指与沪深 300 表现接近,暂未形成清晰的成长/大盘偏向。";
41
+ const risk =
42
+ spread >= 1.5
43
+ ? `最强与最弱指数相差 ${formatPercentagePoint(spread)},单看综合指数可能掩盖明显分化。`
44
+ : `最强与最弱指数相差 ${formatPercentagePoint(spread)},指数间分化暂时可控。`;
45
+ return { direction: `四个宽基指数 ${direction}`, dispersion, risk, strength, strongest, style, weakest };
46
+ }
47
+
48
+ function analyzeOverseasStructure(evidence) {
49
+ if (!evidence) {
50
+ return {
51
+ conclusion: "隔夜海外指数数据不可用,外部风险背景待开盘数据确认",
52
+ direction: undefined,
53
+ inference: "海外指数数据不可用,不补写外部市场判断。"
54
+ };
55
+ }
56
+ const direction = readDirection(evidence.quotes);
57
+ const average = evidence.quotes.reduce((sum, quote) => sum + quote.changePercent, 0) / evidence.quotes.length;
58
+ const conclusion = `隔夜美股 ${direction},外部风险背景${average >= 0.3 ? "偏积极" : average <= -0.3 ? "偏谨慎" : "偏中性"}`;
59
+ const nasdaq = evidence.quotes.find(({ symbol }) => symbol === "usIXIC");
60
+ const sp500 = evidence.quotes.find(({ symbol }) => symbol === "usINX");
61
+ const gap = nasdaq.changePercent - sp500.changePercent;
62
+ const relative =
63
+ gap >= 0.3
64
+ ? `纳斯达克较标普 500 高 ${formatPercentagePoint(gap)},海外科技风险偏好相对更强。`
65
+ : gap <= -0.3
66
+ ? `纳斯达克较标普 500 低 ${formatPercentagePoint(-gap)},海外科技风险偏好相对更弱。`
67
+ : "纳斯达克与标普 500 表现接近,海外科技风格未显示明显偏离。";
68
+ return { conclusion, direction, inference: `${conclusion}。${relative}` };
69
+ }
70
+
71
+ function analyzeSectorStructure(evidence) {
72
+ if (!evidence) return "行业数据不可用,不补写行业主线判断。";
73
+ const leaders = evidence.leaders
74
+ .slice(0, 2)
75
+ .map(({ name }) => name)
76
+ .join("、");
77
+ const laggards = evidence.laggards
78
+ .slice(0, 2)
79
+ .map(({ name }) => name)
80
+ .join("、");
81
+ return `领涨端集中在${leaders},领跌端集中在${laggards};这只描述行业横截面强弱,不构成市场涨跌的驱动归因。`;
82
+ }
83
+
84
+ function readDirection(quotes) {
85
+ const positive = quotes.filter(({ changePercent }) => changePercent > 0).length;
86
+ const negative = quotes.filter(({ changePercent }) => changePercent < 0).length;
87
+ const flat = quotes.length - positive - negative;
88
+ return `${positive} 涨 ${negative} 跌${flat > 0 ? ` ${flat} 平` : ""}`;
89
+ }
90
+
91
+ function formatPercentagePoint(value) {
92
+ return `${value.toFixed(2)} 个百分点`;
93
+ }