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.
Files changed (47) hide show
  1. package/.agents/skills/mlclaw/SKILL.md +214 -0
  2. package/.agents/skills/mlclaw/agents/openai.yaml +4 -0
  3. package/.gitattributes +35 -0
  4. package/Dockerfile +45 -0
  5. package/LICENSE +21 -0
  6. package/README.md +206 -0
  7. package/assets/mlclaw.svg +143 -0
  8. package/dist/hf-state-sync.js +9532 -0
  9. package/dist/mlclaw-space-runtime.js +5010 -0
  10. package/dist/mlclaw.mjs +16502 -0
  11. package/entrypoint.sh +87 -0
  12. package/mlclaw.ps1 +108 -0
  13. package/mlclaw.sh +117 -0
  14. package/openclaw.default.json +67 -0
  15. package/package.json +66 -0
  16. package/scripts/configure-huggingface-model.mjs +86 -0
  17. package/scripts/configure-telegram.mjs +55 -0
  18. package/scripts/report-telegram-probe.mjs +18 -0
  19. package/space/README.md +42 -0
  20. package/src/hf-bucket-client/client.ts +217 -0
  21. package/src/hf-state-sync/archive.ts +137 -0
  22. package/src/hf-state-sync/cli.ts +92 -0
  23. package/src/hf-state-sync/hub.ts +81 -0
  24. package/src/hf-state-sync/manifest.ts +67 -0
  25. package/src/hf-state-sync/paths.ts +73 -0
  26. package/src/hf-state-sync/restore.ts +109 -0
  27. package/src/hf-state-sync/snapshot.ts +133 -0
  28. package/src/hf-state-sync/sqlite.ts +57 -0
  29. package/src/hf-state-sync/supervise.ts +256 -0
  30. package/src/vendor/hfjs-xet/error.ts +52 -0
  31. package/src/vendor/hfjs-xet/types/public.ts +207 -0
  32. package/src/vendor/hfjs-xet/utils/ChunkCache.ts +102 -0
  33. package/src/vendor/hfjs-xet/utils/RangeList.ts +182 -0
  34. package/src/vendor/hfjs-xet/utils/SplicedBlob.ts +249 -0
  35. package/src/vendor/hfjs-xet/utils/XetBlob.ts +732 -0
  36. package/src/vendor/hfjs-xet/utils/checkCredentials.ts +21 -0
  37. package/src/vendor/hfjs-xet/utils/combineUint8Arrays.ts +13 -0
  38. package/src/vendor/hfjs-xet/utils/createXorbs.ts +782 -0
  39. package/src/vendor/hfjs-xet/utils/shardParser.ts +152 -0
  40. package/src/vendor/hfjs-xet/utils/sum.ts +9 -0
  41. package/src/vendor/hfjs-xet/utils/uploadShards.ts +443 -0
  42. package/src/vendor/hfjs-xet/utils/xetWriteToken.ts +101 -0
  43. package/src/vendor/hfjs-xet/vendor/lz4js/index.ts +540 -0
  44. package/src/vendor/hfjs-xet/vendor/lz4js/util.ts +57 -0
  45. package/src/vendor/hfjs-xet/vendor/lz4js/xxh32.ts +99 -0
  46. package/src/vendor/hfjs-xet/vendor/type-fest/basic.ts +34 -0
  47. 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
+ }