@openbmb/clawxrouter 1.0.4

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.
@@ -0,0 +1,86 @@
1
+ import type { PrivacyConfig, SensitivityLevel } from "./types.js";
2
+
3
+ /**
4
+ * Check if guard agent is properly configured
5
+ */
6
+ export function isGuardAgentConfigured(config: PrivacyConfig): boolean {
7
+ return Boolean(
8
+ config.guardAgent?.id &&
9
+ config.guardAgent?.model &&
10
+ config.guardAgent?.workspace
11
+ );
12
+ }
13
+
14
+ /**
15
+ * Get guard agent configuration (returns null if not fully configured).
16
+ *
17
+ * The model field uses "provider/model" format (e.g. "ollama/llama3.2:3b", "vllm/qwen2.5:7b").
18
+ * When no slash is present, the provider is inferred from localModel.provider config,
19
+ * falling back to "ollama" only if nothing else is configured.
20
+ */
21
+ export function getGuardAgentConfig(config: PrivacyConfig): {
22
+ id: string;
23
+ model: string;
24
+ workspace: string;
25
+ provider: string;
26
+ modelName: string;
27
+ } | null {
28
+ if (!isGuardAgentConfigured(config)) {
29
+ return null;
30
+ }
31
+
32
+ const fullModel = config.guardAgent?.model ?? "ollama/openbmb/minicpm4.1";
33
+ const firstSlash = fullModel.indexOf("/");
34
+ const defaultProvider = config.localModel?.provider ?? "ollama";
35
+ const [provider, modelName] = firstSlash >= 0
36
+ ? [fullModel.slice(0, firstSlash), fullModel.slice(firstSlash + 1)]
37
+ : [defaultProvider, fullModel];
38
+
39
+ return {
40
+ id: config.guardAgent?.id ?? "guard",
41
+ model: fullModel,
42
+ workspace: config.guardAgent?.workspace ?? "~/.openclaw/workspace-guard",
43
+ provider,
44
+ modelName,
45
+ };
46
+ }
47
+
48
+ /**
49
+ * Check if a session key belongs to a guard subsession
50
+ */
51
+ export function isGuardSessionKey(sessionKey: string): boolean {
52
+ return sessionKey.endsWith(":guard") || sessionKey.includes(":guard:");
53
+ }
54
+
55
+ /**
56
+ * Build a placeholder message to insert into the main (cloud-visible) session history
57
+ * when a message is redirected to the guard subsession.
58
+ *
59
+ * This ensures the cloud model never sees the actual sensitive content,
60
+ * but knows that something was handled privately.
61
+ */
62
+ export function buildMainSessionPlaceholder(level: SensitivityLevel, reason?: string, timestamp?: number): string {
63
+ const emoji = level === "S3" ? "🔒" : "🔑";
64
+ const levelLabel = level === "S3" ? "Private" : "Sensitive";
65
+ const reasonSuffix = reason ? ` (${reason})` : "";
66
+ const tsSuffix = timestamp ? ` [ts=${new Date(timestamp).toISOString()}]` : "";
67
+ return `${emoji} [${levelLabel} message — processed locally${reasonSuffix}]${tsSuffix}`;
68
+ }
69
+
70
+ const BUILTIN_LOCAL_PROVIDERS = [
71
+ "ollama", "llama.cpp", "localai", "llamafile", "lmstudio",
72
+ "vllm", "mlx", "sglang", "tgi", "koboldcpp", "tabbyapi", "nitro",
73
+ ];
74
+
75
+ /**
76
+ * Validate that a model reference is local-only (not a cloud provider).
77
+ * Used to enforce the constraint that guard sessions only use local models.
78
+ *
79
+ * Checks against built-in list + any extra providers from config.localProviders.
80
+ */
81
+ export function isLocalProvider(provider: string, extraProviders?: string[]): boolean {
82
+ const lower = provider.toLowerCase();
83
+ if (BUILTIN_LOCAL_PROVIDERS.includes(lower)) return true;
84
+ if (extraProviders?.some((p) => p.toLowerCase() === lower)) return true;
85
+ return false;
86
+ }