apcore-toolkit 0.4.1 → 0.5.1

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 (108) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/LICENSE +185 -0
  3. package/README.md +91 -39
  4. package/dist/ai-enhancer.d.ts +18 -1
  5. package/dist/ai-enhancer.d.ts.map +1 -1
  6. package/dist/ai-enhancer.js +100 -23
  7. package/dist/ai-enhancer.js.map +1 -1
  8. package/dist/binding-loader.d.ts +55 -0
  9. package/dist/binding-loader.d.ts.map +1 -0
  10. package/dist/binding-loader.js +175 -0
  11. package/dist/binding-loader.js.map +1 -0
  12. package/dist/binding-parser.d.ts +80 -0
  13. package/dist/binding-parser.d.ts.map +1 -0
  14. package/dist/binding-parser.js +257 -0
  15. package/dist/binding-parser.js.map +1 -0
  16. package/dist/browser/index.d.ts +17 -0
  17. package/dist/browser/index.d.ts.map +1 -0
  18. package/dist/browser/index.js +46 -0
  19. package/dist/browser/index.js.map +1 -0
  20. package/dist/{display-resolver.d.ts → display/resolver.d.ts} +14 -2
  21. package/dist/display/resolver.d.ts.map +1 -0
  22. package/dist/{display-resolver.js → display/resolver.js} +79 -25
  23. package/dist/display/resolver.js.map +1 -0
  24. package/dist/formatting/markdown.d.ts.map +1 -1
  25. package/dist/formatting/markdown.js +25 -22
  26. package/dist/formatting/markdown.js.map +1 -1
  27. package/dist/http-verb-map.d.ts +79 -0
  28. package/dist/http-verb-map.d.ts.map +1 -0
  29. package/dist/http-verb-map.js +179 -0
  30. package/dist/http-verb-map.js.map +1 -0
  31. package/dist/index.d.ts +8 -5
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +12 -4
  34. package/dist/index.js.map +1 -1
  35. package/dist/openapi.d.ts.map +1 -1
  36. package/dist/openapi.js +37 -10
  37. package/dist/openapi.js.map +1 -1
  38. package/dist/output/base-writer.d.ts +17 -0
  39. package/dist/output/base-writer.d.ts.map +1 -0
  40. package/dist/output/base-writer.js +34 -0
  41. package/dist/output/base-writer.js.map +1 -0
  42. package/dist/output/errors.d.ts +7 -2
  43. package/dist/output/errors.d.ts.map +1 -1
  44. package/dist/output/errors.js +8 -3
  45. package/dist/output/errors.js.map +1 -1
  46. package/dist/output/factory.d.ts +13 -1
  47. package/dist/output/factory.d.ts.map +1 -1
  48. package/dist/output/factory.js +21 -2
  49. package/dist/output/factory.js.map +1 -1
  50. package/dist/output/http-proxy-writer.d.ts +82 -0
  51. package/dist/output/http-proxy-writer.d.ts.map +1 -0
  52. package/dist/output/http-proxy-writer.js +222 -0
  53. package/dist/output/http-proxy-writer.js.map +1 -0
  54. package/dist/output/index.d.ts +1 -1
  55. package/dist/output/index.d.ts.map +1 -1
  56. package/dist/output/index.js +1 -1
  57. package/dist/output/index.js.map +1 -1
  58. package/dist/output/registry-writer.d.ts +23 -5
  59. package/dist/output/registry-writer.d.ts.map +1 -1
  60. package/dist/output/registry-writer.js +52 -14
  61. package/dist/output/registry-writer.js.map +1 -1
  62. package/dist/output/types.d.ts +1 -0
  63. package/dist/output/types.d.ts.map +1 -1
  64. package/dist/output/types.js.map +1 -1
  65. package/dist/output/typescript-writer.d.ts +14 -6
  66. package/dist/output/typescript-writer.d.ts.map +1 -1
  67. package/dist/output/typescript-writer.js +100 -32
  68. package/dist/output/typescript-writer.js.map +1 -1
  69. package/dist/output/verifiers.d.ts +1 -9
  70. package/dist/output/verifiers.d.ts.map +1 -1
  71. package/dist/output/verifiers.js +92 -42
  72. package/dist/output/verifiers.js.map +1 -1
  73. package/dist/output/verify-core.d.ts +20 -0
  74. package/dist/output/verify-core.d.ts.map +1 -0
  75. package/dist/output/verify-core.js +59 -0
  76. package/dist/output/verify-core.js.map +1 -0
  77. package/dist/output/yaml-writer.d.ts +18 -6
  78. package/dist/output/yaml-writer.d.ts.map +1 -1
  79. package/dist/output/yaml-writer.js +99 -42
  80. package/dist/output/yaml-writer.js.map +1 -1
  81. package/dist/resolve-target.d.ts.map +1 -1
  82. package/dist/resolve-target.js +34 -5
  83. package/dist/resolve-target.js.map +1 -1
  84. package/dist/safe-keys.d.ts +2 -0
  85. package/dist/safe-keys.d.ts.map +1 -0
  86. package/dist/safe-keys.js +19 -0
  87. package/dist/safe-keys.js.map +1 -0
  88. package/dist/scanner.d.ts +22 -0
  89. package/dist/scanner.d.ts.map +1 -1
  90. package/dist/scanner.js +40 -16
  91. package/dist/scanner.js.map +1 -1
  92. package/dist/schema-utils.d.ts.map +1 -1
  93. package/dist/schema-utils.js +13 -2
  94. package/dist/schema-utils.js.map +1 -1
  95. package/dist/serializers.d.ts.map +1 -1
  96. package/dist/serializers.js +2 -0
  97. package/dist/serializers.js.map +1 -1
  98. package/dist/types.d.ts +16 -0
  99. package/dist/types.d.ts.map +1 -1
  100. package/dist/types.js +3 -0
  101. package/dist/types.js.map +1 -1
  102. package/package.json +9 -2
  103. package/dist/display-resolver.d.ts.map +0 -1
  104. package/dist/display-resolver.js.map +0 -1
  105. package/dist/flatten-params.d.ts +0 -16
  106. package/dist/flatten-params.d.ts.map +0 -1
  107. package/dist/flatten-params.js +0 -18
  108. package/dist/flatten-params.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,73 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.1] - 2026-04-30
4
+
5
+ ### Fixed
6
+
7
+ - **`package.json` `preinstall` hook removed** — the `npx only-allow pnpm` script was a development-time guardrail that also fired when downstream consumers installed `apcore-toolkit` as a dependency via npm or yarn, causing their installs to fail. The hook has been removed from the published package; pnpm enforcement remains in the monorepo root for internal development.
8
+
9
+ ## [0.5.0] - 2026-04-21
10
+
11
+ ### Added
12
+
13
+ - **`BindingLoader`** / **`BindingLoadError`** — parses `.binding.yaml` files back into `ScannedModule` objects (inverse of `YAMLWriter`). Pure-data reader: no target resolution, no Registry side effects. Matches the Python and Rust implementations in API shape and behaviour.
14
+ - `load(path, options?)` — single file or directory of `*.binding.yaml`.
15
+ - `loadData(data, options?)` — pre-parsed YAML data.
16
+ - Loose mode (default): only `module_id + target` required.
17
+ - Strict mode (`{ strict: true }`): additionally requires `input_schema + output_schema`.
18
+ - `spec_version` validated; missing or unsupported values emit a `console.warn` but do not throw.
19
+ - `annotations` parsed via `annotationsFromJSON` from `apcore-js`; malformed values degrade to `null` with a warning.
20
+ - `BindingLoadError.filePath`, `moduleId`, `missingFields`, and `reason` fields exposed for programmatic handling.
21
+ - **`ScannedModule.display`** — new readonly field (`Record<string, unknown> | null`) for the sparse display overlay. `createScannedModule` factory and `cloneModule` helper updated; deep-cloned on read and write.
22
+
23
+ ### Changed
24
+
25
+ - **`YAMLWriter._buildBinding`** — emits top-level `display:` key only when `module.display !== null`.
26
+ - **`serializers.moduleToDict`** — includes `display` key (deep-cloned).
27
+
28
+ ### Dependencies
29
+
30
+ - **`apcore-js >= 0.19.0`** — picks up the 12-field `ModuleAnnotations` and `annotationsFromJSON`. No toolkit changes required for annotations semantics.
31
+
32
+ ### Tests
33
+
34
+ - +29 new tests: 23 for `BindingLoader` (parsing, strict/loose modes, filesystem loading, round-trip), 4 for `display` field emission/serialization, and 2 hardening tests (malformed display/schema warning). Total suite: 320 tests.
35
+
36
+ ### Hardening (post-review)
37
+
38
+ - **`BindingLoader`**: `_asRecord` / `_asRecordOrNull` now warn when given a non-mapping value (previously silent). `_parseExamples` uses `structuredClone` on each entry so caller mutation of the returned `ScannedModule.examples` cannot leak into the YAML parser's object graph. `fs.statSync` failures are inspected for `ENOENT`/other `errno` codes so users see a specific error instead of a generic "path does not exist" for permission issues.
39
+
40
+ ### Hardening (cross-SDK sync — post-audit)
41
+
42
+ - **`BindingLoader` strict-mode wrong-type rejection** — a required field is now rejected when absent, `null`, or of the wrong type (e.g. `module_id: 42`, `target: true`, empty-string `module_id`). Previously TypeScript silently coerced wrong-type scalars via `String(value)`, while Rust already rejected them; the same YAML now behaves identically in all three SDKs. The error reason widens from `"missing required fields"` to **`"missing or invalid required fields"`**, matching the Rust loader.
43
+ - **`BindingLoader._asRecord` defensive deep-copy** — previously returned a fresh outer `{}` but shared nested refs with the parsed YAML source graph. Now `structuredClone`s the filtered result so caller mutation of `ScannedModule.inputSchema`/`outputSchema`/`metadata` does not leak back into the YAML parser's object graph (defensive parity with the Python `copy.deepcopy` and Rust `Value.clone` loaders).
44
+
45
+ ### Removed
46
+
47
+ - **`flattenParams`** — removed from README (Features list and API table). The symbol was advertised there but never exported from `src/index.ts`; the canonical docs previously described it as a TypeScript utility for "flattening Zod schemas", but TypeScript's native object-argument idiom (`function createUser(body: { username, email })`) already accepts flat inputs, making the wrapper a no-op. Users who need to iterate a Zod schema's fields at runtime can do so directly via `Object.keys(schema.shape)`. The Python `flatten_pydantic_params` remains and continues to serve Python's Pydantic-model unwrapping use-case.
48
+
49
+ ### Added (browser / edge runtime subpath)
50
+
51
+ - **`apcore-toolkit/browser`** — new subpath export that exposes the runtime-neutral subset of the toolkit. Intended for consumers that bundle apcore-toolkit into a browser, edge runtime, or worker environment (e.g. `tiptap-apcore`). The default entry point continues to re-export the full Node-capable surface unchanged — this subpath is strictly additive; existing consumers (`nestjs-apcore` et al.) see zero API changes.
52
+ - Exposes: `ScannedModule` / `createScannedModule` / `cloneModule`, `BaseScanner`, the HTTP verb mapping helpers, `enrichSchemaDescriptions`, the OpenAPI resolvers (`resolveRef` / `resolveSchema` / `deepResolveRefs` / `extractInputSchema` / `extractOutputSchema`), the serializers (`annotationsToDict` / `moduleToDict` / `modulesToDicts`), `toMarkdown`, `BindingParser` / `parseBindingDocument` / `BindingLoadError`, the write-pipeline types (`WriteResult` / `VerifyResult` / `Verifier` / `createWriteResult` / `WriteError` / `InvalidFormatError`), `RegistryVerifier` / `runVerifierChain`, and `HTTPProxyRegistryWriter` / `HTTPProxyWriterError`.
53
+ - Excludes (Node-only): `YAMLWriter`, `TypeScriptWriter`, `RegistryWriter`, `getWriter`, `BindingLoader` (the fs-reading subclass — use `BindingParser` instead), `DisplayResolver`, `AIEnhancer`, `resolveTarget`, the file-based verifiers (`YAMLVerifier`, `SyntaxVerifier`, `MagicBytesVerifier`, `JSONVerifier`), and `VERSION`. These touch `node:fs` / `node:path` / `node:module` / `process.*` and cannot be safely bundled for browsers.
54
+ - **`BindingParser`** — new class at `src/binding-parser.ts` that owns the runtime-neutral binding document parsing logic. `BindingLoader` is now a subclass that adds `load(filePath)` for filesystem loading. `BindingLoader.loadData(data)` continues to work unchanged (inherited). Mirrors the `load_data` split available on the Python `BindingLoader` class.
55
+ - **`parseBindingDocument(raw, options?, filePath?)`** — standalone function form of `BindingParser.loadData`, with an optional explicit `filePath` for richer `BindingLoadError` messages when the document came from a known file location.
56
+ - **`HTTPProxyRegistryWriter` documented in README API table** — previously shipped but undocumented. Uses only global `fetch` / `AbortController` / `URLSearchParams`; runs in any modern runtime.
57
+
58
+ ### Internal restructuring (no public API change)
59
+
60
+ - **`src/output/verifiers.ts` split** — the runtime-neutral `RegistryVerifier` class and `runVerifierChain` function moved to a new `src/output/verify-core.ts`. `verifiers.ts` still re-exports them, so all existing imports (`nestjs-apcore`, the default package entry, internal consumers like `registry-writer.ts` and `base-writer.ts`) continue to resolve the same symbols from the same path. The split lets `apcore-toolkit/browser` import directly from `verify-core.ts` without pulling in the file-based verifiers' `node:fs` / `node:module` dependencies.
61
+ - **`src/binding-loader.ts` split** — the class hierarchy is now `BindingLoader extends BindingParser`, with the pure parsing primitives and error / options types relocated to `src/binding-parser.ts`. `BindingLoader` retains its `load(filePath)` method and re-exports `BindingParser`, `parseBindingDocument`, `BindingLoadError`, and `BindingLoadOptions` so all existing import paths keep working.
62
+
63
+ ### Tests
64
+
65
+ - +3 new tests in `tests/browser-entry.test.ts`:
66
+ 1. The expected 30-symbol browser-safe surface is actually exported.
67
+ 2. Node-only symbols (`YAMLWriter`, `BindingLoader`, `AIEnhancer`, `VERSION`, et al.) are **not** leaked into the subpath.
68
+ 3. Static import-graph walker starts at `src/browser/index.ts` and recursively reads every relative import; fails if any file in the transitive graph references `node:*`, a bare Node builtin, `process.*`, or `createRequire`. This is the regression guard — any future change that accidentally pulls a Node dependency into the browser subpath will be blocked in CI.
69
+ - Full suite: **457 tests across 22 files, all passing.**
70
+
3
71
  ## [0.4.0] - 2026-03-25
4
72
 
5
73
  ### Added
package/LICENSE ADDED
@@ -0,0 +1,185 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship made available under
36
+ the License, as indicated by a copyright notice that is included in
37
+ or attached to the work (an example is provided in the Appendix below).
38
+
39
+ "Derivative Works" shall mean any work, whether in Source or Object
40
+ form, that is based on (or derived from) the Work and for which the
41
+ editorial revisions, annotations, elaborations, or other modifications
42
+ represent, as a whole, an original work of authorship. For the purposes
43
+ of this License, Derivative Works shall not include works that remain
44
+ separable from, or merely link (or bind by name) to the interfaces of,
45
+ the Work and Derivative Works thereof.
46
+
47
+ "Contribution" shall mean, as defined in Section 5, any work of authorship,
48
+ including the original version of the Work and any modifications or
49
+ additions to that Work or Derivative Works of the Work, that is
50
+ intentionally submitted to the Licensor for inclusion in the Work by the
51
+ copyright owner or by an individual or Legal Entity authorized to submit
52
+ on behalf of the copyright owner. For the purposes of this definition,
53
+ "submitted" means any form of electronic, verbal, or written communication
54
+ sent to the Licensor or its representatives, including but not limited to
55
+ communication on electronic mailing lists, source code control systems,
56
+ and issue tracking systems that are managed by, or on behalf of, the
57
+ Licensor for the purpose of discussing and improving the Work, but
58
+ excluding communication that is conspicuously marked or otherwise
59
+ designated in writing by the copyright owner as "Not a Contribution."
60
+
61
+ "Contributor" shall mean Licensor and any Legal Entity on behalf of
62
+ whom a Contribution has been received by the Licensor and subsequently
63
+ incorporated within the Work.
64
+
65
+ 2. Grant of Copyright License. Subject to the terms and conditions of
66
+ this License, each Contributor hereby grants to You a perpetual,
67
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
68
+ copyright license to reproduce, prepare Derivative Works of,
69
+ publicly display, publicly perform, sublicense, and distribute the
70
+ Work and such Derivative Works in Source or Object form.
71
+
72
+ 3. Grant of Patent License. Subject to the terms and conditions of
73
+ this License, each Contributor hereby grants to You a perpetual,
74
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
75
+ (except as stated in this section) patent license to make, have made,
76
+ use, offer to sell, sell, import, and otherwise transfer the Work,
77
+ where such license applies only to those patent claims licensable
78
+ by such Contributor that are necessarily infringed by their
79
+ Contribution(s) alone or by the combination of their Contribution(s)
80
+ with the Work to which such Contribution(s) was submitted. If You
81
+ institute patent litigation against any entity (including a cross-claim
82
+ or counterclaim in a lawsuit) alleging that the Work or any Contribution
83
+ incorporated within the Work constitutes direct or contributory patent
84
+ infringement, then any patent licenses granted to You under this License
85
+ for that Work shall terminate as of the date such litigation is filed.
86
+
87
+ 4. Redistribution. You may reproduce and distribute copies of the
88
+ Work or Derivative Works thereof in any medium, with or without
89
+ modifications, and in Source or Object form, provided that You
90
+ meet the following conditions:
91
+
92
+ (a) You must give any other recipients of the Work or Derivative
93
+ Works a copy of this License; and
94
+
95
+ (b) You must cause any modified files to carry prominent notices
96
+ stating that You changed the files; and
97
+
98
+ (c) You must retain, in the Source form of any Derivative Works
99
+ that You distribute, all copyright, patent, trademark, and
100
+ attribution notices from the Source form of the Work,
101
+ excluding those notices that do not pertain to any part of
102
+ the Derivative Works; and
103
+
104
+ (d) If the Work includes a "NOTICE" text file as part of its
105
+ distribution, You must include a readable copy of the
106
+ attribution notices contained within such NOTICE file, in
107
+ at least one of the following places: within a NOTICE text
108
+ file distributed as part of the Derivative Works; within
109
+ the Source form or documentation, if provided along with the
110
+ Derivative Works; or, within a display generated by the
111
+ Derivative Works, if and wherever such third-party notices
112
+ normally appear. The contents of the NOTICE file are for
113
+ informational purposes only and do not modify the License.
114
+ You may add Your own attribution notices within Derivative
115
+ Works that You distribute, alongside or as an addendum to
116
+ the NOTICE text from the Work, provided that such additional
117
+ attribution notices cannot be construed as modifying the License.
118
+
119
+ You may add Your own license statement for Your modifications and
120
+ may provide additional grant of rights to use, copy, modify, merge,
121
+ publish, distribute, sublicense, and/or sell copies of the Work and
122
+ Derivative Works, subject to the conditions of this License.
123
+
124
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
125
+ any Contribution intentionally submitted for inclusion in the Work
126
+ by You to the Licensor shall be under the terms and conditions of
127
+ this License, without any additional terms or conditions.
128
+ Notwithstanding the above, nothing herein shall supersede or modify
129
+ the terms of any separate license agreement you may have executed
130
+ with Licensor regarding such Contributions.
131
+
132
+ 6. Trademarks. This License does not grant permission to use the trade
133
+ names, trademarks, service marks, or product names of the Licensor,
134
+ except as required for reasonable and customary use in describing the
135
+ origin of the Work and reproducing the content of the NOTICE file.
136
+
137
+ 7. Disclaimer of Warranty. Unless required by applicable law or
138
+ agreed to in writing, Licensor provides the Work (and each
139
+ Contributor provides its Contributions) on an "AS IS" BASIS,
140
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
141
+ implied, including, without limitation, any warranties or conditions
142
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
143
+ PARTICULAR PURPOSE. You are solely responsible for determining the
144
+ appropriateness of using or reproducing the Work and assume any
145
+ risks associated with Your exercise of permissions under this License.
146
+
147
+ 8. Limitation of Liability. In no event and under no legal theory,
148
+ whether in tort (including negligence), contract, or otherwise,
149
+ unless required by applicable law (such as deliberate and grossly
150
+ negligent acts) or agreed to in writing, shall any Contributor be
151
+ liable to You for damages, including any direct, indirect, special,
152
+ incidental, or exemplary damages of any character arising as a
153
+ result of this License or out of the use or inability to use the
154
+ Work (including but not limited to damages for loss of goodwill,
155
+ work stoppage, computer failure or malfunction, or all other
156
+ commercial damages or losses), even if such Contributor has been
157
+ advised of the possibility of such damages.
158
+
159
+ 9. Accepting Warranty or Additional Liability. While redistributing
160
+ the Work or Derivative Works thereof, You may choose to offer,
161
+ and charge a fee for, acceptance of support, warranty, indemnity,
162
+ or other liability obligations and/or rights consistent with this
163
+ License. However, in accepting such obligations, You may offer
164
+ such conditions only on Your own behalf and on Your sole
165
+ responsibility, not on behalf of any other Contributor, and only
166
+ if You agree to indemnify, defend, and hold each Contributor
167
+ harmless for any liability incurred by, or claims asserted against,
168
+ such Contributor by reason of your accepting any such warranty or
169
+ additional liability.
170
+
171
+ END OF TERMS AND CONDITIONS
172
+
173
+ Copyright 2024 AI Partner Up
174
+
175
+ Licensed under the Apache License, Version 2.0 (the "License");
176
+ you may not use this file except in compliance with the License.
177
+ You may obtain a copy of the License at
178
+
179
+ http://www.apache.org/licenses/LICENSE-2.0
180
+
181
+ Unless required by applicable law or agreed to in writing, software
182
+ distributed under the License is distributed on an "AS IS" BASIS,
183
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
184
+ See the License for the specific language governing permissions and
185
+ limitations under the License.
package/README.md CHANGED
@@ -16,10 +16,10 @@ npm install apcore-toolkit
16
16
 
17
17
  - Abstract `BaseScanner` for framework-specific endpoint scanning
18
18
  - OpenAPI schema extraction (`extractInputSchema`, `extractOutputSchema`)
19
- - Multi-format output writers (YAML, TypeScript, Registry) with pluggable verification
19
+ - Multi-format output writers (YAML, TypeScript, Registry, HTTP-proxy) with pluggable verification
20
20
  - Markdown formatting with depth control and table heuristics
21
21
  - Module serialization utilities
22
- - `flattenParams` for Zod-based parameter flattening
22
+ - Runtime-neutral subset via `apcore-toolkit/browser` for browser / edge / worker environments
23
23
 
24
24
  ## Usage
25
25
 
@@ -114,45 +114,97 @@ const dict = moduleToDict(mod); // snake_case keys
114
114
  const dicts = modulesToDicts(modules); // batch conversion
115
115
  ```
116
116
 
117
+ ## Browser / edge runtime
118
+
119
+ The default entry point (`apcore-toolkit`) targets Node: it exposes writers
120
+ that touch the filesystem (`YAMLWriter`, `TypeScriptWriter`), a binding
121
+ loader that reads from disk (`BindingLoader`), display / target resolvers,
122
+ and the `VERSION` constant — all of which transitively pull in `node:fs`,
123
+ `node:path`, `node:module`, or `process.*` and would break a browser
124
+ bundle.
125
+
126
+ For browser, edge-runtime, or worker consumers, `apcore-toolkit/browser`
127
+ exports the runtime-neutral subset — schema / OpenAPI utilities, the
128
+ abstract scanner, serializers, Markdown formatting, the binding **parser**
129
+ (no filesystem access), the write-pipeline types, the runtime-neutral
130
+ verifier primitives (`RegistryVerifier`, `runVerifierChain`), and the
131
+ `HTTPProxyRegistryWriter` (uses only global `fetch` / `AbortController`).
132
+
133
+ ```typescript
134
+ import {
135
+ BaseScanner,
136
+ BindingParser,
137
+ parseBindingDocument,
138
+ HTTPProxyRegistryWriter,
139
+ toMarkdown,
140
+ } from 'apcore-toolkit/browser';
141
+
142
+ // Parse a binding document fetched from a backend (no fs access).
143
+ const resp = await fetch('/api/bindings');
144
+ const doc = await resp.json();
145
+ const modules = new BindingParser().loadData(doc);
146
+
147
+ // Register each module as an HTTP proxy in an in-browser registry.
148
+ const writer = new HTTPProxyRegistryWriter({ baseUrl: '/api' });
149
+ await writer.write(modules, registry);
150
+ ```
151
+
152
+ The default entry continues to re-export every symbol it always did (for
153
+ tri-SDK parity with the Python and Rust toolkits and for unchanged behaviour
154
+ in `nestjs-apcore` etc.). The `/browser` subpath is strictly additive — it
155
+ exposes a subset of the same underlying classes, not a forked implementation.
156
+ A static import-graph check in the test suite fails CI if any Node-only
157
+ reference leaks into the subpath.
158
+
117
159
  ## API
118
160
 
119
- | Export | Description |
120
- |--------|-------------|
121
- | `ScannedModule` | Interface for scanned endpoint data |
122
- | `createScannedModule()` | Factory with defaults for optional fields |
123
- | `cloneModule()` | Defensive copy with optional overrides |
124
- | `BaseScanner` | Abstract base class for scanners |
125
- | `YAMLWriter` | Writes YAML binding files |
126
- | `TypeScriptWriter` | Generates TypeScript module wrappers |
127
- | `RegistryWriter` | Registers modules into an apcore Registry |
128
- | `getWriter()` | Factory for writer instances |
129
- | `extractInputSchema()` | Extract input schema from OpenAPI operation |
130
- | `extractOutputSchema()` | Extract output schema from OpenAPI operation |
131
- | `resolveRef()` | Resolve `$ref` in OpenAPI documents |
132
- | `resolveSchema()` | Resolve schema with single-level `$ref` support |
133
- | `deepResolveRefs()` | Recursively resolve all nested `$ref` pointers in a schema |
134
- | `enrichSchemaDescriptions()` | Merge parameter descriptions into schema |
135
- | `toMarkdown()` | Convert dict to formatted Markdown |
136
- | `moduleToDict()` | Serialize module to snake_case dict |
137
- | `modulesToDicts()` | Batch serialize modules |
138
- | `annotationsToDict()` | Convert annotations to plain dict |
139
- | `resolveTarget()` | Dynamic import + named export resolution |
140
- | `flattenParams()` | Flatten Zod schema params into keyword args |
141
- | `WriteResult` | Structured result type for writer operations |
142
- | `Verifier` | Interface for pluggable output verification |
143
- | `VerifyResult` | Result type for verification operations |
144
- | `WriteError` | Error class for I/O failures during write |
145
- | `YAMLVerifier` | Verifies YAML binding file structure |
146
- | `SyntaxVerifier` | Verifies file is non-empty and readable |
147
- | `RegistryVerifier` | Verifies module registered in registry |
148
- | `MagicBytesVerifier` | Verifies file header matches expected bytes |
149
- | `JSONVerifier` | Verifies valid JSON, optional schema check |
150
- | `createWriteResult()` | Factory for WriteResult with defaults |
151
- | `runVerifierChain()` | Run verifier chain, short-circuit on first failure |
152
- | `Enhancer` | Pluggable interface for metadata enhancement |
153
- | `AIEnhancer` | SLM-based metadata enhancement for scanned modules |
154
- | `DisplayResolver` | Sparse binding.yaml overlay resolves alias, description, guidance, tags into `metadata["display"]` |
155
- | `VERSION` | Package version string |
161
+ The **Browser** column marks whether a symbol is also re-exported from
162
+ `apcore-toolkit/browser`. All symbols without a ✓ touch `node:fs`,
163
+ `node:path`, `node:module`, or `process.*` and are Node-only.
164
+
165
+ | Export | Browser | Description |
166
+ |--------|:---:|-------------|
167
+ | `ScannedModule` | | Interface for scanned endpoint data |
168
+ | `createScannedModule()` | | Factory with defaults for optional fields |
169
+ | `cloneModule()` | | Defensive copy with optional overrides |
170
+ | `BaseScanner` | | Abstract base class for scanners |
171
+ | `YAMLWriter` | | Writes YAML binding files |
172
+ | `BindingLoader` | | Reads `.binding.yaml` files from disk and parses them back into `ScannedModule` objects. Subclass of `BindingParser`. |
173
+ | `BindingParser` | ✓ | Runtime-neutral half of `BindingLoader`. `loadData(data)` parses an already-loaded binding document into `ScannedModule[]` no filesystem access. |
174
+ | `parseBindingDocument()` | | Standalone-function form of `BindingParser.loadData`, with an optional `filePath` for richer error messages. |
175
+ | `BindingLoadError` | | Error class raised when binding parsing fails; carries `filePath`, `moduleId`, `missingFields`, `reason` |
176
+ | `TypeScriptWriter` | | Generates TypeScript module wrappers |
177
+ | `RegistryWriter` | | Registers modules into an apcore Registry |
178
+ | `HTTPProxyRegistryWriter` | | Registers modules as HTTP-proxied entries in an in-memory registry. Each module's `execute()` forwards inputs to a backend URL via global `fetch`. Works in any runtime with `fetch` (Node 20+, browsers, edge, workers). |
179
+ | `HTTPProxyWriterError` | | Error class thrown when HTTP fields cannot be extracted from a `ScannedModule` |
180
+ | `getWriter()` | | Factory for writer instances |
181
+ | `extractInputSchema()` | | Extract input schema from OpenAPI operation |
182
+ | `extractOutputSchema()` | | Extract output schema from OpenAPI operation |
183
+ | `resolveRef()` | | Resolve `$ref` in OpenAPI documents |
184
+ | `resolveSchema()` | | Resolve schema with single-level `$ref` support |
185
+ | `deepResolveRefs()` | | Recursively resolve all nested `$ref` pointers in a schema |
186
+ | `enrichSchemaDescriptions()` | | Merge parameter descriptions into schema |
187
+ | `toMarkdown()` | | Convert dict to formatted Markdown |
188
+ | `moduleToDict()` | | Serialize module to snake_case dict |
189
+ | `modulesToDicts()` | | Batch serialize modules |
190
+ | `annotationsToDict()` | | Convert annotations to plain dict |
191
+ | `resolveTarget()` | | Dynamic import + named export resolution (supports `allowedPrefixes` allowlist) |
192
+ | `WriteResult` | | Structured result type for writer operations |
193
+ | `Verifier` | | Interface for pluggable output verification |
194
+ | `VerifyResult` | | Result type for verification operations |
195
+ | `WriteError` | | Error class for I/O failures during write |
196
+ | `InvalidFormatError` | | Error thrown by `getWriter` for unrecognised format names |
197
+ | `YAMLVerifier` | | Verifies YAML binding file structure (reads file) |
198
+ | `SyntaxVerifier` | | Verifies file is non-empty and parses as TypeScript (reads file) |
199
+ | `RegistryVerifier` | ✓ | Verifies module registered in a registry (pure; no filesystem) |
200
+ | `MagicBytesVerifier` | | Verifies file header matches expected bytes (reads file) |
201
+ | `JSONVerifier` | | Verifies valid JSON, optional schema check (reads file) |
202
+ | `createWriteResult()` | ✓ | Factory for WriteResult with defaults |
203
+ | `runVerifierChain()` | ✓ | Run verifier chain, short-circuit on first failure |
204
+ | `Enhancer` | | Pluggable interface for metadata enhancement |
205
+ | `AIEnhancer` | | SLM-based metadata enhancement for scanned modules |
206
+ | `DisplayResolver` | | Sparse binding.yaml overlay — resolves alias, description, guidance, tags into `metadata["display"]` |
207
+ | `VERSION` | | Package version string |
156
208
 
157
209
  ## Documentation
158
210
 
@@ -25,6 +25,22 @@ export interface AIEnhancerOptions {
25
25
  batchSize?: number;
26
26
  timeout?: number;
27
27
  }
28
+ /**
29
+ * AI-driven metadata enhancement using a local SLM (Small Language Model).
30
+ *
31
+ * Calls an OpenAI-compatible local API (Ollama, vLLM, LM Studio, etc.) to fill
32
+ * metadata gaps that static analysis cannot resolve: missing descriptions,
33
+ * behavioral annotation inference, and input schema generation for untyped
34
+ * functions.
35
+ *
36
+ * Enhancement is gated behind the `APCORE_AI_ENABLED` environment variable.
37
+ * All AI-generated fields are tagged with `x-generated-by: slm` in the module
38
+ * metadata for auditability.
39
+ *
40
+ * @example
41
+ * const enhancer = new AIEnhancer({ endpoint: 'http://localhost:11434/v1', model: 'qwen:0.6b' });
42
+ * const enhanced = await enhancer.enhance(modules);
43
+ */
28
44
  export declare class AIEnhancer {
29
45
  readonly endpoint: string;
30
46
  readonly model: string;
@@ -34,10 +50,11 @@ export declare class AIEnhancer {
34
50
  constructor(options?: AIEnhancerOptions);
35
51
  static isEnabled(): boolean;
36
52
  enhance(modules: ScannedModule[]): Promise<ScannedModule[]>;
53
+ private _annotationsAreDefault;
37
54
  private _identifyGaps;
38
55
  private _enhanceModule;
39
56
  private _buildPrompt;
40
57
  private _callLLM;
41
- static _parseResponse(response: string): Record<string, unknown>;
58
+ private static _parseResponse;
42
59
  }
43
60
  //# sourceMappingURL=ai-enhancer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-enhancer.d.ts","sourceRoot":"","sources":["../src/ai-enhancer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA4EhD;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,UAAU;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,CAAC,EAAE,iBAAiB;IAkBvC,MAAM,CAAC,SAAS,IAAI,OAAO;IAKrB,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IA0BjE,OAAO,CAAC,aAAa;YAkBP,cAAc;IA6E5B,OAAO,CAAC,YAAY;YAkDN,QAAQ;IAuCtB,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAcjE"}
1
+ {"version":3,"file":"ai-enhancer.d.ts","sourceRoot":"","sources":["../src/ai-enhancer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA4EhD;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,UAAU;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,CAAC,EAAE,iBAAiB;IA4BvC,MAAM,CAAC,SAAS,IAAI,OAAO;IAKrB,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IA+BjE,OAAO,CAAC,sBAAsB;IAc9B,OAAO,CAAC,aAAa;YAsBP,cAAc;IAyF5B,OAAO,CAAC,YAAY;YA2DN,QAAQ;IAuCtB,OAAO,CAAC,MAAM,CAAC,cAAc;CAsB9B"}