@rivus/agent 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-memory.js +114 -0
- package/dist/index.d.ts +29 -203
- package/dist/index.js +81 -259
- package/dist/pi-tool-proxy.d.ts +194 -0
- package/dist/pi.d.ts +10 -1
- package/dist/pi.js +111 -1
- package/dist/rivus-daemon-cli.js +35 -17
- package/dist/rivus-plugin-registry.js +2 -114
- package/dist/rivus-plugin-testkit.d.ts +2 -174
- package/dist/rivus-plugin-testkit.js +2 -1
- package/dist/rivus-plugin.d.ts +175 -0
- package/dist/tool-input-digest.js +126 -0
- package/examples/pi-feishu-deployment.bootstrap.ts +7 -4
- package/package.json +1 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { s as AgentLoopInput } from "./agent-loop.js";
|
|
2
|
+
import { c as MemoryScope, t as AgentMemoryAuthority } from "./agent-memory.js";
|
|
3
|
+
import { A as RivusToolRisk, D as RivusToolGrantSet, b as RivusResolvedToolDescriptor, g as RivusPluginCatalog, m as RivusHostToolDescriptor } from "./rivus-plugin.js";
|
|
4
|
+
import { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
5
|
+
|
|
6
|
+
//#region src/domain/recovery-action.d.ts
|
|
7
|
+
interface RecoveryAction {
|
|
8
|
+
readonly actorId: string;
|
|
9
|
+
readonly at: string;
|
|
10
|
+
readonly note: string;
|
|
11
|
+
}
|
|
12
|
+
declare class InvalidRecoveryAction extends Error {
|
|
13
|
+
readonly name = "InvalidRecoveryAction";
|
|
14
|
+
}
|
|
15
|
+
declare function createRecoveryAction(input: RecoveryAction): RecoveryAction;
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/application/delegation/tool-operation-ledger.d.ts
|
|
18
|
+
interface ToolOperationBinding {
|
|
19
|
+
readonly agentId: string;
|
|
20
|
+
readonly inputDigest: string;
|
|
21
|
+
readonly instanceId: string;
|
|
22
|
+
readonly sourceMessageId: string;
|
|
23
|
+
readonly toolId: string;
|
|
24
|
+
readonly toolVersion: string;
|
|
25
|
+
}
|
|
26
|
+
type ToolOperationState = {
|
|
27
|
+
readonly status: "pending";
|
|
28
|
+
} | {
|
|
29
|
+
readonly result: unknown;
|
|
30
|
+
readonly status: "completed";
|
|
31
|
+
} | {
|
|
32
|
+
readonly reason: string;
|
|
33
|
+
readonly status: "reconciliation-required";
|
|
34
|
+
} | {
|
|
35
|
+
readonly status: "aborted";
|
|
36
|
+
};
|
|
37
|
+
interface ToolOperationRecord {
|
|
38
|
+
readonly binding: ToolOperationBinding;
|
|
39
|
+
readonly operationId: string;
|
|
40
|
+
readonly reconciliation?: ToolOperationReconciliation;
|
|
41
|
+
readonly revision: number;
|
|
42
|
+
readonly state: ToolOperationState;
|
|
43
|
+
}
|
|
44
|
+
interface ToolOperationReconciliation extends RecoveryAction {
|
|
45
|
+
readonly outcome: "applied" | "not-applied";
|
|
46
|
+
}
|
|
47
|
+
type ToolOperationReconciliationOutcome = {
|
|
48
|
+
readonly result: unknown;
|
|
49
|
+
readonly status: "applied";
|
|
50
|
+
} | {
|
|
51
|
+
readonly status: "not-applied";
|
|
52
|
+
};
|
|
53
|
+
type ToolOperationBeginResult = {
|
|
54
|
+
readonly status: "acquired";
|
|
55
|
+
} | {
|
|
56
|
+
readonly result: unknown;
|
|
57
|
+
readonly status: "completed";
|
|
58
|
+
} | {
|
|
59
|
+
readonly status: "blocked";
|
|
60
|
+
readonly reason: string;
|
|
61
|
+
};
|
|
62
|
+
type ToolOperationInspectResult = {
|
|
63
|
+
readonly status: "missing";
|
|
64
|
+
} | {
|
|
65
|
+
readonly result: unknown;
|
|
66
|
+
readonly status: "completed";
|
|
67
|
+
} | {
|
|
68
|
+
readonly status: "blocked";
|
|
69
|
+
readonly reason: string;
|
|
70
|
+
};
|
|
71
|
+
interface ToolOperationLedger {
|
|
72
|
+
abort(operationId: string, binding: ToolOperationBinding): Promise<void>;
|
|
73
|
+
begin(operationId: string, binding: ToolOperationBinding): Promise<ToolOperationBeginResult>;
|
|
74
|
+
complete(operationId: string, binding: ToolOperationBinding, result: unknown): Promise<void>;
|
|
75
|
+
inspect(operationId: string, binding: ToolOperationBinding): Promise<ToolOperationInspectResult>;
|
|
76
|
+
reconciliationRequired(): ReadonlyArray<ToolOperationRecord>;
|
|
77
|
+
reconcile(input: {
|
|
78
|
+
readonly action: RecoveryAction;
|
|
79
|
+
readonly expectedRevision: number;
|
|
80
|
+
readonly operationId: string;
|
|
81
|
+
readonly outcome: ToolOperationReconciliationOutcome;
|
|
82
|
+
}): Promise<ToolOperationRecord>;
|
|
83
|
+
requireReconciliation(operationId: string, binding: ToolOperationBinding, reason: string): Promise<void>;
|
|
84
|
+
unresolvedForSource(sourceMessageId: string): ReadonlyArray<ToolOperationRecord>;
|
|
85
|
+
}
|
|
86
|
+
declare function createToolOperationLedger(options?: {
|
|
87
|
+
readonly initial?: ReadonlyArray<ToolOperationRecord>;
|
|
88
|
+
readonly persist?: (record: ToolOperationRecord) => Promise<void>;
|
|
89
|
+
}): ToolOperationLedger;
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/application/delegation/tool-authority.d.ts
|
|
92
|
+
interface InvocationAuthorityRef {
|
|
93
|
+
readonly id: string;
|
|
94
|
+
}
|
|
95
|
+
interface InvocationAuthority {
|
|
96
|
+
readonly agentId: string;
|
|
97
|
+
readonly instanceId: string;
|
|
98
|
+
readonly memory?: AgentMemoryAuthority;
|
|
99
|
+
readonly runId: string;
|
|
100
|
+
readonly sessionKey: string;
|
|
101
|
+
readonly sourceMessageId: string;
|
|
102
|
+
readonly tenantKey: string;
|
|
103
|
+
readonly toolGrantSet: RivusToolGrantSet;
|
|
104
|
+
}
|
|
105
|
+
declare class InvalidInvocationAuthority extends Error {
|
|
106
|
+
readonly name = "InvalidInvocationAuthority";
|
|
107
|
+
}
|
|
108
|
+
declare function createInvocationAuthority(authority: InvocationAuthority): InvocationAuthorityRef;
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/application/delegation/tool-broker.d.ts
|
|
111
|
+
interface AuthorizationPolicyState {
|
|
112
|
+
readonly epoch: number;
|
|
113
|
+
readonly revokedToolIds: ReadonlyArray<string>;
|
|
114
|
+
}
|
|
115
|
+
interface AuthorizationPolicyProvider {
|
|
116
|
+
current(): Promise<AuthorizationPolicyState>;
|
|
117
|
+
}
|
|
118
|
+
interface ToolApprovalRequest {
|
|
119
|
+
readonly approvalId: string;
|
|
120
|
+
readonly agentId: string;
|
|
121
|
+
readonly instanceId: string;
|
|
122
|
+
readonly inputDigest: string;
|
|
123
|
+
readonly operationId: string;
|
|
124
|
+
readonly runId: string;
|
|
125
|
+
readonly sessionKey: string;
|
|
126
|
+
readonly tenantKey: string;
|
|
127
|
+
readonly callId: string;
|
|
128
|
+
readonly toolId: string;
|
|
129
|
+
readonly toolVersion: string;
|
|
130
|
+
readonly risk: RivusToolRisk;
|
|
131
|
+
}
|
|
132
|
+
interface ToolApprovalService {
|
|
133
|
+
consume(request: ToolApprovalRequest): Promise<boolean>;
|
|
134
|
+
}
|
|
135
|
+
interface ToolBrokerOptions {
|
|
136
|
+
readonly approvals: ToolApprovalService;
|
|
137
|
+
readonly catalog: RivusPluginCatalog;
|
|
138
|
+
readonly hostTools?: ReadonlyArray<RivusHostToolDescriptor>;
|
|
139
|
+
readonly policy: AuthorizationPolicyProvider;
|
|
140
|
+
readonly operations?: ToolOperationLedger;
|
|
141
|
+
}
|
|
142
|
+
interface ToolExecutionRequest {
|
|
143
|
+
readonly authority: InvocationAuthorityRef;
|
|
144
|
+
readonly callId: string;
|
|
145
|
+
readonly toolId: string;
|
|
146
|
+
readonly version: string;
|
|
147
|
+
readonly input: unknown;
|
|
148
|
+
readonly operationId?: string;
|
|
149
|
+
readonly approvalId?: string;
|
|
150
|
+
}
|
|
151
|
+
interface ToolBroker {
|
|
152
|
+
execute(request: ToolExecutionRequest): Promise<unknown>;
|
|
153
|
+
}
|
|
154
|
+
declare class ToolInvocationDenied extends Error {
|
|
155
|
+
readonly name = "ToolInvocationDenied";
|
|
156
|
+
}
|
|
157
|
+
declare function createToolBroker(options: ToolBrokerOptions): ToolBroker;
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region src/infrastructure/pi/pi-tool-proxy.d.ts
|
|
160
|
+
interface PiToolApprovalRequest {
|
|
161
|
+
readonly agentId: string;
|
|
162
|
+
readonly allowedActorOpenIds: ReadonlyArray<string>;
|
|
163
|
+
readonly approvalId: string;
|
|
164
|
+
readonly callId: string;
|
|
165
|
+
readonly endpointId: string;
|
|
166
|
+
readonly inputDigest: string;
|
|
167
|
+
readonly instanceId: string;
|
|
168
|
+
readonly operationId: string;
|
|
169
|
+
readonly risk: RivusToolRisk;
|
|
170
|
+
readonly runId: string;
|
|
171
|
+
readonly sessionKey: string;
|
|
172
|
+
readonly signal?: AbortSignal;
|
|
173
|
+
readonly sourceMessageId: string;
|
|
174
|
+
readonly tenantKey: string;
|
|
175
|
+
readonly toolId: string;
|
|
176
|
+
readonly toolVersion: string;
|
|
177
|
+
}
|
|
178
|
+
interface PiToolApprovalGateway {
|
|
179
|
+
requestApproval(request: PiToolApprovalRequest): Promise<void>;
|
|
180
|
+
}
|
|
181
|
+
interface PiToolProxyOptions {
|
|
182
|
+
readonly agentId: string;
|
|
183
|
+
readonly approvals: PiToolApprovalGateway;
|
|
184
|
+
readonly broker: ToolBroker;
|
|
185
|
+
readonly getActiveInput: () => AgentLoopInput | undefined;
|
|
186
|
+
readonly instanceId: string;
|
|
187
|
+
readonly memoryScopes?: ReadonlyArray<MemoryScope>;
|
|
188
|
+
readonly toolGrantSet: RivusToolGrantSet;
|
|
189
|
+
readonly tools: ReadonlyArray<RivusResolvedToolDescriptor>;
|
|
190
|
+
}
|
|
191
|
+
declare function createPiToolProxyDefinitions(options: PiToolProxyOptions): ToolDefinition[];
|
|
192
|
+
declare function createPiToolNameResolver(tools: ReadonlyArray<Pick<RivusResolvedToolDescriptor, "id">>): (toolName: string) => string;
|
|
193
|
+
//#endregion
|
|
194
|
+
export { createRecoveryAction as A, ToolOperationReconciliation as C, createToolOperationLedger as D, ToolOperationState as E, InvalidRecoveryAction as O, ToolOperationLedger as S, ToolOperationRecord as T, InvocationAuthorityRef as _, createPiToolProxyDefinitions as a, ToolOperationBinding as b, ToolApprovalRequest as c, ToolBrokerOptions as d, ToolExecutionRequest as f, InvocationAuthority as g, InvalidInvocationAuthority as h, createPiToolNameResolver as i, RecoveryAction as k, ToolApprovalService as l, createToolBroker as m, PiToolApprovalRequest as n, AuthorizationPolicyProvider as o, ToolInvocationDenied as p, PiToolProxyOptions as r, AuthorizationPolicyState as s, PiToolApprovalGateway as t, ToolBroker as u, createInvocationAuthority as v, ToolOperationReconciliationOutcome as w, ToolOperationInspectResult as x, ToolOperationBeginResult as y };
|
package/dist/pi.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { a as createPiToolProxyDefinitions, i as createPiToolNameResolver, n as PiToolApprovalRequest, r as PiToolProxyOptions, t as PiToolApprovalGateway } from "./pi-tool-proxy.js";
|
|
2
|
+
import { o as RegisteredRivusSkill } from "./rivus-plugin.js";
|
|
1
3
|
import { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
2
4
|
|
|
3
5
|
//#region src/infrastructure/pi/pi-project-skill-read-tool.d.ts
|
|
@@ -9,4 +11,11 @@ declare function createPiProjectSkillReadTool(options: {
|
|
|
9
11
|
readonly skillPaths: ReadonlyArray<string>;
|
|
10
12
|
}): ToolDefinition;
|
|
11
13
|
//#endregion
|
|
12
|
-
|
|
14
|
+
//#region src/infrastructure/pi/pi-skill-tool.d.ts
|
|
15
|
+
interface PiSkillRuntime {
|
|
16
|
+
readonly prompt: string;
|
|
17
|
+
readonly tool?: ToolDefinition;
|
|
18
|
+
}
|
|
19
|
+
declare function createPiSkillRuntime(skills: ReadonlyArray<RegisteredRivusSkill>): PiSkillRuntime;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { type PiSkillRuntime, type PiToolApprovalGateway, type PiToolApprovalRequest, type PiToolProxyOptions, ProjectSkillReadDenied, createPiProjectSkillReadTool, createPiSkillRuntime, createPiToolNameResolver, createPiToolProxyDefinitions };
|
package/dist/pi.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { d as requiresToolApproval } from "./agent-memory.js";
|
|
2
|
+
import { l as createPiSkillRuntime, o as createInvocationAuthority, r as createToolInputDigest } from "./tool-input-digest.js";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
1
4
|
import { isAbsolute, relative } from "node:path";
|
|
2
5
|
import { readFile, realpath, stat } from "node:fs/promises";
|
|
6
|
+
import { Unsafe } from "typebox";
|
|
3
7
|
import { createReadToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
4
8
|
//#region src/infrastructure/pi/pi-project-skill-read-tool.ts
|
|
5
9
|
var ProjectSkillReadDenied = class extends Error {
|
|
@@ -30,4 +34,110 @@ async function authorize(path, sources) {
|
|
|
30
34
|
throw new ProjectSkillReadDenied("read is restricted to the bound Project Skill sources");
|
|
31
35
|
}
|
|
32
36
|
//#endregion
|
|
33
|
-
|
|
37
|
+
//#region src/infrastructure/pi/pi-tool-proxy.ts
|
|
38
|
+
function createPiToolProxyDefinitions(options) {
|
|
39
|
+
const names = /* @__PURE__ */ new Set();
|
|
40
|
+
return options.tools.map((tool) => {
|
|
41
|
+
const name = toPiToolName(tool.id);
|
|
42
|
+
if (names.has(name)) throw new Error(`Pi tool name collision: ${name}`);
|
|
43
|
+
names.add(name);
|
|
44
|
+
return {
|
|
45
|
+
description: tool.description,
|
|
46
|
+
execute: async (callId, input, signal) => {
|
|
47
|
+
const activeInput = options.getActiveInput();
|
|
48
|
+
const invocation = activeInput?.invocation;
|
|
49
|
+
if (!activeInput || !invocation) throw new Error(`tool ${tool.id} requires an active agent run with a trusted invocation`);
|
|
50
|
+
if (!invocation.tenantKey) throw new Error(`tool ${tool.id} requires a trusted tenant identity`);
|
|
51
|
+
throwIfAborted(signal ?? activeInput.abortSignal);
|
|
52
|
+
const inputDigest = createToolInputDigest(input);
|
|
53
|
+
const operationId = createBoundId("operation", {
|
|
54
|
+
agentId: options.agentId,
|
|
55
|
+
inputDigest,
|
|
56
|
+
instanceId: options.instanceId,
|
|
57
|
+
sourceMessageId: invocation.sourceMessageId,
|
|
58
|
+
toolId: tool.id,
|
|
59
|
+
toolVersion: tool.version
|
|
60
|
+
});
|
|
61
|
+
const approvalId = createBoundId("approval", {
|
|
62
|
+
callId,
|
|
63
|
+
operationId,
|
|
64
|
+
runId: activeInput.runId
|
|
65
|
+
});
|
|
66
|
+
if (requiresToolApproval(tool.risk)) {
|
|
67
|
+
if (invocation.allowedActorOpenIds.length === 0) throw new Error(`tool ${tool.id} requires at least one trusted approval actor`);
|
|
68
|
+
await options.approvals.requestApproval({
|
|
69
|
+
agentId: options.agentId,
|
|
70
|
+
allowedActorOpenIds: invocation.allowedActorOpenIds,
|
|
71
|
+
approvalId,
|
|
72
|
+
callId,
|
|
73
|
+
endpointId: invocation.endpointId,
|
|
74
|
+
inputDigest,
|
|
75
|
+
instanceId: options.instanceId,
|
|
76
|
+
operationId,
|
|
77
|
+
risk: tool.risk,
|
|
78
|
+
runId: activeInput.runId,
|
|
79
|
+
sessionKey: activeInput.sessionKey,
|
|
80
|
+
signal: signal ?? activeInput.abortSignal,
|
|
81
|
+
sourceMessageId: invocation.sourceMessageId,
|
|
82
|
+
tenantKey: invocation.tenantKey,
|
|
83
|
+
toolId: tool.id,
|
|
84
|
+
toolVersion: tool.version
|
|
85
|
+
});
|
|
86
|
+
throwIfAborted(signal ?? activeInput.abortSignal);
|
|
87
|
+
}
|
|
88
|
+
const result = await options.broker.execute({
|
|
89
|
+
authority: createInvocationAuthority({
|
|
90
|
+
agentId: options.agentId,
|
|
91
|
+
instanceId: options.instanceId,
|
|
92
|
+
...invocation.memory ? { memory: {
|
|
93
|
+
...invocation.memory,
|
|
94
|
+
scopes: options.memoryScopes ?? []
|
|
95
|
+
} } : {},
|
|
96
|
+
runId: activeInput.runId,
|
|
97
|
+
sessionKey: activeInput.sessionKey,
|
|
98
|
+
sourceMessageId: invocation.sourceMessageId,
|
|
99
|
+
tenantKey: invocation.tenantKey,
|
|
100
|
+
toolGrantSet: options.toolGrantSet
|
|
101
|
+
}),
|
|
102
|
+
callId,
|
|
103
|
+
input,
|
|
104
|
+
operationId,
|
|
105
|
+
...requiresToolApproval(tool.risk) ? { approvalId } : {},
|
|
106
|
+
toolId: tool.id,
|
|
107
|
+
version: tool.version
|
|
108
|
+
});
|
|
109
|
+
return {
|
|
110
|
+
content: [{
|
|
111
|
+
text: stringifyToolResult(result),
|
|
112
|
+
type: "text"
|
|
113
|
+
}],
|
|
114
|
+
details: result
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
executionMode: "sequential",
|
|
118
|
+
label: tool.id,
|
|
119
|
+
name,
|
|
120
|
+
parameters: Unsafe(tool.inputSchema),
|
|
121
|
+
promptSnippet: `${name}: ${tool.description}`
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function createPiToolNameResolver(tools) {
|
|
126
|
+
const toolIdsByPiName = new Map(tools.map((tool) => [toPiToolName(tool.id), tool.id]));
|
|
127
|
+
return (toolName) => toolIdsByPiName.get(toolName) ?? toolName;
|
|
128
|
+
}
|
|
129
|
+
function toPiToolName(toolId) {
|
|
130
|
+
return `rivus_${toolId.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
131
|
+
}
|
|
132
|
+
function createBoundId(kind, binding) {
|
|
133
|
+
return `${kind}:${createHash("sha256").update(JSON.stringify(binding)).digest("hex")}`;
|
|
134
|
+
}
|
|
135
|
+
function throwIfAborted(signal) {
|
|
136
|
+
if (signal.aborted) throw signal.reason ?? /* @__PURE__ */ new Error("tool execution was aborted");
|
|
137
|
+
}
|
|
138
|
+
function stringifyToolResult(result) {
|
|
139
|
+
if (typeof result === "string") return result;
|
|
140
|
+
return JSON.stringify(result ?? null);
|
|
141
|
+
}
|
|
142
|
+
//#endregion
|
|
143
|
+
export { ProjectSkillReadDenied, createPiProjectSkillReadTool, createPiSkillRuntime, createPiToolNameResolver, createPiToolProxyDefinitions };
|
package/dist/rivus-daemon-cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
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";
|
|
@@ -432,6 +433,7 @@ function createFeishuCardRollover(options) {
|
|
|
432
433
|
const leaseMs = options.leaseMs ?? 51e4;
|
|
433
434
|
if (!Number.isSafeInteger(leaseMs) || leaseMs < 1) throw new Error("Feishu card stream lease must be a positive integer");
|
|
434
435
|
const counters = createCounters();
|
|
436
|
+
const latestTextByRun = /* @__PURE__ */ new Map();
|
|
435
437
|
const liveRuns = /* @__PURE__ */ new Map();
|
|
436
438
|
const semaphore = Effect.unsafeMakeSemaphore(1);
|
|
437
439
|
const exclusive = (effect) => semaphore.withPermits(1)(effect);
|
|
@@ -447,7 +449,7 @@ function createFeishuCardRollover(options) {
|
|
|
447
449
|
const presentationId = (runId, generation) => `${runId}#${generation}`;
|
|
448
450
|
const publishProgress = (action) => Effect.suspend(() => {
|
|
449
451
|
const chain = options.store.chain(action.runId);
|
|
450
|
-
if (chain && acceptsCardPresentationProgress(chain)) return options.publisher.publish(action);
|
|
452
|
+
if (chain && acceptsCardPresentationProgress(chain)) return options.publisher.publish(action).pipe(Effect.tap(() => Effect.sync(() => latestTextByRun.set(action.runId, action.text))));
|
|
451
453
|
return recordNow({
|
|
452
454
|
...chain ? {
|
|
453
455
|
generation: chain.activeGeneration,
|
|
@@ -457,20 +459,28 @@ function createFeishuCardRollover(options) {
|
|
|
457
459
|
type: "stale_update_dropped"
|
|
458
460
|
});
|
|
459
461
|
});
|
|
460
|
-
const publishTerminal = (action) =>
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
462
|
+
const publishTerminal = (action) => {
|
|
463
|
+
const latestText = latestTextByRun.get(action.runId);
|
|
464
|
+
const resolvedAction = action.type === "cancel" && action.text === void 0 && latestText !== void 0 ? {
|
|
465
|
+
...action,
|
|
466
|
+
text: latestText
|
|
467
|
+
} : action;
|
|
468
|
+
return options.publisher.publish(resolvedAction).pipe(Effect.tapError((error) => recordNow({
|
|
469
|
+
error,
|
|
470
|
+
runId: action.runId,
|
|
471
|
+
type: "terminal_delivery_failed"
|
|
472
|
+
})), Effect.tap(() => options.store.markTerminal({
|
|
473
|
+
runId: action.runId,
|
|
474
|
+
terminalReceiptId: `${action.runId}:${action.type}`
|
|
475
|
+
}).pipe(Effect.catchAll((error) => recordNow({
|
|
476
|
+
error,
|
|
477
|
+
runId: action.runId,
|
|
478
|
+
type: "presentation_write_failed"
|
|
479
|
+
})))), Effect.ensuring(Effect.sync(() => {
|
|
480
|
+
latestTextByRun.delete(action.runId);
|
|
481
|
+
liveRuns.delete(action.runId);
|
|
482
|
+
})));
|
|
483
|
+
};
|
|
474
484
|
const publishAction = (action) => {
|
|
475
485
|
switch (action.type) {
|
|
476
486
|
case "update_text": return publishProgress(action);
|
|
@@ -504,6 +514,7 @@ function createFeishuCardRollover(options) {
|
|
|
504
514
|
};
|
|
505
515
|
const predecessor = start.presentation;
|
|
506
516
|
const generation = predecessor.generation + 1;
|
|
517
|
+
const text = latestTextByRun.get(runId);
|
|
507
518
|
record({
|
|
508
519
|
cardId: predecessor.cardId,
|
|
509
520
|
generation,
|
|
@@ -516,7 +527,8 @@ function createFeishuCardRollover(options) {
|
|
|
516
527
|
const created = yield* options.createSuccessor({
|
|
517
528
|
generation,
|
|
518
529
|
presentationId: successorId,
|
|
519
|
-
run
|
|
530
|
+
run,
|
|
531
|
+
...text === void 0 ? {} : { text }
|
|
520
532
|
}).pipe(Effect.map((target) => ({ target })), Effect.catchAll((error) => options.store.failHandoff({
|
|
521
533
|
failedAt: startedAt.toISOString(),
|
|
522
534
|
runId
|
|
@@ -538,6 +550,7 @@ function createFeishuCardRollover(options) {
|
|
|
538
550
|
};
|
|
539
551
|
yield* options.publisher.publish({
|
|
540
552
|
runId,
|
|
553
|
+
...text === void 0 ? {} : { text },
|
|
541
554
|
type: "handoff"
|
|
542
555
|
}).pipe(Effect.catchAll((error) => recordNow({
|
|
543
556
|
cardId: predecessor.cardId,
|
|
@@ -583,6 +596,7 @@ function createFeishuCardRollover(options) {
|
|
|
583
596
|
runId: run.runId,
|
|
584
597
|
sourceMessageId: run.messageId
|
|
585
598
|
});
|
|
599
|
+
latestTextByRun.delete(run.runId);
|
|
586
600
|
liveRuns.set(run.runId, run);
|
|
587
601
|
return presentation;
|
|
588
602
|
})),
|
|
@@ -603,6 +617,10 @@ function createFeishuCardRollover(options) {
|
|
|
603
617
|
});
|
|
604
618
|
},
|
|
605
619
|
publish: (action) => exclusive(publishAction(action)),
|
|
620
|
+
releaseRun: (runId) => Effect.sync(() => {
|
|
621
|
+
latestTextByRun.delete(runId);
|
|
622
|
+
liveRuns.delete(runId);
|
|
623
|
+
}),
|
|
606
624
|
recover: () => exclusive(Effect.gen(function* () {
|
|
607
625
|
const compensatedAt = yield* options.clock.now;
|
|
608
626
|
const compensated = yield* options.store.compensateInterruptedHandoffs(compensatedAt.toISOString());
|
|
@@ -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 {
|
|
212
|
+
export { resolveRivusAgentDefinition as n, deepFreeze as r, createRivusPluginCatalog as t };
|