mlclaw 0.4.9 → 0.5.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.
- package/Dockerfile +4 -3
- package/README.md +9 -2
- package/assets/hf-tooling/manifest.json +9 -0
- package/assets/hf-tooling/skills/hf-broker/SKILL.md +126 -0
- package/dist/hf-tooling-seed.js +17 -0
- package/dist/mlclaw-space-runtime.js +109 -11
- package/dist/mlclaw.mjs +4 -3
- package/entrypoint.sh +33 -1
- package/package.json +4 -4
package/Dockerfile
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
ARG OPENCLAW_VERSION=2026.7.1
|
|
2
2
|
ARG OPENCLAW_BASE_IMAGE=ghcr.io/openclaw/openclaw:${OPENCLAW_VERSION}
|
|
3
|
-
ARG BROKERKIT_PLUGIN_VERSION=0.
|
|
4
|
-
ARG BROKERKIT_VERSION=hf-broker/v0.
|
|
5
|
-
ARG MLCLAW_RUNTIME_IMAGE=ghcr.io/huggingface/mlclaw:0.
|
|
3
|
+
ARG BROKERKIT_PLUGIN_VERSION=0.4.1
|
|
4
|
+
ARG BROKERKIT_VERSION=hf-broker/v0.6.2
|
|
5
|
+
ARG MLCLAW_RUNTIME_IMAGE=ghcr.io/huggingface/mlclaw:0.5.0-openclaw-2026.7.1
|
|
6
6
|
|
|
7
7
|
FROM golang:1.26.5-bookworm AS hf-broker-build
|
|
8
8
|
ARG BROKERKIT_VERSION
|
|
@@ -43,6 +43,7 @@ RUN apt-get update \
|
|
|
43
43
|
&& rm -rf /var/lib/apt/lists/*
|
|
44
44
|
RUN python3 -m pip install --break-system-packages --no-cache-dir \
|
|
45
45
|
"huggingface_hub==1.19.0" \
|
|
46
|
+
"hf-xet==1.5.2" \
|
|
46
47
|
"datasets==5.0.0" \
|
|
47
48
|
"safetensors==0.8.0" \
|
|
48
49
|
"fastapi==0.137.1" \
|
package/README.md
CHANGED
|
@@ -384,8 +384,15 @@ across Space rebuilds, local container replacement, and gateway migration. The
|
|
|
384
384
|
Space does not use `HF_TOKEN` or `HUGGINGFACE_HUB_TOKEN` secrets. Its broad
|
|
385
385
|
credential is stored as `MLCLAW_BROKER_HF_TOKEN`, written to a broker-owned
|
|
386
386
|
`0600` file during startup, and removed from child-process environments.
|
|
387
|
-
OpenClaw uses only the generated broker agent credential.
|
|
388
|
-
|
|
387
|
+
OpenClaw uses only the generated broker agent credential. At startup, ML Claw
|
|
388
|
+
asks HF Broker to render the active policy with the exact deployment state
|
|
389
|
+
bucket protected. Agent requests against that bucket are denied before an
|
|
390
|
+
approval is created. Other repository paths and bucket key prefixes can use
|
|
391
|
+
operator-approved grants lasting up to 24 hours or seven days; the installed
|
|
392
|
+
`hf-broker` skill explains request, wait, recovery, write, read, and revocation
|
|
393
|
+
workflows.
|
|
394
|
+
|
|
395
|
+
Broker grant and event state and encrypted control credentials live under the root-owned
|
|
389
396
|
`/var/lib/mlclaw-protected` tree. They are included in the durable snapshot
|
|
390
397
|
through a root-only `.mlclaw-protected` staging step, then restored outside the
|
|
391
398
|
agent-owned live directory before OpenClaw starts. Rebuildable Git mirrors, the
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"python": {
|
|
24
24
|
"packages": {
|
|
25
25
|
"huggingface_hub": "1.19.0",
|
|
26
|
+
"hf_xet": "1.5.2",
|
|
26
27
|
"datasets": "5.0.0",
|
|
27
28
|
"safetensors": "0.8.0"
|
|
28
29
|
}
|
|
@@ -30,7 +31,15 @@
|
|
|
30
31
|
"skills": {
|
|
31
32
|
"source": "https://github.com/huggingface/skills",
|
|
32
33
|
"revision": "89d91fd4d0e6d4330471ba35f1c388489e94b496",
|
|
34
|
+
"managed": [
|
|
35
|
+
{
|
|
36
|
+
"name": "hf-broker",
|
|
37
|
+
"source": "https://github.com/osolmaz/brokerkit",
|
|
38
|
+
"revision": "hf-broker/v0.6.2"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
33
41
|
"installed": [
|
|
42
|
+
"hf-broker",
|
|
34
43
|
"hf-cli",
|
|
35
44
|
"huggingface-spaces",
|
|
36
45
|
"huggingface-datasets",
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hf-broker
|
|
3
|
+
description: Use ML Claw's HF Broker for protected Hugging Face repository and bucket reads, writes, temporary grants, recovery, and revocation. Use instead of asking for or exposing a Hugging Face access token.
|
|
4
|
+
metadata:
|
|
5
|
+
{ "openclaw": { "emoji": "🤗", "requires": { "bins": ["hf-broker"] } } }
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Hugging Face Broker
|
|
9
|
+
|
|
10
|
+
Use the preconfigured HF Broker for protected Hugging Face operations. Never
|
|
11
|
+
ask for, print, copy, or export the broker's Hugging Face token. Do not run
|
|
12
|
+
`hf auth login` to work around a broker decision.
|
|
13
|
+
|
|
14
|
+
## Choose a workflow
|
|
15
|
+
|
|
16
|
+
Use the advertised `hf_*` MCP tools for ordinary typed operations and grant
|
|
17
|
+
management. Use `hf-broker client` when a local file must enter or leave the
|
|
18
|
+
protected stream store. The runtime already provides the broker endpoint and a
|
|
19
|
+
limited agent credential.
|
|
20
|
+
|
|
21
|
+
Every mutation needs a stable request ID. Reuse it only for an exact retry of
|
|
22
|
+
the same operation. If a response is lost, recover the existing operation or
|
|
23
|
+
grant instead of submitting another mutation.
|
|
24
|
+
|
|
25
|
+
## Request reusable write access
|
|
26
|
+
|
|
27
|
+
Request a temporary grant only when repeated writes are needed. Keep the scope
|
|
28
|
+
as narrow as possible. A day is 1,440 minutes and a week is 10,080 minutes.
|
|
29
|
+
These repeated-write examples explicitly request the deployment policy's
|
|
30
|
+
25-use ceiling; the operator may approve a smaller use budget.
|
|
31
|
+
|
|
32
|
+
For one bucket key prefix:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
hf-broker client grant request bucket.object.write OWNER/BUCKET \
|
|
36
|
+
--key 'artifacts/**' \
|
|
37
|
+
--minutes 10080 \
|
|
38
|
+
--max-uses 25 \
|
|
39
|
+
--reason "Write the requested artifacts for one week" \
|
|
40
|
+
--request-id STABLE-GRANT-REQUEST-ID
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
For one repository path prefix:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
hf-broker client grant request repo.commit.create OWNER/REPO \
|
|
47
|
+
--type dataset \
|
|
48
|
+
--path 'data/**' \
|
|
49
|
+
--minutes 1440 \
|
|
50
|
+
--max-uses 25 \
|
|
51
|
+
--reason "Update the requested dataset path for one day" \
|
|
52
|
+
--request-id STABLE-GRANT-REQUEST-ID
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Normal append-only Git pushes can also use a scoped `git.push.append` grant.
|
|
56
|
+
Keep the repository type, ref, and path selectors exact. Force pushes, ref
|
|
57
|
+
deletion, repository deletion, visibility changes, and access management stay
|
|
58
|
+
short-lived or single-use.
|
|
59
|
+
|
|
60
|
+
A pending grant requires an operator decision. Keep waiting on the same grant
|
|
61
|
+
rather than creating another request:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
hf-broker client grant wait --wait-timeout 15m GRANT-ID
|
|
65
|
+
hf-broker client grant get GRANT-ID
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
MCP grant calls use bounded waits. If `hf_grant_request` or `hf_grant_wait`
|
|
69
|
+
returns `pending`, call `hf_grant_wait` again with the same grant ID. Use
|
|
70
|
+
`hf_grant_cancel` for an unapproved request and `hf_grant_revoke` when reusable
|
|
71
|
+
access is no longer needed.
|
|
72
|
+
|
|
73
|
+
## Write and read bucket objects
|
|
74
|
+
|
|
75
|
+
Upload a local file through the broker's stream store. File bytes do not belong
|
|
76
|
+
in MCP JSON, chat messages, plans, approvals, or logs.
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
hf-broker client bucket object write \
|
|
80
|
+
--target-json '{"kind":"bucket","namespace":"OWNER","name":"BUCKET"}' \
|
|
81
|
+
--arguments-json '{"path":"artifacts/result.bin"}' \
|
|
82
|
+
--source ./result.bin \
|
|
83
|
+
--media-type application/octet-stream \
|
|
84
|
+
--reason "Upload the requested result" \
|
|
85
|
+
--request-id STABLE-WRITE-REQUEST-ID \
|
|
86
|
+
--wait=true \
|
|
87
|
+
--wait-timeout 15m
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Set `"overwrite":true` only when replacing the currently observed object is
|
|
91
|
+
intentional. The broker checks the bound precondition again before commit.
|
|
92
|
+
|
|
93
|
+
Read into a new destination and let the client verify the returned stream:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
hf-broker client bucket object read \
|
|
97
|
+
--target-json '{"kind":"bucket","namespace":"OWNER","name":"BUCKET"}' \
|
|
98
|
+
--arguments-json '{"path":"artifacts/result.bin"}' \
|
|
99
|
+
--output ./downloaded-result.bin \
|
|
100
|
+
--reason "Read the requested result" \
|
|
101
|
+
--wait=true \
|
|
102
|
+
--wait-timeout 15m
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Use `hf_bucket_object_list` or the matching client command to inspect only the
|
|
106
|
+
approved bucket prefix. Do not use the ML Claw state bucket for agent work. Its
|
|
107
|
+
exact target is denied by deployment policy, and approval cannot override that
|
|
108
|
+
deny.
|
|
109
|
+
|
|
110
|
+
## Recover operations
|
|
111
|
+
|
|
112
|
+
A timeout may leave a durable operation pending. Continue with its operation ID
|
|
113
|
+
or recover it by request ID:
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
hf-broker client operation get OPERATION-ID
|
|
117
|
+
hf-broker client operation wait --wait-timeout 15m OPERATION-ID
|
|
118
|
+
hf-broker client operation cancel OPERATION-ID
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
If the operation ID was lost, call the `hf_operation_list` MCP tool with the
|
|
122
|
+
stable `request_id`, then continue with the returned operation ID.
|
|
123
|
+
|
|
124
|
+
Stop only after a terminal result, explicit cancellation, or an unrecoverable
|
|
125
|
+
broker error. Revocation and expiry prevent later matching writes from reaching
|
|
126
|
+
Hugging Face.
|
package/dist/hf-tooling-seed.js
CHANGED
|
@@ -140,6 +140,13 @@ conflict is durable: inspect the existing operation instead of restarting the
|
|
|
140
140
|
broker. Protected actions appear in the ML Claw BrokerKit control and may also
|
|
141
141
|
be sent through configured OpenClaw channels.
|
|
142
142
|
|
|
143
|
+
For repeated repository or bucket writes, request the narrowest temporary grant
|
|
144
|
+
with \`hf_grant_request\`. A bounded wait may return a pending grant; continue
|
|
145
|
+
with \`hf_grant_wait\` using the same grant ID. Revoke the grant when the work is
|
|
146
|
+
finished. Use the installed \`hf-broker\` client for local file upload and
|
|
147
|
+
verified download streams. Never use the deployment state bucket for agent
|
|
148
|
+
work; its exact target is denied by policy.
|
|
149
|
+
|
|
143
150
|
After repository creation, use the brokered Git transport for repository
|
|
144
151
|
contents. The limited broker credential is not a Hugging Face Hub token; do
|
|
145
152
|
not report it as missing Hub access.
|
|
@@ -210,11 +217,21 @@ function assertToolingManifest(value) {
|
|
|
210
217
|
if (!skills || !Array.isArray(skills.installed) || !skills.installed.every((skill) => typeof skill === "string")) {
|
|
211
218
|
throw new Error("HF tooling manifest must list installed skills");
|
|
212
219
|
}
|
|
220
|
+
if (!Array.isArray(skills.managed) || !skills.managed.every(isManagedSkillSource)) {
|
|
221
|
+
throw new Error("HF tooling manifest must list managed skill sources");
|
|
222
|
+
}
|
|
213
223
|
const python = record.python;
|
|
214
224
|
if (!python || typeof python.packages !== "object" || python.packages === null) {
|
|
215
225
|
throw new Error("HF tooling manifest must list Python packages");
|
|
216
226
|
}
|
|
217
227
|
}
|
|
228
|
+
function isManagedSkillSource(value) {
|
|
229
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
230
|
+
const source = value;
|
|
231
|
+
return [source.name, source.source, source.revision].every(
|
|
232
|
+
(field) => typeof field === "string" && field.trim().length > 0
|
|
233
|
+
);
|
|
234
|
+
}
|
|
218
235
|
async function copyMissingTree(sourceRoot, targetRoot) {
|
|
219
236
|
const copied = [];
|
|
220
237
|
await assertDirectory(sourceRoot, "HF tooling templates");
|
|
@@ -947,6 +947,8 @@ var formats = import_formats.default.fullFormats;
|
|
|
947
947
|
var equal = import_equal.default.default ?? import_equal.default;
|
|
948
948
|
var ucs2length = import_ucs2length.default.default ?? import_ucs2length.default;
|
|
949
949
|
var validateDescriptor = validate20;
|
|
950
|
+
var pattern4 = new RegExp("^sha256:[0-9a-f]{64}$", "u");
|
|
951
|
+
var func1 = ucs2length;
|
|
950
952
|
function validate20(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
|
|
951
953
|
;
|
|
952
954
|
let vErrors = null;
|
|
@@ -962,13 +964,13 @@ function validate20(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
962
964
|
if (errors === _errs0) {
|
|
963
965
|
if (data && typeof data == "object" && !Array.isArray(data)) {
|
|
964
966
|
let missing0;
|
|
965
|
-
if (data.api_version === void 0 && (missing0 = "api_version")) {
|
|
967
|
+
if (data.api_version === void 0 && (missing0 = "api_version") || data.contract_digest === void 0 && (missing0 = "contract_digest") || data.build_id === void 0 && (missing0 = "build_id")) {
|
|
966
968
|
validate20.errors = [{ instancePath, schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Descriptor/required", keyword: "required", params: { missingProperty: missing0 }, message: "must have required property '" + missing0 + "'" }];
|
|
967
969
|
return false;
|
|
968
970
|
} else {
|
|
969
971
|
const _errs2 = errors;
|
|
970
972
|
for (const key0 in data) {
|
|
971
|
-
if (!(key0 === "api_version")) {
|
|
973
|
+
if (!(key0 === "api_version" || key0 === "contract_digest" || key0 === "build_id")) {
|
|
972
974
|
validate20.errors = [{ instancePath, schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Descriptor/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" }];
|
|
973
975
|
return false;
|
|
974
976
|
break;
|
|
@@ -977,6 +979,7 @@ function validate20(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
977
979
|
if (_errs2 === errors) {
|
|
978
980
|
if (data.api_version !== void 0) {
|
|
979
981
|
let data0 = data.api_version;
|
|
982
|
+
const _errs3 = errors;
|
|
980
983
|
if (typeof data0 !== "string") {
|
|
981
984
|
validate20.errors = [{ instancePath: instancePath + "/api_version", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Descriptor/properties/api_version/type", keyword: "type", params: { type: "string" }, message: "must be string" }];
|
|
982
985
|
return false;
|
|
@@ -985,6 +988,54 @@ function validate20(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
985
988
|
validate20.errors = [{ instancePath: instancePath + "/api_version", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Descriptor/properties/api_version/const", keyword: "const", params: { allowedValue: "brokerkit.io/operator/v1" }, message: "must be equal to constant" }];
|
|
986
989
|
return false;
|
|
987
990
|
}
|
|
991
|
+
var valid1 = _errs3 === errors;
|
|
992
|
+
} else {
|
|
993
|
+
var valid1 = true;
|
|
994
|
+
}
|
|
995
|
+
if (valid1) {
|
|
996
|
+
if (data.contract_digest !== void 0) {
|
|
997
|
+
let data1 = data.contract_digest;
|
|
998
|
+
const _errs5 = errors;
|
|
999
|
+
if (errors === _errs5) {
|
|
1000
|
+
if (typeof data1 === "string") {
|
|
1001
|
+
if (!pattern4.test(data1)) {
|
|
1002
|
+
validate20.errors = [{ instancePath: instancePath + "/contract_digest", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Descriptor/properties/contract_digest/pattern", keyword: "pattern", params: { pattern: "^sha256:[0-9a-f]{64}$" }, message: 'must match pattern "^sha256:[0-9a-f]{64}$"' }];
|
|
1003
|
+
return false;
|
|
1004
|
+
}
|
|
1005
|
+
} else {
|
|
1006
|
+
validate20.errors = [{ instancePath: instancePath + "/contract_digest", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Descriptor/properties/contract_digest/type", keyword: "type", params: { type: "string" }, message: "must be string" }];
|
|
1007
|
+
return false;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
var valid1 = _errs5 === errors;
|
|
1011
|
+
} else {
|
|
1012
|
+
var valid1 = true;
|
|
1013
|
+
}
|
|
1014
|
+
if (valid1) {
|
|
1015
|
+
if (data.build_id !== void 0) {
|
|
1016
|
+
let data2 = data.build_id;
|
|
1017
|
+
const _errs7 = errors;
|
|
1018
|
+
if (errors === _errs7) {
|
|
1019
|
+
if (typeof data2 === "string") {
|
|
1020
|
+
if (func1(data2) > 128) {
|
|
1021
|
+
validate20.errors = [{ instancePath: instancePath + "/build_id", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Descriptor/properties/build_id/maxLength", keyword: "maxLength", params: { limit: 128 }, message: "must NOT have more than 128 characters" }];
|
|
1022
|
+
return false;
|
|
1023
|
+
} else {
|
|
1024
|
+
if (func1(data2) < 1) {
|
|
1025
|
+
validate20.errors = [{ instancePath: instancePath + "/build_id", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Descriptor/properties/build_id/minLength", keyword: "minLength", params: { limit: 1 }, message: "must NOT have fewer than 1 characters" }];
|
|
1026
|
+
return false;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
} else {
|
|
1030
|
+
validate20.errors = [{ instancePath: instancePath + "/build_id", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Descriptor/properties/build_id/type", keyword: "type", params: { type: "string" }, message: "must be string" }];
|
|
1031
|
+
return false;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
var valid1 = _errs7 === errors;
|
|
1035
|
+
} else {
|
|
1036
|
+
var valid1 = true;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
988
1039
|
}
|
|
989
1040
|
}
|
|
990
1041
|
}
|
|
@@ -997,7 +1048,6 @@ function validate20(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
997
1048
|
return errors === 0;
|
|
998
1049
|
}
|
|
999
1050
|
validate20.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
|
|
1000
|
-
var func1 = ucs2length;
|
|
1001
1051
|
function validate22(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
|
|
1002
1052
|
;
|
|
1003
1053
|
let vErrors = null;
|
|
@@ -1013,13 +1063,13 @@ function validate22(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
1013
1063
|
if (errors === _errs0) {
|
|
1014
1064
|
if (data && typeof data == "object" && !Array.isArray(data)) {
|
|
1015
1065
|
let missing0;
|
|
1016
|
-
if (data.status === void 0 && (missing0 = "status")) {
|
|
1066
|
+
if (data.status === void 0 && (missing0 = "status") || data.contract_digest === void 0 && (missing0 = "contract_digest") || data.build_id === void 0 && (missing0 = "build_id")) {
|
|
1017
1067
|
validate22.errors = [{ instancePath, schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Health/required", keyword: "required", params: { missingProperty: missing0 }, message: "must have required property '" + missing0 + "'" }];
|
|
1018
1068
|
return false;
|
|
1019
1069
|
} else {
|
|
1020
1070
|
const _errs2 = errors;
|
|
1021
1071
|
for (const key0 in data) {
|
|
1022
|
-
if (!(key0 === "status")) {
|
|
1072
|
+
if (!(key0 === "status" || key0 === "contract_digest" || key0 === "build_id")) {
|
|
1023
1073
|
validate22.errors = [{ instancePath, schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Health/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" }];
|
|
1024
1074
|
return false;
|
|
1025
1075
|
break;
|
|
@@ -1045,6 +1095,54 @@ function validate22(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
1045
1095
|
return false;
|
|
1046
1096
|
}
|
|
1047
1097
|
}
|
|
1098
|
+
var valid1 = _errs3 === errors;
|
|
1099
|
+
} else {
|
|
1100
|
+
var valid1 = true;
|
|
1101
|
+
}
|
|
1102
|
+
if (valid1) {
|
|
1103
|
+
if (data.contract_digest !== void 0) {
|
|
1104
|
+
let data1 = data.contract_digest;
|
|
1105
|
+
const _errs5 = errors;
|
|
1106
|
+
if (errors === _errs5) {
|
|
1107
|
+
if (typeof data1 === "string") {
|
|
1108
|
+
if (!pattern4.test(data1)) {
|
|
1109
|
+
validate22.errors = [{ instancePath: instancePath + "/contract_digest", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Health/properties/contract_digest/pattern", keyword: "pattern", params: { pattern: "^sha256:[0-9a-f]{64}$" }, message: 'must match pattern "^sha256:[0-9a-f]{64}$"' }];
|
|
1110
|
+
return false;
|
|
1111
|
+
}
|
|
1112
|
+
} else {
|
|
1113
|
+
validate22.errors = [{ instancePath: instancePath + "/contract_digest", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Health/properties/contract_digest/type", keyword: "type", params: { type: "string" }, message: "must be string" }];
|
|
1114
|
+
return false;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
var valid1 = _errs5 === errors;
|
|
1118
|
+
} else {
|
|
1119
|
+
var valid1 = true;
|
|
1120
|
+
}
|
|
1121
|
+
if (valid1) {
|
|
1122
|
+
if (data.build_id !== void 0) {
|
|
1123
|
+
let data2 = data.build_id;
|
|
1124
|
+
const _errs7 = errors;
|
|
1125
|
+
if (errors === _errs7) {
|
|
1126
|
+
if (typeof data2 === "string") {
|
|
1127
|
+
if (func1(data2) > 128) {
|
|
1128
|
+
validate22.errors = [{ instancePath: instancePath + "/build_id", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Health/properties/build_id/maxLength", keyword: "maxLength", params: { limit: 128 }, message: "must NOT have more than 128 characters" }];
|
|
1129
|
+
return false;
|
|
1130
|
+
} else {
|
|
1131
|
+
if (func1(data2) < 1) {
|
|
1132
|
+
validate22.errors = [{ instancePath: instancePath + "/build_id", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Health/properties/build_id/minLength", keyword: "minLength", params: { limit: 1 }, message: "must NOT have fewer than 1 characters" }];
|
|
1133
|
+
return false;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
} else {
|
|
1137
|
+
validate22.errors = [{ instancePath: instancePath + "/build_id", schemaPath: "https://brokerkit.dev/schema/operator/v1/runtime/components#/$defs/Health/properties/build_id/type", keyword: "type", params: { type: "string" }, message: "must be string" }];
|
|
1138
|
+
return false;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
var valid1 = _errs7 === errors;
|
|
1142
|
+
} else {
|
|
1143
|
+
var valid1 = true;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1048
1146
|
}
|
|
1049
1147
|
}
|
|
1050
1148
|
}
|
|
@@ -1062,7 +1160,7 @@ var schema37 = { "type": "object", "additionalProperties": false, "required": ["
|
|
|
1062
1160
|
var schema38 = { "type": "string", "enum": ["pending", "active", "denied", "canceled", "expired", "consumed", "revoked"] };
|
|
1063
1161
|
var schema44 = { "type": "string", "enum": ["approve", "deny", "revoke"] };
|
|
1064
1162
|
var schema45 = { "type": "object", "additionalProperties": false, "required": ["max_duration_seconds", "max_uses"], "properties": { "max_duration_seconds": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "max_uses": { "type": ["integer", "null"], "minimum": 1, "maximum": 9007199254740991 } } };
|
|
1065
|
-
var
|
|
1163
|
+
var func7 = Object.prototype.hasOwnProperty;
|
|
1066
1164
|
var func0 = equal;
|
|
1067
1165
|
var formats0 = formats["date-time"];
|
|
1068
1166
|
var schema40 = { "type": "string", "enum": ["unknown", "low", "medium", "high", "critical"] };
|
|
@@ -1441,7 +1539,7 @@ function validate24(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
1441
1539
|
} else {
|
|
1442
1540
|
const _errs1 = errors;
|
|
1443
1541
|
for (const key0 in data) {
|
|
1444
|
-
if (!
|
|
1542
|
+
if (!func7.call(schema37.properties, key0)) {
|
|
1445
1543
|
validate24.errors = [{ instancePath, schemaPath: "#/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" }];
|
|
1446
1544
|
return false;
|
|
1447
1545
|
break;
|
|
@@ -2022,7 +2120,7 @@ function validate32(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
2022
2120
|
} else {
|
|
2023
2121
|
const _errs1 = errors;
|
|
2024
2122
|
for (const key0 in data) {
|
|
2025
|
-
if (!
|
|
2123
|
+
if (!func7.call(schema37.properties, key0)) {
|
|
2026
2124
|
validate32.errors = [{ instancePath, schemaPath: "#/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" }];
|
|
2027
2125
|
return false;
|
|
2028
2126
|
break;
|
|
@@ -3083,7 +3181,7 @@ function validate39(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
3083
3181
|
return errors === 0;
|
|
3084
3182
|
}
|
|
3085
3183
|
validate39.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
|
|
3086
|
-
var
|
|
3184
|
+
var pattern6 = new RegExp("^[A-Za-z0-9_-]+$", "u");
|
|
3087
3185
|
function validate47(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
|
|
3088
3186
|
let vErrors = null;
|
|
3089
3187
|
let errors = 0;
|
|
@@ -3171,7 +3269,7 @@ function validate47(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
3171
3269
|
validate47.errors = [{ instancePath: instancePath + "/handle", schemaPath: "#/properties/handle/minLength", keyword: "minLength", params: { limit: 22 }, message: "must NOT have fewer than 22 characters" }];
|
|
3172
3270
|
return false;
|
|
3173
3271
|
} else {
|
|
3174
|
-
if (!
|
|
3272
|
+
if (!pattern6.test(data2)) {
|
|
3175
3273
|
validate47.errors = [{ instancePath: instancePath + "/handle", schemaPath: "#/properties/handle/pattern", keyword: "pattern", params: { pattern: "^[A-Za-z0-9_-]+$" }, message: 'must match pattern "^[A-Za-z0-9_-]+$"' }];
|
|
3176
3274
|
return false;
|
|
3177
3275
|
}
|
|
@@ -3841,7 +3939,7 @@ function validate54(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
3841
3939
|
validate54.errors = [{ instancePath: instancePath + "/handle", schemaPath: "#/properties/handle/minLength", keyword: "minLength", params: { limit: 22 }, message: "must NOT have fewer than 22 characters" }];
|
|
3842
3940
|
return false;
|
|
3843
3941
|
} else {
|
|
3844
|
-
if (!
|
|
3942
|
+
if (!pattern6.test(data2)) {
|
|
3845
3943
|
validate54.errors = [{ instancePath: instancePath + "/handle", schemaPath: "#/properties/handle/pattern", keyword: "pattern", params: { pattern: "^[A-Za-z0-9_-]+$" }, message: 'must match pattern "^[A-Za-z0-9_-]+$"' }];
|
|
3846
3944
|
return false;
|
|
3847
3945
|
}
|
package/dist/mlclaw.mjs
CHANGED
|
@@ -15383,10 +15383,10 @@ function nextLink(header) {
|
|
|
15383
15383
|
|
|
15384
15384
|
// src/mlclaw/release-config.generated.ts
|
|
15385
15385
|
var RELEASE_CONFIG = {
|
|
15386
|
-
"packageVersion": "0.
|
|
15386
|
+
"packageVersion": "0.5.0",
|
|
15387
15387
|
"openclawVersion": "2026.7.1",
|
|
15388
|
-
"brokerkitVersion": "hf-broker/v0.
|
|
15389
|
-
"brokerkitPluginVersion": "0.
|
|
15388
|
+
"brokerkitVersion": "hf-broker/v0.6.2",
|
|
15389
|
+
"brokerkitPluginVersion": "0.4.1",
|
|
15390
15390
|
"runtimeImageRepository": "ghcr.io/huggingface/mlclaw"
|
|
15391
15391
|
};
|
|
15392
15392
|
|
|
@@ -15530,6 +15530,7 @@ RUN apt-get update \\
|
|
|
15530
15530
|
&& rm -rf /var/lib/apt/lists/*
|
|
15531
15531
|
RUN python3 -m pip install --break-system-packages --no-cache-dir \\
|
|
15532
15532
|
"huggingface_hub==1.19.0" \\
|
|
15533
|
+
"hf-xet==1.5.2" \\
|
|
15533
15534
|
"datasets==5.0.0" \\
|
|
15534
15535
|
"safetensors==0.8.0" \\
|
|
15535
15536
|
"fastapi==0.137.1" \\
|
package/entrypoint.sh
CHANGED
|
@@ -9,6 +9,8 @@ export MLCLAW_OPENCLAW_UID="$OPENCLAW_UID"
|
|
|
9
9
|
export MLCLAW_OPENCLAW_GID="$OPENCLAW_GID"
|
|
10
10
|
HF_BROKER_ENABLED=0
|
|
11
11
|
HF_BROKER_RUN_DIR="/run/mlclaw-hf-broker"
|
|
12
|
+
HF_BROKER_POLICY_DIR="$HF_BROKER_RUN_DIR/policy"
|
|
13
|
+
HF_BROKER_SCOPE_FILE="$HF_BROKER_POLICY_DIR/scope.json"
|
|
12
14
|
STATE_HF_TOKEN=""
|
|
13
15
|
RESTORED_PROTECTED_STATE_DIR="$LIVE_DIR/.mlclaw-protected"
|
|
14
16
|
PROTECTED_STATE_DIR="/var/lib/mlclaw-protected"
|
|
@@ -50,6 +52,8 @@ prepare_hf_broker() {
|
|
|
50
52
|
|
|
51
53
|
export MLCLAW_HF_BROKER_URL="http://127.0.0.1:7863"
|
|
52
54
|
export MLCLAW_HF_BROKER_AGENT_SECRET_FILE="$agent_secret_file"
|
|
55
|
+
export HF_BROKER_AGENT_ENDPOINT="tcp://127.0.0.1:7863"
|
|
56
|
+
export HF_BROKER_SHARED_SECRET_FILE="$agent_secret_file"
|
|
53
57
|
if [ "${MLCLAW_GATEWAY_LOCATION:-}" = "local" ]; then
|
|
54
58
|
export MLCLAW_TRUSTED_HF_TOKEN_FILE="$token_file"
|
|
55
59
|
fi
|
|
@@ -81,6 +85,32 @@ restore_protected_state() {
|
|
|
81
85
|
chmod 0700 "$PROTECTED_STATE_DIR/control" "$HF_BROKER_STATE_DIR"
|
|
82
86
|
}
|
|
83
87
|
|
|
88
|
+
render_hf_broker_policy() {
|
|
89
|
+
if [ "$HF_BROKER_ENABLED" != "1" ]; then
|
|
90
|
+
return
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
local state_bucket="${OPENCLAW_HF_STATE_BUCKET:-}"
|
|
94
|
+
local protected_target=()
|
|
95
|
+
if [ -n "$state_bucket" ]; then
|
|
96
|
+
protected_target=(--protect-bucket "$state_bucket")
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
install -d -m 0700 -o hf-broker -g hf-broker "$HF_BROKER_POLICY_DIR"
|
|
100
|
+
gosu hf-broker:hf-broker /usr/local/bin/hf-broker policy render \
|
|
101
|
+
--preset request-all-agent-operations \
|
|
102
|
+
--client default \
|
|
103
|
+
--profile-out "$HF_BROKER_POLICY_DIR/profile.json" \
|
|
104
|
+
--output "$HF_BROKER_SCOPE_FILE" \
|
|
105
|
+
--manifest-out "$HF_BROKER_POLICY_DIR/manifest.json" \
|
|
106
|
+
--replace \
|
|
107
|
+
"${protected_target[@]}"
|
|
108
|
+
gosu hf-broker:hf-broker /usr/local/bin/hf-broker doctor policy \
|
|
109
|
+
--profile "$HF_BROKER_POLICY_DIR/profile.json" \
|
|
110
|
+
--scope "$HF_BROKER_SCOPE_FILE" \
|
|
111
|
+
--manifest "$HF_BROKER_POLICY_DIR/manifest.json"
|
|
112
|
+
}
|
|
113
|
+
|
|
84
114
|
start_hf_broker() {
|
|
85
115
|
if [ "$HF_BROKER_ENABLED" != "1" ]; then
|
|
86
116
|
return
|
|
@@ -95,7 +125,8 @@ start_hf_broker() {
|
|
|
95
125
|
HF_BROKER_OPERATOR_SECRETS_FILE="$HF_BROKER_RUN_DIR/operator-secrets.conf" \
|
|
96
126
|
HF_BROKER_AGENT_ENDPOINT=tcp://127.0.0.1:7863 \
|
|
97
127
|
HF_BROKER_OPERATOR_ENDPOINT=tcp://127.0.0.1:7864 \
|
|
98
|
-
HF_BROKER_SCOPE_FILE
|
|
128
|
+
HF_BROKER_SCOPE_FILE="$HF_BROKER_SCOPE_FILE" \
|
|
129
|
+
HF_BROKER_XET_PYTHON=/usr/bin/python3 \
|
|
99
130
|
HF_BROKER_STATE_DIR="$HF_BROKER_STATE_DIR" \
|
|
100
131
|
gosu hf-broker:hf-broker /usr/local/bin/hf-broker &
|
|
101
132
|
HF_BROKER_PID=$!
|
|
@@ -172,6 +203,7 @@ mkdir -p "$LIVE_DIR" "$WORKSPACE_DIR" "$STATE_DIR"
|
|
|
172
203
|
chown_openclaw_live
|
|
173
204
|
install -d -m 0710 -o root -g hf-broker "$PROTECTED_STATE_DIR"
|
|
174
205
|
install -d -m 0700 -o root -g root "$PROTECTED_STATE_DIR/control"
|
|
206
|
+
render_hf_broker_policy
|
|
175
207
|
start_hf_broker
|
|
176
208
|
|
|
177
209
|
if [ -n "${OPENCLAW_AGENT_NAME:-}" ]; then
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mlclaw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"config": {
|
|
6
6
|
"openclawVersion": "2026.7.1",
|
|
7
|
-
"brokerkitVersion": "hf-broker/v0.
|
|
8
|
-
"brokerkitPluginVersion": "0.
|
|
7
|
+
"brokerkitVersion": "hf-broker/v0.6.2",
|
|
8
|
+
"brokerkitPluginVersion": "0.4.1",
|
|
9
9
|
"runtimeImageRepository": "ghcr.io/huggingface/mlclaw"
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"commander": "^14.0.3",
|
|
77
77
|
"hono": "^4.12.28",
|
|
78
78
|
"lucide-react": "^0.468.0",
|
|
79
|
-
"openclaw-brokerkit": "0.
|
|
79
|
+
"openclaw-brokerkit": "0.4.1",
|
|
80
80
|
"react": "^19.2.7",
|
|
81
81
|
"react-dom": "^19.2.7",
|
|
82
82
|
"skillflag": "^0.2.0",
|