@rivus/agent 0.6.2 → 0.7.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/README.md +12 -0
- package/dist/agent-loop.d.ts +10 -1
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +477 -2
- package/dist/index.js +1540 -66
- package/dist/pi-tool-proxy.d.ts +3 -0
- package/dist/pi.js +3 -0
- package/dist/rivus-daemon-cli.js +133 -7
- package/dist/rivus-plugin-registry.js +227 -3
- package/dist/rivus-plugin.d.ts +8 -0
- package/dist/tool-input-digest.js +2 -0
- package/examples/pi-feishu-deployment.bootstrap.ts +187 -4
- package/package.json +1 -1
package/dist/pi-tool-proxy.d.ts
CHANGED
|
@@ -94,6 +94,9 @@ interface InvocationAuthorityRef {
|
|
|
94
94
|
}
|
|
95
95
|
interface InvocationAuthority {
|
|
96
96
|
readonly agentId: string;
|
|
97
|
+
readonly allowedActorOpenIds?: ReadonlyArray<string>;
|
|
98
|
+
readonly conversationId?: string;
|
|
99
|
+
readonly endpointId?: string;
|
|
97
100
|
readonly instanceId: string;
|
|
98
101
|
readonly memory?: AgentMemoryAuthority;
|
|
99
102
|
readonly runId: string;
|
package/dist/pi.js
CHANGED
|
@@ -88,6 +88,9 @@ function createPiToolProxyDefinitions(options) {
|
|
|
88
88
|
const result = await options.broker.execute({
|
|
89
89
|
authority: createInvocationAuthority({
|
|
90
90
|
agentId: options.agentId,
|
|
91
|
+
allowedActorOpenIds: invocation.allowedActorOpenIds,
|
|
92
|
+
...invocation.memory?.conversationId ? { conversationId: invocation.memory.conversationId } : {},
|
|
93
|
+
endpointId: invocation.endpointId,
|
|
91
94
|
instanceId: options.instanceId,
|
|
92
95
|
...invocation.memory ? { memory: {
|
|
93
96
|
...invocation.memory,
|
package/dist/rivus-daemon-cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
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
|
+
import { h as narrowBackgroundSessionDefinition, n as resolveRivusAgentDefinition, r as deepFreeze, t as createRivusPluginCatalog } from "./rivus-plugin-registry.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { Effect } from "effect";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -109,7 +109,7 @@ async function loadRivusDeployment(options) {
|
|
|
109
109
|
continue;
|
|
110
110
|
}
|
|
111
111
|
try {
|
|
112
|
-
const baseDefinition = resolveRivusAgentDefinition(catalog, agent);
|
|
112
|
+
const baseDefinition = resolveRivusAgentDefinition(catalog, agent, { backgroundSessions: options.manifest.backgroundSessions?.enabled === true });
|
|
113
113
|
const projectSpace = agent.projectSpaceId ? options.manifest.projectSpaces?.find(({ id }) => id === agent.projectSpaceId) : void 0;
|
|
114
114
|
const definition = projectSpace ? deepFreeze({
|
|
115
115
|
...baseDefinition,
|
|
@@ -224,6 +224,13 @@ function validateRivusDeploymentManifest(manifest) {
|
|
|
224
224
|
if (!defaultEndpoint) throw new Error(`default endpoint does not exist: ${manifest.defaultEndpointId}`);
|
|
225
225
|
if (defaultEndpoint.agentId !== defaultAgent.agentId) throw new Error("default endpoint is not bound to the default agent");
|
|
226
226
|
if (!defaultEndpoint.enabled) throw new Error("default endpoint must be enabled");
|
|
227
|
+
if (manifest.backgroundSessions) validateBackgroundSessions(manifest.backgroundSessions);
|
|
228
|
+
}
|
|
229
|
+
function validateBackgroundSessions(config) {
|
|
230
|
+
if (config.required && !config.enabled) throw new Error("backgroundSessions.required requires backgroundSessions.enabled");
|
|
231
|
+
if (config.leaseRenewalIntervalMs >= config.leaseMs) throw new Error("backgroundSessions.leaseRenewalIntervalMs must be shorter than leaseMs");
|
|
232
|
+
if (config.stepTimeoutMs <= 0 || config.maxConcurrentSessions <= 0 || config.leaseMs <= 0) throw new Error("backgroundSessions durations and concurrency must be positive");
|
|
233
|
+
if (config.retryBackoffMs <= 0 || config.sessionLifetimeMs <= 0 || config.maxConsecutiveFailures <= 0) throw new Error("backgroundSessions retry and lifetime limits must be positive");
|
|
227
234
|
}
|
|
228
235
|
function validateRelativeProjectPath(value, owner) {
|
|
229
236
|
if (value.trim() === "" || isAbsolute(value) || value.includes("\0")) throw new Error(`${owner} must be a non-empty relative path`);
|
|
@@ -656,6 +663,19 @@ function createCounters() {
|
|
|
656
663
|
};
|
|
657
664
|
}
|
|
658
665
|
//#endregion
|
|
666
|
+
//#region src/application/background-session/background-session-config.ts
|
|
667
|
+
const DEFAULT_BACKGROUND_SESSION_STEP_TIMEOUT_MS = 300 * 1e3;
|
|
668
|
+
const DEFAULT_BACKGROUND_SESSION_MAX_CONCURRENT_SESSIONS = 4;
|
|
669
|
+
const DEFAULT_BACKGROUND_SESSION_LEASE_MS = 3e4;
|
|
670
|
+
const DEFAULT_BACKGROUND_SESSION_LEASE_RENEWAL_INTERVAL_MS = 1e4;
|
|
671
|
+
const DEFAULT_BACKGROUND_SESSION_MAX_CONSECUTIVE_FAILURES = 3;
|
|
672
|
+
const DEFAULT_BACKGROUND_SESSION_RETRY_BACKOFF_MS = 3e4;
|
|
673
|
+
const DEFAULT_BACKGROUND_SESSION_LIFETIME_MS = 1440 * 60 * 1e3;
|
|
674
|
+
const DEFAULT_BACKGROUND_SESSION_SUPERVISOR_INTERVAL_MS = 1e3;
|
|
675
|
+
function resolveBackgroundSessionSupervisorIntervalMs(leaseMs) {
|
|
676
|
+
return Math.min(5e3, Math.max(200, Math.floor(leaseMs / 10)));
|
|
677
|
+
}
|
|
678
|
+
//#endregion
|
|
659
679
|
//#region src/infrastructure/config/rivus-deployment-manifest.ts
|
|
660
680
|
var RivusDeploymentManifestError = class extends Error {
|
|
661
681
|
manifestPath;
|
|
@@ -684,12 +704,17 @@ function parseManifest(value) {
|
|
|
684
704
|
exactKeys(root, [
|
|
685
705
|
"agents",
|
|
686
706
|
"automations",
|
|
707
|
+
"backgroundSessions",
|
|
687
708
|
"defaultAgentId",
|
|
688
709
|
"defaultEndpointId",
|
|
689
710
|
"endpoints",
|
|
690
711
|
"plugins",
|
|
691
712
|
"projectSpaces"
|
|
692
|
-
], "manifest", [
|
|
713
|
+
], "manifest", [
|
|
714
|
+
"automations",
|
|
715
|
+
"backgroundSessions",
|
|
716
|
+
"projectSpaces"
|
|
717
|
+
]);
|
|
693
718
|
const plugins = array(root.plugins, "manifest.plugins").map((entry, index) => {
|
|
694
719
|
const plugin = record(entry, `manifest.plugins[${index}]`);
|
|
695
720
|
exactKeys(plugin, [
|
|
@@ -816,9 +841,11 @@ function parseManifest(value) {
|
|
|
816
841
|
workingDirectory: string(projectSpace.workingDirectory, `manifest.projectSpaces[${index}].workingDirectory`)
|
|
817
842
|
});
|
|
818
843
|
});
|
|
844
|
+
const backgroundSessions = root.backgroundSessions === void 0 ? void 0 : parseBackgroundSessions(record(root.backgroundSessions, "manifest.backgroundSessions"));
|
|
819
845
|
return Object.freeze({
|
|
820
846
|
agents: Object.freeze(agents),
|
|
821
847
|
automations: Object.freeze(automations),
|
|
848
|
+
...backgroundSessions ? { backgroundSessions } : {},
|
|
822
849
|
defaultAgentId: string(root.defaultAgentId, "manifest.defaultAgentId"),
|
|
823
850
|
defaultEndpointId: string(root.defaultEndpointId, "manifest.defaultEndpointId"),
|
|
824
851
|
endpoints: Object.freeze(endpoints),
|
|
@@ -826,6 +853,38 @@ function parseManifest(value) {
|
|
|
826
853
|
projectSpaces: Object.freeze(projectSpaces)
|
|
827
854
|
});
|
|
828
855
|
}
|
|
856
|
+
function parseBackgroundSessions(value) {
|
|
857
|
+
exactKeys(value, [
|
|
858
|
+
"enabled",
|
|
859
|
+
"leaseMs",
|
|
860
|
+
"leaseRenewalIntervalMs",
|
|
861
|
+
"maxConsecutiveFailures",
|
|
862
|
+
"maxConcurrentSessions",
|
|
863
|
+
"required",
|
|
864
|
+
"retryBackoffMs",
|
|
865
|
+
"sessionLifetimeMs",
|
|
866
|
+
"stepTimeoutMs"
|
|
867
|
+
], "manifest.backgroundSessions", [
|
|
868
|
+
"leaseMs",
|
|
869
|
+
"leaseRenewalIntervalMs",
|
|
870
|
+
"maxConsecutiveFailures",
|
|
871
|
+
"maxConcurrentSessions",
|
|
872
|
+
"retryBackoffMs",
|
|
873
|
+
"sessionLifetimeMs",
|
|
874
|
+
"stepTimeoutMs"
|
|
875
|
+
]);
|
|
876
|
+
return Object.freeze({
|
|
877
|
+
enabled: boolean(value.enabled, "manifest.backgroundSessions.enabled"),
|
|
878
|
+
required: boolean(value.required, "manifest.backgroundSessions.required"),
|
|
879
|
+
stepTimeoutMs: positiveInteger(value.stepTimeoutMs ?? 3e5, "manifest.backgroundSessions.stepTimeoutMs"),
|
|
880
|
+
maxConcurrentSessions: positiveInteger(value.maxConcurrentSessions ?? 4, "manifest.backgroundSessions.maxConcurrentSessions"),
|
|
881
|
+
leaseMs: positiveInteger(value.leaseMs ?? 3e4, "manifest.backgroundSessions.leaseMs"),
|
|
882
|
+
leaseRenewalIntervalMs: positiveInteger(value.leaseRenewalIntervalMs ?? 1e4, "manifest.backgroundSessions.leaseRenewalIntervalMs"),
|
|
883
|
+
maxConsecutiveFailures: positiveInteger(value.maxConsecutiveFailures ?? 3, "manifest.backgroundSessions.maxConsecutiveFailures"),
|
|
884
|
+
retryBackoffMs: positiveInteger(value.retryBackoffMs ?? 3e4, "manifest.backgroundSessions.retryBackoffMs"),
|
|
885
|
+
sessionLifetimeMs: positiveInteger(value.sessionLifetimeMs ?? 864e5, "manifest.backgroundSessions.sessionLifetimeMs")
|
|
886
|
+
});
|
|
887
|
+
}
|
|
829
888
|
function record(value, path) {
|
|
830
889
|
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`${path} must be an object`);
|
|
831
890
|
return value;
|
|
@@ -1192,7 +1251,7 @@ function createAgentInstanceRegistry(options = {}) {
|
|
|
1192
1251
|
skillGrantRevision: definition.skillGrantSet.revision,
|
|
1193
1252
|
toolGrantRevision: definition.toolGrantSet.revision
|
|
1194
1253
|
});
|
|
1195
|
-
const bindingId = binding.kind === "endpoint" ? binding.endpointId : binding.automationId;
|
|
1254
|
+
const bindingId = binding.kind === "endpoint" ? binding.endpointId : binding.kind === "automation" ? binding.automationId : binding.agentId;
|
|
1196
1255
|
const bindingKey = `${binding.kind}:${bindingId}:${definition.agentId}`;
|
|
1197
1256
|
const existing = records.get(bindingKey);
|
|
1198
1257
|
if (existing) {
|
|
@@ -1217,6 +1276,10 @@ function createAgentInstanceRegistry(options = {}) {
|
|
|
1217
1276
|
automationId,
|
|
1218
1277
|
kind: "automation"
|
|
1219
1278
|
}, definition),
|
|
1279
|
+
resolveBackgroundSession: (agentId, definition) => resolveBinding({
|
|
1280
|
+
agentId,
|
|
1281
|
+
kind: "background-session"
|
|
1282
|
+
}, definition),
|
|
1220
1283
|
resolveEndpoint: (endpointId, definition) => resolveBinding({
|
|
1221
1284
|
endpointId,
|
|
1222
1285
|
kind: "endpoint"
|
|
@@ -1296,6 +1359,7 @@ function createRivusAgentHost(options) {
|
|
|
1296
1359
|
const definitions = new Map(options.definitions.map((definition) => [definition.agentId, definition]));
|
|
1297
1360
|
const endpoints = /* @__PURE__ */ new Map();
|
|
1298
1361
|
const automations = /* @__PURE__ */ new Map();
|
|
1362
|
+
const backgroundSessions = /* @__PURE__ */ new Map();
|
|
1299
1363
|
for (const endpoint of options.endpoints) {
|
|
1300
1364
|
if (endpoints.has(endpoint.id)) throw new InvalidRivusEndpointBinding(`duplicate endpoint: ${endpoint.id}`);
|
|
1301
1365
|
const definition = definitions.get(endpoint.agentId);
|
|
@@ -1308,6 +1372,11 @@ function createRivusAgentHost(options) {
|
|
|
1308
1372
|
if (!definitions.has(automation.definition.agentId)) throw new InvalidRivusEndpointBinding(`unknown automation agent: ${automation.definition.agentId}`);
|
|
1309
1373
|
automations.set(automation.id, options.runtimePool.registry.resolveAutomation(automation.id, automation.definition));
|
|
1310
1374
|
}
|
|
1375
|
+
for (const backgroundSession of options.backgroundSessions ?? []) {
|
|
1376
|
+
if (backgroundSessions.has(backgroundSession.agentId)) throw new InvalidRivusEndpointBinding(`duplicate background session agent: ${backgroundSession.agentId}`);
|
|
1377
|
+
if (!definitions.has(backgroundSession.agentId)) throw new InvalidRivusEndpointBinding(`unknown background session agent: ${backgroundSession.agentId}`);
|
|
1378
|
+
backgroundSessions.set(backgroundSession.agentId, options.runtimePool.registry.resolveBackgroundSession(backgroundSession.agentId, backgroundSession.definition));
|
|
1379
|
+
}
|
|
1311
1380
|
const resolveEndpoint = (endpointId) => {
|
|
1312
1381
|
const instance = endpoints.get(endpointId);
|
|
1313
1382
|
if (!instance) throw new InvalidRivusEndpointBinding(`unknown endpoint: ${endpointId}`);
|
|
@@ -1318,11 +1387,19 @@ function createRivusAgentHost(options) {
|
|
|
1318
1387
|
if (!instance) throw new InvalidRivusEndpointBinding(`unknown automation: ${automationId}`);
|
|
1319
1388
|
return instance;
|
|
1320
1389
|
};
|
|
1390
|
+
const resolveBackgroundSession = (agentId) => {
|
|
1391
|
+
const instance = backgroundSessions.get(agentId);
|
|
1392
|
+
if (!instance) throw new InvalidRivusEndpointBinding(`unknown background session agent: ${agentId}`);
|
|
1393
|
+
return instance;
|
|
1394
|
+
};
|
|
1321
1395
|
return {
|
|
1396
|
+
cancelBackgroundSession: (agentId, input) => options.runtimePool.cancel(resolveBackgroundSession(agentId), input),
|
|
1322
1397
|
cancelEndpoint: (endpointId, input) => options.runtimePool.cancel(resolveEndpoint(endpointId), input),
|
|
1323
1398
|
handleAutomation: (automationId, input) => options.runtimePool.run(resolveAutomation(automationId), input),
|
|
1399
|
+
handleBackgroundSession: (agentId, input) => options.runtimePool.run(resolveBackgroundSession(agentId), input),
|
|
1324
1400
|
handleEndpoint: (endpointId, input) => options.runtimePool.run(resolveEndpoint(endpointId), input),
|
|
1325
1401
|
resolveAutomation,
|
|
1402
|
+
resolveBackgroundSession,
|
|
1326
1403
|
resolveEndpoint
|
|
1327
1404
|
};
|
|
1328
1405
|
}
|
|
@@ -1359,9 +1436,15 @@ async function createRivusDeploymentDaemon(options) {
|
|
|
1359
1436
|
})));
|
|
1360
1437
|
const definitions = new Map(deployment.definitions.map((definition) => [definition.agentId, definition]));
|
|
1361
1438
|
const automationDefinitions = new Map(deployment.automationDefinitions.map((definition) => [definition.id, definition]));
|
|
1439
|
+
const backgroundSessionsConfig = deployment.manifest.backgroundSessions;
|
|
1440
|
+
const backgroundDefinitions = /* @__PURE__ */ new Map();
|
|
1441
|
+
if (backgroundSessionsConfig?.enabled) for (const agent of deployment.agents) {
|
|
1442
|
+
if (agent.status !== "enabled" || !agent.definition) continue;
|
|
1443
|
+
backgroundDefinitions.set(agent.agentId, narrowBackgroundSessionDefinition(agent.definition));
|
|
1444
|
+
}
|
|
1362
1445
|
const runtimePool = createAgentRuntimePool({
|
|
1363
1446
|
createRuntime: (instance) => {
|
|
1364
|
-
const definition = instance.binding.kind === "automation" ? automationDefinitions.get(instance.binding.automationId)?.runtimeDefinition : definitions.get(instance.agentId);
|
|
1447
|
+
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);
|
|
1365
1448
|
if (!definition) throw new RivusDeploymentDaemonLifecycleError(`runtime instance references unknown agent: ${instance.agentId}`);
|
|
1366
1449
|
const projectSpace = definition.projectSpaceId ? projectSpaces.get(definition.projectSpaceId) : void 0;
|
|
1367
1450
|
return options.createRuntime({
|
|
@@ -1392,11 +1475,20 @@ async function createRivusDeploymentDaemon(options) {
|
|
|
1392
1475
|
lifecycle: definition.enabled && agentEnabled ? "stopped" : "disabled"
|
|
1393
1476
|
};
|
|
1394
1477
|
});
|
|
1478
|
+
const backgroundSessionSlot = backgroundSessionsConfig ? {
|
|
1479
|
+
agentEnabled: backgroundDefinitions.size > 0,
|
|
1480
|
+
definition: backgroundSessionsConfig,
|
|
1481
|
+
lifecycle: backgroundSessionsConfig.enabled && backgroundDefinitions.size > 0 ? "stopped" : "disabled"
|
|
1482
|
+
} : void 0;
|
|
1395
1483
|
const host = createRivusAgentHost({
|
|
1396
1484
|
automations: automationSlots.filter((slot) => slot.definition.enabled && slot.agentEnabled && slot.resolvedDefinition !== void 0).map((slot) => ({
|
|
1397
1485
|
definition: slot.resolvedDefinition.runtimeDefinition,
|
|
1398
1486
|
id: slot.definition.id
|
|
1399
1487
|
})),
|
|
1488
|
+
...backgroundSessionSlot ? { backgroundSessions: [...backgroundDefinitions].map(([agentId, definition]) => ({
|
|
1489
|
+
agentId,
|
|
1490
|
+
definition
|
|
1491
|
+
})) } : {},
|
|
1400
1492
|
definitions: deployment.definitions,
|
|
1401
1493
|
endpoints: slots.filter((slot) => slot.definition.enabled && slot.agentEnabled).map((slot) => ({
|
|
1402
1494
|
agentId: slot.definition.agentId,
|
|
@@ -1424,7 +1516,15 @@ async function createRivusDeploymentDaemon(options) {
|
|
|
1424
1516
|
agentId: slot.definition.agentId,
|
|
1425
1517
|
automationId: slot.definition.id
|
|
1426
1518
|
});
|
|
1427
|
-
const
|
|
1519
|
+
const backgroundSessionStatus = (slot) => Object.freeze({
|
|
1520
|
+
...componentStatus(slot),
|
|
1521
|
+
...slot.adapter?.status ? { supervisor: slot.adapter.status() } : {}
|
|
1522
|
+
});
|
|
1523
|
+
const allSlots = [
|
|
1524
|
+
...slots,
|
|
1525
|
+
...automationSlots,
|
|
1526
|
+
...backgroundSessionSlot ? [backgroundSessionSlot] : []
|
|
1527
|
+
];
|
|
1428
1528
|
const isReady = () => allSlots.every(isSlotReady);
|
|
1429
1529
|
const failedRequiredEndpointIds = () => slots.filter((slot) => slot.definition.enabled && slot.definition.required && slot.lifecycle !== "running").map((slot) => slot.definition.id);
|
|
1430
1530
|
const failedRequiredAutomationIds = () => automationSlots.filter((slot) => slot.definition.enabled && slot.definition.required && slot.lifecycle !== "running").map((slot) => slot.definition.id);
|
|
@@ -1437,6 +1537,7 @@ async function createRivusDeploymentDaemon(options) {
|
|
|
1437
1537
|
const status = () => Object.freeze({
|
|
1438
1538
|
agents: deployment.agents,
|
|
1439
1539
|
automations: Object.freeze(automationSlots.map(automationStatus)),
|
|
1540
|
+
...backgroundSessionSlot ? { backgroundSessions: backgroundSessionStatus(backgroundSessionSlot) } : {},
|
|
1440
1541
|
defaultAgentId: deployment.manifest.defaultAgentId,
|
|
1441
1542
|
defaultEndpointId: deployment.manifest.defaultEndpointId,
|
|
1442
1543
|
endpoints: Object.freeze(slots.map(endpointStatus)),
|
|
@@ -1501,6 +1602,18 @@ async function createRivusDeploymentDaemon(options) {
|
|
|
1501
1602
|
});
|
|
1502
1603
|
degraded ||= slotDegraded;
|
|
1503
1604
|
}
|
|
1605
|
+
if (backgroundSessionSlot) {
|
|
1606
|
+
const slotDegraded = await startSlot(backgroundSessionSlot, true, async () => {
|
|
1607
|
+
if (!options.createBackgroundSession) throw new RivusDeploymentDaemonLifecycleError("deployment bootstrap does not provide Background Session adapters");
|
|
1608
|
+
return options.createBackgroundSession({
|
|
1609
|
+
agentIds: [...backgroundDefinitions.keys()],
|
|
1610
|
+
cancel: (input) => host.cancelBackgroundSession(input.agentId, input),
|
|
1611
|
+
config: backgroundSessionSlot.definition,
|
|
1612
|
+
run: (input) => host.handleBackgroundSession(input.agentId, input)
|
|
1613
|
+
});
|
|
1614
|
+
});
|
|
1615
|
+
degraded ||= slotDegraded;
|
|
1616
|
+
}
|
|
1504
1617
|
lifecycle = degraded ? "degraded" : "running";
|
|
1505
1618
|
assertRequiredReadiness();
|
|
1506
1619
|
},
|
|
@@ -1514,6 +1627,7 @@ async function createRivusDeploymentDaemon(options) {
|
|
|
1514
1627
|
lifecycle = "stopping";
|
|
1515
1628
|
const errors = [];
|
|
1516
1629
|
await stopSlots(automationSlots, errors);
|
|
1630
|
+
if (backgroundSessionSlot) await stopSlots([backgroundSessionSlot], errors);
|
|
1517
1631
|
await stopSlots(slots, errors);
|
|
1518
1632
|
try {
|
|
1519
1633
|
await runtimePool.disposeAll();
|
|
@@ -1654,6 +1768,7 @@ async function createConfiguredRivusDeploymentDaemon(options) {
|
|
|
1654
1768
|
const manifest = await loadRivusDeploymentManifest(options.manifestPath, options.manifestOptions);
|
|
1655
1769
|
return createRivusDeploymentDaemon({
|
|
1656
1770
|
...options.createAutomation ? { createAutomation: options.createAutomation } : {},
|
|
1771
|
+
...options.createBackgroundSession ? { createBackgroundSession: options.createBackgroundSession } : {},
|
|
1657
1772
|
createEndpoint: options.createEndpoint,
|
|
1658
1773
|
createRuntime: options.createRuntime,
|
|
1659
1774
|
deploymentRoot: dirname(options.manifestPath),
|
|
@@ -2968,6 +3083,17 @@ function toRedactedDeploymentManifest(manifest) {
|
|
|
2968
3083
|
templateId,
|
|
2969
3084
|
timeZone
|
|
2970
3085
|
})),
|
|
3086
|
+
...manifest.backgroundSessions ? { backgroundSessions: {
|
|
3087
|
+
enabled: manifest.backgroundSessions.enabled,
|
|
3088
|
+
leaseMs: manifest.backgroundSessions.leaseMs,
|
|
3089
|
+
leaseRenewalIntervalMs: manifest.backgroundSessions.leaseRenewalIntervalMs,
|
|
3090
|
+
maxConsecutiveFailures: manifest.backgroundSessions.maxConsecutiveFailures,
|
|
3091
|
+
maxConcurrentSessions: manifest.backgroundSessions.maxConcurrentSessions,
|
|
3092
|
+
required: manifest.backgroundSessions.required,
|
|
3093
|
+
retryBackoffMs: manifest.backgroundSessions.retryBackoffMs,
|
|
3094
|
+
sessionLifetimeMs: manifest.backgroundSessions.sessionLifetimeMs,
|
|
3095
|
+
stepTimeoutMs: manifest.backgroundSessions.stepTimeoutMs
|
|
3096
|
+
} } : {},
|
|
2971
3097
|
defaultAgentId: manifest.defaultAgentId,
|
|
2972
3098
|
defaultEndpointId: manifest.defaultEndpointId,
|
|
2973
3099
|
endpoints: manifest.endpoints.map(({ agentId, credentialRef, enabled, id, required, sessionNamespace }) => ({
|
|
@@ -3109,4 +3235,4 @@ function hasRecoveryRunner(daemon) {
|
|
|
3109
3235
|
return typeof daemon.openRecoveryControl === "function";
|
|
3110
3236
|
}
|
|
3111
3237
|
//#endregion
|
|
3112
|
-
export {
|
|
3238
|
+
export { loadRivusDeployment as $, DEFAULT_BACKGROUND_SESSION_LIFETIME_MS as A, acceptsCardPresentationProgress as B, loadRivusDaemonConfig as C, loadRivusDeploymentManifest as D, RivusDeploymentManifestError as E, DEFAULT_BACKGROUND_SESSION_SUPERVISOR_INTERVAL_MS as F, createCardPresentationChain as G, beginCardPresentationHandoff as H, resolveBackgroundSessionSupervisorIntervalMs as I, markCardPresentationTerminal as J, failCardPresentationHandoff as K, DEFAULT_CARD_STREAM_LEASE_MS as L, DEFAULT_BACKGROUND_SESSION_MAX_CONSECUTIVE_FAILURES as M, DEFAULT_BACKGROUND_SESSION_RETRY_BACKOFF_MS as N, DEFAULT_BACKGROUND_SESSION_LEASE_MS as O, DEFAULT_BACKGROUND_SESSION_STEP_TIMEOUT_MS as P, RivusPluginLoadError as Q, createFeishuCardRollover as R, RivusDaemonConfigError as S, resolveNodeRivusPluginModulePath as T, compensateCardPresentationHandoff as U, activeCardPresentation as V, completeCardPresentationHandoff as W, resolveFeishuEndpointCredentials as X, FeishuEndpointCredentialError as Y, loadMergedLocalEnvFile as Z, createStableId as _, InvalidRivusProjectSpace as a, createRivusEnvFromOpenClawConfig as b, RivusDeploymentReadinessError as c, createRivusAgentHost as d, validateRivusDeploymentManifest as et, AgentInstanceBusy as f, createAgentInstanceRegistry as g, AgentInstanceConflict as h, resolveRivusProjectSpace as i, DEFAULT_BACKGROUND_SESSION_MAX_CONCURRENT_SESSIONS as j, DEFAULT_BACKGROUND_SESSION_LEASE_RENEWAL_INTERVAL_MS as k, createRivusDeploymentDaemon as l, createAgentRuntimePool as m, createRivusDeploymentCliProcess as n, RivusDeploymentAutomationReadinessError as o, AgentRuntimeDisposed as p, isCardPresentationHandoffDue as q, createConfiguredRivusDeploymentDaemon as r, RivusDeploymentDaemonLifecycleError as s, runRivusDaemonCli as t, InvalidRivusEndpointBinding as u, createRivusDaemonShutdownController as v, loadNodeRivusPluginModule as w, formatRivusEnvFile as x, OpenClawEnvImportError as y, CardPresentationTransitionDenied as z };
|
|
@@ -1,5 +1,227 @@
|
|
|
1
1
|
import { c as InvalidRivusPlugin, o as createRivusMemoryToolContract, r as RIVUS_MEMORY_TOOL_PLUGIN_ID, t as MEMORY_SCOPES } from "./agent-memory.js";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
+
//#region src/application/background-session/background-session-authority.ts
|
|
4
|
+
const BACKGROUND_SESSION_TOOL_IDS = [
|
|
5
|
+
"background.start",
|
|
6
|
+
"background.wait",
|
|
7
|
+
"background.list",
|
|
8
|
+
"background.status",
|
|
9
|
+
"background.send",
|
|
10
|
+
"background.stop"
|
|
11
|
+
];
|
|
12
|
+
const BACKGROUND_SESSION_START_TOOL_ID = "background.start";
|
|
13
|
+
const BACKGROUND_SESSION_TOOL_PLUGIN_ID = "rivus-core";
|
|
14
|
+
const BACKGROUND_SESSION_TOOL_VERSION = "1.0.0";
|
|
15
|
+
const BACKGROUND_SESSION_SESSION_KEY_PREFIX = "background";
|
|
16
|
+
function createBackgroundSessionKey(sessionId) {
|
|
17
|
+
return `${BACKGROUND_SESSION_SESSION_KEY_PREFIX}:${sessionId}`;
|
|
18
|
+
}
|
|
19
|
+
function createBackgroundSessionStepSourceMessageId(sessionId, stepCount) {
|
|
20
|
+
return `bg:${sessionId}:step:${stepCount}`;
|
|
21
|
+
}
|
|
22
|
+
function createBackgroundSessionToolContracts() {
|
|
23
|
+
return [
|
|
24
|
+
Object.freeze({
|
|
25
|
+
description: "Start a background agent session. Use when the request must wait for external changes, observe over time, or continue working after the foreground run ends. Returns a stable session id immediately; the foreground response can finish here. The detached session continues with the granted Skills, CLI, Tools, Project Space, and Memory of this agent.",
|
|
26
|
+
digest: contractDigest("background.start"),
|
|
27
|
+
id: "background.start",
|
|
28
|
+
idempotency: "supported",
|
|
29
|
+
inputSchema: Object.freeze({
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
properties: Object.freeze({
|
|
32
|
+
displayName: {
|
|
33
|
+
type: "string",
|
|
34
|
+
maxLength: 200
|
|
35
|
+
},
|
|
36
|
+
prompt: {
|
|
37
|
+
type: "string",
|
|
38
|
+
minLength: 1,
|
|
39
|
+
maxLength: 2e4
|
|
40
|
+
}
|
|
41
|
+
}),
|
|
42
|
+
required: ["prompt"],
|
|
43
|
+
type: "object"
|
|
44
|
+
}),
|
|
45
|
+
pluginId: BACKGROUND_SESSION_TOOL_PLUGIN_ID,
|
|
46
|
+
risk: "mutate",
|
|
47
|
+
version: BACKGROUND_SESSION_TOOL_VERSION
|
|
48
|
+
}),
|
|
49
|
+
Object.freeze({
|
|
50
|
+
description: "Pause the current background session durably and end the current step. Call with delayMs to resume after a delay, with until to resume at an absolute ISO time, or with neither to wait for user input. After this call no further tool calls are accepted in this step.",
|
|
51
|
+
digest: contractDigest("background.wait"),
|
|
52
|
+
id: "background.wait",
|
|
53
|
+
idempotency: "supported",
|
|
54
|
+
inputSchema: Object.freeze({
|
|
55
|
+
additionalProperties: false,
|
|
56
|
+
properties: Object.freeze({
|
|
57
|
+
delayMs: {
|
|
58
|
+
type: "integer",
|
|
59
|
+
minimum: 1e3,
|
|
60
|
+
maximum: 864e5
|
|
61
|
+
},
|
|
62
|
+
reason: {
|
|
63
|
+
type: "string",
|
|
64
|
+
maxLength: 500
|
|
65
|
+
},
|
|
66
|
+
until: {
|
|
67
|
+
type: "string",
|
|
68
|
+
maxLength: 64
|
|
69
|
+
}
|
|
70
|
+
}),
|
|
71
|
+
type: "object"
|
|
72
|
+
}),
|
|
73
|
+
pluginId: BACKGROUND_SESSION_TOOL_PLUGIN_ID,
|
|
74
|
+
risk: "mutate",
|
|
75
|
+
version: BACKGROUND_SESSION_TOOL_VERSION
|
|
76
|
+
}),
|
|
77
|
+
Object.freeze({
|
|
78
|
+
description: "List background sessions owned by this conversation, newest first. Optionally filter by phase and limit the number of results.",
|
|
79
|
+
digest: contractDigest("background.list"),
|
|
80
|
+
id: "background.list",
|
|
81
|
+
idempotency: "supported",
|
|
82
|
+
inputSchema: Object.freeze({
|
|
83
|
+
additionalProperties: false,
|
|
84
|
+
properties: Object.freeze({
|
|
85
|
+
limit: {
|
|
86
|
+
type: "integer",
|
|
87
|
+
minimum: 1,
|
|
88
|
+
maximum: 50
|
|
89
|
+
},
|
|
90
|
+
phase: {
|
|
91
|
+
enum: [
|
|
92
|
+
"queued",
|
|
93
|
+
"running",
|
|
94
|
+
"waiting",
|
|
95
|
+
"input-required",
|
|
96
|
+
"stopping",
|
|
97
|
+
"stopped",
|
|
98
|
+
"completed",
|
|
99
|
+
"failed",
|
|
100
|
+
"reconciliation-required"
|
|
101
|
+
],
|
|
102
|
+
type: "string"
|
|
103
|
+
}
|
|
104
|
+
}),
|
|
105
|
+
type: "object"
|
|
106
|
+
}),
|
|
107
|
+
pluginId: BACKGROUND_SESSION_TOOL_PLUGIN_ID,
|
|
108
|
+
risk: "observe",
|
|
109
|
+
version: BACKGROUND_SESSION_TOOL_VERSION
|
|
110
|
+
}),
|
|
111
|
+
Object.freeze({
|
|
112
|
+
description: "Return the current phase, step counts, wake time, and result of one background session owned by this conversation.",
|
|
113
|
+
digest: contractDigest("background.status"),
|
|
114
|
+
id: "background.status",
|
|
115
|
+
idempotency: "supported",
|
|
116
|
+
inputSchema: Object.freeze({
|
|
117
|
+
additionalProperties: false,
|
|
118
|
+
properties: Object.freeze({ sessionId: {
|
|
119
|
+
type: "string",
|
|
120
|
+
minLength: 1,
|
|
121
|
+
maxLength: 200
|
|
122
|
+
} }),
|
|
123
|
+
required: ["sessionId"],
|
|
124
|
+
type: "object"
|
|
125
|
+
}),
|
|
126
|
+
pluginId: BACKGROUND_SESSION_TOOL_PLUGIN_ID,
|
|
127
|
+
risk: "observe",
|
|
128
|
+
version: BACKGROUND_SESSION_TOOL_VERSION
|
|
129
|
+
}),
|
|
130
|
+
Object.freeze({
|
|
131
|
+
description: "Send new user instruction text to a background session owned by this conversation and wake it. The input is delivered exactly once in the next step.",
|
|
132
|
+
digest: contractDigest("background.send"),
|
|
133
|
+
id: "background.send",
|
|
134
|
+
idempotency: "supported",
|
|
135
|
+
inputSchema: Object.freeze({
|
|
136
|
+
additionalProperties: false,
|
|
137
|
+
properties: Object.freeze({
|
|
138
|
+
message: {
|
|
139
|
+
type: "string",
|
|
140
|
+
minLength: 1,
|
|
141
|
+
maxLength: 2e4
|
|
142
|
+
},
|
|
143
|
+
sessionId: {
|
|
144
|
+
type: "string",
|
|
145
|
+
minLength: 1,
|
|
146
|
+
maxLength: 200
|
|
147
|
+
}
|
|
148
|
+
}),
|
|
149
|
+
required: ["message", "sessionId"],
|
|
150
|
+
type: "object"
|
|
151
|
+
}),
|
|
152
|
+
pluginId: BACKGROUND_SESSION_TOOL_PLUGIN_ID,
|
|
153
|
+
risk: "mutate",
|
|
154
|
+
version: BACKGROUND_SESSION_TOOL_VERSION
|
|
155
|
+
}),
|
|
156
|
+
Object.freeze({
|
|
157
|
+
description: "Stop a background session owned by this conversation. Persists the cancellation, aborts the active step and its owned process, and delivers a terminal notice.",
|
|
158
|
+
digest: contractDigest("background.stop"),
|
|
159
|
+
id: "background.stop",
|
|
160
|
+
idempotency: "supported",
|
|
161
|
+
inputSchema: Object.freeze({
|
|
162
|
+
additionalProperties: false,
|
|
163
|
+
properties: Object.freeze({
|
|
164
|
+
reason: {
|
|
165
|
+
type: "string",
|
|
166
|
+
maxLength: 500
|
|
167
|
+
},
|
|
168
|
+
sessionId: {
|
|
169
|
+
type: "string",
|
|
170
|
+
minLength: 1,
|
|
171
|
+
maxLength: 200
|
|
172
|
+
}
|
|
173
|
+
}),
|
|
174
|
+
required: ["sessionId"],
|
|
175
|
+
type: "object"
|
|
176
|
+
}),
|
|
177
|
+
pluginId: BACKGROUND_SESSION_TOOL_PLUGIN_ID,
|
|
178
|
+
risk: "mutate",
|
|
179
|
+
version: BACKGROUND_SESSION_TOOL_VERSION
|
|
180
|
+
})
|
|
181
|
+
];
|
|
182
|
+
}
|
|
183
|
+
function backgroundSessionToolIds() {
|
|
184
|
+
return [...BACKGROUND_SESSION_TOOL_IDS];
|
|
185
|
+
}
|
|
186
|
+
function isBackgroundSessionToolId(toolId) {
|
|
187
|
+
return BACKGROUND_SESSION_TOOL_IDS.includes(toolId);
|
|
188
|
+
}
|
|
189
|
+
function extendBackgroundSessionDefinition(definition) {
|
|
190
|
+
const contracts = createBackgroundSessionToolContracts();
|
|
191
|
+
const existingIds = new Set(definition.tools.map(({ id }) => id));
|
|
192
|
+
const additions = contracts.filter((contract) => !existingIds.has(contract.id));
|
|
193
|
+
const toolGrantSet = Object.freeze({
|
|
194
|
+
revision: grantRevision(definition.toolGrantSet.revision, additions.map(({ id }) => id)),
|
|
195
|
+
toolIds: Object.freeze([...definition.toolGrantSet.toolIds, ...additions.map(({ id }) => id)].sort())
|
|
196
|
+
});
|
|
197
|
+
return Object.freeze({
|
|
198
|
+
...definition,
|
|
199
|
+
tools: Object.freeze([...definition.tools, ...additions]),
|
|
200
|
+
toolGrantSet
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function narrowBackgroundSessionDefinition(definition) {
|
|
204
|
+
const childToolIds = definition.toolGrantSet.toolIds.filter((id) => id !== BACKGROUND_SESSION_START_TOOL_ID);
|
|
205
|
+
const toolGrantSet = Object.freeze({
|
|
206
|
+
revision: grantRevision(definition.toolGrantSet.revision, childToolIds),
|
|
207
|
+
toolIds: Object.freeze(childToolIds)
|
|
208
|
+
});
|
|
209
|
+
return Object.freeze({
|
|
210
|
+
...definition,
|
|
211
|
+
tools: Object.freeze(definition.tools.filter(({ id }) => id !== BACKGROUND_SESSION_START_TOOL_ID)),
|
|
212
|
+
toolGrantSet
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
function grantRevision(parentRevision, toolIds) {
|
|
216
|
+
return `sha256:${createHash("sha256").update(JSON.stringify({
|
|
217
|
+
parentRevision,
|
|
218
|
+
toolIds: [...toolIds].sort()
|
|
219
|
+
})).digest("hex")}`;
|
|
220
|
+
}
|
|
221
|
+
function contractDigest(toolId) {
|
|
222
|
+
return `sha256:${createHash("sha256").update(`background-tool:${toolId}:${BACKGROUND_SESSION_TOOL_VERSION}`).digest("hex")}`;
|
|
223
|
+
}
|
|
224
|
+
//#endregion
|
|
3
225
|
//#region src/application/plugin/deep-freeze.ts
|
|
4
226
|
function deepFreeze(value) {
|
|
5
227
|
if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
|
|
@@ -70,7 +292,7 @@ function createRivusPluginCatalog() {
|
|
|
70
292
|
})
|
|
71
293
|
};
|
|
72
294
|
}
|
|
73
|
-
function resolveRivusAgentDefinition(catalog, deployment) {
|
|
295
|
+
function resolveRivusAgentDefinition(catalog, deployment, options = {}) {
|
|
74
296
|
const snapshot = catalog.snapshot();
|
|
75
297
|
const plugin = snapshot.plugins.find((candidate) => candidate.id === deployment.pluginId);
|
|
76
298
|
if (!plugin) throw new InvalidRivusPlugin(`unknown deployment plugin: ${deployment.pluginId}`);
|
|
@@ -135,7 +357,7 @@ function resolveRivusAgentDefinition(catalog, deployment) {
|
|
|
135
357
|
}),
|
|
136
358
|
skillIds
|
|
137
359
|
});
|
|
138
|
-
|
|
360
|
+
const definition = deepFreeze({
|
|
139
361
|
agentId: deployment.agentId,
|
|
140
362
|
endpointIds: [...deployment.endpointIds],
|
|
141
363
|
memory: {
|
|
@@ -153,6 +375,8 @@ function resolveRivusAgentDefinition(catalog, deployment) {
|
|
|
153
375
|
toolGrantSet,
|
|
154
376
|
tools
|
|
155
377
|
});
|
|
378
|
+
if (options.backgroundSessions === true) return extendBackgroundSessionDefinition(definition);
|
|
379
|
+
return definition;
|
|
156
380
|
}
|
|
157
381
|
function validateMemoryScopes(scopes, owner) {
|
|
158
382
|
const result = /* @__PURE__ */ new Set();
|
|
@@ -209,4 +433,4 @@ function stableJson(value) {
|
|
|
209
433
|
return JSON.stringify(value);
|
|
210
434
|
}
|
|
211
435
|
//#endregion
|
|
212
|
-
export { resolveRivusAgentDefinition as n, deepFreeze as r, createRivusPluginCatalog as t };
|
|
436
|
+
export { BACKGROUND_SESSION_START_TOOL_ID as a, BACKGROUND_SESSION_TOOL_VERSION as c, createBackgroundSessionStepSourceMessageId as d, createBackgroundSessionToolContracts as f, narrowBackgroundSessionDefinition as h, BACKGROUND_SESSION_SESSION_KEY_PREFIX as i, backgroundSessionToolIds as l, isBackgroundSessionToolId as m, resolveRivusAgentDefinition as n, BACKGROUND_SESSION_TOOL_IDS as o, extendBackgroundSessionDefinition as p, deepFreeze as r, BACKGROUND_SESSION_TOOL_PLUGIN_ID as s, createRivusPluginCatalog as t, createBackgroundSessionKey as u };
|
package/dist/rivus-plugin.d.ts
CHANGED
|
@@ -16,6 +16,12 @@ interface RivusPluginManifest {
|
|
|
16
16
|
interface RivusToolExecutor {
|
|
17
17
|
execute(input: unknown, context: RivusToolExecutionContext): unknown;
|
|
18
18
|
}
|
|
19
|
+
interface RivusToolExecutionOrigin {
|
|
20
|
+
readonly endpointId: string;
|
|
21
|
+
readonly tenantKey: string;
|
|
22
|
+
readonly conversationId?: string;
|
|
23
|
+
readonly allowedActorOpenIds: ReadonlyArray<string>;
|
|
24
|
+
}
|
|
19
25
|
interface RivusToolExecutionContext {
|
|
20
26
|
readonly agentId: string;
|
|
21
27
|
readonly instanceId: string;
|
|
@@ -27,6 +33,8 @@ interface RivusToolExecutionContext {
|
|
|
27
33
|
readonly toolId: string;
|
|
28
34
|
readonly toolVersion: string;
|
|
29
35
|
readonly sessionKey: string;
|
|
36
|
+
readonly origin?: RivusToolExecutionOrigin;
|
|
37
|
+
readonly sourceMessageId?: string;
|
|
30
38
|
}
|
|
31
39
|
interface RivusToolFactoryContext {
|
|
32
40
|
readonly toolId: string;
|
|
@@ -64,6 +64,7 @@ var InvalidInvocationAuthority = class extends Error {
|
|
|
64
64
|
};
|
|
65
65
|
function createInvocationAuthority(authority) {
|
|
66
66
|
if (!authority.sourceMessageId.trim()) throw new InvalidInvocationAuthority("invocation authority requires a trusted source message id");
|
|
67
|
+
if (authority.endpointId !== void 0 && !authority.endpointId.trim()) throw new InvalidInvocationAuthority("invocation authority requires a trusted endpoint id");
|
|
67
68
|
const reference = Object.freeze({ id: `authority:${randomUUID()}` });
|
|
68
69
|
const memory = authority.memory ? Object.freeze({
|
|
69
70
|
...authority.memory,
|
|
@@ -71,6 +72,7 @@ function createInvocationAuthority(authority) {
|
|
|
71
72
|
}) : void 0;
|
|
72
73
|
authorities.set(reference, Object.freeze({
|
|
73
74
|
...authority,
|
|
75
|
+
...authority.allowedActorOpenIds ? { allowedActorOpenIds: Object.freeze([...authority.allowedActorOpenIds]) } : {},
|
|
74
76
|
...memory ? { memory } : {}
|
|
75
77
|
}));
|
|
76
78
|
return reference;
|