mlclaw 0.1.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 +214 -0
- package/.agents/skills/mlclaw/agents/openai.yaml +4 -0
- package/.gitattributes +35 -0
- package/Dockerfile +45 -0
- package/LICENSE +21 -0
- package/README.md +206 -0
- package/assets/mlclaw.svg +143 -0
- package/dist/hf-state-sync.js +9532 -0
- package/dist/mlclaw-space-runtime.js +5010 -0
- package/dist/mlclaw.mjs +16502 -0
- package/entrypoint.sh +87 -0
- package/mlclaw.ps1 +108 -0
- package/mlclaw.sh +117 -0
- package/openclaw.default.json +67 -0
- package/package.json +66 -0
- package/scripts/configure-huggingface-model.mjs +86 -0
- package/scripts/configure-telegram.mjs +55 -0
- package/scripts/report-telegram-probe.mjs +18 -0
- package/space/README.md +42 -0
- package/src/hf-bucket-client/client.ts +217 -0
- package/src/hf-state-sync/archive.ts +137 -0
- package/src/hf-state-sync/cli.ts +92 -0
- package/src/hf-state-sync/hub.ts +81 -0
- package/src/hf-state-sync/manifest.ts +67 -0
- package/src/hf-state-sync/paths.ts +73 -0
- package/src/hf-state-sync/restore.ts +109 -0
- package/src/hf-state-sync/snapshot.ts +133 -0
- package/src/hf-state-sync/sqlite.ts +57 -0
- package/src/hf-state-sync/supervise.ts +256 -0
- package/src/vendor/hfjs-xet/error.ts +52 -0
- package/src/vendor/hfjs-xet/types/public.ts +207 -0
- package/src/vendor/hfjs-xet/utils/ChunkCache.ts +102 -0
- package/src/vendor/hfjs-xet/utils/RangeList.ts +182 -0
- package/src/vendor/hfjs-xet/utils/SplicedBlob.ts +249 -0
- package/src/vendor/hfjs-xet/utils/XetBlob.ts +732 -0
- package/src/vendor/hfjs-xet/utils/checkCredentials.ts +21 -0
- package/src/vendor/hfjs-xet/utils/combineUint8Arrays.ts +13 -0
- package/src/vendor/hfjs-xet/utils/createXorbs.ts +782 -0
- package/src/vendor/hfjs-xet/utils/shardParser.ts +152 -0
- package/src/vendor/hfjs-xet/utils/sum.ts +9 -0
- package/src/vendor/hfjs-xet/utils/uploadShards.ts +443 -0
- package/src/vendor/hfjs-xet/utils/xetWriteToken.ts +101 -0
- package/src/vendor/hfjs-xet/vendor/lz4js/index.ts +540 -0
- package/src/vendor/hfjs-xet/vendor/lz4js/util.ts +57 -0
- package/src/vendor/hfjs-xet/vendor/lz4js/xxh32.ts +99 -0
- package/src/vendor/hfjs-xet/vendor/type-fest/basic.ts +34 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
// @ts-nocheck -- vendored upstream code, kept verbatim; our strict tsconfig does not apply.
|
|
2
|
+
// Vendored from huggingface/huggingface.js@f8fdf6be (packages/hub/src/utils/SplicedBlob.ts), MIT License.
|
|
3
|
+
// Delete this directory when bucket support is upstreamed to @huggingface/hub.
|
|
4
|
+
import { sum } from "./sum";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a single splice operation
|
|
8
|
+
*/
|
|
9
|
+
interface SpliceOperation {
|
|
10
|
+
insert: Blob;
|
|
11
|
+
start: number;
|
|
12
|
+
end: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*
|
|
18
|
+
* A SplicedBlob is a Blob that represents the result of splicing one or more insert blobs
|
|
19
|
+
* into an original blob at specified positions, replacing content between start and end.
|
|
20
|
+
*
|
|
21
|
+
* It is a drop-in replacement for the Blob class, so you can use it as a Blob.
|
|
22
|
+
* The splicing is done virtually without copying data until accessed.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const originalBlob = new Blob(["Hello, World!"]);
|
|
26
|
+
* const insertBlob = new Blob(["Beautiful "]);
|
|
27
|
+
* const splicedBlob = SplicedBlob.create(originalBlob, insertBlob, 7, 7);
|
|
28
|
+
* // Result represents: "Hello, Beautiful World!"
|
|
29
|
+
*/
|
|
30
|
+
export class SplicedBlob extends Blob {
|
|
31
|
+
public originalBlob: Blob;
|
|
32
|
+
public spliceOperations: SpliceOperation[];
|
|
33
|
+
|
|
34
|
+
private constructor(originalBlob: Blob, spliceOperations: SpliceOperation[]) {
|
|
35
|
+
super();
|
|
36
|
+
|
|
37
|
+
this.originalBlob = originalBlob;
|
|
38
|
+
this.spliceOperations = spliceOperations; // Create a copy to prevent external mutation
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static create(originalBlob: Blob, operations: SpliceOperation[]): SplicedBlob {
|
|
42
|
+
// Validate all operations
|
|
43
|
+
for (const op of operations) {
|
|
44
|
+
if (op.start < 0 || op.end < 0) {
|
|
45
|
+
throw new Error("Invalid start/end positions for SplicedBlob");
|
|
46
|
+
}
|
|
47
|
+
if (op.start > originalBlob.size || op.end > originalBlob.size) {
|
|
48
|
+
throw new Error("Invalid start/end positions for SplicedBlob");
|
|
49
|
+
}
|
|
50
|
+
if (op.start > op.end) {
|
|
51
|
+
throw new Error("Invalid start/end positions for SplicedBlob");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Sort operations by start position and validate no overlaps
|
|
56
|
+
const sortedOps = [...operations].sort((a, b) => a.start - b.start);
|
|
57
|
+
for (let i = 0; i < sortedOps.length - 1; i++) {
|
|
58
|
+
if (sortedOps[i].end > sortedOps[i + 1].start) {
|
|
59
|
+
throw new Error("Overlapping splice operations are not supported");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return new SplicedBlob(originalBlob, sortedOps);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Returns the size of the spliced blob.
|
|
68
|
+
* Size = original size - total replaced size + total insert size
|
|
69
|
+
*/
|
|
70
|
+
override get size(): number {
|
|
71
|
+
let totalReplacedSize = 0;
|
|
72
|
+
let totalInsertSize = 0;
|
|
73
|
+
|
|
74
|
+
for (const op of this.spliceOperations) {
|
|
75
|
+
totalReplacedSize += op.end - op.start;
|
|
76
|
+
totalInsertSize += op.insert.size;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return this.originalBlob.size - totalReplacedSize + totalInsertSize;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Returns the MIME type of the original blob.
|
|
84
|
+
*/
|
|
85
|
+
override get type(): string {
|
|
86
|
+
return this.originalBlob.type;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Returns a new instance of SplicedBlob that is a slice of the current one.
|
|
91
|
+
*
|
|
92
|
+
* The slice is inclusive of the start and exclusive of the end.
|
|
93
|
+
* The slice method does not support negative start/end.
|
|
94
|
+
*
|
|
95
|
+
* @param start beginning of the slice
|
|
96
|
+
* @param end end of the slice
|
|
97
|
+
*/
|
|
98
|
+
override slice(start = 0, end = this.size): Blob {
|
|
99
|
+
if (start < 0 || end < 0) {
|
|
100
|
+
throw new TypeError("Unsupported negative start/end on SplicedBlob.slice");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
start = Math.min(start, this.size);
|
|
104
|
+
end = Math.min(end, this.size);
|
|
105
|
+
|
|
106
|
+
if (start >= end) {
|
|
107
|
+
return new Blob([]);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Get all segments and calculate their cumulative positions
|
|
111
|
+
const segments = this.segments;
|
|
112
|
+
const segmentBoundaries: number[] = [0];
|
|
113
|
+
let cumulativeSize = 0;
|
|
114
|
+
|
|
115
|
+
for (const segment of segments) {
|
|
116
|
+
cumulativeSize += segment.size;
|
|
117
|
+
segmentBoundaries.push(cumulativeSize);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Find which segments the slice spans
|
|
121
|
+
const resultSegments: Blob[] = [];
|
|
122
|
+
|
|
123
|
+
for (let i = 0; i < segments.length; i++) {
|
|
124
|
+
const segmentStart = segmentBoundaries[i];
|
|
125
|
+
const segmentEnd = segmentBoundaries[i + 1];
|
|
126
|
+
|
|
127
|
+
// Skip segments that are entirely before the slice
|
|
128
|
+
if (segmentEnd <= start) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Skip segments that are entirely after the slice
|
|
133
|
+
if (segmentStart >= end) {
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Calculate slice bounds within this segment
|
|
138
|
+
const sliceStart = Math.max(0, start - segmentStart);
|
|
139
|
+
const sliceEnd = Math.min(segments[i].size, end - segmentStart);
|
|
140
|
+
|
|
141
|
+
if (sliceStart < sliceEnd) {
|
|
142
|
+
resultSegments.push(segments[i].slice(sliceStart, sliceEnd));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return new Blob(resultSegments);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
get firstSpliceIndex(): number {
|
|
150
|
+
return this.spliceOperations[0]?.start ?? Infinity;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Read the spliced blob content and returns it as an ArrayBuffer.
|
|
155
|
+
*/
|
|
156
|
+
override async arrayBuffer(): Promise<ArrayBuffer> {
|
|
157
|
+
const segments = this.segments;
|
|
158
|
+
const buffers = await Promise.all(segments.map((segment) => segment.arrayBuffer()));
|
|
159
|
+
|
|
160
|
+
// Concatenate all buffers
|
|
161
|
+
const totalSize = sum(buffers.map((buffer) => buffer.byteLength));
|
|
162
|
+
const result = new Uint8Array(totalSize);
|
|
163
|
+
|
|
164
|
+
let offset = 0;
|
|
165
|
+
for (const buffer of buffers) {
|
|
166
|
+
result.set(new Uint8Array(buffer), offset);
|
|
167
|
+
offset += buffer.byteLength;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return result.buffer;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Read the spliced blob content and returns it as a string.
|
|
175
|
+
*/
|
|
176
|
+
override async text(): Promise<string> {
|
|
177
|
+
const buffer = await this.arrayBuffer();
|
|
178
|
+
return new TextDecoder().decode(buffer);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Returns a stream around the spliced blob content.
|
|
183
|
+
*/
|
|
184
|
+
override stream(): ReturnType<Blob["stream"]> {
|
|
185
|
+
const readable = new ReadableStream({
|
|
186
|
+
start: async (controller) => {
|
|
187
|
+
try {
|
|
188
|
+
const segments = this.segments;
|
|
189
|
+
|
|
190
|
+
for (const segment of segments) {
|
|
191
|
+
const reader = segment.stream().getReader();
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
while (true) {
|
|
195
|
+
const { done, value } = await reader.read();
|
|
196
|
+
if (done) {
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
controller.enqueue(value);
|
|
200
|
+
}
|
|
201
|
+
} finally {
|
|
202
|
+
reader.releaseLock();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
controller.close();
|
|
207
|
+
} catch (error) {
|
|
208
|
+
controller.error(error);
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
return readable;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get all segments that make up the spliced blob.
|
|
218
|
+
* This includes original blob segments between splice operations and insert blobs.
|
|
219
|
+
*/
|
|
220
|
+
private get segments(): Blob[] {
|
|
221
|
+
const segments: Blob[] = [];
|
|
222
|
+
let currentPosition = 0;
|
|
223
|
+
|
|
224
|
+
// Sort operations by start position to ensure correct order
|
|
225
|
+
const sortedOps = [...this.spliceOperations].sort((a, b) => a.start - b.start);
|
|
226
|
+
|
|
227
|
+
for (const op of sortedOps) {
|
|
228
|
+
// Add segment from current position to start of this operation
|
|
229
|
+
if (currentPosition < op.start) {
|
|
230
|
+
segments.push(this.originalBlob.slice(currentPosition, op.start));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Add the insert blob (if it has content)
|
|
234
|
+
if (op.insert.size > 0) {
|
|
235
|
+
segments.push(op.insert);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Move current position to end of this operation
|
|
239
|
+
currentPosition = op.end;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Add remaining segment after last operation
|
|
243
|
+
if (currentPosition < this.originalBlob.size) {
|
|
244
|
+
segments.push(this.originalBlob.slice(currentPosition));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return segments;
|
|
248
|
+
}
|
|
249
|
+
}
|