@gendigital/sage-openclaw 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +1648 -489
- package/dist/index.cjs.map +4 -4
- package/dist/mcp-server.cjs +230 -96
- package/dist/mcp-server.cjs.map +4 -4
- package/dist/model-download-worker.cjs +139 -94
- package/dist/model-download-worker.cjs.map +3 -3
- package/dist/skill-upload-worker.cjs +5638 -0
- package/dist/skill-upload-worker.cjs.map +7 -0
- package/openclaw.plugin.json +6 -1
- package/package.json +8 -3
- package/resources/threats/_macros.yaml +193 -0
- package/resources/threats/agent-layer.yaml +19 -1
- package/resources/threats/commands.yaml +165 -31
- package/resources/threats/credentials.yaml +24 -4
- package/resources/threats/dummy.yaml +52 -17
- package/resources/threats/files.yaml +38 -0
- package/resources/threats/mac-commands.yaml +118 -27
- package/resources/threats/mac-credentials.yaml +34 -8
- package/resources/threats/mac-files.yaml +20 -0
- package/resources/threats/mac-obfuscation.yaml +28 -6
- package/resources/threats/mac-persistence.yaml +30 -4
- package/resources/threats/mac-supply-chain.yaml +12 -3
- package/resources/threats/mitre.yaml +325 -62
- package/resources/threats/obfuscation.yaml +33 -8
- package/resources/threats/persistence.yaml +40 -5
- package/resources/threats/prompt-injection.yaml +58 -0
- package/resources/threats/self-defense.yaml +15 -2
- package/resources/threats/supply_chain.yaml +6 -1
- package/resources/threats/urls.yaml +10 -0
- package/resources/threats/win-commands.yaml +294 -60
- package/resources/threats/win-credentials.yaml +68 -9
- package/resources/threats/win-files.yaml +20 -0
- package/resources/threats/win-obfuscation.yaml +56 -8
- package/resources/threats/win-persistence.yaml +45 -7
- package/resources/threats/win-supply-chain.yaml +5 -1
|
@@ -67,7 +67,7 @@ function Pn(s3, t) {
|
|
|
67
67
|
function zn(s3, t) {
|
|
68
68
|
s3.head = new ue(t, void 0, s3.head, s3), s3.tail || (s3.tail = s3.head), s3.length++;
|
|
69
69
|
}
|
|
70
|
-
var import_events, import_fs, import_node_events, import_node_stream, import_node_string_decoder, import_node_path4, import_node_fs2, import_path, import_events2, import_assert, import_buffer, ks, import_zlib, import_node_path5, import_node_path6, import_fs2, import_fs3, import_path2, import_node_path7, import_path3, import_node_fs3, import_node_assert, import_node_crypto2, import_node_fs4, import_node_path8, import_fs4, import_node_fs5, import_node_path9, import_node_fs6,
|
|
70
|
+
var import_events, import_fs, import_node_events, import_node_stream, import_node_string_decoder, import_node_path4, import_node_fs2, import_path, import_events2, import_assert, import_buffer, ks, import_zlib, import_node_path5, import_node_path6, import_fs2, import_fs3, import_path2, import_node_path7, import_path3, import_node_fs3, import_node_assert, import_node_crypto2, import_node_fs4, import_node_path8, import_fs4, import_node_fs5, import_node_path9, import_node_fs6, import_promises3, import_node_path10, import_node_path11, import_node_fs7, import_node_path12, kr, vr, Os, Br, Pr, zr, q, j, rt, Le, jt, Ne, Ts, Ae, xs, z, Mt, b, Qt, Bt, _, A, g, yi, De, L, w, Ri, bi, Ls, _i, Z, gi, Ie, Jt, yt, C, te, Ur, Hr, Wr, Gr, Ce, Oi, Zr, Yr, D, Vr, ot, H, ee, m, xi, J, Li, Ii, Ci, se, Fe, Ut, Ht, Ni, Pt, ht, U, nt, Y, zt, Ai, Q, ie, Di, ke, Rt, ve, bt, _t, Me, tt, Wt, $r, As, Ds, Is, Cs, Fs, Xr, re, K, jr, M, Qr, vs, Jr, ki, Ot, Gt, vi, ne, Be, Pe, ze, Ue, He, We, Ge, Ze, Ye, Ms, en, sn, Bs, rn, nn, Ps, zs, Bi, oe, hn, he, Ke, F, an, Tt, Pi, ln, at, cn, fn, dn, lt, un, mn, pn, zi, En, xt, ct, Sn, yn, Rn, bn, f, Yt, Lt, gn, Zi, Yi, On, B, Nt, et, Ui, Us, V, ae, ft, Hs, p, it, dt, Hi, At, y, Ve, $e, Wi, Ws, Gs, le, Gi, Xe, Kt, ut, qe, Dt, je, Qe, Zs, Tn, st, mt, Nn, Ki, An, Dn, It, Vi, Cn, Ys, ce, Je, $i, Fn, kn, Xi, Ks, Js, vn, Xs, qs, js, ji, Qs, fe, ti, Qi, ei, Ji, ts, es, is, pt, ii, ss, qi, X, de, si, ri, Mn, ni, ue, di, tr, oi, me, W, Ct, Ft, pe, rs, G, ns, hi, er, as, ls, ai, li, ir, os, ci, rr, hs, Et, kt, Un, Hn, or, hr, Wn, Gn, Zn, Yn, fr, dr, ar, ur, mr, pr, Kn, Vn, $n, lr, cs, fs2, ui, Xn, ds, qn, us, we, wt, Qn, Er, ms, wr, Jn, Sr, ps, yr, $t, Rr, to, eo, io, Ei, _r, gr, ys, Or, Rs, P, bs, _s, Si, Tr, xr, ye, Lr, Nr, Es, St, O, wi, Ar, Xt, ws, Ss, gs, Re, be, _e, ge, ro, Oe, no, oo, ho, Dr, qt, Se, Te, ao, lo, co, fo, uo, mo, po, Eo, vt, wo, So;
|
|
71
71
|
var init_index_min = __esm({
|
|
72
72
|
"../../node_modules/.pnpm/tar@7.5.13/node_modules/tar/dist/esm/index.min.js"() {
|
|
73
73
|
import_events = __toESM(require("events"), 1);
|
|
@@ -99,7 +99,7 @@ var init_index_min = __esm({
|
|
|
99
99
|
import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
100
100
|
import_node_path9 = __toESM(require("node:path"), 1);
|
|
101
101
|
import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
102
|
-
|
|
102
|
+
import_promises3 = __toESM(require("node:fs/promises"), 1);
|
|
103
103
|
import_node_path10 = __toESM(require("node:path"), 1);
|
|
104
104
|
import_node_path11 = require("node:path");
|
|
105
105
|
import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
@@ -2258,7 +2258,7 @@ var init_index_min = __esm({
|
|
|
2258
2258
|
E ? e(E) : x && a ? ds(x, o, h, (xe) => S(xe)) : n ? import_node_fs6.default.chmod(s3, r, e) : e();
|
|
2259
2259
|
};
|
|
2260
2260
|
if (s3 === d) return Qn(s3, S);
|
|
2261
|
-
if (l) return
|
|
2261
|
+
if (l) return import_promises3.default.mkdir(s3, { mode: r, recursive: true }).then((E) => S(null, E ?? void 0), S);
|
|
2262
2262
|
let N = f(import_node_path10.default.relative(d, s3)).split("/");
|
|
2263
2263
|
ms(d, N, r, c, d, void 0, S);
|
|
2264
2264
|
};
|
|
@@ -2970,6 +2970,7 @@ var import_node_path = require("node:path");
|
|
|
2970
2970
|
var fs = __toESM(require("node:fs"), 1);
|
|
2971
2971
|
var fsPromises = __toESM(require("node:fs/promises"), 1);
|
|
2972
2972
|
var import_node_os = require("node:os");
|
|
2973
|
+
var import_promises = require("node:timers/promises");
|
|
2973
2974
|
var name1 = "read";
|
|
2974
2975
|
var name2 = "File";
|
|
2975
2976
|
function getFileContent(path, encoding = "utf-8") {
|
|
@@ -2984,6 +2985,43 @@ function getProcEnv() {
|
|
|
2984
2985
|
function getHomeDir() {
|
|
2985
2986
|
return getProcEnv().HOME || (0, import_node_os.homedir)();
|
|
2986
2987
|
}
|
|
2988
|
+
async function removeStaleFileLock(lockPath, staleAgeMs) {
|
|
2989
|
+
try {
|
|
2990
|
+
const s3 = await fsPromises.stat(lockPath);
|
|
2991
|
+
if (Date.now() - s3.mtimeMs < staleAgeMs) return;
|
|
2992
|
+
await fsPromises.rmdir(lockPath);
|
|
2993
|
+
} catch {
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
async function acquireFileLock(filePath, timeoutMs = 250, staleAgeMs = 3e4) {
|
|
2997
|
+
const lockPath = `${filePath}.lock`;
|
|
2998
|
+
const deadline = Date.now() + timeoutMs;
|
|
2999
|
+
while (true) {
|
|
3000
|
+
try {
|
|
3001
|
+
await fsPromises.mkdir(lockPath);
|
|
3002
|
+
return async () => {
|
|
3003
|
+
try {
|
|
3004
|
+
await fsPromises.rmdir(lockPath);
|
|
3005
|
+
} catch {
|
|
3006
|
+
}
|
|
3007
|
+
};
|
|
3008
|
+
} catch {
|
|
3009
|
+
await removeStaleFileLock(lockPath, staleAgeMs);
|
|
3010
|
+
const remainingMs = deadline - Date.now();
|
|
3011
|
+
if (remainingMs <= 0) return void 0;
|
|
3012
|
+
await (0, import_promises.setTimeout)(Math.min(50, remainingMs));
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
async function withFileLock(filePath, callback) {
|
|
3017
|
+
const release = await acquireFileLock(filePath);
|
|
3018
|
+
if (!release) return;
|
|
3019
|
+
try {
|
|
3020
|
+
return await callback();
|
|
3021
|
+
} finally {
|
|
3022
|
+
await release();
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
2987
3025
|
|
|
2988
3026
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
2989
3027
|
var external_exports = {};
|
|
@@ -7046,7 +7084,8 @@ var ArtifactSchema = external_exports.object({
|
|
|
7046
7084
|
var VerdictSeveritySchema = external_exports.enum(["info", "warning", "critical"]);
|
|
7047
7085
|
var ThreatSchema = external_exports.object({
|
|
7048
7086
|
id: external_exports.string(),
|
|
7049
|
-
version: external_exports.number().int().
|
|
7087
|
+
version: external_exports.number().int().positive(),
|
|
7088
|
+
detectionName: external_exports.string(),
|
|
7050
7089
|
category: external_exports.string(),
|
|
7051
7090
|
severity: VerdictSeveritySchema,
|
|
7052
7091
|
confidence: external_exports.number(),
|
|
@@ -7099,14 +7138,21 @@ var PackageCheckConfigSchema = external_exports.object({
|
|
|
7099
7138
|
var AmsiCheckConfigSchema = external_exports.object({
|
|
7100
7139
|
enabled: external_exports.boolean().default(true)
|
|
7101
7140
|
});
|
|
7102
|
-
var
|
|
7103
|
-
|
|
7141
|
+
var SkillCheckConfigSchema = external_exports.object({
|
|
7142
|
+
enabled: external_exports.boolean().default(true),
|
|
7143
|
+
cache_ttl_days: external_exports.number().min(0).default(1),
|
|
7144
|
+
/**
|
|
7145
|
+
* Upload unknown skills (never seen by the analyzer) for deep content
|
|
7146
|
+
* analysis. When false, the scan still looks skills up by content hash and
|
|
7147
|
+
* still flags known-risky ones — but no skill content ever leaves the
|
|
7148
|
+
* machine and the upload worker never runs (lookup-only mode).
|
|
7149
|
+
*/
|
|
7150
|
+
upload_enabled: external_exports.boolean().default(true)
|
|
7151
|
+
});
|
|
7104
7152
|
var PiCheckConfigSchema = external_exports.object({
|
|
7105
7153
|
enabled: external_exports.boolean().default(false),
|
|
7106
7154
|
max_content_length: external_exports.number().default(16384),
|
|
7107
|
-
model_path: external_exports.string().optional()
|
|
7108
|
-
high_risk_threshold: external_exports.number().default(DEFAULT_PI_HIGH_RISK_THRESHOLD),
|
|
7109
|
-
medium_risk_threshold: external_exports.number().default(DEFAULT_PI_MEDIUM_RISK_THRESHOLD)
|
|
7155
|
+
model_path: external_exports.string().optional()
|
|
7110
7156
|
});
|
|
7111
7157
|
var ExceptionDecisionSchema = external_exports.enum(["allow", "deny"]);
|
|
7112
7158
|
var ExceptionMatchSchema = external_exports.enum(["executable", "domain", "path", "plugin", "regex"]);
|
|
@@ -7128,6 +7174,7 @@ var ConfigSchema = external_exports.object({
|
|
|
7128
7174
|
file_check: FileCheckConfigSchema.default({}),
|
|
7129
7175
|
package_check: PackageCheckConfigSchema.default({}),
|
|
7130
7176
|
amsi_check: AmsiCheckConfigSchema.default({}),
|
|
7177
|
+
skill_check: SkillCheckConfigSchema.default({}),
|
|
7131
7178
|
pi_check: PiCheckConfigSchema.default({}),
|
|
7132
7179
|
heuristics_enabled: external_exports.boolean().default(true),
|
|
7133
7180
|
cache: CacheConfigSchema.default({}),
|
|
@@ -7136,6 +7183,8 @@ var ConfigSchema = external_exports.object({
|
|
|
7136
7183
|
operational_logging: OperationalLoggingConfigSchema.default({}),
|
|
7137
7184
|
sensitivity: SensitivitySchema.default("balanced"),
|
|
7138
7185
|
disabled_threats: external_exports.array(external_exports.string()).default([]),
|
|
7186
|
+
announce_clean_scans: external_exports.boolean().default(true),
|
|
7187
|
+
manage_status_line: external_exports.boolean().default(true),
|
|
7139
7188
|
brand_key: external_exports.string().min(1).max(32).regex(/^[a-z0-9_-]+$/u).optional(),
|
|
7140
7189
|
community_iq: external_exports.boolean().default(true)
|
|
7141
7190
|
});
|
|
@@ -7150,6 +7199,8 @@ var HookTypeSchema = external_exports.enum([
|
|
|
7150
7199
|
|
|
7151
7200
|
// ../core/src/config.ts
|
|
7152
7201
|
var SAGE_DIR = "~/.sage";
|
|
7202
|
+
var MS_PER_DAY = 24 * 60 * 60 * 1e3;
|
|
7203
|
+
var CLOCK_SKEW_TOLERANCE_MS = 5 * 60 * 1e3;
|
|
7153
7204
|
function resolvedSageDir() {
|
|
7154
7205
|
return resolvePath(SAGE_DIR);
|
|
7155
7206
|
}
|
|
@@ -7216,7 +7267,7 @@ function sanitizeBrandKey(data, logger) {
|
|
|
7216
7267
|
if (typeof brandKey === "string" && brandKey.length >= 1 && brandKey.length <= 32 && BRAND_KEY_RE.test(brandKey)) {
|
|
7217
7268
|
return data;
|
|
7218
7269
|
}
|
|
7219
|
-
logger.warn(`Invalid brand_key in config
|
|
7270
|
+
logger.warn(`Invalid brand_key in config - ignoring`, { brand_key: brandKey });
|
|
7220
7271
|
const { brand_key: _2, ...rest } = data;
|
|
7221
7272
|
return rest;
|
|
7222
7273
|
}
|
|
@@ -7284,7 +7335,7 @@ async function loadConfig(configPath, logger = nullLogger) {
|
|
|
7284
7335
|
|
|
7285
7336
|
// ../core/src/installation-id.ts
|
|
7286
7337
|
var import_node_crypto = require("node:crypto");
|
|
7287
|
-
var
|
|
7338
|
+
var import_promises2 = require("node:fs/promises");
|
|
7288
7339
|
var import_node_path2 = require("node:path");
|
|
7289
7340
|
async function getInstallationId(sageDirPath) {
|
|
7290
7341
|
const sageDir = sageDirPath ?? resolvePath("~/.sage");
|
|
@@ -7299,8 +7350,8 @@ async function getInstallationId(sageDirPath) {
|
|
|
7299
7350
|
}
|
|
7300
7351
|
try {
|
|
7301
7352
|
const id = (0, import_node_crypto.randomUUID)();
|
|
7302
|
-
await (0,
|
|
7303
|
-
await (0,
|
|
7353
|
+
await (0, import_promises2.mkdir)(sageDir, { recursive: true, mode: 448 });
|
|
7354
|
+
await (0, import_promises2.writeFile)(idPath, id, { encoding: "utf-8", mode: 384, flag: fileExists ? "w" : "wx" });
|
|
7304
7355
|
return id;
|
|
7305
7356
|
} catch (err) {
|
|
7306
7357
|
if (err.code === "EEXIST") {
|
|
@@ -7318,17 +7369,18 @@ async function getInstallationId(sageDirPath) {
|
|
|
7318
7369
|
// ../core/src/clients/model-downloader.ts
|
|
7319
7370
|
var import_node_crypto3 = require("node:crypto");
|
|
7320
7371
|
var import_node_fs8 = require("node:fs");
|
|
7321
|
-
var
|
|
7372
|
+
var import_promises4 = require("node:fs/promises");
|
|
7322
7373
|
var import_node_path13 = require("node:path");
|
|
7323
7374
|
var import_node_stream2 = require("node:stream");
|
|
7324
|
-
var
|
|
7375
|
+
var import_promises5 = require("node:stream/promises");
|
|
7325
7376
|
|
|
7326
7377
|
// ../core/src/model-storage.ts
|
|
7327
7378
|
var import_node_fs = require("node:fs");
|
|
7328
7379
|
var import_node_path3 = require("node:path");
|
|
7329
|
-
var MODEL_SCHEMA_VERSION = "
|
|
7380
|
+
var MODEL_SCHEMA_VERSION = "v2";
|
|
7330
7381
|
var REQUIRED_MODELS_BY_SCHEMA = {
|
|
7331
|
-
v1: ["pi-model"]
|
|
7382
|
+
v1: ["pi-model"],
|
|
7383
|
+
v2: ["pi-model"]
|
|
7332
7384
|
};
|
|
7333
7385
|
var REQUIRED_MODEL_FILES = {
|
|
7334
7386
|
"pi-model": [
|
|
@@ -7377,8 +7429,8 @@ async function downloadModel(opts) {
|
|
|
7377
7429
|
const stagingDir = getDownloadStagingDir(sageDir);
|
|
7378
7430
|
const lockPath = `${modelDir}.lock`;
|
|
7379
7431
|
try {
|
|
7380
|
-
await (0,
|
|
7381
|
-
await (0,
|
|
7432
|
+
await (0, import_promises4.mkdir)(stagingDir, { recursive: true });
|
|
7433
|
+
await (0, import_promises4.mkdir)((0, import_node_path13.resolve)(modelDir, ".."), { recursive: true });
|
|
7382
7434
|
} catch (err) {
|
|
7383
7435
|
logger.warn(`failed to prepare model storage for ${modelName}: ${err}`);
|
|
7384
7436
|
return false;
|
|
@@ -7404,7 +7456,7 @@ async function downloadModel(opts) {
|
|
|
7404
7456
|
});
|
|
7405
7457
|
return false;
|
|
7406
7458
|
}
|
|
7407
|
-
await (0,
|
|
7459
|
+
await (0, import_promises4.mkdir)(extractDir, { recursive: true });
|
|
7408
7460
|
await extractTarGz(archivePath, extractDir);
|
|
7409
7461
|
const extractDirResolved = extractDir;
|
|
7410
7462
|
const missing = requiredModelFiles(modelName).filter(
|
|
@@ -7417,26 +7469,26 @@ async function downloadModel(opts) {
|
|
|
7417
7469
|
const aside = `${modelDir}.${suffix}.old`;
|
|
7418
7470
|
let asideUsed = false;
|
|
7419
7471
|
if (await pathExists(modelDir)) {
|
|
7420
|
-
await (0,
|
|
7472
|
+
await (0, import_promises4.rename)(modelDir, aside);
|
|
7421
7473
|
asideUsed = true;
|
|
7422
7474
|
}
|
|
7423
7475
|
try {
|
|
7424
|
-
await (0,
|
|
7476
|
+
await (0, import_promises4.rename)(extractDir, modelDir);
|
|
7425
7477
|
extractDir = null;
|
|
7426
7478
|
} catch (err) {
|
|
7427
7479
|
if (asideUsed) {
|
|
7428
7480
|
try {
|
|
7429
|
-
await (0,
|
|
7481
|
+
await (0, import_promises4.rename)(aside, modelDir);
|
|
7430
7482
|
} catch {
|
|
7431
7483
|
}
|
|
7432
7484
|
}
|
|
7433
7485
|
throw err;
|
|
7434
7486
|
}
|
|
7435
7487
|
if (asideUsed) {
|
|
7436
|
-
await (0,
|
|
7488
|
+
await (0, import_promises4.rm)(aside, { recursive: true, force: true }).catch(() => {
|
|
7437
7489
|
});
|
|
7438
7490
|
}
|
|
7439
|
-
await (0,
|
|
7491
|
+
await (0, import_promises4.unlink)(archivePath).catch(() => {
|
|
7440
7492
|
});
|
|
7441
7493
|
archivePath = null;
|
|
7442
7494
|
logger.info(`model ${modelName} installed (schema ${schema})`);
|
|
@@ -7448,14 +7500,14 @@ async function downloadModel(opts) {
|
|
|
7448
7500
|
return false;
|
|
7449
7501
|
} finally {
|
|
7450
7502
|
if (extractDir) {
|
|
7451
|
-
await (0,
|
|
7503
|
+
await (0, import_promises4.rm)(extractDir, { recursive: true, force: true }).catch(() => {
|
|
7452
7504
|
});
|
|
7453
7505
|
}
|
|
7454
7506
|
if (archivePath) {
|
|
7455
|
-
await (0,
|
|
7507
|
+
await (0, import_promises4.unlink)(archivePath).catch(() => {
|
|
7456
7508
|
});
|
|
7457
7509
|
}
|
|
7458
|
-
await (0,
|
|
7510
|
+
await (0, import_promises4.unlink)(lockPath).catch(() => {
|
|
7459
7511
|
});
|
|
7460
7512
|
}
|
|
7461
7513
|
}
|
|
@@ -7468,11 +7520,11 @@ async function streamFetchToFile(url, destPath, fetchImpl = fetch) {
|
|
|
7468
7520
|
throw new Error(`empty response body from ${url}`);
|
|
7469
7521
|
}
|
|
7470
7522
|
const nodeStream = import_node_stream2.Readable.fromWeb(response.body);
|
|
7471
|
-
await (0,
|
|
7523
|
+
await (0, import_promises5.pipeline)(nodeStream, (0, import_node_fs8.createWriteStream)(destPath));
|
|
7472
7524
|
}
|
|
7473
7525
|
async function sha256OfFile(path) {
|
|
7474
7526
|
const hash = (0, import_node_crypto3.createHash)("sha256");
|
|
7475
|
-
const buf = await (0,
|
|
7527
|
+
const buf = await (0, import_promises4.readFile)(path);
|
|
7476
7528
|
hash.update(buf);
|
|
7477
7529
|
return hash.digest("hex");
|
|
7478
7530
|
}
|
|
@@ -7486,7 +7538,7 @@ async function extractTarGz(archivePath, destDir) {
|
|
|
7486
7538
|
}
|
|
7487
7539
|
async function pathExists(path) {
|
|
7488
7540
|
try {
|
|
7489
|
-
await (0,
|
|
7541
|
+
await (0, import_promises4.stat)(path);
|
|
7490
7542
|
return true;
|
|
7491
7543
|
} catch {
|
|
7492
7544
|
return false;
|
|
@@ -7503,7 +7555,7 @@ function fileExistsSync(path) {
|
|
|
7503
7555
|
async function tryAcquireLock(lockPath, logger) {
|
|
7504
7556
|
try {
|
|
7505
7557
|
const payload = JSON.stringify({ pid: process.pid, ts: Date.now() });
|
|
7506
|
-
await (0,
|
|
7558
|
+
await (0, import_promises4.writeFile)(lockPath, payload, { flag: "wx" });
|
|
7507
7559
|
return true;
|
|
7508
7560
|
} catch (err) {
|
|
7509
7561
|
const code = err.code;
|
|
@@ -7513,15 +7565,15 @@ async function tryAcquireLock(lockPath, logger) {
|
|
|
7513
7565
|
}
|
|
7514
7566
|
}
|
|
7515
7567
|
try {
|
|
7516
|
-
const raw = await (0,
|
|
7568
|
+
const raw = await (0, import_promises4.readFile)(lockPath, "utf-8");
|
|
7517
7569
|
const parsed = JSON.parse(raw);
|
|
7518
7570
|
const age = Date.now() - (parsed.ts ?? 0);
|
|
7519
7571
|
if (age > STALE_LOCK_MS) {
|
|
7520
|
-
await (0,
|
|
7572
|
+
await (0, import_promises4.unlink)(lockPath).catch(() => {
|
|
7521
7573
|
});
|
|
7522
7574
|
try {
|
|
7523
7575
|
const payload = JSON.stringify({ pid: process.pid, ts: Date.now() });
|
|
7524
|
-
await (0,
|
|
7576
|
+
await (0, import_promises4.writeFile)(lockPath, payload, { flag: "wx" });
|
|
7525
7577
|
return true;
|
|
7526
7578
|
} catch {
|
|
7527
7579
|
return false;
|
|
@@ -7533,7 +7585,7 @@ async function tryAcquireLock(lockPath, logger) {
|
|
|
7533
7585
|
}
|
|
7534
7586
|
|
|
7535
7587
|
// ../core/src/sage-proxy.ts
|
|
7536
|
-
function
|
|
7588
|
+
function mapSageHostOs(platform) {
|
|
7537
7589
|
switch (platform) {
|
|
7538
7590
|
case "win32":
|
|
7539
7591
|
return "WINDOWS";
|
|
@@ -7545,21 +7597,37 @@ function mapSageProxyOs(platform) {
|
|
|
7545
7597
|
return platform;
|
|
7546
7598
|
}
|
|
7547
7599
|
}
|
|
7548
|
-
function
|
|
7600
|
+
function mapSageHostArchitecture(arch) {
|
|
7549
7601
|
return arch.toUpperCase();
|
|
7550
7602
|
}
|
|
7603
|
+
function buildSageUserConfig(config) {
|
|
7604
|
+
return {
|
|
7605
|
+
sensitivity: config.sensitivity,
|
|
7606
|
+
url_check_enabled: config.url_check.enabled,
|
|
7607
|
+
file_check_enabled: config.file_check.enabled,
|
|
7608
|
+
package_check_enabled: config.package_check.enabled,
|
|
7609
|
+
heuristics_enabled: config.heuristics_enabled,
|
|
7610
|
+
pi_check_enabled: config.pi_check.enabled,
|
|
7611
|
+
community_iq_enabled: config.community_iq,
|
|
7612
|
+
// Optional-chained + defaulted: real callers pass a loadConfig result (skill_check
|
|
7613
|
+
// always present via the schema default), but this feeds fail-open telemetry, so a
|
|
7614
|
+
// partial config must never crash the envelope build.
|
|
7615
|
+
skill_check_upload_enabled: config.skill_check?.upload_enabled ?? true
|
|
7616
|
+
};
|
|
7617
|
+
}
|
|
7551
7618
|
function buildSageProxyEnvelope(args) {
|
|
7552
7619
|
return {
|
|
7553
7620
|
identity: { uuid: args.iid },
|
|
7554
7621
|
product: { version_app: args.versionApp },
|
|
7555
7622
|
platform: {
|
|
7556
|
-
os: args.platformOs ??
|
|
7557
|
-
architecture: args.platformArchitecture ??
|
|
7623
|
+
os: args.platformOs ?? mapSageHostOs(process.platform),
|
|
7624
|
+
architecture: args.platformArchitecture ?? mapSageHostArchitecture(process.arch)
|
|
7558
7625
|
},
|
|
7559
7626
|
agent: {
|
|
7560
7627
|
agent_runtime: args.agentRuntime,
|
|
7561
7628
|
agent_runtime_version: args.agentRuntimeVersion
|
|
7562
|
-
}
|
|
7629
|
+
},
|
|
7630
|
+
...args.config ? { config: buildSageUserConfig(args.config) } : {}
|
|
7563
7631
|
};
|
|
7564
7632
|
}
|
|
7565
7633
|
|
|
@@ -7568,7 +7636,7 @@ var import_node_path14 = require("node:path");
|
|
|
7568
7636
|
var import_node_url = require("node:url");
|
|
7569
7637
|
var import_meta = {};
|
|
7570
7638
|
function resolveVersion() {
|
|
7571
|
-
if (true) return "0.
|
|
7639
|
+
if (true) return "0.13.0";
|
|
7572
7640
|
try {
|
|
7573
7641
|
const pkgPath = (0, import_node_path14.join)((0, import_node_path14.dirname)((0, import_node_url.fileURLToPath)(import_meta.url)), "..", "package.json");
|
|
7574
7642
|
const pkg = JSON.parse(getFileContentSync(pkgPath));
|
|
@@ -7607,14 +7675,23 @@ async function fetchModelManifest(args) {
|
|
|
7607
7675
|
logger.debug("Skipping model manifest fetch: missing installation id");
|
|
7608
7676
|
return null;
|
|
7609
7677
|
}
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7678
|
+
let config = args.config;
|
|
7679
|
+
if (!config) {
|
|
7680
|
+
try {
|
|
7681
|
+
config = await loadConfig(args.configPath, logger);
|
|
7682
|
+
} catch (err) {
|
|
7683
|
+
logger.debug(`Model manifest config load failed: ${err}`);
|
|
7684
|
+
}
|
|
7685
|
+
}
|
|
7617
7686
|
try {
|
|
7687
|
+
const envelope = buildSageProxyEnvelope({
|
|
7688
|
+
iid: args.iid,
|
|
7689
|
+
versionApp: args.versionApp ?? VERSION,
|
|
7690
|
+
agentRuntime: args.agentRuntime,
|
|
7691
|
+
agentRuntimeVersion: args.agentRuntimeVersion ?? "unknown",
|
|
7692
|
+
config
|
|
7693
|
+
});
|
|
7694
|
+
const body = { ...envelope, models: { schema: args.schema } };
|
|
7618
7695
|
const response = await fetch(resolveEndpoint("/v2/model-manifest"), {
|
|
7619
7696
|
method: "POST",
|
|
7620
7697
|
signal: AbortSignal.timeout(timeoutMs),
|
|
@@ -7691,6 +7768,8 @@ async function ensureModelsAvailable(args) {
|
|
|
7691
7768
|
schema,
|
|
7692
7769
|
agentRuntime: args.agentRuntime ?? "unknown",
|
|
7693
7770
|
agentRuntimeVersion: args.agentRuntimeVersion,
|
|
7771
|
+
config: args.config,
|
|
7772
|
+
configPath: args.configPath,
|
|
7694
7773
|
versionApp: args.versionApp,
|
|
7695
7774
|
logger
|
|
7696
7775
|
});
|
|
@@ -7736,78 +7815,42 @@ async function ensureModelsAvailable(args) {
|
|
|
7736
7815
|
}
|
|
7737
7816
|
|
|
7738
7817
|
// ../core/src/jsonl-log-writer.ts
|
|
7739
|
-
var
|
|
7818
|
+
var import_promises6 = require("node:fs/promises");
|
|
7740
7819
|
var import_node_path15 = require("node:path");
|
|
7741
|
-
var import_promises6 = require("node:timers/promises");
|
|
7742
7820
|
var writeQueues = /* @__PURE__ */ new Map();
|
|
7743
|
-
var ROTATE_LOCK_TIMEOUT_MS = 250;
|
|
7744
|
-
var ROTATE_LOCK_STALE_MS = 3e4;
|
|
7745
|
-
var ROTATE_LOCK_POLL_MS = 50;
|
|
7746
7821
|
async function shouldRotate(filePath, maxBytes, maxFiles) {
|
|
7747
7822
|
if (maxBytes <= 0 || maxFiles <= 0) return false;
|
|
7748
7823
|
try {
|
|
7749
|
-
const s3 = await (0,
|
|
7824
|
+
const s3 = await (0, import_promises6.stat)(filePath);
|
|
7750
7825
|
return s3.size >= maxBytes;
|
|
7751
7826
|
} catch {
|
|
7752
7827
|
return false;
|
|
7753
7828
|
}
|
|
7754
7829
|
}
|
|
7755
|
-
async function removeStaleRotateLock(lockPath) {
|
|
7756
|
-
try {
|
|
7757
|
-
const s3 = await (0, import_promises5.stat)(lockPath);
|
|
7758
|
-
if (Date.now() - s3.mtimeMs < ROTATE_LOCK_STALE_MS) return;
|
|
7759
|
-
await (0, import_promises5.rmdir)(lockPath);
|
|
7760
|
-
} catch {
|
|
7761
|
-
}
|
|
7762
|
-
}
|
|
7763
|
-
async function acquireRotateLock(filePath) {
|
|
7764
|
-
const lockPath = `${filePath}.lock`;
|
|
7765
|
-
const deadline = Date.now() + ROTATE_LOCK_TIMEOUT_MS;
|
|
7766
|
-
while (true) {
|
|
7767
|
-
try {
|
|
7768
|
-
await (0, import_promises5.mkdir)(lockPath);
|
|
7769
|
-
return async () => {
|
|
7770
|
-
try {
|
|
7771
|
-
await (0, import_promises5.rmdir)(lockPath);
|
|
7772
|
-
} catch {
|
|
7773
|
-
}
|
|
7774
|
-
};
|
|
7775
|
-
} catch {
|
|
7776
|
-
await removeStaleRotateLock(lockPath);
|
|
7777
|
-
const remainingMs = deadline - Date.now();
|
|
7778
|
-
if (remainingMs <= 0) return void 0;
|
|
7779
|
-
await (0, import_promises6.setTimeout)(Math.min(ROTATE_LOCK_POLL_MS, remainingMs));
|
|
7780
|
-
}
|
|
7781
|
-
}
|
|
7782
|
-
}
|
|
7783
7830
|
async function rotateIfNeeded(filePath, maxBytes, maxFiles) {
|
|
7784
7831
|
if (!await shouldRotate(filePath, maxBytes, maxFiles)) return;
|
|
7785
|
-
|
|
7786
|
-
if (!releaseLock) return;
|
|
7787
|
-
try {
|
|
7832
|
+
await withFileLock(filePath, async () => {
|
|
7788
7833
|
if (!await shouldRotate(filePath, maxBytes, maxFiles)) return;
|
|
7789
7834
|
try {
|
|
7790
|
-
await (0,
|
|
7835
|
+
await (0, import_promises6.unlink)(`${filePath}.${maxFiles}`);
|
|
7791
7836
|
} catch {
|
|
7792
7837
|
}
|
|
7793
7838
|
for (let i = maxFiles - 1; i >= 1; i--) {
|
|
7794
7839
|
try {
|
|
7795
|
-
await (0,
|
|
7840
|
+
await (0, import_promises6.rename)(`${filePath}.${i}`, `${filePath}.${i + 1}`);
|
|
7796
7841
|
} catch {
|
|
7797
7842
|
}
|
|
7798
7843
|
}
|
|
7799
7844
|
try {
|
|
7800
|
-
await (0,
|
|
7845
|
+
await (0, import_promises6.rename)(filePath, `${filePath}.1`);
|
|
7801
7846
|
} catch {
|
|
7802
7847
|
}
|
|
7803
|
-
}
|
|
7804
|
-
await releaseLock();
|
|
7805
|
-
}
|
|
7848
|
+
});
|
|
7806
7849
|
}
|
|
7807
7850
|
async function appendJsonlEntryNow(path, config, entry) {
|
|
7808
|
-
await (0,
|
|
7851
|
+
await (0, import_promises6.mkdir)((0, import_node_path15.dirname)(path), { recursive: true });
|
|
7809
7852
|
await rotateIfNeeded(path, config.max_bytes, config.max_files);
|
|
7810
|
-
await (0,
|
|
7853
|
+
await (0, import_promises6.appendFile)(path, `${JSON.stringify(entry)}
|
|
7811
7854
|
`);
|
|
7812
7855
|
}
|
|
7813
7856
|
async function appendJsonlEntry(config, entry) {
|
|
@@ -7937,11 +7980,12 @@ function createOperationalLogger(config, runtime) {
|
|
|
7937
7980
|
async function readWorkerArgs() {
|
|
7938
7981
|
const env = process.env;
|
|
7939
7982
|
const sageDir = env.SAGE_DIR ? resolvePath(env.SAGE_DIR) : resolvePath("~/.sage");
|
|
7983
|
+
const configPath = env.SAGE_CONFIG_PATH ? resolvePath(env.SAGE_CONFIG_PATH) : void 0;
|
|
7940
7984
|
const agentRuntime = env.SAGE_AGENT_RUNTIME ?? "unknown";
|
|
7941
7985
|
const agentRuntimeVersion = env.SAGE_AGENT_RUNTIME_VERSION || void 0;
|
|
7942
7986
|
const versionApp = env.SAGE_VERSION_APP || void 0;
|
|
7943
7987
|
const schema = env.SAGE_MODEL_SCHEMA || MODEL_SCHEMA_VERSION;
|
|
7944
|
-
return { sageDir, agentRuntime, agentRuntimeVersion, versionApp, schema };
|
|
7988
|
+
return { sageDir, configPath, agentRuntime, agentRuntimeVersion, versionApp, schema };
|
|
7945
7989
|
}
|
|
7946
7990
|
async function createWorkerLogger(agentRuntime) {
|
|
7947
7991
|
try {
|
|
@@ -7981,6 +8025,7 @@ async function workerMain() {
|
|
|
7981
8025
|
iid,
|
|
7982
8026
|
agentRuntime: args.agentRuntime,
|
|
7983
8027
|
agentRuntimeVersion: args.agentRuntimeVersion,
|
|
8028
|
+
configPath: args.configPath,
|
|
7984
8029
|
versionApp: args.versionApp,
|
|
7985
8030
|
schema: args.schema,
|
|
7986
8031
|
logger
|