@rivus/agent 0.14.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -10
- package/dist/bootstrap/pi-feishu.js +11 -9
- package/dist/cli.js +2 -2
- package/examples/pi-feishu-deployment.bootstrap.ts +11 -9
- package/examples/pi-feishu.bootstrap.ts +18 -17
- package/package.json +5 -13
package/README.md
CHANGED
|
@@ -58,10 +58,7 @@ npx rivus --help
|
|
|
58
58
|
Create the default Personal Agent Home without cloning this repository or installing another local Rivus copy:
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
|
-
npm install --global
|
|
62
|
-
@rivus/agent \
|
|
63
|
-
@earendil-works/pi-coding-agent@^0.80.6 \
|
|
64
|
-
@larksuiteoapi/node-sdk@^1.70.0
|
|
61
|
+
npm install --global @rivus/agent
|
|
65
62
|
rivus setup
|
|
66
63
|
cp "$HOME/.rivus-agent/.env.example" "$HOME/.rivus-agent/.env"
|
|
67
64
|
# Fill the Feishu and model-provider values in ~/.rivus-agent/.env.
|
|
@@ -71,11 +68,8 @@ rivus start
|
|
|
71
68
|
|
|
72
69
|
`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).
|
|
73
70
|
|
|
74
|
-
The Pi plus Feishu Bootstrap is
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
npm install @earendil-works/pi-coding-agent@^0.80.6 @larksuiteoapi/node-sdk@^1.70.0
|
|
78
|
-
```
|
|
71
|
+
The maintained Pi plus Feishu Bootstrap is the default Personal Home runtime, so its pinned Pi SDK and compatible
|
|
72
|
+
Feishu SDK are installed transitively with `@rivus/agent`. Optional adapter SDKs such as ACP remain separate peers.
|
|
79
73
|
|
|
80
74
|
## Quick Start
|
|
81
75
|
|
|
@@ -427,7 +421,7 @@ Recognized variables:
|
|
|
427
421
|
- `RIVUS_WEATHER_DEFAULT_LOCATION` selects the example `current-weather` Tool's fallback city and defaults to `北京`; it is not a Core setting.
|
|
428
422
|
- `RIVUS_TELEMETRY_ENVIRONMENT` defaults to `NODE_ENV`, then `local`; `RIVUS_TELEMETRY_SERVICE_NAME` defaults to `rivus-agent`.
|
|
429
423
|
|
|
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.
|
|
424
|
+
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.2` for GLM BYOK. The templates create Pi's isolated `ModelRuntime`, apply the resolved API key with `setRuntimeApiKey()`, resolve the model with `getModel(provider, modelId)`, 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.
|
|
431
425
|
|
|
432
426
|
## Core Usage
|
|
433
427
|
|
|
@@ -9,7 +9,7 @@ import { mkdir, readFile } from "node:fs/promises";
|
|
|
9
9
|
import { join, relative } from "node:path";
|
|
10
10
|
import { homedir } from "node:os";
|
|
11
11
|
import * as Lark from "@larksuiteoapi/node-sdk";
|
|
12
|
-
import {
|
|
12
|
+
import { ModelRuntime, SessionManager, createAgentSession } from "@earendil-works/pi-coding-agent";
|
|
13
13
|
//#region examples/pi-feishu-deployment.bootstrap.ts
|
|
14
14
|
const STATE_DIR = process.env.RIVUS_DEPLOYMENT_STATE_DIR?.trim() || ".rivus/deployment";
|
|
15
15
|
const PI_AGENT_DIR = join(STATE_DIR, "pi-agent");
|
|
@@ -532,23 +532,25 @@ async function resolveFeishuBotOpenId(credentials, domain) {
|
|
|
532
532
|
return openId;
|
|
533
533
|
}
|
|
534
534
|
async function createPiSessionOptions(context) {
|
|
535
|
-
const authStorage = AuthStorage.create(PI_AUTH_FILE);
|
|
536
535
|
const modelReference = optional(context.env.PI_MODEL);
|
|
537
536
|
const configuredModel = modelReference ? parseModelReference(modelReference) : void 0;
|
|
538
537
|
const provider = configuredModel?.provider;
|
|
539
538
|
const apiKey = await resolvePiApiKey(context.env);
|
|
540
539
|
const baseUrl = optional(context.env.PI_BASE_URL);
|
|
541
540
|
if ((apiKey || baseUrl) && !provider) throw new Error("PI_API_KEY and PI_BASE_URL require PI_MODEL in provider/model form");
|
|
542
|
-
if (apiKey) authStorage.setRuntimeApiKey(provider, apiKey);
|
|
543
541
|
if (baseUrl) await writeProviderBaseUrlOverride(provider, baseUrl);
|
|
544
|
-
const
|
|
545
|
-
|
|
546
|
-
|
|
542
|
+
const modelRuntime = await ModelRuntime.create({
|
|
543
|
+
allowModelNetwork: false,
|
|
544
|
+
authPath: PI_AUTH_FILE,
|
|
545
|
+
modelsPath: baseUrl ? PI_MODELS_FILE : null
|
|
546
|
+
});
|
|
547
|
+
if (apiKey) await modelRuntime.setRuntimeApiKey(provider, apiKey);
|
|
548
|
+
const model = configuredModel ? modelRuntime.getModel(configuredModel.provider, configuredModel.modelId) : void 0;
|
|
549
|
+
if (modelReference && !model) throw new Error(`PI_MODEL ${modelReference} was not found in the Pi model runtime`);
|
|
547
550
|
const thinkingLevel = readThinkingLevel(context.env.PI_THINKING_LEVEL);
|
|
548
551
|
return {
|
|
549
|
-
authStorage,
|
|
550
552
|
cwd: process.cwd(),
|
|
551
|
-
|
|
553
|
+
modelRuntime,
|
|
552
554
|
...model ? { model } : {},
|
|
553
555
|
...thinkingLevel ? { thinkingLevel } : {}
|
|
554
556
|
};
|
|
@@ -568,7 +570,7 @@ function optional(value) {
|
|
|
568
570
|
}
|
|
569
571
|
function parseModelReference(reference) {
|
|
570
572
|
const separator = reference.indexOf("/");
|
|
571
|
-
if (separator <= 0 || separator === reference.length - 1) throw new Error("PI_MODEL must use provider/model form, for example zai/glm-5.
|
|
573
|
+
if (separator <= 0 || separator === reference.length - 1) throw new Error("PI_MODEL must use provider/model form, for example zai/glm-5.2");
|
|
572
574
|
return {
|
|
573
575
|
modelId: reference.slice(separator + 1),
|
|
574
576
|
provider: reference.slice(0, separator)
|
package/dist/cli.js
CHANGED
|
@@ -416,8 +416,8 @@ function isMissingPath(error) {
|
|
|
416
416
|
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
417
417
|
}
|
|
418
418
|
function projectPackageJson(directory, manifest) {
|
|
419
|
-
const pi = manifest.
|
|
420
|
-
const lark = manifest.
|
|
419
|
+
const pi = manifest.dependencies?.["@earendil-works/pi-coding-agent"];
|
|
420
|
+
const lark = manifest.dependencies?.["@larksuiteoapi/node-sdk"];
|
|
421
421
|
const effect = manifest.dependencies?.effect;
|
|
422
422
|
if (!pi || !lark || !effect) throw new Error("Rivus package manifest is missing its Effect, Pi, or Feishu dependency range");
|
|
423
423
|
const projectName = sanitizePackageName(basename(directory));
|
|
@@ -4,7 +4,7 @@ import { homedir } from "node:os";
|
|
|
4
4
|
import { join, relative } from "node:path";
|
|
5
5
|
import { Effect } from "effect";
|
|
6
6
|
import * as Lark from "@larksuiteoapi/node-sdk";
|
|
7
|
-
import {
|
|
7
|
+
import { createAgentSession, ModelRuntime, SessionManager } from "@earendil-works/pi-coding-agent";
|
|
8
8
|
import {
|
|
9
9
|
createAgentsMdInstructionsProvider,
|
|
10
10
|
createAgentHarness,
|
|
@@ -720,7 +720,6 @@ async function resolveFeishuBotOpenId(
|
|
|
720
720
|
}
|
|
721
721
|
|
|
722
722
|
async function createPiSessionOptions(context: RivusDeploymentBootstrapContext): Promise<PiSessionOptions> {
|
|
723
|
-
const authStorage = AuthStorage.create(PI_AUTH_FILE);
|
|
724
723
|
const modelReference = optional(context.env.PI_MODEL);
|
|
725
724
|
const configuredModel = modelReference ? parseModelReference(modelReference) : undefined;
|
|
726
725
|
const provider = configuredModel?.provider;
|
|
@@ -729,16 +728,19 @@ async function createPiSessionOptions(context: RivusDeploymentBootstrapContext):
|
|
|
729
728
|
if ((apiKey || baseUrl) && !provider) {
|
|
730
729
|
throw new Error("PI_API_KEY and PI_BASE_URL require PI_MODEL in provider/model form");
|
|
731
730
|
}
|
|
732
|
-
if (apiKey) authStorage.setRuntimeApiKey(provider!, apiKey);
|
|
733
731
|
if (baseUrl) await writeProviderBaseUrlOverride(provider!, baseUrl);
|
|
734
|
-
const
|
|
735
|
-
|
|
736
|
-
|
|
732
|
+
const modelRuntime = await ModelRuntime.create({
|
|
733
|
+
allowModelNetwork: false,
|
|
734
|
+
authPath: PI_AUTH_FILE,
|
|
735
|
+
modelsPath: baseUrl ? PI_MODELS_FILE : null
|
|
736
|
+
});
|
|
737
|
+
if (apiKey) await modelRuntime.setRuntimeApiKey(provider!, apiKey);
|
|
738
|
+
const model = configuredModel ? modelRuntime.getModel(configuredModel.provider, configuredModel.modelId) : undefined;
|
|
739
|
+
if (modelReference && !model) throw new Error(`PI_MODEL ${modelReference} was not found in the Pi model runtime`);
|
|
737
740
|
const thinkingLevel = readThinkingLevel(context.env.PI_THINKING_LEVEL);
|
|
738
741
|
return {
|
|
739
|
-
authStorage,
|
|
740
742
|
cwd: process.cwd(),
|
|
741
|
-
|
|
743
|
+
modelRuntime,
|
|
742
744
|
...(model ? { model } : {}),
|
|
743
745
|
...(thinkingLevel ? { thinkingLevel } : {})
|
|
744
746
|
};
|
|
@@ -762,7 +764,7 @@ function optional(value: string | undefined): string | undefined {
|
|
|
762
764
|
function parseModelReference(reference: string): { readonly modelId: string; readonly provider: string } {
|
|
763
765
|
const separator = reference.indexOf("/");
|
|
764
766
|
if (separator <= 0 || separator === reference.length - 1) {
|
|
765
|
-
throw new Error("PI_MODEL must use provider/model form, for example zai/glm-5.
|
|
767
|
+
throw new Error("PI_MODEL must use provider/model form, for example zai/glm-5.2");
|
|
766
768
|
}
|
|
767
769
|
return { modelId: reference.slice(separator + 1), provider: reference.slice(0, separator) };
|
|
768
770
|
}
|
|
@@ -2,7 +2,7 @@ import { mkdir } from "node:fs/promises";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
4
|
import * as Lark from "@larksuiteoapi/node-sdk";
|
|
5
|
-
import {
|
|
5
|
+
import { createAgentSession, ModelRuntime, SessionManager } from "@earendil-works/pi-coding-agent";
|
|
6
6
|
import {
|
|
7
7
|
createJsonFetchRequest,
|
|
8
8
|
createJsonFileFeishuCardTargetRegistry,
|
|
@@ -164,44 +164,45 @@ function createLazyFeishuWebSocketClient(options: {
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
async function createPiSessionOptions(context: RivusDaemonBootstrapContext): Promise<PiSessionOptions> {
|
|
167
|
-
const authStorage = AuthStorage.create(PI_AUTH_FILE);
|
|
168
167
|
const provider = readProviderFromModel(context.config.pi.model);
|
|
169
168
|
|
|
170
|
-
if (context.config.pi.
|
|
169
|
+
if (context.config.pi.baseUrl) {
|
|
171
170
|
if (!provider) {
|
|
172
|
-
throw new Error("
|
|
171
|
+
throw new Error("PI_BASE_URL requires PI_MODEL in provider/model form, for example zai/glm-5.2");
|
|
173
172
|
}
|
|
174
|
-
|
|
173
|
+
await writeProviderBaseUrlOverride(provider, context.config.pi.baseUrl);
|
|
175
174
|
}
|
|
176
175
|
|
|
177
|
-
|
|
176
|
+
const modelRuntime = await ModelRuntime.create({
|
|
177
|
+
allowModelNetwork: false,
|
|
178
|
+
authPath: PI_AUTH_FILE,
|
|
179
|
+
modelsPath: context.config.pi.baseUrl ? PI_MODELS_FILE : null
|
|
180
|
+
});
|
|
181
|
+
if (context.config.pi.apiKey) {
|
|
178
182
|
if (!provider) {
|
|
179
|
-
throw new Error("
|
|
183
|
+
throw new Error("PI_API_KEY requires PI_MODEL in provider/model form, for example zai/glm-5.2");
|
|
180
184
|
}
|
|
181
|
-
await
|
|
185
|
+
await modelRuntime.setRuntimeApiKey(provider, context.config.pi.apiKey);
|
|
182
186
|
}
|
|
183
|
-
|
|
184
|
-
const modelRegistry = ModelRegistry.create(authStorage, context.config.pi.baseUrl ? PI_MODELS_FILE : undefined);
|
|
185
|
-
const model = context.config.pi.model ? resolveConfiguredPiModel(modelRegistry, context.config.pi.model) : undefined;
|
|
187
|
+
const model = context.config.pi.model ? resolveConfiguredPiModel(modelRuntime, context.config.pi.model) : undefined;
|
|
186
188
|
return {
|
|
187
|
-
authStorage,
|
|
188
189
|
cwd: process.cwd(),
|
|
189
|
-
|
|
190
|
+
modelRuntime,
|
|
190
191
|
...(model ? { model } : {}),
|
|
191
192
|
...(context.config.pi.thinkingLevel ? { thinkingLevel: context.config.pi.thinkingLevel } : {})
|
|
192
193
|
};
|
|
193
194
|
}
|
|
194
195
|
|
|
195
|
-
function resolveConfiguredPiModel(
|
|
196
|
+
function resolveConfiguredPiModel(modelRuntime: ModelRuntime, modelReference: string): PiSessionOptions["model"] {
|
|
196
197
|
const provider = readProviderFromModel(modelReference);
|
|
197
198
|
const modelId = readModelIdFromModel(modelReference);
|
|
198
199
|
if (!provider || !modelId) {
|
|
199
|
-
throw new Error("PI_MODEL must use provider/model form, for example zai/glm-5.
|
|
200
|
+
throw new Error("PI_MODEL must use provider/model form, for example zai/glm-5.2");
|
|
200
201
|
}
|
|
201
202
|
|
|
202
|
-
const model =
|
|
203
|
+
const model = modelRuntime.getModel(provider, modelId);
|
|
203
204
|
if (!model) {
|
|
204
|
-
throw new Error(`PI_MODEL ${modelReference} was not found in the Pi model
|
|
205
|
+
throw new Error(`PI_MODEL ${modelReference} was not found in the Pi model runtime`);
|
|
205
206
|
}
|
|
206
207
|
return model as PiSessionOptions["model"];
|
|
207
208
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rivus/agent",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "A local agent daemon core built around a usable agent harness and domain events.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -88,35 +88,28 @@
|
|
|
88
88
|
"version-packages:ci": "npm run version-packages && npm run check"
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
|
+
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
92
|
+
"@larksuiteoapi/node-sdk": "1.71.1",
|
|
91
93
|
"@opentelemetry/api": "^1.9.1",
|
|
92
94
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.220.0",
|
|
93
95
|
"@opentelemetry/resources": "^2.9.0",
|
|
94
96
|
"@opentelemetry/sdk-trace-base": "^2.9.0",
|
|
95
97
|
"@opentelemetry/sdk-trace-node": "^2.9.0",
|
|
98
|
+
"axios": "1.18.0",
|
|
96
99
|
"effect": "^3.21.4",
|
|
97
100
|
"typebox": "^1.1.38"
|
|
98
101
|
},
|
|
99
102
|
"peerDependencies": {
|
|
100
|
-
"@agentclientprotocol/sdk": "^1.3.0"
|
|
101
|
-
"@earendil-works/pi-coding-agent": "0.80.6",
|
|
102
|
-
"@larksuiteoapi/node-sdk": "^1.70.0"
|
|
103
|
+
"@agentclientprotocol/sdk": "^1.3.0"
|
|
103
104
|
},
|
|
104
105
|
"peerDependenciesMeta": {
|
|
105
106
|
"@agentclientprotocol/sdk": {
|
|
106
107
|
"optional": true
|
|
107
|
-
},
|
|
108
|
-
"@earendil-works/pi-coding-agent": {
|
|
109
|
-
"optional": true
|
|
110
|
-
},
|
|
111
|
-
"@larksuiteoapi/node-sdk": {
|
|
112
|
-
"optional": true
|
|
113
108
|
}
|
|
114
109
|
},
|
|
115
110
|
"devDependencies": {
|
|
116
111
|
"@agentclientprotocol/sdk": "^1.3.0",
|
|
117
112
|
"@changesets/cli": "^2.31.1",
|
|
118
|
-
"@earendil-works/pi-coding-agent": "0.80.6",
|
|
119
|
-
"@larksuiteoapi/node-sdk": "1.71.1",
|
|
120
113
|
"@types/node": "24.13.3",
|
|
121
114
|
"@vitest/coverage-v8": "4.1.10",
|
|
122
115
|
"jscpd": "4.2.5",
|
|
@@ -128,7 +121,6 @@
|
|
|
128
121
|
"node": "^24.11.0"
|
|
129
122
|
},
|
|
130
123
|
"overrides": {
|
|
131
|
-
"axios": "1.16.0",
|
|
132
124
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.4"
|
|
133
125
|
},
|
|
134
126
|
"devEngines": {
|