@roamcode.ai/server 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +7 -0
- package/dist/index.js +61 -3
- package/dist/managed-update-helper.js +0 -1
- package/dist/start.js +61 -3
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -996,6 +996,13 @@ declare class Updater {
|
|
|
996
996
|
private persistReleaseCache;
|
|
997
997
|
private refresh;
|
|
998
998
|
getVersion(force?: boolean): Promise<VersionInfo>;
|
|
999
|
+
private readRawStatus;
|
|
1000
|
+
/**
|
|
1001
|
+
* Reconcile the durable status with runtime truth on every read. This prevents a helper that failed
|
|
1002
|
+
* before its first write (bad executable, missing file, launch failure) from leaving every client on
|
|
1003
|
+
* “Starting…” forever, and lets a restarted server confirm success even if the helper's final write
|
|
1004
|
+
* raced the service restart.
|
|
1005
|
+
*/
|
|
999
1006
|
readStatus(): UpdateStatus;
|
|
1000
1007
|
private writeStatus;
|
|
1001
1008
|
readLastGoodVersion(): string | undefined;
|
package/dist/index.js
CHANGED
|
@@ -2191,13 +2191,14 @@ async function installManagedRelease(opts) {
|
|
|
2191
2191
|
}
|
|
2192
2192
|
|
|
2193
2193
|
// src/updater.ts
|
|
2194
|
-
var RUNNING_VERSION = "1.0.
|
|
2194
|
+
var RUNNING_VERSION = "1.0.4" ? "1.0.4".replace(/^v/, "") : packageVersion();
|
|
2195
2195
|
var RUNNING_BUILD = RUNNING_VERSION;
|
|
2196
2196
|
var RELEASES_API = "https://api.github.com/repos/burakgon/roamcode/releases?per_page=100";
|
|
2197
2197
|
var RELEASE_MANIFEST_ASSET = "roamcode-release.json";
|
|
2198
2198
|
var CHECK_CACHE_MS = 15 * 6e4;
|
|
2199
2199
|
var FAILED_CHECK_TTL_MS = 3e4;
|
|
2200
2200
|
var FETCH_TIMEOUT_MS = 2e4;
|
|
2201
|
+
var UPDATE_STARTUP_TIMEOUT_MS = 2e4;
|
|
2201
2202
|
var UPDATE_STALE_MS = 30 * 6e4;
|
|
2202
2203
|
var defaultUpdaterFs = {
|
|
2203
2204
|
existsSync: nodeExistsSync,
|
|
@@ -2435,7 +2436,7 @@ var Updater = class {
|
|
|
2435
2436
|
buildDrift: installDrift
|
|
2436
2437
|
};
|
|
2437
2438
|
}
|
|
2438
|
-
|
|
2439
|
+
readRawStatus() {
|
|
2439
2440
|
try {
|
|
2440
2441
|
const parsed = JSON.parse(this.fs.readFileSync(join8(this.dataDir, "update-status.json")));
|
|
2441
2442
|
return parsed && typeof parsed.state === "string" ? parsed : { state: "idle" };
|
|
@@ -2443,6 +2444,49 @@ var Updater = class {
|
|
|
2443
2444
|
return { state: "idle" };
|
|
2444
2445
|
}
|
|
2445
2446
|
}
|
|
2447
|
+
/**
|
|
2448
|
+
* Reconcile the durable status with runtime truth on every read. This prevents a helper that failed
|
|
2449
|
+
* before its first write (bad executable, missing file, launch failure) from leaving every client on
|
|
2450
|
+
* “Starting…” forever, and lets a restarted server confirm success even if the helper's final write
|
|
2451
|
+
* raced the service restart.
|
|
2452
|
+
*/
|
|
2453
|
+
readStatus() {
|
|
2454
|
+
const status = this.readRawStatus();
|
|
2455
|
+
if (status.state === "idle" || status.state === "done" || status.state === "failed") return status;
|
|
2456
|
+
if (status.target && status.operationId) {
|
|
2457
|
+
const active = readActiveVersion(this.installRoot());
|
|
2458
|
+
if (active === status.target && this.runningVersion === status.target) {
|
|
2459
|
+
const done = {
|
|
2460
|
+
operationId: status.operationId,
|
|
2461
|
+
state: "done",
|
|
2462
|
+
phase: "done",
|
|
2463
|
+
target: status.target,
|
|
2464
|
+
...status.fromVersion ? { fromVersion: status.fromVersion } : {},
|
|
2465
|
+
updatedAt: this.now()
|
|
2466
|
+
};
|
|
2467
|
+
this.writeStatus(done);
|
|
2468
|
+
return done;
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2471
|
+
const age = this.now() - (status.updatedAt ?? 0);
|
|
2472
|
+
const helperHasNotReported = status.state === "starting" && (status.phase === "starting" || status.phase === "preparing migration" || status.phase === "preparing rollback");
|
|
2473
|
+
if (helperHasNotReported && age >= UPDATE_STARTUP_TIMEOUT_MS || age >= UPDATE_STALE_MS) {
|
|
2474
|
+
const failed = {
|
|
2475
|
+
operationId: status.operationId ?? "unknown",
|
|
2476
|
+
state: "failed",
|
|
2477
|
+
phase: "failed",
|
|
2478
|
+
...status.target ? { target: status.target } : {},
|
|
2479
|
+
...status.fromVersion ? { fromVersion: status.fromVersion } : {},
|
|
2480
|
+
error: helperHasNotReported ? "The update process could not start. The current version is still running; retry the update." : "The update stopped reporting progress. The current version is still available; retry the update.",
|
|
2481
|
+
...status.log ? { log: status.log } : {},
|
|
2482
|
+
updatedAt: this.now()
|
|
2483
|
+
};
|
|
2484
|
+
this.writeStatus(failed);
|
|
2485
|
+
this.inFlight = false;
|
|
2486
|
+
return failed;
|
|
2487
|
+
}
|
|
2488
|
+
return status;
|
|
2489
|
+
}
|
|
2446
2490
|
writeStatus(status) {
|
|
2447
2491
|
this.fs.mkdirSync(this.dataDir);
|
|
2448
2492
|
const path = join8(this.dataDir, "update-status.json");
|
|
@@ -2469,7 +2513,7 @@ var Updater = class {
|
|
|
2469
2513
|
return this.now() - (status.updatedAt ?? 0) < UPDATE_STALE_MS;
|
|
2470
2514
|
}
|
|
2471
2515
|
finalizeRestartIfHealthy() {
|
|
2472
|
-
const status = this.
|
|
2516
|
+
const status = this.readRawStatus();
|
|
2473
2517
|
if (status.state !== "restarting" || !status.target || !status.operationId) return;
|
|
2474
2518
|
const active = readActiveVersion(this.installRoot());
|
|
2475
2519
|
if (active !== status.target || this.runningVersion !== status.target) return;
|
|
@@ -2557,6 +2601,20 @@ var Updater = class {
|
|
|
2557
2601
|
updatedAt: this.now()
|
|
2558
2602
|
});
|
|
2559
2603
|
});
|
|
2604
|
+
child.on("exit", (code, signal) => {
|
|
2605
|
+
if (code === 0) return;
|
|
2606
|
+
const current = this.readRawStatus();
|
|
2607
|
+
if (current.operationId !== operationId || current.state === "done" || current.state === "failed" || current.state === "idle")
|
|
2608
|
+
return;
|
|
2609
|
+
this.inFlight = false;
|
|
2610
|
+
this.writeStatus({
|
|
2611
|
+
...status,
|
|
2612
|
+
state: "failed",
|
|
2613
|
+
phase: "failed",
|
|
2614
|
+
error: `The update process exited before installation began (${signal ?? `code ${code ?? "unknown"}`}). The current version is still running.`,
|
|
2615
|
+
updatedAt: this.now()
|
|
2616
|
+
});
|
|
2617
|
+
});
|
|
2560
2618
|
child.unref();
|
|
2561
2619
|
return { started: true, operationId, target };
|
|
2562
2620
|
} catch (error) {
|
package/dist/start.js
CHANGED
|
@@ -765,12 +765,13 @@ function readPreviousVersion(root) {
|
|
|
765
765
|
}
|
|
766
766
|
|
|
767
767
|
// src/updater.ts
|
|
768
|
-
var RUNNING_VERSION = "1.0.
|
|
768
|
+
var RUNNING_VERSION = "1.0.4" ? "1.0.4".replace(/^v/, "") : packageVersion();
|
|
769
769
|
var RELEASES_API = "https://api.github.com/repos/burakgon/roamcode/releases?per_page=100";
|
|
770
770
|
var RELEASE_MANIFEST_ASSET = "roamcode-release.json";
|
|
771
771
|
var CHECK_CACHE_MS = 15 * 6e4;
|
|
772
772
|
var FAILED_CHECK_TTL_MS = 3e4;
|
|
773
773
|
var FETCH_TIMEOUT_MS = 2e4;
|
|
774
|
+
var UPDATE_STARTUP_TIMEOUT_MS = 2e4;
|
|
774
775
|
var UPDATE_STALE_MS = 30 * 6e4;
|
|
775
776
|
var defaultUpdaterFs = {
|
|
776
777
|
existsSync: nodeExistsSync,
|
|
@@ -1007,7 +1008,7 @@ var Updater = class {
|
|
|
1007
1008
|
buildDrift: installDrift
|
|
1008
1009
|
};
|
|
1009
1010
|
}
|
|
1010
|
-
|
|
1011
|
+
readRawStatus() {
|
|
1011
1012
|
try {
|
|
1012
1013
|
const parsed = JSON.parse(this.fs.readFileSync(join6(this.dataDir, "update-status.json")));
|
|
1013
1014
|
return parsed && typeof parsed.state === "string" ? parsed : { state: "idle" };
|
|
@@ -1015,6 +1016,49 @@ var Updater = class {
|
|
|
1015
1016
|
return { state: "idle" };
|
|
1016
1017
|
}
|
|
1017
1018
|
}
|
|
1019
|
+
/**
|
|
1020
|
+
* Reconcile the durable status with runtime truth on every read. This prevents a helper that failed
|
|
1021
|
+
* before its first write (bad executable, missing file, launch failure) from leaving every client on
|
|
1022
|
+
* “Starting…” forever, and lets a restarted server confirm success even if the helper's final write
|
|
1023
|
+
* raced the service restart.
|
|
1024
|
+
*/
|
|
1025
|
+
readStatus() {
|
|
1026
|
+
const status = this.readRawStatus();
|
|
1027
|
+
if (status.state === "idle" || status.state === "done" || status.state === "failed") return status;
|
|
1028
|
+
if (status.target && status.operationId) {
|
|
1029
|
+
const active = readActiveVersion(this.installRoot());
|
|
1030
|
+
if (active === status.target && this.runningVersion === status.target) {
|
|
1031
|
+
const done = {
|
|
1032
|
+
operationId: status.operationId,
|
|
1033
|
+
state: "done",
|
|
1034
|
+
phase: "done",
|
|
1035
|
+
target: status.target,
|
|
1036
|
+
...status.fromVersion ? { fromVersion: status.fromVersion } : {},
|
|
1037
|
+
updatedAt: this.now()
|
|
1038
|
+
};
|
|
1039
|
+
this.writeStatus(done);
|
|
1040
|
+
return done;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
const age = this.now() - (status.updatedAt ?? 0);
|
|
1044
|
+
const helperHasNotReported = status.state === "starting" && (status.phase === "starting" || status.phase === "preparing migration" || status.phase === "preparing rollback");
|
|
1045
|
+
if (helperHasNotReported && age >= UPDATE_STARTUP_TIMEOUT_MS || age >= UPDATE_STALE_MS) {
|
|
1046
|
+
const failed = {
|
|
1047
|
+
operationId: status.operationId ?? "unknown",
|
|
1048
|
+
state: "failed",
|
|
1049
|
+
phase: "failed",
|
|
1050
|
+
...status.target ? { target: status.target } : {},
|
|
1051
|
+
...status.fromVersion ? { fromVersion: status.fromVersion } : {},
|
|
1052
|
+
error: helperHasNotReported ? "The update process could not start. The current version is still running; retry the update." : "The update stopped reporting progress. The current version is still available; retry the update.",
|
|
1053
|
+
...status.log ? { log: status.log } : {},
|
|
1054
|
+
updatedAt: this.now()
|
|
1055
|
+
};
|
|
1056
|
+
this.writeStatus(failed);
|
|
1057
|
+
this.inFlight = false;
|
|
1058
|
+
return failed;
|
|
1059
|
+
}
|
|
1060
|
+
return status;
|
|
1061
|
+
}
|
|
1018
1062
|
writeStatus(status) {
|
|
1019
1063
|
this.fs.mkdirSync(this.dataDir);
|
|
1020
1064
|
const path = join6(this.dataDir, "update-status.json");
|
|
@@ -1041,7 +1085,7 @@ var Updater = class {
|
|
|
1041
1085
|
return this.now() - (status.updatedAt ?? 0) < UPDATE_STALE_MS;
|
|
1042
1086
|
}
|
|
1043
1087
|
finalizeRestartIfHealthy() {
|
|
1044
|
-
const status = this.
|
|
1088
|
+
const status = this.readRawStatus();
|
|
1045
1089
|
if (status.state !== "restarting" || !status.target || !status.operationId) return;
|
|
1046
1090
|
const active = readActiveVersion(this.installRoot());
|
|
1047
1091
|
if (active !== status.target || this.runningVersion !== status.target) return;
|
|
@@ -1129,6 +1173,20 @@ var Updater = class {
|
|
|
1129
1173
|
updatedAt: this.now()
|
|
1130
1174
|
});
|
|
1131
1175
|
});
|
|
1176
|
+
child.on("exit", (code, signal) => {
|
|
1177
|
+
if (code === 0) return;
|
|
1178
|
+
const current = this.readRawStatus();
|
|
1179
|
+
if (current.operationId !== operationId || current.state === "done" || current.state === "failed" || current.state === "idle")
|
|
1180
|
+
return;
|
|
1181
|
+
this.inFlight = false;
|
|
1182
|
+
this.writeStatus({
|
|
1183
|
+
...status,
|
|
1184
|
+
state: "failed",
|
|
1185
|
+
phase: "failed",
|
|
1186
|
+
error: `The update process exited before installation began (${signal ?? `code ${code ?? "unknown"}`}). The current version is still running.`,
|
|
1187
|
+
updatedAt: this.now()
|
|
1188
|
+
});
|
|
1189
|
+
});
|
|
1132
1190
|
child.unref();
|
|
1133
1191
|
return { started: true, operationId, target };
|
|
1134
1192
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roamcode.ai/server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Host-native server for RoamCode",
|
|
5
5
|
"homepage": "https://roamcode.ai",
|
|
6
6
|
"bugs": "https://github.com/burakgon/roamcode/issues",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"node-pty": "1.1.0",
|
|
41
41
|
"web-push": "^3.6.7",
|
|
42
42
|
"zod": "^4.4.3",
|
|
43
|
-
"@roamcode.ai/web": "1.0.
|
|
43
|
+
"@roamcode.ai/web": "1.0.4"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/better-sqlite3": "^7.6.13",
|