@spencer-kit/coder-studio 0.3.5 → 0.3.7
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/CHANGELOG.md +12 -0
- package/dist/esm/bin.mjs +1374 -316
- package/dist/esm/bin.mjs.map +4 -4
- package/dist/esm/migrations/001_init.sql +15 -1
- package/dist/esm/server-runner.mjs +1401 -390
- package/dist/esm/server-runner.mjs.map +4 -4
- package/dist/web/assets/index-CoNo6FuB.css +1 -0
- package/dist/web/assets/index-DdIyj_YE.js +111 -0
- package/dist/web/assets/index-DdIyj_YE.js.map +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/bin.test.ts +70 -0
- package/src/cli.ts +67 -3
- package/src/server-runner.test.ts +45 -2
- package/src/server-runner.ts +13 -0
- package/dist/web/assets/index-B3PO5hz_.js +0 -111
- package/dist/web/assets/index-B3PO5hz_.js.map +0 -1
- package/dist/web/assets/index-BbpuXQCm.css +0 -1
|
@@ -385,34 +385,34 @@ var init_config = __esm({
|
|
|
385
385
|
});
|
|
386
386
|
|
|
387
387
|
// packages/core/src/runtime.ts
|
|
388
|
-
import { existsSync
|
|
389
|
-
import { homedir
|
|
390
|
-
import { dirname
|
|
388
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
389
|
+
import { homedir } from "node:os";
|
|
390
|
+
import { dirname, join } from "node:path";
|
|
391
391
|
function getRuntimeDir() {
|
|
392
392
|
const override = process.env.CODER_STUDIO_RUNTIME_DIR;
|
|
393
393
|
if (override && override.trim()) {
|
|
394
394
|
return override;
|
|
395
395
|
}
|
|
396
|
-
return
|
|
396
|
+
return join(homedir(), ".coder-studio");
|
|
397
397
|
}
|
|
398
398
|
function getRuntimePath() {
|
|
399
399
|
const pathOverride = process.env.CODER_STUDIO_RUNTIME_JSON_PATH;
|
|
400
400
|
if (pathOverride && pathOverride.trim()) {
|
|
401
401
|
return pathOverride;
|
|
402
402
|
}
|
|
403
|
-
return
|
|
403
|
+
return join(getRuntimeDir(), "runtime.json");
|
|
404
404
|
}
|
|
405
405
|
function writeRuntimeConfig(config) {
|
|
406
406
|
const runtimePath = getRuntimePath();
|
|
407
|
-
const runtimeDir =
|
|
408
|
-
if (!
|
|
409
|
-
|
|
407
|
+
const runtimeDir = dirname(runtimePath);
|
|
408
|
+
if (!existsSync(runtimeDir)) {
|
|
409
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
410
410
|
}
|
|
411
|
-
|
|
411
|
+
writeFileSync(runtimePath, JSON.stringify(config, null, 2), "utf-8");
|
|
412
412
|
}
|
|
413
413
|
function deleteRuntimeConfig() {
|
|
414
414
|
const runtimePath = getRuntimePath();
|
|
415
|
-
if (
|
|
415
|
+
if (existsSync(runtimePath)) {
|
|
416
416
|
unlinkSync(runtimePath);
|
|
417
417
|
}
|
|
418
418
|
}
|
|
@@ -593,6 +593,7 @@ var init_config_schema2 = __esm({
|
|
|
593
593
|
"packages/providers/src/codex/config-schema.ts"() {
|
|
594
594
|
"use strict";
|
|
595
595
|
codexConfigSchema = z2.object({
|
|
596
|
+
model: z2.string().min(1).optional(),
|
|
596
597
|
additionalArgs: z2.array(z2.string()).default([]),
|
|
597
598
|
envVars: z2.record(z2.string(), z2.string()).default({})
|
|
598
599
|
});
|
|
@@ -639,6 +640,7 @@ function buildCodexSupervisorEvalCommand(config, req) {
|
|
|
639
640
|
"-s",
|
|
640
641
|
"read-only",
|
|
641
642
|
"--skip-git-repo-check",
|
|
643
|
+
...req.model ? ["-m", req.model] : [],
|
|
642
644
|
...cfg.additionalArgs,
|
|
643
645
|
req.prompt
|
|
644
646
|
],
|
|
@@ -786,7 +788,7 @@ var init_src = __esm({
|
|
|
786
788
|
});
|
|
787
789
|
|
|
788
790
|
// packages/utils/src/direct-execution.ts
|
|
789
|
-
import { posix, resolve
|
|
791
|
+
import { posix, resolve } from "node:path";
|
|
790
792
|
function isWindowsDrivePath(path10) {
|
|
791
793
|
return /^[A-Za-z]:\//.test(path10);
|
|
792
794
|
}
|
|
@@ -820,7 +822,7 @@ function normalizeModuleUrlPath(moduleUrl) {
|
|
|
820
822
|
}
|
|
821
823
|
function normalizeArgvPath(argv1) {
|
|
822
824
|
const isAbsoluteWindowsPath = /^[A-Za-z]:[\\/]/.test(argv1) || /^\\\\/.test(argv1);
|
|
823
|
-
return normalizeComparablePath(isAbsoluteWindowsPath ? argv1 :
|
|
825
|
+
return normalizeComparablePath(isAbsoluteWindowsPath ? argv1 : resolve(argv1));
|
|
824
826
|
}
|
|
825
827
|
function isDirectExecution(moduleUrl, argv1 = process.argv[1]) {
|
|
826
828
|
if (argv1 === void 0) {
|
|
@@ -995,7 +997,7 @@ var init_image = __esm({
|
|
|
995
997
|
// packages/server/src/fs/file-io.ts
|
|
996
998
|
import { createHash } from "crypto";
|
|
997
999
|
import { readFile as fsReadFile, writeFile as fsWriteFile, mkdir, rm, stat } from "fs/promises";
|
|
998
|
-
import { dirname as
|
|
1000
|
+
import { dirname as dirname2, isAbsolute, relative, resolve as resolve2 } from "path";
|
|
999
1001
|
async function statSafe(path10) {
|
|
1000
1002
|
try {
|
|
1001
1003
|
return await stat(path10);
|
|
@@ -1009,7 +1011,7 @@ async function createFile(rootPath, relPath) {
|
|
|
1009
1011
|
if (existing) {
|
|
1010
1012
|
throw { code: "already_exists", message: "File already exists" };
|
|
1011
1013
|
}
|
|
1012
|
-
await mkdir(
|
|
1014
|
+
await mkdir(dirname2(abs), { recursive: true });
|
|
1013
1015
|
await fsWriteFile(abs, "", "utf-8");
|
|
1014
1016
|
}
|
|
1015
1017
|
async function createDirectory(rootPath, relPath) {
|
|
@@ -1029,8 +1031,8 @@ async function deleteEntry(rootPath, relPath) {
|
|
|
1029
1031
|
await rm(abs, { recursive: true });
|
|
1030
1032
|
}
|
|
1031
1033
|
function resolveSafe(root, relPath) {
|
|
1032
|
-
const absRoot =
|
|
1033
|
-
const abs =
|
|
1034
|
+
const absRoot = resolve2(root);
|
|
1035
|
+
const abs = resolve2(absRoot, relPath);
|
|
1034
1036
|
const rel = relative(absRoot, abs);
|
|
1035
1037
|
if (rel === ".." || rel.startsWith(`..${"/"}`) || isAbsolute(rel)) {
|
|
1036
1038
|
throw { code: "path_escape", message: "Path escapes workspace root" };
|
|
@@ -1079,7 +1081,7 @@ async function writeFile(rootPath, relPath, content, baseHash) {
|
|
|
1079
1081
|
};
|
|
1080
1082
|
}
|
|
1081
1083
|
}
|
|
1082
|
-
await mkdir(
|
|
1084
|
+
await mkdir(dirname2(abs), { recursive: true });
|
|
1083
1085
|
await fsWriteFile(abs, content, "utf-8");
|
|
1084
1086
|
const newHash = createHash("sha256").update(content).digest("hex");
|
|
1085
1087
|
return { newHash };
|
|
@@ -2108,8 +2110,8 @@ var init_command_check = __esm({
|
|
|
2108
2110
|
});
|
|
2109
2111
|
|
|
2110
2112
|
// packages/server/src/provider-runtime/e2e-provider-mock.ts
|
|
2111
|
-
import { chmodSync, existsSync as
|
|
2112
|
-
import { dirname as
|
|
2113
|
+
import { chmodSync, existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
2114
|
+
import { dirname as dirname3, join as join2 } from "node:path";
|
|
2113
2115
|
function createE2EProviderMockOverrides(env = process.env) {
|
|
2114
2116
|
const statePath = env.CODER_STUDIO_E2E_PROVIDER_STATE_PATH;
|
|
2115
2117
|
if (!statePath) {
|
|
@@ -2191,10 +2193,10 @@ function getInstallProviderId(file, args) {
|
|
|
2191
2193
|
return null;
|
|
2192
2194
|
}
|
|
2193
2195
|
function readMockState(statePath) {
|
|
2194
|
-
if (!
|
|
2196
|
+
if (!existsSync3(statePath)) {
|
|
2195
2197
|
return {};
|
|
2196
2198
|
}
|
|
2197
|
-
const raw =
|
|
2199
|
+
const raw = readFileSync3(statePath, "utf8");
|
|
2198
2200
|
if (!raw.trim()) {
|
|
2199
2201
|
return {};
|
|
2200
2202
|
}
|
|
@@ -2209,22 +2211,22 @@ function readMockState(statePath) {
|
|
|
2209
2211
|
function writeMockState(statePath, updater) {
|
|
2210
2212
|
const nextState = readMockState(statePath);
|
|
2211
2213
|
updater(nextState);
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
+
mkdirSync2(dirname3(statePath), { recursive: true });
|
|
2215
|
+
writeFileSync2(statePath, JSON.stringify(nextState, null, 2));
|
|
2214
2216
|
return nextState;
|
|
2215
2217
|
}
|
|
2216
2218
|
function ensureProviderCommand(binDir, providerId) {
|
|
2217
|
-
|
|
2218
|
-
const scriptPath =
|
|
2219
|
-
|
|
2219
|
+
mkdirSync2(binDir, { recursive: true });
|
|
2220
|
+
const scriptPath = join2(binDir, providerId);
|
|
2221
|
+
writeFileSync2(scriptPath, PROVIDER_COMMAND_SCRIPTS[providerId], "utf8");
|
|
2220
2222
|
chmodSync(scriptPath, 493);
|
|
2221
2223
|
}
|
|
2222
2224
|
function appendDebugLog(path10, line) {
|
|
2223
2225
|
if (!path10) {
|
|
2224
2226
|
return;
|
|
2225
2227
|
}
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
+
mkdirSync2(dirname3(path10), { recursive: true });
|
|
2229
|
+
writeFileSync2(path10, `${line}
|
|
2228
2230
|
`, { flag: "a" });
|
|
2229
2231
|
}
|
|
2230
2232
|
var PROVIDER_INSTALL_PACKAGES, PROVIDER_COMMAND_SCRIPTS;
|
|
@@ -2705,12 +2707,46 @@ function resolveSupervisorEvaluationTimeoutSec(value) {
|
|
|
2705
2707
|
}
|
|
2706
2708
|
return value;
|
|
2707
2709
|
}
|
|
2708
|
-
|
|
2710
|
+
function resolveSupervisorRetryEnabled(value) {
|
|
2711
|
+
return typeof value === "boolean" ? value : DEFAULT_SUPERVISOR_RETRY_ENABLED;
|
|
2712
|
+
}
|
|
2713
|
+
function resolveSupervisorRetryMaxCount(value) {
|
|
2714
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isSafeInteger(value)) {
|
|
2715
|
+
return DEFAULT_SUPERVISOR_RETRY_MAX_COUNT;
|
|
2716
|
+
}
|
|
2717
|
+
if (value < 0 || value > MAX_SUPERVISOR_RETRY_MAX_COUNT) {
|
|
2718
|
+
return DEFAULT_SUPERVISOR_RETRY_MAX_COUNT;
|
|
2719
|
+
}
|
|
2720
|
+
return value;
|
|
2721
|
+
}
|
|
2722
|
+
function resolveSupervisorRetryDelaySec(value) {
|
|
2723
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isSafeInteger(value)) {
|
|
2724
|
+
return DEFAULT_SUPERVISOR_RETRY_DELAY_SEC;
|
|
2725
|
+
}
|
|
2726
|
+
if (value < 1 || value > MAX_SUPERVISOR_RETRY_DELAY_SEC) {
|
|
2727
|
+
return DEFAULT_SUPERVISOR_RETRY_DELAY_SEC;
|
|
2728
|
+
}
|
|
2729
|
+
return value;
|
|
2730
|
+
}
|
|
2731
|
+
function resolveSupervisorRetryOnTimeout(value) {
|
|
2732
|
+
return typeof value === "boolean" ? value : DEFAULT_SUPERVISOR_RETRY_ON_TIMEOUT;
|
|
2733
|
+
}
|
|
2734
|
+
function resolveSupervisorRetryOnEvaluatorError(value) {
|
|
2735
|
+
return typeof value === "boolean" ? value : DEFAULT_SUPERVISOR_RETRY_ON_EVALUATOR_ERROR;
|
|
2736
|
+
}
|
|
2737
|
+
var DEFAULT_SUPERVISOR_EVALUATION_TIMEOUT_SEC, MAX_SUPERVISOR_EVALUATION_TIMEOUT_SEC, DEFAULT_SUPERVISOR_RETRY_ENABLED, DEFAULT_SUPERVISOR_RETRY_MAX_COUNT, MAX_SUPERVISOR_RETRY_MAX_COUNT, DEFAULT_SUPERVISOR_RETRY_DELAY_SEC, MAX_SUPERVISOR_RETRY_DELAY_SEC, DEFAULT_SUPERVISOR_RETRY_ON_TIMEOUT, DEFAULT_SUPERVISOR_RETRY_ON_EVALUATOR_ERROR, DEFAULT_SUPERVISOR_CONFIG;
|
|
2709
2738
|
var init_supervisor = __esm({
|
|
2710
2739
|
"packages/core/src/domain/supervisor.ts"() {
|
|
2711
2740
|
"use strict";
|
|
2712
2741
|
DEFAULT_SUPERVISOR_EVALUATION_TIMEOUT_SEC = 600;
|
|
2713
2742
|
MAX_SUPERVISOR_EVALUATION_TIMEOUT_SEC = 86400;
|
|
2743
|
+
DEFAULT_SUPERVISOR_RETRY_ENABLED = false;
|
|
2744
|
+
DEFAULT_SUPERVISOR_RETRY_MAX_COUNT = 0;
|
|
2745
|
+
MAX_SUPERVISOR_RETRY_MAX_COUNT = 20;
|
|
2746
|
+
DEFAULT_SUPERVISOR_RETRY_DELAY_SEC = 10;
|
|
2747
|
+
MAX_SUPERVISOR_RETRY_DELAY_SEC = 3600;
|
|
2748
|
+
DEFAULT_SUPERVISOR_RETRY_ON_TIMEOUT = true;
|
|
2749
|
+
DEFAULT_SUPERVISOR_RETRY_ON_EVALUATOR_ERROR = false;
|
|
2714
2750
|
DEFAULT_SUPERVISOR_CONFIG = {
|
|
2715
2751
|
maxCyclesPerSession: 100,
|
|
2716
2752
|
terminalLinesForEvaluation: 500,
|
|
@@ -3738,10 +3774,10 @@ var init_database = __esm({
|
|
|
3738
3774
|
}
|
|
3739
3775
|
});
|
|
3740
3776
|
|
|
3741
|
-
// packages/server/src/storage/
|
|
3777
|
+
// packages/server/src/storage/schema-version.ts
|
|
3742
3778
|
import { DatabaseSync } from "node:sqlite";
|
|
3743
|
-
import { readFileSync as
|
|
3744
|
-
import { join as
|
|
3779
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
3780
|
+
import { join as join3 } from "path";
|
|
3745
3781
|
function normalizeSql(sql) {
|
|
3746
3782
|
return (sql ?? "").replace(/\s+/g, " ").trim();
|
|
3747
3783
|
}
|
|
@@ -3762,15 +3798,229 @@ function listSchemaEntries(db) {
|
|
|
3762
3798
|
sql: normalizeSql(row.sql)
|
|
3763
3799
|
}));
|
|
3764
3800
|
}
|
|
3765
|
-
function
|
|
3801
|
+
function schemaEntrySignature(entry) {
|
|
3802
|
+
return `${entry.type}:${entry.name}:${entry.tableName}:${entry.sql}`;
|
|
3803
|
+
}
|
|
3804
|
+
function buildSchemaEntries(schemaSql) {
|
|
3766
3805
|
const db = new DatabaseSync(":memory:");
|
|
3767
3806
|
try {
|
|
3768
|
-
db.exec(
|
|
3807
|
+
db.exec(schemaSql);
|
|
3769
3808
|
return listSchemaEntries(db);
|
|
3770
3809
|
} finally {
|
|
3771
3810
|
db.close();
|
|
3772
3811
|
}
|
|
3773
3812
|
}
|
|
3813
|
+
function hasExactFingerprint(actualEntries, expectedEntries) {
|
|
3814
|
+
if (actualEntries.length !== expectedEntries.length) {
|
|
3815
|
+
return false;
|
|
3816
|
+
}
|
|
3817
|
+
return actualEntries.every(
|
|
3818
|
+
(entry, index) => schemaEntrySignature(entry) === schemaEntrySignature(expectedEntries[index])
|
|
3819
|
+
);
|
|
3820
|
+
}
|
|
3821
|
+
function describeSchemaMismatch(expected, actual) {
|
|
3822
|
+
const expectedByName = new Map(expected.map((entry) => [`${entry.type}:${entry.name}`, entry]));
|
|
3823
|
+
const actualByName = new Map(actual.map((entry) => [`${entry.type}:${entry.name}`, entry]));
|
|
3824
|
+
const keys = /* @__PURE__ */ new Set([...expectedByName.keys(), ...actualByName.keys()]);
|
|
3825
|
+
for (const key of keys) {
|
|
3826
|
+
const expectedEntry = expectedByName.get(key);
|
|
3827
|
+
const actualEntry = actualByName.get(key);
|
|
3828
|
+
if (!expectedEntry) {
|
|
3829
|
+
return `unexpected ${actualEntry?.type ?? "schema object"} ${actualEntry?.name ?? key}`;
|
|
3830
|
+
}
|
|
3831
|
+
if (!actualEntry) {
|
|
3832
|
+
return `missing ${expectedEntry.type} ${expectedEntry.name}`;
|
|
3833
|
+
}
|
|
3834
|
+
if (schemaEntrySignature(expectedEntry) !== schemaEntrySignature(actualEntry)) {
|
|
3835
|
+
return `definition mismatch for ${expectedEntry.type} ${expectedEntry.name}`;
|
|
3836
|
+
}
|
|
3837
|
+
}
|
|
3838
|
+
return "unknown schema drift";
|
|
3839
|
+
}
|
|
3840
|
+
function detectSchema(db) {
|
|
3841
|
+
const actualEntries = listSchemaEntries(db);
|
|
3842
|
+
const userVersionRow = db.prepare("PRAGMA user_version").get();
|
|
3843
|
+
const userVersion = userVersionRow?.user_version ?? 0;
|
|
3844
|
+
if (actualEntries.length === 0) {
|
|
3845
|
+
return {
|
|
3846
|
+
state: "empty",
|
|
3847
|
+
userVersion,
|
|
3848
|
+
mismatch: null
|
|
3849
|
+
};
|
|
3850
|
+
}
|
|
3851
|
+
if (hasExactFingerprint(actualEntries, CURRENT_SCHEMA_ENTRIES)) {
|
|
3852
|
+
return {
|
|
3853
|
+
state: "current",
|
|
3854
|
+
userVersion,
|
|
3855
|
+
mismatch: null
|
|
3856
|
+
};
|
|
3857
|
+
}
|
|
3858
|
+
if (hasExactFingerprint(actualEntries, V1_SCHEMA_ENTRIES)) {
|
|
3859
|
+
return {
|
|
3860
|
+
state: "v1",
|
|
3861
|
+
userVersion,
|
|
3862
|
+
mismatch: null
|
|
3863
|
+
};
|
|
3864
|
+
}
|
|
3865
|
+
return {
|
|
3866
|
+
state: "incompatible",
|
|
3867
|
+
userVersion,
|
|
3868
|
+
mismatch: describeSchemaMismatch(CURRENT_SCHEMA_ENTRIES, actualEntries)
|
|
3869
|
+
};
|
|
3870
|
+
}
|
|
3871
|
+
function stampCurrentSchemaVersion(db) {
|
|
3872
|
+
db.exec(`PRAGMA user_version = ${CURRENT_SCHEMA_VERSION}`);
|
|
3873
|
+
}
|
|
3874
|
+
var CURRENT_SCHEMA_VERSION, CURRENT_SCHEMA_PATH, CURRENT_SCHEMA_SQL, V1_SCHEMA_SQL, CURRENT_SCHEMA_ENTRIES, V1_SCHEMA_ENTRIES, IncompatibleSchemaError;
|
|
3875
|
+
var init_schema_version = __esm({
|
|
3876
|
+
"packages/server/src/storage/schema-version.ts"() {
|
|
3877
|
+
"use strict";
|
|
3878
|
+
CURRENT_SCHEMA_VERSION = 2;
|
|
3879
|
+
CURRENT_SCHEMA_PATH = join3(import.meta.dirname, "migrations", "001_init.sql");
|
|
3880
|
+
CURRENT_SCHEMA_SQL = readFileSync4(CURRENT_SCHEMA_PATH, "utf-8");
|
|
3881
|
+
V1_SCHEMA_SQL = `
|
|
3882
|
+
CREATE TABLE workspaces (
|
|
3883
|
+
id TEXT PRIMARY KEY,
|
|
3884
|
+
path TEXT NOT NULL UNIQUE,
|
|
3885
|
+
target_runtime TEXT NOT NULL,
|
|
3886
|
+
wsl_distro TEXT,
|
|
3887
|
+
opened_at INTEGER NOT NULL,
|
|
3888
|
+
last_active_at INTEGER NOT NULL,
|
|
3889
|
+
ui_state TEXT
|
|
3890
|
+
);
|
|
3891
|
+
|
|
3892
|
+
CREATE TABLE terminals (
|
|
3893
|
+
id TEXT PRIMARY KEY,
|
|
3894
|
+
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
3895
|
+
kind TEXT NOT NULL,
|
|
3896
|
+
cwd TEXT NOT NULL,
|
|
3897
|
+
argv TEXT NOT NULL,
|
|
3898
|
+
env TEXT,
|
|
3899
|
+
title TEXT,
|
|
3900
|
+
cols INTEGER NOT NULL,
|
|
3901
|
+
rows INTEGER NOT NULL,
|
|
3902
|
+
created_at INTEGER NOT NULL,
|
|
3903
|
+
ended_at INTEGER,
|
|
3904
|
+
exit_code INTEGER
|
|
3905
|
+
);
|
|
3906
|
+
|
|
3907
|
+
CREATE INDEX idx_terminals_workspace ON terminals(workspace_id);
|
|
3908
|
+
CREATE INDEX idx_terminals_kind ON terminals(workspace_id, kind);
|
|
3909
|
+
|
|
3910
|
+
CREATE TABLE sessions (
|
|
3911
|
+
id TEXT PRIMARY KEY,
|
|
3912
|
+
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
3913
|
+
terminal_id TEXT NOT NULL REFERENCES terminals(id) ON DELETE CASCADE,
|
|
3914
|
+
provider_id TEXT NOT NULL,
|
|
3915
|
+
capability TEXT NOT NULL,
|
|
3916
|
+
state TEXT NOT NULL,
|
|
3917
|
+
started_at INTEGER NOT NULL,
|
|
3918
|
+
ended_at INTEGER,
|
|
3919
|
+
last_active_at INTEGER NOT NULL,
|
|
3920
|
+
completion_percent INTEGER,
|
|
3921
|
+
error_reason TEXT,
|
|
3922
|
+
archived BOOLEAN DEFAULT 0,
|
|
3923
|
+
title TEXT
|
|
3924
|
+
);
|
|
3925
|
+
|
|
3926
|
+
CREATE INDEX idx_sessions_workspace ON sessions(workspace_id);
|
|
3927
|
+
CREATE UNIQUE INDEX idx_sessions_terminal ON sessions(terminal_id);
|
|
3928
|
+
CREATE UNIQUE INDEX idx_sessions_id_workspace ON sessions(id, workspace_id);
|
|
3929
|
+
|
|
3930
|
+
CREATE TABLE provider_configs (
|
|
3931
|
+
provider_id TEXT PRIMARY KEY,
|
|
3932
|
+
config TEXT NOT NULL
|
|
3933
|
+
);
|
|
3934
|
+
|
|
3935
|
+
CREATE TABLE user_settings (
|
|
3936
|
+
key TEXT PRIMARY KEY,
|
|
3937
|
+
value TEXT NOT NULL
|
|
3938
|
+
);
|
|
3939
|
+
|
|
3940
|
+
CREATE TABLE auth_sessions (
|
|
3941
|
+
token TEXT PRIMARY KEY,
|
|
3942
|
+
created_at INTEGER NOT NULL,
|
|
3943
|
+
last_seen_at INTEGER NOT NULL
|
|
3944
|
+
);
|
|
3945
|
+
|
|
3946
|
+
CREATE INDEX idx_auth_sessions_last_seen_at ON auth_sessions(last_seen_at);
|
|
3947
|
+
|
|
3948
|
+
CREATE TABLE supervisors (
|
|
3949
|
+
id TEXT PRIMARY KEY,
|
|
3950
|
+
session_id TEXT NOT NULL UNIQUE,
|
|
3951
|
+
workspace_id TEXT NOT NULL,
|
|
3952
|
+
state TEXT NOT NULL,
|
|
3953
|
+
objective TEXT NOT NULL,
|
|
3954
|
+
evaluator_provider_id TEXT NOT NULL,
|
|
3955
|
+
last_cycle_at INTEGER,
|
|
3956
|
+
last_evaluated_turn_id TEXT,
|
|
3957
|
+
error_reason TEXT,
|
|
3958
|
+
created_at INTEGER NOT NULL,
|
|
3959
|
+
updated_at INTEGER NOT NULL,
|
|
3960
|
+
FOREIGN KEY (session_id, workspace_id) REFERENCES sessions(id, workspace_id) ON DELETE CASCADE,
|
|
3961
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
|
|
3962
|
+
);
|
|
3963
|
+
|
|
3964
|
+
CREATE INDEX idx_supervisors_workspace ON supervisors(workspace_id);
|
|
3965
|
+
CREATE INDEX idx_supervisors_session ON supervisors(session_id);
|
|
3966
|
+
CREATE UNIQUE INDEX idx_supervisors_id_session ON supervisors(id, session_id);
|
|
3967
|
+
|
|
3968
|
+
CREATE TABLE supervisor_cycles (
|
|
3969
|
+
id TEXT PRIMARY KEY,
|
|
3970
|
+
supervisor_id TEXT NOT NULL,
|
|
3971
|
+
session_id TEXT NOT NULL,
|
|
3972
|
+
status TEXT NOT NULL,
|
|
3973
|
+
trigger TEXT NOT NULL,
|
|
3974
|
+
evidence_source TEXT NOT NULL,
|
|
3975
|
+
objective TEXT NOT NULL,
|
|
3976
|
+
evaluator_provider_id TEXT NOT NULL,
|
|
3977
|
+
turn_id TEXT,
|
|
3978
|
+
progress INTEGER,
|
|
3979
|
+
result TEXT,
|
|
3980
|
+
injected_guidance TEXT,
|
|
3981
|
+
error_reason TEXT,
|
|
3982
|
+
created_at INTEGER NOT NULL,
|
|
3983
|
+
completed_at INTEGER,
|
|
3984
|
+
FOREIGN KEY (supervisor_id, session_id) REFERENCES supervisors(id, session_id) ON DELETE CASCADE,
|
|
3985
|
+
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
3986
|
+
);
|
|
3987
|
+
|
|
3988
|
+
CREATE INDEX idx_supervisor_cycles_supervisor ON supervisor_cycles(supervisor_id, created_at DESC);
|
|
3989
|
+
CREATE INDEX idx_supervisor_cycles_session ON supervisor_cycles(session_id, created_at DESC);
|
|
3990
|
+
|
|
3991
|
+
CREATE TABLE auth_login_blocks (
|
|
3992
|
+
ip TEXT PRIMARY KEY,
|
|
3993
|
+
failed_count INTEGER NOT NULL,
|
|
3994
|
+
first_failed_at INTEGER NOT NULL,
|
|
3995
|
+
last_failed_at INTEGER NOT NULL,
|
|
3996
|
+
blocked_until INTEGER
|
|
3997
|
+
);
|
|
3998
|
+
|
|
3999
|
+
CREATE INDEX idx_auth_login_blocks_blocked_until ON auth_login_blocks(blocked_until);
|
|
4000
|
+
|
|
4001
|
+
CREATE TABLE auth_login_failures (
|
|
4002
|
+
ip TEXT NOT NULL,
|
|
4003
|
+
failed_at INTEGER NOT NULL
|
|
4004
|
+
);
|
|
4005
|
+
|
|
4006
|
+
CREATE INDEX idx_auth_login_failures_ip_failed_at ON auth_login_failures(ip, failed_at);
|
|
4007
|
+
`;
|
|
4008
|
+
CURRENT_SCHEMA_ENTRIES = buildSchemaEntries(CURRENT_SCHEMA_SQL);
|
|
4009
|
+
V1_SCHEMA_ENTRIES = buildSchemaEntries(V1_SCHEMA_SQL);
|
|
4010
|
+
IncompatibleSchemaError = class extends Error {
|
|
4011
|
+
code = "db_incompatible_schema";
|
|
4012
|
+
constructor(dbPath, mismatch) {
|
|
4013
|
+
super(
|
|
4014
|
+
`db_incompatible_schema: Database schema mismatch detected at ${dbPath}: ${mismatch}. This build requires the current baseline schema. Delete the local database file and restart.`
|
|
4015
|
+
);
|
|
4016
|
+
this.name = "IncompatibleSchemaError";
|
|
4017
|
+
}
|
|
4018
|
+
};
|
|
4019
|
+
}
|
|
4020
|
+
});
|
|
4021
|
+
|
|
4022
|
+
// packages/server/src/storage/db.ts
|
|
4023
|
+
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
3774
4024
|
function hasTable(db, tableName) {
|
|
3775
4025
|
const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(tableName);
|
|
3776
4026
|
return row?.name === tableName;
|
|
@@ -3797,68 +4047,75 @@ function detectLegacySchema(db) {
|
|
|
3797
4047
|
}
|
|
3798
4048
|
return reasons;
|
|
3799
4049
|
}
|
|
3800
|
-
function
|
|
3801
|
-
return `${entry.type}:${entry.name}:${entry.tableName}:${entry.sql}`;
|
|
3802
|
-
}
|
|
3803
|
-
function isSchemaEmpty(db) {
|
|
3804
|
-
return listSchemaEntries(db).length === 0;
|
|
3805
|
-
}
|
|
3806
|
-
function assertNoLegacySchema(db, dbPath) {
|
|
4050
|
+
function throwIfLegacySchema(db, dbPath) {
|
|
3807
4051
|
const reasons = detectLegacySchema(db);
|
|
3808
4052
|
if (reasons.length === 0) {
|
|
3809
4053
|
return;
|
|
3810
4054
|
}
|
|
3811
|
-
throw new
|
|
3812
|
-
`Legacy database schema detected at ${dbPath}: ${reasons.join(", ")}. This build no longer supports automatic database upgrades. Delete the local database file and restart.`
|
|
3813
|
-
);
|
|
3814
|
-
}
|
|
3815
|
-
function describeSchemaMismatch(expected, actual) {
|
|
3816
|
-
const expectedByName = new Map(expected.map((entry) => [`${entry.type}:${entry.name}`, entry]));
|
|
3817
|
-
const actualByName = new Map(actual.map((entry) => [`${entry.type}:${entry.name}`, entry]));
|
|
3818
|
-
const keys = /* @__PURE__ */ new Set([...expectedByName.keys(), ...actualByName.keys()]);
|
|
3819
|
-
for (const key of keys) {
|
|
3820
|
-
const expectedEntry = expectedByName.get(key);
|
|
3821
|
-
const actualEntry = actualByName.get(key);
|
|
3822
|
-
if (!expectedEntry) {
|
|
3823
|
-
return `unexpected ${actualEntry?.type ?? "schema object"} ${actualEntry?.name ?? key}`;
|
|
3824
|
-
}
|
|
3825
|
-
if (!actualEntry) {
|
|
3826
|
-
return `missing ${expectedEntry.type} ${expectedEntry.name}`;
|
|
3827
|
-
}
|
|
3828
|
-
if (schemaEntrySignature(expectedEntry) !== schemaEntrySignature(actualEntry)) {
|
|
3829
|
-
return `definition mismatch for ${expectedEntry.type} ${expectedEntry.name}`;
|
|
3830
|
-
}
|
|
3831
|
-
}
|
|
3832
|
-
return "unknown schema drift";
|
|
3833
|
-
}
|
|
3834
|
-
function assertSchemaMatchesBaseline(db, dbPath) {
|
|
3835
|
-
const actualEntries = listSchemaEntries(db);
|
|
3836
|
-
const expectedSignatures = EXPECTED_SCHEMA_ENTRIES.map(schemaEntrySignature);
|
|
3837
|
-
const actualSignatures = actualEntries.map(schemaEntrySignature);
|
|
3838
|
-
if (actualSignatures.length === expectedSignatures.length && actualSignatures.every((signature, index) => signature === expectedSignatures[index])) {
|
|
3839
|
-
return;
|
|
3840
|
-
}
|
|
3841
|
-
const mismatch = describeSchemaMismatch(EXPECTED_SCHEMA_ENTRIES, actualEntries);
|
|
3842
|
-
throw new Error(
|
|
3843
|
-
`Database schema mismatch detected at ${dbPath}: ${mismatch}. This build requires the current baseline schema. Delete the local database file and restart.`
|
|
3844
|
-
);
|
|
4055
|
+
throw new IncompatibleSchemaError(dbPath, `legacy schema detected (${reasons.join(", ")})`);
|
|
3845
4056
|
}
|
|
3846
4057
|
function initializeSchema(db) {
|
|
3847
4058
|
withTransaction(db, () => {
|
|
3848
|
-
db.exec(
|
|
4059
|
+
db.exec(CURRENT_SCHEMA_SQL);
|
|
3849
4060
|
});
|
|
3850
4061
|
}
|
|
3851
|
-
function
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
4062
|
+
function upgradeSchemaV1ToV2(db) {
|
|
4063
|
+
withTransaction(db, () => {
|
|
4064
|
+
db.exec("ALTER TABLE supervisors ADD COLUMN evaluator_model TEXT");
|
|
4065
|
+
db.exec("ALTER TABLE supervisors ADD COLUMN max_supervision_count INTEGER NOT NULL DEFAULT 0");
|
|
4066
|
+
db.exec(
|
|
4067
|
+
"ALTER TABLE supervisors ADD COLUMN completed_supervision_count INTEGER NOT NULL DEFAULT 0"
|
|
4068
|
+
);
|
|
4069
|
+
db.exec("ALTER TABLE supervisors ADD COLUMN scheduled_at INTEGER");
|
|
4070
|
+
db.exec("ALTER TABLE supervisors ADD COLUMN stop_reason TEXT");
|
|
4071
|
+
db.exec(`
|
|
4072
|
+
CREATE TABLE supervisor_cycle_attempts (
|
|
4073
|
+
id TEXT PRIMARY KEY,
|
|
4074
|
+
cycle_id TEXT NOT NULL REFERENCES supervisor_cycles(id) ON DELETE CASCADE,
|
|
4075
|
+
attempt_index INTEGER NOT NULL,
|
|
4076
|
+
status TEXT NOT NULL,
|
|
4077
|
+
started_at INTEGER NOT NULL,
|
|
4078
|
+
completed_at INTEGER,
|
|
4079
|
+
error_reason TEXT,
|
|
4080
|
+
provider_model TEXT
|
|
4081
|
+
)
|
|
4082
|
+
`);
|
|
4083
|
+
db.exec(
|
|
4084
|
+
"CREATE INDEX idx_supervisor_cycle_attempts_cycle ON supervisor_cycle_attempts(cycle_id, attempt_index)"
|
|
4085
|
+
);
|
|
4086
|
+
stampCurrentSchemaVersion(db);
|
|
4087
|
+
});
|
|
4088
|
+
}
|
|
4089
|
+
function assertCurrentSchema(db, dbPath) {
|
|
4090
|
+
const detection = detectSchema(db);
|
|
4091
|
+
if (detection.state !== "current") {
|
|
4092
|
+
throw new IncompatibleSchemaError(dbPath, detection.mismatch ?? "unknown schema drift");
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
function initializeOrUpgradeSchema(db, dbPath) {
|
|
4096
|
+
throwIfLegacySchema(db, dbPath);
|
|
4097
|
+
const detection = detectSchema(db);
|
|
4098
|
+
switch (detection.state) {
|
|
4099
|
+
case "empty":
|
|
4100
|
+
initializeSchema(db);
|
|
4101
|
+
assertCurrentSchema(db, dbPath);
|
|
4102
|
+
return;
|
|
4103
|
+
case "current":
|
|
4104
|
+
if (detection.userVersion !== CURRENT_SCHEMA_VERSION) {
|
|
4105
|
+
stampCurrentSchemaVersion(db);
|
|
4106
|
+
}
|
|
4107
|
+
assertCurrentSchema(db, dbPath);
|
|
4108
|
+
return;
|
|
4109
|
+
case "v1":
|
|
4110
|
+
upgradeSchemaV1ToV2(db);
|
|
4111
|
+
assertCurrentSchema(db, dbPath);
|
|
4112
|
+
return;
|
|
4113
|
+
case "incompatible":
|
|
4114
|
+
throw new IncompatibleSchemaError(dbPath, detection.mismatch ?? "unknown schema drift");
|
|
3857
4115
|
}
|
|
3858
|
-
assertSchemaMatchesBaseline(db, dbPath);
|
|
3859
4116
|
}
|
|
3860
4117
|
function openDatabase(dbPath) {
|
|
3861
|
-
const db = new
|
|
4118
|
+
const db = new DatabaseSync2(dbPath);
|
|
3862
4119
|
try {
|
|
3863
4120
|
db.exec("PRAGMA journal_mode = WAL");
|
|
3864
4121
|
db.exec("PRAGMA foreign_keys = ON");
|
|
@@ -3866,7 +4123,7 @@ function openDatabase(dbPath) {
|
|
|
3866
4123
|
if (integrityResult[0]?.integrity_check !== "ok") {
|
|
3867
4124
|
throw new Error(`Database integrity check failed: ${JSON.stringify(integrityResult)}`);
|
|
3868
4125
|
}
|
|
3869
|
-
|
|
4126
|
+
initializeOrUpgradeSchema(db, dbPath);
|
|
3870
4127
|
return db;
|
|
3871
4128
|
} catch (error) {
|
|
3872
4129
|
try {
|
|
@@ -3883,16 +4140,14 @@ function closeDatabase(db) {
|
|
|
3883
4140
|
db.close();
|
|
3884
4141
|
}
|
|
3885
4142
|
}
|
|
3886
|
-
var
|
|
4143
|
+
var LEGACY_TABLES, LEGACY_SESSION_COLUMNS;
|
|
3887
4144
|
var init_db = __esm({
|
|
3888
4145
|
"packages/server/src/storage/db.ts"() {
|
|
3889
4146
|
"use strict";
|
|
3890
4147
|
init_database();
|
|
3891
|
-
|
|
3892
|
-
SCHEMA_SQL = readFileSync6(SCHEMA_PATH, "utf-8");
|
|
4148
|
+
init_schema_version();
|
|
3893
4149
|
LEGACY_TABLES = ["hook_registrations", "_migrations"];
|
|
3894
4150
|
LEGACY_SESSION_COLUMNS = ["resume_id", "transcript_path"];
|
|
3895
|
-
EXPECTED_SCHEMA_ENTRIES = buildExpectedSchemaEntries();
|
|
3896
4151
|
}
|
|
3897
4152
|
});
|
|
3898
4153
|
|
|
@@ -4142,6 +4397,93 @@ var init_settings_repo = __esm({
|
|
|
4142
4397
|
}
|
|
4143
4398
|
});
|
|
4144
4399
|
|
|
4400
|
+
// packages/server/src/storage/repositories/supervisor-cycle-attempt-repo.ts
|
|
4401
|
+
var SupervisorCycleAttemptRepo;
|
|
4402
|
+
var init_supervisor_cycle_attempt_repo = __esm({
|
|
4403
|
+
"packages/server/src/storage/repositories/supervisor-cycle-attempt-repo.ts"() {
|
|
4404
|
+
"use strict";
|
|
4405
|
+
SupervisorCycleAttemptRepo = class {
|
|
4406
|
+
constructor(db) {
|
|
4407
|
+
this.db = db;
|
|
4408
|
+
}
|
|
4409
|
+
db;
|
|
4410
|
+
create(input) {
|
|
4411
|
+
this.db.prepare(
|
|
4412
|
+
`INSERT INTO supervisor_cycle_attempts (id, cycle_id, attempt_index, status, started_at, completed_at, error_reason, provider_model)
|
|
4413
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
|
4414
|
+
).run(
|
|
4415
|
+
input.id,
|
|
4416
|
+
input.cycleId,
|
|
4417
|
+
input.attemptIndex,
|
|
4418
|
+
input.status,
|
|
4419
|
+
input.startedAt,
|
|
4420
|
+
input.completedAt ?? null,
|
|
4421
|
+
input.errorReason ?? null,
|
|
4422
|
+
input.providerModel ?? null
|
|
4423
|
+
);
|
|
4424
|
+
return this.findById(input.id);
|
|
4425
|
+
}
|
|
4426
|
+
findById(id) {
|
|
4427
|
+
const row = this.db.prepare("SELECT * FROM supervisor_cycle_attempts WHERE id = ?").get(id);
|
|
4428
|
+
return row ? this.rowToAttempt(row) : void 0;
|
|
4429
|
+
}
|
|
4430
|
+
listForCycle(cycleId) {
|
|
4431
|
+
const rows = this.db.prepare(
|
|
4432
|
+
"SELECT * FROM supervisor_cycle_attempts WHERE cycle_id = ? ORDER BY attempt_index ASC"
|
|
4433
|
+
).all(cycleId);
|
|
4434
|
+
return rows.map((row) => this.rowToAttempt(row));
|
|
4435
|
+
}
|
|
4436
|
+
update(id, patch) {
|
|
4437
|
+
const assignments = [];
|
|
4438
|
+
const params = { id };
|
|
4439
|
+
if (patch.status !== void 0) {
|
|
4440
|
+
assignments.push("status = @status");
|
|
4441
|
+
params.status = patch.status;
|
|
4442
|
+
}
|
|
4443
|
+
if (patch.completedAt !== void 0) {
|
|
4444
|
+
assignments.push("completed_at = @completedAt");
|
|
4445
|
+
params.completedAt = patch.completedAt;
|
|
4446
|
+
}
|
|
4447
|
+
if (patch.errorReason !== void 0) {
|
|
4448
|
+
assignments.push("error_reason = @errorReason");
|
|
4449
|
+
params.errorReason = patch.errorReason;
|
|
4450
|
+
}
|
|
4451
|
+
if (patch.providerModel !== void 0) {
|
|
4452
|
+
assignments.push("provider_model = @providerModel");
|
|
4453
|
+
params.providerModel = patch.providerModel;
|
|
4454
|
+
}
|
|
4455
|
+
if (assignments.length === 0) {
|
|
4456
|
+
const existing = this.findById(id);
|
|
4457
|
+
if (!existing) {
|
|
4458
|
+
throw new Error(`Supervisor cycle attempt not found: ${id}`);
|
|
4459
|
+
}
|
|
4460
|
+
return existing;
|
|
4461
|
+
}
|
|
4462
|
+
const result = this.db.prepare(`UPDATE supervisor_cycle_attempts SET ${assignments.join(", ")} WHERE id = @id`).run(params);
|
|
4463
|
+
if (result.changes === 0) {
|
|
4464
|
+
throw new Error(`Supervisor cycle attempt not found: ${id}`);
|
|
4465
|
+
}
|
|
4466
|
+
return this.findById(id);
|
|
4467
|
+
}
|
|
4468
|
+
deleteForCycle(cycleId) {
|
|
4469
|
+
this.db.prepare("DELETE FROM supervisor_cycle_attempts WHERE cycle_id = ?").run(cycleId);
|
|
4470
|
+
}
|
|
4471
|
+
rowToAttempt(row) {
|
|
4472
|
+
return {
|
|
4473
|
+
id: row.id,
|
|
4474
|
+
cycleId: row.cycle_id,
|
|
4475
|
+
attemptIndex: row.attempt_index,
|
|
4476
|
+
status: row.status,
|
|
4477
|
+
startedAt: row.started_at,
|
|
4478
|
+
completedAt: row.completed_at ?? void 0,
|
|
4479
|
+
errorReason: row.error_reason ?? void 0,
|
|
4480
|
+
providerModel: row.provider_model ?? void 0
|
|
4481
|
+
};
|
|
4482
|
+
}
|
|
4483
|
+
};
|
|
4484
|
+
}
|
|
4485
|
+
});
|
|
4486
|
+
|
|
4145
4487
|
// packages/server/src/storage/repositories/supervisor-cycle-repo.ts
|
|
4146
4488
|
var SupervisorCycleRepo;
|
|
4147
4489
|
var init_supervisor_cycle_repo = __esm({
|
|
@@ -4271,8 +4613,8 @@ var init_supervisor_repo = __esm({
|
|
|
4271
4613
|
db;
|
|
4272
4614
|
create(input) {
|
|
4273
4615
|
this.db.prepare(
|
|
4274
|
-
`INSERT INTO supervisors (id, session_id, workspace_id, state, objective, evaluator_provider_id, last_cycle_at, last_evaluated_turn_id, error_reason, created_at, updated_at)
|
|
4275
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
4616
|
+
`INSERT INTO supervisors (id, session_id, workspace_id, state, objective, evaluator_provider_id, evaluator_model, max_supervision_count, completed_supervision_count, scheduled_at, stop_reason, last_cycle_at, last_evaluated_turn_id, error_reason, created_at, updated_at)
|
|
4617
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
4276
4618
|
).run(
|
|
4277
4619
|
input.id,
|
|
4278
4620
|
input.sessionId,
|
|
@@ -4280,6 +4622,11 @@ var init_supervisor_repo = __esm({
|
|
|
4280
4622
|
input.state,
|
|
4281
4623
|
input.objective,
|
|
4282
4624
|
input.evaluatorProviderId,
|
|
4625
|
+
input.evaluatorModel ?? null,
|
|
4626
|
+
input.maxSupervisionCount ?? 0,
|
|
4627
|
+
input.completedSupervisionCount ?? 0,
|
|
4628
|
+
input.scheduledAt ?? null,
|
|
4629
|
+
input.stopReason ?? null,
|
|
4283
4630
|
input.lastCycleAt ?? null,
|
|
4284
4631
|
input.lastEvaluatedTurnId ?? null,
|
|
4285
4632
|
input.errorReason ?? null,
|
|
@@ -4318,6 +4665,26 @@ var init_supervisor_repo = __esm({
|
|
|
4318
4665
|
assignments.push("evaluator_provider_id = @evaluatorProviderId");
|
|
4319
4666
|
params.evaluatorProviderId = patch.evaluatorProviderId;
|
|
4320
4667
|
}
|
|
4668
|
+
if (patch.evaluatorModel !== void 0) {
|
|
4669
|
+
assignments.push("evaluator_model = @evaluatorModel");
|
|
4670
|
+
params.evaluatorModel = patch.evaluatorModel;
|
|
4671
|
+
}
|
|
4672
|
+
if (patch.maxSupervisionCount !== void 0) {
|
|
4673
|
+
assignments.push("max_supervision_count = @maxSupervisionCount");
|
|
4674
|
+
params.maxSupervisionCount = patch.maxSupervisionCount;
|
|
4675
|
+
}
|
|
4676
|
+
if (patch.completedSupervisionCount !== void 0) {
|
|
4677
|
+
assignments.push("completed_supervision_count = @completedSupervisionCount");
|
|
4678
|
+
params.completedSupervisionCount = patch.completedSupervisionCount;
|
|
4679
|
+
}
|
|
4680
|
+
if (patch.scheduledAt !== void 0) {
|
|
4681
|
+
assignments.push("scheduled_at = @scheduledAt");
|
|
4682
|
+
params.scheduledAt = patch.scheduledAt;
|
|
4683
|
+
}
|
|
4684
|
+
if (patch.stopReason !== void 0) {
|
|
4685
|
+
assignments.push("stop_reason = @stopReason");
|
|
4686
|
+
params.stopReason = patch.stopReason;
|
|
4687
|
+
}
|
|
4321
4688
|
if (patch.lastCycleAt !== void 0) {
|
|
4322
4689
|
assignments.push("last_cycle_at = @lastCycleAt");
|
|
4323
4690
|
params.lastCycleAt = patch.lastCycleAt;
|
|
@@ -4347,6 +4714,11 @@ var init_supervisor_repo = __esm({
|
|
|
4347
4714
|
state: row.state,
|
|
4348
4715
|
objective: row.objective,
|
|
4349
4716
|
evaluatorProviderId: row.evaluator_provider_id,
|
|
4717
|
+
evaluatorModel: row.evaluator_model ?? void 0,
|
|
4718
|
+
maxSupervisionCount: row.max_supervision_count,
|
|
4719
|
+
completedSupervisionCount: row.completed_supervision_count,
|
|
4720
|
+
scheduledAt: row.scheduled_at ?? void 0,
|
|
4721
|
+
stopReason: row.stop_reason ?? void 0,
|
|
4350
4722
|
cycles: [],
|
|
4351
4723
|
lastCycleAt: row.last_cycle_at ?? void 0,
|
|
4352
4724
|
lastEvaluatedTurnId: row.last_evaluated_turn_id ?? void 0,
|
|
@@ -5364,7 +5736,7 @@ var init_context_builder = __esm({
|
|
|
5364
5736
|
});
|
|
5365
5737
|
|
|
5366
5738
|
// packages/server/src/terminal/pty-host.ts
|
|
5367
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
5739
|
+
import { chmodSync as chmodSync2, existsSync as existsSync4, statSync } from "node:fs";
|
|
5368
5740
|
import { createRequire } from "node:module";
|
|
5369
5741
|
import path6 from "node:path";
|
|
5370
5742
|
function ensureNodePtySpawnHelperExecutable(deps = {}) {
|
|
@@ -5374,7 +5746,7 @@ function ensureNodePtySpawnHelperExecutable(deps = {}) {
|
|
|
5374
5746
|
}
|
|
5375
5747
|
const arch = deps.arch ?? process.arch;
|
|
5376
5748
|
const resolve4 = deps.resolve ?? ((id) => require2.resolve(id));
|
|
5377
|
-
const fileExists = deps.existsSync ??
|
|
5749
|
+
const fileExists = deps.existsSync ?? existsSync4;
|
|
5378
5750
|
const stat7 = deps.statSync ?? statSync;
|
|
5379
5751
|
const chmod = deps.chmodSync ?? chmodSync2;
|
|
5380
5752
|
let packageJsonPath;
|
|
@@ -5534,12 +5906,63 @@ function getSupervisorEvaluationTimeoutMs(settingsRepo) {
|
|
|
5534
5906
|
const timeoutSec = resolveSupervisorEvaluationTimeoutSec(storedValue);
|
|
5535
5907
|
return timeoutSec * 1e3;
|
|
5536
5908
|
}
|
|
5537
|
-
|
|
5909
|
+
function getSettingOrDefault(settingsRepo, key, fallback) {
|
|
5910
|
+
try {
|
|
5911
|
+
return settingsRepo?.get(key) ?? fallback;
|
|
5912
|
+
} catch {
|
|
5913
|
+
return fallback;
|
|
5914
|
+
}
|
|
5915
|
+
}
|
|
5916
|
+
function getSupervisorRetrySettings(settingsRepo) {
|
|
5917
|
+
return {
|
|
5918
|
+
retryEnabled: resolveSupervisorRetryEnabled(
|
|
5919
|
+
getSettingOrDefault(
|
|
5920
|
+
settingsRepo,
|
|
5921
|
+
SUPERVISOR_RETRY_ENABLED_SETTING_KEY,
|
|
5922
|
+
DEFAULT_SUPERVISOR_RETRY_ENABLED
|
|
5923
|
+
)
|
|
5924
|
+
),
|
|
5925
|
+
retryMaxCount: resolveSupervisorRetryMaxCount(
|
|
5926
|
+
getSettingOrDefault(
|
|
5927
|
+
settingsRepo,
|
|
5928
|
+
SUPERVISOR_RETRY_MAX_COUNT_SETTING_KEY,
|
|
5929
|
+
DEFAULT_SUPERVISOR_RETRY_MAX_COUNT
|
|
5930
|
+
)
|
|
5931
|
+
),
|
|
5932
|
+
retryDelaySec: resolveSupervisorRetryDelaySec(
|
|
5933
|
+
getSettingOrDefault(
|
|
5934
|
+
settingsRepo,
|
|
5935
|
+
SUPERVISOR_RETRY_DELAY_SEC_SETTING_KEY,
|
|
5936
|
+
DEFAULT_SUPERVISOR_RETRY_DELAY_SEC
|
|
5937
|
+
)
|
|
5938
|
+
),
|
|
5939
|
+
retryOnTimeout: resolveSupervisorRetryOnTimeout(
|
|
5940
|
+
getSettingOrDefault(
|
|
5941
|
+
settingsRepo,
|
|
5942
|
+
SUPERVISOR_RETRY_ON_TIMEOUT_SETTING_KEY,
|
|
5943
|
+
DEFAULT_SUPERVISOR_RETRY_ON_TIMEOUT
|
|
5944
|
+
)
|
|
5945
|
+
),
|
|
5946
|
+
retryOnEvaluatorError: resolveSupervisorRetryOnEvaluatorError(
|
|
5947
|
+
getSettingOrDefault(
|
|
5948
|
+
settingsRepo,
|
|
5949
|
+
SUPERVISOR_RETRY_ON_EVALUATOR_ERROR_SETTING_KEY,
|
|
5950
|
+
DEFAULT_SUPERVISOR_RETRY_ON_EVALUATOR_ERROR
|
|
5951
|
+
)
|
|
5952
|
+
)
|
|
5953
|
+
};
|
|
5954
|
+
}
|
|
5955
|
+
var SUPERVISOR_EVALUATION_TIMEOUT_SETTING_KEY, SUPERVISOR_RETRY_ENABLED_SETTING_KEY, SUPERVISOR_RETRY_MAX_COUNT_SETTING_KEY, SUPERVISOR_RETRY_DELAY_SEC_SETTING_KEY, SUPERVISOR_RETRY_ON_TIMEOUT_SETTING_KEY, SUPERVISOR_RETRY_ON_EVALUATOR_ERROR_SETTING_KEY;
|
|
5538
5956
|
var init_settings = __esm({
|
|
5539
5957
|
"packages/server/src/supervisor/settings.ts"() {
|
|
5540
5958
|
"use strict";
|
|
5541
5959
|
init_src3();
|
|
5542
5960
|
SUPERVISOR_EVALUATION_TIMEOUT_SETTING_KEY = "supervisor.evaluationTimeoutSec";
|
|
5961
|
+
SUPERVISOR_RETRY_ENABLED_SETTING_KEY = "supervisor.retryEnabled";
|
|
5962
|
+
SUPERVISOR_RETRY_MAX_COUNT_SETTING_KEY = "supervisor.retryMaxCount";
|
|
5963
|
+
SUPERVISOR_RETRY_DELAY_SEC_SETTING_KEY = "supervisor.retryDelaySec";
|
|
5964
|
+
SUPERVISOR_RETRY_ON_TIMEOUT_SETTING_KEY = "supervisor.retryOnTimeout";
|
|
5965
|
+
SUPERVISOR_RETRY_ON_EVALUATOR_ERROR_SETTING_KEY = "supervisor.retryOnEvaluatorError";
|
|
5543
5966
|
}
|
|
5544
5967
|
});
|
|
5545
5968
|
|
|
@@ -5761,6 +6184,12 @@ function extractSupervisorMessage(output, providerId) {
|
|
|
5761
6184
|
}
|
|
5762
6185
|
const lines = trimmed.split(/\r?\n/).filter(Boolean);
|
|
5763
6186
|
if (providerId === "codex") {
|
|
6187
|
+
if (trimmed === "[objective complete]") {
|
|
6188
|
+
return trimmed;
|
|
6189
|
+
}
|
|
6190
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
|
|
6191
|
+
return stripCodeFence(trimmed);
|
|
6192
|
+
}
|
|
5764
6193
|
const scan = scanCodexStream(lines);
|
|
5765
6194
|
if (scan.turnFailure) {
|
|
5766
6195
|
throw new Error(`Supervisor (codex) failed: ${scan.turnFailure}`);
|
|
@@ -5862,7 +6291,7 @@ var init_evaluator = __esm({
|
|
|
5862
6291
|
prompt,
|
|
5863
6292
|
sessionId: supervisor.sessionId,
|
|
5864
6293
|
workspacePath: context.workspacePath,
|
|
5865
|
-
model: typeof config.model === "string" ? config.model : void 0
|
|
6294
|
+
model: typeof supervisor.evaluatorModel === "string" && supervisor.evaluatorModel.trim() ? supervisor.evaluatorModel.trim() : typeof config.model === "string" ? config.model : void 0
|
|
5866
6295
|
});
|
|
5867
6296
|
if (!command) {
|
|
5868
6297
|
throw {
|
|
@@ -5891,7 +6320,11 @@ var init_evaluator = __esm({
|
|
|
5891
6320
|
);
|
|
5892
6321
|
throw error;
|
|
5893
6322
|
}
|
|
5894
|
-
|
|
6323
|
+
const normalizedMessage = message.slice(0, this.config.guidanceMaxChars);
|
|
6324
|
+
return {
|
|
6325
|
+
message: normalizedMessage,
|
|
6326
|
+
objectiveComplete: normalizedMessage.trim() === "[objective complete]"
|
|
6327
|
+
};
|
|
5895
6328
|
}
|
|
5896
6329
|
};
|
|
5897
6330
|
}
|
|
@@ -5927,7 +6360,13 @@ var init_injector = __esm({
|
|
|
5927
6360
|
}
|
|
5928
6361
|
deps;
|
|
5929
6362
|
config;
|
|
5930
|
-
async inject(supervisor, input, recentCycles) {
|
|
6363
|
+
async inject(supervisor, input, recentCycles, options = {}) {
|
|
6364
|
+
if (options.signal?.aborted) {
|
|
6365
|
+
throw {
|
|
6366
|
+
code: "supervisor_eval_aborted",
|
|
6367
|
+
message: "Supervisor evaluator aborted"
|
|
6368
|
+
};
|
|
6369
|
+
}
|
|
5931
6370
|
const session = this.deps.sessionMgr.get(supervisor.sessionId);
|
|
5932
6371
|
if (!session) {
|
|
5933
6372
|
throw {
|
|
@@ -5948,6 +6387,12 @@ var init_injector = __esm({
|
|
|
5948
6387
|
if (duplicate) {
|
|
5949
6388
|
return { injected: false, text };
|
|
5950
6389
|
}
|
|
6390
|
+
if (options.signal?.aborted) {
|
|
6391
|
+
throw {
|
|
6392
|
+
code: "supervisor_eval_aborted",
|
|
6393
|
+
message: "Supervisor evaluator aborted"
|
|
6394
|
+
};
|
|
6395
|
+
}
|
|
5951
6396
|
const BRACKETED_PASTE_START = "\x1B[200~";
|
|
5952
6397
|
const BRACKETED_PASTE_END = "\x1B[201~";
|
|
5953
6398
|
const SUBMIT = "\r";
|
|
@@ -5970,6 +6415,9 @@ var init_scheduler = __esm({
|
|
|
5970
6415
|
}
|
|
5971
6416
|
deps;
|
|
5972
6417
|
unsubscribe = null;
|
|
6418
|
+
scheduledTimer = null;
|
|
6419
|
+
scheduledRetryDelayMs = 1e3;
|
|
6420
|
+
retryAtBySupervisorId = /* @__PURE__ */ new Map();
|
|
5973
6421
|
start() {
|
|
5974
6422
|
this.unsubscribe?.();
|
|
5975
6423
|
this.unsubscribe = this.deps.eventBus.on(
|
|
@@ -5982,9 +6430,64 @@ var init_scheduler = __esm({
|
|
|
5982
6430
|
}
|
|
5983
6431
|
);
|
|
5984
6432
|
}
|
|
6433
|
+
refresh() {
|
|
6434
|
+
this.clearScheduledTimer();
|
|
6435
|
+
const scheduled = this.deps.listScheduledSupervisors?.() ?? [];
|
|
6436
|
+
this.pruneRetryState(scheduled);
|
|
6437
|
+
if (scheduled.length === 0) {
|
|
6438
|
+
return;
|
|
6439
|
+
}
|
|
6440
|
+
const now = Date.now();
|
|
6441
|
+
const nextAt = scheduled.reduce((earliest, item) => {
|
|
6442
|
+
const candidate = this.getNextAttemptAt(item, now);
|
|
6443
|
+
return candidate < earliest ? candidate : earliest;
|
|
6444
|
+
}, Number.POSITIVE_INFINITY);
|
|
6445
|
+
if (!Number.isFinite(nextAt)) {
|
|
6446
|
+
return;
|
|
6447
|
+
}
|
|
6448
|
+
const delayMs = Math.max(nextAt - now, 0);
|
|
6449
|
+
this.scheduledTimer = setTimeout(() => {
|
|
6450
|
+
this.scheduledTimer = null;
|
|
6451
|
+
const current = this.deps.listScheduledSupervisors?.() ?? [];
|
|
6452
|
+
this.pruneRetryState(current);
|
|
6453
|
+
const dueAt = Date.now();
|
|
6454
|
+
const due = current.filter(
|
|
6455
|
+
(item) => item.scheduledAt <= dueAt && (this.retryAtBySupervisorId.get(item.supervisorId) ?? Number.NEGATIVE_INFINITY) <= dueAt
|
|
6456
|
+
);
|
|
6457
|
+
for (const item of due) {
|
|
6458
|
+
this.retryAtBySupervisorId.set(item.supervisorId, dueAt + this.scheduledRetryDelayMs);
|
|
6459
|
+
this.deps.onScheduledDue?.(item.supervisorId);
|
|
6460
|
+
}
|
|
6461
|
+
this.refresh();
|
|
6462
|
+
}, delayMs);
|
|
6463
|
+
this.scheduledTimer.unref?.();
|
|
6464
|
+
}
|
|
5985
6465
|
stop() {
|
|
5986
6466
|
this.unsubscribe?.();
|
|
5987
6467
|
this.unsubscribe = null;
|
|
6468
|
+
this.clearScheduledTimer();
|
|
6469
|
+
this.retryAtBySupervisorId.clear();
|
|
6470
|
+
}
|
|
6471
|
+
clearScheduledTimer() {
|
|
6472
|
+
if (this.scheduledTimer) {
|
|
6473
|
+
clearTimeout(this.scheduledTimer);
|
|
6474
|
+
this.scheduledTimer = null;
|
|
6475
|
+
}
|
|
6476
|
+
}
|
|
6477
|
+
getNextAttemptAt(item, now) {
|
|
6478
|
+
if (item.scheduledAt > now) {
|
|
6479
|
+
return item.scheduledAt;
|
|
6480
|
+
}
|
|
6481
|
+
const retryAt = this.retryAtBySupervisorId.get(item.supervisorId);
|
|
6482
|
+
return retryAt && retryAt > now ? retryAt : item.scheduledAt;
|
|
6483
|
+
}
|
|
6484
|
+
pruneRetryState(scheduled) {
|
|
6485
|
+
const scheduledIds = new Set(scheduled.map((item) => item.supervisorId));
|
|
6486
|
+
for (const supervisorId of this.retryAtBySupervisorId.keys()) {
|
|
6487
|
+
if (!scheduledIds.has(supervisorId)) {
|
|
6488
|
+
this.retryAtBySupervisorId.delete(supervisorId);
|
|
6489
|
+
}
|
|
6490
|
+
}
|
|
5988
6491
|
}
|
|
5989
6492
|
};
|
|
5990
6493
|
}
|
|
@@ -6005,6 +6508,9 @@ function generateSupervisorId() {
|
|
|
6005
6508
|
function generateCycleId() {
|
|
6006
6509
|
return `cycle_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
6007
6510
|
}
|
|
6511
|
+
function generateAttemptId() {
|
|
6512
|
+
return `attempt_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
6513
|
+
}
|
|
6008
6514
|
function messageOf(error, fallback) {
|
|
6009
6515
|
if (error instanceof Error) {
|
|
6010
6516
|
return error.message;
|
|
@@ -6032,6 +6538,7 @@ var init_manager2 = __esm({
|
|
|
6032
6538
|
init_evaluator();
|
|
6033
6539
|
init_injector();
|
|
6034
6540
|
init_scheduler();
|
|
6541
|
+
init_settings();
|
|
6035
6542
|
NOOP_LOGGER3 = {
|
|
6036
6543
|
child: () => NOOP_LOGGER3,
|
|
6037
6544
|
debug: () => {
|
|
@@ -6060,7 +6567,8 @@ var init_manager2 = __esm({
|
|
|
6060
6567
|
sessionMgr: deps.sessionMgr,
|
|
6061
6568
|
terminalMgr: deps.terminalMgr,
|
|
6062
6569
|
providerRegistry: deps.providerRegistry,
|
|
6063
|
-
logger: this.logger
|
|
6570
|
+
logger: this.logger,
|
|
6571
|
+
git: deps.git
|
|
6064
6572
|
});
|
|
6065
6573
|
this.evaluator = new SupervisorEvaluator({
|
|
6066
6574
|
providerRegistry: deps.providerRegistry,
|
|
@@ -6079,10 +6587,19 @@ var init_manager2 = __esm({
|
|
|
6079
6587
|
onTurnCompleted: (sessionId) => {
|
|
6080
6588
|
const supervisorId = this.supervisorsBySession.get(sessionId);
|
|
6081
6589
|
if (supervisorId) {
|
|
6082
|
-
void this.runEvaluation(supervisorId).catch((error) => {
|
|
6590
|
+
void this.runEvaluation(supervisorId, "turn_completed").catch((error) => {
|
|
6083
6591
|
this.logger.warn({ err: error, supervisorId }, "Supervisor auto-evaluation failed");
|
|
6084
6592
|
});
|
|
6085
6593
|
}
|
|
6594
|
+
},
|
|
6595
|
+
listScheduledSupervisors: () => this.listScheduledSupervisors(),
|
|
6596
|
+
onScheduledDue: (supervisorId) => {
|
|
6597
|
+
void this.runEvaluation(supervisorId, "scheduled").catch((error) => {
|
|
6598
|
+
this.logger.warn(
|
|
6599
|
+
{ err: error, supervisorId },
|
|
6600
|
+
"Supervisor scheduled auto-evaluation failed"
|
|
6601
|
+
);
|
|
6602
|
+
});
|
|
6086
6603
|
}
|
|
6087
6604
|
});
|
|
6088
6605
|
}
|
|
@@ -6091,6 +6608,7 @@ var init_manager2 = __esm({
|
|
|
6091
6608
|
supervisorsBySession = /* @__PURE__ */ new Map();
|
|
6092
6609
|
inFlight = /* @__PURE__ */ new Set();
|
|
6093
6610
|
pendingDeletes = /* @__PURE__ */ new Set();
|
|
6611
|
+
pendingPauses = /* @__PURE__ */ new Set();
|
|
6094
6612
|
evaluationAbortControllers = /* @__PURE__ */ new Map();
|
|
6095
6613
|
inFlightCompletions = /* @__PURE__ */ new Map();
|
|
6096
6614
|
scheduler;
|
|
@@ -6143,6 +6661,7 @@ var init_manager2 = __esm({
|
|
|
6143
6661
|
}
|
|
6144
6662
|
);
|
|
6145
6663
|
this.scheduler.start();
|
|
6664
|
+
this.scheduler.refresh();
|
|
6146
6665
|
}
|
|
6147
6666
|
stop() {
|
|
6148
6667
|
this.scheduler.stop();
|
|
@@ -6214,12 +6733,17 @@ var init_manager2 = __esm({
|
|
|
6214
6733
|
state: "idle",
|
|
6215
6734
|
objective: req.objective.trim(),
|
|
6216
6735
|
evaluatorProviderId: req.evaluatorProviderId,
|
|
6736
|
+
evaluatorModel: req.evaluatorModel?.trim() || void 0,
|
|
6737
|
+
maxSupervisionCount: req.maxSupervisionCount ?? 0,
|
|
6738
|
+
completedSupervisionCount: 0,
|
|
6739
|
+
scheduledAt: req.scheduledAt,
|
|
6217
6740
|
createdAt: now,
|
|
6218
6741
|
updatedAt: now
|
|
6219
6742
|
})
|
|
6220
6743
|
);
|
|
6221
6744
|
this.storeSnapshot(supervisor);
|
|
6222
6745
|
this.broadcastState(supervisor, "created");
|
|
6746
|
+
this.scheduler.refresh();
|
|
6223
6747
|
return supervisor;
|
|
6224
6748
|
}
|
|
6225
6749
|
async update(id, patch) {
|
|
@@ -6231,6 +6755,9 @@ var init_manager2 = __esm({
|
|
|
6231
6755
|
this.deps.supervisorRepo.update(id, {
|
|
6232
6756
|
objective: patch.objective !== void 0 ? patch.objective.trim() : current.objective,
|
|
6233
6757
|
evaluatorProviderId: patch.evaluatorProviderId ?? current.evaluatorProviderId,
|
|
6758
|
+
evaluatorModel: patch.evaluatorModel === void 0 ? current.evaluatorModel : patch.evaluatorModel?.trim() || null,
|
|
6759
|
+
maxSupervisionCount: patch.maxSupervisionCount ?? current.maxSupervisionCount,
|
|
6760
|
+
scheduledAt: patch.scheduledAt === void 0 ? current.scheduledAt : patch.scheduledAt,
|
|
6234
6761
|
state: current.state === "error" ? "idle" : current.state,
|
|
6235
6762
|
errorReason: null,
|
|
6236
6763
|
updatedAt: Date.now()
|
|
@@ -6238,9 +6765,14 @@ var init_manager2 = __esm({
|
|
|
6238
6765
|
);
|
|
6239
6766
|
this.storeSnapshot(updated);
|
|
6240
6767
|
this.broadcastState(updated, "updated");
|
|
6768
|
+
this.scheduler.refresh();
|
|
6241
6769
|
return updated;
|
|
6242
6770
|
}
|
|
6243
6771
|
async pause(id) {
|
|
6772
|
+
if (this.inFlight.has(id)) {
|
|
6773
|
+
this.pendingPauses.add(id);
|
|
6774
|
+
this.evaluationAbortControllers.get(id)?.abort();
|
|
6775
|
+
}
|
|
6244
6776
|
const updated = this.attachCycles(
|
|
6245
6777
|
this.deps.supervisorRepo.update(id, {
|
|
6246
6778
|
state: "paused",
|
|
@@ -6249,6 +6781,7 @@ var init_manager2 = __esm({
|
|
|
6249
6781
|
);
|
|
6250
6782
|
this.storeSnapshot(updated);
|
|
6251
6783
|
this.broadcastState(updated, "state_changed");
|
|
6784
|
+
this.scheduler.refresh();
|
|
6252
6785
|
return updated;
|
|
6253
6786
|
}
|
|
6254
6787
|
async resume(id) {
|
|
@@ -6261,6 +6794,7 @@ var init_manager2 = __esm({
|
|
|
6261
6794
|
);
|
|
6262
6795
|
this.storeSnapshot(updated);
|
|
6263
6796
|
this.broadcastState(updated, "state_changed");
|
|
6797
|
+
this.scheduler.refresh();
|
|
6264
6798
|
return updated;
|
|
6265
6799
|
}
|
|
6266
6800
|
async delete(id) {
|
|
@@ -6269,6 +6803,7 @@ var init_manager2 = __esm({
|
|
|
6269
6803
|
this.pendingDeletes.add(id);
|
|
6270
6804
|
this.evaluationAbortControllers.get(id)?.abort();
|
|
6271
6805
|
await this.inFlightCompletions.get(id)?.promise;
|
|
6806
|
+
this.scheduler.refresh();
|
|
6272
6807
|
return;
|
|
6273
6808
|
}
|
|
6274
6809
|
this.deleteNow(supervisor);
|
|
@@ -6302,8 +6837,8 @@ var init_manager2 = __esm({
|
|
|
6302
6837
|
* auto trigger path (scheduler) and for tests that want to observe the
|
|
6303
6838
|
* final cycle outcome.
|
|
6304
6839
|
*/
|
|
6305
|
-
async runEvaluation(supervisorId) {
|
|
6306
|
-
const started = await this.beginCycle(supervisorId,
|
|
6840
|
+
async runEvaluation(supervisorId, trigger = "turn_completed") {
|
|
6841
|
+
const started = await this.beginCycle(supervisorId, trigger);
|
|
6307
6842
|
if (!started) {
|
|
6308
6843
|
return null;
|
|
6309
6844
|
}
|
|
@@ -6347,9 +6882,41 @@ var init_manager2 = __esm({
|
|
|
6347
6882
|
}
|
|
6348
6883
|
return null;
|
|
6349
6884
|
}
|
|
6350
|
-
if (
|
|
6885
|
+
if (supervisor.state === "stopped") {
|
|
6886
|
+
if (trigger === "manual") {
|
|
6887
|
+
throw {
|
|
6888
|
+
code: "supervisor_stopped",
|
|
6889
|
+
message: `Supervisor ${id} is stopped`
|
|
6890
|
+
};
|
|
6891
|
+
}
|
|
6892
|
+
return null;
|
|
6893
|
+
}
|
|
6894
|
+
if ((trigger === "turn_completed" || trigger === "scheduled") && (supervisor.state !== "idle" || session.state !== "running" && session.state !== "idle")) {
|
|
6895
|
+
return null;
|
|
6896
|
+
}
|
|
6897
|
+
if (supervisor.maxSupervisionCount > 0 && supervisor.completedSupervisionCount >= supervisor.maxSupervisionCount) {
|
|
6898
|
+
const stopped = this.attachCycles(
|
|
6899
|
+
this.deps.supervisorRepo.update(id, {
|
|
6900
|
+
state: "stopped",
|
|
6901
|
+
stopReason: "max_supervision_count_reached",
|
|
6902
|
+
updatedAt: Date.now()
|
|
6903
|
+
})
|
|
6904
|
+
);
|
|
6905
|
+
this.storeSnapshot(stopped);
|
|
6906
|
+
this.broadcastState(stopped, "state_changed");
|
|
6907
|
+
this.scheduler.refresh();
|
|
6351
6908
|
return null;
|
|
6352
6909
|
}
|
|
6910
|
+
if (trigger === "turn_completed") {
|
|
6911
|
+
if (supervisor.scheduledAt !== void 0 && supervisor.scheduledAt !== null && supervisor.scheduledAt > Date.now()) {
|
|
6912
|
+
return null;
|
|
6913
|
+
}
|
|
6914
|
+
}
|
|
6915
|
+
if (trigger === "scheduled") {
|
|
6916
|
+
if (supervisor.scheduledAt === void 0 || supervisor.scheduledAt > Date.now()) {
|
|
6917
|
+
return null;
|
|
6918
|
+
}
|
|
6919
|
+
}
|
|
6353
6920
|
if (trigger === "manual" && !INJECTABLE_SESSION_STATES.has(session.state)) {
|
|
6354
6921
|
throw {
|
|
6355
6922
|
code: "supervisor_session_not_ready",
|
|
@@ -6360,20 +6927,25 @@ var init_manager2 = __esm({
|
|
|
6360
6927
|
this.evaluationAbortControllers.set(id, new AbortController());
|
|
6361
6928
|
this.inFlightCompletions.set(id, createDeferredCompletion());
|
|
6362
6929
|
try {
|
|
6930
|
+
const retrySettings = getSupervisorRetrySettings(this.deps.settingsRepo);
|
|
6363
6931
|
const context = await this.contextBuilder.build(supervisor);
|
|
6364
6932
|
if (trigger === "turn_completed" && context.lastTurnId && context.lastTurnId === supervisor.lastEvaluatedTurnId) {
|
|
6365
6933
|
this.releaseInFlight(id);
|
|
6366
6934
|
return null;
|
|
6367
6935
|
}
|
|
6936
|
+
const shouldConsumeScheduledAt = trigger === "scheduled" || trigger === "turn_completed" && supervisor.scheduledAt !== void 0 && supervisor.scheduledAt !== null && supervisor.scheduledAt <= Date.now();
|
|
6368
6937
|
const evaluatingSupervisor = this.attachCycles(
|
|
6369
6938
|
this.deps.supervisorRepo.update(supervisor.id, {
|
|
6370
6939
|
state: "evaluating",
|
|
6940
|
+
scheduledAt: shouldConsumeScheduledAt ? null : supervisor.scheduledAt ?? void 0,
|
|
6941
|
+
stopReason: null,
|
|
6371
6942
|
errorReason: null,
|
|
6372
6943
|
updatedAt: Date.now()
|
|
6373
6944
|
})
|
|
6374
6945
|
);
|
|
6375
6946
|
this.storeSnapshot(evaluatingSupervisor);
|
|
6376
6947
|
this.broadcastState(evaluatingSupervisor, "state_changed");
|
|
6948
|
+
this.scheduler.refresh();
|
|
6377
6949
|
const activeCycle = this.deps.cycleRepo.create({
|
|
6378
6950
|
id: generateCycleId(),
|
|
6379
6951
|
supervisorId: supervisor.id,
|
|
@@ -6387,7 +6959,18 @@ var init_manager2 = __esm({
|
|
|
6387
6959
|
createdAt: Date.now()
|
|
6388
6960
|
});
|
|
6389
6961
|
this.broadcastCycle(evaluatingSupervisor, activeCycle, "created");
|
|
6390
|
-
return {
|
|
6962
|
+
return {
|
|
6963
|
+
cycle: activeCycle,
|
|
6964
|
+
context,
|
|
6965
|
+
trigger,
|
|
6966
|
+
retry: {
|
|
6967
|
+
retryEnabled: retrySettings.retryEnabled,
|
|
6968
|
+
retryMaxCount: retrySettings.retryMaxCount,
|
|
6969
|
+
retryDelayMs: retrySettings.retryDelaySec * 1e3,
|
|
6970
|
+
retryOnTimeout: retrySettings.retryOnTimeout,
|
|
6971
|
+
retryOnEvaluatorError: retrySettings.retryOnEvaluatorError
|
|
6972
|
+
}
|
|
6973
|
+
};
|
|
6391
6974
|
} catch (error) {
|
|
6392
6975
|
this.releaseInFlight(id);
|
|
6393
6976
|
this.markSupervisorError(id, error);
|
|
@@ -6404,75 +6987,20 @@ var init_manager2 = __esm({
|
|
|
6404
6987
|
const supervisorId = activeCycle.supervisorId;
|
|
6405
6988
|
try {
|
|
6406
6989
|
const supervisorForEval = this.supervisors.get(supervisorId) ?? this.requireSupervisor(supervisorId);
|
|
6407
|
-
const
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
let injected = false;
|
|
6411
|
-
let injectedText;
|
|
6412
|
-
let cycleResult;
|
|
6413
|
-
let injectionError;
|
|
6414
|
-
if (evaluation.message.trim()) {
|
|
6415
|
-
const injectingSupervisor = this.attachCycles(
|
|
6416
|
-
this.deps.supervisorRepo.update(supervisorId, {
|
|
6417
|
-
state: "injecting",
|
|
6418
|
-
updatedAt: Date.now()
|
|
6419
|
-
})
|
|
6420
|
-
);
|
|
6421
|
-
this.storeSnapshot(injectingSupervisor);
|
|
6422
|
-
this.broadcastState(injectingSupervisor, "state_changed");
|
|
6423
|
-
const recentCycles = this.deps.cycleRepo.listRecentForSupervisor(supervisorId, this.config.guidanceDedupeWindow + 1).filter((cycle) => cycle.id !== activeCycle.id);
|
|
6424
|
-
try {
|
|
6425
|
-
const injection = await this.injector.inject(
|
|
6426
|
-
injectingSupervisor,
|
|
6427
|
-
{
|
|
6428
|
-
message: evaluation.message
|
|
6429
|
-
},
|
|
6430
|
-
recentCycles
|
|
6431
|
-
);
|
|
6432
|
-
injected = injection.injected;
|
|
6433
|
-
injectedText = injection.injected ? injection.text : void 0;
|
|
6434
|
-
cycleResult = injection.injected ? injection.text : `Skipped duplicate: ${injection.text}`;
|
|
6435
|
-
} catch (error) {
|
|
6436
|
-
injectionError = messageOf(error, "Injection failed");
|
|
6437
|
-
this.logger.warn(
|
|
6438
|
-
{ err: error, supervisorId, cycleId: activeCycle.id },
|
|
6439
|
-
"Supervisor injection failed"
|
|
6440
|
-
);
|
|
6441
|
-
}
|
|
6442
|
-
}
|
|
6443
|
-
const finalStatus = injectionError ? "failed" : injected ? "injected" : "completed";
|
|
6444
|
-
const finishedCycle = this.deps.cycleRepo.update(activeCycle.id, {
|
|
6445
|
-
status: finalStatus,
|
|
6446
|
-
result: cycleResult ?? null,
|
|
6447
|
-
injectedGuidance: injectedText,
|
|
6448
|
-
errorReason: injectionError ?? null,
|
|
6449
|
-
completedAt: Date.now()
|
|
6450
|
-
});
|
|
6451
|
-
const latestState = this.supervisors.get(supervisorId)?.state;
|
|
6452
|
-
const nextState = latestState === "paused" ? "paused" : injectionError ? "error" : "idle";
|
|
6453
|
-
const finishedSupervisor = this.attachCycles(
|
|
6454
|
-
this.deps.supervisorRepo.update(supervisorId, {
|
|
6455
|
-
state: nextState,
|
|
6456
|
-
lastCycleAt: finishedCycle.completedAt,
|
|
6457
|
-
lastEvaluatedTurnId: context.lastTurnId ?? void 0,
|
|
6458
|
-
errorReason: injectionError ?? null,
|
|
6459
|
-
updatedAt: Date.now()
|
|
6460
|
-
})
|
|
6461
|
-
);
|
|
6462
|
-
this.storeSnapshot(finishedSupervisor);
|
|
6463
|
-
this.broadcastCycle(finishedSupervisor, finishedCycle, "updated");
|
|
6464
|
-
this.broadcastState(finishedSupervisor, "state_changed");
|
|
6465
|
-
this.deps.cycleRepo.pruneOldest(supervisorId, this.config.maxCyclesPerSession);
|
|
6990
|
+
const signal = this.evaluationAbortControllers.get(supervisorId)?.signal;
|
|
6991
|
+
const evaluation = await this.executeCycleWithRetry(started, supervisorForEval, signal);
|
|
6992
|
+
const finalized = this.finalizeSuccessfulCycle(activeCycle, context, evaluation);
|
|
6466
6993
|
if (this.pendingDeletes.has(supervisorId)) {
|
|
6467
6994
|
this.pendingDeletes.delete(supervisorId);
|
|
6468
|
-
this.deleteNow(
|
|
6995
|
+
this.deleteNow(finalized.supervisor);
|
|
6469
6996
|
}
|
|
6470
|
-
return
|
|
6997
|
+
return finalized.cycle;
|
|
6471
6998
|
} catch (error) {
|
|
6472
6999
|
if (isSupervisorEvalAborted(error)) {
|
|
7000
|
+
const cancelled = this.pendingPauses.has(supervisorId);
|
|
6473
7001
|
const abortedCycle = this.deps.cycleRepo.update(activeCycle.id, {
|
|
6474
|
-
status: "failed",
|
|
6475
|
-
errorReason: messageOf(error, "Supervisor evaluator aborted"),
|
|
7002
|
+
status: cancelled ? "cancelled" : "failed",
|
|
7003
|
+
errorReason: cancelled ? null : messageOf(error, "Supervisor evaluator aborted"),
|
|
6476
7004
|
completedAt: Date.now()
|
|
6477
7005
|
});
|
|
6478
7006
|
const currentSupervisor = this.supervisors.get(supervisorId) ?? this.requireSupervisor(supervisorId);
|
|
@@ -6483,10 +7011,11 @@ var init_manager2 = __esm({
|
|
|
6483
7011
|
return abortedCycle;
|
|
6484
7012
|
}
|
|
6485
7013
|
const latestState = this.supervisors.get(supervisorId)?.state;
|
|
6486
|
-
const nextState = latestState === "paused" ? "paused" : "idle";
|
|
7014
|
+
const nextState = cancelled || latestState === "paused" ? "paused" : "idle";
|
|
6487
7015
|
const recoveredSupervisor = this.attachCycles(
|
|
6488
7016
|
this.deps.supervisorRepo.update(supervisorId, {
|
|
6489
7017
|
state: nextState,
|
|
7018
|
+
stopReason: null,
|
|
6490
7019
|
errorReason: null,
|
|
6491
7020
|
updatedAt: Date.now()
|
|
6492
7021
|
})
|
|
@@ -6495,6 +7024,8 @@ var init_manager2 = __esm({
|
|
|
6495
7024
|
this.broadcastCycle(recoveredSupervisor, abortedCycle, "updated");
|
|
6496
7025
|
this.broadcastState(recoveredSupervisor, "state_changed");
|
|
6497
7026
|
this.deps.cycleRepo.pruneOldest(supervisorId, this.config.maxCyclesPerSession);
|
|
7027
|
+
this.scheduler.refresh();
|
|
7028
|
+
this.pendingPauses.delete(supervisorId);
|
|
6498
7029
|
return abortedCycle;
|
|
6499
7030
|
}
|
|
6500
7031
|
logFailure(
|
|
@@ -6512,6 +7043,7 @@ var init_manager2 = __esm({
|
|
|
6512
7043
|
const failedSupervisor = this.attachCycles(
|
|
6513
7044
|
this.deps.supervisorRepo.update(supervisorId, {
|
|
6514
7045
|
state: "error",
|
|
7046
|
+
stopReason: null,
|
|
6515
7047
|
errorReason: reason,
|
|
6516
7048
|
updatedAt: Date.now()
|
|
6517
7049
|
})
|
|
@@ -6525,9 +7057,122 @@ var init_manager2 = __esm({
|
|
|
6525
7057
|
}
|
|
6526
7058
|
throw error;
|
|
6527
7059
|
} finally {
|
|
7060
|
+
this.pendingPauses.delete(supervisorId);
|
|
6528
7061
|
this.releaseInFlight(supervisorId);
|
|
6529
7062
|
}
|
|
6530
7063
|
}
|
|
7064
|
+
async executeCycleWithRetry(started, supervisor, signal) {
|
|
7065
|
+
for (let attemptIndex = 0; ; attemptIndex += 1) {
|
|
7066
|
+
const attempt = this.deps.cycleAttemptRepo.create({
|
|
7067
|
+
id: generateAttemptId(),
|
|
7068
|
+
cycleId: started.cycle.id,
|
|
7069
|
+
attemptIndex,
|
|
7070
|
+
status: "evaluating",
|
|
7071
|
+
startedAt: Date.now()
|
|
7072
|
+
});
|
|
7073
|
+
try {
|
|
7074
|
+
const evaluation = await this.evaluator.evaluate(supervisor, started.context, { signal });
|
|
7075
|
+
this.deps.cycleAttemptRepo.update(attempt.id, {
|
|
7076
|
+
status: "completed",
|
|
7077
|
+
completedAt: Date.now(),
|
|
7078
|
+
providerModel: supervisor.evaluatorModel ?? null
|
|
7079
|
+
});
|
|
7080
|
+
if (evaluation.objectiveComplete) {
|
|
7081
|
+
return {
|
|
7082
|
+
objectiveComplete: true,
|
|
7083
|
+
injected: false,
|
|
7084
|
+
cycleResult: evaluation.message
|
|
7085
|
+
};
|
|
7086
|
+
}
|
|
7087
|
+
if (!evaluation.message.trim()) {
|
|
7088
|
+
return {
|
|
7089
|
+
objectiveComplete: false,
|
|
7090
|
+
injected: false
|
|
7091
|
+
};
|
|
7092
|
+
}
|
|
7093
|
+
if (signal?.aborted || this.pendingPauses.has(supervisor.id)) {
|
|
7094
|
+
throw { code: "supervisor_eval_aborted", message: "Supervisor evaluator aborted" };
|
|
7095
|
+
}
|
|
7096
|
+
const injectingSupervisor = this.attachCycles(
|
|
7097
|
+
this.deps.supervisorRepo.update(supervisor.id, {
|
|
7098
|
+
state: "injecting",
|
|
7099
|
+
updatedAt: Date.now()
|
|
7100
|
+
})
|
|
7101
|
+
);
|
|
7102
|
+
this.storeSnapshot(injectingSupervisor);
|
|
7103
|
+
this.broadcastState(injectingSupervisor, "state_changed");
|
|
7104
|
+
const recentCycles = this.deps.cycleRepo.listRecentForSupervisor(supervisor.id, this.config.guidanceDedupeWindow + 1).filter((cycle) => cycle.id !== started.cycle.id);
|
|
7105
|
+
const injection = await this.injector.inject(
|
|
7106
|
+
injectingSupervisor,
|
|
7107
|
+
{
|
|
7108
|
+
message: evaluation.message
|
|
7109
|
+
},
|
|
7110
|
+
recentCycles,
|
|
7111
|
+
{ signal }
|
|
7112
|
+
);
|
|
7113
|
+
return {
|
|
7114
|
+
objectiveComplete: false,
|
|
7115
|
+
injected: injection.injected,
|
|
7116
|
+
injectedText: injection.injected ? injection.text : void 0,
|
|
7117
|
+
cycleResult: injection.injected ? injection.text : `Skipped duplicate: ${injection.text}`
|
|
7118
|
+
};
|
|
7119
|
+
} catch (error) {
|
|
7120
|
+
if (isSupervisorEvalAborted(error)) {
|
|
7121
|
+
this.deps.cycleAttemptRepo.update(attempt.id, {
|
|
7122
|
+
status: this.pendingPauses.has(supervisor.id) ? "cancelled" : "failed",
|
|
7123
|
+
completedAt: Date.now(),
|
|
7124
|
+
errorReason: this.pendingPauses.has(supervisor.id) ? null : messageOf(error, "Supervisor evaluator aborted")
|
|
7125
|
+
});
|
|
7126
|
+
throw error;
|
|
7127
|
+
}
|
|
7128
|
+
const reason = messageOf(error, "Supervisor evaluation failed");
|
|
7129
|
+
this.deps.cycleAttemptRepo.update(attempt.id, {
|
|
7130
|
+
status: "failed",
|
|
7131
|
+
completedAt: Date.now(),
|
|
7132
|
+
errorReason: reason
|
|
7133
|
+
});
|
|
7134
|
+
if (!this.shouldRetryAttempt(error, attemptIndex, started.retry)) {
|
|
7135
|
+
throw error;
|
|
7136
|
+
}
|
|
7137
|
+
await this.sleep(started.retry.retryDelayMs, signal);
|
|
7138
|
+
const evaluatingSupervisor = this.attachCycles(
|
|
7139
|
+
this.deps.supervisorRepo.update(supervisor.id, {
|
|
7140
|
+
state: "evaluating",
|
|
7141
|
+
updatedAt: Date.now()
|
|
7142
|
+
})
|
|
7143
|
+
);
|
|
7144
|
+
this.storeSnapshot(evaluatingSupervisor);
|
|
7145
|
+
this.broadcastState(evaluatingSupervisor, "state_changed");
|
|
7146
|
+
}
|
|
7147
|
+
}
|
|
7148
|
+
}
|
|
7149
|
+
finalizeSuccessfulCycle(activeCycle, context, result) {
|
|
7150
|
+
const finalStatus = result.injected ? "injected" : result.objectiveComplete ? "completed" : "completed";
|
|
7151
|
+
const finishedCycle = this.deps.cycleRepo.update(activeCycle.id, {
|
|
7152
|
+
status: finalStatus,
|
|
7153
|
+
result: result.cycleResult ?? null,
|
|
7154
|
+
injectedGuidance: result.injectedText ?? null,
|
|
7155
|
+
errorReason: null,
|
|
7156
|
+
completedAt: Date.now()
|
|
7157
|
+
});
|
|
7158
|
+
const finishedSupervisor = this.attachCycles(
|
|
7159
|
+
this.deps.supervisorRepo.update(activeCycle.supervisorId, {
|
|
7160
|
+
state: result.objectiveComplete ? "stopped" : "idle",
|
|
7161
|
+
completedSupervisionCount: (this.supervisors.get(activeCycle.supervisorId)?.completedSupervisionCount ?? 0) + 1,
|
|
7162
|
+
stopReason: result.objectiveComplete ? "objective_complete" : null,
|
|
7163
|
+
lastCycleAt: finishedCycle.completedAt,
|
|
7164
|
+
lastEvaluatedTurnId: context.lastTurnId ?? void 0,
|
|
7165
|
+
errorReason: null,
|
|
7166
|
+
updatedAt: Date.now()
|
|
7167
|
+
})
|
|
7168
|
+
);
|
|
7169
|
+
this.storeSnapshot(finishedSupervisor);
|
|
7170
|
+
this.broadcastCycle(finishedSupervisor, finishedCycle, "updated");
|
|
7171
|
+
this.broadcastState(finishedSupervisor, "state_changed");
|
|
7172
|
+
this.deps.cycleRepo.pruneOldest(activeCycle.supervisorId, this.config.maxCyclesPerSession);
|
|
7173
|
+
this.scheduler.refresh();
|
|
7174
|
+
return { cycle: finishedCycle, supervisor: finishedSupervisor };
|
|
7175
|
+
}
|
|
6531
7176
|
/**
|
|
6532
7177
|
* Flip a supervisor to 'error' state when something blows up before we
|
|
6533
7178
|
* had a chance to create a cycle. Without this the supervisor can get
|
|
@@ -6593,6 +7238,14 @@ var init_manager2 = __esm({
|
|
|
6593
7238
|
cycles: this.deps.cycleRepo.listRecentForSupervisor(supervisor.id, 20)
|
|
6594
7239
|
};
|
|
6595
7240
|
}
|
|
7241
|
+
listScheduledSupervisors() {
|
|
7242
|
+
return Array.from(this.supervisors.values()).filter(
|
|
7243
|
+
(supervisor) => supervisor.state === "idle" && typeof supervisor.scheduledAt === "number" && Number.isFinite(supervisor.scheduledAt)
|
|
7244
|
+
).map((supervisor) => ({
|
|
7245
|
+
supervisorId: supervisor.id,
|
|
7246
|
+
scheduledAt: supervisor.scheduledAt
|
|
7247
|
+
}));
|
|
7248
|
+
}
|
|
6596
7249
|
storeSnapshot(supervisor) {
|
|
6597
7250
|
this.supervisors.set(supervisor.id, supervisor);
|
|
6598
7251
|
this.supervisorsBySession.set(supervisor.sessionId, supervisor.id);
|
|
@@ -6602,7 +7255,9 @@ var init_manager2 = __esm({
|
|
|
6602
7255
|
this.supervisors.delete(supervisor.id);
|
|
6603
7256
|
this.supervisorsBySession.delete(supervisor.sessionId);
|
|
6604
7257
|
this.pendingDeletes.delete(supervisor.id);
|
|
7258
|
+
this.pendingPauses.delete(supervisor.id);
|
|
6605
7259
|
this.releaseInFlight(supervisor.id);
|
|
7260
|
+
this.scheduler.refresh();
|
|
6606
7261
|
this.deps.broadcaster.broadcast(
|
|
6607
7262
|
Topics.supervisorState(supervisor.workspaceId, supervisor.sessionId),
|
|
6608
7263
|
{ supervisorId: supervisor.id, event: "deleted" }
|
|
@@ -6636,6 +7291,43 @@ var init_manager2 = __esm({
|
|
|
6636
7291
|
{ cycle, event }
|
|
6637
7292
|
);
|
|
6638
7293
|
}
|
|
7294
|
+
shouldRetryAttempt(error, attemptIndex, retry) {
|
|
7295
|
+
if (!retry.retryEnabled) {
|
|
7296
|
+
return false;
|
|
7297
|
+
}
|
|
7298
|
+
if (attemptIndex >= retry.retryMaxCount) {
|
|
7299
|
+
return false;
|
|
7300
|
+
}
|
|
7301
|
+
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
|
7302
|
+
if (code === "supervisor_eval_timeout") {
|
|
7303
|
+
return retry.retryOnTimeout;
|
|
7304
|
+
}
|
|
7305
|
+
if (code === "supervisor_eval_failed") {
|
|
7306
|
+
return retry.retryOnEvaluatorError;
|
|
7307
|
+
}
|
|
7308
|
+
return false;
|
|
7309
|
+
}
|
|
7310
|
+
async sleep(delayMs, signal) {
|
|
7311
|
+
if (delayMs <= 0) {
|
|
7312
|
+
return;
|
|
7313
|
+
}
|
|
7314
|
+
if (signal?.aborted) {
|
|
7315
|
+
throw { code: "supervisor_eval_aborted", message: "Supervisor evaluator aborted" };
|
|
7316
|
+
}
|
|
7317
|
+
await new Promise((resolve4, reject) => {
|
|
7318
|
+
const timer = setTimeout(() => {
|
|
7319
|
+
signal?.removeEventListener("abort", onAbort);
|
|
7320
|
+
resolve4();
|
|
7321
|
+
}, delayMs);
|
|
7322
|
+
timer.unref?.();
|
|
7323
|
+
const onAbort = () => {
|
|
7324
|
+
clearTimeout(timer);
|
|
7325
|
+
signal?.removeEventListener("abort", onAbort);
|
|
7326
|
+
reject({ code: "supervisor_eval_aborted", message: "Supervisor evaluator aborted" });
|
|
7327
|
+
};
|
|
7328
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
7329
|
+
});
|
|
7330
|
+
}
|
|
6639
7331
|
};
|
|
6640
7332
|
}
|
|
6641
7333
|
});
|
|
@@ -7446,9 +8138,9 @@ var init_validator = __esm({
|
|
|
7446
8138
|
});
|
|
7447
8139
|
|
|
7448
8140
|
// packages/server/src/fs/gitignore.ts
|
|
7449
|
-
import { existsSync as
|
|
8141
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
7450
8142
|
import ignore from "ignore";
|
|
7451
|
-
import { join as
|
|
8143
|
+
import { join as join4, relative as relative3 } from "path";
|
|
7452
8144
|
function normalizePath(path10) {
|
|
7453
8145
|
return path10.replace(/\\/g, "/");
|
|
7454
8146
|
}
|
|
@@ -7468,26 +8160,26 @@ function isIgnoredByGitignore(ig, path10) {
|
|
|
7468
8160
|
return ig.ignores(path10) || ig.ignores(`${path10}/`);
|
|
7469
8161
|
}
|
|
7470
8162
|
function createGitignoreFilter(rootPath, dirPath) {
|
|
7471
|
-
const gitignorePath =
|
|
7472
|
-
if (!
|
|
8163
|
+
const gitignorePath = join4(rootPath, ".gitignore");
|
|
8164
|
+
if (!existsSync5(gitignorePath)) {
|
|
7473
8165
|
return (name) => !isDefaultTreeIgnored(name);
|
|
7474
8166
|
}
|
|
7475
|
-
const gitignoreContent =
|
|
8167
|
+
const gitignoreContent = readFileSync5(gitignorePath, "utf-8");
|
|
7476
8168
|
const ig = ignore().add(gitignoreContent);
|
|
7477
8169
|
return (name) => {
|
|
7478
8170
|
if (isAlwaysTreeIgnored(name)) {
|
|
7479
8171
|
return false;
|
|
7480
8172
|
}
|
|
7481
|
-
const relativePath = relativeToRoot(rootPath,
|
|
8173
|
+
const relativePath = relativeToRoot(rootPath, join4(dirPath, name));
|
|
7482
8174
|
return !isIgnoredByGitignore(ig, relativePath);
|
|
7483
8175
|
};
|
|
7484
8176
|
}
|
|
7485
8177
|
function createWatcherIgnoreFilter(rootPath) {
|
|
7486
|
-
const gitignorePath =
|
|
7487
|
-
if (!
|
|
8178
|
+
const gitignorePath = join4(rootPath, ".gitignore");
|
|
8179
|
+
if (!existsSync5(gitignorePath)) {
|
|
7488
8180
|
return (path10) => DEFAULT_WATCHER_IGNORED_PATTERNS.some((p) => p.test(normalizePath(path10)));
|
|
7489
8181
|
}
|
|
7490
|
-
const gitignoreContent =
|
|
8182
|
+
const gitignoreContent = readFileSync5(gitignorePath, "utf-8");
|
|
7491
8183
|
const ig = ignore().add(gitignoreContent);
|
|
7492
8184
|
return (path10) => {
|
|
7493
8185
|
const normalizedPath = normalizePath(path10);
|
|
@@ -7537,6 +8229,7 @@ var init_watcher = __esm({
|
|
|
7537
8229
|
dirtyTimer = null;
|
|
7538
8230
|
firstDirtyTime = null;
|
|
7539
8231
|
pendingReason = null;
|
|
8232
|
+
pendingWorktreeChanged = false;
|
|
7540
8233
|
DEBOUNCE_MS = 200;
|
|
7541
8234
|
MAX_WAIT_MS = 1e3;
|
|
7542
8235
|
/**
|
|
@@ -7549,6 +8242,9 @@ var init_watcher = __esm({
|
|
|
7549
8242
|
if (this.firstDirtyTime === null) {
|
|
7550
8243
|
this.firstDirtyTime = now;
|
|
7551
8244
|
}
|
|
8245
|
+
if (changedPath && this.isWorktreeMetadataPath(changedPath)) {
|
|
8246
|
+
this.pendingWorktreeChanged = true;
|
|
8247
|
+
}
|
|
7552
8248
|
if (changedPath && !this.isGitMetadataPath(changedPath)) {
|
|
7553
8249
|
this.pendingReason = "fs_change";
|
|
7554
8250
|
} else if (changedPath && this.pendingReason !== "fs_change") {
|
|
@@ -7567,13 +8263,23 @@ var init_watcher = __esm({
|
|
|
7567
8263
|
this.broadcaster?.broadcast(Topics.workspaceFsDirty(this.workspaceId), {
|
|
7568
8264
|
reason: this.pendingReason ?? "fs_change"
|
|
7569
8265
|
});
|
|
8266
|
+
if (this.pendingWorktreeChanged) {
|
|
8267
|
+
this.broadcaster?.broadcast(Topics.workspaceGitState(this.workspaceId), {
|
|
8268
|
+
worktreeChanged: true
|
|
8269
|
+
});
|
|
8270
|
+
}
|
|
7570
8271
|
this.dirtyTimer = null;
|
|
7571
8272
|
this.firstDirtyTime = null;
|
|
7572
8273
|
this.pendingReason = null;
|
|
8274
|
+
this.pendingWorktreeChanged = false;
|
|
7573
8275
|
}
|
|
7574
8276
|
isGitMetadataPath(changedPath) {
|
|
7575
8277
|
return changedPath.replace(/\\/g, "/").includes("/.git/");
|
|
7576
8278
|
}
|
|
8279
|
+
isWorktreeMetadataPath(changedPath) {
|
|
8280
|
+
const normalized = changedPath.replace(/\\/g, "/");
|
|
8281
|
+
return normalized.includes("/.git/worktrees");
|
|
8282
|
+
}
|
|
7577
8283
|
/**
|
|
7578
8284
|
* Stops watching and cleans up resources.
|
|
7579
8285
|
*/
|
|
@@ -7809,12 +8515,103 @@ var init_manager4 = __esm({
|
|
|
7809
8515
|
}
|
|
7810
8516
|
});
|
|
7811
8517
|
|
|
8518
|
+
// packages/server/src/ws/activation.ts
|
|
8519
|
+
var DEFAULT_OPTIONS, ActivationManager;
|
|
8520
|
+
var init_activation = __esm({
|
|
8521
|
+
"packages/server/src/ws/activation.ts"() {
|
|
8522
|
+
"use strict";
|
|
8523
|
+
DEFAULT_OPTIONS = {
|
|
8524
|
+
graceMs: 3e3
|
|
8525
|
+
};
|
|
8526
|
+
ActivationManager = class {
|
|
8527
|
+
options;
|
|
8528
|
+
lease = null;
|
|
8529
|
+
generation = 0;
|
|
8530
|
+
constructor(options) {
|
|
8531
|
+
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
8532
|
+
}
|
|
8533
|
+
claim(clientInstanceId, wsClientId, request) {
|
|
8534
|
+
const now = Date.now();
|
|
8535
|
+
const activeLease = this.getLease();
|
|
8536
|
+
if (activeLease && activeLease.clientInstanceId === clientInstanceId) {
|
|
8537
|
+
const isGraceRecovery = activeLease.graceUntil !== null && now <= activeLease.graceUntil;
|
|
8538
|
+
const displacedWsClientId2 = isGraceRecovery || activeLease.wsClientId === wsClientId ? null : activeLease.wsClientId;
|
|
8539
|
+
activeLease.wsClientId = wsClientId;
|
|
8540
|
+
activeLease.graceUntil = null;
|
|
8541
|
+
return {
|
|
8542
|
+
active: true,
|
|
8543
|
+
generation: activeLease.generation,
|
|
8544
|
+
recoveryMode: "grace_recover",
|
|
8545
|
+
displacedWsClientId: displacedWsClientId2
|
|
8546
|
+
};
|
|
8547
|
+
}
|
|
8548
|
+
const displacedWsClientId = activeLease && activeLease.clientInstanceId !== clientInstanceId ? activeLease.wsClientId : null;
|
|
8549
|
+
const recoveryMode = displacedWsClientId === null ? "fresh" : "takeover";
|
|
8550
|
+
this.generation += 1;
|
|
8551
|
+
this.lease = {
|
|
8552
|
+
clientInstanceId,
|
|
8553
|
+
wsClientId,
|
|
8554
|
+
generation: this.generation,
|
|
8555
|
+
issuedAt: now,
|
|
8556
|
+
graceUntil: null,
|
|
8557
|
+
ip: request.ip,
|
|
8558
|
+
userAgent: request.headers["user-agent"] ?? ""
|
|
8559
|
+
};
|
|
8560
|
+
return {
|
|
8561
|
+
active: true,
|
|
8562
|
+
generation: this.lease.generation,
|
|
8563
|
+
recoveryMode,
|
|
8564
|
+
displacedWsClientId
|
|
8565
|
+
};
|
|
8566
|
+
}
|
|
8567
|
+
release(clientInstanceId, generation) {
|
|
8568
|
+
const lease = this.getLease();
|
|
8569
|
+
if (!lease) {
|
|
8570
|
+
return;
|
|
8571
|
+
}
|
|
8572
|
+
if (lease.clientInstanceId !== clientInstanceId || lease.generation !== generation) {
|
|
8573
|
+
return;
|
|
8574
|
+
}
|
|
8575
|
+
this.lease = null;
|
|
8576
|
+
}
|
|
8577
|
+
onSocketClosed(wsClientId) {
|
|
8578
|
+
const lease = this.getLease();
|
|
8579
|
+
if (!lease || lease.wsClientId !== wsClientId) {
|
|
8580
|
+
return;
|
|
8581
|
+
}
|
|
8582
|
+
lease.graceUntil = Date.now() + this.options.graceMs;
|
|
8583
|
+
}
|
|
8584
|
+
getLease() {
|
|
8585
|
+
if (!this.lease) {
|
|
8586
|
+
return null;
|
|
8587
|
+
}
|
|
8588
|
+
return this.lease;
|
|
8589
|
+
}
|
|
8590
|
+
};
|
|
8591
|
+
}
|
|
8592
|
+
});
|
|
8593
|
+
|
|
7812
8594
|
// packages/server/src/ws/dispatch.ts
|
|
7813
8595
|
function registerCommand(op, schema, handler) {
|
|
7814
8596
|
handlers.set(op, handler);
|
|
7815
8597
|
schemas.set(op, schema);
|
|
7816
8598
|
}
|
|
7817
8599
|
async function dispatch(msg, ctx, clientId) {
|
|
8600
|
+
const isWsDispatch = clientId !== void 0 && typeof ctx.broadcaster.getRequestMetadata === "function";
|
|
8601
|
+
if (isWsDispatch && !ACTIVATION_ALLOWLIST.has(msg.op)) {
|
|
8602
|
+
const active = ctx.activationMgr.getLease();
|
|
8603
|
+
if (!active || active.wsClientId !== clientId) {
|
|
8604
|
+
return {
|
|
8605
|
+
kind: "result",
|
|
8606
|
+
id: msg.id,
|
|
8607
|
+
ok: false,
|
|
8608
|
+
error: {
|
|
8609
|
+
code: "activation_required",
|
|
8610
|
+
message: "This tab is no longer the active session"
|
|
8611
|
+
}
|
|
8612
|
+
};
|
|
8613
|
+
}
|
|
8614
|
+
}
|
|
7818
8615
|
const handler = handlers.get(msg.op);
|
|
7819
8616
|
if (!handler) {
|
|
7820
8617
|
return {
|
|
@@ -7871,21 +8668,26 @@ function normalizeError(error) {
|
|
|
7871
8668
|
message: candidate.message || "An internal error occurred"
|
|
7872
8669
|
};
|
|
7873
8670
|
}
|
|
7874
|
-
var handlers, schemas;
|
|
8671
|
+
var handlers, schemas, ACTIVATION_ALLOWLIST;
|
|
7875
8672
|
var init_dispatch = __esm({
|
|
7876
8673
|
"packages/server/src/ws/dispatch.ts"() {
|
|
7877
8674
|
"use strict";
|
|
7878
8675
|
handlers = /* @__PURE__ */ new Map();
|
|
7879
8676
|
schemas = /* @__PURE__ */ new Map();
|
|
8677
|
+
ACTIVATION_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
8678
|
+
"activation.claim",
|
|
8679
|
+
"activation.release",
|
|
8680
|
+
"connection.probe"
|
|
8681
|
+
]);
|
|
7880
8682
|
}
|
|
7881
8683
|
});
|
|
7882
8684
|
|
|
7883
8685
|
// packages/server/src/ws/fencing.ts
|
|
7884
|
-
var
|
|
8686
|
+
var DEFAULT_OPTIONS2, FencingManager;
|
|
7885
8687
|
var init_fencing = __esm({
|
|
7886
8688
|
"packages/server/src/ws/fencing.ts"() {
|
|
7887
8689
|
"use strict";
|
|
7888
|
-
|
|
8690
|
+
DEFAULT_OPTIONS2 = {
|
|
7889
8691
|
visibleHeartbeatMs: 1e4,
|
|
7890
8692
|
// 10 seconds
|
|
7891
8693
|
hiddenHeartbeatMs: 2e4,
|
|
@@ -7904,7 +8706,7 @@ var init_fencing = __esm({
|
|
|
7904
8706
|
// workspaceId -> { clientId, closedAt, ip, ua } (for grace period)
|
|
7905
8707
|
lastWriter = /* @__PURE__ */ new Map();
|
|
7906
8708
|
constructor(options) {
|
|
7907
|
-
this.options = { ...
|
|
8709
|
+
this.options = { ...DEFAULT_OPTIONS2, ...options };
|
|
7908
8710
|
}
|
|
7909
8711
|
/**
|
|
7910
8712
|
* Request controller status for a workspace.
|
|
@@ -8053,7 +8855,7 @@ var init_fencing = __esm({
|
|
|
8053
8855
|
});
|
|
8054
8856
|
|
|
8055
8857
|
// packages/server/src/commands/terminal.ts
|
|
8056
|
-
import { basename
|
|
8858
|
+
import { basename } from "node:path";
|
|
8057
8859
|
import { z as z5 } from "zod";
|
|
8058
8860
|
function decodeTerminalInput(args) {
|
|
8059
8861
|
if ("bytes" in args) {
|
|
@@ -8108,11 +8910,11 @@ function resolveShellCommand() {
|
|
|
8108
8910
|
const shellPath2 = process.env.ComSpec || process.env.COMSPEC || "cmd.exe";
|
|
8109
8911
|
return {
|
|
8110
8912
|
argv: [shellPath2],
|
|
8111
|
-
title:
|
|
8913
|
+
title: basename(shellPath2) || shellPath2
|
|
8112
8914
|
};
|
|
8113
8915
|
}
|
|
8114
8916
|
const shellPath = process.env.SHELL || "/bin/bash";
|
|
8115
|
-
const shellName =
|
|
8917
|
+
const shellName = basename(shellPath);
|
|
8116
8918
|
const argv = shellName === "cmd.exe" ? [shellPath] : [shellPath, "-i"];
|
|
8117
8919
|
return {
|
|
8118
8920
|
argv,
|
|
@@ -8478,6 +9280,20 @@ var init_client = __esm({
|
|
|
8478
9280
|
return false;
|
|
8479
9281
|
}
|
|
8480
9282
|
}
|
|
9283
|
+
sendControlAndClose(msg, code, reason) {
|
|
9284
|
+
if (this.socket.readyState !== WebSocket.OPEN) {
|
|
9285
|
+
return false;
|
|
9286
|
+
}
|
|
9287
|
+
try {
|
|
9288
|
+
this.socket.send(JSON.stringify(msg), () => {
|
|
9289
|
+
this.socket.close(code, reason);
|
|
9290
|
+
});
|
|
9291
|
+
return true;
|
|
9292
|
+
} catch (error) {
|
|
9293
|
+
console.error(`Failed to send message to client ${this.id}:`, error);
|
|
9294
|
+
return false;
|
|
9295
|
+
}
|
|
9296
|
+
}
|
|
8481
9297
|
sendBinary(data) {
|
|
8482
9298
|
if (this.socket.readyState !== WebSocket.OPEN) {
|
|
8483
9299
|
return false;
|
|
@@ -8642,6 +9458,16 @@ var init_client = __esm({
|
|
|
8642
9458
|
};
|
|
8643
9459
|
return this.send(event);
|
|
8644
9460
|
}
|
|
9461
|
+
sendEventAndClose(topic, data, code, reason, seq = 0) {
|
|
9462
|
+
const event = {
|
|
9463
|
+
kind: "event",
|
|
9464
|
+
topic,
|
|
9465
|
+
seq,
|
|
9466
|
+
timestamp: Date.now(),
|
|
9467
|
+
data
|
|
9468
|
+
};
|
|
9469
|
+
return this.sendControlAndClose(event, code, reason);
|
|
9470
|
+
}
|
|
8645
9471
|
/**
|
|
8646
9472
|
* Check if client subscribes to a topic (supports glob patterns)
|
|
8647
9473
|
*/
|
|
@@ -8751,6 +9577,7 @@ var init_hub = __esm({
|
|
|
8751
9577
|
}
|
|
8752
9578
|
deps;
|
|
8753
9579
|
clients = /* @__PURE__ */ new Map();
|
|
9580
|
+
clientRequests = /* @__PURE__ */ new Map();
|
|
8754
9581
|
eventUnsubscribers = [];
|
|
8755
9582
|
nextStreamId = 1;
|
|
8756
9583
|
// Per-client queue of waiters for the next inbound binary frame. The
|
|
@@ -8767,9 +9594,10 @@ var init_hub = __esm({
|
|
|
8767
9594
|
/**
|
|
8768
9595
|
* Handle a new WebSocket connection
|
|
8769
9596
|
*/
|
|
8770
|
-
handleConnection(socket,
|
|
9597
|
+
handleConnection(socket, req) {
|
|
8771
9598
|
const client = new WsClient(socket, uuidv4(), this.deps.logger);
|
|
8772
9599
|
this.clients.set(client.id, client);
|
|
9600
|
+
this.clientRequests.set(client.id, req);
|
|
8773
9601
|
client.sendEvent("connection.status", {
|
|
8774
9602
|
status: "connected",
|
|
8775
9603
|
clientId: client.id,
|
|
@@ -8903,8 +9731,10 @@ var init_hub = __esm({
|
|
|
8903
9731
|
*/
|
|
8904
9732
|
handleClose(client) {
|
|
8905
9733
|
this.clients.delete(client.id);
|
|
9734
|
+
this.clientRequests.delete(client.id);
|
|
8906
9735
|
this.discardPendingBinaryWaiters(client.id);
|
|
8907
9736
|
this.deps.commandContext?.autoFetch.unregisterViewer(client.id);
|
|
9737
|
+
this.deps.commandContext?.activationMgr.onSocketClosed(client.id);
|
|
8908
9738
|
}
|
|
8909
9739
|
/**
|
|
8910
9740
|
* Takeover: Force close existing writer and accept new one
|
|
@@ -8945,6 +9775,24 @@ var init_hub = __esm({
|
|
|
8945
9775
|
if (!client) return false;
|
|
8946
9776
|
return client.sendBinary(data);
|
|
8947
9777
|
}
|
|
9778
|
+
revokeAndCloseClient(clientId, generation) {
|
|
9779
|
+
const client = this.clients.get(clientId);
|
|
9780
|
+
if (!client) {
|
|
9781
|
+
return;
|
|
9782
|
+
}
|
|
9783
|
+
client.sendEventAndClose(
|
|
9784
|
+
"activation.revoked",
|
|
9785
|
+
{
|
|
9786
|
+
reason: "displaced",
|
|
9787
|
+
generation
|
|
9788
|
+
},
|
|
9789
|
+
4001,
|
|
9790
|
+
"single_active_displaced"
|
|
9791
|
+
);
|
|
9792
|
+
}
|
|
9793
|
+
getRequestMetadata(clientId) {
|
|
9794
|
+
return this.clientRequests.get(clientId);
|
|
9795
|
+
}
|
|
8948
9796
|
/**
|
|
8949
9797
|
* Get the current writer client
|
|
8950
9798
|
* DEPRECATED: Writer tracking now handled by FencingManager
|
|
@@ -8972,6 +9820,7 @@ var init_hub = __esm({
|
|
|
8972
9820
|
client.close();
|
|
8973
9821
|
}
|
|
8974
9822
|
this.clients.clear();
|
|
9823
|
+
this.clientRequests.clear();
|
|
8975
9824
|
}
|
|
8976
9825
|
/**
|
|
8977
9826
|
* Subscribe to domain events and broadcast them
|
|
@@ -9101,8 +9950,8 @@ var init_hub = __esm({
|
|
|
9101
9950
|
|
|
9102
9951
|
// packages/server/src/commands/workspace.ts
|
|
9103
9952
|
import { readdir as readdir2 } from "node:fs/promises";
|
|
9104
|
-
import { homedir as
|
|
9105
|
-
import { join as
|
|
9953
|
+
import { homedir as homedir2 } from "node:os";
|
|
9954
|
+
import { join as join5 } from "node:path";
|
|
9106
9955
|
import { z as z6 } from "zod";
|
|
9107
9956
|
var init_workspace = __esm({
|
|
9108
9957
|
"packages/server/src/commands/workspace.ts"() {
|
|
@@ -9117,15 +9966,15 @@ var init_workspace = __esm({
|
|
|
9117
9966
|
path: z6.string().optional()
|
|
9118
9967
|
}),
|
|
9119
9968
|
async (args) => {
|
|
9120
|
-
const basePath = args.path ||
|
|
9969
|
+
const basePath = args.path || homedir2();
|
|
9121
9970
|
const entries = await readdir2(basePath, { withFileTypes: true });
|
|
9122
9971
|
const directories = entries.filter((entry) => entry.isDirectory()).map((entry) => ({
|
|
9123
9972
|
name: entry.name,
|
|
9124
|
-
path:
|
|
9973
|
+
path: join5(basePath, entry.name)
|
|
9125
9974
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
9126
9975
|
return {
|
|
9127
9976
|
currentPath: basePath,
|
|
9128
|
-
parentPath: basePath !== "/" ?
|
|
9977
|
+
parentPath: basePath !== "/" ? join5(basePath, "..") : null,
|
|
9129
9978
|
directories
|
|
9130
9979
|
};
|
|
9131
9980
|
}
|
|
@@ -9192,10 +10041,26 @@ var init_workspace = __esm({
|
|
|
9192
10041
|
|
|
9193
10042
|
// packages/server/src/commands/workspace-activity.ts
|
|
9194
10043
|
import { z as z7 } from "zod";
|
|
10044
|
+
function parseWorkspaceLastViewedTarget(value) {
|
|
10045
|
+
try {
|
|
10046
|
+
const parsed = JSON.parse(value);
|
|
10047
|
+
const result = workspaceLastViewedTargetSchema.safeParse(parsed);
|
|
10048
|
+
return result.success ? result.data : null;
|
|
10049
|
+
} catch {
|
|
10050
|
+
return null;
|
|
10051
|
+
}
|
|
10052
|
+
}
|
|
10053
|
+
var WORKSPACE_LAST_VIEWED_TARGET_KEY, workspaceLastViewedTargetSchema;
|
|
9195
10054
|
var init_workspace_activity = __esm({
|
|
9196
10055
|
"packages/server/src/commands/workspace-activity.ts"() {
|
|
9197
10056
|
"use strict";
|
|
9198
10057
|
init_dispatch();
|
|
10058
|
+
WORKSPACE_LAST_VIEWED_TARGET_KEY = "workspace.lastViewedTarget";
|
|
10059
|
+
workspaceLastViewedTargetSchema = z7.object({
|
|
10060
|
+
workspaceId: z7.string(),
|
|
10061
|
+
sessionId: z7.string().optional(),
|
|
10062
|
+
updatedAt: z7.number()
|
|
10063
|
+
});
|
|
9199
10064
|
registerCommand(
|
|
9200
10065
|
"workspace.activate",
|
|
9201
10066
|
z7.object({
|
|
@@ -9216,16 +10081,98 @@ var init_workspace_activity = __esm({
|
|
|
9216
10081
|
ctx.autoFetch.unregisterViewer(clientId);
|
|
9217
10082
|
return {};
|
|
9218
10083
|
});
|
|
10084
|
+
registerCommand("workspace.lastViewedTarget.get", z7.object({}), async (_args, ctx) => {
|
|
10085
|
+
const row = ctx.db.prepare("SELECT value FROM user_settings WHERE key = ?").get(WORKSPACE_LAST_VIEWED_TARGET_KEY);
|
|
10086
|
+
if (!row) {
|
|
10087
|
+
return null;
|
|
10088
|
+
}
|
|
10089
|
+
return parseWorkspaceLastViewedTarget(row.value);
|
|
10090
|
+
});
|
|
10091
|
+
registerCommand(
|
|
10092
|
+
"workspace.lastViewedTarget.set",
|
|
10093
|
+
z7.object({
|
|
10094
|
+
workspaceId: z7.string(),
|
|
10095
|
+
sessionId: z7.string().optional()
|
|
10096
|
+
}),
|
|
10097
|
+
async (args, ctx) => {
|
|
10098
|
+
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
10099
|
+
if (!workspace) {
|
|
10100
|
+
throw {
|
|
10101
|
+
code: "workspace_not_found",
|
|
10102
|
+
message: `Workspace not found: ${args.workspaceId}`
|
|
10103
|
+
};
|
|
10104
|
+
}
|
|
10105
|
+
const session = args.sessionId ? ctx.sessionMgr.get(args.sessionId) : void 0;
|
|
10106
|
+
const nextTarget = {
|
|
10107
|
+
workspaceId: args.workspaceId,
|
|
10108
|
+
sessionId: session && session.workspaceId === args.workspaceId ? session.id : void 0,
|
|
10109
|
+
updatedAt: Date.now()
|
|
10110
|
+
};
|
|
10111
|
+
ctx.db.prepare(
|
|
10112
|
+
`
|
|
10113
|
+
INSERT INTO user_settings (key, value)
|
|
10114
|
+
VALUES (?, ?)
|
|
10115
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
10116
|
+
`
|
|
10117
|
+
).run(WORKSPACE_LAST_VIEWED_TARGET_KEY, JSON.stringify(nextTarget));
|
|
10118
|
+
return nextTarget;
|
|
10119
|
+
}
|
|
10120
|
+
);
|
|
9219
10121
|
}
|
|
9220
10122
|
});
|
|
9221
10123
|
|
|
9222
|
-
// packages/server/src/commands/
|
|
10124
|
+
// packages/server/src/commands/activation.ts
|
|
9223
10125
|
import { z as z8 } from "zod";
|
|
10126
|
+
var init_activation2 = __esm({
|
|
10127
|
+
"packages/server/src/commands/activation.ts"() {
|
|
10128
|
+
"use strict";
|
|
10129
|
+
init_dispatch();
|
|
10130
|
+
registerCommand(
|
|
10131
|
+
"activation.claim",
|
|
10132
|
+
z8.object({ clientInstanceId: z8.string().min(1) }),
|
|
10133
|
+
async (args, ctx, clientId) => {
|
|
10134
|
+
if (!clientId) {
|
|
10135
|
+
throw {
|
|
10136
|
+
code: "activation_request_unavailable",
|
|
10137
|
+
message: "Activation claim requires websocket request metadata"
|
|
10138
|
+
};
|
|
10139
|
+
}
|
|
10140
|
+
const request = ctx.broadcaster.getRequestMetadata?.(clientId);
|
|
10141
|
+
if (!request) {
|
|
10142
|
+
throw {
|
|
10143
|
+
code: "activation_request_unavailable",
|
|
10144
|
+
message: "Activation claim requires websocket request metadata"
|
|
10145
|
+
};
|
|
10146
|
+
}
|
|
10147
|
+
const claim = ctx.activationMgr.claim(args.clientInstanceId, clientId, request);
|
|
10148
|
+
if (claim.displacedWsClientId) {
|
|
10149
|
+
ctx.broadcaster.revokeAndCloseClient?.(claim.displacedWsClientId, claim.generation);
|
|
10150
|
+
}
|
|
10151
|
+
return claim;
|
|
10152
|
+
}
|
|
10153
|
+
);
|
|
10154
|
+
registerCommand(
|
|
10155
|
+
"activation.release",
|
|
10156
|
+
z8.object({ clientInstanceId: z8.string(), generation: z8.number().int().positive() }),
|
|
10157
|
+
async (args, ctx, clientId) => {
|
|
10158
|
+
const lease = ctx.activationMgr.getLease();
|
|
10159
|
+
if (!clientId || !lease || lease.wsClientId !== clientId) {
|
|
10160
|
+
return { ok: false };
|
|
10161
|
+
}
|
|
10162
|
+
ctx.activationMgr.release(args.clientInstanceId, args.generation);
|
|
10163
|
+
return { ok: true };
|
|
10164
|
+
}
|
|
10165
|
+
);
|
|
10166
|
+
}
|
|
10167
|
+
});
|
|
10168
|
+
|
|
10169
|
+
// packages/server/src/commands/connection.ts
|
|
10170
|
+
import { z as z9 } from "zod";
|
|
9224
10171
|
var init_connection = __esm({
|
|
9225
10172
|
"packages/server/src/commands/connection.ts"() {
|
|
9226
10173
|
"use strict";
|
|
9227
10174
|
init_dispatch();
|
|
9228
|
-
registerCommand("connection.probe",
|
|
10175
|
+
registerCommand("connection.probe", z9.object({}).default({}), async () => {
|
|
9229
10176
|
return { ok: true };
|
|
9230
10177
|
});
|
|
9231
10178
|
}
|
|
@@ -9325,7 +10272,7 @@ var init_runtime_status = __esm({
|
|
|
9325
10272
|
});
|
|
9326
10273
|
|
|
9327
10274
|
// packages/server/src/commands/session.ts
|
|
9328
|
-
import { z as
|
|
10275
|
+
import { z as z10 } from "zod";
|
|
9329
10276
|
function getProviderFromRegistry(providerId, registry) {
|
|
9330
10277
|
return registry.find((provider) => provider.id === providerId);
|
|
9331
10278
|
}
|
|
@@ -9336,8 +10283,8 @@ var init_session = __esm({
|
|
|
9336
10283
|
init_dispatch();
|
|
9337
10284
|
registerCommand(
|
|
9338
10285
|
"session.list",
|
|
9339
|
-
|
|
9340
|
-
workspaceId:
|
|
10286
|
+
z10.object({
|
|
10287
|
+
workspaceId: z10.string()
|
|
9341
10288
|
}),
|
|
9342
10289
|
async (args, ctx) => {
|
|
9343
10290
|
return ctx.sessionMgr.getForWorkspace(args.workspaceId);
|
|
@@ -9345,10 +10292,10 @@ var init_session = __esm({
|
|
|
9345
10292
|
);
|
|
9346
10293
|
registerCommand(
|
|
9347
10294
|
"session.create",
|
|
9348
|
-
|
|
9349
|
-
workspaceId:
|
|
9350
|
-
providerId:
|
|
9351
|
-
draft:
|
|
10295
|
+
z10.object({
|
|
10296
|
+
workspaceId: z10.string(),
|
|
10297
|
+
providerId: z10.string(),
|
|
10298
|
+
draft: z10.string().optional()
|
|
9352
10299
|
}),
|
|
9353
10300
|
async (args, ctx) => {
|
|
9354
10301
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9382,8 +10329,8 @@ var init_session = __esm({
|
|
|
9382
10329
|
);
|
|
9383
10330
|
registerCommand(
|
|
9384
10331
|
"session.stop",
|
|
9385
|
-
|
|
9386
|
-
sessionId:
|
|
10332
|
+
z10.object({
|
|
10333
|
+
sessionId: z10.string()
|
|
9387
10334
|
}),
|
|
9388
10335
|
async (args, ctx) => {
|
|
9389
10336
|
await ctx.sessionMgr.stop(args.sessionId);
|
|
@@ -9391,8 +10338,8 @@ var init_session = __esm({
|
|
|
9391
10338
|
);
|
|
9392
10339
|
registerCommand(
|
|
9393
10340
|
"session.remove",
|
|
9394
|
-
|
|
9395
|
-
sessionId:
|
|
10341
|
+
z10.object({
|
|
10342
|
+
sessionId: z10.string()
|
|
9396
10343
|
}),
|
|
9397
10344
|
async (args, ctx) => {
|
|
9398
10345
|
const session = ctx.sessionMgr.get(args.sessionId);
|
|
@@ -9410,9 +10357,9 @@ var init_session = __esm({
|
|
|
9410
10357
|
|
|
9411
10358
|
// packages/server/src/fs/tree.ts
|
|
9412
10359
|
import { readdir as readdir3, stat as stat6 } from "fs/promises";
|
|
9413
|
-
import { join as
|
|
10360
|
+
import { join as join6, relative as relative4 } from "path";
|
|
9414
10361
|
async function readTree(rootPath, subdir) {
|
|
9415
|
-
const targetPath = subdir ?
|
|
10362
|
+
const targetPath = subdir ? join6(rootPath, subdir) : rootPath;
|
|
9416
10363
|
const filter = createGitignoreFilter(rootPath, targetPath);
|
|
9417
10364
|
const entries = await readdir3(targetPath, { withFileTypes: true });
|
|
9418
10365
|
const nodes = [];
|
|
@@ -9420,7 +10367,7 @@ async function readTree(rootPath, subdir) {
|
|
|
9420
10367
|
if (!filter(entry.name)) {
|
|
9421
10368
|
continue;
|
|
9422
10369
|
}
|
|
9423
|
-
const fullPath =
|
|
10370
|
+
const fullPath = join6(targetPath, entry.name);
|
|
9424
10371
|
const relPath = relative4(rootPath, fullPath);
|
|
9425
10372
|
if (entry.isDirectory()) {
|
|
9426
10373
|
nodes.push({
|
|
@@ -9464,7 +10411,7 @@ async function searchFiles(rootPath, query, limit = 10) {
|
|
|
9464
10411
|
const filteredEntries = entries.filter((entry) => filter(entry.name));
|
|
9465
10412
|
filteredEntries.sort((a, b) => a.name.localeCompare(b.name));
|
|
9466
10413
|
for (const entry of filteredEntries) {
|
|
9467
|
-
const fullPath =
|
|
10414
|
+
const fullPath = join6(dirPath, entry.name);
|
|
9468
10415
|
const relPath = relative4(rootPath, fullPath);
|
|
9469
10416
|
if (entry.isDirectory()) {
|
|
9470
10417
|
await walk(fullPath);
|
|
@@ -9557,7 +10504,7 @@ var init_tree = __esm({
|
|
|
9557
10504
|
});
|
|
9558
10505
|
|
|
9559
10506
|
// packages/server/src/commands/file.ts
|
|
9560
|
-
import { z as
|
|
10507
|
+
import { z as z11 } from "zod";
|
|
9561
10508
|
var init_file = __esm({
|
|
9562
10509
|
"packages/server/src/commands/file.ts"() {
|
|
9563
10510
|
"use strict";
|
|
@@ -9566,9 +10513,9 @@ var init_file = __esm({
|
|
|
9566
10513
|
init_dispatch();
|
|
9567
10514
|
registerCommand(
|
|
9568
10515
|
"file.readTree",
|
|
9569
|
-
|
|
9570
|
-
workspaceId:
|
|
9571
|
-
subPath:
|
|
10516
|
+
z11.object({
|
|
10517
|
+
workspaceId: z11.string(),
|
|
10518
|
+
subPath: z11.string().optional()
|
|
9572
10519
|
}),
|
|
9573
10520
|
async (args, ctx) => {
|
|
9574
10521
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9580,10 +10527,10 @@ var init_file = __esm({
|
|
|
9580
10527
|
);
|
|
9581
10528
|
registerCommand(
|
|
9582
10529
|
"file.search",
|
|
9583
|
-
|
|
9584
|
-
workspaceId:
|
|
9585
|
-
query:
|
|
9586
|
-
limit:
|
|
10530
|
+
z11.object({
|
|
10531
|
+
workspaceId: z11.string(),
|
|
10532
|
+
query: z11.string(),
|
|
10533
|
+
limit: z11.number().int().positive().max(50).optional()
|
|
9587
10534
|
}),
|
|
9588
10535
|
async (args, ctx) => {
|
|
9589
10536
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9595,9 +10542,9 @@ var init_file = __esm({
|
|
|
9595
10542
|
);
|
|
9596
10543
|
registerCommand(
|
|
9597
10544
|
"file.read",
|
|
9598
|
-
|
|
9599
|
-
workspaceId:
|
|
9600
|
-
path:
|
|
10545
|
+
z11.object({
|
|
10546
|
+
workspaceId: z11.string(),
|
|
10547
|
+
path: z11.string()
|
|
9601
10548
|
}),
|
|
9602
10549
|
async (args, ctx) => {
|
|
9603
10550
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9609,9 +10556,9 @@ var init_file = __esm({
|
|
|
9609
10556
|
);
|
|
9610
10557
|
registerCommand(
|
|
9611
10558
|
"file.create",
|
|
9612
|
-
|
|
9613
|
-
workspaceId:
|
|
9614
|
-
path:
|
|
10559
|
+
z11.object({
|
|
10560
|
+
workspaceId: z11.string(),
|
|
10561
|
+
path: z11.string()
|
|
9615
10562
|
}),
|
|
9616
10563
|
async (args, ctx) => {
|
|
9617
10564
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9629,9 +10576,9 @@ var init_file = __esm({
|
|
|
9629
10576
|
);
|
|
9630
10577
|
registerCommand(
|
|
9631
10578
|
"file.mkdir",
|
|
9632
|
-
|
|
9633
|
-
workspaceId:
|
|
9634
|
-
path:
|
|
10579
|
+
z11.object({
|
|
10580
|
+
workspaceId: z11.string(),
|
|
10581
|
+
path: z11.string()
|
|
9635
10582
|
}),
|
|
9636
10583
|
async (args, ctx) => {
|
|
9637
10584
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9649,9 +10596,9 @@ var init_file = __esm({
|
|
|
9649
10596
|
);
|
|
9650
10597
|
registerCommand(
|
|
9651
10598
|
"file.delete",
|
|
9652
|
-
|
|
9653
|
-
workspaceId:
|
|
9654
|
-
path:
|
|
10599
|
+
z11.object({
|
|
10600
|
+
workspaceId: z11.string(),
|
|
10601
|
+
path: z11.string()
|
|
9655
10602
|
}),
|
|
9656
10603
|
async (args, ctx) => {
|
|
9657
10604
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9669,11 +10616,11 @@ var init_file = __esm({
|
|
|
9669
10616
|
);
|
|
9670
10617
|
registerCommand(
|
|
9671
10618
|
"file.write",
|
|
9672
|
-
|
|
9673
|
-
workspaceId:
|
|
9674
|
-
path:
|
|
9675
|
-
content:
|
|
9676
|
-
baseHash:
|
|
10619
|
+
z11.object({
|
|
10620
|
+
workspaceId: z11.string(),
|
|
10621
|
+
path: z11.string(),
|
|
10622
|
+
content: z11.string(),
|
|
10623
|
+
baseHash: z11.string().optional()
|
|
9677
10624
|
// For conflict detection
|
|
9678
10625
|
}),
|
|
9679
10626
|
async (args, ctx) => {
|
|
@@ -9764,7 +10711,7 @@ var init_git_events = __esm({
|
|
|
9764
10711
|
});
|
|
9765
10712
|
|
|
9766
10713
|
// packages/server/src/commands/git.ts
|
|
9767
|
-
import { z as
|
|
10714
|
+
import { z as z12 } from "zod";
|
|
9768
10715
|
async function runGitNetworkOperation(ctx, workspaceId, op) {
|
|
9769
10716
|
if (!ctx.autoFetch?.runExclusive) {
|
|
9770
10717
|
return op();
|
|
@@ -9779,16 +10726,16 @@ var init_git2 = __esm({
|
|
|
9779
10726
|
init_diff();
|
|
9780
10727
|
init_dispatch();
|
|
9781
10728
|
init_git_events();
|
|
9782
|
-
gitHttpAuthSchema =
|
|
9783
|
-
username:
|
|
9784
|
-
password:
|
|
10729
|
+
gitHttpAuthSchema = z12.object({
|
|
10730
|
+
username: z12.string(),
|
|
10731
|
+
password: z12.string()
|
|
9785
10732
|
});
|
|
9786
|
-
gitCommitRevisionSchema =
|
|
10733
|
+
gitCommitRevisionSchema = z12.string().regex(/^[0-9a-fA-F]{7,64}$/, "Invalid git commit revision");
|
|
9787
10734
|
GIT_BACKGROUND_FETCH_TIMEOUT_MS = 30 * 1e3;
|
|
9788
10735
|
registerCommand(
|
|
9789
10736
|
"git.status",
|
|
9790
|
-
|
|
9791
|
-
workspaceId:
|
|
10737
|
+
z12.object({
|
|
10738
|
+
workspaceId: z12.string()
|
|
9792
10739
|
}),
|
|
9793
10740
|
async (args, ctx) => {
|
|
9794
10741
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9800,9 +10747,9 @@ var init_git2 = __esm({
|
|
|
9800
10747
|
);
|
|
9801
10748
|
registerCommand(
|
|
9802
10749
|
"git.stage",
|
|
9803
|
-
|
|
9804
|
-
workspaceId:
|
|
9805
|
-
paths:
|
|
10750
|
+
z12.object({
|
|
10751
|
+
workspaceId: z12.string(),
|
|
10752
|
+
paths: z12.array(z12.string())
|
|
9806
10753
|
}),
|
|
9807
10754
|
async (args, ctx) => {
|
|
9808
10755
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9816,10 +10763,10 @@ var init_git2 = __esm({
|
|
|
9816
10763
|
);
|
|
9817
10764
|
registerCommand(
|
|
9818
10765
|
"git.diff",
|
|
9819
|
-
|
|
9820
|
-
workspaceId:
|
|
9821
|
-
path:
|
|
9822
|
-
staged:
|
|
10766
|
+
z12.object({
|
|
10767
|
+
workspaceId: z12.string(),
|
|
10768
|
+
path: z12.string(),
|
|
10769
|
+
staged: z12.boolean().optional()
|
|
9823
10770
|
}),
|
|
9824
10771
|
async (args, ctx) => {
|
|
9825
10772
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9833,9 +10780,9 @@ var init_git2 = __esm({
|
|
|
9833
10780
|
);
|
|
9834
10781
|
registerCommand(
|
|
9835
10782
|
"git.log",
|
|
9836
|
-
|
|
9837
|
-
workspaceId:
|
|
9838
|
-
limit:
|
|
10783
|
+
z12.object({
|
|
10784
|
+
workspaceId: z12.string(),
|
|
10785
|
+
limit: z12.number().int().min(1).max(50).optional()
|
|
9839
10786
|
}),
|
|
9840
10787
|
async (args, ctx) => {
|
|
9841
10788
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9849,8 +10796,8 @@ var init_git2 = __esm({
|
|
|
9849
10796
|
);
|
|
9850
10797
|
registerCommand(
|
|
9851
10798
|
"git.show",
|
|
9852
|
-
|
|
9853
|
-
workspaceId:
|
|
10799
|
+
z12.object({
|
|
10800
|
+
workspaceId: z12.string(),
|
|
9854
10801
|
sha: gitCommitRevisionSchema
|
|
9855
10802
|
}),
|
|
9856
10803
|
async (args, ctx) => {
|
|
@@ -9865,9 +10812,9 @@ var init_git2 = __esm({
|
|
|
9865
10812
|
);
|
|
9866
10813
|
registerCommand(
|
|
9867
10814
|
"git.unstage",
|
|
9868
|
-
|
|
9869
|
-
workspaceId:
|
|
9870
|
-
paths:
|
|
10815
|
+
z12.object({
|
|
10816
|
+
workspaceId: z12.string(),
|
|
10817
|
+
paths: z12.array(z12.string())
|
|
9871
10818
|
}),
|
|
9872
10819
|
async (args, ctx) => {
|
|
9873
10820
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9881,9 +10828,9 @@ var init_git2 = __esm({
|
|
|
9881
10828
|
);
|
|
9882
10829
|
registerCommand(
|
|
9883
10830
|
"git.discard",
|
|
9884
|
-
|
|
9885
|
-
workspaceId:
|
|
9886
|
-
paths:
|
|
10831
|
+
z12.object({
|
|
10832
|
+
workspaceId: z12.string(),
|
|
10833
|
+
paths: z12.array(z12.string())
|
|
9887
10834
|
}),
|
|
9888
10835
|
async (args, ctx) => {
|
|
9889
10836
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9899,9 +10846,9 @@ var init_git2 = __esm({
|
|
|
9899
10846
|
);
|
|
9900
10847
|
registerCommand(
|
|
9901
10848
|
"git.commit",
|
|
9902
|
-
|
|
9903
|
-
workspaceId:
|
|
9904
|
-
message:
|
|
10849
|
+
z12.object({
|
|
10850
|
+
workspaceId: z12.string(),
|
|
10851
|
+
message: z12.string()
|
|
9905
10852
|
}),
|
|
9906
10853
|
async (args, ctx) => {
|
|
9907
10854
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -9918,11 +10865,11 @@ var init_git2 = __esm({
|
|
|
9918
10865
|
);
|
|
9919
10866
|
registerCommand(
|
|
9920
10867
|
"git.push",
|
|
9921
|
-
|
|
9922
|
-
workspaceId:
|
|
9923
|
-
remote:
|
|
9924
|
-
branch:
|
|
9925
|
-
force:
|
|
10868
|
+
z12.object({
|
|
10869
|
+
workspaceId: z12.string(),
|
|
10870
|
+
remote: z12.string().optional(),
|
|
10871
|
+
branch: z12.string().optional(),
|
|
10872
|
+
force: z12.boolean().optional(),
|
|
9926
10873
|
auth: gitHttpAuthSchema.optional()
|
|
9927
10874
|
}),
|
|
9928
10875
|
async (args, ctx) => {
|
|
@@ -9949,10 +10896,10 @@ var init_git2 = __esm({
|
|
|
9949
10896
|
);
|
|
9950
10897
|
registerCommand(
|
|
9951
10898
|
"git.pull",
|
|
9952
|
-
|
|
9953
|
-
workspaceId:
|
|
9954
|
-
remote:
|
|
9955
|
-
branch:
|
|
10899
|
+
z12.object({
|
|
10900
|
+
workspaceId: z12.string(),
|
|
10901
|
+
remote: z12.string().optional(),
|
|
10902
|
+
branch: z12.string().optional(),
|
|
9956
10903
|
auth: gitHttpAuthSchema.optional()
|
|
9957
10904
|
}),
|
|
9958
10905
|
async (args, ctx) => {
|
|
@@ -9980,12 +10927,12 @@ var init_git2 = __esm({
|
|
|
9980
10927
|
);
|
|
9981
10928
|
registerCommand(
|
|
9982
10929
|
"git.fetch",
|
|
9983
|
-
|
|
9984
|
-
workspaceId:
|
|
9985
|
-
remote:
|
|
9986
|
-
prune:
|
|
10930
|
+
z12.object({
|
|
10931
|
+
workspaceId: z12.string(),
|
|
10932
|
+
remote: z12.string().optional(),
|
|
10933
|
+
prune: z12.boolean().optional(),
|
|
9987
10934
|
auth: gitHttpAuthSchema.optional(),
|
|
9988
|
-
background:
|
|
10935
|
+
background: z12.boolean().optional()
|
|
9989
10936
|
}),
|
|
9990
10937
|
async (args, ctx, clientId) => {
|
|
9991
10938
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -10014,10 +10961,10 @@ var init_git2 = __esm({
|
|
|
10014
10961
|
);
|
|
10015
10962
|
registerCommand(
|
|
10016
10963
|
"git.checkout",
|
|
10017
|
-
|
|
10018
|
-
workspaceId:
|
|
10019
|
-
ref:
|
|
10020
|
-
createBranch:
|
|
10964
|
+
z12.object({
|
|
10965
|
+
workspaceId: z12.string(),
|
|
10966
|
+
ref: z12.string(),
|
|
10967
|
+
createBranch: z12.boolean().optional()
|
|
10021
10968
|
}),
|
|
10022
10969
|
async (args, ctx) => {
|
|
10023
10970
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -10039,10 +10986,10 @@ var init_git2 = __esm({
|
|
|
10039
10986
|
);
|
|
10040
10987
|
registerCommand(
|
|
10041
10988
|
"git.branch",
|
|
10042
|
-
|
|
10043
|
-
workspaceId:
|
|
10044
|
-
name:
|
|
10045
|
-
startPoint:
|
|
10989
|
+
z12.object({
|
|
10990
|
+
workspaceId: z12.string(),
|
|
10991
|
+
name: z12.string(),
|
|
10992
|
+
startPoint: z12.string().optional()
|
|
10046
10993
|
}),
|
|
10047
10994
|
async (args, ctx) => {
|
|
10048
10995
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -10061,8 +11008,8 @@ var init_git2 = __esm({
|
|
|
10061
11008
|
);
|
|
10062
11009
|
registerCommand(
|
|
10063
11010
|
"git.branches",
|
|
10064
|
-
|
|
10065
|
-
workspaceId:
|
|
11011
|
+
z12.object({
|
|
11012
|
+
workspaceId: z12.string()
|
|
10066
11013
|
}),
|
|
10067
11014
|
async (args, ctx) => {
|
|
10068
11015
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -10076,37 +11023,37 @@ var init_git2 = __esm({
|
|
|
10076
11023
|
});
|
|
10077
11024
|
|
|
10078
11025
|
// packages/server/src/config/config-io.ts
|
|
10079
|
-
import { existsSync as
|
|
10080
|
-
import { homedir as
|
|
10081
|
-
import { basename as
|
|
11026
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6, renameSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
11027
|
+
import { homedir as homedir3 } from "node:os";
|
|
11028
|
+
import { basename as basename2, dirname as dirname4, join as join7 } from "node:path";
|
|
10082
11029
|
function resolveConfigPath(configType) {
|
|
10083
11030
|
if (configType === "codex") {
|
|
10084
11031
|
const testHome = process.env.CODER_STUDIO_CODEX_HOME;
|
|
10085
11032
|
if (testHome && testHome.trim()) {
|
|
10086
|
-
return
|
|
11033
|
+
return join7(testHome, "config.toml");
|
|
10087
11034
|
}
|
|
10088
11035
|
const codexHome = process.env.CODEX_HOME;
|
|
10089
11036
|
if (codexHome && codexHome.trim()) {
|
|
10090
|
-
return
|
|
11037
|
+
return join7(codexHome, "config.toml");
|
|
10091
11038
|
}
|
|
10092
|
-
return
|
|
11039
|
+
return join7(homedir3(), ".codex", "config.toml");
|
|
10093
11040
|
}
|
|
10094
11041
|
if (configType === "claude") {
|
|
10095
11042
|
const testHome = process.env.CODER_STUDIO_CLAUDE_HOME;
|
|
10096
11043
|
if (testHome && testHome.trim()) {
|
|
10097
|
-
return
|
|
11044
|
+
return join7(testHome, "settings.json");
|
|
10098
11045
|
}
|
|
10099
|
-
return
|
|
11046
|
+
return join7(homedir3(), ".claude", "settings.json");
|
|
10100
11047
|
}
|
|
10101
11048
|
throw new Error(`Unknown config type: ${configType}`);
|
|
10102
11049
|
}
|
|
10103
11050
|
function readConfigFile(configType) {
|
|
10104
11051
|
const configPath = resolveConfigPath(configType);
|
|
10105
|
-
if (!
|
|
11052
|
+
if (!existsSync6(configPath)) {
|
|
10106
11053
|
return { configPath, content: "", exists: false };
|
|
10107
11054
|
}
|
|
10108
11055
|
try {
|
|
10109
|
-
const content =
|
|
11056
|
+
const content = readFileSync6(configPath, "utf-8");
|
|
10110
11057
|
return { configPath, content, exists: true };
|
|
10111
11058
|
} catch {
|
|
10112
11059
|
return { configPath, content: "", exists: false };
|
|
@@ -10115,16 +11062,16 @@ function readConfigFile(configType) {
|
|
|
10115
11062
|
function writeConfigFile(configType, content) {
|
|
10116
11063
|
try {
|
|
10117
11064
|
const configPath = resolveConfigPath(configType);
|
|
10118
|
-
const parentDir =
|
|
10119
|
-
if (!
|
|
10120
|
-
|
|
11065
|
+
const parentDir = dirname4(configPath);
|
|
11066
|
+
if (!existsSync6(parentDir)) {
|
|
11067
|
+
mkdirSync3(parentDir, { recursive: true });
|
|
10121
11068
|
}
|
|
10122
11069
|
let backupPath = null;
|
|
10123
|
-
if (
|
|
11070
|
+
if (existsSync6(configPath)) {
|
|
10124
11071
|
backupPath = createBackup(configPath);
|
|
10125
11072
|
}
|
|
10126
11073
|
const tempPath = `${configPath}.tmp`;
|
|
10127
|
-
|
|
11074
|
+
writeFileSync3(tempPath, content, "utf-8");
|
|
10128
11075
|
renameSync(tempPath, configPath);
|
|
10129
11076
|
return { success: true, backupPath };
|
|
10130
11077
|
} catch (error) {
|
|
@@ -10136,13 +11083,13 @@ function writeConfigFile(configType, content) {
|
|
|
10136
11083
|
}
|
|
10137
11084
|
}
|
|
10138
11085
|
function createBackup(filePath) {
|
|
10139
|
-
const original =
|
|
11086
|
+
const original = readFileSync6(filePath, "utf-8");
|
|
10140
11087
|
const ext = filePath.split(".").pop() ?? "";
|
|
10141
|
-
const base =
|
|
10142
|
-
const dir =
|
|
11088
|
+
const base = basename2(filePath, `.${ext}`);
|
|
11089
|
+
const dir = dirname4(filePath);
|
|
10143
11090
|
const ts = formatTimestamp(/* @__PURE__ */ new Date());
|
|
10144
|
-
const backupPath =
|
|
10145
|
-
|
|
11091
|
+
const backupPath = join7(dir, `${base}.bak.${ts}.${ext}`);
|
|
11092
|
+
writeFileSync3(backupPath, original, "utf-8");
|
|
10146
11093
|
return backupPath;
|
|
10147
11094
|
}
|
|
10148
11095
|
function formatTimestamp(d) {
|
|
@@ -10156,7 +11103,7 @@ var init_config_io = __esm({
|
|
|
10156
11103
|
});
|
|
10157
11104
|
|
|
10158
11105
|
// packages/server/src/commands/settings.ts
|
|
10159
|
-
import { z as
|
|
11106
|
+
import { z as z13 } from "zod";
|
|
10160
11107
|
function flattenSettings(obj, prefix = "") {
|
|
10161
11108
|
const result = {};
|
|
10162
11109
|
for (const [key, value] of Object.entries(obj)) {
|
|
@@ -10179,28 +11126,34 @@ var init_settings2 = __esm({
|
|
|
10179
11126
|
init_provider_config_repo();
|
|
10180
11127
|
init_settings();
|
|
10181
11128
|
init_dispatch();
|
|
10182
|
-
SettingsSchema =
|
|
10183
|
-
defaultProviderId:
|
|
10184
|
-
notifications:
|
|
10185
|
-
enabled:
|
|
10186
|
-
soundEnabled:
|
|
11129
|
+
SettingsSchema = z13.object({
|
|
11130
|
+
defaultProviderId: z13.string().optional(),
|
|
11131
|
+
notifications: z13.object({
|
|
11132
|
+
enabled: z13.boolean().optional(),
|
|
11133
|
+
soundEnabled: z13.boolean().optional(),
|
|
10187
11134
|
// Legacy field — accepted for backward compat with older clients but
|
|
10188
11135
|
// no longer surfaced in the UI. The web client now picks the channel
|
|
10189
11136
|
// automatically based on workspace focus + page visibility.
|
|
10190
|
-
onlyWhenBackgrounded:
|
|
11137
|
+
onlyWhenBackgrounded: z13.boolean().optional()
|
|
10191
11138
|
}).optional(),
|
|
10192
|
-
supervisor:
|
|
10193
|
-
evaluationTimeoutSec:
|
|
11139
|
+
supervisor: z13.object({
|
|
11140
|
+
evaluationTimeoutSec: z13.number().int().min(1).max(MAX_SUPERVISOR_EVALUATION_TIMEOUT_SEC).default(DEFAULT_SUPERVISOR_EVALUATION_TIMEOUT_SEC).optional(),
|
|
11141
|
+
retryEnabled: z13.boolean().optional(),
|
|
11142
|
+
retryMaxCount: z13.number().int().min(0).max(MAX_SUPERVISOR_RETRY_MAX_COUNT).optional(),
|
|
11143
|
+
retryDelaySec: z13.number().int().min(1).max(MAX_SUPERVISOR_RETRY_DELAY_SEC).optional(),
|
|
11144
|
+
retryOnTimeout: z13.boolean().optional(),
|
|
11145
|
+
retryOnEvaluatorError: z13.boolean().optional()
|
|
10194
11146
|
}).optional(),
|
|
10195
|
-
appearance:
|
|
10196
|
-
theme:
|
|
10197
|
-
|
|
10198
|
-
|
|
10199
|
-
|
|
11147
|
+
appearance: z13.object({
|
|
11148
|
+
theme: z13.enum(["dark", "light"]).optional(),
|
|
11149
|
+
themeId: z13.string().optional(),
|
|
11150
|
+
terminalRenderer: z13.enum(["standard", "compatibility"]).optional(),
|
|
11151
|
+
terminalCopyOnSelect: z13.boolean().optional(),
|
|
11152
|
+
locale: z13.enum(["zh", "en"]).optional()
|
|
10200
11153
|
}).optional(),
|
|
10201
11154
|
providers: ProviderSettingsSchema.optional()
|
|
10202
11155
|
});
|
|
10203
|
-
registerCommand("settings.get",
|
|
11156
|
+
registerCommand("settings.get", z13.object({}), async (_args, ctx) => {
|
|
10204
11157
|
const row = ctx.db.prepare("SELECT key, value FROM user_settings").all();
|
|
10205
11158
|
const settings = {};
|
|
10206
11159
|
for (const { key, value } of row) {
|
|
@@ -10229,11 +11182,36 @@ var init_settings2 = __esm({
|
|
|
10229
11182
|
settings[SUPERVISOR_EVALUATION_TIMEOUT_SETTING_KEY]
|
|
10230
11183
|
);
|
|
10231
11184
|
}
|
|
11185
|
+
if (Object.prototype.hasOwnProperty.call(settings, SUPERVISOR_RETRY_ENABLED_SETTING_KEY)) {
|
|
11186
|
+
settings[SUPERVISOR_RETRY_ENABLED_SETTING_KEY] = resolveSupervisorRetryEnabled(
|
|
11187
|
+
settings[SUPERVISOR_RETRY_ENABLED_SETTING_KEY]
|
|
11188
|
+
);
|
|
11189
|
+
}
|
|
11190
|
+
if (Object.prototype.hasOwnProperty.call(settings, SUPERVISOR_RETRY_MAX_COUNT_SETTING_KEY)) {
|
|
11191
|
+
settings[SUPERVISOR_RETRY_MAX_COUNT_SETTING_KEY] = resolveSupervisorRetryMaxCount(
|
|
11192
|
+
settings[SUPERVISOR_RETRY_MAX_COUNT_SETTING_KEY]
|
|
11193
|
+
);
|
|
11194
|
+
}
|
|
11195
|
+
if (Object.prototype.hasOwnProperty.call(settings, SUPERVISOR_RETRY_DELAY_SEC_SETTING_KEY)) {
|
|
11196
|
+
settings[SUPERVISOR_RETRY_DELAY_SEC_SETTING_KEY] = resolveSupervisorRetryDelaySec(
|
|
11197
|
+
settings[SUPERVISOR_RETRY_DELAY_SEC_SETTING_KEY]
|
|
11198
|
+
);
|
|
11199
|
+
}
|
|
11200
|
+
if (Object.prototype.hasOwnProperty.call(settings, SUPERVISOR_RETRY_ON_TIMEOUT_SETTING_KEY)) {
|
|
11201
|
+
settings[SUPERVISOR_RETRY_ON_TIMEOUT_SETTING_KEY] = resolveSupervisorRetryOnTimeout(
|
|
11202
|
+
settings[SUPERVISOR_RETRY_ON_TIMEOUT_SETTING_KEY]
|
|
11203
|
+
);
|
|
11204
|
+
}
|
|
11205
|
+
if (Object.prototype.hasOwnProperty.call(settings, SUPERVISOR_RETRY_ON_EVALUATOR_ERROR_SETTING_KEY)) {
|
|
11206
|
+
settings[SUPERVISOR_RETRY_ON_EVALUATOR_ERROR_SETTING_KEY] = resolveSupervisorRetryOnEvaluatorError(
|
|
11207
|
+
settings[SUPERVISOR_RETRY_ON_EVALUATOR_ERROR_SETTING_KEY]
|
|
11208
|
+
);
|
|
11209
|
+
}
|
|
10232
11210
|
return settings;
|
|
10233
11211
|
});
|
|
10234
11212
|
registerCommand(
|
|
10235
11213
|
"settings.update",
|
|
10236
|
-
|
|
11214
|
+
z13.object({
|
|
10237
11215
|
settings: SettingsSchema
|
|
10238
11216
|
}),
|
|
10239
11217
|
async (args, ctx) => {
|
|
@@ -10265,10 +11243,10 @@ var init_settings2 = __esm({
|
|
|
10265
11243
|
);
|
|
10266
11244
|
registerCommand(
|
|
10267
11245
|
"settings.previewCommand",
|
|
10268
|
-
|
|
10269
|
-
providerId:
|
|
11246
|
+
z13.object({
|
|
11247
|
+
providerId: z13.string(),
|
|
10270
11248
|
config: ProviderLaunchConfigInputSchema,
|
|
10271
|
-
workspacePath:
|
|
11249
|
+
workspacePath: z13.string().optional()
|
|
10272
11250
|
}),
|
|
10273
11251
|
async (args, ctx) => {
|
|
10274
11252
|
const provider = ctx.providerRegistry.find((item) => item.id === args.providerId);
|
|
@@ -10289,8 +11267,8 @@ var init_settings2 = __esm({
|
|
|
10289
11267
|
);
|
|
10290
11268
|
registerCommand(
|
|
10291
11269
|
"settings.readConfigFile",
|
|
10292
|
-
|
|
10293
|
-
configType:
|
|
11270
|
+
z13.object({
|
|
11271
|
+
configType: z13.enum(["codex", "claude"])
|
|
10294
11272
|
}),
|
|
10295
11273
|
async (args) => {
|
|
10296
11274
|
const result = readConfigFile(args.configType);
|
|
@@ -10299,9 +11277,9 @@ var init_settings2 = __esm({
|
|
|
10299
11277
|
);
|
|
10300
11278
|
registerCommand(
|
|
10301
11279
|
"settings.writeConfigFile",
|
|
10302
|
-
|
|
10303
|
-
configType:
|
|
10304
|
-
content:
|
|
11280
|
+
z13.object({
|
|
11281
|
+
configType: z13.enum(["codex", "claude"]),
|
|
11282
|
+
content: z13.string()
|
|
10305
11283
|
}),
|
|
10306
11284
|
async (args) => {
|
|
10307
11285
|
const result = writeConfigFile(args.configType, args.content);
|
|
@@ -10312,19 +11290,19 @@ var init_settings2 = __esm({
|
|
|
10312
11290
|
});
|
|
10313
11291
|
|
|
10314
11292
|
// packages/server/src/commands/provider.ts
|
|
10315
|
-
import { z as
|
|
11293
|
+
import { z as z14 } from "zod";
|
|
10316
11294
|
var init_provider = __esm({
|
|
10317
11295
|
"packages/server/src/commands/provider.ts"() {
|
|
10318
11296
|
"use strict";
|
|
10319
11297
|
init_runtime_status();
|
|
10320
11298
|
init_dispatch();
|
|
10321
|
-
registerCommand("provider.runtimeStatus",
|
|
11299
|
+
registerCommand("provider.runtimeStatus", z14.object({}), async (_args, ctx) => {
|
|
10322
11300
|
return buildProviderRuntimeStatus(ctx.providerRegistry, ctx.providerRuntimeDeps);
|
|
10323
11301
|
});
|
|
10324
11302
|
registerCommand(
|
|
10325
11303
|
"provider.install.start",
|
|
10326
|
-
|
|
10327
|
-
providerId:
|
|
11304
|
+
z14.object({
|
|
11305
|
+
providerId: z14.string()
|
|
10328
11306
|
}),
|
|
10329
11307
|
async (args, ctx) => {
|
|
10330
11308
|
if (!ctx.providerInstallMgr) {
|
|
@@ -10338,8 +11316,8 @@ var init_provider = __esm({
|
|
|
10338
11316
|
);
|
|
10339
11317
|
registerCommand(
|
|
10340
11318
|
"provider.install.get",
|
|
10341
|
-
|
|
10342
|
-
jobId:
|
|
11319
|
+
z14.object({
|
|
11320
|
+
jobId: z14.string()
|
|
10343
11321
|
}),
|
|
10344
11322
|
async (args, ctx) => {
|
|
10345
11323
|
if (!ctx.providerInstallMgr) {
|
|
@@ -10362,36 +11340,45 @@ var init_provider = __esm({
|
|
|
10362
11340
|
});
|
|
10363
11341
|
|
|
10364
11342
|
// packages/server/src/commands/supervisor.ts
|
|
10365
|
-
import { z as
|
|
11343
|
+
import { z as z15 } from "zod";
|
|
10366
11344
|
var supervisorObjectiveSchema, createSupervisorSchema, updateSupervisorSchema, sessionIdSchema, supervisorIdSchema;
|
|
10367
11345
|
var init_supervisor2 = __esm({
|
|
10368
11346
|
"packages/server/src/commands/supervisor.ts"() {
|
|
10369
11347
|
"use strict";
|
|
10370
11348
|
init_dispatch();
|
|
10371
|
-
supervisorObjectiveSchema =
|
|
10372
|
-
createSupervisorSchema =
|
|
10373
|
-
sessionId:
|
|
10374
|
-
workspaceId:
|
|
11349
|
+
supervisorObjectiveSchema = z15.string().trim().min(1).max(4e3);
|
|
11350
|
+
createSupervisorSchema = z15.object({
|
|
11351
|
+
sessionId: z15.string(),
|
|
11352
|
+
workspaceId: z15.string(),
|
|
10375
11353
|
objective: supervisorObjectiveSchema,
|
|
10376
|
-
evaluatorProviderId:
|
|
11354
|
+
evaluatorProviderId: z15.string(),
|
|
11355
|
+
evaluatorModel: z15.string().trim().min(1).max(200).optional(),
|
|
11356
|
+
maxSupervisionCount: z15.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),
|
|
11357
|
+
scheduledAt: z15.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional()
|
|
10377
11358
|
}).strict();
|
|
10378
|
-
updateSupervisorSchema =
|
|
10379
|
-
id:
|
|
11359
|
+
updateSupervisorSchema = z15.object({
|
|
11360
|
+
id: z15.string(),
|
|
10380
11361
|
objective: supervisorObjectiveSchema.optional(),
|
|
10381
|
-
evaluatorProviderId:
|
|
11362
|
+
evaluatorProviderId: z15.string().optional(),
|
|
11363
|
+
evaluatorModel: z15.string().trim().min(1).max(200).nullable().optional(),
|
|
11364
|
+
maxSupervisionCount: z15.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),
|
|
11365
|
+
scheduledAt: z15.number().int().min(0).max(Number.MAX_SAFE_INTEGER).nullable().optional()
|
|
10382
11366
|
}).strict().refine(
|
|
10383
|
-
(input) => input.objective !== void 0 || input.evaluatorProviderId !== void 0,
|
|
10384
|
-
"
|
|
11367
|
+
(input) => input.objective !== void 0 || input.evaluatorProviderId !== void 0 || input.evaluatorModel !== void 0 || input.maxSupervisionCount !== void 0 || input.scheduledAt !== void 0,
|
|
11368
|
+
"at least one supervisor field is required"
|
|
10385
11369
|
);
|
|
10386
|
-
sessionIdSchema =
|
|
10387
|
-
supervisorIdSchema =
|
|
11370
|
+
sessionIdSchema = z15.object({ sessionId: z15.string() });
|
|
11371
|
+
supervisorIdSchema = z15.object({ id: z15.string() });
|
|
10388
11372
|
registerCommand("supervisor.create", createSupervisorSchema, async (args, ctx) => {
|
|
10389
11373
|
return {
|
|
10390
11374
|
supervisor: await ctx.supervisorMgr.create({
|
|
10391
11375
|
sessionId: args.sessionId,
|
|
10392
11376
|
workspaceId: args.workspaceId,
|
|
10393
11377
|
objective: args.objective,
|
|
10394
|
-
evaluatorProviderId: args.evaluatorProviderId
|
|
11378
|
+
evaluatorProviderId: args.evaluatorProviderId,
|
|
11379
|
+
evaluatorModel: args.evaluatorModel,
|
|
11380
|
+
maxSupervisionCount: args.maxSupervisionCount,
|
|
11381
|
+
scheduledAt: args.scheduledAt
|
|
10395
11382
|
})
|
|
10396
11383
|
};
|
|
10397
11384
|
});
|
|
@@ -10402,7 +11389,10 @@ var init_supervisor2 = __esm({
|
|
|
10402
11389
|
return {
|
|
10403
11390
|
supervisor: await ctx.supervisorMgr.update(args.id, {
|
|
10404
11391
|
objective: args.objective,
|
|
10405
|
-
evaluatorProviderId: args.evaluatorProviderId
|
|
11392
|
+
evaluatorProviderId: args.evaluatorProviderId,
|
|
11393
|
+
evaluatorModel: args.evaluatorModel,
|
|
11394
|
+
maxSupervisionCount: args.maxSupervisionCount,
|
|
11395
|
+
scheduledAt: args.scheduledAt
|
|
10406
11396
|
})
|
|
10407
11397
|
};
|
|
10408
11398
|
});
|
|
@@ -10562,7 +11552,7 @@ var init_worktree = __esm({
|
|
|
10562
11552
|
|
|
10563
11553
|
// packages/server/src/commands/worktree.ts
|
|
10564
11554
|
import path9 from "node:path";
|
|
10565
|
-
import { z as
|
|
11555
|
+
import { z as z16 } from "zod";
|
|
10566
11556
|
async function findRelatedWorkspaceIds(ctx, workspacePath) {
|
|
10567
11557
|
const targetCommonDir = await getGitCommonDirPath(workspacePath);
|
|
10568
11558
|
const relatedWorkspaceIds = await Promise.all(
|
|
@@ -10595,7 +11585,7 @@ var init_worktree2 = __esm({
|
|
|
10595
11585
|
init_worktree();
|
|
10596
11586
|
init_dispatch();
|
|
10597
11587
|
init_git_events();
|
|
10598
|
-
registerCommand("worktree.list",
|
|
11588
|
+
registerCommand("worktree.list", z16.object({ workspaceId: z16.string() }), async (args, ctx) => {
|
|
10599
11589
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
10600
11590
|
if (!workspace) {
|
|
10601
11591
|
throw { code: "workspace_not_found", message: `Workspace not found: ${args.workspaceId}` };
|
|
@@ -10604,7 +11594,7 @@ var init_worktree2 = __esm({
|
|
|
10604
11594
|
});
|
|
10605
11595
|
registerCommand(
|
|
10606
11596
|
"worktree.status",
|
|
10607
|
-
|
|
11597
|
+
z16.object({ workspaceId: z16.string(), worktreePath: z16.string() }),
|
|
10608
11598
|
async (args, ctx) => {
|
|
10609
11599
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
10610
11600
|
if (!workspace) {
|
|
@@ -10616,10 +11606,10 @@ var init_worktree2 = __esm({
|
|
|
10616
11606
|
);
|
|
10617
11607
|
registerCommand(
|
|
10618
11608
|
"worktree.diff",
|
|
10619
|
-
|
|
10620
|
-
workspaceId:
|
|
10621
|
-
worktreePath:
|
|
10622
|
-
staged:
|
|
11609
|
+
z16.object({
|
|
11610
|
+
workspaceId: z16.string(),
|
|
11611
|
+
worktreePath: z16.string(),
|
|
11612
|
+
staged: z16.boolean().optional().default(false)
|
|
10623
11613
|
}),
|
|
10624
11614
|
async (args, ctx) => {
|
|
10625
11615
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -10632,7 +11622,7 @@ var init_worktree2 = __esm({
|
|
|
10632
11622
|
);
|
|
10633
11623
|
registerCommand(
|
|
10634
11624
|
"worktree.tree",
|
|
10635
|
-
|
|
11625
|
+
z16.object({ workspaceId: z16.string(), worktreePath: z16.string() }),
|
|
10636
11626
|
async (args, ctx) => {
|
|
10637
11627
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
10638
11628
|
if (!workspace) {
|
|
@@ -10644,10 +11634,10 @@ var init_worktree2 = __esm({
|
|
|
10644
11634
|
);
|
|
10645
11635
|
registerCommand(
|
|
10646
11636
|
"worktree.create",
|
|
10647
|
-
|
|
10648
|
-
workspaceId:
|
|
10649
|
-
branch:
|
|
10650
|
-
path:
|
|
11637
|
+
z16.object({
|
|
11638
|
+
workspaceId: z16.string(),
|
|
11639
|
+
branch: z16.string(),
|
|
11640
|
+
path: z16.string()
|
|
10651
11641
|
}),
|
|
10652
11642
|
async (args, ctx) => {
|
|
10653
11643
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -10662,10 +11652,10 @@ var init_worktree2 = __esm({
|
|
|
10662
11652
|
);
|
|
10663
11653
|
registerCommand(
|
|
10664
11654
|
"worktree.remove",
|
|
10665
|
-
|
|
10666
|
-
workspaceId:
|
|
10667
|
-
worktreePath:
|
|
10668
|
-
force:
|
|
11655
|
+
z16.object({
|
|
11656
|
+
workspaceId: z16.string(),
|
|
11657
|
+
worktreePath: z16.string(),
|
|
11658
|
+
force: z16.boolean().optional().default(false)
|
|
10669
11659
|
}),
|
|
10670
11660
|
async (args, ctx) => {
|
|
10671
11661
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -10689,7 +11679,7 @@ var init_worktree2 = __esm({
|
|
|
10689
11679
|
});
|
|
10690
11680
|
|
|
10691
11681
|
// packages/server/src/commands/fencing.ts
|
|
10692
|
-
import { z as
|
|
11682
|
+
import { z as z17 } from "zod";
|
|
10693
11683
|
function createMockFencingRequest() {
|
|
10694
11684
|
return {
|
|
10695
11685
|
ip: "127.0.0.1",
|
|
@@ -10702,9 +11692,9 @@ var init_fencing2 = __esm({
|
|
|
10702
11692
|
init_dispatch();
|
|
10703
11693
|
registerCommand(
|
|
10704
11694
|
"fencing.request",
|
|
10705
|
-
|
|
10706
|
-
workspaceId:
|
|
10707
|
-
tabId:
|
|
11695
|
+
z17.object({
|
|
11696
|
+
workspaceId: z17.string(),
|
|
11697
|
+
tabId: z17.string()
|
|
10708
11698
|
}),
|
|
10709
11699
|
async (args, ctx, clientId) => {
|
|
10710
11700
|
return ctx.fencingMgr.requestControl(
|
|
@@ -10717,7 +11707,7 @@ var init_fencing2 = __esm({
|
|
|
10717
11707
|
);
|
|
10718
11708
|
registerCommand(
|
|
10719
11709
|
"fencing.heartbeat",
|
|
10720
|
-
|
|
11710
|
+
z17.object({ workspaceId: z17.string() }),
|
|
10721
11711
|
async (args, ctx, clientId) => {
|
|
10722
11712
|
const success = ctx.fencingMgr.heartbeat(args.workspaceId, clientId);
|
|
10723
11713
|
return { success };
|
|
@@ -10725,13 +11715,13 @@ var init_fencing2 = __esm({
|
|
|
10725
11715
|
);
|
|
10726
11716
|
registerCommand(
|
|
10727
11717
|
"fencing.release",
|
|
10728
|
-
|
|
11718
|
+
z17.object({ workspaceId: z17.string() }),
|
|
10729
11719
|
async (args, ctx, clientId) => {
|
|
10730
11720
|
ctx.fencingMgr.release(args.workspaceId, clientId);
|
|
10731
11721
|
return {};
|
|
10732
11722
|
}
|
|
10733
11723
|
);
|
|
10734
|
-
registerCommand("fencing.status",
|
|
11724
|
+
registerCommand("fencing.status", z17.object({ workspaceId: z17.string() }), async (args, ctx) => {
|
|
10735
11725
|
const controller = ctx.fencingMgr.getController(args.workspaceId);
|
|
10736
11726
|
const isUnresponsive = ctx.fencingMgr.isControllerUnresponsive(args.workspaceId);
|
|
10737
11727
|
return {
|
|
@@ -10742,9 +11732,9 @@ var init_fencing2 = __esm({
|
|
|
10742
11732
|
});
|
|
10743
11733
|
registerCommand(
|
|
10744
11734
|
"fencing.takeover",
|
|
10745
|
-
|
|
10746
|
-
workspaceId:
|
|
10747
|
-
tabId:
|
|
11735
|
+
z17.object({
|
|
11736
|
+
workspaceId: z17.string(),
|
|
11737
|
+
tabId: z17.string()
|
|
10748
11738
|
}),
|
|
10749
11739
|
async (args, ctx, clientId) => {
|
|
10750
11740
|
return ctx.fencingMgr.forceTakeover(
|
|
@@ -10764,6 +11754,7 @@ var init_commands = __esm({
|
|
|
10764
11754
|
"use strict";
|
|
10765
11755
|
init_workspace();
|
|
10766
11756
|
init_workspace_activity();
|
|
11757
|
+
init_activation2();
|
|
10767
11758
|
init_connection();
|
|
10768
11759
|
init_session();
|
|
10769
11760
|
init_terminal();
|
|
@@ -10783,6 +11774,7 @@ async function createServer(configOverrides) {
|
|
|
10783
11774
|
ensureDataDir(config);
|
|
10784
11775
|
const db = openDatabase(config.dataDir);
|
|
10785
11776
|
const eventBus = new EventBus();
|
|
11777
|
+
const activationMgr = new ActivationManager();
|
|
10786
11778
|
const fencingMgr = new FencingManager();
|
|
10787
11779
|
const wsHub = new WsHub({ eventBus, commandContext: null, config, fencingMgr });
|
|
10788
11780
|
let workspaceMgr;
|
|
@@ -10873,6 +11865,7 @@ async function createServer(configOverrides) {
|
|
|
10873
11865
|
wsHub.setLogger(app.log);
|
|
10874
11866
|
const supervisorRepo = new SupervisorRepo(db);
|
|
10875
11867
|
const cycleRepo = new SupervisorCycleRepo(db);
|
|
11868
|
+
const cycleAttemptRepo = new SupervisorCycleAttemptRepo(db);
|
|
10876
11869
|
supervisorMgr = new SupervisorManager({
|
|
10877
11870
|
eventBus,
|
|
10878
11871
|
broadcaster: wsHub,
|
|
@@ -10884,6 +11877,7 @@ async function createServer(configOverrides) {
|
|
|
10884
11877
|
settingsRepo,
|
|
10885
11878
|
supervisorRepo,
|
|
10886
11879
|
cycleRepo,
|
|
11880
|
+
cycleAttemptRepo,
|
|
10887
11881
|
logger: app.log
|
|
10888
11882
|
});
|
|
10889
11883
|
await sessionMgr.hydrate();
|
|
@@ -10908,7 +11902,8 @@ async function createServer(configOverrides) {
|
|
|
10908
11902
|
supervisorMgr,
|
|
10909
11903
|
autoFetch,
|
|
10910
11904
|
providerRuntimeDeps,
|
|
10911
|
-
providerInstallMgr
|
|
11905
|
+
providerInstallMgr,
|
|
11906
|
+
activationMgr
|
|
10912
11907
|
};
|
|
10913
11908
|
wsHub.setCommandContext(commandContext);
|
|
10914
11909
|
await app.listen({
|
|
@@ -11079,6 +12074,7 @@ var init_server = __esm({
|
|
|
11079
12074
|
init_provider_config_repo();
|
|
11080
12075
|
init_session_repo();
|
|
11081
12076
|
init_settings_repo();
|
|
12077
|
+
init_supervisor_cycle_attempt_repo();
|
|
11082
12078
|
init_supervisor_cycle_repo();
|
|
11083
12079
|
init_supervisor_repo();
|
|
11084
12080
|
init_manager2();
|
|
@@ -11087,6 +12083,7 @@ var init_server = __esm({
|
|
|
11087
12083
|
init_cleanup();
|
|
11088
12084
|
init_constants();
|
|
11089
12085
|
init_manager4();
|
|
12086
|
+
init_activation();
|
|
11090
12087
|
init_dispatch();
|
|
11091
12088
|
init_fencing();
|
|
11092
12089
|
init_hub();
|
|
@@ -11314,6 +12311,7 @@ var init_storage = __esm({
|
|
|
11314
12311
|
init_provider_config_repo();
|
|
11315
12312
|
init_session_repo();
|
|
11316
12313
|
init_settings_repo();
|
|
12314
|
+
init_supervisor_cycle_attempt_repo();
|
|
11317
12315
|
init_supervisor_cycle_repo();
|
|
11318
12316
|
init_supervisor_repo();
|
|
11319
12317
|
init_terminal_repo();
|
|
@@ -11344,6 +12342,7 @@ __export(src_exports, {
|
|
|
11344
12342
|
RingBuffer: () => RingBuffer,
|
|
11345
12343
|
SessionRepo: () => SessionRepo,
|
|
11346
12344
|
SettingsRepo: () => SettingsRepo,
|
|
12345
|
+
SupervisorCycleAttemptRepo: () => SupervisorCycleAttemptRepo,
|
|
11347
12346
|
SupervisorCycleRepo: () => SupervisorCycleRepo,
|
|
11348
12347
|
SupervisorRepo: () => SupervisorRepo,
|
|
11349
12348
|
TerminalManager: () => TerminalManager,
|
|
@@ -11378,22 +12377,25 @@ var init_src4 = __esm({
|
|
|
11378
12377
|
});
|
|
11379
12378
|
|
|
11380
12379
|
// packages/cli/src/server-runner.ts
|
|
12380
|
+
await init_src4();
|
|
12381
|
+
import { mkdirSync as mkdirSync5 } from "fs";
|
|
12382
|
+
import { dirname as dirname6 } from "path";
|
|
11381
12383
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
11382
12384
|
|
|
11383
12385
|
// packages/cli/src/config-store.ts
|
|
11384
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
11385
|
-
import { homedir } from "os";
|
|
11386
|
-
import { basename, join } from "path";
|
|
12386
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
12387
|
+
import { homedir as homedir4 } from "os";
|
|
12388
|
+
import { basename as basename3, join as join8 } from "path";
|
|
11387
12389
|
function getCliConfigPath() {
|
|
11388
|
-
return
|
|
12390
|
+
return join8(homedir4(), ".coder-studio", "config.json");
|
|
11389
12391
|
}
|
|
11390
12392
|
function readCliConfig() {
|
|
11391
12393
|
const path10 = getCliConfigPath();
|
|
11392
|
-
if (!
|
|
12394
|
+
if (!existsSync7(path10)) {
|
|
11393
12395
|
return null;
|
|
11394
12396
|
}
|
|
11395
12397
|
try {
|
|
11396
|
-
const parsed = JSON.parse(
|
|
12398
|
+
const parsed = JSON.parse(readFileSync7(path10, "utf-8"));
|
|
11397
12399
|
if (parsed.host !== void 0 && typeof parsed.host !== "string" || parsed.port !== void 0 && typeof parsed.port !== "number" || parsed.dataDir !== void 0 && typeof parsed.dataDir !== "string" || parsed.password !== void 0 && typeof parsed.password !== "string") {
|
|
11398
12400
|
return null;
|
|
11399
12401
|
}
|
|
@@ -11404,17 +12406,17 @@ function readCliConfig() {
|
|
|
11404
12406
|
}
|
|
11405
12407
|
|
|
11406
12408
|
// packages/cli/src/embed.ts
|
|
11407
|
-
import { existsSync as
|
|
11408
|
-
import { dirname, resolve } from "path";
|
|
12409
|
+
import { existsSync as existsSync8 } from "fs";
|
|
12410
|
+
import { dirname as dirname5, resolve as resolve3 } from "path";
|
|
11409
12411
|
import { fileURLToPath } from "url";
|
|
11410
12412
|
var __filename = fileURLToPath(import.meta.url);
|
|
11411
|
-
var __dirname =
|
|
11412
|
-
var WEB_ASSETS_DIR =
|
|
12413
|
+
var __dirname = dirname5(__filename);
|
|
12414
|
+
var WEB_ASSETS_DIR = resolve3(__dirname, "../web");
|
|
11413
12415
|
function getStaticAssetsDir() {
|
|
11414
12416
|
return WEB_ASSETS_DIR;
|
|
11415
12417
|
}
|
|
11416
12418
|
function hasWebAssets() {
|
|
11417
|
-
return
|
|
12419
|
+
return existsSync8(WEB_ASSETS_DIR);
|
|
11418
12420
|
}
|
|
11419
12421
|
|
|
11420
12422
|
// packages/cli/src/node-version.ts
|
|
@@ -11448,12 +12450,12 @@ function assertSupportedNodeVersion(version = process.versions.node) {
|
|
|
11448
12450
|
}
|
|
11449
12451
|
|
|
11450
12452
|
// packages/cli/src/package-manifest.ts
|
|
11451
|
-
import { existsSync as
|
|
12453
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
|
|
11452
12454
|
function resolveCliPackageManifestUrl(importMetaUrl) {
|
|
11453
12455
|
const manifestUrl = [
|
|
11454
12456
|
new URL("../package.json", importMetaUrl),
|
|
11455
12457
|
new URL("../../package.json", importMetaUrl)
|
|
11456
|
-
].find((candidate) =>
|
|
12458
|
+
].find((candidate) => existsSync9(candidate));
|
|
11457
12459
|
if (!manifestUrl) {
|
|
11458
12460
|
throw new Error("Unable to locate CLI package.json");
|
|
11459
12461
|
}
|
|
@@ -11461,7 +12463,7 @@ function resolveCliPackageManifestUrl(importMetaUrl) {
|
|
|
11461
12463
|
}
|
|
11462
12464
|
function getCliPackageManifest(importMetaUrl) {
|
|
11463
12465
|
return JSON.parse(
|
|
11464
|
-
|
|
12466
|
+
readFileSync8(resolveCliPackageManifestUrl(importMetaUrl), "utf-8")
|
|
11465
12467
|
);
|
|
11466
12468
|
}
|
|
11467
12469
|
function getCliVersion(importMetaUrl) {
|
|
@@ -11493,6 +12495,14 @@ var buildServerConfig = () => {
|
|
|
11493
12495
|
console.warn(MISSING_WEB_ASSETS_WARNING);
|
|
11494
12496
|
return config;
|
|
11495
12497
|
};
|
|
12498
|
+
var verifyLocalDatabaseCompatibility = () => {
|
|
12499
|
+
const config = parseServerConfig(buildServerConfig());
|
|
12500
|
+
if (config.dataDir !== ":memory:") {
|
|
12501
|
+
mkdirSync5(dirname6(config.dataDir), { recursive: true });
|
|
12502
|
+
}
|
|
12503
|
+
const db = openDatabase(config.dataDir);
|
|
12504
|
+
closeDatabase(db);
|
|
12505
|
+
};
|
|
11496
12506
|
var createShutdownHandler = (server) => async () => {
|
|
11497
12507
|
await server.stop();
|
|
11498
12508
|
process.exit(0);
|
|
@@ -11527,6 +12537,7 @@ void runServerEntrypoint(import.meta.url, process.argv[1]);
|
|
|
11527
12537
|
export {
|
|
11528
12538
|
buildServerConfig,
|
|
11529
12539
|
runServerEntrypoint,
|
|
11530
|
-
startServer
|
|
12540
|
+
startServer,
|
|
12541
|
+
verifyLocalDatabaseCompatibility
|
|
11531
12542
|
};
|
|
11532
12543
|
//# sourceMappingURL=server-runner.mjs.map
|