@rivus/agent 0.13.2 → 0.14.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 +20 -15
- package/dist/acp.d.ts +40 -40
- package/dist/acp.js +71 -31
- package/dist/bootstrap/pi-feishu.d.ts +20 -0
- package/dist/bootstrap/pi-feishu.js +594 -0
- package/dist/{agent-loop.d.ts → chunks/agent-loop.d.ts} +293 -44
- package/dist/chunks/agent-loop.js +1272 -0
- package/dist/chunks/api.d.ts +70 -0
- package/dist/chunks/api.js +471 -0
- package/dist/{rivus-plugin.d.ts → chunks/api2.d.ts} +271 -120
- package/dist/chunks/api2.js +1331 -0
- package/dist/chunks/api3.d.ts +402 -0
- package/dist/chunks/index.d.ts +3662 -0
- package/dist/chunks/module.js +267 -0
- package/dist/chunks/pi-skill-tool.js +460 -0
- package/dist/chunks/pi-tool-proxy.d.ts +188 -0
- package/dist/chunks/pi.js +329 -0
- package/dist/{rivus-daemon-cli.js → chunks/rivus-daemon-cli.js} +2197 -1526
- package/dist/{rivus-plugin-testkit.d.ts → chunks/rivus-plugin-testkit.d.ts} +1 -1
- package/dist/{rivus-plugin-testkit.js → chunks/rivus-plugin-testkit.js} +11 -3
- package/dist/chunks/sha256-digest.js +12 -0
- package/dist/chunks/spi.d.ts +1 -0
- package/dist/chunks/spi.js +2 -0
- package/dist/chunks/src.js +9897 -0
- package/dist/cli.js +602 -93
- package/dist/index.d.ts +8 -3645
- package/dist/index.js +9 -10483
- package/dist/mcp.d.ts +3 -38
- package/dist/mcp.js +4 -114
- package/dist/pi.d.ts +95 -9
- package/dist/pi.js +3 -146
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +1 -1
- package/examples/pi-feishu-deployment.bootstrap.ts +35 -46
- package/examples/pi-feishu.bootstrap.ts +35 -20
- package/examples/rivus-starter.plugin.mjs +3 -1
- package/package.json +8 -2
- package/dist/agent-loop.js +0 -121
- package/dist/agent-memory.d.ts +0 -100
- package/dist/agent-memory.js +0 -114
- package/dist/background-session-authority.js +0 -224
- package/dist/background-session-input.js +0 -45
- package/dist/background-session-service.d.ts +0 -291
- package/dist/pi-tool-proxy.d.ts +0 -197
- package/dist/rivus-plugin-registry.js +0 -215
- package/dist/tool-input-digest.js +0 -128
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ The first milestone is intentionally narrow: make the agent loop and agent harne
|
|
|
10
10
|
|
|
11
11
|
- TypeScript ESM package.
|
|
12
12
|
- Public Plugin SDK with atomic Plugin registration, immutable Catalog snapshots, deterministic Agent Deployment resolution, an explicit Required/Optional Plugin Loader, safe Node module resolution from a Deployment Root, and a manifest-driven Multi-agent Deployment Daemon. Concrete Agent products remain external packages.
|
|
13
|
+
- Revisioned Pi native Runtime Tool grants with a closed seven-Tool vocabulary, exact Profile ∩ Deployment narrowing, fail-closed defaults, and explicit full capability only in the Personal Home starter. Pi Skill discovery accepts an empty catalog and is limited to user-global plus explicit Project Space roots; project-ambient resources stay disabled.
|
|
13
14
|
- Host-bound Workspace Instructions API and built-in `AGENTS.md` provider with deterministic root-to-target discovery, immutable source digests, nested mutation refresh diagnostics, UTF-8/path/symlink checks, and whole-source byte budgeting. The deployment example injects the root View into Pi while Tool-target refresh remains enforced by the provider boundary.
|
|
14
15
|
- Host-issued invocation authority and a call-time Tool Broker that checks exact grants, pinned versions, online revocation, stable operation IDs, durable side-effect fencing, and one-time approval receipts bound to canonical input digests. The Pi Tool Proxy and Feishu Human Interaction gateway are wired in the deployment example.
|
|
15
16
|
- Multi-agent Host primitives with trusted Endpoint bindings, stable Runtime Generation/Instance identities, lazy per-instance Runtime pooling, isolated active-run gates, and restart restoration from persisted registry records.
|
|
@@ -54,22 +55,23 @@ npm install @rivus/agent
|
|
|
54
55
|
npx rivus --help
|
|
55
56
|
```
|
|
56
57
|
|
|
57
|
-
Create
|
|
58
|
+
Create the default Personal Agent Home without cloning this repository or installing another local Rivus copy:
|
|
58
59
|
|
|
59
60
|
```bash
|
|
60
|
-
npm install --global
|
|
61
|
-
rivus
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
npm install --global \
|
|
62
|
+
@rivus/agent \
|
|
63
|
+
@earendil-works/pi-coding-agent@^0.80.6 \
|
|
64
|
+
@larksuiteoapi/node-sdk@^1.70.0
|
|
65
|
+
rivus setup
|
|
66
|
+
cp "$HOME/.rivus-agent/.env.example" "$HOME/.rivus-agent/.env"
|
|
67
|
+
# Fill the Feishu and model-provider values in ~/.rivus-agent/.env.
|
|
68
|
+
rivus doctor
|
|
69
|
+
rivus start
|
|
68
70
|
```
|
|
69
71
|
|
|
70
|
-
`
|
|
72
|
+
`setup` refuses to overwrite existing Home files. `start`, `status`, and `check-config` read `RIVUS_HOME` or `~/.rivus-agent`, use its configured Workspace as cwd, and keep state outside npm installation files. `doctor` checks the Home, global modules, manifest, Workspace, and enabled Endpoint credential references without importing Plugin code or contacting external services. Existing standalone projects remain supported through `rivus init <directory>` and `rivus doctor <directory>`. See the [local deployment runbook](docs/en/operations/local-deployment.md).
|
|
71
73
|
|
|
72
|
-
The Pi plus Feishu
|
|
74
|
+
The Pi plus Feishu Bootstrap is an application-edge package export: install `@earendil-works/pi-coding-agent` and `@larksuiteoapi/node-sdk` beside the global Rivus package. The `@rivus/agent` core keeps those SDKs out of its mandatory runtime dependency graph.
|
|
73
75
|
|
|
74
76
|
```bash
|
|
75
77
|
npm install @earendil-works/pi-coding-agent@^0.80.6 @larksuiteoapi/node-sdk@^1.70.0
|
|
@@ -87,7 +89,7 @@ vp run check
|
|
|
87
89
|
|
|
88
90
|
npm releases are produced only by the `Publish npm` GitHub Actions workflow after a GitHub Release is published for an exact `v<package version>` tag on `main`. The workflow uses npm Trusted Publishing through OIDC and contains no long-lived registry token. See the [npm release runbook](docs/en/operations/npm-release.md) for the one-time first-package bootstrap and normal release procedure.
|
|
89
91
|
|
|
90
|
-
For a manifest-driven multi-agent deployment, keep `rivus.config.json
|
|
92
|
+
For a manifest-driven multi-agent deployment, keep `rivus.config.json` in Rivus Home and install declared Plugin packages beside the global Rivus package. `createConfiguredRivusDeploymentDaemon()` validates the manifest, resolves only declared modules from the Home or Host-trusted npm roots, disables deployments belonging to failed Optional Plugins, and blocks startup when a Required Plugin fails:
|
|
91
93
|
|
|
92
94
|
```json
|
|
93
95
|
{
|
|
@@ -169,7 +171,7 @@ await daemon.start(); // rejects when an enabled Required Endpoint or Automation
|
|
|
169
171
|
|
|
170
172
|
Endpoint factories receive a Host-bound `handle()` function. Inbound payload fields cannot select another Agent or Endpoint. `createConfiguredRivusDaemonBootstrap()` is the small, explicit single-lane Pi/Feishu composition; manifest deployments use the multi-agent path directly, without a parallel compatibility model.
|
|
171
173
|
|
|
172
|
-
[`examples/rivus.config.json`](examples/rivus.config.json) and [`examples/pi-feishu-deployment.bootstrap.ts`](examples/pi-feishu-deployment.bootstrap.ts) form a concrete two-bot composition. Each `credentialRef: "env:<PREFIX>"` resolves only `<PREFIX>_APP_ID` and `<PREFIX>_APP_SECRET`; each Endpoint owns its WebSocket client, durable Inbox, bounded concurrent worker, CardKit target/delivery state, Human Interaction JSONL repository, and lifecycle. Its unique Manifest Session Namespace is prepended before the trusted Host route reaches a fair per-session Scheduler, Harness lane, and Pi Session Registry. Startup resolves the Bot Open ID, waits for the SDK `onReady` handshake, repairs missing terminal CardKit projections, and applies `groupPolicy` before the durable accept. The example restores a separate event log, Tool operation ledger, and Pi session directory per Agent Instance, plus one deployment-scoped append-only Agent Memory log.
|
|
174
|
+
[`examples/rivus.config.json`](examples/rivus.config.json) and [`examples/pi-feishu-deployment.bootstrap.ts`](examples/pi-feishu-deployment.bootstrap.ts) form a concrete two-bot composition. Each `credentialRef: "env:<PREFIX>"` resolves only `<PREFIX>_APP_ID` and `<PREFIX>_APP_SECRET`; each Endpoint owns its WebSocket client, durable Inbox, bounded concurrent worker, CardKit target/delivery state, Human Interaction JSONL repository, and lifecycle. Its unique Manifest Session Namespace is prepended before the trusted Host route reaches a fair per-session Scheduler, Harness lane, and Pi Session Registry. Startup resolves the Bot Open ID, waits for the SDK `onReady` handshake, repairs missing terminal CardKit projections, and applies `groupPolicy` before the durable accept. The example restores a separate event log, Tool operation ledger, and Pi session directory per Agent Instance, plus one deployment-scoped append-only Agent Memory log. Native Pi tools default to none and are activated only by the resolved `runtimeToolGrantSet`; custom Tools come only from the resolved Agent definition. Extensions, prompt templates, themes, ambient project settings, and ambient Pi Skill discovery remain disabled. Pi loads existing user-global Skill roots plus only the selected Project Space's explicit sources, accepts an empty catalog, and validates every `/skill:<name>` before model execution. A bounded `AGENTS.md` View supplies context without granting authority.
|
|
173
175
|
|
|
174
176
|
Interactive Endpoints default `progressDisplay` to `collapsed`: public assistant narration and inspectable Skill/Tool actions remain in chronological order, and every action owns a small native collapsible panel rather than being collected into one process appendix. `expanded` opens completed action panels initially and `hidden` omits them; a running action stays open so its safe parameters and current result are visible. A channel-neutral `RunPresentation` read model preserves stable steps, status, duration, and safe Tool input/result projections across streaming updates and successor cards. Sensitive fields are redacted, machine paths normalized, and long values explicitly truncated before a channel renderer sees them; private reasoning and raw Tool payloads never enter the presentation IR. Ordinary replies never gain an empty process panel. A rollover freezes the predecessor exactly as last rendered and starts a blank successor that receives only post-breakpoint content. Scheduled Automations use a separate final-only `AutomationPresentation` IR: Plugins own title, metadata, sections, items, notes, and sources, while the channel renderer owns visual components.
|
|
175
177
|
|
|
@@ -425,7 +427,7 @@ Recognized variables:
|
|
|
425
427
|
- `RIVUS_WEATHER_DEFAULT_LOCATION` selects the example `current-weather` Tool's fallback city and defaults to `北京`; it is not a Core setting.
|
|
426
428
|
- `RIVUS_TELEMETRY_ENVIRONMENT` defaults to `NODE_ENV`, then `local`; `RIVUS_TELEMETRY_SERVICE_NAME` defaults to `rivus-agent`.
|
|
427
429
|
|
|
428
|
-
For both SDK bootstrap templates, `PI_MODEL` should use Pi's provider/model form when `PI_API_KEY`, `PI_API_KEY_FILE`, or `PI_BASE_URL` is set, for example `anthropic/claude-opus-4-5` or `zai/glm-5.1` for GLM BYOK. The templates apply the resolved Pi API key through Pi `AuthStorage.setRuntimeApiKey()`, resolve the model through Pi's public `ModelRegistry.find(provider, modelId)` API, and apply `PI_BASE_URL` by
|
|
430
|
+
For both SDK bootstrap templates, `PI_MODEL` should use Pi's provider/model form when `PI_API_KEY`, `PI_API_KEY_FILE`, or `PI_BASE_URL` is set, for example `anthropic/claude-opus-4-5` or `zai/glm-5.1` for GLM BYOK. The templates apply the resolved Pi API key through Pi `AuthStorage.setRuntimeApiKey()`, resolve the model through Pi's public `ModelRegistry.find(provider, modelId)` API, and apply `PI_BASE_URL` by merging a local `.rivus/pi-models.json` provider override without removing existing custom models or other providers, matching Pi's `models.json` configuration model.
|
|
429
431
|
|
|
430
432
|
## Core Usage
|
|
431
433
|
|
|
@@ -463,6 +465,7 @@ catalog.registerPlugin({
|
|
|
463
465
|
id: "example",
|
|
464
466
|
memory: { scopes: [] },
|
|
465
467
|
model: { provider: "example" },
|
|
468
|
+
runtimeTools: { allow: ["read", "grep", "find", "ls"] },
|
|
466
469
|
skills: { allow: [] },
|
|
467
470
|
systemPrompt: "Use trusted example sources.",
|
|
468
471
|
tools: { allow: ["example-agent/read"] }
|
|
@@ -475,11 +478,13 @@ const definition = resolveRivusAgentDefinition(catalog, {
|
|
|
475
478
|
endpointIds: ["example-feishu"],
|
|
476
479
|
pluginId: "example-agent",
|
|
477
480
|
profileId: "example",
|
|
481
|
+
runtimeTools: { allow: ["read", "grep"] },
|
|
482
|
+
skills: { allow: [] },
|
|
478
483
|
tools: { allow: ["example-agent/read"] }
|
|
479
484
|
});
|
|
480
485
|
```
|
|
481
486
|
|
|
482
|
-
The resolved definition exposes immutable Tool schemas and a `
|
|
487
|
+
The resolved definition exposes immutable Tool schemas, a `ToolGrantSet`, and a `runtimeToolGrantSet` containing only `read` and `grep`; executor factories remain inside the Catalog boundary. Wildcards, duplicate identifiers, unknown references, and incompatible Plugin API versions are rejected. Missing Runtime Tool allowlists resolve to an empty native grant.
|
|
483
488
|
|
|
484
489
|
External Plugin packages can run reusable conformance checks from the testing subpath:
|
|
485
490
|
|
package/dist/acp.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as AgentLoopInput, t as AgentLoop } from "./chunks/agent-loop.js";
|
|
2
2
|
import * as acp from "@agentclientprotocol/sdk";
|
|
3
3
|
|
|
4
|
-
//#region src/
|
|
4
|
+
//#region src/adapters/acp/runtime/acp-agent-loop.d.ts
|
|
5
5
|
type AcpToolCallStatus = "pending" | "in_progress" | "completed" | "failed";
|
|
6
6
|
interface AcpSessionUpdate {
|
|
7
7
|
readonly content?: unknown;
|
|
@@ -25,14 +25,8 @@ interface AcpAgentSession {
|
|
|
25
25
|
dispose?(): Promise<void> | void;
|
|
26
26
|
invalidate?(): Promise<void> | void;
|
|
27
27
|
}
|
|
28
|
-
interface AcpAgentLoopOptions {
|
|
29
|
-
readonly cancellationSettleTimeoutMs?: number;
|
|
30
|
-
readonly disposeSessionAfterRun?: boolean;
|
|
31
|
-
readonly resolveSession: (input: AgentLoopInput) => Promise<AcpAgentSession> | AcpAgentSession;
|
|
32
|
-
}
|
|
33
|
-
declare function createAcpAgentLoop(options: AcpAgentLoopOptions): AgentLoop;
|
|
34
28
|
//#endregion
|
|
35
|
-
//#region src/
|
|
29
|
+
//#region src/adapters/acp/runtime/acp-permission-policy.d.ts
|
|
36
30
|
interface AcpPermissionOption {
|
|
37
31
|
readonly kind: "allow_once" | "allow_always" | "reject_once" | "reject_always";
|
|
38
32
|
readonly name: string;
|
|
@@ -64,24 +58,14 @@ interface AcpSessionPermissionContext {
|
|
|
64
58
|
type AcpSessionPermissionPolicy = (request: AcpPermissionRequest, context: AcpSessionPermissionContext) => Promise<AcpPermissionSelection | undefined> | AcpPermissionSelection | undefined;
|
|
65
59
|
declare function decideAcpPermission(request: AcpPermissionRequest, policy?: AcpPermissionPolicy): Promise<AcpPermissionDecision>;
|
|
66
60
|
//#endregion
|
|
67
|
-
//#region src/
|
|
61
|
+
//#region src/adapters/acp/runtime/acp-permission-bridge.d.ts
|
|
68
62
|
interface AcpPermissionBridge {
|
|
69
63
|
readonly policy: AcpSessionPermissionPolicy;
|
|
70
64
|
bind(sessionKey: string, policy: AcpPermissionPolicy): () => void;
|
|
71
65
|
}
|
|
72
66
|
declare function createAcpPermissionBridge(): AcpPermissionBridge;
|
|
73
67
|
//#endregion
|
|
74
|
-
//#region src/
|
|
75
|
-
interface AcpAgentServerOptions {
|
|
76
|
-
readonly agentName?: string;
|
|
77
|
-
readonly loop: AgentLoop;
|
|
78
|
-
readonly permissionBridge?: AcpPermissionBridge;
|
|
79
|
-
readonly workingDirectory: string;
|
|
80
|
-
}
|
|
81
|
-
declare function createAcpAgentServer(options: AcpAgentServerOptions): acp.AgentApp;
|
|
82
|
-
declare function serveAcpAgentOnStdio(app: acp.AgentApp): Promise<void>;
|
|
83
|
-
//#endregion
|
|
84
|
-
//#region src/infrastructure/acp/acp-session-store.d.ts
|
|
68
|
+
//#region src/adapters/acp/runtime/acp-session-store.d.ts
|
|
85
69
|
interface AcpSessionRecord {
|
|
86
70
|
readonly sessionId: string;
|
|
87
71
|
}
|
|
@@ -99,7 +83,7 @@ interface JsonAcpSessionStoreOptions {
|
|
|
99
83
|
*/
|
|
100
84
|
declare function createJsonAcpSessionStore(options: JsonAcpSessionStoreOptions): AcpSessionStore;
|
|
101
85
|
//#endregion
|
|
102
|
-
//#region src/
|
|
86
|
+
//#region src/adapters/acp/runtime/acp-stdio-agent-loop.d.ts
|
|
103
87
|
interface AcpMcpServerEnvironmentVariable {
|
|
104
88
|
readonly name: string;
|
|
105
89
|
readonly value: string;
|
|
@@ -110,35 +94,51 @@ interface AcpMcpServer {
|
|
|
110
94
|
readonly env: ReadonlyArray<AcpMcpServerEnvironmentVariable>;
|
|
111
95
|
readonly name: string;
|
|
112
96
|
}
|
|
97
|
+
declare class AcpSessionResumeUnavailable extends Error {
|
|
98
|
+
readonly sessionId: string;
|
|
99
|
+
readonly name = "AcpSessionResumeUnavailable";
|
|
100
|
+
constructor(sessionId: string);
|
|
101
|
+
}
|
|
102
|
+
declare class AcpSessionResumeFailed extends Error {
|
|
103
|
+
readonly sessionId: string;
|
|
104
|
+
readonly cause: unknown;
|
|
105
|
+
readonly name = "AcpSessionResumeFailed";
|
|
106
|
+
constructor(sessionId: string, cause: unknown);
|
|
107
|
+
}
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/adapters/compatibility/agent-execution/acp/acp-runtime.d.ts
|
|
110
|
+
interface AcpAgentLoopOptions {
|
|
111
|
+
readonly cancellationSettleTimeoutMs?: number;
|
|
112
|
+
readonly disposeSessionAfterRun?: boolean;
|
|
113
|
+
readonly resolveSession: (input: AgentLoopInput) => Promise<AcpAgentSession> | AcpAgentSession;
|
|
114
|
+
}
|
|
115
|
+
interface AcpAgentServerOptions {
|
|
116
|
+
readonly loop: AgentLoop;
|
|
117
|
+
readonly workingDirectory: string;
|
|
118
|
+
readonly agentName?: string;
|
|
119
|
+
readonly permissionBridge?: AcpPermissionBridge;
|
|
120
|
+
}
|
|
113
121
|
interface AcpStdioAgentLoopOptions {
|
|
114
|
-
readonly arguments?: ReadonlyArray<string>;
|
|
115
|
-
readonly clientName?: string;
|
|
116
122
|
readonly command: string;
|
|
117
|
-
readonly
|
|
118
|
-
readonly initializationTimeoutMs?: number;
|
|
123
|
+
readonly workingDirectory: string;
|
|
119
124
|
readonly mcpServers?: (input: AgentLoopInput) => ReadonlyArray<AcpMcpServer>;
|
|
120
|
-
readonly onStderr?: (text: string) => void;
|
|
121
|
-
readonly permissionPolicy?: AcpSessionPermissionPolicy;
|
|
122
125
|
/** Persist provider session IDs so a restarted ACP child can load/resume them. */
|
|
123
126
|
readonly sessionStore?: AcpSessionStore;
|
|
127
|
+
readonly permissionPolicy?: AcpSessionPermissionPolicy;
|
|
128
|
+
readonly environment?: Readonly<Record<string, string>>;
|
|
129
|
+
readonly arguments?: ReadonlyArray<string>;
|
|
130
|
+
readonly clientName?: string;
|
|
131
|
+
readonly initializationTimeoutMs?: number;
|
|
124
132
|
readonly terminationTimeoutMs?: number;
|
|
125
|
-
readonly
|
|
133
|
+
readonly onStderr?: (text: string) => void;
|
|
126
134
|
}
|
|
127
135
|
interface AcpStdioAgentLoopHandle {
|
|
128
136
|
readonly loop: AgentLoop;
|
|
129
137
|
dispose(): Promise<void>;
|
|
130
138
|
}
|
|
139
|
+
declare function createAcpAgentLoop(options: AcpAgentLoopOptions): AgentLoop;
|
|
140
|
+
declare function createAcpAgentServer(options: AcpAgentServerOptions): acp.AgentApp;
|
|
141
|
+
declare function serveAcpAgentOnStdio(app: acp.AgentApp): Promise<void>;
|
|
131
142
|
declare function createAcpStdioAgentLoop(options: AcpStdioAgentLoopOptions): AcpStdioAgentLoopHandle;
|
|
132
|
-
declare class AcpSessionResumeUnavailable extends Error {
|
|
133
|
-
readonly sessionId: string;
|
|
134
|
-
readonly name = "AcpSessionResumeUnavailable";
|
|
135
|
-
constructor(sessionId: string);
|
|
136
|
-
}
|
|
137
|
-
declare class AcpSessionResumeFailed extends Error {
|
|
138
|
-
readonly sessionId: string;
|
|
139
|
-
readonly cause: unknown;
|
|
140
|
-
readonly name = "AcpSessionResumeFailed";
|
|
141
|
-
constructor(sessionId: string, cause: unknown);
|
|
142
|
-
}
|
|
143
143
|
//#endregion
|
|
144
144
|
export { type AcpAgentLoopOptions, type AcpAgentServerOptions, type AcpAgentSession, type AcpPermissionBridge, type AcpPermissionDecision, type AcpPermissionOption, type AcpPermissionPolicy, type AcpPermissionRequest, type AcpPermissionSelection, type AcpPermissionToolCall, type AcpPromptResult, type AcpSessionPermissionContext, type AcpSessionPermissionPolicy, type AcpSessionRecord, AcpSessionResumeFailed, AcpSessionResumeUnavailable, type AcpSessionStore, type AcpSessionUpdate, type AcpStdioAgentLoopHandle, type AcpStdioAgentLoopOptions, type AcpToolCallStatus, type JsonAcpSessionStoreOptions, createAcpAgentLoop, createAcpAgentServer, createAcpPermissionBridge, createAcpStdioAgentLoop, createJsonAcpSessionStore, decideAcpPermission, serveAcpAgentOnStdio };
|
package/dist/acp.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as createAgentLoopToolExecutionUpdate, I as createAgentLoopTextDelta, L as createAgentLoopThinkingDelta, R as createAgentLoopToolExecutionEnd, V as createAgentLoopTurnStart, c as toEffectAgentLoop, o as fromEffectAgentLoop, s as toCompatibilityAgentLoopInput, z as createAgentLoopToolExecutionStart } from "./chunks/agent-loop.js";
|
|
2
|
+
import "./chunks/spi.js";
|
|
3
|
+
import * as acp from "@agentclientprotocol/sdk";
|
|
2
4
|
import { Effect, Stream } from "effect";
|
|
3
5
|
import { randomUUID } from "node:crypto";
|
|
4
6
|
import { Readable, Writable } from "node:stream";
|
|
5
|
-
import * as acp from "@agentclientprotocol/sdk";
|
|
6
7
|
import { spawn } from "node:child_process";
|
|
7
8
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
8
9
|
import { dirname } from "node:path";
|
|
9
|
-
//#region src/
|
|
10
|
-
function createAcpAgentLoop(options) {
|
|
11
|
-
const loop = createAsyncIterableAgentLoop({ run: (input) => runAcpSession(input, options) });
|
|
10
|
+
//#region src/adapters/acp/runtime/acp-agent-loop.ts
|
|
11
|
+
function createAcpAgentLoop$1(options) {
|
|
12
12
|
return {
|
|
13
|
-
run: (input) =>
|
|
13
|
+
run: (input) => Stream.fromAsyncIterable(runAcpSession(input, options), (error) => error),
|
|
14
14
|
supportsSteering: true
|
|
15
15
|
};
|
|
16
16
|
}
|
|
@@ -41,7 +41,8 @@ async function* runAcpSession(input, options) {
|
|
|
41
41
|
});
|
|
42
42
|
};
|
|
43
43
|
input.abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
44
|
-
|
|
44
|
+
const takeSteering = () => input.steering ? Effect.runPromise(input.steering.next()) : void 0;
|
|
45
|
+
let steering = takeSteering();
|
|
45
46
|
try {
|
|
46
47
|
if (input.abortSignal.aborted) onAbort();
|
|
47
48
|
while (!currentTurn.completed || updates.length > 0) {
|
|
@@ -68,7 +69,7 @@ async function* runAcpSession(input, options) {
|
|
|
68
69
|
wake?.();
|
|
69
70
|
wake = void 0;
|
|
70
71
|
});
|
|
71
|
-
steering =
|
|
72
|
+
steering = takeSteering();
|
|
72
73
|
}
|
|
73
74
|
if (signal.type === "turn_completed" && currentTurn.completed) break;
|
|
74
75
|
if (signal.type === "wake") wake = void 0;
|
|
@@ -196,8 +197,8 @@ function isRecord$1(value) {
|
|
|
196
197
|
return typeof value === "object" && value !== null;
|
|
197
198
|
}
|
|
198
199
|
//#endregion
|
|
199
|
-
//#region src/
|
|
200
|
-
function createAcpAgentServer(options) {
|
|
200
|
+
//#region src/adapters/acp/runtime/acp-agent-server.ts
|
|
201
|
+
function createAcpAgentServer$1(options) {
|
|
201
202
|
const sessions = /* @__PURE__ */ new Set();
|
|
202
203
|
const active = /* @__PURE__ */ new Map();
|
|
203
204
|
return acp.agent({ name: options.agentName ?? "rivus" }).onRequest(acp.methods.agent.initialize, ({ params }) => ({
|
|
@@ -254,7 +255,7 @@ function createAcpAgentServer(options) {
|
|
|
254
255
|
active.get(params.sessionId)?.abort();
|
|
255
256
|
});
|
|
256
257
|
}
|
|
257
|
-
async function serveAcpAgentOnStdio(app) {
|
|
258
|
+
async function serveAcpAgentOnStdio$1(app) {
|
|
258
259
|
const stream = acp.ndJsonStream(Writable.toWeb(process.stdout), Readable.toWeb(process.stdin));
|
|
259
260
|
await app.connect(stream).closed;
|
|
260
261
|
}
|
|
@@ -305,22 +306,7 @@ function mapAgentLoopEvent(event) {
|
|
|
305
306
|
};
|
|
306
307
|
}
|
|
307
308
|
//#endregion
|
|
308
|
-
//#region src/
|
|
309
|
-
function createAcpPermissionBridge() {
|
|
310
|
-
const policies = /* @__PURE__ */ new Map();
|
|
311
|
-
return {
|
|
312
|
-
bind: (sessionKey, policy) => {
|
|
313
|
-
if (policies.has(sessionKey)) throw new Error(`ACP permission bridge is already bound: ${sessionKey}`);
|
|
314
|
-
policies.set(sessionKey, policy);
|
|
315
|
-
return () => {
|
|
316
|
-
if (policies.get(sessionKey) === policy) policies.delete(sessionKey);
|
|
317
|
-
};
|
|
318
|
-
},
|
|
319
|
-
policy: async (request, context) => policies.get(context.sessionKey)?.(request)
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
//#endregion
|
|
323
|
-
//#region src/infrastructure/acp/acp-permission-policy.ts
|
|
309
|
+
//#region src/adapters/acp/runtime/acp-permission-policy.ts
|
|
324
310
|
async function decideAcpPermission(request, policy) {
|
|
325
311
|
const selection = await policy?.(request);
|
|
326
312
|
if (!selection || !request.options.some((option) => option.optionId === selection.optionId)) return { outcome: "cancelled" };
|
|
@@ -330,7 +316,7 @@ async function decideAcpPermission(request, policy) {
|
|
|
330
316
|
};
|
|
331
317
|
}
|
|
332
318
|
//#endregion
|
|
333
|
-
//#region src/
|
|
319
|
+
//#region src/adapters/acp/runtime/acp-stdio-agent-loop.ts
|
|
334
320
|
async function buildAcpSession(processConnection, options, input) {
|
|
335
321
|
const mcpServers = createMcpServers(options, input);
|
|
336
322
|
const persisted = await options.sessionStore?.load(input.sessionKey);
|
|
@@ -375,7 +361,7 @@ async function restoreAcpSession(processConnection, options, sessionId, mcpServe
|
|
|
375
361
|
throw new AcpSessionResumeFailed(sessionId, error);
|
|
376
362
|
}
|
|
377
363
|
}
|
|
378
|
-
function createAcpStdioAgentLoop(options) {
|
|
364
|
+
function createAcpStdioAgentLoop$1(options) {
|
|
379
365
|
let pendingConnection;
|
|
380
366
|
let activeConnection;
|
|
381
367
|
let ownedChild;
|
|
@@ -433,7 +419,7 @@ function createAcpStdioAgentLoop(options) {
|
|
|
433
419
|
if (child) await terminateChild(child, options.terminationTimeoutMs);
|
|
434
420
|
await current?.catch(() => void 0);
|
|
435
421
|
},
|
|
436
|
-
loop: createAcpAgentLoop({
|
|
422
|
+
loop: createAcpAgentLoop$1({
|
|
437
423
|
disposeSessionAfterRun: false,
|
|
438
424
|
resolveSession: async (input) => {
|
|
439
425
|
const processConnection = await resolveConnection();
|
|
@@ -665,7 +651,61 @@ function withTimeout(promise, timeoutMs, message) {
|
|
|
665
651
|
});
|
|
666
652
|
}
|
|
667
653
|
//#endregion
|
|
668
|
-
//#region src/
|
|
654
|
+
//#region src/adapters/compatibility/agent-execution/acp/acp-runtime.ts
|
|
655
|
+
function createAcpAgentLoop(options) {
|
|
656
|
+
return fromEffectAgentLoop(createAcpAgentLoop$1({
|
|
657
|
+
...options.cancellationSettleTimeoutMs === void 0 ? {} : { cancellationSettleTimeoutMs: options.cancellationSettleTimeoutMs },
|
|
658
|
+
...options.disposeSessionAfterRun === void 0 ? {} : { disposeSessionAfterRun: options.disposeSessionAfterRun },
|
|
659
|
+
resolveSession: (input) => options.resolveSession(toCompatibilityAgentLoopInput(input))
|
|
660
|
+
}));
|
|
661
|
+
}
|
|
662
|
+
function createAcpAgentServer(options) {
|
|
663
|
+
return createAcpAgentServer$1({
|
|
664
|
+
...options.agentName === void 0 ? {} : { agentName: options.agentName },
|
|
665
|
+
loop: toEffectAgentLoop(options.loop),
|
|
666
|
+
...options.permissionBridge ? { permissionBridge: options.permissionBridge } : {},
|
|
667
|
+
workingDirectory: options.workingDirectory
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
function serveAcpAgentOnStdio(app) {
|
|
671
|
+
return serveAcpAgentOnStdio$1(app);
|
|
672
|
+
}
|
|
673
|
+
function createAcpStdioAgentLoop(options) {
|
|
674
|
+
const handle = createAcpStdioAgentLoop$1({
|
|
675
|
+
...options.arguments ? { arguments: options.arguments } : {},
|
|
676
|
+
...options.clientName === void 0 ? {} : { clientName: options.clientName },
|
|
677
|
+
command: options.command,
|
|
678
|
+
...options.environment ? { environment: options.environment } : {},
|
|
679
|
+
...options.initializationTimeoutMs === void 0 ? {} : { initializationTimeoutMs: options.initializationTimeoutMs },
|
|
680
|
+
...options.mcpServers ? { mcpServers: (input) => options.mcpServers(toCompatibilityAgentLoopInput(input)) } : {},
|
|
681
|
+
...options.onStderr ? { onStderr: options.onStderr } : {},
|
|
682
|
+
...options.permissionPolicy ? { permissionPolicy: options.permissionPolicy } : {},
|
|
683
|
+
...options.sessionStore ? { sessionStore: options.sessionStore } : {},
|
|
684
|
+
...options.terminationTimeoutMs === void 0 ? {} : { terminationTimeoutMs: options.terminationTimeoutMs },
|
|
685
|
+
workingDirectory: options.workingDirectory
|
|
686
|
+
});
|
|
687
|
+
return {
|
|
688
|
+
dispose: () => handle.dispose(),
|
|
689
|
+
loop: fromEffectAgentLoop(handle.loop)
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
//#endregion
|
|
693
|
+
//#region src/adapters/acp/runtime/acp-permission-bridge.ts
|
|
694
|
+
function createAcpPermissionBridge() {
|
|
695
|
+
const policies = /* @__PURE__ */ new Map();
|
|
696
|
+
return {
|
|
697
|
+
bind: (sessionKey, policy) => {
|
|
698
|
+
if (policies.has(sessionKey)) throw new Error(`ACP permission bridge is already bound: ${sessionKey}`);
|
|
699
|
+
policies.set(sessionKey, policy);
|
|
700
|
+
return () => {
|
|
701
|
+
if (policies.get(sessionKey) === policy) policies.delete(sessionKey);
|
|
702
|
+
};
|
|
703
|
+
},
|
|
704
|
+
policy: async (request, context) => policies.get(context.sessionKey)?.(request)
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
//#endregion
|
|
708
|
+
//#region src/adapters/acp/runtime/acp-session-store.ts
|
|
669
709
|
/**
|
|
670
710
|
* A small deployment-owned store for ACP provider session identities.
|
|
671
711
|
* The file contains no prompts or credentials, only session-key bindings.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { A as CreateRivusDeploymentBackgroundSessionInput, F as RivusDeploymentBackgroundSession, Fc as AgentRuntimeInput, M as CreateRivusDeploymentEndpointInput, Mc as SessionSchedulerStatus, N as CreateRivusDeploymentRuntimeInput, Pc as AgentRuntimeCancellation, Rc as AgentRuntimeSteering, aa as RivusDeploymentBootstrapContext, dt as ScheduledAutomation, k as CreateRivusDeploymentAutomationInput, la as ProcessDeploymentEndpoint, pl as RecoveryControl } from "../chunks/index.js";
|
|
2
|
+
|
|
3
|
+
//#region examples/pi-feishu-deployment.bootstrap.d.ts
|
|
4
|
+
declare function createRivusDeploymentAdapters(context: RivusDeploymentBootstrapContext): Promise<{
|
|
5
|
+
dispose: () => Promise<void> | undefined;
|
|
6
|
+
createRecoveryControl: () => Promise<RecoveryControl>;
|
|
7
|
+
createBackgroundSession: ((input: CreateRivusDeploymentBackgroundSessionInput) => RivusDeploymentBackgroundSession) | undefined;
|
|
8
|
+
createAutomation: (input: CreateRivusDeploymentAutomationInput) => Promise<ScheduledAutomation>;
|
|
9
|
+
createEndpoint: (input: CreateRivusDeploymentEndpointInput) => Promise<ProcessDeploymentEndpoint>;
|
|
10
|
+
createRuntime: (input: CreateRivusDeploymentRuntimeInput) => Promise<{
|
|
11
|
+
dispose: () => Promise<void>;
|
|
12
|
+
concurrency: "managed";
|
|
13
|
+
status(): SessionSchedulerStatus;
|
|
14
|
+
cancel?(input: AgentRuntimeCancellation): Promise<boolean>;
|
|
15
|
+
steer?(input: AgentRuntimeSteering): Promise<boolean>;
|
|
16
|
+
run(input: AgentRuntimeInput): Promise<unknown>;
|
|
17
|
+
}>;
|
|
18
|
+
}>;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { createRivusDeploymentAdapters };
|