mlclaw 0.4.10 → 0.6.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/.agents/skills/mlclaw/SKILL.md +14 -0
- package/Dockerfile +3 -2
- package/README.md +35 -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 +6029 -301
- package/dist/mlclaw.mjs +698 -18
- package/entrypoint.sh +33 -1
- package/package.json +5 -5
|
@@ -290,6 +290,20 @@ settings to set a Space Secret; do not put the user's broad Hub token into the
|
|
|
290
290
|
Space just so the browser app can mutate secrets. The key must never be logged
|
|
291
291
|
or returned to the browser.
|
|
292
292
|
|
|
293
|
+
Deployment-scoped ChatGPT login uses OpenAI's Codex device-code protocol
|
|
294
|
+
directly and does not require the Codex CLI:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
mlclaw credentials codex login <agent>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
After login, ML Claw imports the deployment credential into a managed native
|
|
301
|
+
OpenClaw OAuth profile. OpenClaw contacts OpenAI directly, refreshes the OAuth
|
|
302
|
+
credential in its private auth store, and discovers the account-visible catalog
|
|
303
|
+
under `openai/*`, including `openai/gpt-5.6-sol` when entitled. ML Claw does not
|
|
304
|
+
proxy model discovery or inference. Normal `OPENAI_API_KEY` profiles continue
|
|
305
|
+
to use the OpenAI Platform route.
|
|
306
|
+
|
|
293
307
|
## Branding
|
|
294
308
|
|
|
295
309
|
ML Claw white-labels the browser gateway at the proxy layer. App Spaces default
|
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
3
|
ARG BROKERKIT_PLUGIN_VERSION=0.4.1
|
|
4
|
-
ARG BROKERKIT_VERSION=hf-broker/v0.
|
|
5
|
-
ARG MLCLAW_RUNTIME_IMAGE=ghcr.io/huggingface/mlclaw:0.
|
|
4
|
+
ARG BROKERKIT_VERSION=hf-broker/v0.6.2
|
|
5
|
+
ARG MLCLAW_RUNTIME_IMAGE=ghcr.io/huggingface/mlclaw:0.6.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
|
@@ -371,6 +371,32 @@ never returned to the browser, exposed to the agent except as its intended
|
|
|
371
371
|
OpenAI credential, or stored as plaintext in the state bucket. App Spaces do
|
|
372
372
|
not keep broad Hugging Face authority in the web control process.
|
|
373
373
|
|
|
374
|
+
To connect an OpenAI/ChatGPT account through Codex device login instead of an
|
|
375
|
+
API key, target the specific deployment. ML Claw performs the device-code flow
|
|
376
|
+
directly over HTTPS. It does not install, invoke, or depend on the Codex CLI.
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
mlclaw credentials codex login mlclaw
|
|
380
|
+
mlclaw credentials codex status mlclaw
|
|
381
|
+
mlclaw credentials codex logout mlclaw
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
`login` requests a one-time device code from OpenAI, prints the verification
|
|
385
|
+
URL and code, polls for approval, encrypts the OAuth credential into the
|
|
386
|
+
selected deployment's private state bucket, and restarts the deployment.
|
|
387
|
+
OpenClaw then discovers the models visible to that ChatGPT account under its
|
|
388
|
+
native `openai/*` provider. For example, an entitled account may expose
|
|
389
|
+
`openai/gpt-5.6-sol` alongside the other live Codex models.
|
|
390
|
+
|
|
391
|
+
At startup, ML Claw imports the encrypted login into a managed native OpenClaw
|
|
392
|
+
OAuth profile. OpenClaw then contacts OpenAI directly for model discovery,
|
|
393
|
+
Responses requests, and token refresh; ML Claw is not in the inference path.
|
|
394
|
+
OpenClaw keeps its own model names, metadata, transport, and refreshed
|
|
395
|
+
credential, and a normal `OPENAI_API_KEY` profile can coexist with the ChatGPT
|
|
396
|
+
route. `status` and `logout` inspect or revoke the deployment-scoped login
|
|
397
|
+
without exposing tokens. Raw OAuth tokens are never printed, stored in the
|
|
398
|
+
Space repository or model configuration, or included in workspace files.
|
|
399
|
+
|
|
374
400
|
## How State Works
|
|
375
401
|
|
|
376
402
|
OpenClaw runs against local disk inside the active runtime. In Space gateway
|
|
@@ -384,8 +410,15 @@ across Space rebuilds, local container replacement, and gateway migration. The
|
|
|
384
410
|
Space does not use `HF_TOKEN` or `HUGGINGFACE_HUB_TOKEN` secrets. Its broad
|
|
385
411
|
credential is stored as `MLCLAW_BROKER_HF_TOKEN`, written to a broker-owned
|
|
386
412
|
`0600` file during startup, and removed from child-process environments.
|
|
387
|
-
OpenClaw uses only the generated broker agent credential.
|
|
388
|
-
|
|
413
|
+
OpenClaw uses only the generated broker agent credential. At startup, ML Claw
|
|
414
|
+
asks HF Broker to render the active policy with the exact deployment state
|
|
415
|
+
bucket protected. Agent requests against that bucket are denied before an
|
|
416
|
+
approval is created. Other repository paths and bucket key prefixes can use
|
|
417
|
+
operator-approved grants lasting up to 24 hours or seven days; the installed
|
|
418
|
+
`hf-broker` skill explains request, wait, recovery, write, read, and revocation
|
|
419
|
+
workflows.
|
|
420
|
+
|
|
421
|
+
Broker grant and event state and encrypted control credentials live under the root-owned
|
|
389
422
|
`/var/lib/mlclaw-protected` tree. They are included in the durable snapshot
|
|
390
423
|
through a root-only `.mlclaw-protected` staging step, then restored outside the
|
|
391
424
|
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");
|