@senpi/runtime 3.0.187 → 3.0.191
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/cli/guide-commands.d.ts.map +1 -1
- package/dist/cli/guide-commands.js +6 -0
- package/dist/cli/guide-commands.js.map +1 -1
- package/dist/cli/senpi-commands.d.ts.map +1 -1
- package/dist/cli/senpi-commands.js +4 -2
- package/dist/cli/senpi-commands.js.map +1 -1
- package/dist/deploy/box-cap.d.ts +7 -0
- package/dist/deploy/box-cap.d.ts.map +1 -0
- package/dist/deploy/box-cap.js +13 -0
- package/dist/deploy/box-cap.js.map +1 -0
- package/dist/deploy/funding.d.ts +13 -1
- package/dist/deploy/funding.d.ts.map +1 -1
- package/dist/deploy/funding.js +13 -4
- package/dist/deploy/funding.js.map +1 -1
- package/dist/deploy/job.d.ts +2 -0
- package/dist/deploy/job.d.ts.map +1 -1
- package/dist/deploy/job.js +2 -2
- package/dist/deploy/job.js.map +1 -1
- package/dist/deploy/messages.d.ts +14 -0
- package/dist/deploy/messages.d.ts.map +1 -1
- package/dist/deploy/messages.js +59 -25
- package/dist/deploy/messages.js.map +1 -1
- package/dist/deploy/orchestrator.d.ts +23 -1
- package/dist/deploy/orchestrator.d.ts.map +1 -1
- package/dist/deploy/orchestrator.js +87 -30
- package/dist/deploy/orchestrator.js.map +1 -1
- package/dist/deploy/package.d.ts +14 -1
- package/dist/deploy/package.d.ts.map +1 -1
- package/dist/deploy/package.js +37 -2
- package/dist/deploy/package.js.map +1 -1
- package/dist/deploy/register.d.ts +2 -0
- package/dist/deploy/register.d.ts.map +1 -1
- package/dist/deploy/register.js +48 -32
- package/dist/deploy/register.js.map +1 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -12
- package/dist/index.js.map +1 -1
- package/dist/runtime/boot-skip.d.ts +18 -0
- package/dist/runtime/boot-skip.d.ts.map +1 -1
- package/dist/runtime/boot-skip.js +25 -0
- package/dist/runtime/boot-skip.js.map +1 -1
- package/dist/runtime/lifecycle-events.d.ts +2 -2
- package/dist/runtime/lifecycle-events.d.ts.map +1 -1
- package/dist/runtime/lifecycle-events.js.map +1 -1
- package/dist/runtime/lifecycle-reaper.d.ts +11 -6
- package/dist/runtime/lifecycle-reaper.d.ts.map +1 -1
- package/dist/runtime/lifecycle-reaper.js +25 -15
- package/dist/runtime/lifecycle-reaper.js.map +1 -1
- package/dist/runtime/notifications.d.ts +10 -0
- package/dist/runtime/notifications.d.ts.map +1 -1
- package/dist/runtime/notifications.js +17 -6
- package/dist/runtime/notifications.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +4 -1
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/scanners/external/scaffold/preflight.py +492 -12
- package/dist/senpi/__tests__/helpers/fake-paper-mcp.d.ts +44 -0
- package/dist/senpi/__tests__/helpers/fake-paper-mcp.d.ts.map +1 -0
- package/dist/senpi/__tests__/helpers/fake-paper-mcp.js +129 -0
- package/dist/senpi/__tests__/helpers/fake-paper-mcp.js.map +1 -0
- package/dist/senpi/client.d.ts +35 -1
- package/dist/senpi/client.d.ts.map +1 -1
- package/dist/senpi/client.js +62 -8
- package/dist/senpi/client.js.map +1 -1
- package/dist/senpi/paper.d.ts +29 -0
- package/dist/senpi/paper.d.ts.map +1 -0
- package/dist/senpi/paper.js +44 -0
- package/dist/senpi/paper.js.map +1 -0
- package/dist/senpi/strategy-status.d.ts.map +1 -1
- package/dist/senpi/strategy-status.js +2 -0
- package/dist/senpi/strategy-status.js.map +1 -1
- package/dist/senpi/types.d.ts +8 -1
- package/dist/senpi/types.d.ts.map +1 -1
- package/dist/telemetry/box-memory.d.ts +29 -0
- package/dist/telemetry/box-memory.d.ts.map +1 -0
- package/dist/telemetry/box-memory.js +113 -0
- package/dist/telemetry/box-memory.js.map +1 -0
- package/dist/telemetry/metrics.d.ts +21 -0
- package/dist/telemetry/metrics.d.ts.map +1 -1
- package/dist/telemetry/metrics.js +82 -0
- package/dist/telemetry/metrics.js.map +1 -1
- package/dist/telemetry/spans/span-hooks.d.ts.map +1 -1
- package/dist/telemetry/spans/span-hooks.js +4 -1
- package/dist/telemetry/spans/span-hooks.js.map +1 -1
- package/dist/telemetry/trace-identity.d.ts.map +1 -1
- package/dist/telemetry/trace-identity.js +2 -0
- package/dist/telemetry/trace-identity.js.map +1 -1
- package/dist/universe/package-universe.js +1 -1
- package/dist/universe/package-universe.js.map +1 -1
- package/dist/utils/event-catalog.d.ts +7 -3
- package/dist/utils/event-catalog.d.ts.map +1 -1
- package/dist/utils/event-catalog.js.map +1 -1
- package/dist/validate/codes.d.ts +2 -0
- package/dist/validate/codes.d.ts.map +1 -1
- package/dist/validate/codes.js +6 -0
- package/dist/validate/codes.js.map +1 -1
- package/dist/validate/live-stage.d.ts +12 -0
- package/dist/validate/live-stage.d.ts.map +1 -1
- package/dist/validate/live-stage.js +16 -0
- package/dist/validate/live-stage.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import { join, dirname } from "node:path";
|
|
|
17
17
|
import { isMoneyCallTool, SenpiClient, senpiOrderCallsInFlight } from "./senpi/client.js";
|
|
18
18
|
import { MoneyCallTracker, registerMoneyCallHooks } from "./runtime/auto-update/money-call-tracker.js";
|
|
19
19
|
import { buildWalletStatusHint } from "./senpi/strategy-status.js";
|
|
20
|
-
import { bootSkippedStatusLabel, partitionByWalletStatus, readBootWalletStatuses, trackableWalletKeys, } from "./runtime/boot-skip.js";
|
|
20
|
+
import { bootSkippedStatusLabel, partitionByWalletStatus, readBootWalletStatuses, readWalletStatusesByWorld, trackableWalletKeys, } from "./runtime/boot-skip.js";
|
|
21
21
|
import { DeployJobController } from "./deploy/job.js";
|
|
22
22
|
import { DEPLOY_CAPABILITIES, registerDeployGatewayMethods } from "./deploy/register.js";
|
|
23
23
|
import { createQuantDesk } from "./quant/register.js";
|
|
@@ -60,6 +60,9 @@ import { registerSkillRouterHook } from "./prompt/skill-router-hook.js";
|
|
|
60
60
|
import { registerCribSheet } from "./tool-surface/crib-hook.js";
|
|
61
61
|
import { getDefaultPiiRedactor, initDefaultPiiRedactor } from "./telemetry/spans/redact-pii.js";
|
|
62
62
|
import { flushOtelLogs, initOtelSdk, shutdownOtelSdk, waitForOtelInit } from "./telemetry/otel-sdk.js";
|
|
63
|
+
import { createBoxMemoryReader } from "./telemetry/box-memory.js";
|
|
64
|
+
import { registerBoxMemoryGauges } from "./telemetry/metrics.js";
|
|
65
|
+
import { walletMode } from "./senpi/paper.js";
|
|
63
66
|
import { getLogLevel, getLogLevelSource, parseLogLevel, setLogLevel, } from "./utils/logger.js";
|
|
64
67
|
import { ExternalScannerIngestError, } from "./scanners/external-scanner-receiver.js";
|
|
65
68
|
import { createLogger } from "./utils/logger.js";
|
|
@@ -227,10 +230,19 @@ function registerSenpiCliMetadata(api) {
|
|
|
227
230
|
registerSenpiCli(ctx.program);
|
|
228
231
|
}, { commands: ["senpi"] });
|
|
229
232
|
}
|
|
233
|
+
/** Running runtimes by world, read from each handle's wallet: a paper wallet is a simulation. */
|
|
234
|
+
function countRuntimesByMode(handles) {
|
|
235
|
+
const counts = { live: 0, paper: 0 };
|
|
236
|
+
for (const handle of handles)
|
|
237
|
+
counts[walletMode(handle.wallet)] += 1;
|
|
238
|
+
return counts;
|
|
239
|
+
}
|
|
230
240
|
/**
|
|
231
241
|
* OpenClaw plugin entry.
|
|
232
242
|
* Boots from internal registry (installed_runtimes.json) in stateDir; does not read runtime list from config.
|
|
233
243
|
*/
|
|
244
|
+
/** How long service start waits for the OTel SDK before registering the box memory gauges anyway. */
|
|
245
|
+
const BOX_MEMORY_OTEL_READY_MS = 120_000;
|
|
234
246
|
const senpiRuntimePlugin = {
|
|
235
247
|
// Must match openclaw.plugin.json `id` — openclaw loader rejects the plugin
|
|
236
248
|
// when `installed_plugins.json` record id (sourced from the manifest) and
|
|
@@ -656,6 +668,7 @@ const senpiRuntimePlugin = {
|
|
|
656
668
|
*/
|
|
657
669
|
let serviceState = "idle";
|
|
658
670
|
let serviceStops = 0;
|
|
671
|
+
let disposeBoxMemoryGauges;
|
|
659
672
|
// Dedicated logger for the runtime-api subtree — required because the
|
|
660
673
|
// PluginLogger surface (info/warn/error) lacks `debug`, while the
|
|
661
674
|
// Logger contract used by `runtime-api/` includes it.
|
|
@@ -865,7 +878,7 @@ const senpiRuntimePlugin = {
|
|
|
865
878
|
if (!mcpTransport)
|
|
866
879
|
await client.connect();
|
|
867
880
|
try {
|
|
868
|
-
return await client.
|
|
881
|
+
return await client.listStrategiesForWallets(wallets, { signal });
|
|
869
882
|
}
|
|
870
883
|
finally {
|
|
871
884
|
if (!mcpTransport)
|
|
@@ -997,26 +1010,26 @@ const senpiRuntimePlugin = {
|
|
|
997
1010
|
// lower-case storage, and rejects the whole batch on one malformed address.
|
|
998
1011
|
const registeredWallets = trackableWalletKeys(registry.runtimes);
|
|
999
1012
|
if (registeredWallets.length > 0) {
|
|
1000
|
-
const read = await
|
|
1013
|
+
const read = await readWalletStatusesByWorld(registeredWallets, async (wallets, signal) => {
|
|
1001
1014
|
const client = mcpTransport ? new SenpiClient(mcpTransport) : new SenpiClient({ apiKey });
|
|
1002
1015
|
if (!mcpTransport)
|
|
1003
1016
|
await client.connect();
|
|
1004
1017
|
try {
|
|
1005
|
-
return await client.
|
|
1018
|
+
return await client.listStrategiesForWallets(wallets, { signal });
|
|
1006
1019
|
}
|
|
1007
1020
|
finally {
|
|
1008
1021
|
if (!mcpTransport)
|
|
1009
1022
|
await client.disconnect().catch(() => { });
|
|
1010
1023
|
}
|
|
1011
1024
|
});
|
|
1012
|
-
if (read.
|
|
1025
|
+
if (read.answered.size > 0) {
|
|
1013
1026
|
walletStatuses = read.statuses;
|
|
1014
1027
|
bootStrategyIds = read.strategyIds;
|
|
1015
|
-
reaper.recordStatuses(
|
|
1028
|
+
reaper.recordStatuses([...read.answered], read.statuses);
|
|
1016
1029
|
}
|
|
1017
|
-
|
|
1018
|
-
pluginLogger.warn("[senpi-runtime] Could not read strategy statuses at boot; booting every registered runtime", { reason:
|
|
1019
|
-
emitEvent(apiLogger, () => buildRuntimeBootStatusUnreadEvent({ reason:
|
|
1030
|
+
for (const failure of read.failures) {
|
|
1031
|
+
pluginLogger.warn("[senpi-runtime] Could not read strategy statuses at boot; booting every registered runtime of that world", { reason: failure.reason, err: failure.message, paper: failure.paper });
|
|
1032
|
+
emitEvent(apiLogger, () => buildRuntimeBootStatusUnreadEvent({ reason: failure.reason, registeredCount: failure.walletCount }));
|
|
1020
1033
|
}
|
|
1021
1034
|
}
|
|
1022
1035
|
const { boot: entriesToBoot, skipped } = partitionByWalletStatus(registry.runtimes, walletStatuses);
|
|
@@ -1244,6 +1257,17 @@ const senpiRuntimePlugin = {
|
|
|
1244
1257
|
strategiesPublisher.start();
|
|
1245
1258
|
// Sends the events added since the previous send, every 1 s.
|
|
1246
1259
|
eventsPublisher.start();
|
|
1260
|
+
// The metrics API has no proxy meter: gauges made before the SDK sets its provider never export.
|
|
1261
|
+
const stopsAtStart = serviceStops;
|
|
1262
|
+
void waitForOtelInit(BOX_MEMORY_OTEL_READY_MS).then(() => {
|
|
1263
|
+
if (serviceStops !== stopsAtStart)
|
|
1264
|
+
return;
|
|
1265
|
+
disposeBoxMemoryGauges?.();
|
|
1266
|
+
disposeBoxMemoryGauges = registerBoxMemoryGauges({
|
|
1267
|
+
read: createBoxMemoryReader({ warn: (message, meta) => pluginLogger.warn(message, meta) }),
|
|
1268
|
+
runtimes: () => countRuntimesByMode(runtimeHandles.values()),
|
|
1269
|
+
});
|
|
1270
|
+
});
|
|
1247
1271
|
// Last, once everything above is up: the reaper's post-boot pass and hourly sweep. Its
|
|
1248
1272
|
// not-active escalation is also off until here, so no delete can land while the boot loop is
|
|
1249
1273
|
// still wiring runtimes and launchers. Nothing here may fail start() — a throw from inside the boot loop takes every runtime down, which
|
|
@@ -1273,6 +1297,8 @@ const senpiRuntimePlugin = {
|
|
|
1273
1297
|
await reaper.stop();
|
|
1274
1298
|
strategiesPublisher.stop();
|
|
1275
1299
|
eventsPublisher.stop();
|
|
1300
|
+
disposeBoxMemoryGauges?.();
|
|
1301
|
+
disposeBoxMemoryGauges = undefined;
|
|
1276
1302
|
// Drain the HTTP server FIRST so in-flight POST /signals requests
|
|
1277
1303
|
// finish before the underlying runtime they target is torn down.
|
|
1278
1304
|
// `apiHandle.close()` never throws.
|
|
@@ -1833,7 +1859,7 @@ const senpiRuntimePlugin = {
|
|
|
1833
1859
|
if (!mcpTransport)
|
|
1834
1860
|
await client.connect();
|
|
1835
1861
|
try {
|
|
1836
|
-
const strategies = await client.
|
|
1862
|
+
const strategies = await client.listStrategiesForWallets([wallet]);
|
|
1837
1863
|
const match = strategies.find((s) => s.strategyWalletAddress.toLowerCase() === wallet.toLowerCase());
|
|
1838
1864
|
if (!match) {
|
|
1839
1865
|
pluginLogger.info("[senpi-runtime] Wallet validation failed: not owned", { wallet });
|
|
@@ -2021,7 +2047,8 @@ const senpiRuntimePlugin = {
|
|
|
2021
2047
|
const targetAddress = typeof params?.address === "string" ? params.address : undefined;
|
|
2022
2048
|
// Set only by the lifecycle reaper: why the strategy counts as gone (stamped on runtime.deleted)
|
|
2023
2049
|
// and which wallet that verdict was about (the concurrency guard below).
|
|
2024
|
-
const deleteReason = params?.deleteReason === "closed_status"
|
|
2050
|
+
const deleteReason = params?.deleteReason === "closed_status" || params?.deleteReason === "paper_failed_status"
|
|
2051
|
+
? params.deleteReason
|
|
2025
2052
|
: undefined;
|
|
2026
2053
|
const expectWallet = typeof params?.expectWallet === "string" && params.expectWallet.trim().length > 0
|
|
2027
2054
|
? params.expectWallet.trim().toLowerCase()
|
|
@@ -2265,7 +2292,7 @@ const senpiRuntimePlugin = {
|
|
|
2265
2292
|
return;
|
|
2266
2293
|
let ids = strategyIds ?? null;
|
|
2267
2294
|
if (strategyIds === undefined && !plan.unchanged) {
|
|
2268
|
-
const read = await readBootWalletStatuses([plan.wallet.trim().toLowerCase()], (wallets, signal) => withSenpiClient((client) => client.
|
|
2295
|
+
const read = await readBootWalletStatuses([plan.wallet.trim().toLowerCase()], (wallets, signal) => withSenpiClient((client) => client.listStrategiesForWallets(wallets, { signal })));
|
|
2269
2296
|
if (!read.ok) {
|
|
2270
2297
|
factsLogger.warn("strategy facts failed: could not read the strategy id; retrying next boot", undefined, {
|
|
2271
2298
|
runtimeId: plan.runtimeId,
|
|
@@ -2513,6 +2540,10 @@ const senpiRuntimePlugin = {
|
|
|
2513
2540
|
},
|
|
2514
2541
|
registryFindByWallet: findRegistryEntryByWallet,
|
|
2515
2542
|
registryFindById: findRegistryEntryById,
|
|
2543
|
+
countRegistryRuntimes: async () => {
|
|
2544
|
+
const { readRegistry } = await import("./runtime/strategy-registry.js");
|
|
2545
|
+
return (await readRegistry(baseStateDir)).runtimes.length;
|
|
2546
|
+
},
|
|
2516
2547
|
// A deploy job outlives a reload; it reads the runtime where it runs (see `liveHostIfStopped`).
|
|
2517
2548
|
getScannerRows: (id) => liveHostIfStopped()?.getScannerRows(id) ?? readScannerRows(id),
|
|
2518
2549
|
// H4: `runtimeHandles` holds the live `run()` handles. A registry row without one is a
|