@kenhkl/agent-moss 0.16.12 → 0.16.13
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 +3 -0
- package/dist/cli.js +213 -65
- package/dist/data/agent_moss.service +4 -0
- package/dist/engine/coordinator.js +134 -25
- package/dist/server.js +213 -65
- package/dist/static/index.html +26 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -394,6 +394,52 @@ var init_runtime_config_bridge = __esm({
|
|
|
394
394
|
}
|
|
395
395
|
});
|
|
396
396
|
|
|
397
|
+
// src/infra/rules-mode.ts
|
|
398
|
+
function truthy(name) {
|
|
399
|
+
return TRUTHY.has((process.env[name] || "").trim().toLowerCase());
|
|
400
|
+
}
|
|
401
|
+
function getRulesMode() {
|
|
402
|
+
if (cached !== null) return cached;
|
|
403
|
+
const raw = (process.env[ENV_RULES_MODE] || "").trim().toLowerCase();
|
|
404
|
+
if (raw) {
|
|
405
|
+
if (VALID_MODES.has(raw)) {
|
|
406
|
+
cached = raw;
|
|
407
|
+
} else {
|
|
408
|
+
console.error(
|
|
409
|
+
`[AgentMoss] ${ENV_RULES_MODE}=${JSON.stringify(raw)} \u975E\u6CD5\uFF08\u53EA\u652F\u6301 hot / cold / builtin\uFF09\uFF1B\u4E3A\u5B89\u5168\u8D77\u89C1\u6309 builtin\uFF08\u4EC5\u5185\u7F6E\u89C4\u5219\uFF09\u5904\u7406`
|
|
410
|
+
);
|
|
411
|
+
cached = "builtin";
|
|
412
|
+
}
|
|
413
|
+
return cached;
|
|
414
|
+
}
|
|
415
|
+
if (truthy(ENV_RULES_BUILTIN_ONLY)) cached = "builtin";
|
|
416
|
+
else if (truthy(ENV_DISABLE_RULE_HOT_RELOAD)) cached = "cold";
|
|
417
|
+
else cached = "hot";
|
|
418
|
+
return cached;
|
|
419
|
+
}
|
|
420
|
+
function isHotReloadEnabled() {
|
|
421
|
+
return getRulesMode() === "hot";
|
|
422
|
+
}
|
|
423
|
+
function isRuntimeConfigDisabled() {
|
|
424
|
+
return getRulesMode() !== "hot";
|
|
425
|
+
}
|
|
426
|
+
function isBuiltinOnly() {
|
|
427
|
+
return getRulesMode() === "builtin";
|
|
428
|
+
}
|
|
429
|
+
var ENV_RULES_MODE, ENV_RULES_BUILTIN_ONLY, ENV_DISABLE_RULE_HOT_RELOAD, TRUTHY, VALID_MODES, cached;
|
|
430
|
+
var init_rules_mode = __esm({
|
|
431
|
+
"src/infra/rules-mode.ts"() {
|
|
432
|
+
"use strict";
|
|
433
|
+
init_esm_shims();
|
|
434
|
+
ENV_RULES_MODE = "AGENT_MOSS_RULES_MODE";
|
|
435
|
+
ENV_RULES_BUILTIN_ONLY = "AGENT_MOSS_RULES_BUILTIN_ONLY";
|
|
436
|
+
ENV_DISABLE_RULE_HOT_RELOAD = "AGENT_MOSS_DISABLE_RULE_HOT_RELOAD";
|
|
437
|
+
TRUTHY = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
438
|
+
VALID_MODES = /* @__PURE__ */ new Set(["hot", "cold", "builtin"]);
|
|
439
|
+
cached = null;
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
|
|
397
443
|
// src/infra/rules-loader.ts
|
|
398
444
|
import { readFileSync as readFileSync2, existsSync, readdirSync, statSync } from "fs";
|
|
399
445
|
import { resolve, dirname, join as join2 } from "path";
|
|
@@ -407,6 +453,7 @@ function parseDirEnv(envName) {
|
|
|
407
453
|
return raw.split(/[,;]/).map((s) => s.trim()).filter(Boolean).map((s) => resolve(s));
|
|
408
454
|
}
|
|
409
455
|
function rulesDirs() {
|
|
456
|
+
if (isBuiltinOnly()) return [];
|
|
410
457
|
const dirs = [];
|
|
411
458
|
for (const env of RULES_DIR_ENVS) dirs.push(...parseDirEnv(env));
|
|
412
459
|
dirs.push(resolve(dataRootDir(), "rules"));
|
|
@@ -420,10 +467,16 @@ function findRulesFile(name) {
|
|
|
420
467
|
return null;
|
|
421
468
|
}
|
|
422
469
|
function loadJson(name) {
|
|
470
|
+
if (!isHotReloadEnabled()) {
|
|
471
|
+
const cached2 = frozenJsonCache.get(name);
|
|
472
|
+
if (cached2 !== void 0) return cached2;
|
|
473
|
+
}
|
|
423
474
|
const p = findRulesFile(name);
|
|
424
475
|
if (!p) return {};
|
|
425
476
|
try {
|
|
426
|
-
|
|
477
|
+
const parsed = JSON.parse(readFileSync2(p, "utf-8")) || {};
|
|
478
|
+
if (!isHotReloadEnabled()) frozenJsonCache.set(name, parsed);
|
|
479
|
+
return parsed;
|
|
427
480
|
} catch {
|
|
428
481
|
return {};
|
|
429
482
|
}
|
|
@@ -748,6 +801,7 @@ function scanRuleDirs() {
|
|
|
748
801
|
return { override, extra, loaded, ignored };
|
|
749
802
|
}
|
|
750
803
|
function rulesCached() {
|
|
804
|
+
if (!isHotReloadEnabled() && _RULES_CACHE) return _RULES_CACHE;
|
|
751
805
|
const dirs = rulesDirs();
|
|
752
806
|
const sig = RULES_DIR_ENVS.map((e) => `${e}=${process.env[e] || ""}`).join("|") + "|" + dirs.join("|");
|
|
753
807
|
const files = [];
|
|
@@ -783,9 +837,11 @@ function identicalToBuiltin(override) {
|
|
|
783
837
|
return Object.keys(override).length > 0;
|
|
784
838
|
}
|
|
785
839
|
function loadOverrideRules() {
|
|
840
|
+
if (isBuiltinOnly()) return {};
|
|
786
841
|
return rulesCached().override;
|
|
787
842
|
}
|
|
788
843
|
function loadExtraRules() {
|
|
844
|
+
if (isBuiltinOnly()) return {};
|
|
789
845
|
return rulesCached().extra;
|
|
790
846
|
}
|
|
791
847
|
function ruleFilesLoaded() {
|
|
@@ -794,12 +850,13 @@ function ruleFilesLoaded() {
|
|
|
794
850
|
function ignoredRuleFiles() {
|
|
795
851
|
return rulesCached().ignored;
|
|
796
852
|
}
|
|
797
|
-
var __filename2, __dirname2, OVERRIDE_FILENAME, EXTRA_FILENAME, RULES_DIR_ENVS, RULES_DIR_CANDS, SCENARIO_LIST_KEYS, EXTRA_CATEGORIES, STRUCT_KEYS, EXTRA_FLAT_FIELD, _RULES_CACHE, warnedIgnored;
|
|
853
|
+
var __filename2, __dirname2, OVERRIDE_FILENAME, EXTRA_FILENAME, RULES_DIR_ENVS, RULES_DIR_CANDS, frozenJsonCache, SCENARIO_LIST_KEYS, EXTRA_CATEGORIES, STRUCT_KEYS, EXTRA_FLAT_FIELD, _RULES_CACHE, warnedIgnored;
|
|
798
854
|
var init_rules_loader = __esm({
|
|
799
855
|
"src/infra/rules-loader.ts"() {
|
|
800
856
|
"use strict";
|
|
801
857
|
init_esm_shims();
|
|
802
858
|
init_paths();
|
|
859
|
+
init_rules_mode();
|
|
803
860
|
init_runtime_config_bridge();
|
|
804
861
|
__filename2 = fileURLToPath2(import.meta.url);
|
|
805
862
|
__dirname2 = dirname(__filename2);
|
|
@@ -822,6 +879,7 @@ var init_rules_loader = __esm({
|
|
|
822
879
|
];
|
|
823
880
|
return cands.filter((c) => existsSync(c));
|
|
824
881
|
})();
|
|
882
|
+
frozenJsonCache = /* @__PURE__ */ new Map();
|
|
825
883
|
SCENARIO_LIST_KEYS = ["extra_command_patterns", "extra_injection_keywords", "extra_sensitive_paths"];
|
|
826
884
|
EXTRA_CATEGORIES = {
|
|
827
885
|
dangerous_commands: ["pattern"],
|
|
@@ -1904,6 +1962,7 @@ function userSkillsDir() {
|
|
|
1904
1962
|
return resolve3(getDataRoot(), "agent_moss_skills");
|
|
1905
1963
|
}
|
|
1906
1964
|
function runtimeCustomSkillKeywords() {
|
|
1965
|
+
if (isRuntimeConfigDisabled()) return {};
|
|
1907
1966
|
try {
|
|
1908
1967
|
const rt = runtimeConfigBridge.current?.loadRuntimeConfig?.();
|
|
1909
1968
|
if (!rt) return {};
|
|
@@ -1921,6 +1980,7 @@ function runtimeCustomSkillKeywords() {
|
|
|
1921
1980
|
}
|
|
1922
1981
|
}
|
|
1923
1982
|
function loadUserSkill(name) {
|
|
1983
|
+
if (isRuntimeConfigDisabled()) return "";
|
|
1924
1984
|
if (userSkillCache[name] !== void 0) return userSkillCache[name];
|
|
1925
1985
|
try {
|
|
1926
1986
|
const p = resolve3(userSkillsDir(), `${name}.md`);
|
|
@@ -1989,6 +2049,7 @@ var init_skill_loader = __esm({
|
|
|
1989
2049
|
init_esm_shims();
|
|
1990
2050
|
init_rules_loader();
|
|
1991
2051
|
init_paths();
|
|
2052
|
+
init_rules_mode();
|
|
1992
2053
|
init_asset_dir();
|
|
1993
2054
|
init_runtime_config_bridge();
|
|
1994
2055
|
__filename3 = fileURLToPath3(import.meta.url);
|
|
@@ -2049,6 +2110,7 @@ __export(runtime_config_exports, {
|
|
|
2049
2110
|
getEnabledScenarioExtensions: () => getEnabledScenarioExtensions,
|
|
2050
2111
|
getEnvOverrides: () => getEnvOverrides,
|
|
2051
2112
|
getProfileOrDetect: () => getProfileOrDetect,
|
|
2113
|
+
getRuleSourceFingerprint: () => getRuleSourceFingerprint,
|
|
2052
2114
|
getRuntimeConfigPath: () => getRuntimeConfigPath,
|
|
2053
2115
|
getScenarioRules: () => getScenarioRules,
|
|
2054
2116
|
hasRuntimeConfig: () => hasRuntimeConfig,
|
|
@@ -2083,7 +2145,22 @@ function getRuntimeConfigPath() {
|
|
|
2083
2145
|
if (envPath) return envPath;
|
|
2084
2146
|
return RUNTIME_CONFIG_PATH;
|
|
2085
2147
|
}
|
|
2148
|
+
function getRuleSourceFingerprint() {
|
|
2149
|
+
if (isRuntimeConfigDisabled()) return `mode:${getRulesMode()}`;
|
|
2150
|
+
const p = getRuntimeConfigPath();
|
|
2151
|
+
try {
|
|
2152
|
+
const st = statSync2(p);
|
|
2153
|
+
return `${p}|${st.mtimeMs}|${st.size}`;
|
|
2154
|
+
} catch {
|
|
2155
|
+
return `${p}|absent`;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2086
2158
|
function saveRuntimeConfig(config) {
|
|
2159
|
+
if (isRuntimeConfigDisabled()) {
|
|
2160
|
+
throw new Error(
|
|
2161
|
+
`\u89C4\u5219\u6765\u6E90\u6A21\u5F0F\u4E3A ${getRulesMode()}\uFF08runtime \u914D\u7F6E\u5DF2\u7981\u7528\uFF09\uFF1A\u4FEE\u6539\u89C4\u5219\u4E0D\u4F1A\u751F\u6548\uFF0C\u8BF7\u5207\u6362\u89C4\u5219\u6765\u6E90\u6A21\u5F0F\u5E76\u91CD\u542F\u670D\u52A1\u3002`
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
2087
2164
|
const p = getRuntimeConfigPath();
|
|
2088
2165
|
const dir = p.substring(0, p.lastIndexOf("/"));
|
|
2089
2166
|
if (dir && !existsSync5(dir)) mkdirSync(dir, { recursive: true });
|
|
@@ -2107,6 +2184,18 @@ function invalidateRuntimeConfigCache() {
|
|
|
2107
2184
|
hasRuntimeConfigCache.clear();
|
|
2108
2185
|
}
|
|
2109
2186
|
function loadRuntimeConfig() {
|
|
2187
|
+
if (isRuntimeConfigDisabled()) {
|
|
2188
|
+
return {
|
|
2189
|
+
version: 1,
|
|
2190
|
+
layers: { ...DEFAULT_LAYERS },
|
|
2191
|
+
L1_rules: {},
|
|
2192
|
+
L2_rules: {},
|
|
2193
|
+
L3_skills: {},
|
|
2194
|
+
L2_2: {},
|
|
2195
|
+
agent_rules: {},
|
|
2196
|
+
scenario_rules: {}
|
|
2197
|
+
};
|
|
2198
|
+
}
|
|
2110
2199
|
const p = getRuntimeConfigPath();
|
|
2111
2200
|
if (!existsSync5(p)) {
|
|
2112
2201
|
const seeded = mergeConfig({}, generateSourceDefaults());
|
|
@@ -2153,6 +2242,7 @@ function loadRuntimeConfig() {
|
|
|
2153
2242
|
function isLayerEnabled(layerKey) {
|
|
2154
2243
|
const disableKey = LAYER_DISABLE_ENV[layerKey];
|
|
2155
2244
|
if (disableKey && process.env[disableKey] === "1") return false;
|
|
2245
|
+
if (isRuntimeConfigDisabled()) return true;
|
|
2156
2246
|
const runtime = loadRuntimeConfig();
|
|
2157
2247
|
const layers = runtime.layers || {};
|
|
2158
2248
|
if (layerKey in layers) return !!layers[layerKey];
|
|
@@ -2253,6 +2343,7 @@ function getEnabledL2SensitivePaths(runtime, osType) {
|
|
|
2253
2343
|
});
|
|
2254
2344
|
}
|
|
2255
2345
|
function hasRuntimeConfig() {
|
|
2346
|
+
if (isRuntimeConfigDisabled()) return false;
|
|
2256
2347
|
const p = getRuntimeConfigPath();
|
|
2257
2348
|
let key;
|
|
2258
2349
|
try {
|
|
@@ -2261,8 +2352,8 @@ function hasRuntimeConfig() {
|
|
|
2261
2352
|
} catch {
|
|
2262
2353
|
return false;
|
|
2263
2354
|
}
|
|
2264
|
-
const
|
|
2265
|
-
if (
|
|
2355
|
+
const cached2 = hasRuntimeConfigCache.get(key);
|
|
2356
|
+
if (cached2 !== void 0) return cached2;
|
|
2266
2357
|
let ok = false;
|
|
2267
2358
|
try {
|
|
2268
2359
|
JSON.parse(readFileSync4(p, "utf-8"));
|
|
@@ -3142,6 +3233,11 @@ function deleteCustomRule(layer, category, ruleId) {
|
|
|
3142
3233
|
}
|
|
3143
3234
|
function addCustomSkill(skillId, category, keywords, content) {
|
|
3144
3235
|
_validateSkillId(skillId);
|
|
3236
|
+
if (isRuntimeConfigDisabled()) {
|
|
3237
|
+
throw new Error(
|
|
3238
|
+
`\u89C4\u5219\u6765\u6E90\u6A21\u5F0F\u4E3A ${getRulesMode()}\uFF08runtime \u914D\u7F6E\u5DF2\u7981\u7528\uFF09\uFF0C\u4E0D\u5141\u8BB8\u65B0\u589E\u81EA\u5B9A\u4E49 skill\u3002`
|
|
3239
|
+
);
|
|
3240
|
+
}
|
|
3145
3241
|
const runtime = loadRuntimeConfig();
|
|
3146
3242
|
const skillsDir = join3(getRuntimeConfigDir(), "agent_moss_skills");
|
|
3147
3243
|
try {
|
|
@@ -3368,6 +3464,7 @@ var init_runtime_config = __esm({
|
|
|
3368
3464
|
init_skill_loader();
|
|
3369
3465
|
init_rules_loader();
|
|
3370
3466
|
init_runtime_config_bridge();
|
|
3467
|
+
init_rules_mode();
|
|
3371
3468
|
__dirname4 = dirname3(fileURLToPath4(import.meta.url));
|
|
3372
3469
|
ENV_RUNTIME_CONFIG_PATH = "AGENT_MOSS_RUNTIME_CONFIG_PATH";
|
|
3373
3470
|
RUNTIME_CONFIG_DIR = runtimeDir();
|
|
@@ -3439,6 +3536,7 @@ __export(config_exports, {
|
|
|
3439
3536
|
isPolicyGenEnabled: () => isPolicyGenEnabled,
|
|
3440
3537
|
isPolicySaveEnabled: () => isPolicySaveEnabled,
|
|
3441
3538
|
probeLLMConnection: () => probeLLMConnection,
|
|
3539
|
+
reloadCustomRules: () => reloadCustomRules,
|
|
3442
3540
|
updateLLMConfig: () => updateLLMConfig,
|
|
3443
3541
|
userRuleVariantPattern: () => userRuleVariantPattern,
|
|
3444
3542
|
wildcardToRegExp: () => wildcardToRegExp
|
|
@@ -3519,17 +3617,19 @@ function wildcardToRegExp(pattern) {
|
|
|
3519
3617
|
}
|
|
3520
3618
|
function loadCustomRules() {
|
|
3521
3619
|
const rules = [];
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3620
|
+
if (!isBuiltinOnly()) {
|
|
3621
|
+
try {
|
|
3622
|
+
const raw = process.env.AGENT_MOSS_CUSTOM_RULES;
|
|
3623
|
+
if (raw) {
|
|
3624
|
+
const parsed = JSON.parse(raw);
|
|
3625
|
+
if (Array.isArray(parsed)) {
|
|
3626
|
+
for (const r of parsed) {
|
|
3627
|
+
if (r && r.pattern && r.action) rules.push({ pattern: r.pattern, action: r.action, severity: r.severity || "high" });
|
|
3628
|
+
}
|
|
3529
3629
|
}
|
|
3530
3630
|
}
|
|
3631
|
+
} catch {
|
|
3531
3632
|
}
|
|
3532
|
-
} catch {
|
|
3533
3633
|
}
|
|
3534
3634
|
for (const rulesPath of USER_RULES_PATHS) {
|
|
3535
3635
|
try {
|
|
@@ -3558,6 +3658,9 @@ function userRuleVariantPattern(pattern) {
|
|
|
3558
3658
|
}
|
|
3559
3659
|
return null;
|
|
3560
3660
|
}
|
|
3661
|
+
function reloadCustomRules() {
|
|
3662
|
+
customRules = loadCustomRules();
|
|
3663
|
+
}
|
|
3561
3664
|
function getLLMConfig() {
|
|
3562
3665
|
return llmConfig;
|
|
3563
3666
|
}
|
|
@@ -3645,6 +3748,7 @@ function layerEnabledOrDefault(key) {
|
|
|
3645
3748
|
}
|
|
3646
3749
|
}
|
|
3647
3750
|
function isBrainEnabled() {
|
|
3751
|
+
if (isRuntimeConfigDisabled()) return false;
|
|
3648
3752
|
return getAgentMossSetting("AGENT_MOSS_BRAIN_ENABLED", "") === "1";
|
|
3649
3753
|
}
|
|
3650
3754
|
function getAgentMossSetting(key, def = "") {
|
|
@@ -3686,6 +3790,7 @@ var init_config = __esm({
|
|
|
3686
3790
|
init_esm_shims();
|
|
3687
3791
|
init_paths();
|
|
3688
3792
|
init_runtime_config();
|
|
3793
|
+
init_rules_mode();
|
|
3689
3794
|
__configModuleDir = (() => {
|
|
3690
3795
|
try {
|
|
3691
3796
|
return path2.dirname(fileURLToPath5(import.meta.url));
|
|
@@ -3742,7 +3847,9 @@ function resolveAgentsDir() {
|
|
|
3742
3847
|
}
|
|
3743
3848
|
function getAgentExtensions(agentId) {
|
|
3744
3849
|
if (!agentId) return null;
|
|
3745
|
-
|
|
3850
|
+
const fp = getRuleSourceFingerprint();
|
|
3851
|
+
const cached2 = cache.get(agentId);
|
|
3852
|
+
if (cached2 && cached2.fp === fp) return cached2.ext;
|
|
3746
3853
|
let ext = null;
|
|
3747
3854
|
try {
|
|
3748
3855
|
if (hasRuntimeConfig()) {
|
|
@@ -3754,7 +3861,7 @@ function getAgentExtensions(agentId) {
|
|
|
3754
3861
|
const agentsDir = resolveAgentsDir();
|
|
3755
3862
|
const rulesFile = resolve4(agentsDir, agentId, "rules.json");
|
|
3756
3863
|
if (!existsSync6(rulesFile)) {
|
|
3757
|
-
cache.set(agentId, null);
|
|
3864
|
+
cache.set(agentId, { fp, ext: null });
|
|
3758
3865
|
return null;
|
|
3759
3866
|
}
|
|
3760
3867
|
try {
|
|
@@ -3762,16 +3869,16 @@ function getAgentExtensions(agentId) {
|
|
|
3762
3869
|
ext = JSON.parse(raw);
|
|
3763
3870
|
if (!ext.agent_id) {
|
|
3764
3871
|
console.warn(`[AgentMoss agents] rules.json \u7F3A\u5C11 agent_id \u5B57\u6BB5: ${rulesFile}`);
|
|
3765
|
-
cache.set(agentId, null);
|
|
3872
|
+
cache.set(agentId, { fp, ext: null });
|
|
3766
3873
|
return null;
|
|
3767
3874
|
}
|
|
3768
3875
|
} catch (e) {
|
|
3769
3876
|
console.error(`[AgentMoss agents] \u52A0\u8F7D agent ${agentId} rules.json \u5931\u8D25:`, e.message);
|
|
3770
|
-
cache.set(agentId, null);
|
|
3877
|
+
cache.set(agentId, { fp, ext: null });
|
|
3771
3878
|
return null;
|
|
3772
3879
|
}
|
|
3773
3880
|
}
|
|
3774
|
-
cache.set(agentId, ext);
|
|
3881
|
+
cache.set(agentId, { fp, ext });
|
|
3775
3882
|
console.error(
|
|
3776
3883
|
`[AgentMoss agents] \u52A0\u8F7D agent ${agentId} \u5B9A\u5236\u89C4\u5219: ${ext.extra_command_patterns?.length ?? 0} cmd patterns, ${ext.extra_injection_keywords?.length ?? 0} injection keywords, ${ext.extra_sensitive_paths?.length ?? 0} sensitive paths, ${ext.builtin_safe_skills?.length ?? 0} builtin safe skills, ${ext.builtin_safe_action_types?.length ?? 0} builtin safe action types`
|
|
3777
3884
|
);
|
|
@@ -3817,7 +3924,9 @@ function resolveScenariosDir() {
|
|
|
3817
3924
|
}
|
|
3818
3925
|
function getScenarioExtensions(scenarioId) {
|
|
3819
3926
|
if (!scenarioId) return null;
|
|
3820
|
-
|
|
3927
|
+
const fp = getRuleSourceFingerprint();
|
|
3928
|
+
const cached2 = cache2.get(scenarioId);
|
|
3929
|
+
if (cached2 && cached2.fp === fp) return cached2.ext;
|
|
3821
3930
|
let ext = null;
|
|
3822
3931
|
let overrideHit = null;
|
|
3823
3932
|
try {
|
|
@@ -3841,7 +3950,7 @@ function getScenarioExtensions(scenarioId) {
|
|
|
3841
3950
|
);
|
|
3842
3951
|
}
|
|
3843
3952
|
if (!existsSync7(rulesFile)) {
|
|
3844
|
-
cache2.set(scenarioId, null);
|
|
3953
|
+
cache2.set(scenarioId, { fp, ext: null });
|
|
3845
3954
|
return null;
|
|
3846
3955
|
}
|
|
3847
3956
|
try {
|
|
@@ -3850,7 +3959,7 @@ function getScenarioExtensions(scenarioId) {
|
|
|
3850
3959
|
const id = data.scenario_id || data.agent_id || "";
|
|
3851
3960
|
if (!id) {
|
|
3852
3961
|
console.warn(`[AgentMoss scenarios] rules.json \u7F3A\u5C11 scenario_id \u5B57\u6BB5: ${rulesFile}`);
|
|
3853
|
-
cache2.set(scenarioId, null);
|
|
3962
|
+
cache2.set(scenarioId, { fp, ext: null });
|
|
3854
3963
|
return null;
|
|
3855
3964
|
}
|
|
3856
3965
|
ext = {
|
|
@@ -3865,11 +3974,11 @@ function getScenarioExtensions(scenarioId) {
|
|
|
3865
3974
|
};
|
|
3866
3975
|
} catch (e) {
|
|
3867
3976
|
console.error(`[AgentMoss scenarios] \u52A0\u8F7D\u573A\u666F ${scenarioId} rules.json \u5931\u8D25:`, e.message);
|
|
3868
|
-
cache2.set(scenarioId, null);
|
|
3977
|
+
cache2.set(scenarioId, { fp, ext: null });
|
|
3869
3978
|
return null;
|
|
3870
3979
|
}
|
|
3871
3980
|
}
|
|
3872
|
-
cache2.set(scenarioId, ext);
|
|
3981
|
+
cache2.set(scenarioId, { fp, ext });
|
|
3873
3982
|
console.error(
|
|
3874
3983
|
`[AgentMoss scenarios] \u52A0\u8F7D\u573A\u666F ${scenarioId} \u5B9A\u5236\u89C4\u5219: ${ext.extra_command_patterns?.length ?? 0} cmd patterns, ${ext.extra_injection_keywords?.length ?? 0} injection keywords, ${ext.extra_sensitive_paths?.length ?? 0} sensitive paths`
|
|
3875
3984
|
);
|
|
@@ -7223,10 +7332,10 @@ async function runLLMAnalysis(input, previous) {
|
|
|
7223
7332
|
const config = input.llmConfig?.apiKey ? { ...globalConfig, ...input.llmConfig } : globalConfig;
|
|
7224
7333
|
const rawDetail = input.aNext.actionDetail.replace(/^terminal-\w+:\s*command=([^,]+).*/, "$1").trim();
|
|
7225
7334
|
const cacheKey = `${input.aNext.actionType}:${rawDetail || input.aNext.actionDetail}`;
|
|
7226
|
-
const
|
|
7227
|
-
if (
|
|
7335
|
+
const cached2 = llmCache.get(cacheKey);
|
|
7336
|
+
if (cached2) {
|
|
7228
7337
|
console.log("[AgentMoss] LLM cache hit");
|
|
7229
|
-
return
|
|
7338
|
+
return cached2;
|
|
7230
7339
|
}
|
|
7231
7340
|
const matchedSkills = matchSkills(input.aNext.actionType, input.aNext.actionDetail, input.reason);
|
|
7232
7341
|
const templates = loadTemplates();
|
|
@@ -10814,12 +10923,12 @@ async function analyzeInner(input, mossLog) {
|
|
|
10814
10923
|
}
|
|
10815
10924
|
const cache3 = getDefaultCache();
|
|
10816
10925
|
mossLog.startStep("step2_cache_lookup");
|
|
10817
|
-
const
|
|
10818
|
-
if (
|
|
10926
|
+
const cached2 = cache3.get(input.sessionId, input.promptSession);
|
|
10927
|
+
if (cached2 !== null) {
|
|
10819
10928
|
mossLog.endStep("step2_cache_lookup", "\u7F13\u5B58\u547D\u4E2D");
|
|
10820
|
-
savePolicyToFile(input.sessionId,
|
|
10821
|
-
const res = allowResult(
|
|
10822
|
-
mossLog.logResult("Allow", res.reason,
|
|
10929
|
+
savePolicyToFile(input.sessionId, cached2);
|
|
10930
|
+
const res = allowResult(cached2, judgment);
|
|
10931
|
+
mossLog.logResult("Allow", res.reason, cached2);
|
|
10823
10932
|
return res;
|
|
10824
10933
|
}
|
|
10825
10934
|
if (!isPolicyGenEnabled()) {
|
|
@@ -11578,6 +11687,7 @@ init_runtime_config();
|
|
|
11578
11687
|
init_token_stats();
|
|
11579
11688
|
init_rules_loader();
|
|
11580
11689
|
init_asset_dir();
|
|
11690
|
+
init_rules_mode();
|
|
11581
11691
|
import { Hono } from "hono";
|
|
11582
11692
|
import { readFileSync as readFileSync18, existsSync as existsSync18, unlinkSync as unlinkSync4 } from "fs";
|
|
11583
11693
|
import { join as join14, dirname as dirname12 } from "path";
|
|
@@ -11603,9 +11713,23 @@ function authMiddleware() {
|
|
|
11603
11713
|
await next();
|
|
11604
11714
|
};
|
|
11605
11715
|
}
|
|
11716
|
+
function displayRuntimeConfig() {
|
|
11717
|
+
return isRuntimeConfigDisabled() ? generateSourceDefaults() : loadRuntimeConfig();
|
|
11718
|
+
}
|
|
11719
|
+
function builtinOnlyReadOnlyMiddleware() {
|
|
11720
|
+
return async (c, next) => {
|
|
11721
|
+
if (isRuntimeConfigDisabled() && !["GET", "HEAD", "OPTIONS"].includes(c.req.method)) {
|
|
11722
|
+
return c.json({
|
|
11723
|
+
detail: `\u89C4\u5219\u6765\u6E90\u6A21\u5F0F\u4E3A ${getRulesMode()}\uFF08runtime \u914D\u7F6E\u5DF2\u7981\u7528\uFF09\uFF1AConsole \u53EA\u8BFB\uFF0C\u4FEE\u6539\u4E0D\u4F1A\u4FDD\u5B58\u3002\u8BF7\u5207\u6362\u89C4\u5219\u6765\u6E90\u6A21\u5F0F\u5E76\u91CD\u542F\u670D\u52A1\u540E\u518D\u6539\u89C4\u5219\u3002`
|
|
11724
|
+
}, 403);
|
|
11725
|
+
}
|
|
11726
|
+
await next();
|
|
11727
|
+
};
|
|
11728
|
+
}
|
|
11606
11729
|
function createConsoleRouter() {
|
|
11607
11730
|
const console2 = new Hono();
|
|
11608
11731
|
console2.use("/api/*", authMiddleware());
|
|
11732
|
+
console2.use("/api/*", builtinOnlyReadOnlyMiddleware());
|
|
11609
11733
|
const serveIndex = (c) => {
|
|
11610
11734
|
const indexFile = join14(STATIC_DIR, "index.html");
|
|
11611
11735
|
if (existsSync18(indexFile)) {
|
|
@@ -11616,8 +11740,8 @@ function createConsoleRouter() {
|
|
|
11616
11740
|
console2.get("/", serveIndex);
|
|
11617
11741
|
console2.get("", serveIndex);
|
|
11618
11742
|
console2.get("/api/layers", (c) => {
|
|
11619
|
-
const rc =
|
|
11620
|
-
return c.json({ layers: rc.layers, env_overrides: getEnvOverrides() });
|
|
11743
|
+
const rc = displayRuntimeConfig();
|
|
11744
|
+
return c.json({ layers: rc.layers, env_overrides: getEnvOverrides(), builtin_only: isBuiltinOnly(), rules_mode: getRulesMode() });
|
|
11621
11745
|
});
|
|
11622
11746
|
console2.put("/api/layers", async (c) => {
|
|
11623
11747
|
const body = await c.req.json();
|
|
@@ -11652,7 +11776,7 @@ function createConsoleRouter() {
|
|
|
11652
11776
|
const rules = mc.rules || [];
|
|
11653
11777
|
let catEnabled = true;
|
|
11654
11778
|
try {
|
|
11655
|
-
const rt =
|
|
11779
|
+
const rt = displayRuntimeConfig();
|
|
11656
11780
|
catEnabled = rt.L2_2?.ltl_rules?.category_enabled !== false;
|
|
11657
11781
|
} catch {
|
|
11658
11782
|
}
|
|
@@ -11708,7 +11832,7 @@ function createConsoleRouter() {
|
|
|
11708
11832
|
return rc;
|
|
11709
11833
|
}
|
|
11710
11834
|
console2.get("/api/rules", (c) => {
|
|
11711
|
-
const rc =
|
|
11835
|
+
const rc = displayRuntimeConfig();
|
|
11712
11836
|
const layer = c.req.query("layer");
|
|
11713
11837
|
const category = c.req.query("category");
|
|
11714
11838
|
const out = {};
|
|
@@ -11773,8 +11897,8 @@ function createConsoleRouter() {
|
|
|
11773
11897
|
return c.json(withL22View(rc));
|
|
11774
11898
|
});
|
|
11775
11899
|
console2.get("/api/skills", (c) => {
|
|
11776
|
-
const rc =
|
|
11777
|
-
return c.json(rc.L3_skills);
|
|
11900
|
+
const rc = displayRuntimeConfig();
|
|
11901
|
+
return c.json(rc.L3_skills || {});
|
|
11778
11902
|
});
|
|
11779
11903
|
console2.put("/api/skills/enabled", async (c) => {
|
|
11780
11904
|
const b = await c.req.json();
|
|
@@ -11806,7 +11930,10 @@ function createConsoleRouter() {
|
|
|
11806
11930
|
}
|
|
11807
11931
|
const userPath = join14(dirname12(getRuntimeConfigPath()), "agent_moss_skills", `${skillId}.md`);
|
|
11808
11932
|
const builtinDir = resolveAssetDir(__dirname10, "skills");
|
|
11809
|
-
const candidates = [
|
|
11933
|
+
const candidates = [
|
|
11934
|
+
...isRuntimeConfigDisabled() ? [] : [userPath],
|
|
11935
|
+
builtinDir ? join14(builtinDir, `${skillId}.md`) : ""
|
|
11936
|
+
].filter(Boolean);
|
|
11810
11937
|
for (const p of candidates) {
|
|
11811
11938
|
if (existsSync18(p)) {
|
|
11812
11939
|
return c.json({ skill_id: skillId, path: p, content: readFileSync18(p, "utf-8") });
|
|
@@ -11815,7 +11942,7 @@ function createConsoleRouter() {
|
|
|
11815
11942
|
return c.json({ detail: `skill ${skillId} \u4E0D\u5B58\u5728` }, 404);
|
|
11816
11943
|
});
|
|
11817
11944
|
console2.get("/api/agents", (c) => {
|
|
11818
|
-
const rc =
|
|
11945
|
+
const rc = displayRuntimeConfig();
|
|
11819
11946
|
return c.json({ agents: getAgentRules(rc) });
|
|
11820
11947
|
});
|
|
11821
11948
|
console2.put("/api/agents/rules/enabled", async (c) => {
|
|
@@ -11854,7 +11981,7 @@ function createConsoleRouter() {
|
|
|
11854
11981
|
});
|
|
11855
11982
|
const enabledScenarioIds = () => (process.env.AGENT_MOSS_SCENARIO || "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
11856
11983
|
console2.get("/api/scenarios", (c) => {
|
|
11857
|
-
const all = getScenarioRules(
|
|
11984
|
+
const all = getScenarioRules(displayRuntimeConfig());
|
|
11858
11985
|
const enabled = enabledScenarioIds();
|
|
11859
11986
|
if (!enabled.length) return c.json({ scenarios: {}, enabled: [] });
|
|
11860
11987
|
const shown = {};
|
|
@@ -11896,8 +12023,8 @@ function createConsoleRouter() {
|
|
|
11896
12023
|
return c.json({ scenarios: getScenarioRules(rc), enabled: enabledScenarioIds() });
|
|
11897
12024
|
});
|
|
11898
12025
|
console2.get("/api/config", (c) => {
|
|
11899
|
-
const rc =
|
|
11900
|
-
return c.json({ ...rc, L2_2: getL22View() });
|
|
12026
|
+
const rc = displayRuntimeConfig();
|
|
12027
|
+
return c.json({ ...rc, L2_2: getL22View(), builtin_only: isBuiltinOnly(), rules_mode: getRulesMode() });
|
|
11901
12028
|
});
|
|
11902
12029
|
console2.get("/api/env-overrides", (c) => {
|
|
11903
12030
|
return c.json({ overrides: getEnvOverrides() });
|
|
@@ -11935,37 +12062,58 @@ function createConsoleRouter() {
|
|
|
11935
12062
|
|
|
11936
12063
|
// src/server.ts
|
|
11937
12064
|
init_runtime_config();
|
|
12065
|
+
init_rules_mode();
|
|
11938
12066
|
init_rules_loader();
|
|
11939
12067
|
function logDeploymentSelfCheck() {
|
|
11940
12068
|
try {
|
|
12069
|
+
const mode = getRulesMode();
|
|
12070
|
+
const builtinOnly = isBuiltinOnly();
|
|
12071
|
+
const runtimeDisabled = isRuntimeConfigDisabled();
|
|
11941
12072
|
console.log("================ AgentMoss \u90E8\u7F72\u81EA\u68C0 ================");
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
try {
|
|
11946
|
-
const dirs = rulesDirs().filter((d) => existsSync19(d));
|
|
11947
|
-
if (dirs.length > 0) {
|
|
11948
|
-
console.log(`\u89C4\u5219\u76EE\u5F55: ${dirs.join(", ")}\uFF08\u53EA\u8BFB\u5176\u4E2D ${OVERRIDE_FILENAME} / ${EXTRA_FILENAME}\uFF09`);
|
|
11949
|
-
}
|
|
11950
|
-
const loaded = ruleFilesLoaded();
|
|
11951
|
-
if (loaded.length > 0) {
|
|
11952
|
-
const ov = loadOverrideRules();
|
|
11953
|
-
const ex = loadExtraRules();
|
|
11954
|
-
console.error(`\u26A0\uFE0F \u5DF2\u4ECE\u89C4\u5219\u76EE\u5F55\u52A0\u8F7D ${loaded.length} \u4E2A\u6587\u4EF6\uFF08\u6574\u4EFD\u66FF\u6362 / \u8FFD\u52A0\uFF0C\u5185\u7F6E\u66F4\u65B0\u4E0D\u4F1A\u53CD\u6620\u5230\u5B83\u4EEC\u4E0A\u9762\uFF09:`);
|
|
11955
|
-
for (const f of loaded) console.error(` ${f}`);
|
|
11956
|
-
const ovs = Object.entries(ov).sort().map(([k, v]) => `${k}\xD7${v.length}`).join(", ");
|
|
11957
|
-
if (ovs) console.error(` \u8986\u76D6\u7C7B\u522B: ${ovs}\uFF08**\u6574\u4EFD\u66FF\u6362**\uFF1A\u672A\u5217\u51FA\u7684\u5185\u7F6E\u89C4\u5219\u4E0D\u518D\u751F\u6548\uFF09`);
|
|
11958
|
-
const exs = Object.entries(ex).sort().map(([k, v]) => `${k}\xD7${v.length}`).join(", ");
|
|
11959
|
-
if (exs) console.log(` \u8FFD\u52A0\u7C7B\u522B: ${exs}\uFF08\u5185\u7F6E\u4FDD\u7559\uFF0C\u8FFD\u52A0\u5728\u5176\u540E\u4E00\u8D77\u5224\u5B9A\uFF09`);
|
|
11960
|
-
}
|
|
11961
|
-
const ignored = ignoredRuleFiles();
|
|
11962
|
-
if (ignored.length > 0) {
|
|
12073
|
+
if (runtimeDisabled) {
|
|
12074
|
+
console.log(`runtime \u914D\u7F6E: ${getRuntimeConfigPath()}\uFF08**\u5DF2\u5FFD\u7565**\uFF1A\u89C4\u5219\u6765\u6E90\u6A21\u5F0F=${mode}\uFF09`);
|
|
12075
|
+
if (builtinOnly) {
|
|
11963
12076
|
console.error(
|
|
11964
|
-
|
|
12077
|
+
"\u89C4\u5219\u6765\u6E90: **\u4EC5\u5185\u7F6E** \u2014\u2014 \u4E0D\u8BFB runtime \u914D\u7F6E / Console \u81EA\u5B9A\u4E49 / \u89C4\u5219\u76EE\u5F55 / AGENT_MOSS_CUSTOM_RULES\uFF1B\u4E0D seed\u3001\u4E0D merge\u3001\u4E0D\u5199\u56DE\u3002"
|
|
11965
12078
|
);
|
|
11966
|
-
|
|
12079
|
+
} else {
|
|
12080
|
+
console.error(
|
|
12081
|
+
"\u89C4\u5219\u6765\u6E90: **\u51B7\u542F\u52A8\uFF08cold\uFF09** \u2014\u2014 \u542F\u52A8\u65F6\u8BFB\u53D6\u5185\u7F6E\u89C4\u5219 + \u89C4\u5219\u76EE\u5F55 / AGENT_MOSS_CUSTOM_RULES / \u573A\u666F\uFF0C\u4E4B\u540E\u51BB\u7ED3\uFF1B\u4E0D\u8BFB runtime \u914D\u7F6E / Console\uFF0C\u4E0D seed\u3001\u4E0D merge\u3001\u4E0D\u5199\u56DE\u3002"
|
|
12082
|
+
);
|
|
12083
|
+
console.error("\u89C4\u5219\u76EE\u5F55\u5185\u5BB9\u6539\u52A8\u9700\u91CD\u542F\u670D\u52A1\u624D\u751F\u6548\u3002");
|
|
12084
|
+
}
|
|
12085
|
+
console.error("Console: \u53EA\u8BFB\uFF08\u89C4\u5219\u5199\u63A5\u53E3\u8FD4\u56DE 403\uFF09\uFF1B\u4FEE\u6539\u89C4\u5219\u9700\u91CD\u542F\u670D\u52A1\u5E76\u5207\u6362\u89C4\u5219\u6765\u6E90\u6A21\u5F0F\u3002");
|
|
12086
|
+
} else {
|
|
12087
|
+
console.log(`runtime \u914D\u7F6E: ${getRuntimeConfigPath()}`);
|
|
12088
|
+
}
|
|
12089
|
+
const layerKeys = ["L1_heuristic", "L2_logic_rules", "L3_llm_analysis", "agent_rules_enabled", "scenario_rules_enabled"];
|
|
12090
|
+
console.log("\u5C42\u7EA7\u5F00\u5173: " + layerKeys.map((k) => `${k}=${isLayerEnabled(k) ? "on" : "OFF"}`).join(" "));
|
|
12091
|
+
if (!builtinOnly) {
|
|
12092
|
+
try {
|
|
12093
|
+
const dirs = rulesDirs().filter((d) => existsSync19(d));
|
|
12094
|
+
if (dirs.length > 0) {
|
|
12095
|
+
console.log(`\u89C4\u5219\u76EE\u5F55: ${dirs.join(", ")}\uFF08\u53EA\u8BFB\u5176\u4E2D ${OVERRIDE_FILENAME} / ${EXTRA_FILENAME}\uFF09`);
|
|
12096
|
+
}
|
|
12097
|
+
const loaded = ruleFilesLoaded();
|
|
12098
|
+
if (loaded.length > 0) {
|
|
12099
|
+
const ov = loadOverrideRules();
|
|
12100
|
+
const ex = loadExtraRules();
|
|
12101
|
+
console.error(`\u26A0\uFE0F \u5DF2\u4ECE\u89C4\u5219\u76EE\u5F55\u52A0\u8F7D ${loaded.length} \u4E2A\u6587\u4EF6\uFF08\u6574\u4EFD\u66FF\u6362 / \u8FFD\u52A0\uFF0C\u5185\u7F6E\u66F4\u65B0\u4E0D\u4F1A\u53CD\u6620\u5230\u5B83\u4EEC\u4E0A\u9762\uFF09:`);
|
|
12102
|
+
for (const f of loaded) console.error(` ${f}`);
|
|
12103
|
+
const ovs = Object.entries(ov).sort().map(([k, v]) => `${k}\xD7${v.length}`).join(", ");
|
|
12104
|
+
if (ovs) console.error(` \u8986\u76D6\u7C7B\u522B: ${ovs}\uFF08**\u6574\u4EFD\u66FF\u6362**\uFF1A\u672A\u5217\u51FA\u7684\u5185\u7F6E\u89C4\u5219\u4E0D\u518D\u751F\u6548\uFF09`);
|
|
12105
|
+
const exs = Object.entries(ex).sort().map(([k, v]) => `${k}\xD7${v.length}`).join(", ");
|
|
12106
|
+
if (exs) console.log(` \u8FFD\u52A0\u7C7B\u522B: ${exs}\uFF08\u5185\u7F6E\u4FDD\u7559\uFF0C\u8FFD\u52A0\u5728\u5176\u540E\u4E00\u8D77\u5224\u5B9A\uFF09`);
|
|
12107
|
+
}
|
|
12108
|
+
const ignored = ignoredRuleFiles();
|
|
12109
|
+
if (ignored.length > 0) {
|
|
12110
|
+
console.error(
|
|
12111
|
+
`\u26A0\uFE0F \u89C4\u5219\u76EE\u5F55\u91CC\u6709 ${ignored.length} \u4E2A json **\u4E0D\u4F1A\u88AB\u8BFB\u53D6**\uFF08\u53EA\u8BA4 ${OVERRIDE_FILENAME} / ${EXTRA_FILENAME}\uFF09:`
|
|
12112
|
+
);
|
|
12113
|
+
for (const f of ignored) console.error(` ${f}`);
|
|
12114
|
+
}
|
|
12115
|
+
} catch {
|
|
11967
12116
|
}
|
|
11968
|
-
} catch {
|
|
11969
12117
|
}
|
|
11970
12118
|
const scenarioRaw = (process.env.AGENT_MOSS_SCENARIO || "").trim();
|
|
11971
12119
|
if (scenarioRaw) {
|
package/dist/static/index.html
CHANGED
|
@@ -201,7 +201,10 @@ body {
|
|
|
201
201
|
.ag-link:hover { text-decoration: underline; }
|
|
202
202
|
|
|
203
203
|
/* Toast */
|
|
204
|
-
.ag-toast { position: fixed; top: 20px; right: 20px; padding: 12px 20px; border-radius: 8px; font-size: 13px; z-index:
|
|
204
|
+
.ag-toast { position: fixed; top: 20px; right: 20px; padding: 12px 20px; border-radius: 8px; font-size: 13px; z-index: 10000; box-shadow: 0 4px 12px rgba(0,0,0,.15); animation: ag-slide-in .3s ease; }
|
|
205
|
+
/* 仅内置规则模式的顶部横幅是 sticky + z-index 9999;toast 必须在其之上,
|
|
206
|
+
并下移一个横幅高度,否则错误提示会被横幅挡住。 */
|
|
207
|
+
body.builtin-only-mode .ag-toast { top: calc(20px + var(--am-builtin-banner-height, 48px)); }
|
|
205
208
|
.ag-toast-success { background: var(--ag-green); color: #fff; }
|
|
206
209
|
.ag-toast-error { background: var(--ag-red); color: #fff; }
|
|
207
210
|
.ag-toast-warning { background: var(--ag-orange); color: #fff; }
|
|
@@ -246,6 +249,10 @@ body {
|
|
|
246
249
|
</style>
|
|
247
250
|
</head>
|
|
248
251
|
<body>
|
|
252
|
+
<div id="builtin-only-banner" style="display:none;background:#b45309;color:#fff;padding:6px 14px;font-size:12px;line-height:1.5;text-align:center;position:sticky;top:0;z-index:9999">
|
|
253
|
+
仅内置规则模式:已忽略 runtime 配置与 Console 自定义,修改规则不会生效。需重启服务并移除 <code>AGENT_MOSS_RULES_BUILTIN_ONLY</code> 后再改规则。<br>
|
|
254
|
+
Built-in rules only: runtime config and Console changes are ignored. Restart without <code>AGENT_MOSS_RULES_BUILTIN_ONLY</code> to edit rules.
|
|
255
|
+
</div>
|
|
249
256
|
<div class="ag-wrap">
|
|
250
257
|
<div class="ag-tabs" id="tabs">
|
|
251
258
|
<div class="ag-tab active" data-page="overview">概览</div>
|
|
@@ -553,6 +560,24 @@ function agPrompt(title, opts = {}) {
|
|
|
553
560
|
// ===== Pages =====
|
|
554
561
|
async function refreshConfig() {
|
|
555
562
|
state.config = await api('config');
|
|
563
|
+
// cold / builtin 模式:顶部显示只读横幅(写接口由后端统一 403)
|
|
564
|
+
const rulesMode = state.config.rules_mode || (state.config.builtin_only ? 'builtin' : 'hot');
|
|
565
|
+
if (rulesMode === 'cold' || rulesMode === 'builtin') {
|
|
566
|
+
const banner = el('builtin-only-banner');
|
|
567
|
+
if (banner) {
|
|
568
|
+
banner.innerHTML = rulesMode === 'cold'
|
|
569
|
+
? '冷启动规则模式:runtime 配置与 Console 自定义已忽略;规则目录仅在启动时读取一次,修改规则目录需重启服务。<br>'
|
|
570
|
+
+ 'Cold-start rules mode: runtime config and Console changes are ignored. Rule directories are loaded once at startup; restart to apply changes.'
|
|
571
|
+
: '仅内置规则模式:已忽略 runtime 配置与 Console 自定义,修改规则不会生效。需重启服务并移除 <code>AGENT_MOSS_RULES_BUILTIN_ONLY</code> 后再改规则。<br>'
|
|
572
|
+
+ 'Built-in rules only: runtime config and Console changes are ignored. Restart without <code>AGENT_MOSS_RULES_BUILTIN_ONLY</code> to edit rules.';
|
|
573
|
+
banner.style.display = 'block';
|
|
574
|
+
// 记录横幅实际高度(窄屏会换行),让 toast 显示在横幅下方而不是被挡住
|
|
575
|
+
document.documentElement.style.setProperty(
|
|
576
|
+
'--am-builtin-banner-height', banner.offsetHeight + 'px'
|
|
577
|
+
);
|
|
578
|
+
document.body.classList.add('builtin-only-mode');
|
|
579
|
+
}
|
|
580
|
+
}
|
|
556
581
|
state.envOverrides = await loadEnvOverrides();
|
|
557
582
|
state.agentRules = await api('agents');
|
|
558
583
|
// 场景定制规则:后端按 AGENT_MOSS_SCENARIO env 过滤(无 env 返回空 → 场景页显示"未启用"提示)
|