codeharbor 0.1.24 → 0.1.25
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/README.md +1 -1
- package/dist/cli.js +215 -51
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -422,7 +422,7 @@ If any check fails, it prints actionable fix commands (for example `codeharbor i
|
|
|
422
422
|
- each accepted request activates the sender's conversation in that room
|
|
423
423
|
- activation TTL: `SESSION_ACTIVE_WINDOW_MINUTES` (default: `20`)
|
|
424
424
|
- Control commands
|
|
425
|
-
- `/status` show session + limiter + metrics + runtime worker status
|
|
425
|
+
- `/status` show session + limiter + metrics + runtime worker status, current version, and update hint
|
|
426
426
|
- `/reset` clear bound Codex session and keep conversation active
|
|
427
427
|
- `/stop` cancel in-flight execution (if running) and reset session context
|
|
428
428
|
- `/agents status` show multi-agent workflow status for current session (when enabled)
|
package/dist/cli.js
CHANGED
|
@@ -25,8 +25,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
|
|
26
26
|
// src/cli.ts
|
|
27
27
|
var import_node_child_process8 = require("child_process");
|
|
28
|
-
var
|
|
29
|
-
var
|
|
28
|
+
var import_node_fs12 = __toESM(require("fs"));
|
|
29
|
+
var import_node_path16 = __toESM(require("path"));
|
|
30
30
|
var import_commander = require("commander");
|
|
31
31
|
|
|
32
32
|
// src/app.ts
|
|
@@ -4463,6 +4463,163 @@ var CodexSessionRuntime = class {
|
|
|
4463
4463
|
}
|
|
4464
4464
|
};
|
|
4465
4465
|
|
|
4466
|
+
// src/package-update-checker.ts
|
|
4467
|
+
var import_node_fs7 = __toESM(require("fs"));
|
|
4468
|
+
var import_node_path10 = __toESM(require("path"));
|
|
4469
|
+
var NpmRegistryUpdateChecker = class {
|
|
4470
|
+
packageName;
|
|
4471
|
+
currentVersion;
|
|
4472
|
+
ttlMs;
|
|
4473
|
+
timeoutMs;
|
|
4474
|
+
fetchImpl;
|
|
4475
|
+
enabled;
|
|
4476
|
+
upgradeCommand;
|
|
4477
|
+
cachedStatus = null;
|
|
4478
|
+
cacheExpiresAt = 0;
|
|
4479
|
+
constructor(options) {
|
|
4480
|
+
this.packageName = options?.packageName?.trim() || "codeharbor";
|
|
4481
|
+
this.currentVersion = options?.currentVersion?.trim() || resolvePackageVersion();
|
|
4482
|
+
this.ttlMs = options?.ttlMs ?? 6 * 60 * 60 * 1e3;
|
|
4483
|
+
this.timeoutMs = options?.timeoutMs ?? 3e3;
|
|
4484
|
+
this.fetchImpl = options?.fetchImpl ?? fetch;
|
|
4485
|
+
this.enabled = options?.enabled ?? process.env.NODE_ENV !== "test";
|
|
4486
|
+
this.upgradeCommand = `npm install -g ${this.packageName}@latest`;
|
|
4487
|
+
}
|
|
4488
|
+
async getStatus() {
|
|
4489
|
+
const now = Date.now();
|
|
4490
|
+
if (this.cachedStatus && now < this.cacheExpiresAt) {
|
|
4491
|
+
return this.cachedStatus;
|
|
4492
|
+
}
|
|
4493
|
+
let nextStatus;
|
|
4494
|
+
if (!this.enabled) {
|
|
4495
|
+
nextStatus = this.buildStatus({
|
|
4496
|
+
latestVersion: null,
|
|
4497
|
+
state: "unknown",
|
|
4498
|
+
error: "update check disabled"
|
|
4499
|
+
});
|
|
4500
|
+
} else {
|
|
4501
|
+
nextStatus = await this.fetchLatestStatus();
|
|
4502
|
+
}
|
|
4503
|
+
this.cachedStatus = nextStatus;
|
|
4504
|
+
this.cacheExpiresAt = now + this.ttlMs;
|
|
4505
|
+
return nextStatus;
|
|
4506
|
+
}
|
|
4507
|
+
async fetchLatestStatus() {
|
|
4508
|
+
const controller = new AbortController();
|
|
4509
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
4510
|
+
timer.unref?.();
|
|
4511
|
+
try {
|
|
4512
|
+
const response = await this.fetchImpl(`https://registry.npmjs.org/${this.packageName}/latest`, {
|
|
4513
|
+
signal: controller.signal
|
|
4514
|
+
});
|
|
4515
|
+
if (!response.ok) {
|
|
4516
|
+
return this.buildStatus({
|
|
4517
|
+
latestVersion: null,
|
|
4518
|
+
state: "unknown",
|
|
4519
|
+
error: `HTTP ${response.status}`
|
|
4520
|
+
});
|
|
4521
|
+
}
|
|
4522
|
+
const payload = await response.json();
|
|
4523
|
+
const latest = typeof payload.version === "string" ? payload.version.trim() : "";
|
|
4524
|
+
if (!latest) {
|
|
4525
|
+
return this.buildStatus({
|
|
4526
|
+
latestVersion: null,
|
|
4527
|
+
state: "unknown",
|
|
4528
|
+
error: "invalid npm response"
|
|
4529
|
+
});
|
|
4530
|
+
}
|
|
4531
|
+
const comparison = compareSemver(this.currentVersion, latest);
|
|
4532
|
+
if (comparison === null) {
|
|
4533
|
+
return this.buildStatus({
|
|
4534
|
+
latestVersion: latest,
|
|
4535
|
+
state: "unknown",
|
|
4536
|
+
error: "version compare unavailable"
|
|
4537
|
+
});
|
|
4538
|
+
}
|
|
4539
|
+
return this.buildStatus({
|
|
4540
|
+
latestVersion: latest,
|
|
4541
|
+
state: comparison < 0 ? "update_available" : "up_to_date",
|
|
4542
|
+
error: null
|
|
4543
|
+
});
|
|
4544
|
+
} catch (error) {
|
|
4545
|
+
return this.buildStatus({
|
|
4546
|
+
latestVersion: null,
|
|
4547
|
+
state: "unknown",
|
|
4548
|
+
error: normalizeError(error)
|
|
4549
|
+
});
|
|
4550
|
+
} finally {
|
|
4551
|
+
clearTimeout(timer);
|
|
4552
|
+
}
|
|
4553
|
+
}
|
|
4554
|
+
buildStatus(input) {
|
|
4555
|
+
return {
|
|
4556
|
+
packageName: this.packageName,
|
|
4557
|
+
currentVersion: this.currentVersion,
|
|
4558
|
+
latestVersion: input.latestVersion,
|
|
4559
|
+
state: input.state,
|
|
4560
|
+
checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4561
|
+
error: input.error,
|
|
4562
|
+
upgradeCommand: this.upgradeCommand
|
|
4563
|
+
};
|
|
4564
|
+
}
|
|
4565
|
+
};
|
|
4566
|
+
function formatPackageUpdateHint(status) {
|
|
4567
|
+
if (status.state === "update_available" && status.latestVersion) {
|
|
4568
|
+
return `\u53D1\u73B0\u65B0\u7248\u672C ${status.latestVersion}\uFF0C\u5EFA\u8BAE\u6267\u884C\uFF1A${status.upgradeCommand}`;
|
|
4569
|
+
}
|
|
4570
|
+
if (status.state === "up_to_date") {
|
|
4571
|
+
return `\u5DF2\u662F\u6700\u65B0\u7248\u672C${status.latestVersion ? `\uFF08${status.latestVersion}\uFF09` : ""}`;
|
|
4572
|
+
}
|
|
4573
|
+
return `\u6682\u65F6\u65E0\u6CD5\u68C0\u67E5\u66F4\u65B0${status.error ? `\uFF08${status.error}\uFF09` : ""}`;
|
|
4574
|
+
}
|
|
4575
|
+
function resolvePackageVersion(packagePath) {
|
|
4576
|
+
const resolvedPath = packagePath ?? import_node_path10.default.resolve(__dirname, "..", "package.json");
|
|
4577
|
+
try {
|
|
4578
|
+
const raw = import_node_fs7.default.readFileSync(resolvedPath, "utf8");
|
|
4579
|
+
const payload = JSON.parse(raw);
|
|
4580
|
+
if (typeof payload.version === "string" && payload.version.trim()) {
|
|
4581
|
+
return payload.version.trim();
|
|
4582
|
+
}
|
|
4583
|
+
} catch {
|
|
4584
|
+
}
|
|
4585
|
+
return "0.0.0";
|
|
4586
|
+
}
|
|
4587
|
+
function compareSemver(current, latest) {
|
|
4588
|
+
const currentParts = parseSemver(current);
|
|
4589
|
+
const latestParts = parseSemver(latest);
|
|
4590
|
+
if (!currentParts || !latestParts) {
|
|
4591
|
+
return null;
|
|
4592
|
+
}
|
|
4593
|
+
for (let i = 0; i < 3; i += 1) {
|
|
4594
|
+
if (currentParts[i] < latestParts[i]) {
|
|
4595
|
+
return -1;
|
|
4596
|
+
}
|
|
4597
|
+
if (currentParts[i] > latestParts[i]) {
|
|
4598
|
+
return 1;
|
|
4599
|
+
}
|
|
4600
|
+
}
|
|
4601
|
+
return 0;
|
|
4602
|
+
}
|
|
4603
|
+
function parseSemver(raw) {
|
|
4604
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(raw.trim());
|
|
4605
|
+
if (!match) {
|
|
4606
|
+
return null;
|
|
4607
|
+
}
|
|
4608
|
+
const major = Number.parseInt(match[1], 10);
|
|
4609
|
+
const minor = Number.parseInt(match[2], 10);
|
|
4610
|
+
const patch = Number.parseInt(match[3], 10);
|
|
4611
|
+
if (!Number.isFinite(major) || !Number.isFinite(minor) || !Number.isFinite(patch)) {
|
|
4612
|
+
return null;
|
|
4613
|
+
}
|
|
4614
|
+
return [major, minor, patch];
|
|
4615
|
+
}
|
|
4616
|
+
function normalizeError(error) {
|
|
4617
|
+
if (error instanceof Error && error.message.trim()) {
|
|
4618
|
+
return error.message.trim();
|
|
4619
|
+
}
|
|
4620
|
+
return String(error);
|
|
4621
|
+
}
|
|
4622
|
+
|
|
4466
4623
|
// src/rate-limiter.ts
|
|
4467
4624
|
var RateLimiter = class {
|
|
4468
4625
|
options;
|
|
@@ -4846,7 +5003,7 @@ function createIdleWorkflowSnapshot() {
|
|
|
4846
5003
|
|
|
4847
5004
|
// src/workflow/autodev.ts
|
|
4848
5005
|
var import_promises4 = __toESM(require("fs/promises"));
|
|
4849
|
-
var
|
|
5006
|
+
var import_node_path11 = __toESM(require("path"));
|
|
4850
5007
|
function parseAutoDevCommand(text) {
|
|
4851
5008
|
const normalized = text.trim();
|
|
4852
5009
|
if (!/^\/autodev(?:\s|$)/i.test(normalized)) {
|
|
@@ -4866,8 +5023,8 @@ function parseAutoDevCommand(text) {
|
|
|
4866
5023
|
};
|
|
4867
5024
|
}
|
|
4868
5025
|
async function loadAutoDevContext(workdir) {
|
|
4869
|
-
const requirementsPath =
|
|
4870
|
-
const taskListPath =
|
|
5026
|
+
const requirementsPath = import_node_path11.default.join(workdir, "REQUIREMENTS.md");
|
|
5027
|
+
const taskListPath = import_node_path11.default.join(workdir, "TASK_LIST.md");
|
|
4871
5028
|
const requirementsContent = await readOptionalFile(requirementsPath);
|
|
4872
5029
|
const taskListContent = await readOptionalFile(taskListPath);
|
|
4873
5030
|
return {
|
|
@@ -5225,6 +5382,7 @@ var Orchestrator = class {
|
|
|
5225
5382
|
cliCompatRecorder;
|
|
5226
5383
|
audioTranscriber;
|
|
5227
5384
|
workflowRunner;
|
|
5385
|
+
packageUpdateChecker;
|
|
5228
5386
|
workflowSnapshots = /* @__PURE__ */ new Map();
|
|
5229
5387
|
autoDevSnapshots = /* @__PURE__ */ new Map();
|
|
5230
5388
|
metrics = new RequestMetrics();
|
|
@@ -5298,6 +5456,9 @@ var Orchestrator = class {
|
|
|
5298
5456
|
enabled: options?.multiAgentWorkflow?.enabled ?? false,
|
|
5299
5457
|
autoRepairMaxRounds: options?.multiAgentWorkflow?.autoRepairMaxRounds ?? 1
|
|
5300
5458
|
});
|
|
5459
|
+
this.packageUpdateChecker = options?.packageUpdateChecker ?? new NpmRegistryUpdateChecker({
|
|
5460
|
+
packageName: "codeharbor"
|
|
5461
|
+
});
|
|
5301
5462
|
this.sessionRuntime = new CodexSessionRuntime(this.executor);
|
|
5302
5463
|
}
|
|
5303
5464
|
async handleMessage(message) {
|
|
@@ -5661,6 +5822,7 @@ var Orchestrator = class {
|
|
|
5661
5822
|
const runtime = this.sessionRuntime.getRuntimeStats();
|
|
5662
5823
|
const workflow = this.workflowSnapshots.get(sessionKey) ?? createIdleWorkflowSnapshot();
|
|
5663
5824
|
const autoDev = this.autoDevSnapshots.get(sessionKey) ?? createIdleAutoDevSnapshot();
|
|
5825
|
+
const packageUpdate = await this.packageUpdateChecker.getStatus();
|
|
5664
5826
|
await this.channel.sendNotice(
|
|
5665
5827
|
message.conversationId,
|
|
5666
5828
|
`[CodeHarbor] \u5F53\u524D\u72B6\u6001
|
|
@@ -5669,6 +5831,8 @@ var Orchestrator = class {
|
|
|
5669
5831
|
- activeUntil: ${activeUntil}
|
|
5670
5832
|
- \u5DF2\u7ED1\u5B9A Codex \u4F1A\u8BDD: ${status.hasCodexSession ? "\u662F" : "\u5426"}
|
|
5671
5833
|
- \u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55: ${roomConfig.workdir}
|
|
5834
|
+
- \u5F53\u524D\u7248\u672C: ${packageUpdate.currentVersion}
|
|
5835
|
+
- \u66F4\u65B0\u68C0\u67E5: ${formatPackageUpdateHint(packageUpdate)}
|
|
5672
5836
|
- \u8FD0\u884C\u4E2D\u4EFB\u52A1: ${metrics.activeExecutions}
|
|
5673
5837
|
- \u6307\u6807: total=${metrics.total}, success=${metrics.success}, failed=${metrics.failed}, timeout=${metrics.timeout}, cancelled=${metrics.cancelled}, rate_limited=${metrics.rateLimited}
|
|
5674
5838
|
- \u5E73\u5747\u8017\u65F6: queue=${metrics.avgQueueMs}ms, exec=${metrics.avgExecMs}ms, send=${metrics.avgSendMs}ms
|
|
@@ -6466,8 +6630,8 @@ ${result.review}
|
|
|
6466
6630
|
}
|
|
6467
6631
|
|
|
6468
6632
|
// src/store/state-store.ts
|
|
6469
|
-
var
|
|
6470
|
-
var
|
|
6633
|
+
var import_node_fs8 = __toESM(require("fs"));
|
|
6634
|
+
var import_node_path12 = __toESM(require("path"));
|
|
6471
6635
|
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
6472
6636
|
var PRUNE_INTERVAL_MS = 5 * 60 * 1e3;
|
|
6473
6637
|
var SQLITE_MODULE_ID = `node:${"sqlite"}`;
|
|
@@ -6493,7 +6657,7 @@ var StateStore = class {
|
|
|
6493
6657
|
this.maxProcessedEventsPerSession = maxProcessedEventsPerSession;
|
|
6494
6658
|
this.maxSessionAgeMs = maxSessionAgeDays * ONE_DAY_MS;
|
|
6495
6659
|
this.maxSessions = maxSessions;
|
|
6496
|
-
|
|
6660
|
+
import_node_fs8.default.mkdirSync(import_node_path12.default.dirname(this.dbPath), { recursive: true });
|
|
6497
6661
|
this.db = new DatabaseSync(this.dbPath);
|
|
6498
6662
|
this.initializeSchema();
|
|
6499
6663
|
this.importLegacyStateIfNeeded();
|
|
@@ -6738,7 +6902,7 @@ var StateStore = class {
|
|
|
6738
6902
|
`);
|
|
6739
6903
|
}
|
|
6740
6904
|
importLegacyStateIfNeeded() {
|
|
6741
|
-
if (!this.legacyJsonPath || !
|
|
6905
|
+
if (!this.legacyJsonPath || !import_node_fs8.default.existsSync(this.legacyJsonPath)) {
|
|
6742
6906
|
return;
|
|
6743
6907
|
}
|
|
6744
6908
|
const countRow = this.db.prepare("SELECT COUNT(*) AS count FROM sessions").get();
|
|
@@ -6821,7 +6985,7 @@ var StateStore = class {
|
|
|
6821
6985
|
};
|
|
6822
6986
|
function loadLegacyState(filePath) {
|
|
6823
6987
|
try {
|
|
6824
|
-
const raw =
|
|
6988
|
+
const raw = import_node_fs8.default.readFileSync(filePath, "utf8");
|
|
6825
6989
|
const parsed = JSON.parse(raw);
|
|
6826
6990
|
if (!parsed.sessions || typeof parsed.sessions !== "object") {
|
|
6827
6991
|
return null;
|
|
@@ -7015,8 +7179,8 @@ function isNonLoopbackHost(host) {
|
|
|
7015
7179
|
}
|
|
7016
7180
|
|
|
7017
7181
|
// src/config.ts
|
|
7018
|
-
var
|
|
7019
|
-
var
|
|
7182
|
+
var import_node_fs9 = __toESM(require("fs"));
|
|
7183
|
+
var import_node_path13 = __toESM(require("path"));
|
|
7020
7184
|
var import_dotenv2 = __toESM(require("dotenv"));
|
|
7021
7185
|
var import_zod = require("zod");
|
|
7022
7186
|
var configSchema = import_zod.z.object({
|
|
@@ -7088,7 +7252,7 @@ var configSchema = import_zod.z.object({
|
|
|
7088
7252
|
matrixCommandPrefix: v.MATRIX_COMMAND_PREFIX,
|
|
7089
7253
|
codexBin: v.CODEX_BIN,
|
|
7090
7254
|
codexModel: v.CODEX_MODEL?.trim() || null,
|
|
7091
|
-
codexWorkdir:
|
|
7255
|
+
codexWorkdir: import_node_path13.default.resolve(v.CODEX_WORKDIR),
|
|
7092
7256
|
codexDangerousBypass: v.CODEX_DANGEROUS_BYPASS,
|
|
7093
7257
|
codexExecTimeoutMs: v.CODEX_EXEC_TIMEOUT_MS,
|
|
7094
7258
|
codexSandboxMode: v.CODEX_SANDBOX_MODE?.trim() || null,
|
|
@@ -7099,8 +7263,8 @@ var configSchema = import_zod.z.object({
|
|
|
7099
7263
|
enabled: v.AGENT_WORKFLOW_ENABLED,
|
|
7100
7264
|
autoRepairMaxRounds: v.AGENT_WORKFLOW_AUTO_REPAIR_MAX_ROUNDS
|
|
7101
7265
|
},
|
|
7102
|
-
stateDbPath:
|
|
7103
|
-
legacyStateJsonPath: v.STATE_PATH.trim() ?
|
|
7266
|
+
stateDbPath: import_node_path13.default.resolve(v.STATE_DB_PATH),
|
|
7267
|
+
legacyStateJsonPath: v.STATE_PATH.trim() ? import_node_path13.default.resolve(v.STATE_PATH) : null,
|
|
7104
7268
|
maxProcessedEventsPerSession: v.MAX_PROCESSED_EVENTS_PER_SESSION,
|
|
7105
7269
|
maxSessionAgeDays: v.MAX_SESSION_AGE_DAYS,
|
|
7106
7270
|
maxSessions: v.MAX_SESSIONS,
|
|
@@ -7141,7 +7305,7 @@ var configSchema = import_zod.z.object({
|
|
|
7141
7305
|
audioTranscribeMaxBytes: v.CLI_COMPAT_AUDIO_TRANSCRIBE_MAX_BYTES,
|
|
7142
7306
|
audioLocalWhisperCommand: v.CLI_COMPAT_AUDIO_LOCAL_WHISPER_COMMAND.trim() ? v.CLI_COMPAT_AUDIO_LOCAL_WHISPER_COMMAND.trim() : null,
|
|
7143
7307
|
audioLocalWhisperTimeoutMs: v.CLI_COMPAT_AUDIO_LOCAL_WHISPER_TIMEOUT_MS,
|
|
7144
|
-
recordPath: v.CLI_COMPAT_RECORD_PATH.trim() ?
|
|
7308
|
+
recordPath: v.CLI_COMPAT_RECORD_PATH.trim() ? import_node_path13.default.resolve(v.CLI_COMPAT_RECORD_PATH) : null
|
|
7145
7309
|
},
|
|
7146
7310
|
doctorHttpTimeoutMs: v.DOCTOR_HTTP_TIMEOUT_MS,
|
|
7147
7311
|
adminBindHost: v.ADMIN_BIND_HOST.trim() || "127.0.0.1",
|
|
@@ -7152,7 +7316,7 @@ var configSchema = import_zod.z.object({
|
|
|
7152
7316
|
adminAllowedOrigins: parseCsvList(v.ADMIN_ALLOWED_ORIGINS),
|
|
7153
7317
|
logLevel: v.LOG_LEVEL
|
|
7154
7318
|
}));
|
|
7155
|
-
function loadEnvFromFile(filePath =
|
|
7319
|
+
function loadEnvFromFile(filePath = import_node_path13.default.resolve(process.cwd(), ".env"), env = process.env) {
|
|
7156
7320
|
import_dotenv2.default.config({
|
|
7157
7321
|
path: filePath,
|
|
7158
7322
|
processEnv: env,
|
|
@@ -7165,9 +7329,9 @@ function loadConfig(env = process.env) {
|
|
|
7165
7329
|
const message = parsed.error.issues.map((issue) => `${issue.path.join(".") || "config"}: ${issue.message}`).join("; ");
|
|
7166
7330
|
throw new Error(`Invalid configuration: ${message}`);
|
|
7167
7331
|
}
|
|
7168
|
-
|
|
7332
|
+
import_node_fs9.default.mkdirSync(import_node_path13.default.dirname(parsed.data.stateDbPath), { recursive: true });
|
|
7169
7333
|
if (parsed.data.legacyStateJsonPath) {
|
|
7170
|
-
|
|
7334
|
+
import_node_fs9.default.mkdirSync(import_node_path13.default.dirname(parsed.data.legacyStateJsonPath), { recursive: true });
|
|
7171
7335
|
}
|
|
7172
7336
|
return parsed.data;
|
|
7173
7337
|
}
|
|
@@ -7334,8 +7498,8 @@ function parseAdminTokens(raw) {
|
|
|
7334
7498
|
}
|
|
7335
7499
|
|
|
7336
7500
|
// src/config-snapshot.ts
|
|
7337
|
-
var
|
|
7338
|
-
var
|
|
7501
|
+
var import_node_fs10 = __toESM(require("fs"));
|
|
7502
|
+
var import_node_path14 = __toESM(require("path"));
|
|
7339
7503
|
var import_zod2 = require("zod");
|
|
7340
7504
|
var CONFIG_SNAPSHOT_SCHEMA_VERSION = 1;
|
|
7341
7505
|
var CONFIG_SNAPSHOT_ENV_KEYS = [
|
|
@@ -7558,9 +7722,9 @@ async function runConfigExportCommand(options = {}) {
|
|
|
7558
7722
|
const snapshot = buildConfigSnapshot(config, stateStore.listRoomSettings(), options.now ?? /* @__PURE__ */ new Date());
|
|
7559
7723
|
const serialized = serializeConfigSnapshot(snapshot);
|
|
7560
7724
|
if (options.outputPath) {
|
|
7561
|
-
const targetPath =
|
|
7562
|
-
|
|
7563
|
-
|
|
7725
|
+
const targetPath = import_node_path14.default.resolve(cwd, options.outputPath);
|
|
7726
|
+
import_node_fs10.default.mkdirSync(import_node_path14.default.dirname(targetPath), { recursive: true });
|
|
7727
|
+
import_node_fs10.default.writeFileSync(targetPath, serialized, "utf8");
|
|
7564
7728
|
output.write(`Exported config snapshot to ${targetPath}
|
|
7565
7729
|
`);
|
|
7566
7730
|
return;
|
|
@@ -7574,8 +7738,8 @@ async function runConfigImportCommand(options) {
|
|
|
7574
7738
|
const cwd = options.cwd ?? process.cwd();
|
|
7575
7739
|
const output = options.output ?? process.stdout;
|
|
7576
7740
|
const actor = options.actor?.trim() || "cli:config-import";
|
|
7577
|
-
const sourcePath =
|
|
7578
|
-
if (!
|
|
7741
|
+
const sourcePath = import_node_path14.default.resolve(cwd, options.filePath);
|
|
7742
|
+
if (!import_node_fs10.default.existsSync(sourcePath)) {
|
|
7579
7743
|
throw new Error(`Config snapshot file not found: ${sourcePath}`);
|
|
7580
7744
|
}
|
|
7581
7745
|
const snapshot = parseConfigSnapshot(parseJsonFile(sourcePath));
|
|
@@ -7605,7 +7769,7 @@ async function runConfigImportCommand(options) {
|
|
|
7605
7769
|
synchronizeRoomSettings(stateStore, normalizedRooms);
|
|
7606
7770
|
stateStore.appendConfigRevision(
|
|
7607
7771
|
actor,
|
|
7608
|
-
`import config snapshot from ${
|
|
7772
|
+
`import config snapshot from ${import_node_path14.default.basename(sourcePath)}`,
|
|
7609
7773
|
JSON.stringify({
|
|
7610
7774
|
type: "config_snapshot_import",
|
|
7611
7775
|
sourcePath,
|
|
@@ -7619,7 +7783,7 @@ async function runConfigImportCommand(options) {
|
|
|
7619
7783
|
output.write(
|
|
7620
7784
|
[
|
|
7621
7785
|
`Imported config snapshot from ${sourcePath}`,
|
|
7622
|
-
`- updated .env in ${
|
|
7786
|
+
`- updated .env in ${import_node_path14.default.resolve(cwd, ".env")}`,
|
|
7623
7787
|
`- synchronized room settings: ${normalizedRooms.length}`,
|
|
7624
7788
|
"- restart required: yes (global env settings are restart-scoped)"
|
|
7625
7789
|
].join("\n") + "\n"
|
|
@@ -7692,7 +7856,7 @@ function buildSnapshotEnv(config) {
|
|
|
7692
7856
|
}
|
|
7693
7857
|
function parseJsonFile(filePath) {
|
|
7694
7858
|
try {
|
|
7695
|
-
const raw =
|
|
7859
|
+
const raw = import_node_fs10.default.readFileSync(filePath, "utf8");
|
|
7696
7860
|
return JSON.parse(raw);
|
|
7697
7861
|
} catch (error) {
|
|
7698
7862
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -7704,10 +7868,10 @@ function parseJsonFile(filePath) {
|
|
|
7704
7868
|
function normalizeSnapshotEnv(env, cwd) {
|
|
7705
7869
|
return {
|
|
7706
7870
|
...env,
|
|
7707
|
-
CODEX_WORKDIR:
|
|
7708
|
-
STATE_DB_PATH:
|
|
7709
|
-
STATE_PATH: env.STATE_PATH.trim() ?
|
|
7710
|
-
CLI_COMPAT_RECORD_PATH: env.CLI_COMPAT_RECORD_PATH.trim() ?
|
|
7871
|
+
CODEX_WORKDIR: import_node_path14.default.resolve(cwd, env.CODEX_WORKDIR),
|
|
7872
|
+
STATE_DB_PATH: import_node_path14.default.resolve(cwd, env.STATE_DB_PATH),
|
|
7873
|
+
STATE_PATH: env.STATE_PATH.trim() ? import_node_path14.default.resolve(cwd, env.STATE_PATH) : "",
|
|
7874
|
+
CLI_COMPAT_RECORD_PATH: env.CLI_COMPAT_RECORD_PATH.trim() ? import_node_path14.default.resolve(cwd, env.CLI_COMPAT_RECORD_PATH) : ""
|
|
7711
7875
|
};
|
|
7712
7876
|
}
|
|
7713
7877
|
function normalizeSnapshotRooms(rooms, cwd) {
|
|
@@ -7722,7 +7886,7 @@ function normalizeSnapshotRooms(rooms, cwd) {
|
|
|
7722
7886
|
throw new Error(`Duplicate roomId in snapshot: ${roomId}`);
|
|
7723
7887
|
}
|
|
7724
7888
|
seen.add(roomId);
|
|
7725
|
-
const workdir =
|
|
7889
|
+
const workdir = import_node_path14.default.resolve(cwd, room.workdir);
|
|
7726
7890
|
ensureDirectory2(workdir, `room workdir (${roomId})`);
|
|
7727
7891
|
normalized.push({
|
|
7728
7892
|
roomId,
|
|
@@ -7749,18 +7913,18 @@ function synchronizeRoomSettings(stateStore, rooms) {
|
|
|
7749
7913
|
}
|
|
7750
7914
|
}
|
|
7751
7915
|
function persistEnvSnapshot(cwd, env) {
|
|
7752
|
-
const envPath =
|
|
7753
|
-
const examplePath =
|
|
7754
|
-
const template =
|
|
7916
|
+
const envPath = import_node_path14.default.resolve(cwd, ".env");
|
|
7917
|
+
const examplePath = import_node_path14.default.resolve(cwd, ".env.example");
|
|
7918
|
+
const template = import_node_fs10.default.existsSync(envPath) ? import_node_fs10.default.readFileSync(envPath, "utf8") : import_node_fs10.default.existsSync(examplePath) ? import_node_fs10.default.readFileSync(examplePath, "utf8") : "";
|
|
7755
7919
|
const overrides = {};
|
|
7756
7920
|
for (const key of CONFIG_SNAPSHOT_ENV_KEYS) {
|
|
7757
7921
|
overrides[key] = env[key];
|
|
7758
7922
|
}
|
|
7759
7923
|
const next = applyEnvOverrides(template, overrides);
|
|
7760
|
-
|
|
7924
|
+
import_node_fs10.default.writeFileSync(envPath, next, "utf8");
|
|
7761
7925
|
}
|
|
7762
7926
|
function ensureDirectory2(dirPath, label) {
|
|
7763
|
-
if (!
|
|
7927
|
+
if (!import_node_fs10.default.existsSync(dirPath) || !import_node_fs10.default.statSync(dirPath).isDirectory()) {
|
|
7764
7928
|
throw new Error(`${label} does not exist or is not a directory: ${dirPath}`);
|
|
7765
7929
|
}
|
|
7766
7930
|
}
|
|
@@ -7834,8 +7998,8 @@ function jsonArrayStringSchema(key, allowEmpty) {
|
|
|
7834
7998
|
|
|
7835
7999
|
// src/preflight.ts
|
|
7836
8000
|
var import_node_child_process7 = require("child_process");
|
|
7837
|
-
var
|
|
7838
|
-
var
|
|
8001
|
+
var import_node_fs11 = __toESM(require("fs"));
|
|
8002
|
+
var import_node_path15 = __toESM(require("path"));
|
|
7839
8003
|
var import_node_util5 = require("util");
|
|
7840
8004
|
var execFileAsync4 = (0, import_node_util5.promisify)(import_node_child_process7.execFile);
|
|
7841
8005
|
var REQUIRED_ENV_KEYS = ["MATRIX_HOMESERVER", "MATRIX_USER_ID", "MATRIX_ACCESS_TOKEN"];
|
|
@@ -7843,10 +8007,10 @@ async function runStartupPreflight(options = {}) {
|
|
|
7843
8007
|
const env = options.env ?? process.env;
|
|
7844
8008
|
const cwd = options.cwd ?? process.cwd();
|
|
7845
8009
|
const checkCodexBinary = options.checkCodexBinary ?? defaultCheckCodexBinary;
|
|
7846
|
-
const fileExists = options.fileExists ??
|
|
8010
|
+
const fileExists = options.fileExists ?? import_node_fs11.default.existsSync;
|
|
7847
8011
|
const isDirectory = options.isDirectory ?? defaultIsDirectory;
|
|
7848
8012
|
const issues = [];
|
|
7849
|
-
const envPath =
|
|
8013
|
+
const envPath = import_node_path15.default.resolve(cwd, ".env");
|
|
7850
8014
|
let resolvedCodexBin = null;
|
|
7851
8015
|
let usedCodexFallback = false;
|
|
7852
8016
|
if (!fileExists(envPath)) {
|
|
@@ -7923,7 +8087,7 @@ async function runStartupPreflight(options = {}) {
|
|
|
7923
8087
|
}
|
|
7924
8088
|
}
|
|
7925
8089
|
const configuredWorkdir = readEnv(env, "CODEX_WORKDIR");
|
|
7926
|
-
const workdir =
|
|
8090
|
+
const workdir = import_node_path15.default.resolve(cwd, configuredWorkdir || cwd);
|
|
7927
8091
|
if (!fileExists(workdir) || !isDirectory(workdir)) {
|
|
7928
8092
|
issues.push({
|
|
7929
8093
|
level: "error",
|
|
@@ -7964,7 +8128,7 @@ async function defaultCheckCodexBinary(bin) {
|
|
|
7964
8128
|
}
|
|
7965
8129
|
function defaultIsDirectory(targetPath) {
|
|
7966
8130
|
try {
|
|
7967
|
-
return
|
|
8131
|
+
return import_node_fs11.default.statSync(targetPath).isDirectory();
|
|
7968
8132
|
} catch {
|
|
7969
8133
|
return false;
|
|
7970
8134
|
}
|
|
@@ -8223,7 +8387,7 @@ function ensureRuntimeHomeOrExit() {
|
|
|
8223
8387
|
}
|
|
8224
8388
|
const home = resolveRuntimeHome();
|
|
8225
8389
|
try {
|
|
8226
|
-
|
|
8390
|
+
import_node_fs12.default.mkdirSync(home, { recursive: true });
|
|
8227
8391
|
} catch (error) {
|
|
8228
8392
|
const message = error instanceof Error ? error.message : String(error);
|
|
8229
8393
|
process.stderr.write(`Runtime setup failed: cannot create ${home}. ${message}
|
|
@@ -8238,7 +8402,7 @@ function ensureRuntimeHomeOrExit() {
|
|
|
8238
8402
|
`);
|
|
8239
8403
|
process.exit(1);
|
|
8240
8404
|
}
|
|
8241
|
-
loadEnvFromFile(
|
|
8405
|
+
loadEnvFromFile(import_node_path16.default.resolve(home, ".env"));
|
|
8242
8406
|
runtimeHome = home;
|
|
8243
8407
|
return runtimeHome;
|
|
8244
8408
|
}
|
|
@@ -8253,8 +8417,8 @@ function parsePortOption(raw, fallback) {
|
|
|
8253
8417
|
}
|
|
8254
8418
|
function resolveCliVersion() {
|
|
8255
8419
|
try {
|
|
8256
|
-
const packagePath =
|
|
8257
|
-
const content =
|
|
8420
|
+
const packagePath = import_node_path16.default.resolve(__dirname, "..", "package.json");
|
|
8421
|
+
const content = import_node_fs12.default.readFileSync(packagePath, "utf8");
|
|
8258
8422
|
const parsed = JSON.parse(content);
|
|
8259
8423
|
return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version : "0.0.0";
|
|
8260
8424
|
} catch {
|
|
@@ -8264,9 +8428,9 @@ function resolveCliVersion() {
|
|
|
8264
8428
|
function resolveCliScriptPath() {
|
|
8265
8429
|
const argvPath = process.argv[1];
|
|
8266
8430
|
if (argvPath && argvPath.trim()) {
|
|
8267
|
-
return
|
|
8431
|
+
return import_node_path16.default.resolve(argvPath);
|
|
8268
8432
|
}
|
|
8269
|
-
return
|
|
8433
|
+
return import_node_path16.default.resolve(__dirname, "cli.js");
|
|
8270
8434
|
}
|
|
8271
8435
|
function maybeReexecServiceCommandWithSudo() {
|
|
8272
8436
|
if (typeof process.getuid !== "function" || process.getuid() === 0) {
|