@gendigital/sage-openclaw 0.9.0 → 0.11.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.
Files changed (35) hide show
  1. package/README.md +63 -20
  2. package/dist/index.cjs +1073 -653
  3. package/dist/index.cjs.map +4 -4
  4. package/dist/mcp-server.cjs +31776 -0
  5. package/dist/mcp-server.cjs.map +7 -0
  6. package/dist/model-download-worker.cjs +422 -29
  7. package/dist/model-download-worker.cjs.map +4 -4
  8. package/openclaw.plugin.json +1 -1
  9. package/package.json +13 -3
  10. package/resources/skills/security-awareness/SKILL.md +5 -1
  11. package/resources/threats/agent-layer.yaml +186 -0
  12. package/resources/threats/commands.yaml +24 -53
  13. package/resources/threats/credentials.yaml +12 -20
  14. package/resources/threats/dummy.yaml +22 -33
  15. package/resources/threats/files.yaml +34 -53
  16. package/resources/threats/mac-commands.yaml +20 -47
  17. package/resources/threats/mac-credentials.yaml +4 -12
  18. package/resources/threats/mac-files.yaml +5 -15
  19. package/resources/threats/mac-obfuscation.yaml +6 -13
  20. package/resources/threats/mac-persistence.yaml +11 -20
  21. package/resources/threats/mac-supply-chain.yaml +5 -8
  22. package/resources/threats/mitre.yaml +105 -167
  23. package/resources/threats/obfuscation.yaml +7 -15
  24. package/resources/threats/persistence.yaml +10 -17
  25. package/resources/threats/prompt-injection.yaml +94 -44
  26. package/resources/threats/self-defense.yaml +8 -12
  27. package/resources/threats/supply_chain.yaml +1 -2
  28. package/resources/threats/urls.yaml +9 -14
  29. package/resources/threats/win-commands.yaml +46 -106
  30. package/resources/threats/win-credentials.yaml +15 -25
  31. package/resources/threats/win-files.yaml +10 -20
  32. package/resources/threats/win-obfuscation.yaml +21 -37
  33. package/resources/threats/win-persistence.yaml +8 -16
  34. package/resources/threats/win-supply-chain.yaml +2 -3
  35. /package/resources/{allowlists → trusted-domains}/trusted-installer-domains.yaml +0 -0
@@ -2961,7 +2961,7 @@ var init_index_min = __esm({
2961
2961
  });
2962
2962
 
2963
2963
  // ../core/src/model-download-worker.ts
2964
- var import_promises5 = require("node:fs/promises");
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");
@@ -7043,23 +7043,21 @@ var ArtifactSchema = external_exports.object({
7043
7043
  value: external_exports.string(),
7044
7044
  context: external_exports.string().optional()
7045
7045
  });
7046
- var SeveritySchema = external_exports.enum(["critical", "high", "medium", "low"]);
7047
- var ActionSchema = external_exports.enum(["block", "require_approval", "log"]);
7046
+ var VerdictSeveritySchema = external_exports.enum(["info", "warning", "critical"]);
7048
7047
  var ThreatSchema = external_exports.object({
7049
7048
  id: external_exports.string(),
7050
7049
  version: external_exports.number().int().optional(),
7051
7050
  category: external_exports.string(),
7052
- severity: SeveritySchema,
7051
+ severity: VerdictSeveritySchema,
7053
7052
  confidence: external_exports.number(),
7054
- action: ActionSchema,
7055
7053
  pattern: external_exports.string(),
7056
7054
  match_on: external_exports.union([external_exports.string(), external_exports.array(external_exports.string())]),
7057
7055
  title: external_exports.string(),
7058
7056
  expires_at: external_exports.string().nullable().optional(),
7059
- revoked: external_exports.boolean().optional().default(false)
7057
+ revoked: external_exports.boolean().optional().default(false),
7058
+ flags: external_exports.array(external_exports.string()).optional().default([])
7060
7059
  });
7061
7060
  var DecisionSchema = external_exports.enum(["allow", "deny", "ask"]);
7062
- var VerdictSeveritySchema = external_exports.enum(["info", "warning", "critical"]);
7063
7061
  var SensitivitySchema = external_exports.enum(["paranoid", "balanced", "relaxed"]);
7064
7062
  var UrlCheckConfigSchema = external_exports.object({
7065
7063
  endpoint: external_exports.string().optional(),
@@ -7072,9 +7070,6 @@ var CacheConfigSchema = external_exports.object({
7072
7070
  ttl_clean_seconds: external_exports.number().default(86400),
7073
7071
  path: external_exports.string().default("~/.sage/cache.json")
7074
7072
  });
7075
- var AllowlistConfigSchema = external_exports.object({
7076
- path: external_exports.string().default("~/.sage/allowlist.json")
7077
- });
7078
7073
  var LoggingConfigSchema = external_exports.object({
7079
7074
  enabled: external_exports.boolean().default(true),
7080
7075
  log_clean: external_exports.boolean().default(false),
@@ -7082,6 +7077,14 @@ var LoggingConfigSchema = external_exports.object({
7082
7077
  max_bytes: external_exports.number().int().min(0).default(5 * 1024 * 1024),
7083
7078
  max_files: external_exports.number().int().min(0).default(3)
7084
7079
  });
7080
+ var OperationalLogLevelSchema = external_exports.enum(["debug", "info", "warn", "error"]);
7081
+ var OperationalLoggingConfigSchema = external_exports.object({
7082
+ enabled: external_exports.boolean().default(true),
7083
+ level: OperationalLogLevelSchema.default("info"),
7084
+ path: external_exports.string().default("~/.sage/operational.jsonl"),
7085
+ max_bytes: external_exports.number().int().min(0).default(5 * 1024 * 1024),
7086
+ max_files: external_exports.number().int().min(0).default(3)
7087
+ });
7085
7088
  var FileCheckConfigSchema = external_exports.object({
7086
7089
  endpoint: external_exports.string().optional(),
7087
7090
  timeout_seconds: external_exports.number().default(5),
@@ -7128,9 +7131,9 @@ var ConfigSchema = external_exports.object({
7128
7131
  pi_check: PiCheckConfigSchema.default({}),
7129
7132
  heuristics_enabled: external_exports.boolean().default(true),
7130
7133
  cache: CacheConfigSchema.default({}),
7131
- allowlist: AllowlistConfigSchema.default({}),
7132
7134
  exceptions: ExceptionsConfigSchema.default({}),
7133
7135
  logging: LoggingConfigSchema.default({}),
7136
+ operational_logging: OperationalLoggingConfigSchema.default({}),
7134
7137
  sensitivity: SensitivitySchema.default("balanced"),
7135
7138
  disabled_threats: external_exports.array(external_exports.string()).default([]),
7136
7139
  brand_key: external_exports.string().min(1).max(32).regex(/^[a-z0-9_-]+$/u).optional(),
@@ -7146,6 +7149,25 @@ var HookTypeSchema = external_exports.enum([
7146
7149
  ]);
7147
7150
 
7148
7151
  // ../core/src/config.ts
7152
+ var SAGE_DIR = "~/.sage";
7153
+ function resolvedSageDir() {
7154
+ return resolvePath(SAGE_DIR);
7155
+ }
7156
+ function defaultConfigPath() {
7157
+ return (0, import_node_path.join)(resolvedSageDir(), "config.json");
7158
+ }
7159
+ function defaultCachePath() {
7160
+ return (0, import_node_path.join)(resolvedSageDir(), "cache.json");
7161
+ }
7162
+ function defaultExceptionsPath() {
7163
+ return (0, import_node_path.join)(resolvedSageDir(), "exceptions.json");
7164
+ }
7165
+ function defaultAuditPath() {
7166
+ return (0, import_node_path.join)(resolvedSageDir(), "audit.jsonl");
7167
+ }
7168
+ function defaultOperationalLogPath() {
7169
+ return (0, import_node_path.join)(resolvedSageDir(), "operational.jsonl");
7170
+ }
7149
7171
  function resolvePath(pathStr) {
7150
7172
  if (pathStr.startsWith("~/") || pathStr === "~") {
7151
7173
  const home = getHomeDir();
@@ -7153,6 +7175,112 @@ function resolvePath(pathStr) {
7153
7175
  }
7154
7176
  return pathStr;
7155
7177
  }
7178
+ function isWithinDirectory(baseDir, targetPath) {
7179
+ const rel = (0, import_node_path.relative)(baseDir, targetPath);
7180
+ if (rel === "") return true;
7181
+ if ((0, import_node_path.isAbsolute)(rel)) return false;
7182
+ return rel !== ".." && !rel.startsWith(`..${import_node_path.sep}`);
7183
+ }
7184
+ function normalizeStateFilePath(configuredPath, fallbackPath, field, logger) {
7185
+ const sageDir = resolvedSageDir();
7186
+ const trimmed = configuredPath.trim();
7187
+ if (trimmed === "") {
7188
+ logger.warn(`Config ${field}.path is empty; using default`, {
7189
+ configuredPath,
7190
+ defaultPath: fallbackPath
7191
+ });
7192
+ return fallbackPath;
7193
+ }
7194
+ const expanded = resolvePath(trimmed);
7195
+ const resolved = (0, import_node_path.isAbsolute)(expanded) ? (0, import_node_path.resolve)(expanded) : (0, import_node_path.resolve)(sageDir, expanded);
7196
+ if (isWithinDirectory(sageDir, resolved)) {
7197
+ if (resolved === sageDir) {
7198
+ logger.warn(`Config ${field}.path must point to a file; using default`, {
7199
+ configuredPath,
7200
+ defaultPath: fallbackPath
7201
+ });
7202
+ return fallbackPath;
7203
+ }
7204
+ return resolved;
7205
+ }
7206
+ logger.warn(`Config ${field}.path escapes ${sageDir}; using default`, {
7207
+ configuredPath,
7208
+ defaultPath: fallbackPath
7209
+ });
7210
+ return fallbackPath;
7211
+ }
7212
+ var BRAND_KEY_RE = /^[a-z0-9_-]+$/u;
7213
+ function sanitizeBrandKey(data, logger) {
7214
+ const brandKey = data.brand_key;
7215
+ if (brandKey === void 0) return data;
7216
+ if (typeof brandKey === "string" && brandKey.length >= 1 && brandKey.length <= 32 && BRAND_KEY_RE.test(brandKey)) {
7217
+ return data;
7218
+ }
7219
+ logger.warn(`Invalid brand_key in config \u2014 ignoring`, { brand_key: brandKey });
7220
+ const { brand_key: _2, ...rest } = data;
7221
+ return rest;
7222
+ }
7223
+ function sanitizeConfigPaths(config, logger) {
7224
+ const cachePath = defaultCachePath();
7225
+ const exceptionsPath = defaultExceptionsPath();
7226
+ const auditPath = defaultAuditPath();
7227
+ const operationalLogPath = defaultOperationalLogPath();
7228
+ return {
7229
+ ...config,
7230
+ cache: {
7231
+ ...config.cache,
7232
+ path: normalizeStateFilePath(config.cache.path, cachePath, "cache", logger)
7233
+ },
7234
+ exceptions: {
7235
+ ...config.exceptions,
7236
+ path: normalizeStateFilePath(config.exceptions.path, exceptionsPath, "exceptions", logger)
7237
+ },
7238
+ logging: {
7239
+ ...config.logging,
7240
+ path: normalizeStateFilePath(config.logging.path, auditPath, "logging", logger)
7241
+ },
7242
+ operational_logging: {
7243
+ ...config.operational_logging,
7244
+ path: normalizeStateFilePath(
7245
+ config.operational_logging.path,
7246
+ operationalLogPath,
7247
+ "operational_logging",
7248
+ logger
7249
+ )
7250
+ }
7251
+ };
7252
+ }
7253
+ function defaultConfig(logger) {
7254
+ return sanitizeConfigPaths(ConfigSchema.parse({}), logger);
7255
+ }
7256
+ function parseConfig(raw, path, logger) {
7257
+ let data;
7258
+ try {
7259
+ data = JSON.parse(raw);
7260
+ } catch (e) {
7261
+ logger.warn(`Failed to parse config from ${path}`, { error: String(e) });
7262
+ return defaultConfig(logger);
7263
+ }
7264
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
7265
+ logger.warn(`Config file ${path} does not contain a JSON object`);
7266
+ return defaultConfig(logger);
7267
+ }
7268
+ const sanitized = sanitizeBrandKey(data, logger);
7269
+ try {
7270
+ return sanitizeConfigPaths(ConfigSchema.parse(sanitized), logger);
7271
+ } catch (e) {
7272
+ logger.warn(`Config validation failed, using defaults`, { error: String(e) });
7273
+ return defaultConfig(logger);
7274
+ }
7275
+ }
7276
+ async function loadConfig(configPath, logger = nullLogger) {
7277
+ const path = configPath ? resolvePath(configPath) : defaultConfigPath();
7278
+ try {
7279
+ return parseConfig(await getFileContent(path), path, logger);
7280
+ } catch {
7281
+ return defaultConfig(logger);
7282
+ }
7283
+ }
7156
7284
 
7157
7285
  // ../core/src/installation-id.ts
7158
7286
  var import_node_crypto = require("node:crypto");
@@ -7440,7 +7568,7 @@ var import_node_path14 = require("node:path");
7440
7568
  var import_node_url = require("node:url");
7441
7569
  var import_meta = {};
7442
7570
  function resolveVersion() {
7443
- if (true) return "0.9.0";
7571
+ if (true) return "0.11.0";
7444
7572
  try {
7445
7573
  const pkgPath = (0, import_node_path14.join)((0, import_node_path14.dirname)((0, import_node_url.fileURLToPath)(import_meta.url)), "..", "package.json");
7446
7574
  const pkg = JSON.parse(getFileContentSync(pkgPath));
@@ -7545,7 +7673,19 @@ async function ensureModelsAvailable(args) {
7545
7673
  const required = REQUIRED_MODELS_BY_SCHEMA[schema] ?? [];
7546
7674
  if (required.length === 0) return [];
7547
7675
  const missing = missingRequiredModels(schema, sageDir);
7548
- if (missing.length === 0) return [...required];
7676
+ logger.debug("Model availability check started", {
7677
+ schema,
7678
+ requiredModels: required,
7679
+ missingModels: missing
7680
+ });
7681
+ if (missing.length === 0) {
7682
+ logger.debug("Model availability check completed", {
7683
+ schema,
7684
+ result: "already_available",
7685
+ installedModels: required
7686
+ });
7687
+ return [...required];
7688
+ }
7549
7689
  const manifest = await fetchModelManifest({
7550
7690
  iid: args.iid,
7551
7691
  schema,
@@ -7555,8 +7695,15 @@ async function ensureModelsAvailable(args) {
7555
7695
  logger
7556
7696
  });
7557
7697
  if (!manifest) {
7558
- logger.debug("model manifest unavailable; skipping background download");
7559
- return required.filter((name) => !missing.includes(name));
7698
+ const installed2 = required.filter((name) => !missing.includes(name));
7699
+ logger.debug("Model availability check completed", {
7700
+ schema,
7701
+ result: "skipped",
7702
+ skippedReason: "manifest_unavailable",
7703
+ installedModels: installed2,
7704
+ missingModels: missing
7705
+ });
7706
+ return installed2;
7560
7707
  }
7561
7708
  const installed = new Set(required.filter((name) => !missing.includes(name)));
7562
7709
  for (const name of missing) {
@@ -7578,7 +7725,212 @@ async function ensureModelsAvailable(args) {
7578
7725
  logger.warn(`download of model '${name}' threw: ${err}`);
7579
7726
  }
7580
7727
  }
7581
- return [...installed];
7728
+ const installedModels = [...installed];
7729
+ logger.debug("Model availability check completed", {
7730
+ schema,
7731
+ result: "checked",
7732
+ installedModels,
7733
+ missingModels: required.filter((name) => !installed.has(name))
7734
+ });
7735
+ return installedModels;
7736
+ }
7737
+
7738
+ // ../core/src/jsonl-log-writer.ts
7739
+ var import_promises5 = require("node:fs/promises");
7740
+ var import_node_path15 = require("node:path");
7741
+ var import_promises6 = require("node:timers/promises");
7742
+ 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
+ async function shouldRotate(filePath, maxBytes, maxFiles) {
7747
+ if (maxBytes <= 0 || maxFiles <= 0) return false;
7748
+ try {
7749
+ const s3 = await (0, import_promises5.stat)(filePath);
7750
+ return s3.size >= maxBytes;
7751
+ } catch {
7752
+ return false;
7753
+ }
7754
+ }
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
+ async function rotateIfNeeded(filePath, maxBytes, maxFiles) {
7784
+ if (!await shouldRotate(filePath, maxBytes, maxFiles)) return;
7785
+ const releaseLock = await acquireRotateLock(filePath);
7786
+ if (!releaseLock) return;
7787
+ try {
7788
+ if (!await shouldRotate(filePath, maxBytes, maxFiles)) return;
7789
+ try {
7790
+ await (0, import_promises5.unlink)(`${filePath}.${maxFiles}`);
7791
+ } catch {
7792
+ }
7793
+ for (let i = maxFiles - 1; i >= 1; i--) {
7794
+ try {
7795
+ await (0, import_promises5.rename)(`${filePath}.${i}`, `${filePath}.${i + 1}`);
7796
+ } catch {
7797
+ }
7798
+ }
7799
+ try {
7800
+ await (0, import_promises5.rename)(filePath, `${filePath}.1`);
7801
+ } catch {
7802
+ }
7803
+ } finally {
7804
+ await releaseLock();
7805
+ }
7806
+ }
7807
+ async function appendJsonlEntryNow(path, config, entry) {
7808
+ await (0, import_promises5.mkdir)((0, import_node_path15.dirname)(path), { recursive: true });
7809
+ await rotateIfNeeded(path, config.max_bytes, config.max_files);
7810
+ await (0, import_promises5.appendFile)(path, `${JSON.stringify(entry)}
7811
+ `);
7812
+ }
7813
+ async function appendJsonlEntry(config, entry) {
7814
+ const path = resolvePath(config.path);
7815
+ const previousWrite = writeQueues.get(path) ?? Promise.resolve();
7816
+ const nextWrite = previousWrite.catch(() => {
7817
+ }).then(() => appendJsonlEntryNow(path, config, entry));
7818
+ writeQueues.set(path, nextWrite);
7819
+ try {
7820
+ await nextWrite;
7821
+ } finally {
7822
+ if (writeQueues.get(path) === nextWrite) writeQueues.delete(path);
7823
+ }
7824
+ }
7825
+
7826
+ // ../core/src/operational-log.ts
7827
+ var LEVEL_PRIORITY = {
7828
+ debug: 10,
7829
+ info: 20,
7830
+ warn: 30,
7831
+ error: 40
7832
+ };
7833
+ var FLUSH_TIMEOUT_MS = 250;
7834
+ function shouldLog(config, level) {
7835
+ return config.enabled && LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[config.level];
7836
+ }
7837
+ function normalizeData(data) {
7838
+ if (!data) return void 0;
7839
+ const seen = /* @__PURE__ */ new WeakSet();
7840
+ try {
7841
+ return JSON.parse(
7842
+ JSON.stringify(data, (_key, value) => {
7843
+ if (typeof value === "bigint") return value.toString();
7844
+ if (value instanceof Error) {
7845
+ return { name: value.name, message: value.message, stack: value.stack };
7846
+ }
7847
+ if (value && typeof value === "object") {
7848
+ if (seen.has(value)) return "[Circular]";
7849
+ seen.add(value);
7850
+ }
7851
+ return value;
7852
+ })
7853
+ );
7854
+ } catch {
7855
+ return { serialization_error: "Failed to serialize log data" };
7856
+ }
7857
+ }
7858
+ async function writeOperationalLogEntry(config, entry) {
7859
+ if (!shouldLog(config, entry.level)) return;
7860
+ try {
7861
+ await appendJsonlEntry(config, entry);
7862
+ } catch {
7863
+ }
7864
+ }
7865
+ function createOperationalLogger(config, runtime) {
7866
+ const pendingWrites = /* @__PURE__ */ new Set();
7867
+ function log(component, level, message, data) {
7868
+ if (!shouldLog(config, level)) return;
7869
+ const entry = {
7870
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7871
+ level,
7872
+ runtime,
7873
+ component,
7874
+ message,
7875
+ ...data ? { data: normalizeData(data) } : {}
7876
+ };
7877
+ const write = writeOperationalLogEntry(config, entry);
7878
+ pendingWrites.add(write);
7879
+ void write.finally(() => pendingWrites.delete(write));
7880
+ }
7881
+ async function flush() {
7882
+ const deadline = Date.now() + FLUSH_TIMEOUT_MS;
7883
+ while (pendingWrites.size > 0) {
7884
+ const remainingMs = deadline - Date.now();
7885
+ if (remainingMs <= 0) return;
7886
+ let timeout;
7887
+ try {
7888
+ const result = await Promise.race([
7889
+ Promise.allSettled([...pendingWrites]).then(() => "drained"),
7890
+ new Promise((resolve4) => {
7891
+ timeout = setTimeout(() => resolve4("timeout"), remainingMs);
7892
+ timeout.unref?.();
7893
+ })
7894
+ ]);
7895
+ if (result === "timeout") return;
7896
+ } finally {
7897
+ if (timeout) clearTimeout(timeout);
7898
+ }
7899
+ }
7900
+ }
7901
+ function forComponent(component) {
7902
+ return {
7903
+ debug(msg, data) {
7904
+ log(component, "debug", msg, data);
7905
+ },
7906
+ info(msg, data) {
7907
+ log(component, "info", msg, data);
7908
+ },
7909
+ warn(msg, data) {
7910
+ log(component, "warn", msg, data);
7911
+ },
7912
+ error(msg, data) {
7913
+ log(component, "error", msg, data);
7914
+ },
7915
+ flush
7916
+ };
7917
+ }
7918
+ return {
7919
+ debug(component, msg, data) {
7920
+ log(component, "debug", msg, data);
7921
+ },
7922
+ info(component, msg, data) {
7923
+ log(component, "info", msg, data);
7924
+ },
7925
+ warn(component, msg, data) {
7926
+ log(component, "warn", msg, data);
7927
+ },
7928
+ error(component, msg, data) {
7929
+ log(component, "error", msg, data);
7930
+ },
7931
+ forComponent,
7932
+ flush
7933
+ };
7582
7934
  }
7583
7935
 
7584
7936
  // ../core/src/model-download-worker.ts
@@ -7591,22 +7943,63 @@ async function readWorkerArgs() {
7591
7943
  const schema = env.SAGE_MODEL_SCHEMA || MODEL_SCHEMA_VERSION;
7592
7944
  return { sageDir, agentRuntime, agentRuntimeVersion, versionApp, schema };
7593
7945
  }
7946
+ async function createWorkerLogger(agentRuntime) {
7947
+ try {
7948
+ const config = await loadConfig();
7949
+ return createOperationalLogger(
7950
+ config.operational_logging,
7951
+ agentRuntime
7952
+ ).forComponent("model-download-worker");
7953
+ } catch {
7954
+ return nullLogger;
7955
+ }
7956
+ }
7594
7957
  async function workerMain() {
7595
7958
  const args = await readWorkerArgs();
7596
7959
  if (!args) return;
7597
- await (0, import_promises5.mkdir)(getModelStorageRoot(args.sageDir), { recursive: true }).catch(() => {
7598
- });
7599
- const iid = await getInstallationId(args.sageDir).catch(() => void 0);
7600
- if (!iid) return;
7601
- await ensureModelsAvailable({
7602
- sageDir: args.sageDir,
7603
- iid,
7604
- agentRuntime: args.agentRuntime,
7605
- agentRuntimeVersion: args.agentRuntimeVersion,
7606
- versionApp: args.versionApp,
7607
- schema: args.schema,
7608
- logger: nullLogger
7609
- });
7960
+ const logger = await createWorkerLogger(args.agentRuntime);
7961
+ try {
7962
+ logger.debug("Model download worker started", {
7963
+ schema: args.schema,
7964
+ agentRuntime: args.agentRuntime,
7965
+ agentRuntimeVersion: args.agentRuntimeVersion,
7966
+ versionApp: args.versionApp
7967
+ });
7968
+ await (0, import_promises7.mkdir)(getModelStorageRoot(args.sageDir), { recursive: true }).catch(() => {
7969
+ });
7970
+ const iid = await getInstallationId(args.sageDir).catch(() => void 0);
7971
+ if (!iid) {
7972
+ logger.debug("Model download worker completed", {
7973
+ result: "skipped",
7974
+ skippedReason: "missing_installation_id"
7975
+ });
7976
+ await logger.flush?.();
7977
+ return;
7978
+ }
7979
+ const installedModels = await ensureModelsAvailable({
7980
+ sageDir: args.sageDir,
7981
+ iid,
7982
+ agentRuntime: args.agentRuntime,
7983
+ agentRuntimeVersion: args.agentRuntimeVersion,
7984
+ versionApp: args.versionApp,
7985
+ schema: args.schema,
7986
+ logger
7987
+ });
7988
+ logger.debug("Model download worker completed", {
7989
+ result: "completed",
7990
+ installedModels
7991
+ });
7992
+ await logger.flush?.();
7993
+ } catch (error) {
7994
+ logger.error("Model download worker failed open", {
7995
+ error: String(error),
7996
+ schema: args.schema,
7997
+ agentRuntime: args.agentRuntime,
7998
+ agentRuntimeVersion: args.agentRuntimeVersion,
7999
+ versionApp: args.versionApp
8000
+ });
8001
+ await logger.flush?.();
8002
+ }
7610
8003
  }
7611
8004
  var isWorkerEntry = (() => {
7612
8005
  try {