entroly-openclaw 1.0.80 → 1.0.82
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 +29 -4
- package/bridge-client.js +46 -1
- package/package.json +1 -1
- package/proof-hooks.js +43 -8
package/README.md
CHANGED
|
@@ -22,12 +22,33 @@ Install the Python engine, then install the publicly verifiable OpenClaw plugin
|
|
|
22
22
|
package from npm:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
pip install "entroly>=1.0.
|
|
25
|
+
pip install "entroly>=1.0.82"
|
|
26
26
|
openclaw plugins install npm:entroly-openclaw
|
|
27
27
|
openclaw plugins enable entroly
|
|
28
28
|
openclaw gateway restart
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
The plugin starts a local Python subprocess for context assembly. That child
|
|
32
|
+
receives only the operating-system paths and Entroly-local settings it needs;
|
|
33
|
+
provider API keys, cloud credentials, registry tokens, and unrelated host
|
|
34
|
+
environment variables are not inherited. OpenClaw remains the sole owner of
|
|
35
|
+
provider authentication.
|
|
36
|
+
|
|
37
|
+
Local receipts are enabled by default because they make context decisions
|
|
38
|
+
auditable. They contain hashes, counts, estimates, warnings, and decision
|
|
39
|
+
metadata rather than conversation text, and are bounded by file-count and byte
|
|
40
|
+
quotas. To opt out of persistence, set:
|
|
41
|
+
|
|
42
|
+
```json5
|
|
43
|
+
{
|
|
44
|
+
plugins: {
|
|
45
|
+
entries: {
|
|
46
|
+
entroly: { config: { writeReceipts: false } }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
31
52
|
ClawHub is an optional registry source. Use it only when
|
|
32
53
|
`openclaw plugins search "entroly"` returns a current public package and its
|
|
33
54
|
install hint. Do not guess a ClawHub slug or treat unpublished metadata as an
|
|
@@ -36,7 +57,7 @@ installable release.
|
|
|
36
57
|
From an Entroly source checkout:
|
|
37
58
|
|
|
38
59
|
```bash
|
|
39
|
-
pip install "entroly>=1.0.
|
|
60
|
+
pip install "entroly>=1.0.82"
|
|
40
61
|
openclaw plugins install ./integrations/openclaw
|
|
41
62
|
openclaw plugins enable entroly
|
|
42
63
|
openclaw gateway restart
|
|
@@ -97,8 +118,10 @@ digest, native window, output reserve, safety reserve, and source.
|
|
|
97
118
|
|
|
98
119
|
Context-budget discovery is local and enabled by default. It does not enable
|
|
99
120
|
remote provider discovery or send credentials anywhere. Local Ollama/LM Studio
|
|
100
|
-
and
|
|
101
|
-
|
|
121
|
+
discovery and a local `ENTROLY_MODEL_REGISTRY` override remain explicit
|
|
122
|
+
operator controls. Remote OpenRouter discovery is deliberately unavailable
|
|
123
|
+
inside the OpenClaw bridge because provider credentials do not cross the
|
|
124
|
+
subprocess boundary. Disable local fallback with
|
|
102
125
|
`autoDiscoverContextBudget: false`.
|
|
103
126
|
|
|
104
127
|
For a custom model that neither OpenClaw nor trusted registry metadata can
|
|
@@ -211,6 +234,8 @@ archive receipts or raise `receiptMaxFiles` / `receiptMaxBytes` explicitly.
|
|
|
211
234
|
|
|
212
235
|
## Safety contract
|
|
213
236
|
|
|
237
|
+
- Provider API keys and unrelated host secrets are removed from the local
|
|
238
|
+
Python bridge environment before it starts.
|
|
214
239
|
- System and developer messages are never modified.
|
|
215
240
|
- Signed text, thinking/reasoning, images, tool calls, tool-result metadata,
|
|
216
241
|
opaque provider signatures, and unknown content blocks are never modified.
|
package/bridge-client.js
CHANGED
|
@@ -3,6 +3,51 @@ import readline from "node:readline";
|
|
|
3
3
|
|
|
4
4
|
export const ENTROLY_BRIDGE_SCHEMA = "entroly.openclaw.bridge.v2";
|
|
5
5
|
|
|
6
|
+
const BRIDGE_ENVIRONMENT_ALLOWLIST = new Set([
|
|
7
|
+
"APPDATA",
|
|
8
|
+
"COMSPEC",
|
|
9
|
+
"ENTROLY_AIR_GAP",
|
|
10
|
+
"ENTROLY_DISABLE_TELEMETRY",
|
|
11
|
+
"ENTROLY_DISCOVER_LOCAL_MODELS",
|
|
12
|
+
"ENTROLY_LMSTUDIO_BASE",
|
|
13
|
+
"ENTROLY_MODEL_DISCOVERY_MAX",
|
|
14
|
+
"ENTROLY_MODEL_DISCOVERY_TIMEOUT",
|
|
15
|
+
"ENTROLY_MODEL_REGISTRY",
|
|
16
|
+
"ENTROLY_OLLAMA_BASE",
|
|
17
|
+
"ENTROLY_OLLAMA_INSPECT_CONTEXT",
|
|
18
|
+
"ENTROLY_OPENCLAW_RECEIPT_KEY_FILE",
|
|
19
|
+
"ENTROLY_UNKNOWN_MODEL_CONTEXT",
|
|
20
|
+
"HOME",
|
|
21
|
+
"HOMEDRIVE",
|
|
22
|
+
"HOMEPATH",
|
|
23
|
+
"LANG",
|
|
24
|
+
"LC_ALL",
|
|
25
|
+
"LC_CTYPE",
|
|
26
|
+
"LOCALAPPDATA",
|
|
27
|
+
"PATH",
|
|
28
|
+
"PATHEXT",
|
|
29
|
+
"SYSTEMDRIVE",
|
|
30
|
+
"SYSTEMROOT",
|
|
31
|
+
"TEMP",
|
|
32
|
+
"TMP",
|
|
33
|
+
"TMPDIR",
|
|
34
|
+
"TZ",
|
|
35
|
+
"USERPROFILE",
|
|
36
|
+
"WINDIR",
|
|
37
|
+
"XDG_STATE_HOME",
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
export function buildBridgeEnvironment(source = {}) {
|
|
41
|
+
return Object.fromEntries(
|
|
42
|
+
Object.entries(source).filter(
|
|
43
|
+
([name, value]) =>
|
|
44
|
+
value !== undefined &&
|
|
45
|
+
value !== null &&
|
|
46
|
+
BRIDGE_ENVIRONMENT_ALLOWLIST.has(name.toUpperCase()),
|
|
47
|
+
),
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
6
51
|
export function validateBridgeHealth(result) {
|
|
7
52
|
if (
|
|
8
53
|
!result ||
|
|
@@ -30,7 +75,7 @@ export class EntrolyBridgeClient {
|
|
|
30
75
|
this.timeoutMs = timeoutMs;
|
|
31
76
|
this.logger = logger;
|
|
32
77
|
this.spawnProcess = spawnProcess;
|
|
33
|
-
this.environment = environment;
|
|
78
|
+
this.environment = buildBridgeEnvironment(environment);
|
|
34
79
|
this.nextId = 1;
|
|
35
80
|
this.pending = new Map();
|
|
36
81
|
this.process = undefined;
|
package/package.json
CHANGED
package/proof-hooks.js
CHANGED
|
@@ -6,15 +6,50 @@ function sha256(value) {
|
|
|
6
6
|
return createHash("sha256").update(String(value), "utf8").digest("hex");
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// Diagnostics can contain provider text, tool names, bridge errors, or recovered
|
|
10
|
+
// material. Treat them as untrusted display data. Canonicalize before redaction
|
|
11
|
+
// so format/control characters cannot be inserted into credential markers to
|
|
12
|
+
// evade secret detection, then escape display syntax and truncate by code point.
|
|
13
|
+
const DISPLAY_WHITESPACE = /[\t\n\r\f\v\u0085\u2028\u2029]+/gu;
|
|
14
|
+
const UNSAFE_FOR_DISPLAY = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/gu;
|
|
15
|
+
const MARKDOWN_DELIMITERS = /([\\`*_[\]{}()<>#+.!|~-])/g;
|
|
16
|
+
const AUTH_SCHEME = /\b(Basic|Bearer)\s+[^\s,;]+/gi;
|
|
17
|
+
const SECRET_FIELD =
|
|
18
|
+
/["']?\b(api[_-]?key|authorization|password|secret|token)\b["']?\s*[:=]\s*(?:"[^"]*(?:"|$)|'[^']*(?:'|$)|(?:Basic|Bearer)\s+[^\s,;]+|[^\s,;"']+)/gi;
|
|
19
|
+
|
|
20
|
+
function diagnosticSource(value) {
|
|
21
|
+
try {
|
|
22
|
+
const candidate = value?.message ?? value ?? "unknown error";
|
|
23
|
+
return typeof candidate === "string" ? candidate : String(candidate);
|
|
24
|
+
} catch {
|
|
25
|
+
return "unknown error";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function normalizeDiagnosticText(value) {
|
|
30
|
+
return diagnosticSource(value)
|
|
31
|
+
.toWellFormed()
|
|
32
|
+
.normalize("NFKC")
|
|
33
|
+
.replace(DISPLAY_WHITESPACE, " ")
|
|
34
|
+
.replace(UNSAFE_FOR_DISPLAY, "")
|
|
11
35
|
.replace(/\s+/g, " ")
|
|
12
|
-
.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
36
|
+
.trim();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function sanitizeDisplayText(value, limit = 400) {
|
|
40
|
+
if (typeof value !== "string" || limit <= 0) return "";
|
|
41
|
+
const escaped = value.replace(MARKDOWN_DELIMITERS, "\\$1");
|
|
42
|
+
const codePoints = [...escaped];
|
|
43
|
+
if (codePoints.length <= limit) return escaped;
|
|
44
|
+
if (limit === 1) return "…";
|
|
45
|
+
return `${codePoints.slice(0, limit - 1).join("")}…`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function safeDiagnostic(value, limit = 400) {
|
|
49
|
+
const redacted = normalizeDiagnosticText(value)
|
|
50
|
+
.replace(AUTH_SCHEME, "$1 [REDACTED]")
|
|
51
|
+
.replace(SECRET_FIELD, "$1=[REDACTED]");
|
|
52
|
+
return sanitizeDisplayText(redacted, limit);
|
|
18
53
|
}
|
|
19
54
|
|
|
20
55
|
function positiveInteger(value, fallback, maximum) {
|