quoroom 0.1.39 → 0.1.41
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 +16 -1
- package/out/mcp/api-server.js +334 -767
- package/out/mcp/cli.js +4244 -5098
- package/out/mcp/server.js +234 -1265
- package/package.json +1 -1
package/out/mcp/api-server.js
CHANGED
|
@@ -9381,19 +9381,19 @@ var init_call = __esm({
|
|
|
9381
9381
|
function getMachineId() {
|
|
9382
9382
|
if (cachedMachineId) return cachedMachineId;
|
|
9383
9383
|
try {
|
|
9384
|
-
const raw = (0,
|
|
9385
|
-
cachedMachineId = (0,
|
|
9384
|
+
const raw = (0, import_os3.hostname)() + (0, import_os3.userInfo)().username;
|
|
9385
|
+
cachedMachineId = (0, import_crypto5.createHash)("sha256").update(raw).digest("hex").slice(0, 12);
|
|
9386
9386
|
} catch {
|
|
9387
9387
|
cachedMachineId = "unknown";
|
|
9388
9388
|
}
|
|
9389
9389
|
return cachedMachineId;
|
|
9390
9390
|
}
|
|
9391
|
-
var
|
|
9391
|
+
var import_crypto5, import_os3, TELEMETRY_TOKEN, cachedMachineId;
|
|
9392
9392
|
var init_telemetry = __esm({
|
|
9393
9393
|
"src/shared/telemetry.ts"() {
|
|
9394
9394
|
"use strict";
|
|
9395
|
-
|
|
9396
|
-
|
|
9395
|
+
import_crypto5 = require("crypto");
|
|
9396
|
+
import_os3 = require("os");
|
|
9397
9397
|
TELEMETRY_TOKEN = process.env.QUOROOM_TELEMETRY_TOKEN ?? "";
|
|
9398
9398
|
cachedMachineId = null;
|
|
9399
9399
|
}
|
|
@@ -9402,33 +9402,22 @@ var init_telemetry = __esm({
|
|
|
9402
9402
|
// src/shared/cloud-sync.ts
|
|
9403
9403
|
var cloud_sync_exports = {};
|
|
9404
9404
|
__export(cloud_sync_exports, {
|
|
9405
|
-
cancelCloudStation: () => cancelCloudStation,
|
|
9406
9405
|
createCloudInvite: () => createCloudInvite,
|
|
9407
|
-
cryptoCheckoutStation: () => cryptoCheckoutStation,
|
|
9408
|
-
cryptoRenewStation: () => cryptoRenewStation,
|
|
9409
|
-
deleteCloudStation: () => deleteCloudStation,
|
|
9410
9406
|
ensureCloudRoomToken: () => ensureCloudRoomToken,
|
|
9411
|
-
execOnCloudStation: () => execOnCloudStation,
|
|
9412
9407
|
fetchCloudRoomMessages: () => fetchCloudRoomMessages,
|
|
9413
9408
|
fetchPublicRooms: () => fetchPublicRooms,
|
|
9414
9409
|
fetchReferredRooms: () => fetchReferredRooms,
|
|
9415
9410
|
fetchRoomFeed: () => fetchRoomFeed,
|
|
9416
|
-
getCloudCryptoPrices: () => getCloudCryptoPrices,
|
|
9417
9411
|
getCloudOnrampUrl: () => getCloudOnrampUrl,
|
|
9418
|
-
getCloudStationLogs: () => getCloudStationLogs,
|
|
9419
9412
|
getRoomCloudId: () => getRoomCloudId,
|
|
9420
9413
|
getRoomId: () => getRoomId,
|
|
9421
9414
|
getStoredCloudRoomToken: () => getStoredCloudRoomToken,
|
|
9422
9415
|
listCloudInvites: () => listCloudInvites,
|
|
9423
|
-
listCloudStationPayments: () => listCloudStationPayments,
|
|
9424
|
-
listCloudStations: () => listCloudStations,
|
|
9425
9416
|
pushActivityToCloud: () => pushActivityToCloud,
|
|
9426
9417
|
registerWithCloud: () => registerWithCloud,
|
|
9427
9418
|
sendCloudHeartbeat: () => sendCloudHeartbeat,
|
|
9428
9419
|
sendCloudRoomMessage: () => sendCloudRoomMessage,
|
|
9429
|
-
startCloudStation: () => startCloudStation,
|
|
9430
9420
|
startCloudSync: () => startCloudSync,
|
|
9431
|
-
stopCloudStation: () => stopCloudStation,
|
|
9432
9421
|
stopCloudSync: () => stopCloudSync
|
|
9433
9422
|
});
|
|
9434
9423
|
function getCloudApi() {
|
|
@@ -9436,16 +9425,16 @@ function getCloudApi() {
|
|
|
9436
9425
|
}
|
|
9437
9426
|
function getCloudTokenFilePath() {
|
|
9438
9427
|
const explicitDataDir = process.env.QUOROOM_DATA_DIR?.trim();
|
|
9439
|
-
if (explicitDataDir) return (0,
|
|
9428
|
+
if (explicitDataDir) return (0, import_path3.join)(explicitDataDir, TOKEN_FILE_NAME);
|
|
9440
9429
|
const dbPath = process.env.QUOROOM_DB_PATH?.trim();
|
|
9441
|
-
if (dbPath) return (0,
|
|
9442
|
-
return (0,
|
|
9430
|
+
if (dbPath) return (0, import_path3.join)((0, import_path3.dirname)(dbPath), TOKEN_FILE_NAME);
|
|
9431
|
+
return (0, import_path3.join)((0, import_os4.homedir)(), ".quoroom", TOKEN_FILE_NAME);
|
|
9443
9432
|
}
|
|
9444
9433
|
function loadTokenStore() {
|
|
9445
9434
|
if (cachedTokens) return cachedTokens;
|
|
9446
9435
|
const filePath = getCloudTokenFilePath();
|
|
9447
9436
|
try {
|
|
9448
|
-
const parsed = JSON.parse((0,
|
|
9437
|
+
const parsed = JSON.parse((0, import_fs3.readFileSync)(filePath, "utf-8"));
|
|
9449
9438
|
cachedTokens = parsed.rooms ?? {};
|
|
9450
9439
|
} catch {
|
|
9451
9440
|
cachedTokens = {};
|
|
@@ -9454,9 +9443,9 @@ function loadTokenStore() {
|
|
|
9454
9443
|
}
|
|
9455
9444
|
function saveTokenStore() {
|
|
9456
9445
|
const filePath = getCloudTokenFilePath();
|
|
9457
|
-
(0,
|
|
9446
|
+
(0, import_fs3.mkdirSync)((0, import_path3.dirname)(filePath), { recursive: true });
|
|
9458
9447
|
const payload = JSON.stringify({ rooms: loadTokenStore() }, null, 2) + "\n";
|
|
9459
|
-
(0,
|
|
9448
|
+
(0, import_fs3.writeFileSync)(filePath, payload, { mode: 384 });
|
|
9460
9449
|
}
|
|
9461
9450
|
function getRoomToken(roomId) {
|
|
9462
9451
|
return loadTokenStore()[roomId];
|
|
@@ -9585,161 +9574,7 @@ function getRoomId() {
|
|
|
9585
9574
|
}
|
|
9586
9575
|
function getRoomCloudId(dbRoomId) {
|
|
9587
9576
|
const machineId = getMachineId();
|
|
9588
|
-
return (0,
|
|
9589
|
-
}
|
|
9590
|
-
function getCachedCloudStations(cloudRoomId) {
|
|
9591
|
-
const cached2 = cloudStationsCache.get(cloudRoomId);
|
|
9592
|
-
if (!cached2) return null;
|
|
9593
|
-
if (Date.now() >= cached2.expiresAt) {
|
|
9594
|
-
cloudStationsCache.delete(cloudRoomId);
|
|
9595
|
-
return null;
|
|
9596
|
-
}
|
|
9597
|
-
return cached2.value;
|
|
9598
|
-
}
|
|
9599
|
-
function setCachedCloudStations(cloudRoomId, stations) {
|
|
9600
|
-
cloudStationsCache.set(cloudRoomId, {
|
|
9601
|
-
value: stations,
|
|
9602
|
-
expiresAt: Date.now() + CLOUD_STATIONS_CACHE_MS
|
|
9603
|
-
});
|
|
9604
|
-
}
|
|
9605
|
-
function invalidateCloudStationsCache(cloudRoomId) {
|
|
9606
|
-
cloudStationsCache.delete(cloudRoomId);
|
|
9607
|
-
}
|
|
9608
|
-
async function listCloudStations(cloudRoomId) {
|
|
9609
|
-
const cached2 = getCachedCloudStations(cloudRoomId);
|
|
9610
|
-
if (cached2) return cached2;
|
|
9611
|
-
try {
|
|
9612
|
-
const res = await fetch(`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/stations`, {
|
|
9613
|
-
headers: cloudHeaders(cloudRoomId),
|
|
9614
|
-
signal: AbortSignal.timeout(1e4)
|
|
9615
|
-
});
|
|
9616
|
-
if (!res.ok) return [];
|
|
9617
|
-
const data = await res.json();
|
|
9618
|
-
const stations = data.stations ?? [];
|
|
9619
|
-
setCachedCloudStations(cloudRoomId, stations);
|
|
9620
|
-
return stations;
|
|
9621
|
-
} catch {
|
|
9622
|
-
return [];
|
|
9623
|
-
}
|
|
9624
|
-
}
|
|
9625
|
-
async function listCloudStationPayments(cloudRoomId) {
|
|
9626
|
-
try {
|
|
9627
|
-
const res = await fetch(`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/billing/payments`, {
|
|
9628
|
-
headers: cloudHeaders(cloudRoomId),
|
|
9629
|
-
signal: AbortSignal.timeout(1e4)
|
|
9630
|
-
});
|
|
9631
|
-
if (!res.ok) return [];
|
|
9632
|
-
const data = await res.json();
|
|
9633
|
-
return data.payments ?? [];
|
|
9634
|
-
} catch {
|
|
9635
|
-
return [];
|
|
9636
|
-
}
|
|
9637
|
-
}
|
|
9638
|
-
async function execOnCloudStation(cloudRoomId, subId, command, timeoutMs = 9e4) {
|
|
9639
|
-
try {
|
|
9640
|
-
const res = await fetch(
|
|
9641
|
-
`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/stations/${subId}/exec`,
|
|
9642
|
-
{
|
|
9643
|
-
method: "POST",
|
|
9644
|
-
headers: cloudHeaders(cloudRoomId, { "Content-Type": "application/json" }),
|
|
9645
|
-
body: JSON.stringify({ command }),
|
|
9646
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
9647
|
-
}
|
|
9648
|
-
);
|
|
9649
|
-
if (!res.ok) return null;
|
|
9650
|
-
return res.json();
|
|
9651
|
-
} catch {
|
|
9652
|
-
return null;
|
|
9653
|
-
}
|
|
9654
|
-
}
|
|
9655
|
-
async function getCloudStationLogs(cloudRoomId, subId, lines) {
|
|
9656
|
-
try {
|
|
9657
|
-
const query = lines ? `?lines=${lines}` : "";
|
|
9658
|
-
const res = await fetch(
|
|
9659
|
-
`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/stations/${subId}/logs${query}`,
|
|
9660
|
-
{
|
|
9661
|
-
headers: cloudHeaders(cloudRoomId),
|
|
9662
|
-
signal: AbortSignal.timeout(15e3)
|
|
9663
|
-
}
|
|
9664
|
-
);
|
|
9665
|
-
if (!res.ok) return null;
|
|
9666
|
-
const data = await res.json();
|
|
9667
|
-
return data.logs ?? "";
|
|
9668
|
-
} catch {
|
|
9669
|
-
return null;
|
|
9670
|
-
}
|
|
9671
|
-
}
|
|
9672
|
-
async function startCloudStation(cloudRoomId, subId) {
|
|
9673
|
-
try {
|
|
9674
|
-
await fetch(
|
|
9675
|
-
`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/stations/${subId}/start`,
|
|
9676
|
-
{
|
|
9677
|
-
method: "POST",
|
|
9678
|
-
headers: cloudHeaders(cloudRoomId),
|
|
9679
|
-
signal: AbortSignal.timeout(3e4)
|
|
9680
|
-
}
|
|
9681
|
-
);
|
|
9682
|
-
} catch {
|
|
9683
|
-
} finally {
|
|
9684
|
-
invalidateCloudStationsCache(cloudRoomId);
|
|
9685
|
-
}
|
|
9686
|
-
}
|
|
9687
|
-
async function stopCloudStation(cloudRoomId, subId) {
|
|
9688
|
-
try {
|
|
9689
|
-
await fetch(
|
|
9690
|
-
`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/stations/${subId}/stop`,
|
|
9691
|
-
{
|
|
9692
|
-
method: "POST",
|
|
9693
|
-
headers: cloudHeaders(cloudRoomId),
|
|
9694
|
-
signal: AbortSignal.timeout(3e4)
|
|
9695
|
-
}
|
|
9696
|
-
);
|
|
9697
|
-
} catch {
|
|
9698
|
-
} finally {
|
|
9699
|
-
invalidateCloudStationsCache(cloudRoomId);
|
|
9700
|
-
}
|
|
9701
|
-
}
|
|
9702
|
-
async function deleteCloudStation(cloudRoomId, subId) {
|
|
9703
|
-
try {
|
|
9704
|
-
await fetch(
|
|
9705
|
-
`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/stations/${subId}`,
|
|
9706
|
-
{
|
|
9707
|
-
method: "DELETE",
|
|
9708
|
-
headers: cloudHeaders(cloudRoomId),
|
|
9709
|
-
signal: AbortSignal.timeout(3e4)
|
|
9710
|
-
}
|
|
9711
|
-
);
|
|
9712
|
-
} catch {
|
|
9713
|
-
} finally {
|
|
9714
|
-
invalidateCloudStationsCache(cloudRoomId);
|
|
9715
|
-
}
|
|
9716
|
-
}
|
|
9717
|
-
async function cancelCloudStation(cloudRoomId, subId) {
|
|
9718
|
-
try {
|
|
9719
|
-
await fetch(
|
|
9720
|
-
`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/billing/cancel/${subId}`,
|
|
9721
|
-
{
|
|
9722
|
-
method: "POST",
|
|
9723
|
-
headers: cloudHeaders(cloudRoomId),
|
|
9724
|
-
signal: AbortSignal.timeout(3e4)
|
|
9725
|
-
}
|
|
9726
|
-
);
|
|
9727
|
-
} catch {
|
|
9728
|
-
} finally {
|
|
9729
|
-
invalidateCloudStationsCache(cloudRoomId);
|
|
9730
|
-
}
|
|
9731
|
-
}
|
|
9732
|
-
async function getCloudCryptoPrices(cloudRoomId) {
|
|
9733
|
-
try {
|
|
9734
|
-
const res = await fetch(
|
|
9735
|
-
`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/billing/crypto-prices`,
|
|
9736
|
-
{ signal: AbortSignal.timeout(1e4) }
|
|
9737
|
-
);
|
|
9738
|
-
if (!res.ok) return null;
|
|
9739
|
-
return res.json();
|
|
9740
|
-
} catch {
|
|
9741
|
-
return null;
|
|
9742
|
-
}
|
|
9577
|
+
return (0, import_crypto6.createHash)("sha256").update(`${machineId}:${dbRoomId}`).digest("hex").slice(0, 32);
|
|
9743
9578
|
}
|
|
9744
9579
|
async function getCloudOnrampUrl(cloudRoomId, walletAddress, amount) {
|
|
9745
9580
|
try {
|
|
@@ -9755,42 +9590,6 @@ async function getCloudOnrampUrl(cloudRoomId, walletAddress, amount) {
|
|
|
9755
9590
|
return null;
|
|
9756
9591
|
}
|
|
9757
9592
|
}
|
|
9758
|
-
async function cryptoCheckoutStation(cloudRoomId, tier, stationName, txHash, chain = "base") {
|
|
9759
|
-
try {
|
|
9760
|
-
const res = await fetch(
|
|
9761
|
-
`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/billing/crypto-checkout`,
|
|
9762
|
-
{
|
|
9763
|
-
method: "POST",
|
|
9764
|
-
headers: cloudHeaders(cloudRoomId, { "Content-Type": "application/json" }),
|
|
9765
|
-
body: JSON.stringify({ tier, stationName, txHash, chain }),
|
|
9766
|
-
signal: AbortSignal.timeout(6e4)
|
|
9767
|
-
}
|
|
9768
|
-
);
|
|
9769
|
-
return res.json();
|
|
9770
|
-
} catch (err) {
|
|
9771
|
-
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
9772
|
-
} finally {
|
|
9773
|
-
invalidateCloudStationsCache(cloudRoomId);
|
|
9774
|
-
}
|
|
9775
|
-
}
|
|
9776
|
-
async function cryptoRenewStation(cloudRoomId, subscriptionId, txHash, chain = "base") {
|
|
9777
|
-
try {
|
|
9778
|
-
const res = await fetch(
|
|
9779
|
-
`${getCloudApi()}/rooms/${encodeURIComponent(cloudRoomId)}/billing/crypto-renew/${subscriptionId}`,
|
|
9780
|
-
{
|
|
9781
|
-
method: "POST",
|
|
9782
|
-
headers: cloudHeaders(cloudRoomId, { "Content-Type": "application/json" }),
|
|
9783
|
-
body: JSON.stringify({ txHash, chain }),
|
|
9784
|
-
signal: AbortSignal.timeout(6e4)
|
|
9785
|
-
}
|
|
9786
|
-
);
|
|
9787
|
-
return res.json();
|
|
9788
|
-
} catch (err) {
|
|
9789
|
-
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
9790
|
-
} finally {
|
|
9791
|
-
invalidateCloudStationsCache(cloudRoomId);
|
|
9792
|
-
}
|
|
9793
|
-
}
|
|
9794
9593
|
async function sendCloudRoomMessage(fromRoomId, toRoomId, subject, body) {
|
|
9795
9594
|
try {
|
|
9796
9595
|
const res = await fetch(`${getCloudApi()}/rooms/message`, {
|
|
@@ -9890,20 +9689,18 @@ async function fetchReferredRooms(cloudRoomId) {
|
|
|
9890
9689
|
return [];
|
|
9891
9690
|
}
|
|
9892
9691
|
}
|
|
9893
|
-
var
|
|
9692
|
+
var import_crypto6, import_os4, import_path3, import_fs3, TOKEN_FILE_NAME, cachedTokens, heartbeatInterval, PUBLIC_ROOMS_CACHE_MS, cachedPublicRooms;
|
|
9894
9693
|
var init_cloud_sync = __esm({
|
|
9895
9694
|
"src/shared/cloud-sync.ts"() {
|
|
9896
9695
|
"use strict";
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9696
|
+
import_crypto6 = require("crypto");
|
|
9697
|
+
import_os4 = require("os");
|
|
9698
|
+
import_path3 = require("path");
|
|
9699
|
+
import_fs3 = require("fs");
|
|
9901
9700
|
init_telemetry();
|
|
9902
9701
|
TOKEN_FILE_NAME = "cloud-room-tokens.json";
|
|
9903
9702
|
cachedTokens = null;
|
|
9904
9703
|
heartbeatInterval = null;
|
|
9905
|
-
CLOUD_STATIONS_CACHE_MS = 1e4;
|
|
9906
|
-
cloudStationsCache = /* @__PURE__ */ new Map();
|
|
9907
9704
|
PUBLIC_ROOMS_CACHE_MS = 3e4;
|
|
9908
9705
|
cachedPublicRooms = null;
|
|
9909
9706
|
}
|
|
@@ -9914,7 +9711,7 @@ var require_package = __commonJS({
|
|
|
9914
9711
|
"package.json"(exports2, module2) {
|
|
9915
9712
|
module2.exports = {
|
|
9916
9713
|
name: "quoroom",
|
|
9917
|
-
version: "0.1.
|
|
9714
|
+
version: "0.1.41",
|
|
9918
9715
|
description: "Open-source local AI agent framework \u2014 Queen, Workers, Quorum. Experimental research tool.",
|
|
9919
9716
|
main: "./out/mcp/server.js",
|
|
9920
9717
|
bin: {
|
|
@@ -10931,6 +10728,7 @@ var require_node_cron = __commonJS({
|
|
|
10931
10728
|
// src/server/index.ts
|
|
10932
10729
|
var index_exports = {};
|
|
10933
10730
|
__export(index_exports, {
|
|
10731
|
+
_createCloudReadyUpdateHandler: () => createCloudReadyUpdateHandler,
|
|
10934
10732
|
_isLoopbackAddress: () => isLoopbackAddress,
|
|
10935
10733
|
_resolveStaticDirForStart: () => resolveStaticDirForStart,
|
|
10936
10734
|
_shellQuote: () => shellQuote,
|
|
@@ -10940,7 +10738,7 @@ __export(index_exports, {
|
|
|
10940
10738
|
});
|
|
10941
10739
|
module.exports = __toCommonJS(index_exports);
|
|
10942
10740
|
var import_node_http2 = __toESM(require("node:http"));
|
|
10943
|
-
var
|
|
10741
|
+
var import_node_https2 = __toESM(require("node:https"));
|
|
10944
10742
|
var import_node_url = require("node:url");
|
|
10945
10743
|
var import_node_fs6 = __toESM(require("node:fs"));
|
|
10946
10744
|
var import_node_path9 = __toESM(require("node:path"));
|
|
@@ -11313,24 +11111,24 @@ var CHAIN_CONFIGS = {
|
|
|
11313
11111
|
var SUPPORTED_CHAINS = ["base", "ethereum", "arbitrum", "optimism", "polygon"];
|
|
11314
11112
|
var SUPPORTED_TOKENS = ["usdc", "usdt"];
|
|
11315
11113
|
var QUEEN_DEFAULTS_BY_PLAN = {
|
|
11316
|
-
none: { queenCycleGapMs: 10 * 60 * 1e3, queenMaxTurns:
|
|
11317
|
-
// 10 min gap,
|
|
11318
|
-
pro: { queenCycleGapMs: 5 * 60 * 1e3, queenMaxTurns:
|
|
11319
|
-
// 5 min gap,
|
|
11320
|
-
max: { queenCycleGapMs: 30 * 1e3, queenMaxTurns:
|
|
11321
|
-
// 30s gap,
|
|
11322
|
-
api: { queenCycleGapMs: 2 * 60 * 1e3, queenMaxTurns:
|
|
11323
|
-
// 2 min gap,
|
|
11114
|
+
none: { queenCycleGapMs: 10 * 60 * 1e3, queenMaxTurns: 50 },
|
|
11115
|
+
// 10 min gap, 50 turns
|
|
11116
|
+
pro: { queenCycleGapMs: 5 * 60 * 1e3, queenMaxTurns: 50 },
|
|
11117
|
+
// 5 min gap, 50 turns
|
|
11118
|
+
max: { queenCycleGapMs: 30 * 1e3, queenMaxTurns: 50 },
|
|
11119
|
+
// 30s gap, 50 turns
|
|
11120
|
+
api: { queenCycleGapMs: 2 * 60 * 1e3, queenMaxTurns: 50 }
|
|
11121
|
+
// 2 min gap, 50 turns
|
|
11324
11122
|
};
|
|
11325
11123
|
var CHATGPT_DEFAULTS_BY_PLAN = {
|
|
11326
|
-
none: { queenCycleGapMs: 10 * 60 * 1e3, queenMaxTurns:
|
|
11327
|
-
// 10 min gap,
|
|
11328
|
-
plus: { queenCycleGapMs: 5 * 60 * 1e3, queenMaxTurns:
|
|
11329
|
-
// 5 min gap,
|
|
11330
|
-
pro: { queenCycleGapMs: 2 * 60 * 1e3, queenMaxTurns:
|
|
11331
|
-
// 2 min gap,
|
|
11332
|
-
api: { queenCycleGapMs: 2 * 60 * 1e3, queenMaxTurns:
|
|
11333
|
-
// 2 min gap,
|
|
11124
|
+
none: { queenCycleGapMs: 10 * 60 * 1e3, queenMaxTurns: 50 },
|
|
11125
|
+
// 10 min gap, 50 turns
|
|
11126
|
+
plus: { queenCycleGapMs: 5 * 60 * 1e3, queenMaxTurns: 50 },
|
|
11127
|
+
// 5 min gap, 50 turns
|
|
11128
|
+
pro: { queenCycleGapMs: 2 * 60 * 1e3, queenMaxTurns: 50 },
|
|
11129
|
+
// 2 min gap, 50 turns
|
|
11130
|
+
api: { queenCycleGapMs: 2 * 60 * 1e3, queenMaxTurns: 50 }
|
|
11131
|
+
// 2 min gap, 50 turns
|
|
11334
11132
|
};
|
|
11335
11133
|
var WORKER_ROLE_PRESETS = {
|
|
11336
11134
|
guardian: {
|
|
@@ -12200,7 +11998,7 @@ function mapRoomRow(row) {
|
|
|
12200
11998
|
maxConcurrentTasks: row.max_concurrent_tasks ?? 3,
|
|
12201
11999
|
workerModel: row.worker_model ?? "claude",
|
|
12202
12000
|
queenCycleGapMs: row.queen_cycle_gap_ms ?? 18e5,
|
|
12203
|
-
queenMaxTurns: row.queen_max_turns ??
|
|
12001
|
+
queenMaxTurns: row.queen_max_turns ?? 50,
|
|
12204
12002
|
queenQuietFrom: row.queen_quiet_from ?? null,
|
|
12205
12003
|
queenQuietUntil: row.queen_quiet_until ?? null,
|
|
12206
12004
|
config,
|
|
@@ -12832,49 +12630,6 @@ function getWalletTransactionSummary(db2, walletId) {
|
|
|
12832
12630
|
).get(walletId);
|
|
12833
12631
|
return { received: received.total.toString(), sent: sent.total.toString() };
|
|
12834
12632
|
}
|
|
12835
|
-
function mapStationRow(row) {
|
|
12836
|
-
let config = null;
|
|
12837
|
-
if (row.config && typeof row.config === "string") {
|
|
12838
|
-
try {
|
|
12839
|
-
config = JSON.parse(row.config);
|
|
12840
|
-
} catch {
|
|
12841
|
-
}
|
|
12842
|
-
}
|
|
12843
|
-
return {
|
|
12844
|
-
id: row.id,
|
|
12845
|
-
roomId: row.room_id,
|
|
12846
|
-
name: row.name,
|
|
12847
|
-
provider: row.provider,
|
|
12848
|
-
externalId: row.external_id,
|
|
12849
|
-
tier: row.tier,
|
|
12850
|
-
region: row.region,
|
|
12851
|
-
status: row.status,
|
|
12852
|
-
monthlyCost: row.monthly_cost,
|
|
12853
|
-
config,
|
|
12854
|
-
createdAt: row.created_at,
|
|
12855
|
-
updatedAt: row.updated_at
|
|
12856
|
-
};
|
|
12857
|
-
}
|
|
12858
|
-
function getStation(db2, id) {
|
|
12859
|
-
const row = db2.prepare("SELECT * FROM stations WHERE id = ?").get(id);
|
|
12860
|
-
return row ? mapStationRow(row) : null;
|
|
12861
|
-
}
|
|
12862
|
-
function listStations(db2, roomId, status2) {
|
|
12863
|
-
if (roomId && status2) {
|
|
12864
|
-
const rows2 = db2.prepare("SELECT * FROM stations WHERE room_id = ? AND status = ? ORDER BY created_at DESC").all(roomId, status2);
|
|
12865
|
-
return rows2.map(mapStationRow);
|
|
12866
|
-
}
|
|
12867
|
-
if (roomId) {
|
|
12868
|
-
const rows2 = db2.prepare("SELECT * FROM stations WHERE room_id = ? ORDER BY created_at DESC").all(roomId);
|
|
12869
|
-
return rows2.map(mapStationRow);
|
|
12870
|
-
}
|
|
12871
|
-
if (status2) {
|
|
12872
|
-
const rows2 = db2.prepare("SELECT * FROM stations WHERE status = ? ORDER BY created_at DESC").all(status2);
|
|
12873
|
-
return rows2.map(mapStationRow);
|
|
12874
|
-
}
|
|
12875
|
-
const rows = db2.prepare("SELECT * FROM stations ORDER BY created_at DESC").all();
|
|
12876
|
-
return rows.map(mapStationRow);
|
|
12877
|
-
}
|
|
12878
12633
|
function mapClerkMessageRow(row) {
|
|
12879
12634
|
return {
|
|
12880
12635
|
id: row.id,
|
|
@@ -13045,16 +12800,13 @@ function ensureClerkWorker(db2) {
|
|
|
13045
12800
|
}
|
|
13046
12801
|
function getRevenueSummary(db2, roomId) {
|
|
13047
12802
|
const wallet = getWalletByRoom(db2, roomId);
|
|
13048
|
-
if (!wallet) return { totalIncome: 0, totalExpenses: 0, netProfit: 0,
|
|
12803
|
+
if (!wallet) return { totalIncome: 0, totalExpenses: 0, netProfit: 0, transactionCount: 0 };
|
|
13049
12804
|
const income = db2.prepare(
|
|
13050
12805
|
"SELECT COALESCE(SUM(CAST(amount AS REAL)), 0) as total FROM wallet_transactions WHERE wallet_id = ? AND type IN ('receive', 'fund')"
|
|
13051
12806
|
).get(wallet.id);
|
|
13052
12807
|
const expenses = db2.prepare(
|
|
13053
12808
|
"SELECT COALESCE(SUM(CAST(amount AS REAL)), 0) as total FROM wallet_transactions WHERE wallet_id = ? AND type IN ('send', 'purchase')"
|
|
13054
12809
|
).get(wallet.id);
|
|
13055
|
-
const stationCosts = db2.prepare(
|
|
13056
|
-
"SELECT COALESCE(SUM(CAST(amount AS REAL)), 0) as total FROM wallet_transactions WHERE wallet_id = ? AND category = 'station_cost'"
|
|
13057
|
-
).get(wallet.id);
|
|
13058
12810
|
const count = db2.prepare(
|
|
13059
12811
|
"SELECT COUNT(*) as cnt FROM wallet_transactions WHERE wallet_id = ?"
|
|
13060
12812
|
).get(wallet.id);
|
|
@@ -13062,7 +12814,6 @@ function getRevenueSummary(db2, roomId) {
|
|
|
13062
12814
|
totalIncome: income.total,
|
|
13063
12815
|
totalExpenses: expenses.total,
|
|
13064
12816
|
netProfit: income.total - expenses.total,
|
|
13065
|
-
stationCosts: stationCosts.total,
|
|
13066
12817
|
transactionCount: count.cnt
|
|
13067
12818
|
};
|
|
13068
12819
|
}
|
|
@@ -22758,9 +22509,9 @@ var eventBus = new EventBus();
|
|
|
22758
22509
|
|
|
22759
22510
|
// src/shared/agent-executor.ts
|
|
22760
22511
|
var import_child_process2 = require("child_process");
|
|
22761
|
-
var
|
|
22762
|
-
var
|
|
22763
|
-
var
|
|
22512
|
+
var import_fs2 = require("fs");
|
|
22513
|
+
var import_path2 = require("path");
|
|
22514
|
+
var import_os2 = require("os");
|
|
22764
22515
|
|
|
22765
22516
|
// src/shared/claude-code.ts
|
|
22766
22517
|
var import_child_process = require("child_process");
|
|
@@ -23174,7 +22925,6 @@ function executeClaudeCode(prompt, options) {
|
|
|
23174
22925
|
}
|
|
23175
22926
|
|
|
23176
22927
|
// src/shared/agent-executor.ts
|
|
23177
|
-
init_cloud_sync();
|
|
23178
22928
|
var DEFAULT_HTTP_TIMEOUT_MS = 6e4;
|
|
23179
22929
|
function linkAbortSignal(controller, external) {
|
|
23180
22930
|
if (!external) return null;
|
|
@@ -23196,11 +22946,11 @@ function resolveCodexNodeScript() {
|
|
|
23196
22946
|
stdio: ["ignore", "pipe", "ignore"]
|
|
23197
22947
|
}).trim().split("\n")[0].trim();
|
|
23198
22948
|
if (!cmdPath) return null;
|
|
23199
|
-
const content = (0,
|
|
22949
|
+
const content = (0, import_fs2.readFileSync)(cmdPath, "utf-8");
|
|
23200
22950
|
const match = content.match(/%dp0%\\(.+?\.js)/);
|
|
23201
22951
|
if (!match) return null;
|
|
23202
|
-
const script = (0,
|
|
23203
|
-
if ((0,
|
|
22952
|
+
const script = (0, import_path2.join)((0, import_path2.dirname)(cmdPath), match[1]);
|
|
22953
|
+
if ((0, import_fs2.existsSync)(script)) {
|
|
23204
22954
|
_codexNodeScript = script;
|
|
23205
22955
|
return script;
|
|
23206
22956
|
}
|
|
@@ -23280,7 +23030,7 @@ async function executeCodex(options) {
|
|
|
23280
23030
|
const nodeScript = resolveCodexNodeScript();
|
|
23281
23031
|
if (nodeScript) {
|
|
23282
23032
|
proc = (0, import_child_process2.spawn)(process.execPath, [nodeScript, ...args], {
|
|
23283
|
-
cwd: (0,
|
|
23033
|
+
cwd: (0, import_os2.homedir)(),
|
|
23284
23034
|
env: process.env,
|
|
23285
23035
|
stdio: ["ignore", "pipe", "pipe"],
|
|
23286
23036
|
windowsHide: true
|
|
@@ -23288,7 +23038,7 @@ async function executeCodex(options) {
|
|
|
23288
23038
|
} else {
|
|
23289
23039
|
const codexCmd = process.platform === "win32" ? "codex.cmd" : "codex";
|
|
23290
23040
|
proc = (0, import_child_process2.spawn)(codexCmd, args, {
|
|
23291
|
-
cwd: (0,
|
|
23041
|
+
cwd: (0, import_os2.homedir)(),
|
|
23292
23042
|
env: process.env,
|
|
23293
23043
|
stdio: ["ignore", "pipe", "pipe"],
|
|
23294
23044
|
windowsHide: true,
|
|
@@ -23899,99 +23649,6 @@ Respond ONLY with a JSON object (no markdown, no explanation):
|
|
|
23899
23649
|
}
|
|
23900
23650
|
return null;
|
|
23901
23651
|
}
|
|
23902
|
-
async function executeApiOnStation(cloudRoomId, stationId, options) {
|
|
23903
|
-
const startTime = Date.now();
|
|
23904
|
-
const apiKey = options.apiKey;
|
|
23905
|
-
if (!apiKey) {
|
|
23906
|
-
return immediateError("Missing API key for station execution.");
|
|
23907
|
-
}
|
|
23908
|
-
if (options.abortSignal?.aborted) {
|
|
23909
|
-
return {
|
|
23910
|
-
output: "Execution aborted",
|
|
23911
|
-
exitCode: 130,
|
|
23912
|
-
durationMs: Date.now() - startTime,
|
|
23913
|
-
sessionId: null,
|
|
23914
|
-
timedOut: false
|
|
23915
|
-
};
|
|
23916
|
-
}
|
|
23917
|
-
const isOpenAiCompat = options.model.startsWith("openai:") || options.model.startsWith("gemini:");
|
|
23918
|
-
const messages = [];
|
|
23919
|
-
if (options.systemPrompt) messages.push({ role: "system", content: options.systemPrompt });
|
|
23920
|
-
messages.push({ role: "user", content: options.prompt });
|
|
23921
|
-
let url;
|
|
23922
|
-
let headers;
|
|
23923
|
-
let body;
|
|
23924
|
-
if (isOpenAiCompat) {
|
|
23925
|
-
const config = resolveOpenAiCompatible(options.model, apiKey);
|
|
23926
|
-
const modelName = config ? parseModelSuffix(options.model, config.prefix) || config.defaultModel : parseModelSuffix(options.model, "openai") || "gpt-4o-mini";
|
|
23927
|
-
url = config?.url ?? "https://api.openai.com/v1/chat/completions";
|
|
23928
|
-
headers = { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json" };
|
|
23929
|
-
body = JSON.stringify({ model: modelName, messages });
|
|
23930
|
-
} else {
|
|
23931
|
-
const modelName = parseAnthropicModel(options.model);
|
|
23932
|
-
url = "https://api.anthropic.com/v1/messages";
|
|
23933
|
-
headers = { "x-api-key": apiKey, "anthropic-version": "2023-06-01", "content-type": "application/json" };
|
|
23934
|
-
body = JSON.stringify({
|
|
23935
|
-
model: modelName,
|
|
23936
|
-
max_tokens: 2048,
|
|
23937
|
-
system: options.systemPrompt,
|
|
23938
|
-
messages: [{ role: "user", content: options.prompt }]
|
|
23939
|
-
});
|
|
23940
|
-
}
|
|
23941
|
-
const headerFlags = Object.entries(headers).map(([k, v]) => `-H '${k}: ${v}'`).join(" ");
|
|
23942
|
-
const b64 = Buffer.from(body).toString("base64");
|
|
23943
|
-
const command = `echo '${b64}' | base64 -d | curl -s --max-time 300 ${headerFlags} -d @- '${url}'`;
|
|
23944
|
-
const result = await new Promise((resolve2) => {
|
|
23945
|
-
let settled = false;
|
|
23946
|
-
const finish = (value) => {
|
|
23947
|
-
if (settled) return;
|
|
23948
|
-
settled = true;
|
|
23949
|
-
resolve2(value);
|
|
23950
|
-
};
|
|
23951
|
-
const onAbort = () => finish({ stdout: "", stderr: "Execution aborted", exitCode: 130 });
|
|
23952
|
-
if (options.abortSignal) {
|
|
23953
|
-
if (options.abortSignal.aborted) {
|
|
23954
|
-
onAbort();
|
|
23955
|
-
return;
|
|
23956
|
-
}
|
|
23957
|
-
options.abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
23958
|
-
}
|
|
23959
|
-
void execOnCloudStation(cloudRoomId, stationId, command, 36e4).then((value) => finish(value)).catch(() => finish(null)).finally(() => {
|
|
23960
|
-
if (options.abortSignal) options.abortSignal.removeEventListener("abort", onAbort);
|
|
23961
|
-
});
|
|
23962
|
-
});
|
|
23963
|
-
if (!result) {
|
|
23964
|
-
return {
|
|
23965
|
-
output: "Error: station execution failed (station unreachable)",
|
|
23966
|
-
exitCode: 1,
|
|
23967
|
-
durationMs: Date.now() - startTime,
|
|
23968
|
-
sessionId: null,
|
|
23969
|
-
timedOut: false
|
|
23970
|
-
};
|
|
23971
|
-
}
|
|
23972
|
-
if (result.exitCode !== 0) {
|
|
23973
|
-
return {
|
|
23974
|
-
output: result.stderr || result.stdout || `Station exec failed with exit code ${result.exitCode}`,
|
|
23975
|
-
exitCode: result.exitCode,
|
|
23976
|
-
durationMs: Date.now() - startTime,
|
|
23977
|
-
sessionId: null,
|
|
23978
|
-
timedOut: false
|
|
23979
|
-
};
|
|
23980
|
-
}
|
|
23981
|
-
try {
|
|
23982
|
-
const parsed = JSON.parse(result.stdout);
|
|
23983
|
-
const output = isOpenAiCompat ? extractOpenAiText(parsed) : extractAnthropicText(parsed);
|
|
23984
|
-
return { output, exitCode: 0, durationMs: Date.now() - startTime, sessionId: null, timedOut: false };
|
|
23985
|
-
} catch {
|
|
23986
|
-
return {
|
|
23987
|
-
output: result.stdout || "(no output from API)",
|
|
23988
|
-
exitCode: 1,
|
|
23989
|
-
durationMs: Date.now() - startTime,
|
|
23990
|
-
sessionId: null,
|
|
23991
|
-
timedOut: false
|
|
23992
|
-
};
|
|
23993
|
-
}
|
|
23994
|
-
}
|
|
23995
23652
|
|
|
23996
23653
|
// src/shared/quorum.ts
|
|
23997
23654
|
function announce(db2, options) {
|
|
@@ -24367,7 +24024,7 @@ function createCycleLogBuffer(cycleId, writer, onEntry) {
|
|
|
24367
24024
|
}
|
|
24368
24025
|
|
|
24369
24026
|
// src/shared/web-tools.ts
|
|
24370
|
-
var
|
|
24027
|
+
var import_crypto4 = require("crypto");
|
|
24371
24028
|
var import_node_os2 = require("node:os");
|
|
24372
24029
|
var import_node_path2 = __toESM(require("node:path"));
|
|
24373
24030
|
var MAX_CONTENT_CHARS = 12e3;
|
|
@@ -24428,7 +24085,7 @@ async function getOrCreateSession(sessionId) {
|
|
|
24428
24085
|
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
24429
24086
|
viewport: { width: 1280, height: 720 }
|
|
24430
24087
|
});
|
|
24431
|
-
const id = sessionId ?? (0,
|
|
24088
|
+
const id = sessionId ?? (0, import_crypto4.randomUUID)();
|
|
24432
24089
|
const session = { context, lastUsed: Date.now(), id };
|
|
24433
24090
|
_sessions.set(id, session);
|
|
24434
24091
|
startSessionCleanup();
|
|
@@ -26082,11 +25739,6 @@ var CLOUD_EVENT_MAP = {
|
|
|
26082
25739
|
"run:completed": "task_completed",
|
|
26083
25740
|
"run:failed": "task_failed",
|
|
26084
25741
|
"skill:created": "skill_created",
|
|
26085
|
-
"station:created": "station_created",
|
|
26086
|
-
"station:started": "station_started",
|
|
26087
|
-
"station:stopped": "station_stopped",
|
|
26088
|
-
"station:canceled": "station_stopped",
|
|
26089
|
-
"station:deleted": "station_stopped",
|
|
26090
25742
|
"self_mod:edited": "self_mod",
|
|
26091
25743
|
"self_mod:reverted": "self_mod",
|
|
26092
25744
|
"wallet:sent": "money_sent",
|
|
@@ -26141,7 +25793,6 @@ function initCloudSync(db2) {
|
|
|
26141
25793
|
if (allRooms.length === 0) return [];
|
|
26142
25794
|
const allWorkers = listWorkers(db2);
|
|
26143
25795
|
const tasks = listTasks(db2);
|
|
26144
|
-
const allStations = listStations(db2);
|
|
26145
25796
|
const version5 = getVersion2();
|
|
26146
25797
|
const workersPerRoom = /* @__PURE__ */ new Map();
|
|
26147
25798
|
const workerCounts = /* @__PURE__ */ new Map();
|
|
@@ -26152,13 +25803,6 @@ function initCloudSync(db2) {
|
|
|
26152
25803
|
list.push({ name: worker.name, state: worker.agentState, model: worker.model ?? void 0 });
|
|
26153
25804
|
workersPerRoom.set(worker.roomId, list);
|
|
26154
25805
|
}
|
|
26155
|
-
const stationsPerRoom = /* @__PURE__ */ new Map();
|
|
26156
|
-
for (const station of allStations) {
|
|
26157
|
-
if (station.roomId == null) continue;
|
|
26158
|
-
const list = stationsPerRoom.get(station.roomId) ?? [];
|
|
26159
|
-
list.push({ name: station.name, status: station.status, tier: station.tier });
|
|
26160
|
-
stationsPerRoom.set(station.roomId, list);
|
|
26161
|
-
}
|
|
26162
25806
|
const taskCounts = /* @__PURE__ */ new Map();
|
|
26163
25807
|
for (const task of tasks) {
|
|
26164
25808
|
if (task.roomId == null) continue;
|
|
@@ -26185,7 +25829,6 @@ function initCloudSync(db2) {
|
|
|
26185
25829
|
version: version5,
|
|
26186
25830
|
queenModel: queen?.model ?? null,
|
|
26187
25831
|
workers: privateWorkers,
|
|
26188
|
-
stations: [],
|
|
26189
25832
|
visibility: "private"
|
|
26190
25833
|
};
|
|
26191
25834
|
}
|
|
@@ -26206,7 +25849,6 @@ function initCloudSync(db2) {
|
|
|
26206
25849
|
version: version5,
|
|
26207
25850
|
queenModel: queen?.model ?? null,
|
|
26208
25851
|
workers: workersPerRoom.get(room.id) ?? [],
|
|
26209
|
-
stations: stationsPerRoom.get(room.id) ?? [],
|
|
26210
25852
|
visibility: "public",
|
|
26211
25853
|
referredByCode: room.referredByCode,
|
|
26212
25854
|
keeperReferralCode
|
|
@@ -26228,7 +25870,6 @@ var import_node_cron = __toESM(require_node_cron());
|
|
|
26228
25870
|
// src/shared/task-runner.ts
|
|
26229
25871
|
var import_path4 = require("path");
|
|
26230
25872
|
var import_fs4 = require("fs");
|
|
26231
|
-
init_cloud_sync();
|
|
26232
25873
|
|
|
26233
25874
|
// src/shared/learned-context.ts
|
|
26234
25875
|
var DISTILL_AFTER_RUNS = 3;
|
|
@@ -26559,78 +26200,6 @@ async function executeTask(taskId, options) {
|
|
|
26559
26200
|
} catch (err) {
|
|
26560
26201
|
console.warn("Non-fatal: worker resolution failed:", err);
|
|
26561
26202
|
}
|
|
26562
|
-
const isStationModel = model?.startsWith("openai:") || model?.startsWith("anthropic:") || model?.startsWith("claude-api:");
|
|
26563
|
-
if (isStationModel && task.roomId) {
|
|
26564
|
-
runningTasks.add(taskId);
|
|
26565
|
-
taskAbortControllers.set(taskId, taskAbort);
|
|
26566
|
-
try {
|
|
26567
|
-
const cloudRoomId = getRoomCloudId(task.roomId);
|
|
26568
|
-
const stations = await listCloudStations(cloudRoomId);
|
|
26569
|
-
const activeStations = stations.filter((s) => s.status === "active");
|
|
26570
|
-
if (activeStations.length > 0) {
|
|
26571
|
-
const run2 = createTaskRun(db2, taskId);
|
|
26572
|
-
try {
|
|
26573
|
-
const station = activeStations[run2.id % activeStations.length];
|
|
26574
|
-
let augmentedPrompt = prependKeeperReferral(task.prompt, db2);
|
|
26575
|
-
try {
|
|
26576
|
-
if (task.learnedContext) {
|
|
26577
|
-
augmentedPrompt = `## Approach (learned from previous runs):
|
|
26578
|
-
${task.learnedContext}
|
|
26579
|
-
|
|
26580
|
-
---
|
|
26581
|
-
|
|
26582
|
-
${augmentedPrompt}`;
|
|
26583
|
-
}
|
|
26584
|
-
} catch (err) {
|
|
26585
|
-
console.warn("Non-fatal: learned context injection failed:", err);
|
|
26586
|
-
}
|
|
26587
|
-
try {
|
|
26588
|
-
const memoryContext = getTaskMemoryContext(db2, taskId);
|
|
26589
|
-
if (memoryContext) {
|
|
26590
|
-
augmentedPrompt = `${memoryContext}
|
|
26591
|
-
|
|
26592
|
-
---
|
|
26593
|
-
|
|
26594
|
-
${augmentedPrompt}`;
|
|
26595
|
-
}
|
|
26596
|
-
} catch (err) {
|
|
26597
|
-
console.warn("Non-fatal: memory injection failed:", err);
|
|
26598
|
-
}
|
|
26599
|
-
const timeoutMs = task.timeoutMinutes != null ? task.timeoutMinutes * 60 * 1e3 : void 0;
|
|
26600
|
-
const stationModel = model;
|
|
26601
|
-
const apiKey = resolveApiKeyForModel(db2, task.roomId, stationModel);
|
|
26602
|
-
const agentResult = await executeApiOnStation(cloudRoomId, station.id, {
|
|
26603
|
-
model: stationModel,
|
|
26604
|
-
prompt: augmentedPrompt,
|
|
26605
|
-
systemPrompt,
|
|
26606
|
-
timeoutMs,
|
|
26607
|
-
apiKey,
|
|
26608
|
-
abortSignal: taskAbort.signal
|
|
26609
|
-
});
|
|
26610
|
-
const result = agentResultToExecutionResult(agentResult);
|
|
26611
|
-
if (taskAbort.signal.aborted) {
|
|
26612
|
-
const errorMsg = "Execution aborted";
|
|
26613
|
-
completeTaskRun(db2, run2.id, result.stdout || errorMsg, void 0, errorMsg);
|
|
26614
|
-
onFailed?.(task, errorMsg);
|
|
26615
|
-
return { success: false, output: result.stdout || "", errorMessage: errorMsg, durationMs: Date.now() - startTime };
|
|
26616
|
-
}
|
|
26617
|
-
return finishRun(db2, run2.id, taskId, task, result, resultsDir, onComplete, onFailed);
|
|
26618
|
-
} catch (err) {
|
|
26619
|
-
const errorMsg = taskAbort.signal.aborted ? "Execution aborted" : err instanceof Error ? err.message : String(err);
|
|
26620
|
-
completeTaskRun(db2, run2.id, "", void 0, errorMsg);
|
|
26621
|
-
onFailed?.(task, errorMsg);
|
|
26622
|
-
return { success: false, output: "", errorMessage: errorMsg, durationMs: Date.now() - startTime };
|
|
26623
|
-
}
|
|
26624
|
-
}
|
|
26625
|
-
} catch (err) {
|
|
26626
|
-
const errorMsg = taskAbort.signal.aborted ? "Execution aborted" : err instanceof Error ? err.message : String(err);
|
|
26627
|
-
onFailed?.(task, errorMsg);
|
|
26628
|
-
return { success: false, output: "", errorMessage: errorMsg, durationMs: Date.now() - startTime };
|
|
26629
|
-
} finally {
|
|
26630
|
-
runningTasks.delete(taskId);
|
|
26631
|
-
taskAbortControllers.delete(taskId);
|
|
26632
|
-
}
|
|
26633
|
-
}
|
|
26634
26203
|
await acquireSlot(getMaxConcurrentTasks(db2, task.roomId));
|
|
26635
26204
|
runningTasks.add(taskId);
|
|
26636
26205
|
taskAbortControllers.set(taskId, taskAbort);
|
|
@@ -26805,16 +26374,6 @@ ${retryPrompt}`;
|
|
|
26805
26374
|
releaseSlot();
|
|
26806
26375
|
}
|
|
26807
26376
|
}
|
|
26808
|
-
function agentResultToExecutionResult(result) {
|
|
26809
|
-
return {
|
|
26810
|
-
stdout: result.output,
|
|
26811
|
-
stderr: "",
|
|
26812
|
-
exitCode: result.exitCode,
|
|
26813
|
-
durationMs: result.durationMs,
|
|
26814
|
-
timedOut: result.timedOut,
|
|
26815
|
-
sessionId: result.sessionId
|
|
26816
|
-
};
|
|
26817
|
-
}
|
|
26818
26377
|
function finishRun(db2, runId, taskId, task, result, resultsDir, onComplete, onFailed) {
|
|
26819
26378
|
const output = result.stdout || result.stderr || "(no output)";
|
|
26820
26379
|
const resultFilePath = saveResult(resultsDir, task.name, output, result);
|
|
@@ -27433,10 +26992,6 @@ var TOOL_NAMES = {
|
|
|
27433
26992
|
// Rooms
|
|
27434
26993
|
quoroom_list_rooms: "listing rooms",
|
|
27435
26994
|
quoroom_room_status: "checking room status",
|
|
27436
|
-
// Stations
|
|
27437
|
-
quoroom_station_create: "creating a station",
|
|
27438
|
-
quoroom_station_list: "listing stations",
|
|
27439
|
-
quoroom_station_exec: "running station command",
|
|
27440
26995
|
// Identity & invites
|
|
27441
26996
|
quoroom_identity_get: "checking identity",
|
|
27442
26997
|
quoroom_invite_create: "creating an invite",
|
|
@@ -29751,14 +29306,14 @@ async function issueEmailVerification(db2, email) {
|
|
|
29751
29306
|
const { windowStartMs, windowCount } = emailSendGate(db2, nowMs);
|
|
29752
29307
|
const code = import_node_crypto4.default.randomInt(0, 1e6).toString().padStart(6, "0");
|
|
29753
29308
|
await sendVerificationCodeEmail(db2, email, code);
|
|
29754
|
-
const
|
|
29309
|
+
const nowIso4 = new Date(nowMs).toISOString();
|
|
29755
29310
|
const expiresAt = new Date(nowMs + EMAIL_VERIFY_CODE_TTL_MINUTES * 60 * 1e3).toISOString();
|
|
29756
29311
|
const codeHash = hashEmailCode(email, code);
|
|
29757
29312
|
setSetting2(db2, CONTACT_EMAIL_KEY, email);
|
|
29758
29313
|
clearSetting(db2, CONTACT_EMAIL_VERIFIED_AT_KEY);
|
|
29759
29314
|
setSetting2(db2, CONTACT_EMAIL_CODE_HASH_KEY, codeHash);
|
|
29760
29315
|
setSetting2(db2, CONTACT_EMAIL_CODE_EXPIRES_AT_KEY, expiresAt);
|
|
29761
|
-
setSetting2(db2, CONTACT_EMAIL_LAST_SENT_AT_KEY,
|
|
29316
|
+
setSetting2(db2, CONTACT_EMAIL_LAST_SENT_AT_KEY, nowIso4);
|
|
29762
29317
|
setSetting2(db2, CONTACT_EMAIL_RATE_WINDOW_START_KEY, new Date(windowStartMs).toISOString());
|
|
29763
29318
|
setSetting2(db2, CONTACT_EMAIL_RATE_WINDOW_COUNT_KEY, String(windowCount + 1));
|
|
29764
29319
|
return {
|
|
@@ -30740,13 +30295,6 @@ function getLocalReferredRooms(db2, roomId) {
|
|
|
30740
30295
|
if (task.roomId == null) continue;
|
|
30741
30296
|
taskCountByRoom.set(task.roomId, (taskCountByRoom.get(task.roomId) ?? 0) + 1);
|
|
30742
30297
|
}
|
|
30743
|
-
const stationsByRoom = /* @__PURE__ */ new Map();
|
|
30744
|
-
for (const station of listStations(db2)) {
|
|
30745
|
-
if (station.roomId == null) continue;
|
|
30746
|
-
const rows = stationsByRoom.get(station.roomId) ?? [];
|
|
30747
|
-
rows.push({ name: station.name, status: station.status, tier: station.tier });
|
|
30748
|
-
stationsByRoom.set(station.roomId, rows);
|
|
30749
|
-
}
|
|
30750
30298
|
return referredRooms.map((candidate) => {
|
|
30751
30299
|
if (candidate.visibility !== "public") {
|
|
30752
30300
|
return {
|
|
@@ -30756,7 +30304,6 @@ function getLocalReferredRooms(db2, roomId) {
|
|
|
30756
30304
|
};
|
|
30757
30305
|
}
|
|
30758
30306
|
const workers = workersByRoom.get(candidate.id) ?? [];
|
|
30759
|
-
const stations = stationsByRoom.get(candidate.id) ?? [];
|
|
30760
30307
|
const wallet = getWalletByRoom(db2, candidate.id);
|
|
30761
30308
|
const earnings = wallet ? getWalletTransactionSummary(db2, wallet.id).received : "0";
|
|
30762
30309
|
const queen = candidate.queenWorkerId ? getWorker(db2, candidate.queenWorkerId) : null;
|
|
@@ -30770,7 +30317,6 @@ function getLocalReferredRooms(db2, roomId) {
|
|
|
30770
30317
|
earnings,
|
|
30771
30318
|
queenModel: queen?.model ?? candidate.workerModel ?? null,
|
|
30772
30319
|
workers,
|
|
30773
|
-
stations,
|
|
30774
30320
|
online: candidate.status === "active",
|
|
30775
30321
|
registeredAt: candidate.createdAt
|
|
30776
30322
|
};
|
|
@@ -31903,7 +31449,7 @@ CREATE TABLE IF NOT EXISTS rooms (
|
|
|
31903
31449
|
max_concurrent_tasks INTEGER NOT NULL DEFAULT 3,
|
|
31904
31450
|
worker_model TEXT NOT NULL DEFAULT 'claude',
|
|
31905
31451
|
queen_cycle_gap_ms INTEGER NOT NULL DEFAULT 1800000,
|
|
31906
|
-
queen_max_turns INTEGER NOT NULL DEFAULT
|
|
31452
|
+
queen_max_turns INTEGER NOT NULL DEFAULT 50,
|
|
31907
31453
|
queen_quiet_from TEXT,
|
|
31908
31454
|
queen_quiet_until TEXT,
|
|
31909
31455
|
config TEXT,
|
|
@@ -32257,23 +31803,6 @@ CREATE TABLE IF NOT EXISTS room_messages (
|
|
|
32257
31803
|
CREATE INDEX IF NOT EXISTS idx_room_messages_room ON room_messages(room_id);
|
|
32258
31804
|
CREATE INDEX IF NOT EXISTS idx_room_messages_status ON room_messages(status);
|
|
32259
31805
|
|
|
32260
|
-
-- Stations
|
|
32261
|
-
CREATE TABLE IF NOT EXISTS stations (
|
|
32262
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
32263
|
-
room_id INTEGER NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
32264
|
-
name TEXT NOT NULL,
|
|
32265
|
-
provider TEXT NOT NULL,
|
|
32266
|
-
external_id TEXT,
|
|
32267
|
-
tier TEXT NOT NULL,
|
|
32268
|
-
region TEXT,
|
|
32269
|
-
status TEXT NOT NULL DEFAULT 'provisioning',
|
|
32270
|
-
monthly_cost REAL NOT NULL DEFAULT 0,
|
|
32271
|
-
config TEXT,
|
|
32272
|
-
created_at DATETIME DEFAULT (datetime('now','localtime')),
|
|
32273
|
-
updated_at DATETIME DEFAULT (datetime('now','localtime'))
|
|
32274
|
-
);
|
|
32275
|
-
CREATE INDEX IF NOT EXISTS idx_stations_room ON stations(room_id);
|
|
32276
|
-
|
|
32277
31806
|
-- Worker cycles (agent loop execution tracking)
|
|
32278
31807
|
CREATE TABLE IF NOT EXISTS worker_cycles (
|
|
32279
31808
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -32357,6 +31886,10 @@ function upsertSetting(database, key, value) {
|
|
|
32357
31886
|
}
|
|
32358
31887
|
function runMigrations(database, log = console.log) {
|
|
32359
31888
|
database.exec(SCHEMA);
|
|
31889
|
+
const legacyQueenTurnsUpdated = database.prepare(`UPDATE rooms SET queen_max_turns = 50 WHERE queen_max_turns = 3`).run().changes;
|
|
31890
|
+
if (legacyQueenTurnsUpdated > 0) {
|
|
31891
|
+
log(`Migrated: updated ${legacyQueenTurnsUpdated} room(s) queen_max_turns from 3 to 50`);
|
|
31892
|
+
}
|
|
32360
31893
|
if (!database.prepare("SELECT value FROM settings WHERE key = ?").get("keeper_referral_code")) {
|
|
32361
31894
|
const code = (0, import_crypto10.randomBytes)(6).toString("base64url").slice(0, 10);
|
|
32362
31895
|
upsertSetting(database, "keeper_referral_code", code);
|
|
@@ -32455,6 +31988,7 @@ function runMigrations(database, log = console.log) {
|
|
|
32455
31988
|
log(`Migrated: reset ${ollamaRooms.length} room worker_model(s) to 'claude'`);
|
|
32456
31989
|
}
|
|
32457
31990
|
database.prepare(`UPDATE rooms SET autonomy_mode = 'semi' WHERE autonomy_mode IS NULL OR autonomy_mode != 'semi'`).run();
|
|
31991
|
+
database.exec(`DROP TABLE IF EXISTS stations`);
|
|
32458
31992
|
log("Database schema initialized");
|
|
32459
31993
|
}
|
|
32460
31994
|
|
|
@@ -32512,9 +32046,6 @@ function closeServerDatabase() {
|
|
|
32512
32046
|
}
|
|
32513
32047
|
}
|
|
32514
32048
|
|
|
32515
|
-
// src/server/updateChecker.ts
|
|
32516
|
-
var import_node_https2 = __toESM(require("node:https"));
|
|
32517
|
-
|
|
32518
32049
|
// src/server/autoUpdate.ts
|
|
32519
32050
|
var import_node_fs4 = __toESM(require("node:fs"));
|
|
32520
32051
|
var import_node_path6 = __toESM(require("node:path"));
|
|
@@ -32672,7 +32203,7 @@ function semverGt(a, b) {
|
|
|
32672
32203
|
}
|
|
32673
32204
|
function getCurrentVersion() {
|
|
32674
32205
|
try {
|
|
32675
|
-
return true ? "0.1.
|
|
32206
|
+
return true ? "0.1.41" : null.version;
|
|
32676
32207
|
} catch {
|
|
32677
32208
|
return "0.0.0";
|
|
32678
32209
|
}
|
|
@@ -32727,11 +32258,37 @@ async function checkAndApplyUpdate(bundleUrl, targetVersion) {
|
|
|
32727
32258
|
}
|
|
32728
32259
|
|
|
32729
32260
|
// src/server/updateChecker.ts
|
|
32730
|
-
var
|
|
32261
|
+
var DEFAULT_CHECK_INTERVAL = 4 * 60 * 60 * 1e3;
|
|
32731
32262
|
var INITIAL_DELAY = 15e3;
|
|
32263
|
+
var REQUEST_TIMEOUT_MS = 1e4;
|
|
32264
|
+
var BACKOFF_BASE_MS = 3e4;
|
|
32265
|
+
var BACKOFF_MAX_MS = 30 * 60 * 1e3;
|
|
32266
|
+
var GITHUB_RELEASES_URL = "https://api.github.com/repos/quoroom-ai/room/releases?per_page=100";
|
|
32267
|
+
var DEFAULT_RELEASE_URL = "https://github.com/quoroom-ai/room/releases";
|
|
32732
32268
|
var cached = null;
|
|
32733
32269
|
var initTimer = null;
|
|
32734
32270
|
var pollInterval = null;
|
|
32271
|
+
var consecutiveFailures = 0;
|
|
32272
|
+
var backoffUntil = 0;
|
|
32273
|
+
var diagnostics = {
|
|
32274
|
+
lastCheckAt: null,
|
|
32275
|
+
lastSuccessAt: null,
|
|
32276
|
+
lastErrorAt: null,
|
|
32277
|
+
lastErrorCode: null,
|
|
32278
|
+
lastErrorMessage: null,
|
|
32279
|
+
updateSource: null,
|
|
32280
|
+
nextCheckAt: null,
|
|
32281
|
+
consecutiveFailures: 0
|
|
32282
|
+
};
|
|
32283
|
+
var UpdateCheckError = class extends Error {
|
|
32284
|
+
code;
|
|
32285
|
+
source;
|
|
32286
|
+
constructor(code, source, message) {
|
|
32287
|
+
super(message);
|
|
32288
|
+
this.code = code;
|
|
32289
|
+
this.source = source;
|
|
32290
|
+
}
|
|
32291
|
+
};
|
|
32735
32292
|
function isTestTag(tag) {
|
|
32736
32293
|
return /-test/i.test(tag);
|
|
32737
32294
|
}
|
|
@@ -32765,59 +32322,219 @@ function pickLatestStable(releases) {
|
|
|
32765
32322
|
}
|
|
32766
32323
|
return bestRelease ?? firstStable;
|
|
32767
32324
|
}
|
|
32768
|
-
function
|
|
32769
|
-
return new
|
|
32770
|
-
|
|
32771
|
-
|
|
32772
|
-
|
|
32773
|
-
|
|
32774
|
-
|
|
32775
|
-
|
|
32776
|
-
|
|
32777
|
-
|
|
32778
|
-
}
|
|
32779
|
-
});
|
|
32780
|
-
});
|
|
32781
|
-
req.on("error", reject);
|
|
32782
|
-
req.setTimeout(1e4, () => {
|
|
32783
|
-
req.destroy();
|
|
32784
|
-
reject(new Error("Timeout"));
|
|
32785
|
-
});
|
|
32786
|
-
});
|
|
32325
|
+
function nowIso(ts = Date.now()) {
|
|
32326
|
+
return new Date(ts).toISOString();
|
|
32327
|
+
}
|
|
32328
|
+
function normalizeVersion(value) {
|
|
32329
|
+
return value.trim().replace(/^v/, "");
|
|
32330
|
+
}
|
|
32331
|
+
function getBackoffMs(failureCount) {
|
|
32332
|
+
if (failureCount <= 1) return 0;
|
|
32333
|
+
const exponent = Math.min(8, failureCount - 2);
|
|
32334
|
+
return Math.min(BACKOFF_MAX_MS, BACKOFF_BASE_MS * 2 ** exponent);
|
|
32787
32335
|
}
|
|
32788
|
-
|
|
32336
|
+
function getGithubToken() {
|
|
32337
|
+
const token = (process.env.QUOROOM_UPDATE_GITHUB_TOKEN || "").trim();
|
|
32338
|
+
return token || null;
|
|
32339
|
+
}
|
|
32340
|
+
function getCloudSourceConfig() {
|
|
32341
|
+
const url = (process.env.QUOROOM_UPDATE_SOURCE_URL || "").trim();
|
|
32342
|
+
if (!url) return null;
|
|
32343
|
+
const token = (process.env.QUOROOM_UPDATE_SOURCE_TOKEN || "").trim() || null;
|
|
32344
|
+
return { url, token };
|
|
32345
|
+
}
|
|
32346
|
+
async function fetchJson(url, source, headers = {}, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
32347
|
+
const timeout = AbortSignal.timeout(timeoutMs);
|
|
32348
|
+
let response;
|
|
32789
32349
|
try {
|
|
32790
|
-
|
|
32791
|
-
|
|
32350
|
+
response = await fetch(url, {
|
|
32351
|
+
headers: {
|
|
32352
|
+
"User-Agent": "quoroom-update-checker",
|
|
32353
|
+
Accept: "application/json",
|
|
32354
|
+
...headers
|
|
32355
|
+
},
|
|
32356
|
+
signal: timeout
|
|
32357
|
+
});
|
|
32358
|
+
} catch (error) {
|
|
32359
|
+
if (error instanceof Error && (error.name === "TimeoutError" || error.name === "AbortError")) {
|
|
32360
|
+
throw new UpdateCheckError("timeout", source, `Request timed out after ${timeoutMs}ms`);
|
|
32361
|
+
}
|
|
32362
|
+
throw new UpdateCheckError(
|
|
32363
|
+
"network",
|
|
32364
|
+
source,
|
|
32365
|
+
error instanceof Error ? error.message : "Network error while checking updates"
|
|
32792
32366
|
);
|
|
32793
|
-
|
|
32794
|
-
|
|
32795
|
-
|
|
32796
|
-
const
|
|
32797
|
-
const
|
|
32798
|
-
|
|
32799
|
-
|
|
32800
|
-
|
|
32801
|
-
if (name.endsWith(".pkg")) assets.mac = url;
|
|
32802
|
-
else if (name.toLowerCase().includes("setup") && name.endsWith(".exe")) assets.windows = url;
|
|
32803
|
-
else if (name.endsWith(".deb")) assets.linux = url;
|
|
32804
|
-
else if (name.startsWith("quoroom-update-") && name.endsWith(".tar.gz")) updateBundle = url;
|
|
32805
|
-
}
|
|
32806
|
-
cached = { latestVersion, releaseUrl: latest.html_url, assets, updateBundle };
|
|
32807
|
-
if (updateBundle && latestVersion) {
|
|
32808
|
-
void checkAndApplyUpdate(updateBundle, latestVersion).catch(() => {
|
|
32809
|
-
});
|
|
32367
|
+
}
|
|
32368
|
+
if (!response.ok) {
|
|
32369
|
+
const rateLimitRemaining = response.headers.get("x-ratelimit-remaining");
|
|
32370
|
+
const retryAfter = response.headers.get("retry-after");
|
|
32371
|
+
const isRateLimited = response.status === 429 || response.status === 403 && (rateLimitRemaining === "0" || Boolean(retryAfter));
|
|
32372
|
+
if (isRateLimited) {
|
|
32373
|
+
const message = retryAfter ? `Rate limited (HTTP ${response.status}, retry-after=${retryAfter}s)` : `Rate limited (HTTP ${response.status})`;
|
|
32374
|
+
throw new UpdateCheckError("rate_limited", source, message);
|
|
32810
32375
|
}
|
|
32376
|
+
throw new UpdateCheckError("http_status", source, `HTTP ${response.status}`);
|
|
32377
|
+
}
|
|
32378
|
+
const body = await response.text();
|
|
32379
|
+
try {
|
|
32380
|
+
return JSON.parse(body);
|
|
32811
32381
|
} catch {
|
|
32382
|
+
throw new UpdateCheckError("invalid_json", source, "Response body is not valid JSON");
|
|
32812
32383
|
}
|
|
32813
32384
|
}
|
|
32814
|
-
function
|
|
32385
|
+
function formatFailure(error) {
|
|
32386
|
+
if (error instanceof UpdateCheckError) {
|
|
32387
|
+
return { code: error.code, source: error.source, message: error.message };
|
|
32388
|
+
}
|
|
32389
|
+
if (error instanceof Error) {
|
|
32390
|
+
return { code: "unexpected", source: "github", message: error.message };
|
|
32391
|
+
}
|
|
32392
|
+
return { code: "unexpected", source: "github", message: String(error) };
|
|
32393
|
+
}
|
|
32394
|
+
function parseGithubUpdateInfo(raw) {
|
|
32395
|
+
if (!Array.isArray(raw)) {
|
|
32396
|
+
throw new UpdateCheckError("invalid_payload", "github", "GitHub response is not an array");
|
|
32397
|
+
}
|
|
32398
|
+
const latest = pickLatestStable(raw);
|
|
32399
|
+
if (!latest?.assets) {
|
|
32400
|
+
throw new UpdateCheckError("invalid_payload", "github", "No stable release with assets found");
|
|
32401
|
+
}
|
|
32402
|
+
const latestVersion = normalizeVersion(latest.tag_name);
|
|
32403
|
+
const assets = { mac: null, windows: null, linux: null };
|
|
32404
|
+
let updateBundle = null;
|
|
32405
|
+
for (const a of latest.assets) {
|
|
32406
|
+
const { name, browser_download_url: url } = a;
|
|
32407
|
+
if (name.endsWith(".pkg")) assets.mac = url;
|
|
32408
|
+
else if (name.toLowerCase().includes("setup") && name.endsWith(".exe")) assets.windows = url;
|
|
32409
|
+
else if (name.endsWith(".deb")) assets.linux = url;
|
|
32410
|
+
else if (name.startsWith("quoroom-update-") && name.endsWith(".tar.gz")) updateBundle = url;
|
|
32411
|
+
}
|
|
32412
|
+
if (!updateBundle) {
|
|
32413
|
+
console.error(`[update-checker] Missing update bundle asset for v${latestVersion}`);
|
|
32414
|
+
}
|
|
32415
|
+
return {
|
|
32416
|
+
latestVersion,
|
|
32417
|
+
releaseUrl: latest.html_url || DEFAULT_RELEASE_URL,
|
|
32418
|
+
assets,
|
|
32419
|
+
updateBundle
|
|
32420
|
+
};
|
|
32421
|
+
}
|
|
32422
|
+
function parseCloudUpdateInfo(raw) {
|
|
32423
|
+
const payload = raw ?? {};
|
|
32424
|
+
const version5 = typeof payload.version === "string" ? normalizeVersion(payload.version) : "";
|
|
32425
|
+
const updateBundleUrl = typeof payload.updateBundleUrl === "string" ? payload.updateBundleUrl.trim() : "";
|
|
32426
|
+
const releaseUrl = typeof payload.releaseUrl === "string" ? payload.releaseUrl.trim() : DEFAULT_RELEASE_URL;
|
|
32427
|
+
if (!version5) {
|
|
32428
|
+
throw new UpdateCheckError("invalid_payload", "cloud", "Cloud source returned missing version");
|
|
32429
|
+
}
|
|
32430
|
+
if (!updateBundleUrl) {
|
|
32431
|
+
throw new UpdateCheckError("missing_bundle", "cloud", `Cloud source missing update bundle for v${version5}`);
|
|
32432
|
+
}
|
|
32433
|
+
return {
|
|
32434
|
+
latestVersion: version5,
|
|
32435
|
+
releaseUrl,
|
|
32436
|
+
assets: { mac: null, windows: null, linux: null },
|
|
32437
|
+
updateBundle: updateBundleUrl
|
|
32438
|
+
};
|
|
32439
|
+
}
|
|
32440
|
+
async function fetchFromGithub() {
|
|
32441
|
+
const headers = {};
|
|
32442
|
+
const githubToken = getGithubToken();
|
|
32443
|
+
if (githubToken) headers.Authorization = `Bearer ${githubToken}`;
|
|
32444
|
+
const raw = await fetchJson(GITHUB_RELEASES_URL, "github", headers);
|
|
32445
|
+
return parseGithubUpdateInfo(raw);
|
|
32446
|
+
}
|
|
32447
|
+
async function fetchFromCloudSource(url, token) {
|
|
32448
|
+
const headers = {};
|
|
32449
|
+
if (token) {
|
|
32450
|
+
headers.Authorization = `Bearer ${token}`;
|
|
32451
|
+
headers["X-Update-Token"] = token;
|
|
32452
|
+
}
|
|
32453
|
+
const raw = await fetchJson(url, "cloud", headers);
|
|
32454
|
+
return parseCloudUpdateInfo(raw);
|
|
32455
|
+
}
|
|
32456
|
+
async function resolveLatestUpdateInfo() {
|
|
32457
|
+
const cloudSource = getCloudSourceConfig();
|
|
32458
|
+
let cloudError = null;
|
|
32459
|
+
if (cloudSource) {
|
|
32460
|
+
try {
|
|
32461
|
+
const info = await fetchFromCloudSource(cloudSource.url, cloudSource.token);
|
|
32462
|
+
return { info, source: "cloud" };
|
|
32463
|
+
} catch (error) {
|
|
32464
|
+
const failed = formatFailure(error);
|
|
32465
|
+
cloudError = { code: failed.code, message: failed.message };
|
|
32466
|
+
console.error(`[update-checker] Cloud update source failed (${failed.code}): ${failed.message}`);
|
|
32467
|
+
}
|
|
32468
|
+
}
|
|
32469
|
+
try {
|
|
32470
|
+
const info = await fetchFromGithub();
|
|
32471
|
+
return { info, source: "github" };
|
|
32472
|
+
} catch (error) {
|
|
32473
|
+
const failed = formatFailure(error);
|
|
32474
|
+
if (cloudError) {
|
|
32475
|
+
throw new UpdateCheckError(
|
|
32476
|
+
failed.code,
|
|
32477
|
+
failed.source,
|
|
32478
|
+
`Cloud source failed (${cloudError.code}): ${cloudError.message}; GitHub fallback failed (${failed.code}): ${failed.message}`
|
|
32479
|
+
);
|
|
32480
|
+
}
|
|
32481
|
+
throw error;
|
|
32482
|
+
}
|
|
32483
|
+
}
|
|
32484
|
+
async function forceCheck(options = {}) {
|
|
32485
|
+
diagnostics.lastCheckAt = nowIso();
|
|
32486
|
+
if (!options.ignoreBackoff && backoffUntil > Date.now()) {
|
|
32487
|
+
diagnostics.nextCheckAt = nowIso(backoffUntil);
|
|
32488
|
+
return;
|
|
32489
|
+
}
|
|
32490
|
+
try {
|
|
32491
|
+
const { info, source } = await resolveLatestUpdateInfo();
|
|
32492
|
+
cached = info;
|
|
32493
|
+
diagnostics.updateSource = source;
|
|
32494
|
+
diagnostics.lastSuccessAt = nowIso();
|
|
32495
|
+
diagnostics.lastErrorAt = null;
|
|
32496
|
+
diagnostics.lastErrorCode = null;
|
|
32497
|
+
diagnostics.lastErrorMessage = null;
|
|
32498
|
+
diagnostics.nextCheckAt = null;
|
|
32499
|
+
consecutiveFailures = 0;
|
|
32500
|
+
diagnostics.consecutiveFailures = 0;
|
|
32501
|
+
if (info.updateBundle && info.latestVersion) {
|
|
32502
|
+
const beforeReadyVersion = getReadyUpdateVersion();
|
|
32503
|
+
await checkAndApplyUpdate(info.updateBundle, info.latestVersion).catch((error) => {
|
|
32504
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
32505
|
+
console.error(`[update-checker] Auto-apply failed for v${info.latestVersion}: ${message}`);
|
|
32506
|
+
});
|
|
32507
|
+
const afterReadyVersion = getReadyUpdateVersion();
|
|
32508
|
+
if (options.onReadyUpdate && afterReadyVersion && afterReadyVersion !== beforeReadyVersion) {
|
|
32509
|
+
try {
|
|
32510
|
+
options.onReadyUpdate(afterReadyVersion);
|
|
32511
|
+
} catch (error) {
|
|
32512
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
32513
|
+
console.error(`[update-checker] onReadyUpdate callback failed: ${message}`);
|
|
32514
|
+
}
|
|
32515
|
+
}
|
|
32516
|
+
}
|
|
32517
|
+
} catch (error) {
|
|
32518
|
+
const failed = formatFailure(error);
|
|
32519
|
+
consecutiveFailures += 1;
|
|
32520
|
+
diagnostics.consecutiveFailures = consecutiveFailures;
|
|
32521
|
+
diagnostics.lastErrorAt = nowIso();
|
|
32522
|
+
diagnostics.lastErrorCode = failed.code;
|
|
32523
|
+
diagnostics.lastErrorMessage = failed.message;
|
|
32524
|
+
const backoffMs = getBackoffMs(consecutiveFailures);
|
|
32525
|
+
backoffUntil = backoffMs > 0 ? Date.now() + backoffMs : 0;
|
|
32526
|
+
diagnostics.nextCheckAt = backoffUntil > 0 ? nowIso(backoffUntil) : null;
|
|
32527
|
+
console.error(`[update-checker] Update check failed (${failed.code}, source=${failed.source}): ${failed.message}`);
|
|
32528
|
+
}
|
|
32529
|
+
}
|
|
32530
|
+
function initUpdateChecker(options = {}) {
|
|
32815
32531
|
if (process.env.NODE_ENV === "test") return;
|
|
32532
|
+
const pollEvery = Number.isFinite(options.pollIntervalMs) && (options.pollIntervalMs ?? 0) > 0 ? Number(options.pollIntervalMs) : DEFAULT_CHECK_INTERVAL;
|
|
32816
32533
|
initTimer = setTimeout(() => {
|
|
32817
|
-
void forceCheck();
|
|
32534
|
+
void forceCheck({ onReadyUpdate: options.onReadyUpdate });
|
|
32818
32535
|
pollInterval = setInterval(() => {
|
|
32819
|
-
void forceCheck();
|
|
32820
|
-
},
|
|
32536
|
+
void forceCheck({ onReadyUpdate: options.onReadyUpdate });
|
|
32537
|
+
}, pollEvery);
|
|
32821
32538
|
}, INITIAL_DELAY);
|
|
32822
32539
|
}
|
|
32823
32540
|
function stopUpdateChecker() {
|
|
@@ -32833,8 +32550,11 @@ function stopUpdateChecker() {
|
|
|
32833
32550
|
function getUpdateInfo() {
|
|
32834
32551
|
return cached;
|
|
32835
32552
|
}
|
|
32553
|
+
function getUpdateDiagnostics() {
|
|
32554
|
+
return { ...diagnostics };
|
|
32555
|
+
}
|
|
32836
32556
|
async function simulateUpdate() {
|
|
32837
|
-
if (!cached) await forceCheck();
|
|
32557
|
+
if (!cached) await forceCheck({ ignoreBackoff: true });
|
|
32838
32558
|
cached = {
|
|
32839
32559
|
latestVersion: "99.0.0",
|
|
32840
32560
|
releaseUrl: "https://github.com/quoroom-ai/room/releases",
|
|
@@ -32853,7 +32573,7 @@ var cachedVersion = null;
|
|
|
32853
32573
|
function getVersion3() {
|
|
32854
32574
|
if (cachedVersion) return cachedVersion;
|
|
32855
32575
|
try {
|
|
32856
|
-
cachedVersion = true ? "0.1.
|
|
32576
|
+
cachedVersion = true ? "0.1.41" : null.version;
|
|
32857
32577
|
} catch {
|
|
32858
32578
|
cachedVersion = "unknown";
|
|
32859
32579
|
}
|
|
@@ -32948,7 +32668,7 @@ function registerStatusRoutes(router) {
|
|
|
32948
32668
|
return { data: { status: getAutoUpdateStatus(), readyVersion: getReadyUpdateVersion() } };
|
|
32949
32669
|
});
|
|
32950
32670
|
router.post("/api/status/check-update", async () => {
|
|
32951
|
-
await forceCheck();
|
|
32671
|
+
await forceCheck({ ignoreBackoff: true });
|
|
32952
32672
|
return { data: { updateInfo: getUpdateInfo() } };
|
|
32953
32673
|
});
|
|
32954
32674
|
router.get("/api/status", (ctx) => {
|
|
@@ -32983,6 +32703,7 @@ function registerStatusRoutes(router) {
|
|
|
32983
32703
|
data.updateInfo = getUpdateInfo();
|
|
32984
32704
|
data.autoUpdate = getAutoUpdateStatus();
|
|
32985
32705
|
data.readyUpdateVersion = getReadyUpdateVersion();
|
|
32706
|
+
data.updateDiagnostics = getUpdateDiagnostics();
|
|
32986
32707
|
}
|
|
32987
32708
|
if (Object.keys(pending).length > 0) {
|
|
32988
32709
|
data.pending = pending;
|
|
@@ -33331,189 +33052,6 @@ function registerCredentialRoutes(router) {
|
|
|
33331
33052
|
});
|
|
33332
33053
|
}
|
|
33333
33054
|
|
|
33334
|
-
// src/server/routes/stations.ts
|
|
33335
|
-
init_cloud_sync();
|
|
33336
|
-
init_telemetry();
|
|
33337
|
-
function registerStationRoutes(router) {
|
|
33338
|
-
router.get("/api/rooms/:roomId/stations", (ctx) => {
|
|
33339
|
-
const roomId = Number(ctx.params.roomId);
|
|
33340
|
-
return { data: listStations(ctx.db, roomId) };
|
|
33341
|
-
});
|
|
33342
|
-
router.get("/api/stations/:id", (ctx) => {
|
|
33343
|
-
const id = Number(ctx.params.id);
|
|
33344
|
-
const station = getStation(ctx.db, id);
|
|
33345
|
-
if (!station) return { status: 404, error: "Station not found" };
|
|
33346
|
-
return { data: station };
|
|
33347
|
-
});
|
|
33348
|
-
router.get("/api/rooms/:roomId/cloud-stations", async (ctx) => {
|
|
33349
|
-
const roomId = Number(ctx.params.roomId);
|
|
33350
|
-
const room = getRoom(ctx.db, roomId);
|
|
33351
|
-
if (!room) return { status: 404, error: "Room not found" };
|
|
33352
|
-
const cloudRoomId = getRoomCloudId(roomId);
|
|
33353
|
-
await ensureCloudRoomToken({
|
|
33354
|
-
roomId: cloudRoomId,
|
|
33355
|
-
name: room.name,
|
|
33356
|
-
goal: room.goal ?? null,
|
|
33357
|
-
visibility: room.visibility
|
|
33358
|
-
});
|
|
33359
|
-
const stations = await listCloudStations(cloudRoomId);
|
|
33360
|
-
return { data: stations };
|
|
33361
|
-
});
|
|
33362
|
-
router.get("/api/rooms/:roomId/cloud-station-payments", async (ctx) => {
|
|
33363
|
-
const roomId = Number(ctx.params.roomId);
|
|
33364
|
-
const room = getRoom(ctx.db, roomId);
|
|
33365
|
-
if (!room) return { status: 404, error: "Room not found" };
|
|
33366
|
-
const cloudRoomId = getRoomCloudId(roomId);
|
|
33367
|
-
await ensureCloudRoomToken({
|
|
33368
|
-
roomId: cloudRoomId,
|
|
33369
|
-
name: room.name,
|
|
33370
|
-
goal: room.goal ?? null,
|
|
33371
|
-
visibility: room.visibility
|
|
33372
|
-
});
|
|
33373
|
-
const payments = await listCloudStationPayments(cloudRoomId);
|
|
33374
|
-
return { data: payments };
|
|
33375
|
-
});
|
|
33376
|
-
router.post("/api/rooms/:roomId/cloud-stations/:id/start", async (ctx) => {
|
|
33377
|
-
const roomId = Number(ctx.params.roomId);
|
|
33378
|
-
const stationId = Number(ctx.params.id);
|
|
33379
|
-
const room = getRoom(ctx.db, roomId);
|
|
33380
|
-
if (!room) return { status: 404, error: "Room not found" };
|
|
33381
|
-
const cloudRoomId = getRoomCloudId(roomId);
|
|
33382
|
-
await ensureCloudRoomToken({
|
|
33383
|
-
roomId: cloudRoomId,
|
|
33384
|
-
name: room.name,
|
|
33385
|
-
goal: room.goal ?? null,
|
|
33386
|
-
visibility: room.visibility
|
|
33387
|
-
});
|
|
33388
|
-
await startCloudStation(cloudRoomId, stationId);
|
|
33389
|
-
eventBus.emit(`room:${roomId}`, "station:started", { roomId, stationId });
|
|
33390
|
-
return { data: { ok: true } };
|
|
33391
|
-
});
|
|
33392
|
-
router.post("/api/rooms/:roomId/cloud-stations/:id/stop", async (ctx) => {
|
|
33393
|
-
const roomId = Number(ctx.params.roomId);
|
|
33394
|
-
const stationId = Number(ctx.params.id);
|
|
33395
|
-
const room = getRoom(ctx.db, roomId);
|
|
33396
|
-
if (!room) return { status: 404, error: "Room not found" };
|
|
33397
|
-
const cloudRoomId = getRoomCloudId(roomId);
|
|
33398
|
-
await ensureCloudRoomToken({
|
|
33399
|
-
roomId: cloudRoomId,
|
|
33400
|
-
name: room.name,
|
|
33401
|
-
goal: room.goal ?? null,
|
|
33402
|
-
visibility: room.visibility
|
|
33403
|
-
});
|
|
33404
|
-
await stopCloudStation(cloudRoomId, stationId);
|
|
33405
|
-
eventBus.emit(`room:${roomId}`, "station:stopped", { roomId, stationId });
|
|
33406
|
-
return { data: { ok: true } };
|
|
33407
|
-
});
|
|
33408
|
-
router.post("/api/rooms/:roomId/cloud-stations/:id/cancel", async (ctx) => {
|
|
33409
|
-
const roomId = Number(ctx.params.roomId);
|
|
33410
|
-
const stationId = Number(ctx.params.id);
|
|
33411
|
-
const room = getRoom(ctx.db, roomId);
|
|
33412
|
-
if (!room) return { status: 404, error: "Room not found" };
|
|
33413
|
-
const cloudRoomId = getRoomCloudId(roomId);
|
|
33414
|
-
await ensureCloudRoomToken({
|
|
33415
|
-
roomId: cloudRoomId,
|
|
33416
|
-
name: room.name,
|
|
33417
|
-
goal: room.goal ?? null,
|
|
33418
|
-
visibility: room.visibility
|
|
33419
|
-
});
|
|
33420
|
-
await cancelCloudStation(cloudRoomId, stationId);
|
|
33421
|
-
eventBus.emit(`room:${roomId}`, "station:canceled", { roomId, stationId });
|
|
33422
|
-
return { data: { ok: true } };
|
|
33423
|
-
});
|
|
33424
|
-
router.delete("/api/rooms/:roomId/cloud-stations/:id", async (ctx) => {
|
|
33425
|
-
const roomId = Number(ctx.params.roomId);
|
|
33426
|
-
const stationId = Number(ctx.params.id);
|
|
33427
|
-
const room = getRoom(ctx.db, roomId);
|
|
33428
|
-
if (!room) return { status: 404, error: "Room not found" };
|
|
33429
|
-
const cloudRoomId = getRoomCloudId(roomId);
|
|
33430
|
-
await ensureCloudRoomToken({
|
|
33431
|
-
roomId: cloudRoomId,
|
|
33432
|
-
name: room.name,
|
|
33433
|
-
goal: room.goal ?? null,
|
|
33434
|
-
visibility: room.visibility
|
|
33435
|
-
});
|
|
33436
|
-
await deleteCloudStation(cloudRoomId, stationId);
|
|
33437
|
-
eventBus.emit(`room:${roomId}`, "station:deleted", { roomId, stationId });
|
|
33438
|
-
return { data: { ok: true } };
|
|
33439
|
-
});
|
|
33440
|
-
router.get("/api/rooms/:roomId/cloud-stations/crypto-prices", async (ctx) => {
|
|
33441
|
-
const roomId = Number(ctx.params.roomId);
|
|
33442
|
-
const room = getRoom(ctx.db, roomId);
|
|
33443
|
-
if (!room) return { status: 404, error: "Room not found" };
|
|
33444
|
-
const cloudRoomId = getRoomCloudId(roomId);
|
|
33445
|
-
await ensureCloudRoomToken({
|
|
33446
|
-
roomId: cloudRoomId,
|
|
33447
|
-
name: room.name,
|
|
33448
|
-
goal: room.goal ?? null,
|
|
33449
|
-
visibility: room.visibility
|
|
33450
|
-
});
|
|
33451
|
-
const pricing = await getCloudCryptoPrices(cloudRoomId);
|
|
33452
|
-
if (!pricing) return { status: 503, error: "Crypto pricing unavailable" };
|
|
33453
|
-
return { data: pricing };
|
|
33454
|
-
});
|
|
33455
|
-
router.post("/api/rooms/:roomId/cloud-stations/crypto-checkout", async (ctx) => {
|
|
33456
|
-
const roomId = Number(ctx.params.roomId);
|
|
33457
|
-
const room = getRoom(ctx.db, roomId);
|
|
33458
|
-
if (!room) return { status: 404, error: "Room not found" };
|
|
33459
|
-
const { tier, name, chain, token } = ctx.body;
|
|
33460
|
-
if (!tier || !name) {
|
|
33461
|
-
return { status: 400, error: "Missing required fields: tier, name" };
|
|
33462
|
-
}
|
|
33463
|
-
const encryptionKey = getMachineId();
|
|
33464
|
-
const selectedChain = chain ?? "base";
|
|
33465
|
-
const selectedToken = token ?? "usdc";
|
|
33466
|
-
const chainConfig2 = CHAIN_CONFIGS[selectedChain];
|
|
33467
|
-
if (!chainConfig2) return { status: 400, error: `Unsupported chain: ${selectedChain}` };
|
|
33468
|
-
const tokenConfig = chainConfig2.tokens[selectedToken];
|
|
33469
|
-
if (!tokenConfig) return { status: 400, error: `Token ${selectedToken} not available on ${selectedChain}` };
|
|
33470
|
-
const cloudRoomId = getRoomCloudId(roomId);
|
|
33471
|
-
await ensureCloudRoomToken({
|
|
33472
|
-
roomId: cloudRoomId,
|
|
33473
|
-
name: room.name,
|
|
33474
|
-
goal: room.goal ?? null,
|
|
33475
|
-
visibility: room.visibility
|
|
33476
|
-
});
|
|
33477
|
-
const pricing = await getCloudCryptoPrices(cloudRoomId);
|
|
33478
|
-
if (!pricing) return { status: 503, error: "Crypto payments unavailable" };
|
|
33479
|
-
const tierInfo = pricing.tiers.find((t) => t.tier === tier);
|
|
33480
|
-
if (!tierInfo) return { status: 400, error: `Unknown tier: ${tier}` };
|
|
33481
|
-
let txHash;
|
|
33482
|
-
try {
|
|
33483
|
-
txHash = await sendToken(
|
|
33484
|
-
ctx.db,
|
|
33485
|
-
roomId,
|
|
33486
|
-
pricing.treasuryAddress,
|
|
33487
|
-
tierInfo.cryptoPrice.toString(),
|
|
33488
|
-
encryptionKey,
|
|
33489
|
-
selectedChain,
|
|
33490
|
-
tokenConfig.address,
|
|
33491
|
-
tokenConfig.decimals
|
|
33492
|
-
);
|
|
33493
|
-
} catch (e) {
|
|
33494
|
-
return { status: 400, error: `Transfer failed: ${e.message}` };
|
|
33495
|
-
}
|
|
33496
|
-
const result = await cryptoCheckoutStation(cloudRoomId, tier, name, txHash, selectedChain);
|
|
33497
|
-
if (!result.ok) {
|
|
33498
|
-
return {
|
|
33499
|
-
status: 502,
|
|
33500
|
-
error: result.error ?? "Provisioning failed",
|
|
33501
|
-
data: { txHash }
|
|
33502
|
-
};
|
|
33503
|
-
}
|
|
33504
|
-
eventBus.emit(`room:${roomId}`, "station:created", { roomId, tier, name });
|
|
33505
|
-
eventBus.emit(`room:${roomId}`, "wallet:sent", { roomId, amount: tierInfo.cryptoPrice, to: pricing.treasuryAddress });
|
|
33506
|
-
return {
|
|
33507
|
-
data: {
|
|
33508
|
-
ok: true,
|
|
33509
|
-
txHash,
|
|
33510
|
-
subscriptionId: result.subscriptionId,
|
|
33511
|
-
currentPeriodEnd: result.currentPeriodEnd
|
|
33512
|
-
}
|
|
33513
|
-
};
|
|
33514
|
-
});
|
|
33515
|
-
}
|
|
33516
|
-
|
|
33517
33055
|
// src/server/routes/room-messages.ts
|
|
33518
33056
|
function registerRoomMessageRoutes(router) {
|
|
33519
33057
|
router.get("/api/rooms/:roomId/messages", (ctx) => {
|
|
@@ -33599,7 +33137,7 @@ var activeByProvider = /* @__PURE__ */ new Map();
|
|
|
33599
33137
|
var MAX_LINES = Math.max(50, parseInt(process.env.QUOROOM_PROVIDER_AUTH_MAX_LINES || "300", 10) || 300);
|
|
33600
33138
|
var SESSION_TIMEOUT_MS = Math.max(3e4, parseInt(process.env.QUOROOM_PROVIDER_AUTH_TIMEOUT_MS || "900000", 10) || 9e5);
|
|
33601
33139
|
var SESSION_TTL_MS = Math.max(6e4, parseInt(process.env.QUOROOM_PROVIDER_AUTH_TTL_MS || "7200000", 10) || 72e5);
|
|
33602
|
-
function
|
|
33140
|
+
function nowIso2() {
|
|
33603
33141
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
33604
33142
|
}
|
|
33605
33143
|
function getProviderCommand(provider) {
|
|
@@ -33672,7 +33210,7 @@ function appendLine(session, stream, rawText) {
|
|
|
33672
33210
|
id: ++session.lineSeq,
|
|
33673
33211
|
stream,
|
|
33674
33212
|
text,
|
|
33675
|
-
timestamp:
|
|
33213
|
+
timestamp: nowIso2()
|
|
33676
33214
|
};
|
|
33677
33215
|
session.lines.push(line);
|
|
33678
33216
|
if (session.lines.length > MAX_LINES) {
|
|
@@ -33720,7 +33258,7 @@ function finalizeSession(session, status2, exitCode) {
|
|
|
33720
33258
|
flushBufferedLines(session);
|
|
33721
33259
|
session.status = status2;
|
|
33722
33260
|
session.exitCode = exitCode;
|
|
33723
|
-
session.endedAt =
|
|
33261
|
+
session.endedAt = nowIso2();
|
|
33724
33262
|
session.updatedAt = session.endedAt;
|
|
33725
33263
|
if (activeByProvider.get(session.provider) === session.sessionId) {
|
|
33726
33264
|
activeByProvider.delete(session.provider);
|
|
@@ -33812,7 +33350,7 @@ function startProviderAuthSession(provider) {
|
|
|
33812
33350
|
shell: process.platform === "win32"
|
|
33813
33351
|
});
|
|
33814
33352
|
registerManagedChildProcess(child);
|
|
33815
|
-
const startedAt2 =
|
|
33353
|
+
const startedAt2 = nowIso2();
|
|
33816
33354
|
const session = {
|
|
33817
33355
|
sessionId: (0, import_node_crypto9.randomUUID)(),
|
|
33818
33356
|
provider,
|
|
@@ -33888,7 +33426,7 @@ var activeByProvider2 = /* @__PURE__ */ new Map();
|
|
|
33888
33426
|
var MAX_LINES2 = Math.max(50, parseInt(process.env.QUOROOM_PROVIDER_INSTALL_MAX_LINES || "300", 10) || 300);
|
|
33889
33427
|
var SESSION_TIMEOUT_MS2 = Math.max(3e4, parseInt(process.env.QUOROOM_PROVIDER_INSTALL_TIMEOUT_MS || "900000", 10) || 9e5);
|
|
33890
33428
|
var SESSION_TTL_MS2 = Math.max(6e4, parseInt(process.env.QUOROOM_PROVIDER_INSTALL_TTL_MS || "7200000", 10) || 72e5);
|
|
33891
|
-
function
|
|
33429
|
+
function nowIso3() {
|
|
33892
33430
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
33893
33431
|
}
|
|
33894
33432
|
function getNpmCommand(platform = process.platform) {
|
|
@@ -33958,7 +33496,7 @@ function appendLine2(session, stream, rawText) {
|
|
|
33958
33496
|
id: ++session.lineSeq,
|
|
33959
33497
|
stream,
|
|
33960
33498
|
text,
|
|
33961
|
-
timestamp:
|
|
33499
|
+
timestamp: nowIso3()
|
|
33962
33500
|
};
|
|
33963
33501
|
session.lines.push(line);
|
|
33964
33502
|
if (session.lines.length > MAX_LINES2) {
|
|
@@ -33988,7 +33526,7 @@ function finalizeSession2(session, status2, exitCode) {
|
|
|
33988
33526
|
flushBufferedLines2(session);
|
|
33989
33527
|
session.status = status2;
|
|
33990
33528
|
session.exitCode = exitCode;
|
|
33991
|
-
session.endedAt =
|
|
33529
|
+
session.endedAt = nowIso3();
|
|
33992
33530
|
session.updatedAt = session.endedAt;
|
|
33993
33531
|
if (activeByProvider2.get(session.provider) === session.sessionId) {
|
|
33994
33532
|
activeByProvider2.delete(session.provider);
|
|
@@ -34076,7 +33614,7 @@ function startProviderInstallSession(provider) {
|
|
|
34076
33614
|
shell: process.platform === "win32"
|
|
34077
33615
|
});
|
|
34078
33616
|
registerManagedChildProcess(child);
|
|
34079
|
-
const startedAt2 =
|
|
33617
|
+
const startedAt2 = nowIso3();
|
|
34080
33618
|
const session = {
|
|
34081
33619
|
sessionId: (0, import_node_crypto10.randomUUID)(),
|
|
34082
33620
|
provider,
|
|
@@ -34331,7 +33869,6 @@ function registerAllRoutes(router) {
|
|
|
34331
33869
|
registerStatusRoutes(router);
|
|
34332
33870
|
registerWalletRoutes(router);
|
|
34333
33871
|
registerCredentialRoutes(router);
|
|
34334
|
-
registerStationRoutes(router);
|
|
34335
33872
|
registerRoomMessageRoutes(router);
|
|
34336
33873
|
registerProviderRoutes(router);
|
|
34337
33874
|
registerContactRoutes(router);
|
|
@@ -34610,7 +34147,7 @@ function streamWithRedirects(url, res, corsHeaders, filename, depth = 0) {
|
|
|
34610
34147
|
}
|
|
34611
34148
|
try {
|
|
34612
34149
|
const parsed = new import_node_url.URL(url);
|
|
34613
|
-
const mod2 = parsed.protocol === "https:" ?
|
|
34150
|
+
const mod2 = parsed.protocol === "https:" ? import_node_https2.default : import_node_http2.default;
|
|
34614
34151
|
mod2.get(url, { headers: { "User-Agent": "quoroom-updater/1.0" } }, (assetRes) => {
|
|
34615
34152
|
if ((assetRes.statusCode === 301 || assetRes.statusCode === 302 || assetRes.statusCode === 307) && assetRes.headers.location) {
|
|
34616
34153
|
assetRes.resume();
|
|
@@ -34758,6 +34295,17 @@ function scheduleSelfRestart() {
|
|
|
34758
34295
|
return false;
|
|
34759
34296
|
}
|
|
34760
34297
|
}
|
|
34298
|
+
function createCloudReadyUpdateHandler(triggerShutdown) {
|
|
34299
|
+
let queued = false;
|
|
34300
|
+
return (version5) => {
|
|
34301
|
+
if (queued) return;
|
|
34302
|
+
queued = true;
|
|
34303
|
+
console.error(`[auto-update] Cloud update v${version5} is ready. Restarting to apply.`);
|
|
34304
|
+
setTimeout(() => {
|
|
34305
|
+
triggerShutdown();
|
|
34306
|
+
}, 120);
|
|
34307
|
+
};
|
|
34308
|
+
}
|
|
34761
34309
|
var MIME_TYPES = {
|
|
34762
34310
|
".html": "text/html; charset=utf-8",
|
|
34763
34311
|
".js": "application/javascript; charset=utf-8",
|
|
@@ -35055,6 +34603,13 @@ function createApiServer(options = {}) {
|
|
|
35055
34603
|
}
|
|
35056
34604
|
const role = principal.role;
|
|
35057
34605
|
if (pathname === "/api/status/update/download" && req.method === "GET") {
|
|
34606
|
+
if (isCloudDeployment()) {
|
|
34607
|
+
res.writeHead(409, responseHeaders);
|
|
34608
|
+
res.end(JSON.stringify({
|
|
34609
|
+
error: "Installer download is disabled in cloud deployment. Updates are applied automatically."
|
|
34610
|
+
}));
|
|
34611
|
+
return;
|
|
34612
|
+
}
|
|
35058
34613
|
if (!isAllowedForRole(role, req.method, pathname, db2)) {
|
|
35059
34614
|
res.writeHead(403, responseHeaders);
|
|
35060
34615
|
res.end(JSON.stringify({ error: "Forbidden" }));
|
|
@@ -35247,7 +34802,18 @@ function startServer(options = {}) {
|
|
|
35247
34802
|
});
|
|
35248
34803
|
}
|
|
35249
34804
|
initCloudSync(serverDb);
|
|
35250
|
-
|
|
34805
|
+
if (deploymentMode === "cloud") {
|
|
34806
|
+
const onReadyUpdate = createCloudReadyUpdateHandler(() => {
|
|
34807
|
+
if (requestProcessShutdown) requestProcessShutdown();
|
|
34808
|
+
else process.exit(0);
|
|
34809
|
+
});
|
|
34810
|
+
initUpdateChecker({
|
|
34811
|
+
pollIntervalMs: 15 * 60 * 1e3,
|
|
34812
|
+
onReadyUpdate
|
|
34813
|
+
});
|
|
34814
|
+
} else {
|
|
34815
|
+
initUpdateChecker();
|
|
34816
|
+
}
|
|
35251
34817
|
startServerRuntime(serverDb);
|
|
35252
34818
|
function listen() {
|
|
35253
34819
|
server.listen(port, bindHost, () => {
|
|
@@ -35330,6 +34896,7 @@ function startServer(options = {}) {
|
|
|
35330
34896
|
}
|
|
35331
34897
|
// Annotate the CommonJS export names for ESM import in node:
|
|
35332
34898
|
0 && (module.exports = {
|
|
34899
|
+
_createCloudReadyUpdateHandler,
|
|
35333
34900
|
_isLoopbackAddress,
|
|
35334
34901
|
_resolveStaticDirForStart,
|
|
35335
34902
|
_shellQuote,
|