@gendigital/sage-openclaw 0.9.0 → 0.10.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 +63 -20
- package/dist/index.cjs +695 -203
- package/dist/index.cjs.map +4 -4
- package/dist/model-download-worker.cjs +426 -19
- package/dist/model-download-worker.cjs.map +4 -4
- package/openclaw.plugin.json +1 -1
- package/package.json +11 -2
- package/resources/threats/prompt-injection.yaml +2 -1
- package/resources/threats/win-credentials.yaml +1 -1
|
@@ -2961,7 +2961,7 @@ var init_index_min = __esm({
|
|
|
2961
2961
|
});
|
|
2962
2962
|
|
|
2963
2963
|
// ../core/src/model-download-worker.ts
|
|
2964
|
-
var
|
|
2964
|
+
var import_promises7 = require("node:fs/promises");
|
|
2965
2965
|
|
|
2966
2966
|
// ../core/src/config.ts
|
|
2967
2967
|
var import_node_path = require("node:path");
|
|
@@ -7082,6 +7082,14 @@ var LoggingConfigSchema = external_exports.object({
|
|
|
7082
7082
|
max_bytes: external_exports.number().int().min(0).default(5 * 1024 * 1024),
|
|
7083
7083
|
max_files: external_exports.number().int().min(0).default(3)
|
|
7084
7084
|
});
|
|
7085
|
+
var OperationalLogLevelSchema = external_exports.enum(["debug", "info", "warn", "error"]);
|
|
7086
|
+
var OperationalLoggingConfigSchema = external_exports.object({
|
|
7087
|
+
enabled: external_exports.boolean().default(true),
|
|
7088
|
+
level: OperationalLogLevelSchema.default("info"),
|
|
7089
|
+
path: external_exports.string().default("~/.sage/operational.jsonl"),
|
|
7090
|
+
max_bytes: external_exports.number().int().min(0).default(5 * 1024 * 1024),
|
|
7091
|
+
max_files: external_exports.number().int().min(0).default(3)
|
|
7092
|
+
});
|
|
7085
7093
|
var FileCheckConfigSchema = external_exports.object({
|
|
7086
7094
|
endpoint: external_exports.string().optional(),
|
|
7087
7095
|
timeout_seconds: external_exports.number().default(5),
|
|
@@ -7131,6 +7139,7 @@ var ConfigSchema = external_exports.object({
|
|
|
7131
7139
|
allowlist: AllowlistConfigSchema.default({}),
|
|
7132
7140
|
exceptions: ExceptionsConfigSchema.default({}),
|
|
7133
7141
|
logging: LoggingConfigSchema.default({}),
|
|
7142
|
+
operational_logging: OperationalLoggingConfigSchema.default({}),
|
|
7134
7143
|
sensitivity: SensitivitySchema.default("balanced"),
|
|
7135
7144
|
disabled_threats: external_exports.array(external_exports.string()).default([]),
|
|
7136
7145
|
brand_key: external_exports.string().min(1).max(32).regex(/^[a-z0-9_-]+$/u).optional(),
|
|
@@ -7146,6 +7155,28 @@ var HookTypeSchema = external_exports.enum([
|
|
|
7146
7155
|
]);
|
|
7147
7156
|
|
|
7148
7157
|
// ../core/src/config.ts
|
|
7158
|
+
var SAGE_DIR = "~/.sage";
|
|
7159
|
+
function resolvedSageDir() {
|
|
7160
|
+
return resolvePath(SAGE_DIR);
|
|
7161
|
+
}
|
|
7162
|
+
function defaultConfigPath() {
|
|
7163
|
+
return (0, import_node_path.join)(resolvedSageDir(), "config.json");
|
|
7164
|
+
}
|
|
7165
|
+
function defaultCachePath() {
|
|
7166
|
+
return (0, import_node_path.join)(resolvedSageDir(), "cache.json");
|
|
7167
|
+
}
|
|
7168
|
+
function defaultAllowlistPath() {
|
|
7169
|
+
return (0, import_node_path.join)(resolvedSageDir(), "allowlist.json");
|
|
7170
|
+
}
|
|
7171
|
+
function defaultExceptionsPath() {
|
|
7172
|
+
return (0, import_node_path.join)(resolvedSageDir(), "exceptions.json");
|
|
7173
|
+
}
|
|
7174
|
+
function defaultAuditPath() {
|
|
7175
|
+
return (0, import_node_path.join)(resolvedSageDir(), "audit.jsonl");
|
|
7176
|
+
}
|
|
7177
|
+
function defaultOperationalLogPath() {
|
|
7178
|
+
return (0, import_node_path.join)(resolvedSageDir(), "operational.jsonl");
|
|
7179
|
+
}
|
|
7149
7180
|
function resolvePath(pathStr) {
|
|
7150
7181
|
if (pathStr.startsWith("~/") || pathStr === "~") {
|
|
7151
7182
|
const home = getHomeDir();
|
|
@@ -7153,6 +7184,117 @@ function resolvePath(pathStr) {
|
|
|
7153
7184
|
}
|
|
7154
7185
|
return pathStr;
|
|
7155
7186
|
}
|
|
7187
|
+
function isWithinDirectory(baseDir, targetPath) {
|
|
7188
|
+
const rel = (0, import_node_path.relative)(baseDir, targetPath);
|
|
7189
|
+
if (rel === "") return true;
|
|
7190
|
+
if ((0, import_node_path.isAbsolute)(rel)) return false;
|
|
7191
|
+
return rel !== ".." && !rel.startsWith(`..${import_node_path.sep}`);
|
|
7192
|
+
}
|
|
7193
|
+
function normalizeStateFilePath(configuredPath, fallbackPath, field, logger) {
|
|
7194
|
+
const sageDir = resolvedSageDir();
|
|
7195
|
+
const trimmed = configuredPath.trim();
|
|
7196
|
+
if (trimmed === "") {
|
|
7197
|
+
logger.warn(`Config ${field}.path is empty; using default`, {
|
|
7198
|
+
configuredPath,
|
|
7199
|
+
defaultPath: fallbackPath
|
|
7200
|
+
});
|
|
7201
|
+
return fallbackPath;
|
|
7202
|
+
}
|
|
7203
|
+
const expanded = resolvePath(trimmed);
|
|
7204
|
+
const resolved = (0, import_node_path.isAbsolute)(expanded) ? (0, import_node_path.resolve)(expanded) : (0, import_node_path.resolve)(sageDir, expanded);
|
|
7205
|
+
if (isWithinDirectory(sageDir, resolved)) {
|
|
7206
|
+
if (resolved === sageDir) {
|
|
7207
|
+
logger.warn(`Config ${field}.path must point to a file; using default`, {
|
|
7208
|
+
configuredPath,
|
|
7209
|
+
defaultPath: fallbackPath
|
|
7210
|
+
});
|
|
7211
|
+
return fallbackPath;
|
|
7212
|
+
}
|
|
7213
|
+
return resolved;
|
|
7214
|
+
}
|
|
7215
|
+
logger.warn(`Config ${field}.path escapes ${sageDir}; using default`, {
|
|
7216
|
+
configuredPath,
|
|
7217
|
+
defaultPath: fallbackPath
|
|
7218
|
+
});
|
|
7219
|
+
return fallbackPath;
|
|
7220
|
+
}
|
|
7221
|
+
var BRAND_KEY_RE = /^[a-z0-9_-]+$/u;
|
|
7222
|
+
function sanitizeBrandKey(data, logger) {
|
|
7223
|
+
const brandKey = data.brand_key;
|
|
7224
|
+
if (brandKey === void 0) return data;
|
|
7225
|
+
if (typeof brandKey === "string" && brandKey.length >= 1 && brandKey.length <= 32 && BRAND_KEY_RE.test(brandKey)) {
|
|
7226
|
+
return data;
|
|
7227
|
+
}
|
|
7228
|
+
logger.warn(`Invalid brand_key in config \u2014 ignoring`, { brand_key: brandKey });
|
|
7229
|
+
const { brand_key: _2, ...rest } = data;
|
|
7230
|
+
return rest;
|
|
7231
|
+
}
|
|
7232
|
+
function sanitizeConfigPaths(config, logger) {
|
|
7233
|
+
const cachePath = defaultCachePath();
|
|
7234
|
+
const allowlistPath = defaultAllowlistPath();
|
|
7235
|
+
const exceptionsPath = defaultExceptionsPath();
|
|
7236
|
+
const auditPath = defaultAuditPath();
|
|
7237
|
+
const operationalLogPath = defaultOperationalLogPath();
|
|
7238
|
+
return {
|
|
7239
|
+
...config,
|
|
7240
|
+
cache: {
|
|
7241
|
+
...config.cache,
|
|
7242
|
+
path: normalizeStateFilePath(config.cache.path, cachePath, "cache", logger)
|
|
7243
|
+
},
|
|
7244
|
+
allowlist: {
|
|
7245
|
+
...config.allowlist,
|
|
7246
|
+
path: normalizeStateFilePath(config.allowlist.path, allowlistPath, "allowlist", logger)
|
|
7247
|
+
},
|
|
7248
|
+
exceptions: {
|
|
7249
|
+
...config.exceptions,
|
|
7250
|
+
path: normalizeStateFilePath(config.exceptions.path, exceptionsPath, "exceptions", logger)
|
|
7251
|
+
},
|
|
7252
|
+
logging: {
|
|
7253
|
+
...config.logging,
|
|
7254
|
+
path: normalizeStateFilePath(config.logging.path, auditPath, "logging", logger)
|
|
7255
|
+
},
|
|
7256
|
+
operational_logging: {
|
|
7257
|
+
...config.operational_logging,
|
|
7258
|
+
path: normalizeStateFilePath(
|
|
7259
|
+
config.operational_logging.path,
|
|
7260
|
+
operationalLogPath,
|
|
7261
|
+
"operational_logging",
|
|
7262
|
+
logger
|
|
7263
|
+
)
|
|
7264
|
+
}
|
|
7265
|
+
};
|
|
7266
|
+
}
|
|
7267
|
+
function defaultConfig(logger) {
|
|
7268
|
+
return sanitizeConfigPaths(ConfigSchema.parse({}), logger);
|
|
7269
|
+
}
|
|
7270
|
+
function parseConfig(raw, path, logger) {
|
|
7271
|
+
let data;
|
|
7272
|
+
try {
|
|
7273
|
+
data = JSON.parse(raw);
|
|
7274
|
+
} catch (e) {
|
|
7275
|
+
logger.warn(`Failed to parse config from ${path}`, { error: String(e) });
|
|
7276
|
+
return defaultConfig(logger);
|
|
7277
|
+
}
|
|
7278
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
7279
|
+
logger.warn(`Config file ${path} does not contain a JSON object`);
|
|
7280
|
+
return defaultConfig(logger);
|
|
7281
|
+
}
|
|
7282
|
+
const sanitized = sanitizeBrandKey(data, logger);
|
|
7283
|
+
try {
|
|
7284
|
+
return sanitizeConfigPaths(ConfigSchema.parse(sanitized), logger);
|
|
7285
|
+
} catch (e) {
|
|
7286
|
+
logger.warn(`Config validation failed, using defaults`, { error: String(e) });
|
|
7287
|
+
return defaultConfig(logger);
|
|
7288
|
+
}
|
|
7289
|
+
}
|
|
7290
|
+
async function loadConfig(configPath, logger = nullLogger) {
|
|
7291
|
+
const path = configPath ? resolvePath(configPath) : defaultConfigPath();
|
|
7292
|
+
try {
|
|
7293
|
+
return parseConfig(await getFileContent(path), path, logger);
|
|
7294
|
+
} catch {
|
|
7295
|
+
return defaultConfig(logger);
|
|
7296
|
+
}
|
|
7297
|
+
}
|
|
7156
7298
|
|
|
7157
7299
|
// ../core/src/installation-id.ts
|
|
7158
7300
|
var import_node_crypto = require("node:crypto");
|
|
@@ -7440,7 +7582,7 @@ var import_node_path14 = require("node:path");
|
|
|
7440
7582
|
var import_node_url = require("node:url");
|
|
7441
7583
|
var import_meta = {};
|
|
7442
7584
|
function resolveVersion() {
|
|
7443
|
-
if (true) return "0.
|
|
7585
|
+
if (true) return "0.10.0";
|
|
7444
7586
|
try {
|
|
7445
7587
|
const pkgPath = (0, import_node_path14.join)((0, import_node_path14.dirname)((0, import_node_url.fileURLToPath)(import_meta.url)), "..", "package.json");
|
|
7446
7588
|
const pkg = JSON.parse(getFileContentSync(pkgPath));
|
|
@@ -7545,7 +7687,19 @@ async function ensureModelsAvailable(args) {
|
|
|
7545
7687
|
const required = REQUIRED_MODELS_BY_SCHEMA[schema] ?? [];
|
|
7546
7688
|
if (required.length === 0) return [];
|
|
7547
7689
|
const missing = missingRequiredModels(schema, sageDir);
|
|
7548
|
-
|
|
7690
|
+
logger.debug("Model availability check started", {
|
|
7691
|
+
schema,
|
|
7692
|
+
requiredModels: required,
|
|
7693
|
+
missingModels: missing
|
|
7694
|
+
});
|
|
7695
|
+
if (missing.length === 0) {
|
|
7696
|
+
logger.debug("Model availability check completed", {
|
|
7697
|
+
schema,
|
|
7698
|
+
result: "already_available",
|
|
7699
|
+
installedModels: required
|
|
7700
|
+
});
|
|
7701
|
+
return [...required];
|
|
7702
|
+
}
|
|
7549
7703
|
const manifest = await fetchModelManifest({
|
|
7550
7704
|
iid: args.iid,
|
|
7551
7705
|
schema,
|
|
@@ -7555,8 +7709,15 @@ async function ensureModelsAvailable(args) {
|
|
|
7555
7709
|
logger
|
|
7556
7710
|
});
|
|
7557
7711
|
if (!manifest) {
|
|
7558
|
-
|
|
7559
|
-
|
|
7712
|
+
const installed2 = required.filter((name) => !missing.includes(name));
|
|
7713
|
+
logger.debug("Model availability check completed", {
|
|
7714
|
+
schema,
|
|
7715
|
+
result: "skipped",
|
|
7716
|
+
skippedReason: "manifest_unavailable",
|
|
7717
|
+
installedModels: installed2,
|
|
7718
|
+
missingModels: missing
|
|
7719
|
+
});
|
|
7720
|
+
return installed2;
|
|
7560
7721
|
}
|
|
7561
7722
|
const installed = new Set(required.filter((name) => !missing.includes(name)));
|
|
7562
7723
|
for (const name of missing) {
|
|
@@ -7578,7 +7739,212 @@ async function ensureModelsAvailable(args) {
|
|
|
7578
7739
|
logger.warn(`download of model '${name}' threw: ${err}`);
|
|
7579
7740
|
}
|
|
7580
7741
|
}
|
|
7581
|
-
|
|
7742
|
+
const installedModels = [...installed];
|
|
7743
|
+
logger.debug("Model availability check completed", {
|
|
7744
|
+
schema,
|
|
7745
|
+
result: "checked",
|
|
7746
|
+
installedModels,
|
|
7747
|
+
missingModels: required.filter((name) => !installed.has(name))
|
|
7748
|
+
});
|
|
7749
|
+
return installedModels;
|
|
7750
|
+
}
|
|
7751
|
+
|
|
7752
|
+
// ../core/src/jsonl-log-writer.ts
|
|
7753
|
+
var import_promises5 = require("node:fs/promises");
|
|
7754
|
+
var import_node_path15 = require("node:path");
|
|
7755
|
+
var import_promises6 = require("node:timers/promises");
|
|
7756
|
+
var writeQueues = /* @__PURE__ */ new Map();
|
|
7757
|
+
var ROTATE_LOCK_TIMEOUT_MS = 250;
|
|
7758
|
+
var ROTATE_LOCK_STALE_MS = 3e4;
|
|
7759
|
+
var ROTATE_LOCK_POLL_MS = 50;
|
|
7760
|
+
async function shouldRotate(filePath, maxBytes, maxFiles) {
|
|
7761
|
+
if (maxBytes <= 0 || maxFiles <= 0) return false;
|
|
7762
|
+
try {
|
|
7763
|
+
const s3 = await (0, import_promises5.stat)(filePath);
|
|
7764
|
+
return s3.size >= maxBytes;
|
|
7765
|
+
} catch {
|
|
7766
|
+
return false;
|
|
7767
|
+
}
|
|
7768
|
+
}
|
|
7769
|
+
async function removeStaleRotateLock(lockPath) {
|
|
7770
|
+
try {
|
|
7771
|
+
const s3 = await (0, import_promises5.stat)(lockPath);
|
|
7772
|
+
if (Date.now() - s3.mtimeMs < ROTATE_LOCK_STALE_MS) return;
|
|
7773
|
+
await (0, import_promises5.rmdir)(lockPath);
|
|
7774
|
+
} catch {
|
|
7775
|
+
}
|
|
7776
|
+
}
|
|
7777
|
+
async function acquireRotateLock(filePath) {
|
|
7778
|
+
const lockPath = `${filePath}.lock`;
|
|
7779
|
+
const deadline = Date.now() + ROTATE_LOCK_TIMEOUT_MS;
|
|
7780
|
+
while (true) {
|
|
7781
|
+
try {
|
|
7782
|
+
await (0, import_promises5.mkdir)(lockPath);
|
|
7783
|
+
return async () => {
|
|
7784
|
+
try {
|
|
7785
|
+
await (0, import_promises5.rmdir)(lockPath);
|
|
7786
|
+
} catch {
|
|
7787
|
+
}
|
|
7788
|
+
};
|
|
7789
|
+
} catch {
|
|
7790
|
+
await removeStaleRotateLock(lockPath);
|
|
7791
|
+
const remainingMs = deadline - Date.now();
|
|
7792
|
+
if (remainingMs <= 0) return void 0;
|
|
7793
|
+
await (0, import_promises6.setTimeout)(Math.min(ROTATE_LOCK_POLL_MS, remainingMs));
|
|
7794
|
+
}
|
|
7795
|
+
}
|
|
7796
|
+
}
|
|
7797
|
+
async function rotateIfNeeded(filePath, maxBytes, maxFiles) {
|
|
7798
|
+
if (!await shouldRotate(filePath, maxBytes, maxFiles)) return;
|
|
7799
|
+
const releaseLock = await acquireRotateLock(filePath);
|
|
7800
|
+
if (!releaseLock) return;
|
|
7801
|
+
try {
|
|
7802
|
+
if (!await shouldRotate(filePath, maxBytes, maxFiles)) return;
|
|
7803
|
+
try {
|
|
7804
|
+
await (0, import_promises5.unlink)(`${filePath}.${maxFiles}`);
|
|
7805
|
+
} catch {
|
|
7806
|
+
}
|
|
7807
|
+
for (let i = maxFiles - 1; i >= 1; i--) {
|
|
7808
|
+
try {
|
|
7809
|
+
await (0, import_promises5.rename)(`${filePath}.${i}`, `${filePath}.${i + 1}`);
|
|
7810
|
+
} catch {
|
|
7811
|
+
}
|
|
7812
|
+
}
|
|
7813
|
+
try {
|
|
7814
|
+
await (0, import_promises5.rename)(filePath, `${filePath}.1`);
|
|
7815
|
+
} catch {
|
|
7816
|
+
}
|
|
7817
|
+
} finally {
|
|
7818
|
+
await releaseLock();
|
|
7819
|
+
}
|
|
7820
|
+
}
|
|
7821
|
+
async function appendJsonlEntryNow(path, config, entry) {
|
|
7822
|
+
await (0, import_promises5.mkdir)((0, import_node_path15.dirname)(path), { recursive: true });
|
|
7823
|
+
await rotateIfNeeded(path, config.max_bytes, config.max_files);
|
|
7824
|
+
await (0, import_promises5.appendFile)(path, `${JSON.stringify(entry)}
|
|
7825
|
+
`);
|
|
7826
|
+
}
|
|
7827
|
+
async function appendJsonlEntry(config, entry) {
|
|
7828
|
+
const path = resolvePath(config.path);
|
|
7829
|
+
const previousWrite = writeQueues.get(path) ?? Promise.resolve();
|
|
7830
|
+
const nextWrite = previousWrite.catch(() => {
|
|
7831
|
+
}).then(() => appendJsonlEntryNow(path, config, entry));
|
|
7832
|
+
writeQueues.set(path, nextWrite);
|
|
7833
|
+
try {
|
|
7834
|
+
await nextWrite;
|
|
7835
|
+
} finally {
|
|
7836
|
+
if (writeQueues.get(path) === nextWrite) writeQueues.delete(path);
|
|
7837
|
+
}
|
|
7838
|
+
}
|
|
7839
|
+
|
|
7840
|
+
// ../core/src/operational-log.ts
|
|
7841
|
+
var LEVEL_PRIORITY = {
|
|
7842
|
+
debug: 10,
|
|
7843
|
+
info: 20,
|
|
7844
|
+
warn: 30,
|
|
7845
|
+
error: 40
|
|
7846
|
+
};
|
|
7847
|
+
var FLUSH_TIMEOUT_MS = 250;
|
|
7848
|
+
function shouldLog(config, level) {
|
|
7849
|
+
return config.enabled && LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[config.level];
|
|
7850
|
+
}
|
|
7851
|
+
function normalizeData(data) {
|
|
7852
|
+
if (!data) return void 0;
|
|
7853
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
7854
|
+
try {
|
|
7855
|
+
return JSON.parse(
|
|
7856
|
+
JSON.stringify(data, (_key, value) => {
|
|
7857
|
+
if (typeof value === "bigint") return value.toString();
|
|
7858
|
+
if (value instanceof Error) {
|
|
7859
|
+
return { name: value.name, message: value.message, stack: value.stack };
|
|
7860
|
+
}
|
|
7861
|
+
if (value && typeof value === "object") {
|
|
7862
|
+
if (seen.has(value)) return "[Circular]";
|
|
7863
|
+
seen.add(value);
|
|
7864
|
+
}
|
|
7865
|
+
return value;
|
|
7866
|
+
})
|
|
7867
|
+
);
|
|
7868
|
+
} catch {
|
|
7869
|
+
return { serialization_error: "Failed to serialize log data" };
|
|
7870
|
+
}
|
|
7871
|
+
}
|
|
7872
|
+
async function writeOperationalLogEntry(config, entry) {
|
|
7873
|
+
if (!shouldLog(config, entry.level)) return;
|
|
7874
|
+
try {
|
|
7875
|
+
await appendJsonlEntry(config, entry);
|
|
7876
|
+
} catch {
|
|
7877
|
+
}
|
|
7878
|
+
}
|
|
7879
|
+
function createOperationalLogger(config, runtime) {
|
|
7880
|
+
const pendingWrites = /* @__PURE__ */ new Set();
|
|
7881
|
+
function log(component, level, message, data) {
|
|
7882
|
+
if (!shouldLog(config, level)) return;
|
|
7883
|
+
const entry = {
|
|
7884
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7885
|
+
level,
|
|
7886
|
+
runtime,
|
|
7887
|
+
component,
|
|
7888
|
+
message,
|
|
7889
|
+
...data ? { data: normalizeData(data) } : {}
|
|
7890
|
+
};
|
|
7891
|
+
const write = writeOperationalLogEntry(config, entry);
|
|
7892
|
+
pendingWrites.add(write);
|
|
7893
|
+
void write.finally(() => pendingWrites.delete(write));
|
|
7894
|
+
}
|
|
7895
|
+
async function flush() {
|
|
7896
|
+
const deadline = Date.now() + FLUSH_TIMEOUT_MS;
|
|
7897
|
+
while (pendingWrites.size > 0) {
|
|
7898
|
+
const remainingMs = deadline - Date.now();
|
|
7899
|
+
if (remainingMs <= 0) return;
|
|
7900
|
+
let timeout;
|
|
7901
|
+
try {
|
|
7902
|
+
const result = await Promise.race([
|
|
7903
|
+
Promise.allSettled([...pendingWrites]).then(() => "drained"),
|
|
7904
|
+
new Promise((resolve4) => {
|
|
7905
|
+
timeout = setTimeout(() => resolve4("timeout"), remainingMs);
|
|
7906
|
+
timeout.unref?.();
|
|
7907
|
+
})
|
|
7908
|
+
]);
|
|
7909
|
+
if (result === "timeout") return;
|
|
7910
|
+
} finally {
|
|
7911
|
+
if (timeout) clearTimeout(timeout);
|
|
7912
|
+
}
|
|
7913
|
+
}
|
|
7914
|
+
}
|
|
7915
|
+
function forComponent(component) {
|
|
7916
|
+
return {
|
|
7917
|
+
debug(msg, data) {
|
|
7918
|
+
log(component, "debug", msg, data);
|
|
7919
|
+
},
|
|
7920
|
+
info(msg, data) {
|
|
7921
|
+
log(component, "info", msg, data);
|
|
7922
|
+
},
|
|
7923
|
+
warn(msg, data) {
|
|
7924
|
+
log(component, "warn", msg, data);
|
|
7925
|
+
},
|
|
7926
|
+
error(msg, data) {
|
|
7927
|
+
log(component, "error", msg, data);
|
|
7928
|
+
},
|
|
7929
|
+
flush
|
|
7930
|
+
};
|
|
7931
|
+
}
|
|
7932
|
+
return {
|
|
7933
|
+
debug(component, msg, data) {
|
|
7934
|
+
log(component, "debug", msg, data);
|
|
7935
|
+
},
|
|
7936
|
+
info(component, msg, data) {
|
|
7937
|
+
log(component, "info", msg, data);
|
|
7938
|
+
},
|
|
7939
|
+
warn(component, msg, data) {
|
|
7940
|
+
log(component, "warn", msg, data);
|
|
7941
|
+
},
|
|
7942
|
+
error(component, msg, data) {
|
|
7943
|
+
log(component, "error", msg, data);
|
|
7944
|
+
},
|
|
7945
|
+
forComponent,
|
|
7946
|
+
flush
|
|
7947
|
+
};
|
|
7582
7948
|
}
|
|
7583
7949
|
|
|
7584
7950
|
// ../core/src/model-download-worker.ts
|
|
@@ -7591,22 +7957,63 @@ async function readWorkerArgs() {
|
|
|
7591
7957
|
const schema = env.SAGE_MODEL_SCHEMA || MODEL_SCHEMA_VERSION;
|
|
7592
7958
|
return { sageDir, agentRuntime, agentRuntimeVersion, versionApp, schema };
|
|
7593
7959
|
}
|
|
7960
|
+
async function createWorkerLogger(agentRuntime) {
|
|
7961
|
+
try {
|
|
7962
|
+
const config = await loadConfig();
|
|
7963
|
+
return createOperationalLogger(
|
|
7964
|
+
config.operational_logging,
|
|
7965
|
+
agentRuntime
|
|
7966
|
+
).forComponent("model-download-worker");
|
|
7967
|
+
} catch {
|
|
7968
|
+
return nullLogger;
|
|
7969
|
+
}
|
|
7970
|
+
}
|
|
7594
7971
|
async function workerMain() {
|
|
7595
7972
|
const args = await readWorkerArgs();
|
|
7596
7973
|
if (!args) return;
|
|
7597
|
-
await (
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7974
|
+
const logger = await createWorkerLogger(args.agentRuntime);
|
|
7975
|
+
try {
|
|
7976
|
+
logger.debug("Model download worker started", {
|
|
7977
|
+
schema: args.schema,
|
|
7978
|
+
agentRuntime: args.agentRuntime,
|
|
7979
|
+
agentRuntimeVersion: args.agentRuntimeVersion,
|
|
7980
|
+
versionApp: args.versionApp
|
|
7981
|
+
});
|
|
7982
|
+
await (0, import_promises7.mkdir)(getModelStorageRoot(args.sageDir), { recursive: true }).catch(() => {
|
|
7983
|
+
});
|
|
7984
|
+
const iid = await getInstallationId(args.sageDir).catch(() => void 0);
|
|
7985
|
+
if (!iid) {
|
|
7986
|
+
logger.debug("Model download worker completed", {
|
|
7987
|
+
result: "skipped",
|
|
7988
|
+
skippedReason: "missing_installation_id"
|
|
7989
|
+
});
|
|
7990
|
+
await logger.flush?.();
|
|
7991
|
+
return;
|
|
7992
|
+
}
|
|
7993
|
+
const installedModels = await ensureModelsAvailable({
|
|
7994
|
+
sageDir: args.sageDir,
|
|
7995
|
+
iid,
|
|
7996
|
+
agentRuntime: args.agentRuntime,
|
|
7997
|
+
agentRuntimeVersion: args.agentRuntimeVersion,
|
|
7998
|
+
versionApp: args.versionApp,
|
|
7999
|
+
schema: args.schema,
|
|
8000
|
+
logger
|
|
8001
|
+
});
|
|
8002
|
+
logger.debug("Model download worker completed", {
|
|
8003
|
+
result: "completed",
|
|
8004
|
+
installedModels
|
|
8005
|
+
});
|
|
8006
|
+
await logger.flush?.();
|
|
8007
|
+
} catch (error) {
|
|
8008
|
+
logger.error("Model download worker failed open", {
|
|
8009
|
+
error: String(error),
|
|
8010
|
+
schema: args.schema,
|
|
8011
|
+
agentRuntime: args.agentRuntime,
|
|
8012
|
+
agentRuntimeVersion: args.agentRuntimeVersion,
|
|
8013
|
+
versionApp: args.versionApp
|
|
8014
|
+
});
|
|
8015
|
+
await logger.flush?.();
|
|
8016
|
+
}
|
|
7610
8017
|
}
|
|
7611
8018
|
var isWorkerEntry = (() => {
|
|
7612
8019
|
try {
|