@botiverse/raft-daemon 0.72.4-play.20260709142358 → 0.72.4
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-OEK5FGK6.js → chunk-TPDIIRNC.js} +691 -191
- package/dist/cli/index.js +33 -2
- package/dist/core.js +9 -1
- package/dist/{dist-NS7NN3BV.js → dist-VNC64ECP.js} +33 -2
- package/dist/index.js +1 -1
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/core.ts
|
|
2
|
-
import
|
|
2
|
+
import path23 from "path";
|
|
3
3
|
import os8 from "os";
|
|
4
4
|
import { createRequire as createRequire3 } from "module";
|
|
5
5
|
import { accessSync } from "fs";
|
|
@@ -636,12 +636,12 @@ function parseModelConfig(runtimeModels, runtime, value, fallback, usesLegacyCla
|
|
|
636
636
|
if (value.kind === "custom" && typeof value.name === "string" && value.name.trim()) {
|
|
637
637
|
return { kind: "custom", name: value.name.trim() };
|
|
638
638
|
}
|
|
639
|
-
if (value.kind === "preset" && typeof value.id === "string" && value.id.trim() && isPresetRuntimeModel(runtimeModels, runtime, value.id.trim())) {
|
|
640
|
-
return { kind: "preset", id: value.id.trim() };
|
|
641
|
-
}
|
|
642
639
|
if (usesLegacyClaudeCustomProvider && runtime === "claude" && legacyCustomModel?.trim()) {
|
|
643
640
|
return { kind: "custom", name: legacyCustomModel.trim() };
|
|
644
641
|
}
|
|
642
|
+
if (value.kind === "preset" && typeof value.id === "string" && value.id.trim()) {
|
|
643
|
+
return { kind: "preset", id: value.id.trim() };
|
|
644
|
+
}
|
|
645
645
|
return modelConfigFromLegacy(runtimeModels, runtime, fallback);
|
|
646
646
|
}
|
|
647
647
|
function parseModeConfig(value) {
|
|
@@ -1366,6 +1366,9 @@ var PROMOTED_IDENTITY_ATTRS = [
|
|
|
1366
1366
|
"caller_kind"
|
|
1367
1367
|
];
|
|
1368
1368
|
var PROMOTED_CLOSED_ATTRS = [
|
|
1369
|
+
"router_reason",
|
|
1370
|
+
"stale_owner_cleanup_result",
|
|
1371
|
+
"stale_owner_cleanup_reason",
|
|
1369
1372
|
"outcome",
|
|
1370
1373
|
"reason",
|
|
1371
1374
|
"event_kind",
|
|
@@ -1374,6 +1377,8 @@ var PROMOTED_CLOSED_ATTRS = [
|
|
|
1374
1377
|
"activity_write_site",
|
|
1375
1378
|
"activity_source",
|
|
1376
1379
|
"hint_source",
|
|
1380
|
+
"weak_source",
|
|
1381
|
+
"competing_fact",
|
|
1377
1382
|
"resolved_activity",
|
|
1378
1383
|
"previous_activity",
|
|
1379
1384
|
"next_activity",
|
|
@@ -1459,11 +1464,16 @@ var TRACE_B0_FIELD_DEFINITIONS = defineTraceFields([
|
|
|
1459
1464
|
{ key: "served_from", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1460
1465
|
{ key: "authority", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1461
1466
|
{ key: "decided_by", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1467
|
+
{ key: "router_reason", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1468
|
+
{ key: "stale_owner_cleanup_result", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1469
|
+
{ key: "stale_owner_cleanup_reason", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1462
1470
|
{ key: "error_class", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1463
1471
|
{ key: "query_name", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "query_registry" },
|
|
1464
1472
|
{ key: "phase", fieldClass: "query_axis", placement: "span_or_event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1465
1473
|
{ key: "eligibility_subcheck", fieldClass: "query_axis", placement: "event", valueKind: "closed_enum", enumBinding: "pending_457" },
|
|
1466
1474
|
{ key: "hint_source", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1475
|
+
{ key: "weak_source", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1476
|
+
{ key: "competing_fact", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1467
1477
|
{ key: "resolved_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1468
1478
|
{ key: "previous_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
1469
1479
|
{ key: "next_activity", fieldClass: "family_query_axis", placement: "event", valueKind: "closed_enum", scope: "family:activity" },
|
|
@@ -2017,7 +2027,7 @@ var optionalIsoTimestampSchema = z2.string().datetime().optional();
|
|
|
2017
2027
|
var agentStatusSchema = z2.enum(["active", "inactive", "stopped"]);
|
|
2018
2028
|
var reminderStatusSchema = z2.enum(["scheduled", "fired", "canceled"]);
|
|
2019
2029
|
var reminderEventTypeSchema = z2.enum(["scheduled", "fired", "snoozed", "updated", "canceled"]);
|
|
2020
|
-
var reasoningEffortSchema = z2.enum(["low", "medium", "high", "xhigh"]);
|
|
2030
|
+
var reasoningEffortSchema = z2.enum(["low", "medium", "high", "xhigh", "max", "ultra"]);
|
|
2021
2031
|
var profileVisibilityMembershipStatusSchema = z2.enum(["active", "removed"]);
|
|
2022
2032
|
var passthroughObject = (shape) => z2.object(shape).passthrough();
|
|
2023
2033
|
var taskStatusSchema = z2.enum(["todo", "in_progress", "in_review", "done", "closed"]);
|
|
@@ -2694,7 +2704,7 @@ var agentApiReminderResponseSchema = passthroughObject({
|
|
|
2694
2704
|
var agentApiReminderLogResponseSchema = passthroughObject({
|
|
2695
2705
|
events: z2.array(agentApiReminderEventSummarySchema)
|
|
2696
2706
|
});
|
|
2697
|
-
var agentApiMigrationStateSchema = z2.enum(["prep", "ready", "in_transit", "arriving", "completed", "aborted", "failed"]);
|
|
2707
|
+
var agentApiMigrationStateSchema = z2.enum(["provisioning", "prep", "ready", "in_transit", "arriving", "completed", "aborted", "failed"]);
|
|
2698
2708
|
var agentApiMigrationSummarySchema = passthroughObject({
|
|
2699
2709
|
id: z2.string(),
|
|
2700
2710
|
agentId: z2.string(),
|
|
@@ -3755,6 +3765,27 @@ var RUNTIME_MODELS = {
|
|
|
3755
3765
|
{ id: "claude-haiku-4-5", label: "Claude Haiku 4.5" }
|
|
3756
3766
|
],
|
|
3757
3767
|
codex: [
|
|
3768
|
+
{
|
|
3769
|
+
id: "gpt-5.6-sol",
|
|
3770
|
+
label: "GPT-5.6 Sol",
|
|
3771
|
+
supportedReasoningEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"],
|
|
3772
|
+
defaultReasoningEffort: "medium",
|
|
3773
|
+
verified: "launchable"
|
|
3774
|
+
},
|
|
3775
|
+
{
|
|
3776
|
+
id: "gpt-5.6-terra",
|
|
3777
|
+
label: "GPT-5.6 Terra",
|
|
3778
|
+
supportedReasoningEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"],
|
|
3779
|
+
defaultReasoningEffort: "medium",
|
|
3780
|
+
verified: "launchable"
|
|
3781
|
+
},
|
|
3782
|
+
{
|
|
3783
|
+
id: "gpt-5.6-luna",
|
|
3784
|
+
label: "GPT-5.6 Luna",
|
|
3785
|
+
supportedReasoningEfforts: ["low", "medium", "high", "xhigh", "max"],
|
|
3786
|
+
defaultReasoningEffort: "medium",
|
|
3787
|
+
verified: "launchable"
|
|
3788
|
+
},
|
|
3758
3789
|
{ id: "gpt-5.5", label: "GPT-5.5" },
|
|
3759
3790
|
{ id: "gpt-5.4", label: "GPT-5.4" },
|
|
3760
3791
|
{ id: "gpt-5.3-codex", label: "GPT-5.3 Codex" },
|
|
@@ -4421,8 +4452,8 @@ async function executeResponseRequest(url, init, {
|
|
|
4421
4452
|
}
|
|
4422
4453
|
|
|
4423
4454
|
// src/directUploadCapability.ts
|
|
4424
|
-
function joinUrl(base,
|
|
4425
|
-
return `${base.replace(/\/+$/, "")}${
|
|
4455
|
+
function joinUrl(base, path24) {
|
|
4456
|
+
return `${base.replace(/\/+$/, "")}${path24}`;
|
|
4426
4457
|
}
|
|
4427
4458
|
function jsonHeaders(apiKey) {
|
|
4428
4459
|
return {
|
|
@@ -5112,15 +5143,6 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
|
|
|
5112
5143
|
return candidates.filter((candidate) => existsSync(candidate.path));
|
|
5113
5144
|
}
|
|
5114
5145
|
|
|
5115
|
-
// src/authEnv.ts
|
|
5116
|
-
var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
|
|
5117
|
-
var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
|
|
5118
|
-
function scrubDaemonChildEnv(env) {
|
|
5119
|
-
delete env[DAEMON_API_KEY_ENV];
|
|
5120
|
-
delete env[SLOCK_AGENT_TOKEN_ENV];
|
|
5121
|
-
return env;
|
|
5122
|
-
}
|
|
5123
|
-
|
|
5124
5146
|
// src/agentCredentialProxy.ts
|
|
5125
5147
|
import { randomBytes } from "crypto";
|
|
5126
5148
|
import http from "http";
|
|
@@ -6702,9 +6724,7 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
|
|
|
6702
6724
|
var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
|
|
6703
6725
|
var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
6704
6726
|
var RAW_CREDENTIAL_ENV_DENYLIST = [
|
|
6705
|
-
"
|
|
6706
|
-
"SLOCK_AGENT_CREDENTIAL_KEY",
|
|
6707
|
-
"SLOCK_AGENT_CREDENTIAL_KEY_FILE"
|
|
6727
|
+
"SLOCK_AGENT_CREDENTIAL_KEY"
|
|
6708
6728
|
];
|
|
6709
6729
|
var WORKSPACE_CLI_TRANSPORT_FILENAMES = [
|
|
6710
6730
|
"agent-token",
|
|
@@ -7059,7 +7079,7 @@ set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
|
|
|
7059
7079
|
SLOCK_SERVER_URL: ctx.config.serverUrl,
|
|
7060
7080
|
PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
|
|
7061
7081
|
};
|
|
7062
|
-
|
|
7082
|
+
delete spawnEnv.SLOCK_AGENT_TOKEN;
|
|
7063
7083
|
for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
|
|
7064
7084
|
delete spawnEnv[key];
|
|
7065
7085
|
}
|
|
@@ -7627,7 +7647,7 @@ function requiresWindowsShell(command, platform = process.platform) {
|
|
|
7627
7647
|
}
|
|
7628
7648
|
function resolveCommandOnPath(command, deps = {}) {
|
|
7629
7649
|
const platform = deps.platform ?? process.platform;
|
|
7630
|
-
const env =
|
|
7650
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
7631
7651
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
7632
7652
|
const existsSyncFn = deps.existsSyncFn ?? existsSync3;
|
|
7633
7653
|
if (platform === "win32") {
|
|
@@ -7653,7 +7673,7 @@ function firstExistingPath(candidates, deps = {}) {
|
|
|
7653
7673
|
return null;
|
|
7654
7674
|
}
|
|
7655
7675
|
function readCommandVersion(command, args = [], deps = {}) {
|
|
7656
|
-
const env =
|
|
7676
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
7657
7677
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
7658
7678
|
try {
|
|
7659
7679
|
const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
|
|
@@ -8079,7 +8099,7 @@ function codexNotificationDiagnosticEvent(message) {
|
|
|
8079
8099
|
return null;
|
|
8080
8100
|
}
|
|
8081
8101
|
const sessionId = codexMessageThreadId(message);
|
|
8082
|
-
const
|
|
8102
|
+
const path24 = boundedString(params.path);
|
|
8083
8103
|
return {
|
|
8084
8104
|
kind: "runtime_diagnostic",
|
|
8085
8105
|
severity: "warning",
|
|
@@ -8087,7 +8107,7 @@ function codexNotificationDiagnosticEvent(message) {
|
|
|
8087
8107
|
itemType: message.method,
|
|
8088
8108
|
message: diagnosticMessage,
|
|
8089
8109
|
...details ? { details } : {},
|
|
8090
|
-
...
|
|
8110
|
+
...path24 ? { path: path24 } : {},
|
|
8091
8111
|
...params.range !== void 0 ? { range: params.range } : {},
|
|
8092
8112
|
payloadBytes: payloadBytes(params),
|
|
8093
8113
|
...sessionId ? { sessionId } : {}
|
|
@@ -9737,11 +9757,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
|
|
|
9737
9757
|
return parseCursorModelsOutput(String(result.stdout || ""));
|
|
9738
9758
|
}
|
|
9739
9759
|
function buildCursorModelProbeEnv(deps = {}) {
|
|
9740
|
-
return
|
|
9760
|
+
return withWindowsUserEnvironment({
|
|
9741
9761
|
...deps.env ?? process.env,
|
|
9742
9762
|
FORCE_COLOR: "0",
|
|
9743
9763
|
NO_COLOR: "1"
|
|
9744
|
-
}, deps)
|
|
9764
|
+
}, deps);
|
|
9745
9765
|
}
|
|
9746
9766
|
function runCursorModelsCommand() {
|
|
9747
9767
|
return spawnSync("cursor-agent", ["models"], {
|
|
@@ -9797,7 +9817,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
|
|
|
9797
9817
|
}
|
|
9798
9818
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
|
|
9799
9819
|
const existsSyncFn = deps.existsSyncFn ?? existsSync5;
|
|
9800
|
-
const env =
|
|
9820
|
+
const env = deps.env ?? process.env;
|
|
9801
9821
|
const winPath = path8.win32;
|
|
9802
9822
|
let geminiEntry = null;
|
|
9803
9823
|
try {
|
|
@@ -9934,15 +9954,12 @@ var GeminiDriver = class {
|
|
|
9934
9954
|
// src/drivers/kimi.ts
|
|
9935
9955
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
9936
9956
|
import { spawn as spawn7 } from "child_process";
|
|
9937
|
-
import {
|
|
9957
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
9938
9958
|
import os4 from "os";
|
|
9939
9959
|
import path9 from "path";
|
|
9940
9960
|
var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
|
|
9941
9961
|
var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
|
|
9942
9962
|
var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
|
|
9943
|
-
var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
|
|
9944
|
-
var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
|
|
9945
|
-
var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
|
|
9946
9963
|
function parseToolArguments(raw) {
|
|
9947
9964
|
if (typeof raw !== "string") return raw;
|
|
9948
9965
|
try {
|
|
@@ -9951,73 +9968,6 @@ function parseToolArguments(raw) {
|
|
|
9951
9968
|
return raw;
|
|
9952
9969
|
}
|
|
9953
9970
|
}
|
|
9954
|
-
function readKimiConfigSource(home = os4.homedir(), env = process.env) {
|
|
9955
|
-
const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
9956
|
-
if (inlineConfig && inlineConfig.trim()) {
|
|
9957
|
-
return {
|
|
9958
|
-
raw: inlineConfig,
|
|
9959
|
-
explicitPath: null,
|
|
9960
|
-
sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
|
|
9961
|
-
};
|
|
9962
|
-
}
|
|
9963
|
-
const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
9964
|
-
const configPath = explicitPath && explicitPath.trim() ? explicitPath : path9.join(home, ".kimi", "config.toml");
|
|
9965
|
-
try {
|
|
9966
|
-
return {
|
|
9967
|
-
raw: readFileSync3(configPath, "utf8"),
|
|
9968
|
-
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
9969
|
-
sourcePath: configPath
|
|
9970
|
-
};
|
|
9971
|
-
} catch {
|
|
9972
|
-
return {
|
|
9973
|
-
raw: null,
|
|
9974
|
-
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
9975
|
-
sourcePath: configPath
|
|
9976
|
-
};
|
|
9977
|
-
}
|
|
9978
|
-
}
|
|
9979
|
-
function buildKimiSpawnEnv(env = process.env) {
|
|
9980
|
-
const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
|
|
9981
|
-
delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
9982
|
-
delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
9983
|
-
return scrubDaemonChildEnv(spawnEnv);
|
|
9984
|
-
}
|
|
9985
|
-
function buildKimiEffectiveEnv(ctx, overrideEnv) {
|
|
9986
|
-
return {
|
|
9987
|
-
...process.env,
|
|
9988
|
-
...ctx.config.envVars || {},
|
|
9989
|
-
...overrideEnv || {}
|
|
9990
|
-
};
|
|
9991
|
-
}
|
|
9992
|
-
function buildKimiLaunchOptions(ctx, opts = {}) {
|
|
9993
|
-
const env = buildKimiEffectiveEnv(ctx, opts.env);
|
|
9994
|
-
const source = readKimiConfigSource(opts.home ?? os4.homedir(), env);
|
|
9995
|
-
const args = [];
|
|
9996
|
-
let configFilePath = null;
|
|
9997
|
-
let configContent = null;
|
|
9998
|
-
if (source.explicitPath) {
|
|
9999
|
-
configFilePath = source.explicitPath;
|
|
10000
|
-
} else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
|
|
10001
|
-
configFilePath = path9.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
|
|
10002
|
-
configContent = source.raw;
|
|
10003
|
-
if (opts.writeGeneratedConfig !== false) {
|
|
10004
|
-
writeFileSync3(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
|
|
10005
|
-
chmodSync(configFilePath, 384);
|
|
10006
|
-
}
|
|
10007
|
-
}
|
|
10008
|
-
if (configFilePath) {
|
|
10009
|
-
args.push("--config-file", configFilePath);
|
|
10010
|
-
}
|
|
10011
|
-
if (ctx.config.model && ctx.config.model !== "default") {
|
|
10012
|
-
args.push("--model", ctx.config.model);
|
|
10013
|
-
}
|
|
10014
|
-
return {
|
|
10015
|
-
args,
|
|
10016
|
-
env: buildKimiSpawnEnv(env),
|
|
10017
|
-
configFilePath,
|
|
10018
|
-
configContent
|
|
10019
|
-
};
|
|
10020
|
-
}
|
|
10021
9971
|
function resolveKimiSpawn(commandArgs, deps = {}) {
|
|
10022
9972
|
return {
|
|
10023
9973
|
command: resolveCommandOnPath("kimi", deps) ?? "kimi",
|
|
@@ -10041,25 +9991,7 @@ var KimiDriver = class {
|
|
|
10041
9991
|
};
|
|
10042
9992
|
model = {
|
|
10043
9993
|
detectedModelsVerifiedAs: "launchable",
|
|
10044
|
-
toLaunchSpec: (modelId
|
|
10045
|
-
if (!ctx) return { args: ["--model", modelId] };
|
|
10046
|
-
const launchCtx = {
|
|
10047
|
-
...ctx,
|
|
10048
|
-
config: {
|
|
10049
|
-
...ctx.config,
|
|
10050
|
-
model: modelId
|
|
10051
|
-
}
|
|
10052
|
-
};
|
|
10053
|
-
const launch = buildKimiLaunchOptions(launchCtx, {
|
|
10054
|
-
home: opts?.home,
|
|
10055
|
-
writeGeneratedConfig: false
|
|
10056
|
-
});
|
|
10057
|
-
return {
|
|
10058
|
-
args: launch.args,
|
|
10059
|
-
env: launch.env,
|
|
10060
|
-
configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
|
|
10061
|
-
};
|
|
10062
|
-
}
|
|
9994
|
+
toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
|
|
10063
9995
|
};
|
|
10064
9996
|
supportsStdinNotification = true;
|
|
10065
9997
|
busyDeliveryMode = "direct";
|
|
@@ -10083,23 +10015,21 @@ var KimiDriver = class {
|
|
|
10083
10015
|
` system_prompt_path: ./${KIMI_SYSTEM_PROMPT_FILE}`,
|
|
10084
10016
|
""
|
|
10085
10017
|
].join("\n"), "utf8");
|
|
10086
|
-
const launch = buildKimiLaunchOptions(ctx);
|
|
10087
10018
|
const args = [
|
|
10088
10019
|
"--wire",
|
|
10089
10020
|
"--yolo",
|
|
10090
10021
|
"--agent-file",
|
|
10091
10022
|
agentFilePath,
|
|
10092
10023
|
"--session",
|
|
10093
|
-
this.sessionId
|
|
10094
|
-
...launch.args
|
|
10024
|
+
this.sessionId
|
|
10095
10025
|
];
|
|
10096
10026
|
const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config));
|
|
10097
10027
|
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
10098
10028
|
args.push("--model", launchRuntimeFields.model);
|
|
10099
10029
|
}
|
|
10100
10030
|
const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
10101
|
-
const
|
|
10102
|
-
const proc = spawn7(
|
|
10031
|
+
const launch = resolveKimiSpawn(args);
|
|
10032
|
+
const proc = spawn7(launch.command, launch.args, {
|
|
10103
10033
|
cwd: ctx.workingDirectory,
|
|
10104
10034
|
stdio: ["pipe", "pipe", "pipe"],
|
|
10105
10035
|
env: spawnEnv,
|
|
@@ -10107,7 +10037,7 @@ var KimiDriver = class {
|
|
|
10107
10037
|
// and has an 8191-character command-line limit. Kimi's official
|
|
10108
10038
|
// installer/uv entrypoint is an executable, so launch it directly and
|
|
10109
10039
|
// keep prompts on stdin / files instead of routing through cmd.exe.
|
|
10110
|
-
shell:
|
|
10040
|
+
shell: launch.shell
|
|
10111
10041
|
});
|
|
10112
10042
|
proc.stdin?.write(JSON.stringify({
|
|
10113
10043
|
jsonrpc: "2.0",
|
|
@@ -10220,9 +10150,14 @@ var KimiDriver = class {
|
|
|
10220
10150
|
return detectKimiModels();
|
|
10221
10151
|
}
|
|
10222
10152
|
};
|
|
10223
|
-
function detectKimiModels(home = os4.homedir()
|
|
10224
|
-
const
|
|
10225
|
-
|
|
10153
|
+
function detectKimiModels(home = os4.homedir()) {
|
|
10154
|
+
const configPath = path9.join(home, ".kimi", "config.toml");
|
|
10155
|
+
let raw;
|
|
10156
|
+
try {
|
|
10157
|
+
raw = readFileSync3(configPath, "utf8");
|
|
10158
|
+
} catch {
|
|
10159
|
+
return null;
|
|
10160
|
+
}
|
|
10226
10161
|
const models = [];
|
|
10227
10162
|
const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
|
|
10228
10163
|
const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
|
|
@@ -10901,7 +10836,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
10901
10836
|
const platform = deps.platform ?? process.platform;
|
|
10902
10837
|
const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
|
|
10903
10838
|
const result = spawnSyncFn("opencode", ["models"], {
|
|
10904
|
-
env:
|
|
10839
|
+
env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
|
|
10905
10840
|
encoding: "utf8",
|
|
10906
10841
|
timeout: 5e3,
|
|
10907
10842
|
shell: platform === "win32"
|
|
@@ -11527,10 +11462,8 @@ function mapPiSdkEventToParsedEvents(event, state) {
|
|
|
11527
11462
|
case "agent_end":
|
|
11528
11463
|
events.push({ kind: "turn_end", sessionId: state.sessionId || void 0 });
|
|
11529
11464
|
return events;
|
|
11530
|
-
default:
|
|
11531
|
-
|
|
11532
|
-
return _exhaustive;
|
|
11533
|
-
}
|
|
11465
|
+
default:
|
|
11466
|
+
return events;
|
|
11534
11467
|
}
|
|
11535
11468
|
}
|
|
11536
11469
|
var PI_RUNTIME_SESSION_DESCRIPTOR = {
|
|
@@ -11715,15 +11648,21 @@ async function createPiAgentSessionForContext(ctx, sessionId, opts = {}) {
|
|
|
11715
11648
|
}
|
|
11716
11649
|
}
|
|
11717
11650
|
var PiSdkRuntimeSession = class {
|
|
11718
|
-
constructor(ctx, setCurrentSessionId, sessionFactory = createPiAgentSessionForContext) {
|
|
11651
|
+
constructor(ctx, setCurrentSessionId, sessionFactory = createPiAgentSessionForContext, opts = {}) {
|
|
11719
11652
|
this.ctx = ctx;
|
|
11720
11653
|
this.setCurrentSessionId = setCurrentSessionId;
|
|
11721
11654
|
this.sessionFactory = sessionFactory;
|
|
11722
11655
|
this.mappingState = createPiSdkEventMappingState(ctx.config.sessionId || null);
|
|
11656
|
+
const runtimeConfig = hydrateRuntimeConfig(ctx.config);
|
|
11657
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(runtimeConfig);
|
|
11658
|
+
this.sdkCallEnvPatch = buildPiSessionCreateEnvPatch(runtimeConfig, launchRuntimeFields.envVars);
|
|
11659
|
+
this.sdkCallEnvRemoveFirst = opts.isolateHostProviderEnv ? BUILTIN_BLOCKED_HOST_PROVIDER_ENV_KEYS : void 0;
|
|
11723
11660
|
}
|
|
11724
11661
|
descriptor = PI_RUNTIME_SESSION_DESCRIPTOR;
|
|
11725
11662
|
events = new EventEmitter2();
|
|
11726
11663
|
mappingState;
|
|
11664
|
+
sdkCallEnvPatch;
|
|
11665
|
+
sdkCallEnvRemoveFirst;
|
|
11727
11666
|
session = null;
|
|
11728
11667
|
unsubscribe = null;
|
|
11729
11668
|
started = false;
|
|
@@ -11853,7 +11792,7 @@ var PiSdkRuntimeSession = class {
|
|
|
11853
11792
|
setImmediate(() => {
|
|
11854
11793
|
if (this.didClose) return;
|
|
11855
11794
|
try {
|
|
11856
|
-
void invoke
|
|
11795
|
+
void withProcessEnvPatch(this.sdkCallEnvPatch, invoke, { removeFirst: this.sdkCallEnvRemoveFirst }).catch((error) => {
|
|
11857
11796
|
if (this.didClose) return;
|
|
11858
11797
|
this.events.emit("runtime_event", {
|
|
11859
11798
|
kind: "error",
|
|
@@ -11986,7 +11925,7 @@ var BuiltInDriver = class extends PiDriver {
|
|
|
11986
11925
|
exposeLaunchTraceEvidence: true,
|
|
11987
11926
|
exposeLaunchEnvToTools: false,
|
|
11988
11927
|
isolateHostProviderEnv: true
|
|
11989
|
-
}));
|
|
11928
|
+
}), { isolateHostProviderEnv: true });
|
|
11990
11929
|
}
|
|
11991
11930
|
buildSystemPrompt(config, _agentId) {
|
|
11992
11931
|
return buildCliTransportSystemPrompt(config, {
|
|
@@ -22708,6 +22647,11 @@ function onceDrain(res) {
|
|
|
22708
22647
|
return new Promise((resolve) => res.once("drain", resolve));
|
|
22709
22648
|
}
|
|
22710
22649
|
|
|
22650
|
+
// src/agentMigrationObjectStoreBundle.ts
|
|
22651
|
+
import { createHash as createHash9 } from "crypto";
|
|
22652
|
+
import { lstat as lstat3, mkdir as mkdir3, readFile as readFile4, readlink as readlink2, rm as rm3, symlink, writeFile as writeFile3 } from "fs/promises";
|
|
22653
|
+
import path20 from "path";
|
|
22654
|
+
|
|
22711
22655
|
// src/agentMigrationExport.ts
|
|
22712
22656
|
import { createHash as createHash8 } from "crypto";
|
|
22713
22657
|
import { createReadStream } from "fs";
|
|
@@ -23029,19 +22973,142 @@ function sortByPath(entries) {
|
|
|
23029
22973
|
return [...entries].sort((a, b) => a.path.localeCompare(b.path));
|
|
23030
22974
|
}
|
|
23031
22975
|
|
|
22976
|
+
// src/agentMigrationObjectStoreBundle.ts
|
|
22977
|
+
var AGENT_MIGRATION_OBJECT_STORE_BUNDLE_SCHEMA_VERSION = "agent-object-store-bundle/v1";
|
|
22978
|
+
var AGENT_MIGRATION_OBJECT_STORE_CONTENT_TYPE = "application/vnd.slock.agent-migration-bundle";
|
|
22979
|
+
async function buildAgentMigrationObjectStoreBundle(input) {
|
|
22980
|
+
const workspacePath = path20.resolve(input.workspacePath);
|
|
22981
|
+
const manifest = await buildAgentMigrationExportManifest({
|
|
22982
|
+
agentId: input.agentId,
|
|
22983
|
+
slockHome: input.slockHome,
|
|
22984
|
+
workspacePath,
|
|
22985
|
+
mode: "forensic"
|
|
22986
|
+
});
|
|
22987
|
+
const files = [];
|
|
22988
|
+
for (const entry of manifest.files) {
|
|
22989
|
+
if (entry.source !== "workspace" || !entry.workspaceRelativePath) {
|
|
22990
|
+
throw new Error("MIGRATION_OBJECT_STORE_UNSUPPORTED_ENTRY");
|
|
22991
|
+
}
|
|
22992
|
+
const sourcePath = path20.resolve(entry.sourcePath);
|
|
22993
|
+
if (entry.kind === "symlink") {
|
|
22994
|
+
files.push({
|
|
22995
|
+
kind: "symlink",
|
|
22996
|
+
workspaceRelativePath: normalizeWorkspaceRelativePath(entry.workspaceRelativePath),
|
|
22997
|
+
linkTarget: entry.linkTarget ?? await readlink2(sourcePath)
|
|
22998
|
+
});
|
|
22999
|
+
continue;
|
|
23000
|
+
}
|
|
23001
|
+
const stat4 = await lstat3(sourcePath);
|
|
23002
|
+
if (!stat4.isFile()) throw new Error("MIGRATION_OBJECT_STORE_FILE_KIND_MISMATCH");
|
|
23003
|
+
files.push({
|
|
23004
|
+
kind: "file",
|
|
23005
|
+
workspaceRelativePath: normalizeWorkspaceRelativePath(entry.workspaceRelativePath),
|
|
23006
|
+
contentBase64: (await readFile4(sourcePath)).toString("base64")
|
|
23007
|
+
});
|
|
23008
|
+
}
|
|
23009
|
+
const payload = {
|
|
23010
|
+
schemaVersion: AGENT_MIGRATION_OBJECT_STORE_BUNDLE_SCHEMA_VERSION,
|
|
23011
|
+
manifest,
|
|
23012
|
+
files
|
|
23013
|
+
};
|
|
23014
|
+
const bundle = Buffer.from(`${JSON.stringify(sortJsonValue2(payload))}
|
|
23015
|
+
`, "utf8");
|
|
23016
|
+
if (!Number.isSafeInteger(input.maxBytes) || input.maxBytes <= 0 || bundle.byteLength > input.maxBytes) {
|
|
23017
|
+
throw new Error("MIGRATION_OBJECT_STORE_BUNDLE_TOO_LARGE");
|
|
23018
|
+
}
|
|
23019
|
+
return {
|
|
23020
|
+
bundle,
|
|
23021
|
+
manifestSha256: sha256Buffer2(Buffer.from(canonicalJson2(manifest), "utf8"))
|
|
23022
|
+
};
|
|
23023
|
+
}
|
|
23024
|
+
async function stageAgentMigrationObjectStoreBundle(input) {
|
|
23025
|
+
const parsed = parseObjectStoreBundle(input.bundle);
|
|
23026
|
+
const stagingWorkspacePath = path20.join(
|
|
23027
|
+
path20.resolve(input.slockHome),
|
|
23028
|
+
"migrations",
|
|
23029
|
+
sanitizePathSegment(input.sessionId),
|
|
23030
|
+
"workspace"
|
|
23031
|
+
);
|
|
23032
|
+
await rm3(stagingWorkspacePath, { recursive: true, force: true });
|
|
23033
|
+
await mkdir3(stagingWorkspacePath, { recursive: true });
|
|
23034
|
+
for (const file of parsed.files) {
|
|
23035
|
+
const relativePath = normalizeWorkspaceRelativePath(file.workspaceRelativePath);
|
|
23036
|
+
const targetPath = path20.join(stagingWorkspacePath, relativePath);
|
|
23037
|
+
await mkdir3(path20.dirname(targetPath), { recursive: true });
|
|
23038
|
+
if (file.kind === "symlink") {
|
|
23039
|
+
if (!file.linkTarget) throw new Error("MIGRATION_OBJECT_STORE_LINK_TARGET_MISSING");
|
|
23040
|
+
await symlink(file.linkTarget, targetPath);
|
|
23041
|
+
continue;
|
|
23042
|
+
}
|
|
23043
|
+
if (file.kind !== "file" || typeof file.contentBase64 !== "string") {
|
|
23044
|
+
throw new Error("MIGRATION_OBJECT_STORE_FILE_CONTENT_MISSING");
|
|
23045
|
+
}
|
|
23046
|
+
await writeFile3(targetPath, Buffer.from(file.contentBase64, "base64"), { mode: 384 });
|
|
23047
|
+
}
|
|
23048
|
+
return {
|
|
23049
|
+
manifest: parsed.manifest,
|
|
23050
|
+
manifestSha256: sha256Buffer2(Buffer.from(canonicalJson2(parsed.manifest), "utf8")),
|
|
23051
|
+
stagingWorkspacePath
|
|
23052
|
+
};
|
|
23053
|
+
}
|
|
23054
|
+
function parseObjectStoreBundle(buffer) {
|
|
23055
|
+
let parsed;
|
|
23056
|
+
try {
|
|
23057
|
+
parsed = JSON.parse(buffer.toString("utf8"));
|
|
23058
|
+
} catch {
|
|
23059
|
+
throw new Error("MIGRATION_OBJECT_STORE_BUNDLE_INVALID_JSON");
|
|
23060
|
+
}
|
|
23061
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
23062
|
+
throw new Error("MIGRATION_OBJECT_STORE_BUNDLE_INVALID");
|
|
23063
|
+
}
|
|
23064
|
+
const bundle = parsed;
|
|
23065
|
+
if (bundle.schemaVersion !== AGENT_MIGRATION_OBJECT_STORE_BUNDLE_SCHEMA_VERSION) {
|
|
23066
|
+
throw new Error("MIGRATION_OBJECT_STORE_BUNDLE_SCHEMA_UNSUPPORTED");
|
|
23067
|
+
}
|
|
23068
|
+
if (!bundle.manifest || typeof bundle.manifest !== "object" || Array.isArray(bundle.manifest)) {
|
|
23069
|
+
throw new Error("MIGRATION_OBJECT_STORE_MANIFEST_MISSING");
|
|
23070
|
+
}
|
|
23071
|
+
if (!Array.isArray(bundle.files)) throw new Error("MIGRATION_OBJECT_STORE_FILES_MISSING");
|
|
23072
|
+
return bundle;
|
|
23073
|
+
}
|
|
23074
|
+
function normalizeWorkspaceRelativePath(relativePath) {
|
|
23075
|
+
const normalized = path20.posix.normalize(relativePath.replaceAll("\\", "/"));
|
|
23076
|
+
if (normalized === "." || normalized.startsWith("../") || normalized === ".." || path20.isAbsolute(normalized)) {
|
|
23077
|
+
throw new Error("MIGRATION_OBJECT_STORE_UNSAFE_PATH");
|
|
23078
|
+
}
|
|
23079
|
+
return normalized;
|
|
23080
|
+
}
|
|
23081
|
+
function canonicalJson2(value) {
|
|
23082
|
+
return JSON.stringify(sortJsonValue2(value));
|
|
23083
|
+
}
|
|
23084
|
+
function sortJsonValue2(value) {
|
|
23085
|
+
if (Array.isArray(value)) return value.map(sortJsonValue2);
|
|
23086
|
+
if (!value || typeof value !== "object") return value;
|
|
23087
|
+
return Object.keys(value).sort().reduce((result, key) => {
|
|
23088
|
+
result[key] = sortJsonValue2(value[key]);
|
|
23089
|
+
return result;
|
|
23090
|
+
}, {});
|
|
23091
|
+
}
|
|
23092
|
+
function sha256Buffer2(buffer) {
|
|
23093
|
+
return createHash9("sha256").update(buffer).digest("hex");
|
|
23094
|
+
}
|
|
23095
|
+
function sanitizePathSegment(value) {
|
|
23096
|
+
return value.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 128) || "migration";
|
|
23097
|
+
}
|
|
23098
|
+
|
|
23032
23099
|
// src/agentMigrationImport.ts
|
|
23033
|
-
import { createHash as
|
|
23100
|
+
import { createHash as createHash10 } from "crypto";
|
|
23034
23101
|
import { createReadStream as createReadStream2 } from "fs";
|
|
23035
|
-
import { access as access2, cp, lstat as
|
|
23036
|
-
import
|
|
23102
|
+
import { access as access2, cp, lstat as lstat4, mkdir as mkdir4, readlink as readlink3, rename, writeFile as writeFile4 } from "fs/promises";
|
|
23103
|
+
import path21 from "path";
|
|
23037
23104
|
async function buildAgentMigrationAdoptPlan(input) {
|
|
23038
|
-
const slockHome =
|
|
23105
|
+
const slockHome = path21.resolve(input.slockHome);
|
|
23039
23106
|
let manifest;
|
|
23040
23107
|
if (input.sourceKind === "orphan_directory" && !input.manifest) {
|
|
23041
23108
|
manifest = await buildAgentMigrationExportManifest({
|
|
23042
23109
|
agentId: input.agentId,
|
|
23043
23110
|
slockHome,
|
|
23044
|
-
workspacePath:
|
|
23111
|
+
workspacePath: path21.resolve(input.orphanWorkspacePath),
|
|
23045
23112
|
mode: "forensic",
|
|
23046
23113
|
now: input.now
|
|
23047
23114
|
});
|
|
@@ -23054,14 +23121,14 @@ async function buildAgentMigrationAdoptPlan(input) {
|
|
|
23054
23121
|
manifest,
|
|
23055
23122
|
expectedAgentId: input.sourceKind === "orphan_directory" ? input.agentId : manifest.agentId
|
|
23056
23123
|
});
|
|
23057
|
-
const sourceWorkspacePath =
|
|
23124
|
+
const sourceWorkspacePath = path21.resolve(
|
|
23058
23125
|
input.sourceKind === "staged_bundle" ? input.stagingWorkspacePath : input.orphanWorkspacePath
|
|
23059
23126
|
);
|
|
23060
|
-
const finalWorkspacePath =
|
|
23061
|
-
const reportPath =
|
|
23127
|
+
const finalWorkspacePath = path21.resolve(input.finalWorkspacePath ?? path21.join(slockHome, "agents", manifest.agentId));
|
|
23128
|
+
const reportPath = path21.resolve(input.reportPath ?? path21.join(
|
|
23062
23129
|
slockHome,
|
|
23063
23130
|
"migrations",
|
|
23064
|
-
|
|
23131
|
+
sanitizePathSegment2(input.generation.grantKey),
|
|
23065
23132
|
"arrival-report.json"
|
|
23066
23133
|
));
|
|
23067
23134
|
const manifestSha256 = hashAgentMigrationManifest(manifest);
|
|
@@ -23141,7 +23208,7 @@ async function executeAgentMigrationAdoptPlan(plan, rebind, now = currentDate())
|
|
|
23141
23208
|
return { report, reportPath: plan.reportPath, reportSha256 };
|
|
23142
23209
|
}
|
|
23143
23210
|
function hashAgentMigrationManifest(manifest) {
|
|
23144
|
-
return
|
|
23211
|
+
return sha256Buffer3(Buffer.from(canonicalJson3(manifest), "utf8"));
|
|
23145
23212
|
}
|
|
23146
23213
|
function assertManifestIdentity(input) {
|
|
23147
23214
|
if (input.manifest.schemaVersion !== AGENT_MIGRATION_BUNDLE_SCHEMA_VERSION) {
|
|
@@ -23182,13 +23249,13 @@ async function verifyManifestFileEntry(sourceWorkspacePath, entry) {
|
|
|
23182
23249
|
if (entry.source !== "workspace" || !entry.workspaceRelativePath) {
|
|
23183
23250
|
throw new Error("MIGRATION_MANIFEST_ENTRY_NOT_WORKSPACE");
|
|
23184
23251
|
}
|
|
23185
|
-
const relative =
|
|
23186
|
-
const entryPath =
|
|
23187
|
-
const info = await
|
|
23252
|
+
const relative = normalizeWorkspaceRelativePath2(entry.workspaceRelativePath);
|
|
23253
|
+
const entryPath = path21.join(sourceWorkspacePath, relative);
|
|
23254
|
+
const info = await lstat4(entryPath).catch(() => null);
|
|
23188
23255
|
if (!info) throw new Error("MIGRATION_MANIFEST_FILE_MISSING");
|
|
23189
23256
|
if (entry.kind === "symlink") {
|
|
23190
23257
|
if (!info.isSymbolicLink()) throw new Error("MIGRATION_MANIFEST_KIND_MISMATCH");
|
|
23191
|
-
const linkTarget = await
|
|
23258
|
+
const linkTarget = await readlink3(entryPath);
|
|
23192
23259
|
if (entry.linkTarget !== linkTarget) throw new Error("MIGRATION_MANIFEST_LINK_MISMATCH");
|
|
23193
23260
|
return;
|
|
23194
23261
|
}
|
|
@@ -23201,15 +23268,15 @@ async function verifyManifestFileEntry(sourceWorkspacePath, entry) {
|
|
|
23201
23268
|
if (actual !== entry.sha256) throw new Error("MIGRATION_MANIFEST_FILE_SHA_MISMATCH");
|
|
23202
23269
|
}
|
|
23203
23270
|
}
|
|
23204
|
-
function
|
|
23205
|
-
const normalized =
|
|
23206
|
-
if (normalized === "." || normalized.startsWith("../") || normalized === ".." ||
|
|
23271
|
+
function normalizeWorkspaceRelativePath2(relativePath) {
|
|
23272
|
+
const normalized = path21.posix.normalize(relativePath.replaceAll("\\", "/"));
|
|
23273
|
+
if (normalized === "." || normalized.startsWith("../") || normalized === ".." || path21.isAbsolute(normalized)) {
|
|
23207
23274
|
throw new Error("MIGRATION_MANIFEST_UNSAFE_PATH");
|
|
23208
23275
|
}
|
|
23209
23276
|
return normalized;
|
|
23210
23277
|
}
|
|
23211
23278
|
async function assertFinalWorkspaceAvailable(sourceWorkspacePath, finalWorkspacePath) {
|
|
23212
|
-
if (
|
|
23279
|
+
if (path21.resolve(sourceWorkspacePath) === path21.resolve(finalWorkspacePath)) return;
|
|
23213
23280
|
try {
|
|
23214
23281
|
await access2(finalWorkspacePath);
|
|
23215
23282
|
throw new Error("MIGRATION_WORKSPACE_ALREADY_EXISTS");
|
|
@@ -23218,48 +23285,48 @@ async function assertFinalWorkspaceAvailable(sourceWorkspacePath, finalWorkspace
|
|
|
23218
23285
|
}
|
|
23219
23286
|
}
|
|
23220
23287
|
async function placeWorkspace(sourceWorkspacePath, finalWorkspacePath) {
|
|
23221
|
-
if (
|
|
23288
|
+
if (path21.resolve(sourceWorkspacePath) === path21.resolve(finalWorkspacePath)) return;
|
|
23222
23289
|
const stagingPath = `${finalWorkspacePath}.migration-${process.pid}-${Date.now()}`;
|
|
23223
|
-
await
|
|
23290
|
+
await mkdir4(path21.dirname(finalWorkspacePath), { recursive: true });
|
|
23224
23291
|
await cp(sourceWorkspacePath, stagingPath, { recursive: true, dereference: false, errorOnExist: true, force: false });
|
|
23225
23292
|
await rename(stagingPath, finalWorkspacePath);
|
|
23226
23293
|
}
|
|
23227
23294
|
async function writeArrivalReport(reportPath, report) {
|
|
23228
|
-
const payload = `${
|
|
23295
|
+
const payload = `${canonicalJson3(report)}
|
|
23229
23296
|
`;
|
|
23230
|
-
await
|
|
23231
|
-
await
|
|
23232
|
-
return
|
|
23297
|
+
await mkdir4(path21.dirname(reportPath), { recursive: true });
|
|
23298
|
+
await writeFile4(reportPath, payload, { mode: 384 });
|
|
23299
|
+
return sha256Buffer3(Buffer.from(payload, "utf8"));
|
|
23233
23300
|
}
|
|
23234
23301
|
async function sha256File2(filePath) {
|
|
23235
|
-
const hash =
|
|
23302
|
+
const hash = createHash10("sha256");
|
|
23236
23303
|
const stream = createReadStream2(filePath);
|
|
23237
23304
|
for await (const chunk of stream) {
|
|
23238
23305
|
hash.update(chunk);
|
|
23239
23306
|
}
|
|
23240
23307
|
return hash.digest("hex");
|
|
23241
23308
|
}
|
|
23242
|
-
function
|
|
23243
|
-
return
|
|
23309
|
+
function sha256Buffer3(buffer) {
|
|
23310
|
+
return createHash10("sha256").update(buffer).digest("hex");
|
|
23244
23311
|
}
|
|
23245
|
-
function
|
|
23246
|
-
return JSON.stringify(
|
|
23312
|
+
function canonicalJson3(value) {
|
|
23313
|
+
return JSON.stringify(sortJsonValue3(value));
|
|
23247
23314
|
}
|
|
23248
|
-
function
|
|
23249
|
-
if (Array.isArray(value)) return value.map(
|
|
23315
|
+
function sortJsonValue3(value) {
|
|
23316
|
+
if (Array.isArray(value)) return value.map(sortJsonValue3);
|
|
23250
23317
|
if (!value || typeof value !== "object") return value;
|
|
23251
23318
|
return Object.keys(value).sort().reduce((result, key) => {
|
|
23252
|
-
result[key] =
|
|
23319
|
+
result[key] = sortJsonValue3(value[key]);
|
|
23253
23320
|
return result;
|
|
23254
23321
|
}, {});
|
|
23255
23322
|
}
|
|
23256
|
-
function
|
|
23323
|
+
function sanitizePathSegment2(value) {
|
|
23257
23324
|
return value.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 128) || "migration";
|
|
23258
23325
|
}
|
|
23259
23326
|
|
|
23260
23327
|
// src/secretFile.ts
|
|
23261
|
-
import { chmodSync
|
|
23262
|
-
import
|
|
23328
|
+
import { chmodSync, mkdirSync as mkdirSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
23329
|
+
import path22 from "path";
|
|
23263
23330
|
function readSecretFileSync(filePath) {
|
|
23264
23331
|
return readFileSync9(filePath, "utf8").trim();
|
|
23265
23332
|
}
|
|
@@ -23269,6 +23336,8 @@ var DEFAULT_TRACE_UPLOAD_URL = "https://slock-trace-upload.botiverse.dev";
|
|
|
23269
23336
|
var RUNNER_CREDENTIAL_SCOPES = ["send", "read", "mentions", "tasks", "reactions", "server", "channels", "knowledge"];
|
|
23270
23337
|
var RUNNER_CREDENTIAL_MINT_MAX_ATTEMPTS2 = 3;
|
|
23271
23338
|
var RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2 = 250;
|
|
23339
|
+
var MIGRATION_OBJECT_STORE_DOWNLOAD_RETRY_INITIAL_MS = 25;
|
|
23340
|
+
var MIGRATION_OBJECT_STORE_DOWNLOAD_RETRY_MAX_MS = 250;
|
|
23272
23341
|
var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
|
|
23273
23342
|
"daemon.lifecycle.start": {
|
|
23274
23343
|
spanAttrs: ["machine_dir_present", "local_trace_enabled"],
|
|
@@ -23423,8 +23492,27 @@ function runnerCredentialErrorDetail2(error) {
|
|
|
23423
23492
|
retryable: true
|
|
23424
23493
|
};
|
|
23425
23494
|
}
|
|
23495
|
+
async function waitForAmbientBackoff(delayMs) {
|
|
23496
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
23497
|
+
}
|
|
23426
23498
|
async function waitForRunnerCredentialRetry2() {
|
|
23427
|
-
await
|
|
23499
|
+
await waitForAmbientBackoff(RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2);
|
|
23500
|
+
}
|
|
23501
|
+
function isRetryableMigrationObjectStoreDownloadStatus(status) {
|
|
23502
|
+
return status === 404 || status === 408 || status === 409 || status === 425 || status === 429 || status >= 500;
|
|
23503
|
+
}
|
|
23504
|
+
function migrationTransferFailureMessage(err) {
|
|
23505
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
23506
|
+
return message.slice(0, 500);
|
|
23507
|
+
}
|
|
23508
|
+
async function migrationStepErrorSuffix(response) {
|
|
23509
|
+
try {
|
|
23510
|
+
const body = await response.clone().json();
|
|
23511
|
+
if (typeof body.code === "string" && body.code.length > 0) return body.code.slice(0, 120);
|
|
23512
|
+
if (typeof body.error === "string" && body.error.length > 0) return body.error.slice(0, 120);
|
|
23513
|
+
} catch {
|
|
23514
|
+
}
|
|
23515
|
+
return response.statusText || "unknown";
|
|
23428
23516
|
}
|
|
23429
23517
|
function parseDaemonCliArgs(args) {
|
|
23430
23518
|
let serverUrl = "";
|
|
@@ -23454,13 +23542,13 @@ function readDaemonVersion(moduleUrl = import.meta.url) {
|
|
|
23454
23542
|
}
|
|
23455
23543
|
}
|
|
23456
23544
|
function resolveSlockCliPath(moduleUrl = import.meta.url) {
|
|
23457
|
-
const thisDir =
|
|
23458
|
-
const bundledDistPath =
|
|
23545
|
+
const thisDir = path23.dirname(fileURLToPath(moduleUrl));
|
|
23546
|
+
const bundledDistPath = path23.resolve(thisDir, "cli", "index.js");
|
|
23459
23547
|
try {
|
|
23460
23548
|
accessSync(bundledDistPath);
|
|
23461
23549
|
return bundledDistPath;
|
|
23462
23550
|
} catch {
|
|
23463
|
-
const workspaceDistPath =
|
|
23551
|
+
const workspaceDistPath = path23.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
|
|
23464
23552
|
accessSync(workspaceDistPath);
|
|
23465
23553
|
return workspaceDistPath;
|
|
23466
23554
|
}
|
|
@@ -23474,7 +23562,7 @@ function resolveSlockCliPathOrEmpty(moduleUrl = import.meta.url) {
|
|
|
23474
23562
|
}
|
|
23475
23563
|
async function runBundledSlockCli(argv) {
|
|
23476
23564
|
process.argv = [process.execPath, "slock", ...argv];
|
|
23477
|
-
await import("./dist-
|
|
23565
|
+
await import("./dist-VNC64ECP.js");
|
|
23478
23566
|
}
|
|
23479
23567
|
function detectRuntimes(tracer = noopTracer) {
|
|
23480
23568
|
const ids = [];
|
|
@@ -23606,6 +23694,8 @@ function summarizeIncomingMessage(msg) {
|
|
|
23606
23694
|
return `(directory=${msg.directoryName})`;
|
|
23607
23695
|
case "machine:runtime_models:detect":
|
|
23608
23696
|
return `(runtime=${msg.runtime}, req=${msg.requestId})`;
|
|
23697
|
+
case "machine:migration_transport:lease":
|
|
23698
|
+
return `(agent=${msg.agentId}, migration=${msg.migrationId}, session=${msg.sessionId}, provider=${msg.provider}, role=${msg.role}, kind=${msg.transferKind}, url=${msg.url ? "set" : "missing"})`;
|
|
23609
23699
|
case "reminder.upsert":
|
|
23610
23700
|
return `(agent=${msg.agentId}, id=${msg.reminder.reminderId}, v${msg.reminder.version}, fireAt=${msg.reminder.fireAt})`;
|
|
23611
23701
|
case "reminder.cancel":
|
|
@@ -23638,6 +23728,9 @@ var DaemonCore = class {
|
|
|
23638
23728
|
migrationTransport;
|
|
23639
23729
|
migrationTransportListenPromise = null;
|
|
23640
23730
|
migrationTransportListening = false;
|
|
23731
|
+
migrationTransportUrl = null;
|
|
23732
|
+
migrationTransferLease = null;
|
|
23733
|
+
migrationTransferRuns = /* @__PURE__ */ new Set();
|
|
23641
23734
|
tracer;
|
|
23642
23735
|
injectedTracer;
|
|
23643
23736
|
machineLock = null;
|
|
@@ -23692,7 +23785,7 @@ var DaemonCore = class {
|
|
|
23692
23785
|
}
|
|
23693
23786
|
resolveMachineStateRoot() {
|
|
23694
23787
|
if (this.options.machineStateDir) return this.options.machineStateDir;
|
|
23695
|
-
if (this.options.dataDir) return
|
|
23788
|
+
if (this.options.dataDir) return path23.join(path23.dirname(this.options.dataDir), "machines");
|
|
23696
23789
|
return resolveDefaultMachineStateRoot();
|
|
23697
23790
|
}
|
|
23698
23791
|
shouldEnableLocalTrace() {
|
|
@@ -23720,7 +23813,7 @@ var DaemonCore = class {
|
|
|
23720
23813
|
sinks: [this.localTraceSink]
|
|
23721
23814
|
}));
|
|
23722
23815
|
this.agentManager.setTracer(this.tracer);
|
|
23723
|
-
this.agentManager.setCliTransportTraceDir(
|
|
23816
|
+
this.agentManager.setCliTransportTraceDir(path23.join(machineDir, "traces"));
|
|
23724
23817
|
}
|
|
23725
23818
|
installTraceBundleUploader(machineDir) {
|
|
23726
23819
|
if (!this.shouldEnableLocalTrace()) return;
|
|
@@ -23770,7 +23863,9 @@ var DaemonCore = class {
|
|
|
23770
23863
|
span.addEvent("daemon.machine_lock.acquired", { machine_dir_present: true });
|
|
23771
23864
|
span.end("ok");
|
|
23772
23865
|
}
|
|
23773
|
-
this.
|
|
23866
|
+
if (this.migrationTransport) {
|
|
23867
|
+
this.startMigrationTransport();
|
|
23868
|
+
}
|
|
23774
23869
|
try {
|
|
23775
23870
|
this.connection.connect();
|
|
23776
23871
|
} catch (err) {
|
|
@@ -23839,10 +23934,35 @@ var DaemonCore = class {
|
|
|
23839
23934
|
});
|
|
23840
23935
|
span.end(status);
|
|
23841
23936
|
}
|
|
23937
|
+
getMigrationTransportReady() {
|
|
23938
|
+
const transferLease = this.getActiveMigrationTransferLease();
|
|
23939
|
+
if (transferLease) {
|
|
23940
|
+
return {
|
|
23941
|
+
provisioned: true,
|
|
23942
|
+
endpoint: transferLease.url,
|
|
23943
|
+
leaseSource: "server",
|
|
23944
|
+
provider: transferLease.provider,
|
|
23945
|
+
role: transferLease.role,
|
|
23946
|
+
transferKind: transferLease.transferKind,
|
|
23947
|
+
url: transferLease.url,
|
|
23948
|
+
expiresAt: transferLease.expiresAt,
|
|
23949
|
+
maxBytes: transferLease.maxBytes,
|
|
23950
|
+
observedAt: currentDate().toISOString()
|
|
23951
|
+
};
|
|
23952
|
+
}
|
|
23953
|
+
const endpoint = this.migrationTransportListening ? this.migrationTransportUrl : null;
|
|
23954
|
+
return {
|
|
23955
|
+
provisioned: Boolean(endpoint),
|
|
23956
|
+
endpoint,
|
|
23957
|
+
leaseSource: endpoint ? "env" : null,
|
|
23958
|
+
observedAt: currentDate().toISOString()
|
|
23959
|
+
};
|
|
23960
|
+
}
|
|
23842
23961
|
startMigrationTransport() {
|
|
23843
23962
|
if (!this.migrationTransport || this.migrationTransportListenPromise) return;
|
|
23844
23963
|
this.migrationTransportListenPromise = this.migrationTransport.listen().then(({ url }) => {
|
|
23845
23964
|
this.migrationTransportListening = true;
|
|
23965
|
+
this.migrationTransportUrl = url;
|
|
23846
23966
|
logger.info(`[Slock Daemon] Agent migration HTTP transport listening: ${url}`);
|
|
23847
23967
|
this.recordDaemonTrace("daemon.migration_transport.listen", {
|
|
23848
23968
|
outcome: "listening",
|
|
@@ -23850,6 +23970,7 @@ var DaemonCore = class {
|
|
|
23850
23970
|
});
|
|
23851
23971
|
}).catch((err) => {
|
|
23852
23972
|
this.migrationTransportListening = false;
|
|
23973
|
+
this.migrationTransportUrl = null;
|
|
23853
23974
|
logger.error("[Slock Daemon] Agent migration HTTP transport failed to listen", err);
|
|
23854
23975
|
this.recordDaemonTrace("daemon.migration_transport.listen", {
|
|
23855
23976
|
outcome: "failed",
|
|
@@ -23865,6 +23986,7 @@ var DaemonCore = class {
|
|
|
23865
23986
|
if (!this.migrationTransportListening) return;
|
|
23866
23987
|
try {
|
|
23867
23988
|
await this.migrationTransport.close();
|
|
23989
|
+
this.migrationTransportUrl = null;
|
|
23868
23990
|
logger.info("[Slock Daemon] Agent migration HTTP transport stopped");
|
|
23869
23991
|
this.recordDaemonTrace("daemon.migration_transport.stop", { outcome: "stopped" });
|
|
23870
23992
|
} catch (err) {
|
|
@@ -23875,7 +23997,368 @@ var DaemonCore = class {
|
|
|
23875
23997
|
}, "error");
|
|
23876
23998
|
} finally {
|
|
23877
23999
|
this.migrationTransportListening = false;
|
|
24000
|
+
this.migrationTransportUrl = null;
|
|
24001
|
+
}
|
|
24002
|
+
}
|
|
24003
|
+
getActiveMigrationTransferLease() {
|
|
24004
|
+
const lease = this.migrationTransferLease;
|
|
24005
|
+
if (!lease) return null;
|
|
24006
|
+
const expiresAtMs = Date.parse(lease.expiresAt);
|
|
24007
|
+
if (!Number.isFinite(expiresAtMs) || expiresAtMs <= currentTimeMs()) return null;
|
|
24008
|
+
return lease;
|
|
24009
|
+
}
|
|
24010
|
+
validateMigrationTransferLease(lease) {
|
|
24011
|
+
if (!lease.agentId.trim()) throw new Error("migration transfer lease agent id is required");
|
|
24012
|
+
if (!lease.migrationId.trim()) throw new Error("migration transfer lease migration id is required");
|
|
24013
|
+
if (!lease.migrationGeneration.trim()) throw new Error("migration transfer lease migrationGeneration is required");
|
|
24014
|
+
if (!lease.sessionId.trim()) throw new Error("migration transfer lease session id is required");
|
|
24015
|
+
if (lease.provider !== "object_store") throw new Error(`unsupported migration transfer provider: ${lease.provider}`);
|
|
24016
|
+
if (lease.leaseSource !== "server") throw new Error(`unsupported migration transfer lease source: ${lease.leaseSource}`);
|
|
24017
|
+
if (lease.role !== "source" && lease.role !== "target") throw new Error(`unsupported migration transfer role: ${lease.role}`);
|
|
24018
|
+
if (lease.transferKind !== "upload" && lease.transferKind !== "download") {
|
|
24019
|
+
throw new Error(`unsupported migration transfer kind: ${lease.transferKind}`);
|
|
24020
|
+
}
|
|
24021
|
+
if (!lease.url.trim()) throw new Error("migration transfer lease url is required");
|
|
24022
|
+
if (!lease.bearerToken.trim()) throw new Error("migration transfer lease bearer token is required");
|
|
24023
|
+
const expiresAtMs = Date.parse(lease.expiresAt);
|
|
24024
|
+
if (!lease.expiresAt.trim() || !Number.isFinite(expiresAtMs) || expiresAtMs <= currentTimeMs()) {
|
|
24025
|
+
throw new Error("migration transfer lease expiresAt must be a future timestamp");
|
|
24026
|
+
}
|
|
24027
|
+
if (!Number.isInteger(lease.maxBytes) || lease.maxBytes <= 0) {
|
|
24028
|
+
throw new Error("migration transfer lease maxBytes must be a positive integer");
|
|
24029
|
+
}
|
|
24030
|
+
}
|
|
24031
|
+
handleMigrationTransportLease(lease) {
|
|
24032
|
+
try {
|
|
24033
|
+
this.applyMigrationTransferLease(lease);
|
|
24034
|
+
} catch (err) {
|
|
24035
|
+
logger.error("[Slock Daemon] Failed to apply migration transport lease", err);
|
|
24036
|
+
this.recordDaemonTrace("daemon.migration_transport.lease", {
|
|
24037
|
+
outcome: "failed",
|
|
24038
|
+
lease_present: true,
|
|
24039
|
+
error_class: err instanceof Error ? err.name : typeof err
|
|
24040
|
+
}, "error");
|
|
24041
|
+
}
|
|
24042
|
+
}
|
|
24043
|
+
applyMigrationTransferLease(lease) {
|
|
24044
|
+
this.validateMigrationTransferLease(lease);
|
|
24045
|
+
if (this.migrationTransferLease?.agentId === lease.agentId && this.migrationTransferLease?.migrationId === lease.migrationId && this.migrationTransferLease?.migrationGeneration === lease.migrationGeneration && this.migrationTransferLease?.sessionId === lease.sessionId && this.migrationTransferLease?.role === lease.role) {
|
|
24046
|
+
this.migrationTransferLease = lease;
|
|
24047
|
+
this.emitReadyIfConnected();
|
|
24048
|
+
this.recordDaemonTrace("daemon.migration_transport.lease", {
|
|
24049
|
+
outcome: "unchanged",
|
|
24050
|
+
agent_id_present: true,
|
|
24051
|
+
migration_id_present: true,
|
|
24052
|
+
session_id_present: true,
|
|
24053
|
+
migration_generation: lease.migrationGeneration,
|
|
24054
|
+
provider: lease.provider,
|
|
24055
|
+
role: lease.role,
|
|
24056
|
+
transfer_kind: lease.transferKind
|
|
24057
|
+
});
|
|
24058
|
+
this.startMigrationTransferRun(lease);
|
|
24059
|
+
return;
|
|
24060
|
+
}
|
|
24061
|
+
this.migrationTransferLease = lease;
|
|
24062
|
+
this.emitReadyIfConnected();
|
|
24063
|
+
this.recordDaemonTrace("daemon.migration_transport.lease", {
|
|
24064
|
+
outcome: "applied",
|
|
24065
|
+
agent_id_present: true,
|
|
24066
|
+
migration_id_present: true,
|
|
24067
|
+
session_id_present: true,
|
|
24068
|
+
migration_generation: lease.migrationGeneration,
|
|
24069
|
+
provider: lease.provider,
|
|
24070
|
+
role: lease.role,
|
|
24071
|
+
transfer_kind: lease.transferKind,
|
|
24072
|
+
url_present: Boolean(lease.url),
|
|
24073
|
+
bearer_token_present: Boolean(lease.bearerToken)
|
|
24074
|
+
});
|
|
24075
|
+
this.startMigrationTransferRun(lease);
|
|
24076
|
+
}
|
|
24077
|
+
startMigrationTransferRun(lease) {
|
|
24078
|
+
const key = [
|
|
24079
|
+
lease.agentId,
|
|
24080
|
+
lease.migrationId,
|
|
24081
|
+
lease.migrationGeneration,
|
|
24082
|
+
lease.sessionId,
|
|
24083
|
+
lease.role
|
|
24084
|
+
].join(":");
|
|
24085
|
+
if (this.migrationTransferRuns.has(key)) return;
|
|
24086
|
+
this.migrationTransferRuns.add(key);
|
|
24087
|
+
void this.runMigrationTransferLease(lease).catch(async (err) => {
|
|
24088
|
+
logger.error("[Slock Daemon] Migration object-store transfer failed", err);
|
|
24089
|
+
this.recordDaemonTrace("daemon.migration_transport.object_store", {
|
|
24090
|
+
outcome: "failed",
|
|
24091
|
+
role: lease.role,
|
|
24092
|
+
transfer_kind: lease.transferKind,
|
|
24093
|
+
agent_id_present: Boolean(lease.agentId),
|
|
24094
|
+
migration_id_present: Boolean(lease.migrationId),
|
|
24095
|
+
session_id_present: Boolean(lease.sessionId),
|
|
24096
|
+
error_class: err instanceof Error ? err.name : typeof err
|
|
24097
|
+
}, "error");
|
|
24098
|
+
try {
|
|
24099
|
+
await this.reportMigrationTransportLost(lease, err);
|
|
24100
|
+
} catch (reportErr) {
|
|
24101
|
+
logger.error("[Slock Daemon] Failed to report migration transport loss", reportErr);
|
|
24102
|
+
this.recordDaemonTrace("daemon.migration_transport.object_store", {
|
|
24103
|
+
outcome: "transport_lost_report_failed",
|
|
24104
|
+
role: lease.role,
|
|
24105
|
+
transfer_kind: lease.transferKind,
|
|
24106
|
+
migration_id_present: Boolean(lease.migrationId),
|
|
24107
|
+
error_class: reportErr instanceof Error ? reportErr.name : typeof reportErr
|
|
24108
|
+
}, "error");
|
|
24109
|
+
}
|
|
24110
|
+
}).finally(() => {
|
|
24111
|
+
this.migrationTransferRuns.delete(key);
|
|
24112
|
+
});
|
|
24113
|
+
}
|
|
24114
|
+
async runMigrationTransferLease(lease) {
|
|
24115
|
+
if (lease.provider !== "object_store") return;
|
|
24116
|
+
if (lease.role === "source") {
|
|
24117
|
+
await this.uploadMigrationObjectStoreBundle(lease);
|
|
24118
|
+
return;
|
|
24119
|
+
}
|
|
24120
|
+
await this.downloadAndImportMigrationObjectStoreBundle(lease);
|
|
24121
|
+
}
|
|
24122
|
+
migrationObjectStoreHeaders(lease) {
|
|
24123
|
+
return {
|
|
24124
|
+
"X-Raft-Migration-Token": lease.bearerToken
|
|
24125
|
+
};
|
|
24126
|
+
}
|
|
24127
|
+
async uploadMigrationObjectStoreBundle(lease) {
|
|
24128
|
+
if (lease.transferKind !== "upload") {
|
|
24129
|
+
throw new Error("MIGRATION_OBJECT_STORE_SOURCE_KIND_MISMATCH");
|
|
23878
24130
|
}
|
|
24131
|
+
const built = await buildAgentMigrationObjectStoreBundle({
|
|
24132
|
+
agentId: lease.agentId,
|
|
24133
|
+
slockHome: this.slockHome,
|
|
24134
|
+
workspacePath: path23.join(this.agentsDataDir, lease.agentId),
|
|
24135
|
+
maxBytes: lease.maxBytes
|
|
24136
|
+
});
|
|
24137
|
+
const response = await daemonFetch(lease.url, {
|
|
24138
|
+
method: "PUT",
|
|
24139
|
+
headers: {
|
|
24140
|
+
...this.migrationObjectStoreHeaders(lease),
|
|
24141
|
+
"Content-Type": AGENT_MIGRATION_OBJECT_STORE_CONTENT_TYPE
|
|
24142
|
+
},
|
|
24143
|
+
body: new Uint8Array(built.bundle)
|
|
24144
|
+
});
|
|
24145
|
+
if (!response.ok) {
|
|
24146
|
+
throw new Error(`MIGRATION_OBJECT_STORE_UPLOAD_FAILED:${response.status}`);
|
|
24147
|
+
}
|
|
24148
|
+
await this.reportMigrationSourceReady(lease, built.manifestSha256);
|
|
24149
|
+
this.recordDaemonTrace("daemon.migration_transport.object_store", {
|
|
24150
|
+
outcome: "uploaded",
|
|
24151
|
+
role: lease.role,
|
|
24152
|
+
transfer_kind: lease.transferKind,
|
|
24153
|
+
bundle_bytes: built.bundle.byteLength,
|
|
24154
|
+
max_bytes: lease.maxBytes
|
|
24155
|
+
});
|
|
24156
|
+
}
|
|
24157
|
+
async downloadAndImportMigrationObjectStoreBundle(lease) {
|
|
24158
|
+
if (lease.transferKind !== "download") {
|
|
24159
|
+
throw new Error("MIGRATION_OBJECT_STORE_TARGET_KIND_MISMATCH");
|
|
24160
|
+
}
|
|
24161
|
+
const bundle = await this.downloadMigrationObjectStoreBundleWithRetry(lease);
|
|
24162
|
+
if (bundle.byteLength > lease.maxBytes) {
|
|
24163
|
+
throw new Error("MIGRATION_OBJECT_STORE_BUNDLE_TOO_LARGE");
|
|
24164
|
+
}
|
|
24165
|
+
const staged = await stageAgentMigrationObjectStoreBundle({
|
|
24166
|
+
bundle,
|
|
24167
|
+
slockHome: this.slockHome,
|
|
24168
|
+
sessionId: lease.sessionId
|
|
24169
|
+
});
|
|
24170
|
+
const targetImport = await this.fetchMigrationTargetImportView(lease.migrationId);
|
|
24171
|
+
if (targetImport.agentId !== lease.agentId) {
|
|
24172
|
+
throw new Error("MIGRATION_TARGET_IMPORT_AGENT_MISMATCH");
|
|
24173
|
+
}
|
|
24174
|
+
if (targetImport.manifestSha256 && targetImport.manifestSha256 !== staged.manifestSha256) {
|
|
24175
|
+
throw new Error("MIGRATION_TARGET_IMPORT_MANIFEST_SHA_MISMATCH");
|
|
24176
|
+
}
|
|
24177
|
+
const plan = await buildAgentMigrationAdoptPlan({
|
|
24178
|
+
sourceKind: "staged_bundle",
|
|
24179
|
+
slockHome: this.slockHome,
|
|
24180
|
+
stagingWorkspacePath: staged.stagingWorkspacePath,
|
|
24181
|
+
finalWorkspacePath: path23.join(this.agentsDataDir, lease.agentId),
|
|
24182
|
+
manifest: staged.manifest,
|
|
24183
|
+
manifestSha256: staged.manifestSha256,
|
|
24184
|
+
generation: {
|
|
24185
|
+
grantKey: targetImport.grantKey,
|
|
24186
|
+
migrationGeneration: targetImport.migrationGeneration,
|
|
24187
|
+
sourceMachineId: targetImport.sourceMachineId,
|
|
24188
|
+
targetMachineId: targetImport.targetMachineId,
|
|
24189
|
+
localMachineId: targetImport.targetMachineId
|
|
24190
|
+
}
|
|
24191
|
+
});
|
|
24192
|
+
await executeAgentMigrationAdoptPlan(plan, this.migrationRebindClient(targetImport.grantKey));
|
|
24193
|
+
this.recordDaemonTrace("daemon.migration_transport.object_store", {
|
|
24194
|
+
outcome: "imported",
|
|
24195
|
+
role: lease.role,
|
|
24196
|
+
transfer_kind: lease.transferKind,
|
|
24197
|
+
bundle_bytes: bundle.byteLength,
|
|
24198
|
+
manifest_sha_present: true
|
|
24199
|
+
});
|
|
24200
|
+
}
|
|
24201
|
+
async downloadMigrationObjectStoreBundleWithRetry(lease) {
|
|
24202
|
+
const expiresAtMs = Date.parse(lease.expiresAt);
|
|
24203
|
+
let attempt = 0;
|
|
24204
|
+
let delayMs = MIGRATION_OBJECT_STORE_DOWNLOAD_RETRY_INITIAL_MS;
|
|
24205
|
+
let lastStatus = null;
|
|
24206
|
+
let lastErrorClass = null;
|
|
24207
|
+
while (currentTimeMs() < expiresAtMs) {
|
|
24208
|
+
attempt += 1;
|
|
24209
|
+
try {
|
|
24210
|
+
const response = await daemonFetch(lease.url, {
|
|
24211
|
+
method: "GET",
|
|
24212
|
+
headers: this.migrationObjectStoreHeaders(lease)
|
|
24213
|
+
});
|
|
24214
|
+
if (response.ok) {
|
|
24215
|
+
return Buffer.from(await response.arrayBuffer());
|
|
24216
|
+
}
|
|
24217
|
+
lastStatus = response.status;
|
|
24218
|
+
lastErrorClass = null;
|
|
24219
|
+
if (!isRetryableMigrationObjectStoreDownloadStatus(response.status)) {
|
|
24220
|
+
throw new Error(`MIGRATION_OBJECT_STORE_DOWNLOAD_FAILED:${response.status}`);
|
|
24221
|
+
}
|
|
24222
|
+
} catch (err) {
|
|
24223
|
+
if (err instanceof Error && err.message.startsWith("MIGRATION_OBJECT_STORE_DOWNLOAD_FAILED:")) {
|
|
24224
|
+
throw err;
|
|
24225
|
+
}
|
|
24226
|
+
lastErrorClass = err instanceof Error ? err.name : typeof err;
|
|
24227
|
+
}
|
|
24228
|
+
const remainingMs = expiresAtMs - currentTimeMs();
|
|
24229
|
+
if (remainingMs <= 0) break;
|
|
24230
|
+
const sleepMs = Math.min(delayMs, remainingMs);
|
|
24231
|
+
this.recordDaemonTrace("daemon.migration_transport.object_store", {
|
|
24232
|
+
outcome: "download_retry",
|
|
24233
|
+
role: lease.role,
|
|
24234
|
+
transfer_kind: lease.transferKind,
|
|
24235
|
+
attempt,
|
|
24236
|
+
status: lastStatus,
|
|
24237
|
+
error_class: lastErrorClass,
|
|
24238
|
+
retry_delay_ms: sleepMs
|
|
24239
|
+
});
|
|
24240
|
+
await waitForAmbientBackoff(sleepMs);
|
|
24241
|
+
delayMs = Math.min(delayMs * 2, MIGRATION_OBJECT_STORE_DOWNLOAD_RETRY_MAX_MS);
|
|
24242
|
+
}
|
|
24243
|
+
const suffix = lastStatus !== null ? String(lastStatus) : lastErrorClass ?? "unknown";
|
|
24244
|
+
throw new Error(`MIGRATION_OBJECT_STORE_DOWNLOAD_RETRY_EXHAUSTED:${suffix}`);
|
|
24245
|
+
}
|
|
24246
|
+
async reportMigrationTransportLost(lease, err) {
|
|
24247
|
+
const url = new URL(`/internal/computer/agent-migrations/by-id/${encodeURIComponent(lease.migrationId)}/transport-lost`, this.options.serverUrl);
|
|
24248
|
+
const response = await daemonFetch(url, {
|
|
24249
|
+
method: "POST",
|
|
24250
|
+
headers: {
|
|
24251
|
+
...this.internalComputerHeaders(),
|
|
24252
|
+
"Content-Type": "application/json"
|
|
24253
|
+
},
|
|
24254
|
+
body: JSON.stringify({
|
|
24255
|
+
role: lease.role,
|
|
24256
|
+
transferKind: lease.transferKind,
|
|
24257
|
+
message: migrationTransferFailureMessage(err)
|
|
24258
|
+
})
|
|
24259
|
+
});
|
|
24260
|
+
if (!response.ok) {
|
|
24261
|
+
throw new Error(`MIGRATION_TRANSPORT_LOST_REPORT_FAILED:${response.status}`);
|
|
24262
|
+
}
|
|
24263
|
+
this.recordDaemonTrace("daemon.migration_transport.object_store", {
|
|
24264
|
+
outcome: "transport_lost_reported",
|
|
24265
|
+
role: lease.role,
|
|
24266
|
+
transfer_kind: lease.transferKind,
|
|
24267
|
+
migration_id_present: Boolean(lease.migrationId)
|
|
24268
|
+
});
|
|
24269
|
+
}
|
|
24270
|
+
async reportMigrationSourceReady(lease, manifestSha256) {
|
|
24271
|
+
const url = new URL(`/internal/computer/agent-migrations/by-id/${encodeURIComponent(lease.migrationId)}/source-ready`, this.options.serverUrl);
|
|
24272
|
+
const response = await daemonFetch(url, {
|
|
24273
|
+
method: "POST",
|
|
24274
|
+
headers: {
|
|
24275
|
+
...this.internalComputerHeaders(),
|
|
24276
|
+
"Content-Type": "application/json"
|
|
24277
|
+
},
|
|
24278
|
+
body: JSON.stringify({
|
|
24279
|
+
manifestPath: `object-store:${lease.sessionId}/manifest.json`,
|
|
24280
|
+
manifestSha256
|
|
24281
|
+
})
|
|
24282
|
+
});
|
|
24283
|
+
if (!response.ok) {
|
|
24284
|
+
throw new Error(`MIGRATION_SOURCE_READY_REPORT_FAILED:${response.status}:${await migrationStepErrorSuffix(response)}`);
|
|
24285
|
+
}
|
|
24286
|
+
this.recordDaemonTrace("daemon.migration_transport.object_store", {
|
|
24287
|
+
outcome: "source_ready_reported",
|
|
24288
|
+
role: lease.role,
|
|
24289
|
+
transfer_kind: lease.transferKind,
|
|
24290
|
+
migration_id_present: Boolean(lease.migrationId)
|
|
24291
|
+
});
|
|
24292
|
+
}
|
|
24293
|
+
async fetchMigrationTargetImportView(migrationId) {
|
|
24294
|
+
const url = new URL(`/internal/computer/agent-migrations/by-id/${encodeURIComponent(migrationId)}`, this.options.serverUrl);
|
|
24295
|
+
const response = await daemonFetch(url, {
|
|
24296
|
+
method: "GET",
|
|
24297
|
+
headers: this.internalComputerHeaders()
|
|
24298
|
+
});
|
|
24299
|
+
if (!response.ok) {
|
|
24300
|
+
throw new Error(`MIGRATION_TARGET_IMPORT_LOOKUP_FAILED:${response.status}`);
|
|
24301
|
+
}
|
|
24302
|
+
const body = await response.json();
|
|
24303
|
+
if (!body.migration) throw new Error("MIGRATION_TARGET_IMPORT_VIEW_MISSING");
|
|
24304
|
+
return body.migration;
|
|
24305
|
+
}
|
|
24306
|
+
async fetchMigrationTargetImportViewByGrantKey(grantKey) {
|
|
24307
|
+
const url = new URL(`/internal/computer/agent-migrations/${encodeURIComponent(grantKey)}`, this.options.serverUrl);
|
|
24308
|
+
const response = await daemonFetch(url, {
|
|
24309
|
+
method: "GET",
|
|
24310
|
+
headers: this.internalComputerHeaders()
|
|
24311
|
+
});
|
|
24312
|
+
if (!response.ok) {
|
|
24313
|
+
throw new Error(`MIGRATION_TARGET_IMPORT_LOOKUP_FAILED:${response.status}`);
|
|
24314
|
+
}
|
|
24315
|
+
const body = await response.json();
|
|
24316
|
+
if (!body.migration) throw new Error("MIGRATION_TARGET_IMPORT_VIEW_MISSING");
|
|
24317
|
+
return body.migration;
|
|
24318
|
+
}
|
|
24319
|
+
migrationRebindClient(grantKey) {
|
|
24320
|
+
return {
|
|
24321
|
+
startTransfer: (input) => this.postMigrationTargetImportStep(grantKey, "start-transfer", input),
|
|
24322
|
+
flipMachine: (input) => this.postMigrationTargetImportStep(grantKey, "flip-machine", input),
|
|
24323
|
+
markArrived: (input) => this.postMigrationTargetImportStep(grantKey, "arrived", input)
|
|
24324
|
+
};
|
|
24325
|
+
}
|
|
24326
|
+
async postMigrationTargetImportStep(grantKey, step, body) {
|
|
24327
|
+
return await this.postMigrationTargetImportStepOnce(grantKey, step, body, true);
|
|
24328
|
+
}
|
|
24329
|
+
async postMigrationTargetImportStepOnce(grantKey, step, body, allowStartGenerationRefresh) {
|
|
24330
|
+
const url = new URL(`/internal/computer/agent-migrations/${encodeURIComponent(grantKey)}/${step}`, this.options.serverUrl);
|
|
24331
|
+
const response = await daemonFetch(url, {
|
|
24332
|
+
method: "POST",
|
|
24333
|
+
headers: {
|
|
24334
|
+
...this.internalComputerHeaders(),
|
|
24335
|
+
"Content-Type": "application/json"
|
|
24336
|
+
},
|
|
24337
|
+
body: JSON.stringify(body)
|
|
24338
|
+
});
|
|
24339
|
+
if (!response.ok) {
|
|
24340
|
+
const suffix = await migrationStepErrorSuffix(response);
|
|
24341
|
+
if (step === "start-transfer" && response.status === 409 && suffix === "migration_generation_stale" && allowStartGenerationRefresh) {
|
|
24342
|
+
const current = await this.fetchMigrationTargetImportViewByGrantKey(grantKey);
|
|
24343
|
+
if (current.state === "in_transit") return current;
|
|
24344
|
+
if (current.state === "ready" && current.migrationGeneration !== body.migrationGeneration) {
|
|
24345
|
+
return await this.postMigrationTargetImportStepOnce(grantKey, step, {
|
|
24346
|
+
...body,
|
|
24347
|
+
migrationGeneration: current.migrationGeneration
|
|
24348
|
+
}, false);
|
|
24349
|
+
}
|
|
24350
|
+
}
|
|
24351
|
+
throw new Error(`MIGRATION_TARGET_IMPORT_${step.toUpperCase().replace("-", "_")}_FAILED:${response.status}:${suffix}`);
|
|
24352
|
+
}
|
|
24353
|
+
const responseBody = await response.json();
|
|
24354
|
+
if (!responseBody.migration) throw new Error("MIGRATION_TARGET_IMPORT_VIEW_MISSING");
|
|
24355
|
+
return responseBody.migration;
|
|
24356
|
+
}
|
|
24357
|
+
internalComputerHeaders() {
|
|
24358
|
+
return {
|
|
24359
|
+
"Authorization": `Bearer ${this.options.apiKey}`,
|
|
24360
|
+
"X-Slock-Client": "daemon-migration-object-store"
|
|
24361
|
+
};
|
|
23879
24362
|
}
|
|
23880
24363
|
withDaemonTraceScope(tracer) {
|
|
23881
24364
|
return {
|
|
@@ -24323,6 +24806,9 @@ var DaemonCore = class {
|
|
|
24323
24806
|
});
|
|
24324
24807
|
break;
|
|
24325
24808
|
}
|
|
24809
|
+
case "machine:migration_transport:lease":
|
|
24810
|
+
this.handleMigrationTransportLease(msg);
|
|
24811
|
+
break;
|
|
24326
24812
|
case "reminder.upsert":
|
|
24327
24813
|
this.reminderCache.upsert(msg.reminder);
|
|
24328
24814
|
break;
|
|
@@ -24380,24 +24866,16 @@ var DaemonCore = class {
|
|
|
24380
24866
|
firedAtClient: (/* @__PURE__ */ new Date()).toISOString()
|
|
24381
24867
|
});
|
|
24382
24868
|
}
|
|
24383
|
-
|
|
24869
|
+
emitReadyIfConnected() {
|
|
24870
|
+
if (this.connection.connected) this.emitReady();
|
|
24871
|
+
}
|
|
24872
|
+
emitReady() {
|
|
24384
24873
|
const { ids: runtimes, versions: runtimeVersions, diagnostics: runtimeDiagnostics = {} } = this.runtimeDetector();
|
|
24385
24874
|
const runtimeInfo = runtimes.map((id) => runtimeVersions[id] ? `${id} (${runtimeVersions[id]})` : id);
|
|
24386
24875
|
logger.info(`[Daemon] Detected runtimes: ${runtimeInfo.join(", ") || "none"}`);
|
|
24387
24876
|
for (const [runtime, diagnostic] of Object.entries(runtimeDiagnostics)) {
|
|
24388
24877
|
logger.warn(`[Daemon] Runtime ${runtime} diagnostic: ${diagnostic}`);
|
|
24389
24878
|
}
|
|
24390
|
-
if (!this.opencliWrappersRegenerated) {
|
|
24391
|
-
this.opencliWrappersRegenerated = true;
|
|
24392
|
-
try {
|
|
24393
|
-
const { scanned, rewritten } = regenerateExistingOpencliWrappers(this.agentsDataDir);
|
|
24394
|
-
if (scanned > 0) {
|
|
24395
|
-
logger.info(`[Daemon] Refreshed ${rewritten}/${scanned} opencli wrapper(s) to current self-healing form`);
|
|
24396
|
-
}
|
|
24397
|
-
} catch (err) {
|
|
24398
|
-
logger.warn(`[Daemon] opencli wrapper refresh skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
24399
|
-
}
|
|
24400
|
-
}
|
|
24401
24879
|
const runningAgentIds = this.agentManager.getRunningAgentIds();
|
|
24402
24880
|
const idleAgentSessions = this.agentManager.getIdleAgentSessionIds();
|
|
24403
24881
|
const runtimeProfileReports = this.agentManager.getAgentRuntimeProfileReports();
|
|
@@ -24409,7 +24887,8 @@ var DaemonCore = class {
|
|
|
24409
24887
|
hostname: this.options.hostname ?? os8.hostname(),
|
|
24410
24888
|
os: this.options.osDescription ?? `${os8.platform()} ${os8.arch()}`,
|
|
24411
24889
|
daemonVersion: this.daemonVersion,
|
|
24412
|
-
...this.computerVersion ? { computerVersion: this.computerVersion } : {}
|
|
24890
|
+
...this.computerVersion ? { computerVersion: this.computerVersion } : {},
|
|
24891
|
+
migrationTransport: this.getMigrationTransportReady()
|
|
24413
24892
|
});
|
|
24414
24893
|
this.recordDaemonTrace("daemon.ready.sent", {
|
|
24415
24894
|
runtimes_count: runtimes.length,
|
|
@@ -24417,6 +24896,23 @@ var DaemonCore = class {
|
|
|
24417
24896
|
idle_agents_count: idleAgentSessions.length,
|
|
24418
24897
|
runtime_profile_reports_count: runtimeProfileReports.length
|
|
24419
24898
|
});
|
|
24899
|
+
}
|
|
24900
|
+
handleConnect() {
|
|
24901
|
+
if (!this.opencliWrappersRegenerated) {
|
|
24902
|
+
this.opencliWrappersRegenerated = true;
|
|
24903
|
+
try {
|
|
24904
|
+
const { scanned, rewritten } = regenerateExistingOpencliWrappers(this.agentsDataDir);
|
|
24905
|
+
if (scanned > 0) {
|
|
24906
|
+
logger.info(`[Daemon] Refreshed ${rewritten}/${scanned} opencli wrapper(s) to current self-healing form`);
|
|
24907
|
+
}
|
|
24908
|
+
} catch (err) {
|
|
24909
|
+
logger.warn(`[Daemon] opencli wrapper refresh skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
24910
|
+
}
|
|
24911
|
+
}
|
|
24912
|
+
this.emitReady();
|
|
24913
|
+
const runningAgentIds = this.agentManager.getRunningAgentIds();
|
|
24914
|
+
const idleAgentSessions = this.agentManager.getIdleAgentSessionIds();
|
|
24915
|
+
const runtimeProfileReports = this.agentManager.getAgentRuntimeProfileReports();
|
|
24420
24916
|
if (this.options.onComputerUpgradeReconcile) {
|
|
24421
24917
|
void Promise.resolve().then(
|
|
24422
24918
|
() => this.options.onComputerUpgradeReconcile((done) => {
|
|
@@ -24504,6 +25000,10 @@ export {
|
|
|
24504
25000
|
resolveAgentMigrationControlSeamEnabled,
|
|
24505
25001
|
AGENT_MIGRATION_BUNDLE_SCHEMA_VERSION,
|
|
24506
25002
|
buildAgentMigrationExportManifest,
|
|
25003
|
+
AGENT_MIGRATION_OBJECT_STORE_BUNDLE_SCHEMA_VERSION,
|
|
25004
|
+
AGENT_MIGRATION_OBJECT_STORE_CONTENT_TYPE,
|
|
25005
|
+
buildAgentMigrationObjectStoreBundle,
|
|
25006
|
+
stageAgentMigrationObjectStoreBundle,
|
|
24507
25007
|
buildAgentMigrationAdoptPlan,
|
|
24508
25008
|
verifyAgentMigrationAdoptPlan,
|
|
24509
25009
|
executeAgentMigrationAdoptPlan,
|