@botiverse/raft-daemon 0.63.5-play.20260623160336 → 0.63.6
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/{chunk-A2AHKVS2.js → chunk-DUWRNQQE.js} +226 -148
- package/dist/core.js +1 -5
- package/dist/index.js +3 -5
- package/package.json +2 -1
|
@@ -2683,19 +2683,6 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
|
|
|
2683
2683
|
return candidates.filter((candidate) => existsSync(candidate.path));
|
|
2684
2684
|
}
|
|
2685
2685
|
|
|
2686
|
-
// src/authEnv.ts
|
|
2687
|
-
var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
|
|
2688
|
-
var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
|
|
2689
|
-
function scrubDaemonAuthEnv(env) {
|
|
2690
|
-
delete env[DAEMON_API_KEY_ENV];
|
|
2691
|
-
return env;
|
|
2692
|
-
}
|
|
2693
|
-
function scrubDaemonChildEnv(env) {
|
|
2694
|
-
delete env[DAEMON_API_KEY_ENV];
|
|
2695
|
-
delete env[SLOCK_AGENT_TOKEN_ENV];
|
|
2696
|
-
return env;
|
|
2697
|
-
}
|
|
2698
|
-
|
|
2699
2686
|
// src/agentCredentialProxy.ts
|
|
2700
2687
|
import { randomBytes } from "crypto";
|
|
2701
2688
|
import http from "http";
|
|
@@ -3535,6 +3522,7 @@ function latestVisibleMessages(messages, limit) {
|
|
|
3535
3522
|
return sorted.slice(Math.max(0, sorted.length - limit));
|
|
3536
3523
|
}
|
|
3537
3524
|
function isMessageModelSeen(input, message) {
|
|
3525
|
+
if (messageSenderId(message) === input.agentId) return true;
|
|
3538
3526
|
const seq = Math.floor(messageSeq(message));
|
|
3539
3527
|
if (Number.isFinite(seq) && seq > 0 && typeof input.modelSeenSeq === "number" && input.modelSeenSeq >= seq) return true;
|
|
3540
3528
|
return input.isMessageModelSeen?.({ target: input.target, message }) === true;
|
|
@@ -4262,9 +4250,7 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
|
|
|
4262
4250
|
var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
|
|
4263
4251
|
var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
4264
4252
|
var RAW_CREDENTIAL_ENV_DENYLIST = [
|
|
4265
|
-
"
|
|
4266
|
-
"SLOCK_AGENT_CREDENTIAL_KEY",
|
|
4267
|
-
"SLOCK_AGENT_CREDENTIAL_KEY_FILE"
|
|
4253
|
+
"SLOCK_AGENT_CREDENTIAL_KEY"
|
|
4268
4254
|
];
|
|
4269
4255
|
var WORKSPACE_CLI_TRANSPORT_FILENAMES = [
|
|
4270
4256
|
"agent-token",
|
|
@@ -4616,7 +4602,7 @@ set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
|
|
|
4616
4602
|
SLOCK_SERVER_URL: ctx.config.serverUrl,
|
|
4617
4603
|
PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
|
|
4618
4604
|
};
|
|
4619
|
-
|
|
4605
|
+
delete spawnEnv.SLOCK_AGENT_TOKEN;
|
|
4620
4606
|
for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
|
|
4621
4607
|
delete spawnEnv[key];
|
|
4622
4608
|
}
|
|
@@ -5138,7 +5124,7 @@ function requiresWindowsShell(command, platform = process.platform) {
|
|
|
5138
5124
|
}
|
|
5139
5125
|
function resolveCommandOnPath(command, deps = {}) {
|
|
5140
5126
|
const platform = deps.platform ?? process.platform;
|
|
5141
|
-
const env =
|
|
5127
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
5142
5128
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
5143
5129
|
const existsSyncFn = deps.existsSyncFn ?? existsSync3;
|
|
5144
5130
|
if (platform === "win32") {
|
|
@@ -5164,7 +5150,7 @@ function firstExistingPath(candidates, deps = {}) {
|
|
|
5164
5150
|
return null;
|
|
5165
5151
|
}
|
|
5166
5152
|
function readCommandVersion(command, args = [], deps = {}) {
|
|
5167
|
-
const env =
|
|
5153
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
5168
5154
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
5169
5155
|
try {
|
|
5170
5156
|
const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
|
|
@@ -7244,11 +7230,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
|
|
|
7244
7230
|
return parseCursorModelsOutput(String(result.stdout || ""));
|
|
7245
7231
|
}
|
|
7246
7232
|
function buildCursorModelProbeEnv(deps = {}) {
|
|
7247
|
-
return
|
|
7233
|
+
return withWindowsUserEnvironment({
|
|
7248
7234
|
...deps.env ?? process.env,
|
|
7249
7235
|
FORCE_COLOR: "0",
|
|
7250
7236
|
NO_COLOR: "1"
|
|
7251
|
-
}, deps)
|
|
7237
|
+
}, deps);
|
|
7252
7238
|
}
|
|
7253
7239
|
function runCursorModelsCommand() {
|
|
7254
7240
|
return spawnSync("cursor-agent", ["models"], {
|
|
@@ -7304,7 +7290,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
|
|
|
7304
7290
|
}
|
|
7305
7291
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
|
|
7306
7292
|
const existsSyncFn = deps.existsSyncFn ?? existsSync5;
|
|
7307
|
-
const env =
|
|
7293
|
+
const env = deps.env ?? process.env;
|
|
7308
7294
|
const winPath = path8.win32;
|
|
7309
7295
|
let geminiEntry = null;
|
|
7310
7296
|
try {
|
|
@@ -7441,15 +7427,12 @@ var GeminiDriver = class {
|
|
|
7441
7427
|
// src/drivers/kimi.ts
|
|
7442
7428
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
7443
7429
|
import { spawn as spawn7 } from "child_process";
|
|
7444
|
-
import {
|
|
7430
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
7445
7431
|
import os4 from "os";
|
|
7446
7432
|
import path9 from "path";
|
|
7447
7433
|
var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
|
|
7448
7434
|
var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
|
|
7449
7435
|
var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
|
|
7450
|
-
var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
|
|
7451
|
-
var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
|
|
7452
|
-
var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
|
|
7453
7436
|
function parseToolArguments(raw) {
|
|
7454
7437
|
if (typeof raw !== "string") return raw;
|
|
7455
7438
|
try {
|
|
@@ -7458,73 +7441,6 @@ function parseToolArguments(raw) {
|
|
|
7458
7441
|
return raw;
|
|
7459
7442
|
}
|
|
7460
7443
|
}
|
|
7461
|
-
function readKimiConfigSource(home = os4.homedir(), env = process.env) {
|
|
7462
|
-
const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
7463
|
-
if (inlineConfig && inlineConfig.trim()) {
|
|
7464
|
-
return {
|
|
7465
|
-
raw: inlineConfig,
|
|
7466
|
-
explicitPath: null,
|
|
7467
|
-
sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
|
|
7468
|
-
};
|
|
7469
|
-
}
|
|
7470
|
-
const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
7471
|
-
const configPath = explicitPath && explicitPath.trim() ? explicitPath : path9.join(home, ".kimi", "config.toml");
|
|
7472
|
-
try {
|
|
7473
|
-
return {
|
|
7474
|
-
raw: readFileSync3(configPath, "utf8"),
|
|
7475
|
-
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
7476
|
-
sourcePath: configPath
|
|
7477
|
-
};
|
|
7478
|
-
} catch {
|
|
7479
|
-
return {
|
|
7480
|
-
raw: null,
|
|
7481
|
-
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
7482
|
-
sourcePath: configPath
|
|
7483
|
-
};
|
|
7484
|
-
}
|
|
7485
|
-
}
|
|
7486
|
-
function buildKimiSpawnEnv(env = process.env) {
|
|
7487
|
-
const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
|
|
7488
|
-
delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
7489
|
-
delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
7490
|
-
return scrubDaemonChildEnv(spawnEnv);
|
|
7491
|
-
}
|
|
7492
|
-
function buildKimiEffectiveEnv(ctx, overrideEnv) {
|
|
7493
|
-
return {
|
|
7494
|
-
...process.env,
|
|
7495
|
-
...ctx.config.envVars || {},
|
|
7496
|
-
...overrideEnv || {}
|
|
7497
|
-
};
|
|
7498
|
-
}
|
|
7499
|
-
function buildKimiLaunchOptions(ctx, opts = {}) {
|
|
7500
|
-
const env = buildKimiEffectiveEnv(ctx, opts.env);
|
|
7501
|
-
const source = readKimiConfigSource(opts.home ?? os4.homedir(), env);
|
|
7502
|
-
const args = [];
|
|
7503
|
-
let configFilePath = null;
|
|
7504
|
-
let configContent = null;
|
|
7505
|
-
if (source.explicitPath) {
|
|
7506
|
-
configFilePath = source.explicitPath;
|
|
7507
|
-
} else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
|
|
7508
|
-
configFilePath = path9.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
|
|
7509
|
-
configContent = source.raw;
|
|
7510
|
-
if (opts.writeGeneratedConfig !== false) {
|
|
7511
|
-
writeFileSync3(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
|
|
7512
|
-
chmodSync(configFilePath, 384);
|
|
7513
|
-
}
|
|
7514
|
-
}
|
|
7515
|
-
if (configFilePath) {
|
|
7516
|
-
args.push("--config-file", configFilePath);
|
|
7517
|
-
}
|
|
7518
|
-
if (ctx.config.model && ctx.config.model !== "default") {
|
|
7519
|
-
args.push("--model", ctx.config.model);
|
|
7520
|
-
}
|
|
7521
|
-
return {
|
|
7522
|
-
args,
|
|
7523
|
-
env: buildKimiSpawnEnv(env),
|
|
7524
|
-
configFilePath,
|
|
7525
|
-
configContent
|
|
7526
|
-
};
|
|
7527
|
-
}
|
|
7528
7444
|
function resolveKimiSpawn(commandArgs, deps = {}) {
|
|
7529
7445
|
return {
|
|
7530
7446
|
command: resolveCommandOnPath("kimi", deps) ?? "kimi",
|
|
@@ -7548,25 +7464,7 @@ var KimiDriver = class {
|
|
|
7548
7464
|
};
|
|
7549
7465
|
model = {
|
|
7550
7466
|
detectedModelsVerifiedAs: "launchable",
|
|
7551
|
-
toLaunchSpec: (modelId
|
|
7552
|
-
if (!ctx) return { args: ["--model", modelId] };
|
|
7553
|
-
const launchCtx = {
|
|
7554
|
-
...ctx,
|
|
7555
|
-
config: {
|
|
7556
|
-
...ctx.config,
|
|
7557
|
-
model: modelId
|
|
7558
|
-
}
|
|
7559
|
-
};
|
|
7560
|
-
const launch = buildKimiLaunchOptions(launchCtx, {
|
|
7561
|
-
home: opts?.home,
|
|
7562
|
-
writeGeneratedConfig: false
|
|
7563
|
-
});
|
|
7564
|
-
return {
|
|
7565
|
-
args: launch.args,
|
|
7566
|
-
env: launch.env,
|
|
7567
|
-
configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
|
|
7568
|
-
};
|
|
7569
|
-
}
|
|
7467
|
+
toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
|
|
7570
7468
|
};
|
|
7571
7469
|
supportsStdinNotification = true;
|
|
7572
7470
|
busyDeliveryMode = "direct";
|
|
@@ -7590,23 +7488,21 @@ var KimiDriver = class {
|
|
|
7590
7488
|
` system_prompt_path: ./${KIMI_SYSTEM_PROMPT_FILE}`,
|
|
7591
7489
|
""
|
|
7592
7490
|
].join("\n"), "utf8");
|
|
7593
|
-
const launch = buildKimiLaunchOptions(ctx);
|
|
7594
7491
|
const args = [
|
|
7595
7492
|
"--wire",
|
|
7596
7493
|
"--yolo",
|
|
7597
7494
|
"--agent-file",
|
|
7598
7495
|
agentFilePath,
|
|
7599
7496
|
"--session",
|
|
7600
|
-
this.sessionId
|
|
7601
|
-
...launch.args
|
|
7497
|
+
this.sessionId
|
|
7602
7498
|
];
|
|
7603
7499
|
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
7604
7500
|
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
7605
7501
|
args.push("--model", launchRuntimeFields.model);
|
|
7606
7502
|
}
|
|
7607
7503
|
const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
7608
|
-
const
|
|
7609
|
-
const proc = spawn7(
|
|
7504
|
+
const launch = resolveKimiSpawn(args);
|
|
7505
|
+
const proc = spawn7(launch.command, launch.args, {
|
|
7610
7506
|
cwd: ctx.workingDirectory,
|
|
7611
7507
|
stdio: ["pipe", "pipe", "pipe"],
|
|
7612
7508
|
env: spawnEnv,
|
|
@@ -7614,7 +7510,7 @@ var KimiDriver = class {
|
|
|
7614
7510
|
// and has an 8191-character command-line limit. Kimi's official
|
|
7615
7511
|
// installer/uv entrypoint is an executable, so launch it directly and
|
|
7616
7512
|
// keep prompts on stdin / files instead of routing through cmd.exe.
|
|
7617
|
-
shell:
|
|
7513
|
+
shell: launch.shell
|
|
7618
7514
|
});
|
|
7619
7515
|
proc.stdin?.write(JSON.stringify({
|
|
7620
7516
|
jsonrpc: "2.0",
|
|
@@ -7727,9 +7623,14 @@ var KimiDriver = class {
|
|
|
7727
7623
|
return detectKimiModels();
|
|
7728
7624
|
}
|
|
7729
7625
|
};
|
|
7730
|
-
function detectKimiModels(home = os4.homedir()
|
|
7731
|
-
const
|
|
7732
|
-
|
|
7626
|
+
function detectKimiModels(home = os4.homedir()) {
|
|
7627
|
+
const configPath = path9.join(home, ".kimi", "config.toml");
|
|
7628
|
+
let raw;
|
|
7629
|
+
try {
|
|
7630
|
+
raw = readFileSync3(configPath, "utf8");
|
|
7631
|
+
} catch {
|
|
7632
|
+
return null;
|
|
7633
|
+
}
|
|
7733
7634
|
const models = [];
|
|
7734
7635
|
const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
|
|
7735
7636
|
const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
|
|
@@ -8395,7 +8296,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
8395
8296
|
const platform = deps.platform ?? process.platform;
|
|
8396
8297
|
const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
|
|
8397
8298
|
const result = spawnSyncFn("opencode", ["models"], {
|
|
8398
|
-
env:
|
|
8299
|
+
env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
|
|
8399
8300
|
encoding: "utf8",
|
|
8400
8301
|
timeout: 5e3,
|
|
8401
8302
|
shell: platform === "win32"
|
|
@@ -10440,6 +10341,7 @@ var STDIN_NOTIFICATION_INITIAL_DELAY_MS = 3e3;
|
|
|
10440
10341
|
var STDIN_NOTIFICATION_RETRY_DELAY_MS = 15e3;
|
|
10441
10342
|
var RUNTIME_ERROR_DELIVERY_BACKOFF_BASE_MS = 1e4;
|
|
10442
10343
|
var RUNTIME_ERROR_DELIVERY_BACKOFF_MAX_MS = 5 * 6e4;
|
|
10344
|
+
var RUNTIME_ERROR_FINGERPRINT_FENCE_THRESHOLD = 3;
|
|
10443
10345
|
var SPAWN_FAIL_BACKOFF_BASE_MS = 1e3;
|
|
10444
10346
|
var SPAWN_FAIL_BACKOFF_MAX_MS = 3e4;
|
|
10445
10347
|
var SPAWN_FAIL_BACKOFF_THRESHOLD = 3;
|
|
@@ -11349,6 +11251,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
11349
11251
|
agentStartIntervalMs;
|
|
11350
11252
|
startingInboxes = /* @__PURE__ */ new Map();
|
|
11351
11253
|
terminalRuntimeFailures = /* @__PURE__ */ new Map();
|
|
11254
|
+
runtimeErrorFingerprintFences = /* @__PURE__ */ new Map();
|
|
11352
11255
|
pendingStartRebinds = /* @__PURE__ */ new Map();
|
|
11353
11256
|
/** Cached configs for agents whose process exited normally — enables auto-restart on next message */
|
|
11354
11257
|
idleAgentConfigs = /* @__PURE__ */ new Map();
|
|
@@ -11515,6 +11418,94 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
11515
11418
|
if (state.timer) clearTimeout(state.timer);
|
|
11516
11419
|
this.agentSpawnFailBackoff.delete(agentId);
|
|
11517
11420
|
}
|
|
11421
|
+
// ----- RUNTIME-ERROR FINGERPRINT FENCE (per-agent) ---------------------
|
|
11422
|
+
// The delivery backoff above is scoped to AgentProcess and is cleared when a
|
|
11423
|
+
// runtime process exits. Recoverable terminal errors intentionally keep an
|
|
11424
|
+
// idle restart cache so the next message can wake the agent, but that also
|
|
11425
|
+
// means a deterministic same-fingerprint runtime error can close/restart
|
|
11426
|
+
// forever. Keep this counter outside AgentProcess and reset only on real turn
|
|
11427
|
+
// progress or explicit stop.
|
|
11428
|
+
runtimeErrorFingerprintFenceResetEvent(eventKind) {
|
|
11429
|
+
switch (eventKind) {
|
|
11430
|
+
case "thinking":
|
|
11431
|
+
case "text":
|
|
11432
|
+
case "tool_call":
|
|
11433
|
+
case "tool_output":
|
|
11434
|
+
case "compaction_finished":
|
|
11435
|
+
case "review_finished":
|
|
11436
|
+
case "turn_end":
|
|
11437
|
+
return true;
|
|
11438
|
+
default:
|
|
11439
|
+
return false;
|
|
11440
|
+
}
|
|
11441
|
+
}
|
|
11442
|
+
resetRuntimeErrorFingerprintFence(agentId, resetSource, ap) {
|
|
11443
|
+
const state = this.runtimeErrorFingerprintFences.get(agentId);
|
|
11444
|
+
if (!state) return;
|
|
11445
|
+
this.runtimeErrorFingerprintFences.delete(agentId);
|
|
11446
|
+
this.recordDaemonTrace("daemon.agent.runtime_error_fingerprint_fence.reset", {
|
|
11447
|
+
agentId,
|
|
11448
|
+
runtime: ap?.config.runtime,
|
|
11449
|
+
model: ap?.config.model,
|
|
11450
|
+
launchId: ap?.launchId || state.launchId || void 0,
|
|
11451
|
+
fingerprint: state.fingerprint,
|
|
11452
|
+
attempts: state.attempts,
|
|
11453
|
+
reset_source: resetSource
|
|
11454
|
+
});
|
|
11455
|
+
}
|
|
11456
|
+
formatRuntimeErrorFingerprintFenceDetail(state) {
|
|
11457
|
+
return [
|
|
11458
|
+
`Runtime stopped after ${state.attempts} repeated runtime errors with the same fingerprint (${state.fingerprint}).`,
|
|
11459
|
+
`Last error: ${state.lastRuntimeError}`,
|
|
11460
|
+
"Restart after the runtime/tooling issue is fixed."
|
|
11461
|
+
].join(" ");
|
|
11462
|
+
}
|
|
11463
|
+
noteRuntimeErrorFingerprintFence(agentId, ap, message, fingerprint, terminalFailure, stickyTerminalFailure) {
|
|
11464
|
+
if (!fingerprint) return null;
|
|
11465
|
+
if (stickyTerminalFailure || terminalFailure?.actionRequired) return null;
|
|
11466
|
+
let state = this.runtimeErrorFingerprintFences.get(agentId);
|
|
11467
|
+
if (!state || state.fingerprint !== fingerprint) {
|
|
11468
|
+
state = {
|
|
11469
|
+
fingerprint,
|
|
11470
|
+
attempts: 0,
|
|
11471
|
+
lastRuntimeError: message,
|
|
11472
|
+
detail: "",
|
|
11473
|
+
launchId: ap.launchId
|
|
11474
|
+
};
|
|
11475
|
+
this.runtimeErrorFingerprintFences.set(agentId, state);
|
|
11476
|
+
}
|
|
11477
|
+
state.attempts += 1;
|
|
11478
|
+
state.lastRuntimeError = message;
|
|
11479
|
+
state.launchId = ap.launchId;
|
|
11480
|
+
state.detail = this.formatRuntimeErrorFingerprintFenceDetail(state);
|
|
11481
|
+
const fenced = state.attempts >= RUNTIME_ERROR_FINGERPRINT_FENCE_THRESHOLD;
|
|
11482
|
+
this.recordDaemonTrace("daemon.agent.runtime_error_fingerprint_fence", {
|
|
11483
|
+
agentId,
|
|
11484
|
+
runtime: ap.config.runtime,
|
|
11485
|
+
model: ap.config.model,
|
|
11486
|
+
launchId: ap.launchId || void 0,
|
|
11487
|
+
fingerprint,
|
|
11488
|
+
attempts: state.attempts,
|
|
11489
|
+
threshold: RUNTIME_ERROR_FINGERPRINT_FENCE_THRESHOLD,
|
|
11490
|
+
fenced,
|
|
11491
|
+
runtime_error_class: buildRuntimeErrorDiagnosticEnvelope(message).spanAttrs.runtime_error_class
|
|
11492
|
+
}, fenced ? "error" : "ok");
|
|
11493
|
+
return fenced ? state : null;
|
|
11494
|
+
}
|
|
11495
|
+
applyRuntimeErrorFingerprintFence(agentId, ap, state) {
|
|
11496
|
+
this.recordDaemonTrace("daemon.agent.runtime_error_fingerprint_fence.tripped", {
|
|
11497
|
+
agentId,
|
|
11498
|
+
runtime: ap.config.runtime,
|
|
11499
|
+
model: ap.config.model,
|
|
11500
|
+
launchId: ap.launchId || void 0,
|
|
11501
|
+
fingerprint: state.fingerprint,
|
|
11502
|
+
attempts: state.attempts,
|
|
11503
|
+
threshold: RUNTIME_ERROR_FINGERPRINT_FENCE_THRESHOLD
|
|
11504
|
+
}, "error");
|
|
11505
|
+
this.idleAgentConfigs.delete(agentId);
|
|
11506
|
+
this.sendAgentStatus(agentId, "inactive", ap.launchId);
|
|
11507
|
+
this.cleanupTerminalRuntimeFailure(agentId, ap, state.detail);
|
|
11508
|
+
}
|
|
11518
11509
|
scheduleStdinNotification(agentId, ap, delayMs) {
|
|
11519
11510
|
return ap.notifications.schedule(() => {
|
|
11520
11511
|
this.sendStdinNotification(agentId);
|
|
@@ -12498,6 +12489,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
12498
12489
|
let prompt;
|
|
12499
12490
|
let promptSource;
|
|
12500
12491
|
let wakeMessageDeliveredAsInboxUpdate = false;
|
|
12492
|
+
let startingInboxDeliveredAsInput = false;
|
|
12501
12493
|
const startingInboxMessages = this.startingInboxes.get(agentId) || [];
|
|
12502
12494
|
if (runtimeConfig.runtimeProfileControl && !wakeMessage) {
|
|
12503
12495
|
prompt = driver.supportsNativeStandingPrompt ? NATIVE_STANDING_PROMPT_STARTUP_INPUT : formatRuntimeProfileControlStartupInput(runtimeConfig.runtimeProfileControl, driver);
|
|
@@ -12538,6 +12530,10 @@ You also have unread messages in other channels:`;
|
|
|
12538
12530
|
Use the inbox/read commands at a natural breakpoint if you choose to inspect those targets.`;
|
|
12539
12531
|
}
|
|
12540
12532
|
}
|
|
12533
|
+
} else if (startingInboxMessages.length > 0) {
|
|
12534
|
+
startingInboxDeliveredAsInput = true;
|
|
12535
|
+
prompt = this.formatInboxUpdateRuntimeInput(startingInboxMessages, driver);
|
|
12536
|
+
promptSource = "starting_inbox_update";
|
|
12541
12537
|
} else if (isResume && unreadSummary && Object.keys(unreadSummary).length > 0) {
|
|
12542
12538
|
prompt = `You have unread messages from while you were offline:`;
|
|
12543
12539
|
for (const [ch, count] of Object.entries(unreadSummary)) {
|
|
@@ -12670,6 +12666,10 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
12670
12666
|
}
|
|
12671
12667
|
if (wakeMessageDeliveredAsInboxUpdate) {
|
|
12672
12668
|
this.recordInboxUpdateProjection(agentId, agentProcess, agentProcess.inbox, "spawn_wake_inbox_update", "wake", prompt);
|
|
12669
|
+
} else if (startingInboxDeliveredAsInput) {
|
|
12670
|
+
this.recordInboxUpdateProjection(agentId, agentProcess, startingInboxMessages, "spawn_starting_inbox_update", "wake", prompt);
|
|
12671
|
+
this.consumeVisibleMessages(agentId, { messages: startingInboxMessages, source: "spawn_starting_inbox_update" });
|
|
12672
|
+
this.ackInjectedRuntimeProfileMessages(agentId, startingInboxMessages, agentProcess.launchId);
|
|
12673
12673
|
} else if (wakeMessage && !wakeMessageTransient) {
|
|
12674
12674
|
this.consumeVisibleMessages(agentId, { messages: [wakeMessage], source: "spawn_wake_message" });
|
|
12675
12675
|
this.ackInjectedRuntimeProfileMessages(agentId, [wakeMessage], agentProcess.launchId);
|
|
@@ -13311,6 +13311,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13311
13311
|
this.agentVisibleBoundaries.delete(agentId);
|
|
13312
13312
|
this.agentVisibleMessageIds.delete(agentId);
|
|
13313
13313
|
this.resetSpawnFailBackoff(agentId);
|
|
13314
|
+
this.resetRuntimeErrorFingerprintFence(agentId, "explicit_stop", ap);
|
|
13314
13315
|
}
|
|
13315
13316
|
this.runtimeExitTraceAttrs.set(ap.runtime, {
|
|
13316
13317
|
stop_source: silent ? "daemon_internal" : "explicit_request",
|
|
@@ -13495,6 +13496,19 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13495
13496
|
return false;
|
|
13496
13497
|
});
|
|
13497
13498
|
}
|
|
13499
|
+
if (!transientDelivery && (this.queuedAgentStarts.has(agentId) || this.agentsStarting.has(agentId))) {
|
|
13500
|
+
const pending = this.startingInboxes.get(agentId) || [];
|
|
13501
|
+
pending.push(message);
|
|
13502
|
+
this.startingInboxes.set(agentId, pending);
|
|
13503
|
+
this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
|
|
13504
|
+
outcome: this.agentsStarting.has(agentId) ? "queued_for_starting_process" : "queued_for_queued_start",
|
|
13505
|
+
accepted: true,
|
|
13506
|
+
process_present: false,
|
|
13507
|
+
cached_idle_config_present: false,
|
|
13508
|
+
starting_inbox_count: pending.length
|
|
13509
|
+
}));
|
|
13510
|
+
return true;
|
|
13511
|
+
}
|
|
13498
13512
|
logger.warn(`[Agent ${agentId}] Delivery received but no running process or cached idle config exists`);
|
|
13499
13513
|
if (transientDelivery) {
|
|
13500
13514
|
this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
|
|
@@ -15426,6 +15440,9 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
15426
15440
|
return;
|
|
15427
15441
|
}
|
|
15428
15442
|
this.noteRuntimeProgress(ap, event.kind);
|
|
15443
|
+
if (this.runtimeErrorFingerprintFenceResetEvent(event.kind)) {
|
|
15444
|
+
this.resetRuntimeErrorFingerprintFence(agentId, `runtime_progress:${event.kind}`, ap);
|
|
15445
|
+
}
|
|
15429
15446
|
recordProgressObservedAfterStall();
|
|
15430
15447
|
} else if (event.kind !== "internal_progress") {
|
|
15431
15448
|
this.recordDaemonTrace("daemon.agent.event.received_without_process", {
|
|
@@ -15618,6 +15635,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
15618
15635
|
let visibleErrorMessage = event.message;
|
|
15619
15636
|
if (ap) {
|
|
15620
15637
|
const runtimeErrorDiagnostics = buildRuntimeErrorDiagnosticEnvelope(event.message);
|
|
15638
|
+
const runtimeErrorFingerprint = typeof runtimeErrorDiagnostics.spanAttrs.runtime_error_fingerprint === "string" ? runtimeErrorDiagnostics.spanAttrs.runtime_error_fingerprint : null;
|
|
15621
15639
|
if (runtimeErrorDiagnostics.spanAttrs.runtime_error_action_required === true) {
|
|
15622
15640
|
visibleErrorMessage = formatRuntimeLoginRequiredMessage(ap.driver.id);
|
|
15623
15641
|
}
|
|
@@ -15634,6 +15652,17 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
15634
15652
|
terminalWakeable: Boolean(ap.driver.supportsStdinNotification && terminalFailure && !terminalFailure.actionRequired)
|
|
15635
15653
|
});
|
|
15636
15654
|
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "error" });
|
|
15655
|
+
const fingerprintFence = this.noteRuntimeErrorFingerprintFence(
|
|
15656
|
+
agentId,
|
|
15657
|
+
ap,
|
|
15658
|
+
event.message,
|
|
15659
|
+
runtimeErrorFingerprint,
|
|
15660
|
+
terminalFailure,
|
|
15661
|
+
stickyTerminalFailure
|
|
15662
|
+
);
|
|
15663
|
+
if (fingerprintFence) {
|
|
15664
|
+
visibleErrorMessage = fingerprintFence.detail;
|
|
15665
|
+
}
|
|
15637
15666
|
this.noteRuntimeErrorDeliveryBackoff(agentId, ap, event.message, terminalFailure, stickyTerminalFailure, backoffReasonOverride);
|
|
15638
15667
|
if (reduction.shouldDisableToolBoundaryFlush) {
|
|
15639
15668
|
this.recordGatedSteeringEvent(agentId, ap, "disabled", {
|
|
@@ -15654,7 +15683,9 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
15654
15683
|
...runtimeTraceCounterAttrs(ap),
|
|
15655
15684
|
...this.finalizeRuntimeProfileTurnControl(agentId, ap, "runtime_error")
|
|
15656
15685
|
});
|
|
15657
|
-
if (
|
|
15686
|
+
if (fingerprintFence) {
|
|
15687
|
+
this.applyRuntimeErrorFingerprintFence(agentId, ap, fingerprintFence);
|
|
15688
|
+
} else if (ap.driver.supportsStdinNotification && terminalFailure) {
|
|
15658
15689
|
if (terminalFailure.actionRequired) {
|
|
15659
15690
|
logger.warn(`[Agent ${agentId}] ${ap.driver.id} auth requires user action; terminating runtime process`);
|
|
15660
15691
|
try {
|
|
@@ -17174,9 +17205,10 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
|
|
|
17174
17205
|
eventAttrs: {
|
|
17175
17206
|
"daemon.receive": ["seq", "deliveryId"],
|
|
17176
17207
|
"daemon.deliver_to_agent_manager": ["accepted"],
|
|
17208
|
+
"daemon.delivery.buffered_for_start": ["pending_count"],
|
|
17177
17209
|
"daemon.ack.sent": ["seq"]
|
|
17178
17210
|
},
|
|
17179
|
-
endAttrs: ["outcome", "ackSeq", "deliveryId", "error_class"]
|
|
17211
|
+
endAttrs: ["outcome", "ackSeq", "deliveryId", "error_class", "pending_count"]
|
|
17180
17212
|
},
|
|
17181
17213
|
"daemon.runtime_profile.control.received": {
|
|
17182
17214
|
spanAttrs: ["agentId", "control_kind", "key_present", "launchId"],
|
|
@@ -17222,7 +17254,7 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
|
|
|
17222
17254
|
spanAttrs: ["agentId", "event_kind", "runtime"]
|
|
17223
17255
|
}
|
|
17224
17256
|
};
|
|
17225
|
-
var DAEMON_CLI_USAGE =
|
|
17257
|
+
var DAEMON_CLI_USAGE = "Usage: slock-daemon --server-url <url> --api-key <key>";
|
|
17226
17258
|
var RunnerCredentialMintError2 = class extends Error {
|
|
17227
17259
|
code;
|
|
17228
17260
|
retryable;
|
|
@@ -17258,9 +17290,9 @@ function runnerCredentialErrorDetail2(error) {
|
|
|
17258
17290
|
async function waitForRunnerCredentialRetry2() {
|
|
17259
17291
|
await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
|
|
17260
17292
|
}
|
|
17261
|
-
function parseDaemonCliArgs(args
|
|
17293
|
+
function parseDaemonCliArgs(args) {
|
|
17262
17294
|
let serverUrl = "";
|
|
17263
|
-
let apiKey =
|
|
17295
|
+
let apiKey = "";
|
|
17264
17296
|
for (let i = 0; i < args.length; i++) {
|
|
17265
17297
|
if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
|
|
17266
17298
|
if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
|
|
@@ -17460,6 +17492,8 @@ var DaemonCore = class {
|
|
|
17460
17492
|
observedMachineId = null;
|
|
17461
17493
|
localTraceSink = null;
|
|
17462
17494
|
traceBundleUploader = null;
|
|
17495
|
+
coreStartingAgentIds = /* @__PURE__ */ new Set();
|
|
17496
|
+
coreStartPendingDeliveries = /* @__PURE__ */ new Map();
|
|
17463
17497
|
constructor(options) {
|
|
17464
17498
|
this.options = options;
|
|
17465
17499
|
this.daemonVersion = options.daemonVersion ?? readDaemonVersion();
|
|
@@ -17737,19 +17771,63 @@ var DaemonCore = class {
|
|
|
17737
17771
|
}
|
|
17738
17772
|
);
|
|
17739
17773
|
}
|
|
17774
|
+
sendDeliveryAck(msg, traceparent) {
|
|
17775
|
+
const ackSeq = msg.seq > 0 ? msg.seq : msg.message.seq ?? 0;
|
|
17776
|
+
const ack = {
|
|
17777
|
+
type: "agent:deliver:ack",
|
|
17778
|
+
agentId: msg.agentId,
|
|
17779
|
+
seq: ackSeq,
|
|
17780
|
+
deliveryId: msg.deliveryId,
|
|
17781
|
+
...traceparent ? { traceparent } : {}
|
|
17782
|
+
};
|
|
17783
|
+
this.connection.send(ack);
|
|
17784
|
+
}
|
|
17740
17785
|
async startAgentFromMessage(msg) {
|
|
17741
|
-
this.
|
|
17742
|
-
|
|
17743
|
-
|
|
17744
|
-
|
|
17745
|
-
msg.
|
|
17746
|
-
config
|
|
17747
|
-
msg.
|
|
17748
|
-
msg.
|
|
17749
|
-
msg.
|
|
17750
|
-
msg.
|
|
17751
|
-
msg.wakeMessageTransient ?? false
|
|
17752
|
-
|
|
17786
|
+
this.coreStartingAgentIds.add(msg.agentId);
|
|
17787
|
+
let wakeDeliveryAck = null;
|
|
17788
|
+
let replayDeliveries = [];
|
|
17789
|
+
try {
|
|
17790
|
+
this.observeRuntimeContext(msg.config);
|
|
17791
|
+
const agentCredential = await this.mintRunnerCredential(msg.agentId, msg.config);
|
|
17792
|
+
const config = { ...msg.config, agentCredentialKey: agentCredential.apiKey, agentCredentialId: agentCredential.credentialId };
|
|
17793
|
+
const pendingDeliveries = this.coreStartPendingDeliveries.get(msg.agentId) || [];
|
|
17794
|
+
this.coreStartPendingDeliveries.delete(msg.agentId);
|
|
17795
|
+
let wakeMessage = msg.wakeMessage;
|
|
17796
|
+
let wakeMessageTransient = msg.wakeMessageTransient ?? false;
|
|
17797
|
+
replayDeliveries = [...pendingDeliveries];
|
|
17798
|
+
if (!wakeMessage) {
|
|
17799
|
+
const wakeIndex = replayDeliveries.findIndex((delivery) => delivery.transient !== true);
|
|
17800
|
+
if (wakeIndex >= 0) {
|
|
17801
|
+
const [wakeDelivery] = replayDeliveries.splice(wakeIndex, 1);
|
|
17802
|
+
if (wakeDelivery) {
|
|
17803
|
+
wakeDeliveryAck = wakeDelivery;
|
|
17804
|
+
wakeMessage = wakeDelivery.message;
|
|
17805
|
+
wakeMessageTransient = wakeDelivery.transient ?? false;
|
|
17806
|
+
}
|
|
17807
|
+
}
|
|
17808
|
+
}
|
|
17809
|
+
await this.agentManager.startAgent(
|
|
17810
|
+
msg.agentId,
|
|
17811
|
+
config,
|
|
17812
|
+
wakeMessage,
|
|
17813
|
+
msg.unreadSummary,
|
|
17814
|
+
msg.resumePrompt,
|
|
17815
|
+
msg.launchId,
|
|
17816
|
+
wakeMessageTransient
|
|
17817
|
+
);
|
|
17818
|
+
this.coreStartingAgentIds.delete(msg.agentId);
|
|
17819
|
+
if (wakeDeliveryAck) {
|
|
17820
|
+
this.sendDeliveryAck(wakeDeliveryAck);
|
|
17821
|
+
}
|
|
17822
|
+
for (const delivery of replayDeliveries) {
|
|
17823
|
+
this.handleMessage(delivery);
|
|
17824
|
+
}
|
|
17825
|
+
} catch (err) {
|
|
17826
|
+
this.coreStartPendingDeliveries.delete(msg.agentId);
|
|
17827
|
+
throw err;
|
|
17828
|
+
} finally {
|
|
17829
|
+
this.coreStartingAgentIds.delete(msg.agentId);
|
|
17830
|
+
}
|
|
17753
17831
|
}
|
|
17754
17832
|
handleMessage(msg) {
|
|
17755
17833
|
const summary = summarizeIncomingMessage(msg);
|
|
@@ -17804,6 +17882,14 @@ var DaemonCore = class {
|
|
|
17804
17882
|
logger.info(`[Agent ${msg.agentId}] Delivery received (seq=${msg.seq}, from=@${msg.message.sender_name}, target=${formatChannelTarget(msg)})`);
|
|
17805
17883
|
try {
|
|
17806
17884
|
span.addEvent("daemon.receive", { seq: msg.seq, deliveryId: msg.deliveryId });
|
|
17885
|
+
if (this.coreStartingAgentIds.has(msg.agentId)) {
|
|
17886
|
+
const pending = this.coreStartPendingDeliveries.get(msg.agentId) || [];
|
|
17887
|
+
pending.push(msg);
|
|
17888
|
+
this.coreStartPendingDeliveries.set(msg.agentId, pending);
|
|
17889
|
+
span.addEvent("daemon.delivery.buffered_for_start", { pending_count: pending.length });
|
|
17890
|
+
span.end("ok", { attrs: { outcome: "buffered-for-start", pending_count: pending.length } });
|
|
17891
|
+
break;
|
|
17892
|
+
}
|
|
17807
17893
|
const acceptedOrPromise = this.agentManager.deliverMessage(msg.agentId, msg.message, {
|
|
17808
17894
|
deliveryId: msg.deliveryId,
|
|
17809
17895
|
transient: msg.transient ?? false
|
|
@@ -17816,13 +17902,7 @@ var DaemonCore = class {
|
|
|
17816
17902
|
}
|
|
17817
17903
|
const ackSeq = msg.seq > 0 ? msg.seq : msg.message.seq ?? 0;
|
|
17818
17904
|
span.addEvent("daemon.ack.sent", { seq: ackSeq });
|
|
17819
|
-
this.
|
|
17820
|
-
type: "agent:deliver:ack",
|
|
17821
|
-
agentId: msg.agentId,
|
|
17822
|
-
seq: ackSeq,
|
|
17823
|
-
traceparent: formatTraceparent(span.context),
|
|
17824
|
-
deliveryId: msg.deliveryId
|
|
17825
|
-
});
|
|
17905
|
+
this.sendDeliveryAck(msg, formatTraceparent(span.context));
|
|
17826
17906
|
span.end("ok", { attrs: { outcome: "ack-sent", ackSeq, deliveryId: msg.deliveryId } });
|
|
17827
17907
|
}, (err) => {
|
|
17828
17908
|
logger.error(`[Agent ${msg.agentId}] Delivery handling failed`, err);
|
|
@@ -18186,8 +18266,6 @@ var DaemonCore = class {
|
|
|
18186
18266
|
|
|
18187
18267
|
export {
|
|
18188
18268
|
subscribeDaemonLogs,
|
|
18189
|
-
DAEMON_API_KEY_ENV,
|
|
18190
|
-
scrubDaemonAuthEnv,
|
|
18191
18269
|
resolveWorkspaceDirectoryPath,
|
|
18192
18270
|
scanWorkspaceDirectories,
|
|
18193
18271
|
deleteWorkspaceDirectory,
|
package/dist/core.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DAEMON_API_KEY_ENV,
|
|
3
2
|
DAEMON_CLI_USAGE,
|
|
4
3
|
DaemonCore,
|
|
5
4
|
deleteWorkspaceDirectory,
|
|
@@ -11,11 +10,9 @@ import {
|
|
|
11
10
|
resolveWorkspaceDirectoryPath,
|
|
12
11
|
runBundledSlockCli,
|
|
13
12
|
scanWorkspaceDirectories,
|
|
14
|
-
scrubDaemonAuthEnv,
|
|
15
13
|
subscribeDaemonLogs
|
|
16
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-DUWRNQQE.js";
|
|
17
15
|
export {
|
|
18
|
-
DAEMON_API_KEY_ENV,
|
|
19
16
|
DAEMON_CLI_USAGE,
|
|
20
17
|
DaemonCore,
|
|
21
18
|
deleteWorkspaceDirectory,
|
|
@@ -27,6 +24,5 @@ export {
|
|
|
27
24
|
resolveWorkspaceDirectoryPath,
|
|
28
25
|
runBundledSlockCli,
|
|
29
26
|
scanWorkspaceDirectories,
|
|
30
|
-
scrubDaemonAuthEnv,
|
|
31
27
|
subscribeDaemonLogs
|
|
32
28
|
};
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
DAEMON_CLI_USAGE,
|
|
4
4
|
DaemonCore,
|
|
5
|
-
parseDaemonCliArgs
|
|
6
|
-
|
|
7
|
-
} from "./chunk-A2AHKVS2.js";
|
|
5
|
+
parseDaemonCliArgs
|
|
6
|
+
} from "./chunk-DUWRNQQE.js";
|
|
8
7
|
|
|
9
8
|
// src/index.ts
|
|
10
|
-
var parsedArgs = parseDaemonCliArgs(process.argv.slice(2)
|
|
11
|
-
scrubDaemonAuthEnv(process.env);
|
|
9
|
+
var parsedArgs = parseDaemonCliArgs(process.argv.slice(2));
|
|
12
10
|
if (!parsedArgs) {
|
|
13
11
|
console.error(DAEMON_CLI_USAGE);
|
|
14
12
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botiverse/raft-daemon",
|
|
3
|
-
"version": "0.63.
|
|
3
|
+
"version": "0.63.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"raft-daemon": "dist/raft-daemon.js",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"@slock-ai/trace-client": "workspace:*",
|
|
63
63
|
"@types/node": "^25.5.0",
|
|
64
64
|
"@types/ws": "^8.18.1",
|
|
65
|
+
"fast-check": "^4.8.0",
|
|
65
66
|
"tsup": "^8.5.1",
|
|
66
67
|
"typescript": "^5.9.3"
|
|
67
68
|
}
|