toolcraft 0.0.795 → 0.0.797
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 +2 -2
- package/dist/composition.json +2 -2
- package/node_modules/@poe-code/safe-fs/README.md +3 -0
- package/node_modules/@poe-code/safe-fs/dist/core.d.ts +1 -1
- package/node_modules/@poe-code/safe-fs/dist/storage.d.ts +2 -0
- package/node_modules/@poe-code/safe-fs/dist/storage.js +5 -0
- package/node_modules/@poe-code/xml-ast/README.md +10 -0
- package/node_modules/@poe-code/xml-ast/dist/frames.d.ts +21 -0
- package/node_modules/@poe-code/xml-ast/dist/frames.js +20 -0
- package/node_modules/@poe-code/xml-ast/dist/index.d.ts +6 -3
- package/node_modules/@poe-code/xml-ast/dist/index.js +15 -11
- package/node_modules/tiny-stdio-mcp-server/dist/composition.json +1 -1
- package/node_modules/toolcraft-schema/package.json +1 -1
- package/package.json +2 -2
package/composition.json
CHANGED
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
140
|
"name": "toolcraft",
|
|
141
|
-
"version": "0.0.
|
|
141
|
+
"version": "0.0.797",
|
|
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.
|
|
151
|
+
"version": "0.0.797",
|
|
152
152
|
"license": "MIT"
|
|
153
153
|
},
|
|
154
154
|
{
|
package/dist/composition.json
CHANGED
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
140
|
"name": "toolcraft",
|
|
141
|
-
"version": "0.0.
|
|
141
|
+
"version": "0.0.797",
|
|
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.
|
|
151
|
+
"version": "0.0.797",
|
|
152
152
|
"license": "MIT"
|
|
153
153
|
},
|
|
154
154
|
{
|
|
@@ -15,6 +15,9 @@ To bound aggregate pages across multiple live stores, pass the same
|
|
|
15
15
|
This shares a 256 KiB resident-page budget; `cache.residentBytes` reports current
|
|
16
16
|
page retention. Eviction uses each store's filesystem, and each store still owns
|
|
17
17
|
its `close()` cleanup. The budget excludes caller buffers and backend storage.
|
|
18
|
+
Call `await storage.prepare()` before opening a directory iterator when its
|
|
19
|
+
snapshot includes the scratch directory. It acquires and unlinks the backing
|
|
20
|
+
handle up front, so later spills do not mutate that directory's namespace.
|
|
18
21
|
`IntegerTable.entries()` replays records in unsigned key order with a fixed
|
|
19
22
|
16-level node stack and batches of at most 128 records. It accepts zero-filled
|
|
20
23
|
caller storage with `allocate`, `read` and `write`; mutation during traversal
|
|
@@ -9,7 +9,7 @@ export * from "./fs/webdav/index.js";
|
|
|
9
9
|
export * from "./bridge/index.js";
|
|
10
10
|
export * from "./python/index.js";
|
|
11
11
|
export { parseXml, parseXmlSteps, parseXmlSourceSteps, normalizeXmlChunks, parseXmlStream, XmlLimitError } from "./xml.js";
|
|
12
|
-
export type { XmlName, XmlAttribute, XmlContent, XmlElement, XmlLimits, XmlParserFrame, XmlFrameRequest } from "./xml.js";
|
|
12
|
+
export type { XmlName, XmlAttribute, XmlContent, XmlElement, XmlLimits, XmlParserFrame, XmlFrameRequest, XmlNamespaceScope, XmlNamespaceRequest } from "./xml.js";
|
|
13
13
|
export * from "./contracts/object.js";
|
|
14
14
|
export { ObjectAuthority } from "./fs/object-authority.js";
|
|
15
15
|
export * from "./fs/s3/index.js";
|
|
@@ -44,6 +44,8 @@ export declare class PagedStorage {
|
|
|
44
44
|
private closing;
|
|
45
45
|
constructor(context: PagedStorageContext, maxPages?: number, cache?: PagedStorageCache | undefined);
|
|
46
46
|
allocate(length: number): number;
|
|
47
|
+
/** Acquire and unlink backing storage before observing a directory snapshot. */
|
|
48
|
+
prepare(): Promise<void>;
|
|
47
49
|
private operation;
|
|
48
50
|
private spill;
|
|
49
51
|
private flush;
|
|
@@ -73,6 +73,11 @@ export class PagedStorage {
|
|
|
73
73
|
this.end += length;
|
|
74
74
|
return offset;
|
|
75
75
|
}
|
|
76
|
+
/** Acquire and unlink backing storage before observing a directory snapshot. */
|
|
77
|
+
async prepare() {
|
|
78
|
+
await this.operation(async () => { if (!this.descriptor)
|
|
79
|
+
await this.spill(); });
|
|
80
|
+
}
|
|
76
81
|
operation(action) {
|
|
77
82
|
this.signal.throwIfAborted();
|
|
78
83
|
const execute = () => {
|
|
@@ -62,6 +62,16 @@ metadata. Keep the host stack in bounded backing storage. The parser caches one
|
|
|
62
62
|
current frame; individual frame metadata and namespace scopes still have their own
|
|
63
63
|
size cost. The default string and stream APIs retain their existing ancestry behavior.
|
|
64
64
|
|
|
65
|
+
Also set `storeNamespaces: true` to resolve namespace scopes through host-backed
|
|
66
|
+
immutable storage. `namespaceOperation: "get"` supplies a scope and prefix; fill
|
|
67
|
+
`value` when present and set `complete: true`. For `"set"`, bind the supplied prefix
|
|
68
|
+
and value in a new scope, then fill `result` with its storage `reference` and the
|
|
69
|
+
number of distinct bindings (`size`). Frames carry this scope handle so shadowing
|
|
70
|
+
never changes ancestor scopes. In this mode event elements have an empty
|
|
71
|
+
`namespaces` map; their names and attributes still carry resolved namespace URIs.
|
|
72
|
+
The codec remains filesystem-independent, and individual names, attribute values
|
|
73
|
+
and namespace URIs still need a token storage strategy.
|
|
74
|
+
|
|
65
75
|
Pass `undefined` as the source length to parse incrementally. Such read requests
|
|
66
76
|
have `streaming: true` and request at most 512 UTF-16 units. Return any nonempty
|
|
67
77
|
prefix available without pulling more input; set `complete: true` only when that
|
|
@@ -4,6 +4,7 @@ export interface XmlParserFrame {
|
|
|
4
4
|
content: XmlContent[] | undefined;
|
|
5
5
|
name: string;
|
|
6
6
|
namespaces: Map<string, string>;
|
|
7
|
+
namespaceScope?: XmlNamespaceScope;
|
|
7
8
|
}
|
|
8
9
|
export type XmlFrameRequest = {
|
|
9
10
|
readonly frameOperation: 'push';
|
|
@@ -26,3 +27,23 @@ export declare class XmlFrames {
|
|
|
26
27
|
push(frame: XmlParserFrame): Generator<XmlFrameRequest, void, void>;
|
|
27
28
|
pop(): Generator<XmlFrameRequest, XmlParserFrame | undefined, void>;
|
|
28
29
|
}
|
|
30
|
+
/** A host-owned immutable namespace scope; count includes the built-in xml prefix. */
|
|
31
|
+
export interface XmlNamespaceScope {
|
|
32
|
+
readonly reference: number;
|
|
33
|
+
readonly size: number;
|
|
34
|
+
}
|
|
35
|
+
export type XmlNamespaceRequest = {
|
|
36
|
+
readonly namespaceOperation: 'get';
|
|
37
|
+
readonly scope: XmlNamespaceScope;
|
|
38
|
+
readonly prefix: string;
|
|
39
|
+
value?: string;
|
|
40
|
+
complete?: true;
|
|
41
|
+
} | {
|
|
42
|
+
readonly namespaceOperation: 'set';
|
|
43
|
+
readonly scope: XmlNamespaceScope;
|
|
44
|
+
readonly prefix: string;
|
|
45
|
+
readonly value: string;
|
|
46
|
+
result?: XmlNamespaceScope;
|
|
47
|
+
};
|
|
48
|
+
export declare function namespaceValue(scope: Map<string, string> | XmlNamespaceScope, prefix: string): Generator<XmlNamespaceRequest, string | undefined, void>;
|
|
49
|
+
export declare function bindNamespace(scope: Map<string, string> | XmlNamespaceScope, prefix: string, value: string): Generator<XmlNamespaceRequest, Map<string, string> | XmlNamespaceScope, void>;
|
|
@@ -43,3 +43,23 @@ export class XmlFrames {
|
|
|
43
43
|
return frame;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
export function* namespaceValue(scope, prefix) {
|
|
47
|
+
if (scope instanceof Map)
|
|
48
|
+
return scope.get(prefix);
|
|
49
|
+
const request = { namespaceOperation: 'get', scope, prefix };
|
|
50
|
+
yield request;
|
|
51
|
+
if (!request.complete)
|
|
52
|
+
throw new TypeError('Incomplete XML namespace read');
|
|
53
|
+
return request.value;
|
|
54
|
+
}
|
|
55
|
+
export function* bindNamespace(scope, prefix, value) {
|
|
56
|
+
if (scope instanceof Map) {
|
|
57
|
+
scope.set(prefix, value);
|
|
58
|
+
return scope;
|
|
59
|
+
}
|
|
60
|
+
const request = { namespaceOperation: 'set', scope, prefix, value };
|
|
61
|
+
yield request;
|
|
62
|
+
if (!request.result)
|
|
63
|
+
throw new TypeError('Incomplete XML namespace update');
|
|
64
|
+
return request.result;
|
|
65
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type XmlFrameRequest } from "./frames.js";
|
|
2
|
-
export type { XmlParserFrame, XmlFrameRequest } from "./frames.js";
|
|
1
|
+
import { type XmlNamespaceRequest, type XmlFrameRequest } from "./frames.js";
|
|
2
|
+
export type { XmlParserFrame, XmlFrameRequest, XmlNamespaceScope, XmlNamespaceRequest } from "./frames.js";
|
|
3
3
|
export { normalizeXmlChunks } from "./characters.js";
|
|
4
4
|
import { type XmlSourceStep } from "./source.js";
|
|
5
5
|
export type { XmlSourceRead, XmlSourceStep } from "./source.js";
|
|
@@ -61,11 +61,14 @@ export interface XmlSourceLimits extends XmlStepLimits {
|
|
|
61
61
|
readonly fragmentContent?: boolean;
|
|
62
62
|
/** Store active parser frames through host-serviced requests. Requires retainTree: false. */
|
|
63
63
|
readonly storeFrames?: boolean;
|
|
64
|
+
/** Resolve namespace scopes through host-serviced requests. Requires retainTree: false. */
|
|
65
|
+
readonly storeNamespaces?: boolean;
|
|
64
66
|
}
|
|
65
|
-
export type XmlParseStep = XmlSourceStep | XmlFrameRequest;
|
|
67
|
+
export type XmlParseStep = XmlSourceStep | XmlFrameRequest | XmlNamespaceRequest;
|
|
66
68
|
/** Parse a validated, BOM-free, line-normalized UTF-16 source via bounded read requests. */
|
|
67
69
|
export declare function parseXmlSourceSteps(length: number | undefined, limits?: XmlStepLimits & {
|
|
68
70
|
readonly storeFrames?: false;
|
|
71
|
+
readonly storeNamespaces?: false;
|
|
69
72
|
}): Generator<XmlSourceStep, XmlElement, void>;
|
|
70
73
|
export declare function parseXmlSourceSteps(length: number | undefined, limits: XmlSourceLimits): Generator<XmlParseStep, XmlElement, void>;
|
|
71
74
|
export declare function parseXmlSteps(input: string, limits?: XmlStepLimits): Generator<number, XmlElement, void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { XmlFrames } from "./frames.js";
|
|
1
|
+
import { XmlFrames, bindNamespace, namespaceValue } from "./frames.js";
|
|
2
2
|
import { validCharacter } from "./characters.js";
|
|
3
3
|
export { normalizeXmlChunks } from "./characters.js";
|
|
4
4
|
import { XmlSource } from "./source.js";
|
|
@@ -255,6 +255,8 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
255
255
|
validateLimits(limits);
|
|
256
256
|
if (limits.storeFrames && limits.retainTree !== false)
|
|
257
257
|
throw new TypeError("Stored XML frames require retainTree: false");
|
|
258
|
+
if (limits.storeNamespaces && limits.retainTree !== false)
|
|
259
|
+
throw new TypeError("Stored XML namespaces require retainTree: false");
|
|
258
260
|
if (limits.fragmentContent && limits.retainTree !== false)
|
|
259
261
|
throw new TypeError("XML content fragments require retainTree: false");
|
|
260
262
|
const source = new XmlSource(length);
|
|
@@ -277,6 +279,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
277
279
|
throw new XmlLimitError("maxTextLength", "XML text limit exceeded");
|
|
278
280
|
textLength += text.length;
|
|
279
281
|
};
|
|
282
|
+
const initialNamespaces = limits.storeNamespaces ? yield* bindNamespace({ reference: 0, size: 0 }, "xml", xmlNamespace) : new Map([["xml", xmlNamespace]]);
|
|
280
283
|
const stack = new XmlFrames(limits.storeFrames === true);
|
|
281
284
|
let root;
|
|
282
285
|
const prolog = [];
|
|
@@ -554,7 +557,8 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
554
557
|
}
|
|
555
558
|
let attributes;
|
|
556
559
|
const attrMeta = [];
|
|
557
|
-
|
|
560
|
+
const namespaceParent = yield* stack.peek();
|
|
561
|
+
let namespaces = namespaceParent?.namespaceScope ?? namespaceParent?.namespaces ?? (initialNamespaces instanceof Map ? new Map(initialNamespaces) : initialNamespaces);
|
|
558
562
|
let ownsNamespaces = stack.length === 0;
|
|
559
563
|
while (!repeated) {
|
|
560
564
|
const ws = (yield* skipWhitespace());
|
|
@@ -618,7 +622,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
618
622
|
|| (nsPrefix === "xml") !== (value === xmlNamespace)
|
|
619
623
|
|| (nsPrefix !== "" && value === ""))
|
|
620
624
|
invalid("invalid namespace binding");
|
|
621
|
-
if (!ownsNamespaces) {
|
|
625
|
+
if (!ownsNamespaces && namespaces instanceof Map) {
|
|
622
626
|
const copy = new Map();
|
|
623
627
|
for (const [key, uri] of namespaces) {
|
|
624
628
|
copy.set(key, uri);
|
|
@@ -627,7 +631,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
627
631
|
namespaces = copy;
|
|
628
632
|
ownsNamespaces = true;
|
|
629
633
|
}
|
|
630
|
-
namespaces
|
|
634
|
+
namespaces = yield* bindNamespace(namespaces, nsPrefix, value);
|
|
631
635
|
if (namespaces.size > maxNamespaces)
|
|
632
636
|
throw new XmlLimitError("maxNamespaces", "XML namespace scope limit exceeded");
|
|
633
637
|
}
|
|
@@ -639,10 +643,10 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
639
643
|
if (attribute === "xmlns" || attribute.startsWith("xmlns:"))
|
|
640
644
|
continue;
|
|
641
645
|
pendingWork += attribute.length;
|
|
642
|
-
if (attrPrefix &&
|
|
646
|
+
if (attrPrefix && (yield* namespaceValue(namespaces, attrPrefix)) === undefined)
|
|
643
647
|
invalid("unbound attribute prefix");
|
|
644
648
|
if (expanded) {
|
|
645
|
-
const key = `${attrPrefix ? namespaces
|
|
649
|
+
const key = `${attrPrefix ? (yield* namespaceValue(namespaces, attrPrefix)) : ""}\0${attrLocal}`;
|
|
646
650
|
if (expanded.has(key))
|
|
647
651
|
invalid("duplicate expanded attribute");
|
|
648
652
|
expanded.add(key);
|
|
@@ -654,13 +658,13 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
654
658
|
yield 512;
|
|
655
659
|
pendingWork -= 512;
|
|
656
660
|
}
|
|
657
|
-
if (prefix === "xmlns" || (prefix &&
|
|
661
|
+
if (prefix === "xmlns" || (prefix && (yield* namespaceValue(namespaces, prefix)) === undefined))
|
|
658
662
|
invalid("unbound element prefix");
|
|
659
663
|
if (++nodes > maxNodes)
|
|
660
664
|
throw new XmlLimitError("maxNodes", "XML resource limit exceeded");
|
|
661
665
|
if (stack.length + 1 > maxDepth)
|
|
662
666
|
throw new XmlLimitError("maxDepth", "XML resource limit exceeded");
|
|
663
|
-
const namespace = namespaces
|
|
667
|
+
const namespace = (yield* namespaceValue(namespaces, prefix)) ?? "";
|
|
664
668
|
limits.onElement?.({ name, namespace, localName }, (yield* stack.peek())?.element, stack.length + 1);
|
|
665
669
|
admitContent();
|
|
666
670
|
const retainedAttributes = [];
|
|
@@ -670,7 +674,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
670
674
|
const value = attributes.get(attribute);
|
|
671
675
|
admitContent();
|
|
672
676
|
retainedAttributes.push({ name: attribute, localName: attrLocal,
|
|
673
|
-
namespace: attribute === "xmlns" || attrPrefix === "xmlns" ? xmlnsNamespace : attrPrefix ? namespaces
|
|
677
|
+
namespace: attribute === "xmlns" || attrPrefix === "xmlns" ? xmlnsNamespace : attrPrefix ? (yield* namespaceValue(namespaces, attrPrefix)) : "", value });
|
|
674
678
|
pendingWork += attribute.length + 1;
|
|
675
679
|
}
|
|
676
680
|
}
|
|
@@ -679,7 +683,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
679
683
|
pendingWork -= 512;
|
|
680
684
|
}
|
|
681
685
|
const content = retain ? [] : undefined;
|
|
682
|
-
const element = { kind: "element", name, namespace, localName, children: [], text: "", content: content ?? emptyContent, attributes: retainContent ? retainedAttributes : emptyAttributes, namespaces: retainContent ? namespaces : emptyNamespaces, ...(root === undefined && retainContent ? { prolog, epilog, ...(declaration === undefined ? {} : { declaration }) } : {}) };
|
|
686
|
+
const element = { kind: "element", name, namespace, localName, children: [], text: "", content: content ?? emptyContent, attributes: retainContent ? retainedAttributes : emptyAttributes, namespaces: retainContent && namespaces instanceof Map ? namespaces : emptyNamespaces, ...(root === undefined && retainContent ? { prolog, epilog, ...(declaration === undefined ? {} : { declaration }) } : {}) };
|
|
683
687
|
const parent = (yield* stack.peek());
|
|
684
688
|
if (parent) {
|
|
685
689
|
if (retainTree) {
|
|
@@ -705,7 +709,7 @@ export function* parseXmlSourceSteps(length, limits = {}) {
|
|
|
705
709
|
previousEmpty = { suffix: name + "/>", name, prefix, localName };
|
|
706
710
|
limits.events?.({ type: "open", element, parent: parent?.element });
|
|
707
711
|
if (!empty)
|
|
708
|
-
yield* stack.push({ element, content, name, namespaces });
|
|
712
|
+
yield* stack.push({ element, content, name, namespaces: namespaces instanceof Map ? namespaces : new Map(), ...(namespaces instanceof Map ? {} : { namespaceScope: namespaces }) });
|
|
709
713
|
else
|
|
710
714
|
limits.events?.({ type: "close", element, parent: parent?.element });
|
|
711
715
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.797",
|
|
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.
|
|
180
|
+
"toolcraft-schema": "0.0.797",
|
|
181
181
|
"toolcraft-design": "*",
|
|
182
182
|
"@poe-code/frontmatter": "*",
|
|
183
183
|
"@poe-code/agent-mcp-config": "*",
|