toolcraft 0.0.883 → 0.0.885

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/composition.json CHANGED
@@ -138,7 +138,7 @@
138
138
  },
139
139
  {
140
140
  "name": "toolcraft",
141
- "version": "0.0.883",
141
+ "version": "0.0.885",
142
142
  "license": "MIT"
143
143
  },
144
144
  {
@@ -148,7 +148,7 @@
148
148
  },
149
149
  {
150
150
  "name": "toolcraft-schema",
151
- "version": "0.0.883",
151
+ "version": "0.0.885",
152
152
  "license": "MIT"
153
153
  },
154
154
  {
@@ -138,7 +138,7 @@
138
138
  },
139
139
  {
140
140
  "name": "toolcraft",
141
- "version": "0.0.883",
141
+ "version": "0.0.885",
142
142
  "license": "MIT"
143
143
  },
144
144
  {
@@ -148,7 +148,7 @@
148
148
  },
149
149
  {
150
150
  "name": "toolcraft-schema",
151
- "version": "0.0.883",
151
+ "version": "0.0.885",
152
152
  "license": "MIT"
153
153
  },
154
154
  {
@@ -12,6 +12,7 @@ export declare class MemoryLedger {
12
12
  get availableBytes(): number;
13
13
  canPreallocate64(nameBytes: number): boolean;
14
14
  fileSize(length: number, syscall: string, path: string): void;
15
+ private canReserve;
15
16
  check(bytes: number, units: number, syscall: string, path: string): void;
16
17
  reserve(bytes: number, units: number, syscall: string, path: string): void;
17
18
  release(bytes: number, units: number): void;
@@ -10,9 +10,9 @@ export class MemoryLedger {
10
10
  hasInfiniteRetained;
11
11
  constructor(limits) {
12
12
  this.limits = limits;
13
- this.maxFileBytesSmi = limits.maxFileBytes >= MAX_SMI ? MAX_SMI : (limits.maxFileBytes | 0);
14
- this.maxRetainedBytesSmi = limits.maxRetainedBytes >= MAX_SMI ? MAX_SMI : (limits.maxRetainedBytes | 0);
15
- this.maxMetadataUnitsSmi = limits.maxMetadataUnits >= MAX_SMI ? MAX_SMI : (limits.maxMetadataUnits | 0);
13
+ this.maxFileBytesSmi = Math.min(limits.maxFileBytes, MAX_SMI) | 0;
14
+ this.maxRetainedBytesSmi = Math.min(limits.maxRetainedBytes, MAX_SMI) | 0;
15
+ this.maxMetadataUnitsSmi = Math.min(limits.maxMetadataUnits, MAX_SMI) | 0;
16
16
  this.hasInfiniteRetained = limits.maxRetainedBytes === Infinity;
17
17
  if (limits.maxFileBytes !== Infinity)
18
18
  this.hasInfiniteFileBytes = false;
@@ -31,27 +31,24 @@ export class MemoryLedger {
31
31
  throw new FsError("EFBIG", { syscall, path });
32
32
  }
33
33
  }
34
- check(bytes, units, syscall, path) {
35
- if ((bytes | 0) === bytes && bytes >= 0 &&
34
+ canReserve(bytes, units) {
35
+ return ((bytes | 0) === bytes && bytes >= 0 &&
36
36
  (units | 0) === units && units >= 0 &&
37
37
  this.retainedBytes <= this.maxRetainedBytesSmi - bytes &&
38
- this.metadataUnits <= this.maxMetadataUnitsSmi - units) {
38
+ this.metadataUnits <= this.maxMetadataUnitsSmi - units);
39
+ }
40
+ check(bytes, units, syscall, path) {
41
+ if (this.canReserve(bytes, units))
39
42
  return;
40
- }
41
- const maxRetained = this.limits.maxRetainedBytes;
42
- const maxUnits = this.limits.maxMetadataUnits;
43
43
  if (!Number.isSafeInteger(bytes) || bytes < 0 ||
44
- (maxRetained !== Infinity && bytes > maxRetained - this.retainedBytes) ||
44
+ bytes > this.limits.maxRetainedBytes - this.retainedBytes ||
45
45
  !Number.isSafeInteger(units) || units < 0 ||
46
- (maxUnits !== Infinity && units > maxUnits - this.metadataUnits)) {
46
+ units > this.limits.maxMetadataUnits - this.metadataUnits) {
47
47
  throw new FsError("ENOSPC", { syscall, path });
48
48
  }
49
49
  }
50
50
  reserve(bytes, units, syscall, path) {
51
- if ((bytes | 0) === bytes && bytes >= 0 &&
52
- (units | 0) === units && units >= 0 &&
53
- this.retainedBytes <= this.maxRetainedBytesSmi - bytes &&
54
- this.metadataUnits <= this.maxMetadataUnitsSmi - units) {
51
+ if (this.canReserve(bytes, units)) {
55
52
  this.retainedBytes = (this.retainedBytes + bytes) | 0;
56
53
  this.metadataUnits = (this.metadataUnits + units) | 0;
57
54
  return;
@@ -90,7 +87,4 @@ export class MemoryAllocation {
90
87
  }
91
88
  }
92
89
  }
93
- Object.assign(MemoryAllocation.prototype, {
94
- references: 1,
95
- });
96
90
  Object.assign(MemoryLedger.prototype, { hasInfiniteFileBytes: true });
@@ -28,16 +28,12 @@ export function withObjectFileDescriptors(filesystem, store, options = {}) {
28
28
  while (stagedBytes + chunkBytes > maxStagedBytes || stagedBytes / chunkBytes >= maxStagedPages) {
29
29
  forwarded.signal?.throwIfAborted();
30
30
  await new Promise((resolve, reject) => {
31
- const wake = () => {
31
+ const cleanup = () => {
32
32
  stagingWaiters.delete(wake);
33
33
  forwarded.signal?.removeEventListener("abort", abort);
34
- resolve();
35
- };
36
- const abort = () => {
37
- stagingWaiters.delete(wake);
38
- forwarded.signal?.removeEventListener("abort", abort);
39
- reject(forwarded.signal?.reason);
40
34
  };
35
+ const wake = () => { cleanup(); resolve(); };
36
+ const abort = () => { cleanup(); reject(forwarded.signal?.reason); };
41
37
  stagingWaiters.add(wake);
42
38
  forwarded.signal?.addEventListener("abort", abort, { once: true });
43
39
  if (forwarded.signal?.aborted)
@@ -87,9 +83,13 @@ export function withObjectFileDescriptors(filesystem, store, options = {}) {
87
83
  if (state.failure)
88
84
  throw state.failure.reason;
89
85
  };
86
+ const requirePublication = (writable = true) => {
87
+ if (!store.publish || !writable)
88
+ throw new FsError("ENOTSUP", { path, message: "Object writes require authoritative conditional publication" });
89
+ };
90
90
  const perform = async (forwarded, action) => {
91
91
  check(forwarded);
92
- const scope = composeAbortSignals([...(acquiring && admitted.signal ? [admitted.signal] : []), ...(forwarded.signal ? [forwarded.signal] : [])]);
92
+ const scope = composeAbortSignals([acquiring && admitted.signal, forwarded.signal].filter((signal) => !!signal));
93
93
  try {
94
94
  const result = await action({ signal: scope.signal });
95
95
  scope.signal.throwIfAborted();
@@ -163,8 +163,7 @@ export function withObjectFileDescriptors(filesystem, store, options = {}) {
163
163
  check(forwarded);
164
164
  if (!state.dirty)
165
165
  return;
166
- if (!store.publish)
167
- throw new FsError("ENOTSUP", { path, message: "Object writes require authoritative conditional publication" });
166
+ requirePublication();
168
167
  const expected = state.head?.revision ?? null;
169
168
  let emitted = 0;
170
169
  let active = true;
@@ -174,7 +173,8 @@ export function withObjectFileDescriptors(filesystem, store, options = {}) {
174
173
  let streamScope;
175
174
  try {
176
175
  await perform(forwarded, async (selected) => {
177
- streamScope = composeAbortSignals([...(selected.signal ? [selected.signal] : []), streamAbort.signal]);
176
+ // perform always supplies its composed signal.
177
+ streamScope = composeAbortSignals([selected.signal, streamAbort.signal]);
178
178
  const bodyOptions = { signal: streamScope.signal };
179
179
  source = (async function* () {
180
180
  for (let position = 0; position < state.size; position += chunkBytes) {
@@ -230,8 +230,8 @@ export function withObjectFileDescriptors(filesystem, store, options = {}) {
230
230
  const mutating = admitted.access !== "read" || admitted.creation !== "never" || admitted.truncate;
231
231
  if (mutating && capabilities.readOnly === true)
232
232
  throw new FsError("EROFS", { path });
233
- if (mutating && (!store.publish || capabilities.write === false))
234
- throw new FsError("ENOTSUP", { path, message: "Object writes require authoritative conditional publication" });
233
+ if (mutating)
234
+ requirePublication(capabilities.write !== false);
235
235
  if (admitted.access !== "write" && capabilities.read === false)
236
236
  throw new FsError("EACCES", { path });
237
237
  const acquired = await store.acquire(path, { access: admitted.access, ...(admitted.noFollow ? { noFollow: true } : {}), ...(admitted.signal ? { signal: admitted.signal } : {}) });
@@ -296,16 +296,18 @@ export function withObjectFileDescriptors(filesystem, store, options = {}) {
296
296
  const page = Math.floor(offset / chunkBytes);
297
297
  const within = offset % chunkBytes;
298
298
  const length = Math.min(buffer.byteLength - copied, chunkBytes - within);
299
- const complete = within === 0 && length === chunkBytes;
300
- // Staging owns acknowledged bytes. Borrow the caller's complete
301
- // page until writePage settles instead of allocating another copy.
302
- let bytes = complete ? buffer.subarray(copied, copied + length) : await readStagedPage(page, forwarded);
303
- if (!bytes) {
304
- bytes = new Uint8Array(chunkBytes);
305
- bytes.set(await readBase(page * chunkBytes, chunkBytes, forwarded));
299
+ // Staging owns acknowledged bytes. Borrow complete pages until
300
+ // settlement; only partial writes need read/modify/write storage.
301
+ let bytes = buffer.subarray(copied, copied + length);
302
+ if (within || length !== chunkBytes) {
303
+ let previous = await readStagedPage(page, forwarded);
304
+ if (!previous) {
305
+ previous = new Uint8Array(chunkBytes);
306
+ previous.set(await readBase(page * chunkBytes, chunkBytes, forwarded));
307
+ }
308
+ previous.set(bytes, within);
309
+ bytes = previous;
306
310
  }
307
- if (!complete)
308
- bytes.set(buffer.subarray(copied, copied + length), within);
309
311
  await perform(forwarded, selected => state.staging.writePage(page, bytes, selected));
310
312
  copied += length;
311
313
  }
@@ -8,7 +8,7 @@
8
8
  },
9
9
  {
10
10
  "name": "toolcraft-schema",
11
- "version": "0.0.883",
11
+ "version": "0.0.885",
12
12
  "license": "MIT"
13
13
  }
14
14
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft-schema",
3
- "version": "0.0.883",
3
+ "version": "0.0.885",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft",
3
- "version": "0.0.883",
3
+ "version": "0.0.885",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -177,7 +177,7 @@
177
177
  "saxes"
178
178
  ],
179
179
  "optionalDependencies": {
180
- "toolcraft-schema": "0.0.883",
180
+ "toolcraft-schema": "0.0.885",
181
181
  "toolcraft-design": "*",
182
182
  "@poe-code/frontmatter": "*",
183
183
  "@poe-code/agent-mcp-config": "*",