@rivus/gateway 0.16.2 → 0.17.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.
Files changed (36) hide show
  1. package/LICENSE +674 -21
  2. package/README.md +25 -0
  3. package/dist/bootstrap/herdr-feishu.d.ts +37 -0
  4. package/dist/bootstrap/herdr-feishu.js +856 -0
  5. package/dist/bootstrap/pi-feishu.d.ts +281 -16
  6. package/dist/bootstrap/pi-feishu.js +17314 -344
  7. package/dist/chunks/background-session-authority.js +2 -38
  8. package/dist/chunks/rivus-daemon-cli.d.ts +1115 -0
  9. package/dist/chunks/rivus-node-entrypoint.js +700 -819
  10. package/dist/chunks/{node-rivus-deployment-manifest.js → runtime-cache.js} +1116 -1475
  11. package/dist/cli.d.ts +2 -1
  12. package/dist/cli.js +1 -0
  13. package/dist/index.d.ts +65 -3
  14. package/dist/index.js +3 -1215
  15. package/dist/mcp.d.ts +7 -63
  16. package/dist/mcp.js +3 -250
  17. package/package.json +29 -14
  18. package/templates/a-share-briefing-analysis.mjs +3 -1
  19. package/templates/a-share-briefing-renderer.mjs +15 -5
  20. package/templates/a-share-index-evidence.mjs +9 -3
  21. package/templates/a-share-market-briefing.mjs +3 -1
  22. package/templates/a-share-overseas-evidence.mjs +12 -4
  23. package/templates/a-share-policy-evidence.mjs +30 -10
  24. package/templates/a-share-sector-evidence.mjs +3 -1
  25. package/templates/acp-stdio-proxy.mjs +10 -4
  26. package/templates/current-weather.mjs +36 -12
  27. package/templates/herdr-feishu.mjs +30 -0
  28. package/templates/html-drive-tools.mjs +36 -12
  29. package/templates/pi-feishu-deployment.bootstrap.ts +1 -3
  30. package/templates/pi-feishu.bootstrap.ts +1 -242
  31. package/templates/rivus-agents.plugin.mjs +3 -1
  32. package/dist/chunks/background-session-control-input.js +0 -45
  33. package/dist/chunks/background-session-service.d.ts +0 -390
  34. package/dist/chunks/index.d.ts +0 -4703
  35. package/dist/chunks/service.js +0 -12112
  36. package/templates/langfuse-drive-e2e.mjs +0 -175
@@ -6,10 +6,12 @@ import {
6
6
  createAcpStdioAgentLoop,
7
7
  createJsonAcpSessionStore,
8
8
  serveAcpAgentOnStdio
9
- } from "@rivus/agent/acp";
9
+ } from "@rivus/runtime/acp";
10
10
 
11
11
  const command = process.env.RIVUS_ACP_SERVER_COMMAND?.trim();
12
- if (!command) throw new Error("RIVUS_ACP_SERVER_COMMAND is required and must resolve to an explicit executable");
12
+ if (!command) {
13
+ throw new Error("RIVUS_ACP_SERVER_COMMAND is required and must resolve to an explicit executable");
14
+ }
13
15
 
14
16
  const workingDirectory = process.env.RIVUS_ACP_WORKING_DIRECTORY?.trim() || process.cwd();
15
17
  const sessionStorePath = process.env.RIVUS_ACP_SESSION_STORE?.trim();
@@ -37,7 +39,9 @@ try {
37
39
  }
38
40
 
39
41
  function parseArguments(value) {
40
- if (!value?.trim()) return [];
42
+ if (!value?.trim()) {
43
+ return [];
44
+ }
41
45
  const parsed = JSON.parse(value);
42
46
  if (!Array.isArray(parsed) || parsed.some((item) => typeof item !== "string")) {
43
47
  throw new Error("RIVUS_ACP_SERVER_ARGUMENTS must be a JSON array of strings");
@@ -52,7 +56,9 @@ function selectEnvironment(value) {
52
56
  .map((item) => item.trim())
53
57
  .filter(Boolean) ?? []) {
54
58
  const environmentValue = process.env[key];
55
- if (environmentValue !== undefined) selected[key] = environmentValue;
59
+ if (environmentValue !== undefined) {
60
+ selected[key] = environmentValue;
61
+ }
56
62
  }
57
63
  return selected;
58
64
  }
@@ -85,12 +85,16 @@ async function fetchJson(url, operation) {
85
85
  }
86
86
 
87
87
  function readNumber(value, field) {
88
- if (typeof value !== "number" || !Number.isFinite(value)) throw new Error(`current-weather missing ${field}`);
88
+ if (typeof value !== "number" || !Number.isFinite(value)) {
89
+ throw new Error(`current-weather missing ${field}`);
90
+ }
89
91
  return value;
90
92
  }
91
93
 
92
94
  function readString(value, field) {
93
- if (typeof value !== "string" || !value) throw new Error(`current-weather missing ${field}`);
95
+ if (typeof value !== "string" || !value) {
96
+ throw new Error(`current-weather missing ${field}`);
97
+ }
94
98
  return value;
95
99
  }
96
100
 
@@ -103,15 +107,35 @@ function readFirstNumber(value, field) {
103
107
  }
104
108
 
105
109
  function describeWeatherCode(code) {
106
- if (code === 0) return "晴";
107
- if (code === 1 || code === 2) return "晴间多云";
108
- if (code === 3) return "阴";
109
- if (code === 45 || code === 48) return "有雾";
110
- if (code >= 51 && code <= 57) return "毛毛雨";
111
- if (code >= 61 && code <= 67) return "雨";
112
- if (code >= 71 && code <= 77) return "雪";
113
- if (code >= 80 && code <= 82) return "阵雨";
114
- if (code >= 85 && code <= 86) return "阵雪";
115
- if (code >= 95 && code <= 99) return "雷暴";
110
+ if (code === 0) {
111
+ return "晴";
112
+ }
113
+ if (code === 1 || code === 2) {
114
+ return "晴间多云";
115
+ }
116
+ if (code === 3) {
117
+ return "阴";
118
+ }
119
+ if (code === 45 || code === 48) {
120
+ return "有雾";
121
+ }
122
+ if (code >= 51 && code <= 57) {
123
+ return "毛毛雨";
124
+ }
125
+ if (code >= 61 && code <= 67) {
126
+ return "雨";
127
+ }
128
+ if (code >= 71 && code <= 77) {
129
+ return "雪";
130
+ }
131
+ if (code >= 80 && code <= 82) {
132
+ return "阵雨";
133
+ }
134
+ if (code >= 85 && code <= 86) {
135
+ return "阵雪";
136
+ }
137
+ if (code >= 95 && code <= 99) {
138
+ return "雷暴";
139
+ }
116
140
  return "未知";
117
141
  }
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFile } from "node:fs/promises";
4
+ import { checkHerdrFeishuBridge, startHerdrFeishuBridge } from "@rivus/gateway/bootstrap/herdr-feishu";
5
+
6
+ if (process.argv.slice(2).some((arg) => arg !== "--check")) {
7
+ throw new Error("Usage: herdr-feishu.mjs [--check]");
8
+ }
9
+ const path = process.env.RIVUS_HERDR_CONFIG;
10
+ if (!path) {
11
+ throw new Error("Set RIVUS_HERDR_CONFIG to a private bridge configuration file");
12
+ }
13
+ const config = JSON.parse(await readFile(path, "utf8"));
14
+ const options = {
15
+ ...config,
16
+ appId: process.env.FEISHU_APP_ID,
17
+ appSecret: process.env.FEISHU_APP_SECRET,
18
+ onObservation: (event) => process.stdout.write(`${JSON.stringify(event)}\n`)
19
+ };
20
+ if (process.argv.includes("--check")) {
21
+ process.stdout.write(`${JSON.stringify(await checkHerdrFeishuBridge(options), null, 2)}\n`);
22
+ } else {
23
+ const bridge = await startHerdrFeishuBridge(options);
24
+ process.stdout.write("Herdr bridge started; verify receipt and reply before treating the transport as ready.\n");
25
+ for (const signal of ["SIGINT", "SIGTERM"]) {
26
+ process.once(signal, async () => {
27
+ await bridge.stop();
28
+ });
29
+ }
30
+ }
@@ -25,7 +25,9 @@ export function createHtmlArtifactWriter(options = {}) {
25
25
  try {
26
26
  await writeFile(filePath, html, { encoding: "utf8", flag: "wx" });
27
27
  } catch (error) {
28
- if (!isFileAlreadyPresent(error) || (await readFile(filePath, "utf8")) !== html) throw error;
28
+ if (!isFileAlreadyPresent(error) || (await readFile(filePath, "utf8")) !== html) {
29
+ throw error;
30
+ }
29
31
  }
30
32
  return Object.freeze({
31
33
  artifactId,
@@ -85,15 +87,21 @@ export function createLarkDriveHtmlUploader(options = {}) {
85
87
 
86
88
  async function readRegularFileNoFollow(filePath, artifactId) {
87
89
  const linkMetadata = await lstat(filePath);
88
- if (linkMetadata.isSymbolicLink()) throw new Error(`HTML artifact cannot be a symbolic link: ${artifactId}`);
90
+ if (linkMetadata.isSymbolicLink()) {
91
+ throw new Error(`HTML artifact cannot be a symbolic link: ${artifactId}`);
92
+ }
89
93
  if (typeof constants.O_NOFOLLOW !== "number") {
90
94
  throw new Error("HTML artifact upload requires filesystem no-follow support");
91
95
  }
92
96
  const handle = await open(filePath, constants.O_RDONLY | constants.O_NOFOLLOW);
93
97
  try {
94
98
  const metadata = await handle.stat();
95
- if (!metadata.isFile()) throw new Error(`HTML artifact is not a regular file: ${artifactId}`);
96
- if (metadata.size > 256 * 1024) throw new Error(`HTML artifact exceeds the 256 KiB limit: ${artifactId}`);
99
+ if (!metadata.isFile()) {
100
+ throw new Error(`HTML artifact is not a regular file: ${artifactId}`);
101
+ }
102
+ if (metadata.size > 256 * 1024) {
103
+ throw new Error(`HTML artifact exceeds the 256 KiB limit: ${artifactId}`);
104
+ }
97
105
  return await handle.readFile();
98
106
  } finally {
99
107
  await handle.close();
@@ -138,7 +146,9 @@ function readCompleteHtml(input) {
138
146
  if (!/^<!doctype html>/i.test(html) || !/<html(?:\s|>)/i.test(html) || !/<\/html>\s*$/i.test(html)) {
139
147
  throw new Error("write-html-artifact requires a complete HTML document");
140
148
  }
141
- if (Buffer.byteLength(html) > 256 * 1024) throw new Error("HTML artifact exceeds the 256 KiB limit");
149
+ if (Buffer.byteLength(html) > 256 * 1024) {
150
+ throw new Error("HTML artifact exceeds the 256 KiB limit");
151
+ }
142
152
  return html;
143
153
  }
144
154
 
@@ -165,18 +175,24 @@ function readUploadResult(stdout, requestedName) {
165
175
  throw new Error("lark-cli upload returned invalid JSON");
166
176
  }
167
177
  const result = isRecord(parsed?.data) ? parsed.data : parsed;
168
- if (!isRecord(result)) throw new Error("lark-cli upload returned an invalid result");
178
+ if (!isRecord(result)) {
179
+ throw new Error("lark-cli upload returned an invalid result");
180
+ }
169
181
  const fileToken = readFirstString(result, ["file_token", "fileToken", "token"]);
170
182
  const url = readFirstString(result, ["url", "web_url", "file_url"]);
171
183
  const name = readFirstString(result, ["name", "file_name"]) ?? requestedName;
172
- if (!fileToken || !url) throw new Error("lark-cli upload result is missing file token or URL");
184
+ if (!fileToken || !url) {
185
+ throw new Error("lark-cli upload result is missing file token or URL");
186
+ }
173
187
  return Object.freeze({ fileToken, name, url });
174
188
  }
175
189
 
176
190
  function readFirstString(value, keys) {
177
191
  for (const key of keys) {
178
192
  const candidate = value[key];
179
- if (typeof candidate === "string" && candidate.trim()) return candidate.trim();
193
+ if (typeof candidate === "string" && candidate.trim()) {
194
+ return candidate.trim();
195
+ }
180
196
  }
181
197
  return undefined;
182
198
  }
@@ -191,7 +207,9 @@ function resolveArtifactRoot(cwd, artifactRoot = DEFAULT_ARTIFACT_ROOT) {
191
207
  }
192
208
 
193
209
  function resolveAgentDirectory(artifactRoot, agentId) {
194
- if (typeof agentId !== "string" || !agentId.trim()) throw new Error("HTML artifact tool requires an agent id");
210
+ if (typeof agentId !== "string" || !agentId.trim()) {
211
+ throw new Error("HTML artifact tool requires an agent id");
212
+ }
195
213
  return resolve(artifactRoot, createHash("sha256").update(agentId).digest("hex").slice(0, 16));
196
214
  }
197
215
 
@@ -218,7 +236,9 @@ async function resolveTrustedDirectory(cwd, directory, create) {
218
236
  if (metadata.isSymbolicLink()) {
219
237
  throw new Error("HTML artifact directory cannot contain symbolic links");
220
238
  }
221
- if (!metadata.isDirectory()) throw new Error("HTML artifact path component is not a directory");
239
+ if (!metadata.isDirectory()) {
240
+ throw new Error("HTML artifact path component is not a directory");
241
+ }
222
242
  }
223
243
  const [workspacePath, directoryPath] = await Promise.all([realpath(lexicalWorkspace), realpath(lexicalDirectory)]);
224
244
  const resolvedRelativePath = relative(workspacePath, directoryPath);
@@ -232,12 +252,16 @@ async function readOrCreateDirectory(directory, create) {
232
252
  try {
233
253
  return await lstat(directory);
234
254
  } catch (error) {
235
- if (!isMissingFile(error) || !create) throw error;
255
+ if (!isMissingFile(error) || !create) {
256
+ throw error;
257
+ }
236
258
  }
237
259
  try {
238
260
  await mkdir(directory);
239
261
  } catch (error) {
240
- if (!isFileAlreadyPresent(error)) throw error;
262
+ if (!isFileAlreadyPresent(error)) {
263
+ throw error;
264
+ }
241
265
  }
242
266
  return lstat(directory);
243
267
  }
@@ -1,3 +1 @@
1
- // Projects initialized by Gateway keep the historical bootstrap specifier while
2
- // the implementation remains in the Gateway package canonical owner.
3
- export { createRivusDeploymentAdapters } from "@rivus/agent/bootstrap/pi-feishu";
1
+ export { createRivusDeploymentAdapters } from "@rivus/gateway/bootstrap/pi-feishu";
@@ -1,242 +1 @@
1
- import { mkdir } from "node:fs/promises";
2
- import { homedir } from "node:os";
3
- import { Effect } from "effect";
4
- import * as Lark from "@larksuiteoapi/node-sdk";
5
- import { createAgentSession, ModelRuntime, SessionManager } from "@earendil-works/pi-coding-agent";
6
- import {
7
- createJsonFetchRequest,
8
- createJsonFileFeishuCardTargetRegistry,
9
- createJsonlAgentEventLog,
10
- createLazyFeishuWebSocketEventDispatcher,
11
- mergePiProviderBaseUrlOverride,
12
- createRivusDaemonStatusHttpServer,
13
- createPiAgentLoop,
14
- createPiSessionRegistry,
15
- createSystemClock,
16
- createUuidRunIds,
17
- restoreConfiguredRivusDaemonBootstrap,
18
- type ConfiguredRivusDaemonBootstrapRequest,
19
- type ConfiguredRivusDaemonBootstrapResponse,
20
- type FeishuWebSocketClient,
21
- type RivusDaemonBootstrapContext,
22
- type RivusDaemonFeishuReplayRunner,
23
- type RivusDaemonProcess,
24
- type RivusDaemonPromptRunner,
25
- type RivusDaemonStatusReporter,
26
- type FeishuReceiveMessagePayload,
27
- type FeishuReceiveMessageReplayOptions
28
- } from "@rivus/agent";
29
- import {
30
- createPiSkillReadTools,
31
- createPiSessionResources,
32
- resolvePiSessionToolNames,
33
- validatePiSkillCommand
34
- } from "@rivus/agent/pi";
35
-
36
- type PiSessionOptions = NonNullable<Parameters<typeof createAgentSession>[0]>;
37
-
38
- const STATE_DIR = "./.rivus";
39
- const CARD_TARGETS_FILE = `${STATE_DIR}/feishu-card-targets.json`;
40
- const EVENT_LOG_FILE = `${STATE_DIR}/agent-events.jsonl`;
41
- const PI_AUTH_FILE = `${STATE_DIR}/pi-auth.json`;
42
- const PI_MODELS_FILE = `${STATE_DIR}/pi-models.json`;
43
- const PI_AGENT_DIR = `${STATE_DIR}/pi-agent`;
44
-
45
- export async function createRivusDaemonProcess(
46
- context: RivusDaemonBootstrapContext
47
- ): Promise<RivusDaemonProcess & RivusDaemonPromptRunner & RivusDaemonStatusReporter & RivusDaemonFeishuReplayRunner> {
48
- await mkdir(PI_AGENT_DIR, { recursive: true });
49
-
50
- const piSessionOptions = await createPiSessionOptions(context);
51
- const sessionRegistry = createPiSessionRegistry({
52
- createSession: async () => {
53
- const cwd = process.cwd();
54
- const resources = await createPiSessionResources({
55
- agentDir: PI_AGENT_DIR,
56
- cwd,
57
- homeDirectory: homedir()
58
- });
59
- const customTools = createPiSkillReadTools({
60
- cwd,
61
- runtimeToolIds: [],
62
- skillPaths: resources.skillNames.size > 0 ? resources.skillPaths : []
63
- });
64
- const result = await createAgentSession(
65
- resources.withSessionOptions({
66
- ...piSessionOptions,
67
- customTools,
68
- excludeTools: [],
69
- sessionManager: SessionManager.create(cwd),
70
- tools: [...resolvePiSessionToolNames([], customTools)]
71
- })
72
- );
73
- return {
74
- dispose: () => result.session.dispose(),
75
- preparePrompt: (input) => {
76
- validatePiSkillCommand(input.text, resources.skillNames);
77
- return input.text;
78
- },
79
- session: result.session
80
- };
81
- }
82
- });
83
- const piLoop = createPiAgentLoop({
84
- supportsSteering: true,
85
- disposeSessionAfterRun: false,
86
- resolveSession: (input) => sessionRegistry.resolve(input)
87
- });
88
- const statusPort = readOptionalPort(context.env.RIVUS_STATUS_PORT);
89
- const request = createJsonFetchRequest();
90
-
91
- const bootstrap = await Effect.runPromise(
92
- restoreConfiguredRivusDaemonBootstrap({
93
- cardTargets: createJsonFileFeishuCardTargetRegistry({
94
- filePath: CARD_TARGETS_FILE
95
- }),
96
- clock: createSystemClock(),
97
- config: context.config,
98
- ...(statusPort === undefined
99
- ? {}
100
- : {
101
- createStatusTransport: (statusReporter: RivusDaemonStatusReporter) =>
102
- createRivusDaemonStatusHttpServer({
103
- port: statusPort,
104
- statusReporter
105
- })
106
- }),
107
- eventDispatcher: createLazyFeishuWebSocketEventDispatcher(() => new Lark.EventDispatcher({})),
108
- eventLog: createJsonlAgentEventLog({
109
- filePath: EVENT_LOG_FILE
110
- }),
111
- loop: piLoop,
112
- request: (input: ConfiguredRivusDaemonBootstrapRequest) =>
113
- request(input).pipe(Effect.map((response) => response as ConfiguredRivusDaemonBootstrapResponse)),
114
- runIds: createUuidRunIds(),
115
- sleep: (ms) => Effect.promise(() => new Promise<void>((resolve) => setTimeout(resolve, ms))),
116
- websocketClient: createLazyFeishuWebSocketClient({
117
- appId: context.config.feishu.appId,
118
- appSecret: context.config.feishu.appSecret
119
- })
120
- })
121
- );
122
-
123
- return {
124
- promptText: (command) => bootstrap.promptText(command),
125
- replayReceiveMessage: (payload: FeishuReceiveMessagePayload, options?: FeishuReceiveMessageReplayOptions) =>
126
- bootstrap.runtime.replayReceiveMessage(payload, options),
127
- running: () => bootstrap.process.running(),
128
- start: () => bootstrap.process.start(),
129
- status: () => bootstrap.status(),
130
- stop: () =>
131
- Effect.gen(function* () {
132
- yield* bootstrap.process.stop();
133
- yield* Effect.tryPromise({
134
- try: () => sessionRegistry.disposeAll(),
135
- catch: (error) => error
136
- });
137
- })
138
- };
139
- }
140
-
141
- function createLazyFeishuWebSocketClient(options: {
142
- readonly appId: string;
143
- readonly appSecret: string;
144
- }): FeishuWebSocketClient {
145
- let client:
146
- | {
147
- close(): void;
148
- start(options: Parameters<FeishuWebSocketClient["start"]>[0]): Promise<void> | void;
149
- }
150
- | undefined;
151
-
152
- return {
153
- start: (startOptions) => {
154
- client ??= new Lark.WSClient({
155
- appId: options.appId,
156
- appSecret: options.appSecret
157
- });
158
- return client.start(startOptions);
159
- },
160
- close: () => {
161
- client?.close();
162
- client = undefined;
163
- }
164
- };
165
- }
166
-
167
- async function createPiSessionOptions(context: RivusDaemonBootstrapContext): Promise<PiSessionOptions> {
168
- const provider = readProviderFromModel(context.config.pi.model);
169
-
170
- if (context.config.pi.baseUrl) {
171
- if (!provider) {
172
- throw new Error("PI_BASE_URL requires PI_MODEL in provider/model form, for example zai/glm-5.2");
173
- }
174
- await writeProviderBaseUrlOverride(provider, context.config.pi.baseUrl);
175
- }
176
-
177
- const modelRuntime = await ModelRuntime.create({
178
- allowModelNetwork: false,
179
- authPath: PI_AUTH_FILE,
180
- modelsPath: context.config.pi.baseUrl ? PI_MODELS_FILE : null
181
- });
182
- if (context.config.pi.apiKey) {
183
- if (!provider) {
184
- throw new Error("PI_API_KEY requires PI_MODEL in provider/model form, for example zai/glm-5.2");
185
- }
186
- await modelRuntime.setRuntimeApiKey(provider, context.config.pi.apiKey);
187
- }
188
- const model = context.config.pi.model ? resolveConfiguredPiModel(modelRuntime, context.config.pi.model) : undefined;
189
- return {
190
- cwd: process.cwd(),
191
- modelRuntime,
192
- ...(model ? { model } : {}),
193
- ...(context.config.pi.thinkingLevel ? { thinkingLevel: context.config.pi.thinkingLevel } : {})
194
- };
195
- }
196
-
197
- function resolveConfiguredPiModel(modelRuntime: ModelRuntime, modelReference: string): PiSessionOptions["model"] {
198
- const provider = readProviderFromModel(modelReference);
199
- const modelId = readModelIdFromModel(modelReference);
200
- if (!provider || !modelId) {
201
- throw new Error("PI_MODEL must use provider/model form, for example zai/glm-5.2");
202
- }
203
-
204
- const model = modelRuntime.getModel(provider, modelId);
205
- if (!model) {
206
- throw new Error(`PI_MODEL ${modelReference} was not found in the Pi model runtime`);
207
- }
208
- return model as PiSessionOptions["model"];
209
- }
210
-
211
- function readProviderFromModel(model: string | undefined): string | undefined {
212
- const slashIndex = model?.indexOf("/") ?? -1;
213
- if (!model || slashIndex <= 0) {
214
- return undefined;
215
- }
216
- return model.slice(0, slashIndex);
217
- }
218
-
219
- function readModelIdFromModel(model: string | undefined): string | undefined {
220
- const slashIndex = model?.indexOf("/") ?? -1;
221
- if (!model || slashIndex < 0 || slashIndex === model.length - 1) {
222
- return undefined;
223
- }
224
- return model.slice(slashIndex + 1);
225
- }
226
-
227
- function readOptionalPort(value: string | undefined): number | undefined {
228
- const trimmed = value?.trim();
229
- if (!trimmed) {
230
- return undefined;
231
- }
232
-
233
- const port = Number(trimmed);
234
- if (!Number.isInteger(port) || port < 0 || port > 65_535) {
235
- throw new Error("RIVUS_STATUS_PORT must be an integer between 0 and 65535");
236
- }
237
- return port;
238
- }
239
-
240
- async function writeProviderBaseUrlOverride(provider: string, baseUrl: string): Promise<void> {
241
- await mergePiProviderBaseUrlOverride({ baseUrl, filePath: PI_MODELS_FILE, provider });
242
- }
1
+ export { createRivusDaemonProcess } from "@rivus/gateway/bootstrap/pi-feishu";
@@ -281,7 +281,9 @@ async function saveNote(input, context) {
281
281
  try {
282
282
  await writeFile(filePath, content, { encoding: "utf8", flag: "wx" });
283
283
  } catch (error) {
284
- if (!(error instanceof Error) || !("code" in error) || error.code !== "EEXIST") throw error;
284
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "EEXIST") {
285
+ throw error;
286
+ }
285
287
  if ((await readFile(filePath, "utf8")) !== content) {
286
288
  throw new Error("operation id is already bound to different note content");
287
289
  }
@@ -1,45 +0,0 @@
1
- //#region src/core/application/background-session/control/background-session-control-input.ts
2
- function readBackgroundSessionObject(input, allowed, error) {
3
- if (input === null || typeof input !== "object" || Array.isArray(input)) throw error("background tool input must be an object");
4
- const record = input;
5
- const unknown = Object.keys(record).find((key) => !allowed.includes(key));
6
- if (unknown) throw error(`field is not allowed: ${unknown}`);
7
- return record;
8
- }
9
- function readBackgroundSessionString(value, name, error) {
10
- if (typeof value !== "string" || value.trim() === "") throw error(`${name} must be a non-empty string`);
11
- return value;
12
- }
13
- function readBackgroundSessionInteger(value, name, error) {
14
- if (!Number.isSafeInteger(value) || value < 1) throw error(`${name} must be a positive integer`);
15
- return value;
16
- }
17
- function readBackgroundSessionPhase(value, error) {
18
- const phases = [
19
- "queued",
20
- "running",
21
- "waiting",
22
- "input-required",
23
- "stopping",
24
- "stopped",
25
- "completed",
26
- "failed",
27
- "reconciliation-required"
28
- ];
29
- if (typeof value !== "string" || !phases.includes(value)) throw error(`phase must be one of ${phases.join(", ")}`);
30
- return value;
31
- }
32
- function readBackgroundSessionWaitInput(input, error) {
33
- const { delayMs, reason, until } = readBackgroundSessionObject(input, [
34
- "delayMs",
35
- "reason",
36
- "until"
37
- ], error);
38
- const args = {};
39
- if (delayMs !== void 0) args.delayMs = readBackgroundSessionInteger(delayMs, "delayMs", error);
40
- if (reason !== void 0) args.reason = readBackgroundSessionString(reason, "reason", error);
41
- if (until !== void 0) args.until = readBackgroundSessionString(until, "until", error);
42
- return args;
43
- }
44
- //#endregion
45
- export { readBackgroundSessionWaitInput as a, readBackgroundSessionString as i, readBackgroundSessionObject as n, readBackgroundSessionPhase as r, readBackgroundSessionInteger as t };