farming-code 2.2.18 → 2.2.20
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/backend/agent-manager.js +145 -42
- package/backend/bundle-update-helper.js +109 -0
- package/backend/config-manager.js +110 -4
- package/backend/farming-session-store.js +62 -2
- package/backend/server.js +369 -59
- package/backend/terminal-screen-worker-pool.js +15 -6
- package/backend/update-service.js +46 -23
- package/backend/usage-monitor.js +11 -0
- package/dist/assets/App-BupehIbc.js +210 -0
- package/dist/assets/{FileEditorPane-DNy3LAqS.js → FileEditorPane-CJs6kfZO.js} +1 -1
- package/dist/assets/{IconGlyphs-BsUfqpKN.js → IconGlyphs-CZzDr5o2.js} +1 -1
- package/dist/assets/{ProjectFilesSection-BhDEUVHA.js → ProjectFilesSection-DWCV07lA.js} +1 -1
- package/dist/assets/{ReviewPage-ChtByBe3.js → ReviewPage-DBKNOWsJ.js} +1 -1
- package/dist/assets/code-dark-BAt0Q_Op.css +1 -0
- package/dist/assets/{index-fp8VhOes.js → index-DuMjesL2.js} +2 -2
- package/dist/assets/main-y2aK_56c.css +1 -0
- package/dist/index.html +1 -1
- package/frontend/skins/crt/app.js +257 -35
- package/frontend/skins/crt/index.html +21 -38
- package/frontend/skins/crt/styles/billing.css +6 -1
- package/package.json +1 -1
- package/dist/assets/App-DTAQilnX.js +0 -210
- package/dist/assets/code-dark-5esj0bRu.css +0 -1
- package/dist/assets/main-DSO3i_Gs.css +0 -1
|
@@ -342,10 +342,6 @@ function manifestAssetSafety(asset, manifest, options = {}) {
|
|
|
342
342
|
return { safe: true, reason: '' };
|
|
343
343
|
}
|
|
344
344
|
|
|
345
|
-
function shellQuote(value) {
|
|
346
|
-
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
345
|
function requestWithRedirects(url, options = {}, redirectCount = 0, authOrigin = null) {
|
|
350
346
|
if (redirectCount > 5) {
|
|
351
347
|
return Promise.reject(new Error(`too many redirects for ${url}`));
|
|
@@ -798,7 +794,16 @@ class FarmingUpdateService {
|
|
|
798
794
|
|
|
799
795
|
currentInstallState() {
|
|
800
796
|
const persisted = readJsonFile(this.updateStateFile);
|
|
801
|
-
if (
|
|
797
|
+
if (persisted && persisted.method === this.installMethod) return persisted;
|
|
798
|
+
const current = this.currentVersion();
|
|
799
|
+
const currentVersion = normalizeVersion(current.releaseVersion || current.packageVersion);
|
|
800
|
+
if (
|
|
801
|
+
persisted
|
|
802
|
+
&& persisted.targetMethod === this.installMethod
|
|
803
|
+
&& normalizeVersion(persisted.version) === currentVersion
|
|
804
|
+
) {
|
|
805
|
+
return persisted;
|
|
806
|
+
}
|
|
802
807
|
return this.installState;
|
|
803
808
|
}
|
|
804
809
|
|
|
@@ -1116,19 +1121,22 @@ class FarmingUpdateService {
|
|
|
1116
1121
|
this.runtime,
|
|
1117
1122
|
this.currentVersion().compatibilityProfile,
|
|
1118
1123
|
);
|
|
1119
|
-
this.
|
|
1124
|
+
this.persistInstallState({
|
|
1120
1125
|
phase: 'downloading',
|
|
1126
|
+
method: this.installMethod,
|
|
1121
1127
|
version: status.selected.version,
|
|
1128
|
+
previousVersion: status.current.releaseVersion || status.current.packageVersion,
|
|
1122
1129
|
assetName: status.selected.assetName,
|
|
1123
1130
|
startedAt: new Date(this.now()).toISOString(),
|
|
1124
1131
|
logPath: path.join(this.configDir, 'farming-update.log'),
|
|
1125
|
-
};
|
|
1132
|
+
});
|
|
1126
1133
|
void this.runInstall(asset).catch(error => {
|
|
1127
|
-
this.
|
|
1134
|
+
this.persistInstallState({
|
|
1128
1135
|
...this.installState,
|
|
1129
1136
|
phase: 'failed',
|
|
1130
1137
|
error: error.message || String(error),
|
|
1131
|
-
|
|
1138
|
+
completedAt: new Date(this.now()).toISOString(),
|
|
1139
|
+
});
|
|
1132
1140
|
});
|
|
1133
1141
|
return this.installState;
|
|
1134
1142
|
}
|
|
@@ -1221,7 +1229,7 @@ class FarmingUpdateService {
|
|
|
1221
1229
|
|
|
1222
1230
|
validateArchiveEntries(await this.listArchiveEntries(archivePath));
|
|
1223
1231
|
|
|
1224
|
-
this.
|
|
1232
|
+
this.persistInstallState({ ...this.installState, phase: 'extracting' });
|
|
1225
1233
|
await new Promise((resolve, reject) => {
|
|
1226
1234
|
this.execFile('tar', ['-xzf', archivePath, '-C', tempRoot], (error) => {
|
|
1227
1235
|
if (error) reject(error);
|
|
@@ -1240,23 +1248,38 @@ class FarmingUpdateService {
|
|
|
1240
1248
|
throw new Error('downloaded release is missing scripts/install-release.sh');
|
|
1241
1249
|
}
|
|
1242
1250
|
const logPath = this.installState.logPath || path.join(this.configDir, 'farming-update.log');
|
|
1243
|
-
const
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1251
|
+
const targetMethod = String(releaseMetadata.updateMethod || releaseMetadata.type || this.installMethod);
|
|
1252
|
+
const helperPath = path.join(__dirname, 'bundle-update-helper.js');
|
|
1253
|
+
const nodePath = process.env.FARMING_NODE_BIN || process.execPath;
|
|
1254
|
+
const helperInvocation = nodeScriptInvocation(nodePath, helperPath);
|
|
1255
|
+
const payload = {
|
|
1256
|
+
method: this.installMethod,
|
|
1257
|
+
targetMethod,
|
|
1258
|
+
version: this.installState.version,
|
|
1259
|
+
previousVersion: this.installState.previousVersion,
|
|
1260
|
+
startedAt: this.installState.startedAt,
|
|
1261
|
+
stateFile: this.updateStateFile,
|
|
1262
|
+
logPath,
|
|
1263
|
+
releaseDir,
|
|
1264
|
+
installer,
|
|
1265
|
+
};
|
|
1266
|
+
this.persistInstallState({
|
|
1255
1267
|
...this.installState,
|
|
1256
1268
|
phase: 'installing',
|
|
1269
|
+
targetMethod,
|
|
1257
1270
|
releaseDir,
|
|
1258
1271
|
logPath,
|
|
1259
|
-
};
|
|
1272
|
+
});
|
|
1273
|
+
const child = this.spawn(helperInvocation.command, helperInvocation.args, {
|
|
1274
|
+
cwd: this.configDir,
|
|
1275
|
+
detached: true,
|
|
1276
|
+
stdio: 'ignore',
|
|
1277
|
+
env: {
|
|
1278
|
+
...this.installEnvironment(),
|
|
1279
|
+
FARMING_BUNDLE_UPDATE_PAYLOAD: JSON.stringify(payload),
|
|
1280
|
+
},
|
|
1281
|
+
});
|
|
1282
|
+
if (child && typeof child.unref === 'function') child.unref();
|
|
1260
1283
|
}
|
|
1261
1284
|
}
|
|
1262
1285
|
|
package/backend/usage-monitor.js
CHANGED
|
@@ -10,6 +10,8 @@ const execFileAsync = promisify(execFile);
|
|
|
10
10
|
const USAGE_WINDOW_MS = 5 * 60 * 1000;
|
|
11
11
|
const USAGE_TIMELINE_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
12
12
|
const USAGE_TIMELINE_BUCKET_COUNT = 24;
|
|
13
|
+
const USAGE_LIVE_TIMELINE_WINDOW_MS = 60 * 60 * 1000;
|
|
14
|
+
const USAGE_LIVE_TIMELINE_BUCKET_COUNT = 60;
|
|
13
15
|
const USAGE_DAILY_DAYS = 52 * 7;
|
|
14
16
|
const USAGE_DAILY_CACHE_MS = 5 * 60 * 1000;
|
|
15
17
|
const USAGE_LIVE_DAY_CACHE_MS = 5 * 1000;
|
|
@@ -1020,6 +1022,12 @@ class UsageMonitor {
|
|
|
1020
1022
|
windowMs: historyWindowMs,
|
|
1021
1023
|
alignToBucket: true,
|
|
1022
1024
|
});
|
|
1025
|
+
const liveTimeline = buildUsageTimeline(history.providerEvents, {
|
|
1026
|
+
now,
|
|
1027
|
+
windowMs: USAGE_LIVE_TIMELINE_WINDOW_MS,
|
|
1028
|
+
bucketCount: USAGE_LIVE_TIMELINE_BUCKET_COUNT,
|
|
1029
|
+
alignToBucket: true,
|
|
1030
|
+
});
|
|
1023
1031
|
const openCodeCoverage = history.coverage.find(entry => entry.provider === 'opencode');
|
|
1024
1032
|
const qoderCoverage = history.coverage.find(entry => entry.provider === 'qoder');
|
|
1025
1033
|
|
|
@@ -1027,6 +1035,7 @@ class UsageMonitor {
|
|
|
1027
1035
|
sampledAt: now,
|
|
1028
1036
|
windowMs,
|
|
1029
1037
|
timeline,
|
|
1038
|
+
liveTimeline,
|
|
1030
1039
|
daily: history.daily,
|
|
1031
1040
|
providers: [
|
|
1032
1041
|
{
|
|
@@ -1099,6 +1108,8 @@ module.exports = {
|
|
|
1099
1108
|
USAGE_WINDOW_MS,
|
|
1100
1109
|
USAGE_TIMELINE_WINDOW_MS,
|
|
1101
1110
|
USAGE_TIMELINE_BUCKET_COUNT,
|
|
1111
|
+
USAGE_LIVE_TIMELINE_WINDOW_MS,
|
|
1112
|
+
USAGE_LIVE_TIMELINE_BUCKET_COUNT,
|
|
1102
1113
|
USAGE_DAILY_DAYS,
|
|
1103
1114
|
USAGE_DAILY_CACHE_MS,
|
|
1104
1115
|
USAGE_LIVE_DAY_CACHE_MS,
|