@kenhkl/agent-moss 0.11.0 → 0.11.3

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.
@@ -32,6 +32,90 @@ var init_esm_shims = __esm({
32
32
  }
33
33
  });
34
34
 
35
+ // src/infra/paths.ts
36
+ import { join } from "path";
37
+ import { homedir } from "os";
38
+ import { readFileSync } from "fs";
39
+ function isRoot() {
40
+ const getuid = process.getuid;
41
+ return typeof getuid === "function" && getuid() === 0;
42
+ }
43
+ function resolveOwnerHome() {
44
+ for (const name of [process.env.SUDO_USER, process.env.LOGNAME, process.env.USER]) {
45
+ if (name && name !== "root" && name !== "") {
46
+ const home = homeOf(name);
47
+ if (home) return home;
48
+ }
49
+ }
50
+ try {
51
+ const passwd = readFileSync("/etc/passwd", "utf-8");
52
+ for (const line of passwd.split("\n")) {
53
+ if (!line || line.startsWith("#")) continue;
54
+ const parts = line.split(":");
55
+ if (parts.length < 6) continue;
56
+ const uid = parseInt(parts[2], 10);
57
+ const name = parts[0];
58
+ if (uid >= 1e3 && name && !name.startsWith("_")) {
59
+ return parts[5];
60
+ }
61
+ }
62
+ } catch {
63
+ }
64
+ return null;
65
+ }
66
+ function homeOf(name) {
67
+ try {
68
+ const passwd = readFileSync("/etc/passwd", "utf-8");
69
+ for (const line of passwd.split("\n")) {
70
+ if (!line || line.startsWith("#")) continue;
71
+ const parts = line.split(":");
72
+ if (parts.length >= 6 && parts[0] === name) {
73
+ return parts[5];
74
+ }
75
+ }
76
+ } catch {
77
+ }
78
+ return null;
79
+ }
80
+ function getDataRoot() {
81
+ const envPath = process.env[ENV_DATA_ROOT];
82
+ if (envPath) return envPath;
83
+ if (isRoot()) {
84
+ const ownerHome = resolveOwnerHome();
85
+ if (ownerHome) {
86
+ return join(ownerHome, ".config", "agentmoss");
87
+ }
88
+ }
89
+ return DEFAULT_DATA_ROOT;
90
+ }
91
+ function getInstance() {
92
+ const v = process.env[ENV_INSTANCE] || "";
93
+ return v.trim().replace(/^[/\\]+|[/\\]+$/g, "");
94
+ }
95
+ function getConfigDir() {
96
+ return getDataRoot();
97
+ }
98
+ function getRuntimeConfigDir() {
99
+ return getDataRoot();
100
+ }
101
+ function getTokenStatsPath() {
102
+ const instance = getInstance();
103
+ if (instance) {
104
+ return join(getDataRoot(), instance, "agent_moss_token_stats.json");
105
+ }
106
+ return join(getDataRoot(), "agent_moss_token_stats.json");
107
+ }
108
+ var ENV_DATA_ROOT, ENV_INSTANCE, DEFAULT_DATA_ROOT;
109
+ var init_paths = __esm({
110
+ "src/infra/paths.ts"() {
111
+ "use strict";
112
+ init_esm_shims();
113
+ ENV_DATA_ROOT = "AGENT_MOSS_DATA_DIR";
114
+ ENV_INSTANCE = "AGENT_MOSS_INSTANCE";
115
+ DEFAULT_DATA_ROOT = join(homedir(), ".config", "agentmoss");
116
+ }
117
+ });
118
+
35
119
  // src/config.ts
36
120
  var config_exports = {};
37
121
  __export(config_exports, {
@@ -50,7 +134,6 @@ __export(config_exports, {
50
134
  });
51
135
  import fs from "fs";
52
136
  import path2 from "path";
53
- import os from "os";
54
137
  import { fileURLToPath as fileURLToPath2 } from "url";
55
138
  function loadConfigFile(filePath) {
56
139
  try {
@@ -63,7 +146,7 @@ function loadConfigFile(filePath) {
63
146
  function resolveConfigPath() {
64
147
  const envPath = process.env.AGENT_MOSS_CONFIG_PATH;
65
148
  if (envPath) return envPath;
66
- const userConfig = path2.join(os.homedir(), ".config", "agentmoss", "config.json");
149
+ const userConfig = path2.join(getConfigDir(), "config.json");
67
150
  if (fs.existsSync(userConfig)) return userConfig;
68
151
  const defaultConfig = path2.join(__dirname, "..", "..", "agent_moss", "infra", "config.json.example");
69
152
  if (fs.existsSync(defaultConfig)) {
@@ -232,6 +315,7 @@ var init_config = __esm({
232
315
  "src/config.ts"() {
233
316
  "use strict";
234
317
  init_esm_shims();
318
+ init_paths();
235
319
  llmConfig = (() => {
236
320
  const configPath = resolveConfigPath();
237
321
  const fileConfig = fs.existsSync(configPath) ? loadLLMConfigFromFile(configPath) : {};
@@ -1062,7 +1146,7 @@ var init_logic_rules = __esm({
1062
1146
  });
1063
1147
 
1064
1148
  // src/engine/skill-loader.ts
1065
- import { readFileSync, readdirSync as readdirSync2, existsSync as existsSync2 } from "fs";
1149
+ import { readFileSync as readFileSync2, readdirSync as readdirSync2, existsSync as existsSync2 } from "fs";
1066
1150
  import { resolve, dirname } from "path";
1067
1151
  import { fileURLToPath as fileURLToPath3 } from "url";
1068
1152
  function loadAllSkills() {
@@ -1076,7 +1160,7 @@ function loadAllSkills() {
1076
1160
  const files = readdirSync2(dir).filter((f) => f.endsWith(".md"));
1077
1161
  for (const f of files) {
1078
1162
  const name = f.replace(".md", "");
1079
- cachedSkills[name] = readFileSync(resolve(dir, f), "utf-8");
1163
+ cachedSkills[name] = readFileSync2(resolve(dir, f), "utf-8");
1080
1164
  }
1081
1165
  console.log(`[AgentMoss] Loaded ${Object.keys(cachedSkills).length} skills from ${dir}`);
1082
1166
  return cachedSkills;
@@ -1207,11 +1291,13 @@ __export(runtime_config_exports, {
1207
1291
  updateSkillCategoryEnabled: () => updateSkillCategoryEnabled,
1208
1292
  updateSkillEnabled: () => updateSkillEnabled
1209
1293
  });
1210
- import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync3, mkdirSync, unlinkSync, readdirSync as readdirSync3 } from "fs";
1211
- import { join } from "path";
1212
- import { homedir } from "os";
1294
+ import { readFileSync as readFileSync3, writeFileSync, existsSync as existsSync3, mkdirSync, unlinkSync, readdirSync as readdirSync3 } from "fs";
1295
+ import { join as join2 } from "path";
1213
1296
  import { fileURLToPath as fileURLToPath4 } from "url";
1214
1297
  import { dirname as dirname2 } from "path";
1298
+ function runtimeDir() {
1299
+ return getRuntimeConfigDir();
1300
+ }
1215
1301
  function getRuntimeConfigPath() {
1216
1302
  const envPath = process.env[ENV_RUNTIME_CONFIG_PATH];
1217
1303
  if (envPath) return envPath;
@@ -1244,7 +1330,7 @@ function loadRuntimeConfig() {
1244
1330
  return seeded;
1245
1331
  }
1246
1332
  try {
1247
- const data = JSON.parse(readFileSync2(p, "utf-8"));
1333
+ const data = JSON.parse(readFileSync3(p, "utf-8"));
1248
1334
  const merged = mergeConfig(data, generateSourceDefaults());
1249
1335
  return {
1250
1336
  version: data.version || 1,
@@ -1314,7 +1400,7 @@ function hasRuntimeConfig() {
1314
1400
  const p = getRuntimeConfigPath();
1315
1401
  if (!existsSync3(p)) return false;
1316
1402
  try {
1317
- JSON.parse(readFileSync2(p, "utf-8"));
1403
+ JSON.parse(readFileSync3(p, "utf-8"));
1318
1404
  return true;
1319
1405
  } catch {
1320
1406
  return false;
@@ -1502,11 +1588,11 @@ function _agentRulesToDefaults() {
1502
1588
  return out;
1503
1589
  }
1504
1590
  for (const agentId of entries) {
1505
- const rulesFile = join(agentsDir, agentId, "rules.json");
1591
+ const rulesFile = join2(agentsDir, agentId, "rules.json");
1506
1592
  if (!existsSync3(rulesFile)) continue;
1507
1593
  let data;
1508
1594
  try {
1509
- data = JSON.parse(readFileSync2(rulesFile, "utf-8"));
1595
+ data = JSON.parse(readFileSync3(rulesFile, "utf-8"));
1510
1596
  } catch {
1511
1597
  continue;
1512
1598
  }
@@ -1922,12 +2008,12 @@ function deleteCustomRule(layer, category, ruleId) {
1922
2008
  function addCustomSkill(skillId, category, keywords, content) {
1923
2009
  _validateSkillId(skillId);
1924
2010
  const runtime = loadRuntimeConfig();
1925
- const skillsDir = join(RUNTIME_CONFIG_DIR, "agent_moss_skills");
2011
+ const skillsDir = join2(RUNTIME_CONFIG_DIR, "agent_moss_skills");
1926
2012
  try {
1927
2013
  mkdirSync(skillsDir, { recursive: true });
1928
2014
  } catch {
1929
2015
  }
1930
- writeFileSync(join(skillsDir, `${skillId}.md`), content, "utf-8");
2016
+ writeFileSync(join2(skillsDir, `${skillId}.md`), content, "utf-8");
1931
2017
  const l3 = runtime.L3_skills || (runtime.L3_skills = {});
1932
2018
  const cat = l3[category] || (l3[category] = { category_enabled: true, category_desc: "", skills: [] });
1933
2019
  (cat.skills || (cat.skills = [])).push({ id: skillId, keywords, enabled: true, builtin: false });
@@ -1942,7 +2028,7 @@ function deleteCustomSkill(skillId, category) {
1942
2028
  if (idx >= 0) {
1943
2029
  if (skills[idx].builtin) return null;
1944
2030
  skills.splice(idx, 1);
1945
- const skillPath = join(RUNTIME_CONFIG_DIR, "agent_moss_skills", `${skillId}.md`);
2031
+ const skillPath = join2(RUNTIME_CONFIG_DIR, "agent_moss_skills", `${skillId}.md`);
1946
2032
  try {
1947
2033
  if (existsSync3(skillPath)) unlinkSync(skillPath);
1948
2034
  } catch {
@@ -2058,18 +2144,19 @@ function updateAgentCategoryEnabled(agentId, category, enabled) {
2058
2144
  saveRuntimeConfig(runtime);
2059
2145
  return runtime;
2060
2146
  }
2061
- var __dirname3, RUNTIME_CONFIG_DIR, RUNTIME_CONFIG_PATH, ENV_RUNTIME_CONFIG_PATH, LAYER_DISABLE_ENV, DENY_MODE_LABELS, _AGENTS_DIR_PROD, _AGENTS_DIR_DEV, SKILL_ID_RE;
2147
+ var __dirname3, ENV_RUNTIME_CONFIG_PATH, RUNTIME_CONFIG_DIR, RUNTIME_CONFIG_PATH, LAYER_DISABLE_ENV, DENY_MODE_LABELS, _AGENTS_DIR_PROD, _AGENTS_DIR_DEV, SKILL_ID_RE;
2062
2148
  var init_runtime_config = __esm({
2063
2149
  "src/infra/runtime-config.ts"() {
2064
2150
  "use strict";
2065
2151
  init_esm_shims();
2152
+ init_paths();
2066
2153
  init_heuristic();
2067
2154
  init_logic_rules();
2068
2155
  init_skill_loader();
2069
2156
  __dirname3 = dirname2(fileURLToPath4(import.meta.url));
2070
- RUNTIME_CONFIG_DIR = join(homedir(), ".config", "agentmoss");
2071
- RUNTIME_CONFIG_PATH = join(RUNTIME_CONFIG_DIR, "agent_moss_runtime.json");
2072
2157
  ENV_RUNTIME_CONFIG_PATH = "AGENT_MOSS_RUNTIME_CONFIG_PATH";
2158
+ RUNTIME_CONFIG_DIR = runtimeDir();
2159
+ RUNTIME_CONFIG_PATH = join2(RUNTIME_CONFIG_DIR, "agent_moss_runtime.json");
2073
2160
  LAYER_DISABLE_ENV = {
2074
2161
  L1_heuristic: "AGENT_MOSS_DISABLE_HEURISTIC",
2075
2162
  L2_logic_rules: "AGENT_MOSS_DISABLE_LOGIC_RULES",
@@ -2080,14 +2167,14 @@ var init_runtime_config = __esm({
2080
2167
  deny_read: "\u4EC5\u62E6\u622A\u8BFB\u53D6",
2081
2168
  deny_both: "\u8BFB\u5199\u5747\u62E6\u622A"
2082
2169
  };
2083
- _AGENTS_DIR_PROD = join(__dirname3, "agents");
2084
- _AGENTS_DIR_DEV = join(__dirname3, "..", "..", "..", "agent_moss", "agents");
2170
+ _AGENTS_DIR_PROD = join2(__dirname3, "agents");
2171
+ _AGENTS_DIR_DEV = join2(__dirname3, "..", "..", "..", "agent_moss", "agents");
2085
2172
  SKILL_ID_RE = /^[A-Za-z0-9_-]+$/;
2086
2173
  }
2087
2174
  });
2088
2175
 
2089
2176
  // src/agents/index.ts
2090
- import { readFileSync as readFileSync3, existsSync as existsSync4 } from "fs";
2177
+ import { readFileSync as readFileSync4, existsSync as existsSync4 } from "fs";
2091
2178
  import { resolve as resolve2, dirname as dirname3 } from "path";
2092
2179
  import { fileURLToPath as fileURLToPath5 } from "url";
2093
2180
  function resolveAgentsDir() {
@@ -2114,7 +2201,7 @@ function getAgentExtensions(agentId) {
2114
2201
  return null;
2115
2202
  }
2116
2203
  try {
2117
- const raw = readFileSync3(rulesFile, "utf-8");
2204
+ const raw = readFileSync4(rulesFile, "utf-8");
2118
2205
  ext = JSON.parse(raw);
2119
2206
  if (!ext.agent_id) {
2120
2207
  console.warn(`[AgentMoss agents] rules.json \u7F3A\u5C11 agent_id \u5B57\u6BB5: ${rulesFile}`);
@@ -2762,17 +2849,16 @@ __export(token_stats_exports, {
2762
2849
  recordTokenUsage: () => recordTokenUsage,
2763
2850
  resetTokenStats: () => resetTokenStats
2764
2851
  });
2765
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync2, existsSync as existsSync7, mkdirSync as mkdirSync2, unlinkSync as unlinkSync2 } from "fs";
2766
- import { join as join4 } from "path";
2767
- import { homedir as homedir3 } from "os";
2852
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync2, existsSync as existsSync7, mkdirSync as mkdirSync2, unlinkSync as unlinkSync2 } from "fs";
2768
2853
  function getStatsPath() {
2769
2854
  const envPath = process.env[ENV_STATS_PATH];
2770
- return envPath || STATS_FILE;
2855
+ if (envPath) return envPath;
2856
+ return getTokenStatsPath();
2771
2857
  }
2772
2858
  function loadAllRecords(statsPath) {
2773
2859
  if (!existsSync7(statsPath)) return [];
2774
2860
  try {
2775
- const data = JSON.parse(readFileSync7(statsPath, "utf-8"));
2861
+ const data = JSON.parse(readFileSync8(statsPath, "utf-8"));
2776
2862
  if (Array.isArray(data)) return data;
2777
2863
  if (data && Array.isArray(data.records)) return data.records;
2778
2864
  return [];
@@ -2912,13 +2998,12 @@ function resetTokenStats() {
2912
2998
  }
2913
2999
  }
2914
3000
  }
2915
- var STATS_DIR, STATS_FILE, ENV_STATS_PATH, MAX_RECORDS;
3001
+ var ENV_STATS_PATH, MAX_RECORDS;
2916
3002
  var init_token_stats = __esm({
2917
3003
  "src/engine/token-stats.ts"() {
2918
3004
  "use strict";
2919
3005
  init_esm_shims();
2920
- STATS_DIR = join4(homedir3(), ".config", "agentmoss");
2921
- STATS_FILE = join4(STATS_DIR, "agent_moss_token_stats.json");
3006
+ init_paths();
2922
3007
  ENV_STATS_PATH = "AGENT_MOSS_TOKEN_STATS_PATH";
2923
3008
  MAX_RECORDS = 1e4;
2924
3009
  }
@@ -2937,7 +3022,7 @@ init_skill_loader();
2937
3022
 
2938
3023
  // src/engine/template-loader.ts
2939
3024
  init_esm_shims();
2940
- import { readFileSync as readFileSync4, existsSync as existsSync5 } from "fs";
3025
+ import { readFileSync as readFileSync5, existsSync as existsSync5 } from "fs";
2941
3026
  import { resolve as resolve3, dirname as dirname4 } from "path";
2942
3027
  import { fileURLToPath as fileURLToPath6 } from "url";
2943
3028
  var __filename4 = fileURLToPath6(import.meta.url);
@@ -2958,7 +3043,7 @@ function loadTemplates() {
2958
3043
  const filePath = resolve3(dir, file);
2959
3044
  if (existsSync5(filePath)) {
2960
3045
  const key = file.replace(".txt", "").replace("_template", "");
2961
- cachedTemplates[key] = readFileSync4(filePath, "utf-8");
3046
+ cachedTemplates[key] = readFileSync5(filePath, "utf-8");
2962
3047
  }
2963
3048
  }
2964
3049
  console.log(`[AgentMoss] Loaded ${Object.keys(cachedTemplates).length} templates from ${dir}`);
@@ -2967,8 +3052,8 @@ function loadTemplates() {
2967
3052
 
2968
3053
  // src/engine/script-analyzer.ts
2969
3054
  init_esm_shims();
2970
- import { readFileSync as readFileSync5 } from "fs";
2971
- import { resolve as resolve4, join as join2 } from "path";
3055
+ import { readFileSync as readFileSync6 } from "fs";
3056
+ import { resolve as resolve4, join as join3 } from "path";
2972
3057
  var SUSPICIOUS_PATTERNS = [
2973
3058
  // Network exfiltration (curl/wget POST in scripts is almost never legitimate)
2974
3059
  { name: "curl POST", pattern: /curl\s+(.*\s)?-X\s+POST/i },
@@ -3101,8 +3186,8 @@ function assessKeywordCombinationRisk(matchedKeywords, scriptContent) {
3101
3186
  }
3102
3187
  function readScriptContent(scriptPath, maxLines = 500) {
3103
3188
  try {
3104
- const expandedPath = scriptPath.startsWith("~") ? join2(process.env.HOME || "/home/user", scriptPath.slice(2)) : resolve4(scriptPath);
3105
- const raw = readFileSync5(expandedPath, "utf-8");
3189
+ const expandedPath = scriptPath.startsWith("~") ? join3(process.env.HOME || "/home/user", scriptPath.slice(2)) : resolve4(scriptPath);
3190
+ const raw = readFileSync6(expandedPath, "utf-8");
3106
3191
  const lines = raw.split("\n").slice(0, maxLines);
3107
3192
  return { content: lines.join("\n"), lineCount: lines.length, error: "" };
3108
3193
  } catch (e) {
@@ -3156,8 +3241,8 @@ ${result.scriptContent}
3156
3241
  init_esm_shims();
3157
3242
  init_heuristic();
3158
3243
  init_logic_rules();
3159
- import { readFileSync as readFileSync6, statSync, existsSync as existsSync6 } from "fs";
3160
- import { resolve as resolve5, join as join3, isAbsolute, dirname as dirname5 } from "path";
3244
+ import { readFileSync as readFileSync7, statSync, existsSync as existsSync6 } from "fs";
3245
+ import { resolve as resolve5, join as join4, isAbsolute, dirname as dirname5 } from "path";
3161
3246
  import { homedir as homedir2 } from "os";
3162
3247
  function emptyChain() {
3163
3248
  return {
@@ -3398,7 +3483,7 @@ function extractInlineScriptPath(actionDetail) {
3398
3483
  function resolvePath(p) {
3399
3484
  let expanded = p;
3400
3485
  if (expanded.startsWith("~/") || expanded === "~") {
3401
- expanded = join3(homedir2(), expanded.slice(1));
3486
+ expanded = join4(homedir2(), expanded.slice(1));
3402
3487
  }
3403
3488
  return resolve5(expanded);
3404
3489
  }
@@ -3411,7 +3496,7 @@ function readScriptContent2(scriptPath, maxFileSize = 2 * 1024 * 1024) {
3411
3496
  if (stat.size > maxFileSize) {
3412
3497
  return { content: "", lineCount: 0, fileSize: stat.size, error: `\u811A\u672C\u6587\u4EF6\u8FC7\u5927 (${stat.size} bytes)\uFF0C\u8DF3\u8FC7\u8BFB\u53D6` };
3413
3498
  }
3414
- const content = readFileSync6(path3, "utf-8");
3499
+ const content = readFileSync7(path3, "utf-8");
3415
3500
  const lineCount = content ? content.split("\n").length : 0;
3416
3501
  return { content, lineCount, fileSize: stat.size, error: "" };
3417
3502
  } catch (e) {
@@ -3428,7 +3513,7 @@ function extractChildScriptPaths(content, baseDir) {
3428
3513
  const pathStr = m[1];
3429
3514
  if (pathStr.startsWith("-") || pathStr.startsWith("$")) continue;
3430
3515
  if (pathStr.includes("/dev/") || pathStr.startsWith("|") || pathStr.startsWith(";")) continue;
3431
- const full = isAbsolute(pathStr) ? pathStr : join3(baseDir, pathStr);
3516
+ const full = isAbsolute(pathStr) ? pathStr : join4(baseDir, pathStr);
3432
3517
  const resolved = resolvePath(full);
3433
3518
  if (existsSync6(resolved)) {
3434
3519
  try {