apcore-toolkit 0.5.0 → 0.6.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/CHANGELOG.md +23 -0
- package/LICENSE +1 -1
- package/dist/binding-loader.d.ts +5 -3
- package/dist/binding-loader.d.ts.map +1 -1
- package/dist/binding-loader.js +37 -6
- package/dist/binding-loader.js.map +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/formatting/index.d.ts +2 -0
- package/dist/formatting/index.d.ts.map +1 -1
- package/dist/formatting/index.js +1 -0
- package/dist/formatting/index.js.map +1 -1
- package/dist/formatting/surface.d.ts +44 -0
- package/dist/formatting/surface.d.ts.map +1 -0
- package/dist/formatting/surface.js +338 -0
- package/dist/formatting/surface.js.map +1 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -2
- package/dist/index.js.map +1 -1
- package/dist/openapi.d.ts.map +1 -1
- package/dist/openapi.js +42 -3
- package/dist/openapi.js.map +1 -1
- package/dist/output/base-writer.d.ts.map +1 -1
- package/dist/output/base-writer.js +4 -1
- package/dist/output/base-writer.js.map +1 -1
- package/dist/output/factory.d.ts +1 -1
- package/dist/output/factory.js +2 -2
- package/dist/output/factory.js.map +1 -1
- package/dist/output/http-proxy-writer.d.ts +9 -2
- package/dist/output/http-proxy-writer.d.ts.map +1 -1
- package/dist/output/http-proxy-writer.js +43 -8
- package/dist/output/http-proxy-writer.js.map +1 -1
- package/dist/output/registry-writer.d.ts.map +1 -1
- package/dist/output/registry-writer.js +8 -11
- package/dist/output/registry-writer.js.map +1 -1
- package/dist/output/typescript-writer.js +1 -1
- package/dist/output/typescript-writer.js.map +1 -1
- package/dist/output/verifiers.d.ts +2 -0
- package/dist/output/verifiers.d.ts.map +1 -1
- package/dist/output/verifiers.js +18 -6
- package/dist/output/verifiers.js.map +1 -1
- package/dist/output/verify-core.d.ts +3 -1
- package/dist/output/verify-core.d.ts.map +1 -1
- package/dist/output/verify-core.js +12 -2
- package/dist/output/verify-core.js.map +1 -1
- package/dist/output/yaml-writer.js +1 -1
- package/dist/output/yaml-writer.js.map +1 -1
- package/dist/scanner.d.ts +45 -5
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +92 -42
- package/dist/scanner.js.map +1 -1
- package/package.json +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
## [0.6.0] - 2026-05-07
|
|
5
|
+
|
|
6
|
+
### Changed
|
|
7
|
+
|
|
8
|
+
- **`apcore-js` minimum version bumped from 0.20.0 to 0.21.0** — `package.json` `dependencies` now requires `apcore-js >=0.21.0`. Toolkit only imports stable apcore-js surface (`ModuleAnnotations`, `DEFAULT_ANNOTATIONS`, `ModuleExample`, `Context`, `FunctionModule`, `jsonSchemaToTypeBox`, `annotationsFromJSON`, `annotationsToJSON`); the 0.21.0 additions (`discoverable` field on `ModuleAnnotations`, `PreviewResult`, `Change`, `ephemeral.*` namespace) are automatically handled — `annotationsFromJSON` / `annotationsToJSON` already serialize `discoverable`, and `inferAnnotationsFromMethod` spreads `DEFAULT_ANNOTATIONS` so the new field propagates without code changes. `AIEnhancer` derives its annotation field set from `Object.entries(DEFAULT_ANNOTATIONS)` at load time, so it also picks up `discoverable` automatically. Full vitest suite + `tsc --noEmit` verified against apcore-js 0.21.0.
|
|
9
|
+
- **`apcore-js` minimum version bumped from 0.19.0 to 0.20.0** — `package.json` `dependencies` now requires `apcore-js >=0.20.0`; `pnpm-lock.yaml` regenerated to `apcore-js@0.20.0`. Toolkit only imports stable apcore-js surface (`ModuleAnnotations`, `DEFAULT_ANNOTATIONS`, `ModuleExample`, `Context`, `FunctionModule`, `jsonSchemaToTypeBox`, `annotationsFromJSON`, `annotationsToJSON`); none of these were affected by 0.20.0 changes. Full vitest suite (490 passed) + `tsc --noEmit` clean against apcore-js 0.20.0.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Surface-aware formatters** (refs aiperceivable/apcore-toolkit#13) — `formatModule`, `formatSchema`, `formatModules` for rendering `ScannedModule` and JSON Schema for specific consumer surfaces. Four styles for `formatModule`: `markdown` (LLM context), `skill` (drop-in `.claude/skills/<id>/SKILL.md` or `.gemini/skills/<id>/SKILL.md` body with minimal `name` + `description` frontmatter — no vendor-specific extensions), `table-row` (CLI listing), `json` (programmatic). `formatSchema` styles: `prose`, `table`, `json`. `formatModules` adds optional `groupBy: "tag" | "prefix"`. `display: true` (default) prefers the `ScannedModule.display` overlay over raw fields. Lives in `src/formatting/surface.ts`; re-exported from the top-level package.
|
|
14
|
+
- **Annotation-table cross-SDK alignment** — `formatModule({style: "markdown" | "skill"})` `## Behavior` table now emits only fields that differ from `DEFAULT_ANNOTATIONS`, sorts rows alphabetically by snake_case key, and renders bool values as lowercase `true`/`false`. The section is omitted entirely when every annotation field matches its default. Closes the byte-equality gap with the Python and Rust SDKs.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **`inferAnnotationsFromMethod` canonical mapping** (refs aiperceivable/apcore-toolkit#11) — `HEAD` and `OPTIONS` now map to `readonly=true` (without `cacheable=true`), matching the canonical mapping declared in `apcore-toolkit/docs/features/scanning.md` and aligning with the existing Rust SDK. Previously these methods returned default annotations.
|
|
19
|
+
|
|
20
|
+
## [0.5.1] - 2026-04-30
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **`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.
|
|
25
|
+
|
|
3
26
|
## [0.5.0] - 2026-04-21
|
|
4
27
|
|
|
5
28
|
### Added
|
package/LICENSE
CHANGED
package/dist/binding-loader.d.ts
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
* from `apcore-toolkit/browser` instead.
|
|
14
14
|
*/
|
|
15
15
|
import { BindingParser } from './binding-parser.js';
|
|
16
|
-
import type { BindingLoadOptions } from './binding-parser.js';
|
|
17
16
|
import type { ScannedModule } from './types.js';
|
|
18
17
|
export { BindingLoadError, BindingParser, parseBindingDocument } from './binding-parser.js';
|
|
19
18
|
export type { BindingLoadOptions } from './binding-parser.js';
|
|
@@ -29,17 +28,20 @@ export type { BindingLoadOptions } from './binding-parser.js';
|
|
|
29
28
|
* ```ts
|
|
30
29
|
* const loader = new BindingLoader();
|
|
31
30
|
* const modules = loader.load('./bindings/');
|
|
32
|
-
* const strict = loader.load('foo.binding.yaml',
|
|
31
|
+
* const strict = loader.load('foo.binding.yaml', true, false);
|
|
33
32
|
* ```
|
|
34
33
|
*/
|
|
35
34
|
export declare class BindingLoader extends BindingParser {
|
|
36
35
|
/**
|
|
37
36
|
* Load one file or every `*.binding.yaml` in a directory.
|
|
38
37
|
*
|
|
38
|
+
* @param filePath - Path to a single `.binding.yaml` file or a directory.
|
|
39
|
+
* @param strict - When `true`, also require `input_schema` and `output_schema`. Default: `false`.
|
|
40
|
+
* @param recursive - When `true`, recurse into subdirectories. Default: `false`.
|
|
39
41
|
* @throws {BindingLoadError} when the path is missing, YAML is malformed,
|
|
40
42
|
* or any entry fails validation.
|
|
41
43
|
*/
|
|
42
|
-
load(filePath: string,
|
|
44
|
+
load(filePath: string, strict?: boolean, recursive?: boolean): ScannedModule[];
|
|
43
45
|
/**
|
|
44
46
|
* Recursively collect `.binding.yaml` files under `dir`. Follows symlinks
|
|
45
47
|
* (for parity with the non-recursive branch, which reads file contents and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"binding-loader.d.ts","sourceRoot":"","sources":["../src/binding-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EAEL,aAAa,EAEd,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"binding-loader.d.ts","sourceRoot":"","sources":["../src/binding-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EAEL,aAAa,EAEd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAOhD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC5F,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAgB9D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,aAAc,SAAQ,aAAa;IAC9C;;;;;;;;OAQG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,OAAO,GAAG,aAAa,EAAE;IAwF9E;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;CA6C1B"}
|
package/dist/binding-loader.js
CHANGED
|
@@ -22,6 +22,10 @@ import { BindingLoadError, BindingParser, parseBindingDocument, } from './bindin
|
|
|
22
22
|
// change — plus the new {@link BindingParser} and
|
|
23
23
|
// {@link parseBindingDocument} additions that are now also available.
|
|
24
24
|
export { BindingLoadError, BindingParser, parseBindingDocument } from './binding-parser.js';
|
|
25
|
+
/** Maximum file size (bytes) that BindingLoader will read — matches Rust SDK's 16 MiB cap. */
|
|
26
|
+
const MAX_BINDING_FILE_SIZE = 16 * 1024 * 1024; // 16 MiB
|
|
27
|
+
/** Maximum number of .binding.yaml files per directory scan — matches Rust SDK's cap. */
|
|
28
|
+
const MAX_BINDING_FILES_PER_DIR = 10_000;
|
|
25
29
|
// Cap on directory recursion depth in `_collectRecursive`. This is the
|
|
26
30
|
// PRIMARY defense against symlink loops (`a -> b -> a`): `statSync` resolves
|
|
27
31
|
// symlinks but does not detect cycles, so a cyclic graph would recurse until
|
|
@@ -41,19 +45,22 @@ const MAX_RECURSION_DEPTH = 64;
|
|
|
41
45
|
* ```ts
|
|
42
46
|
* const loader = new BindingLoader();
|
|
43
47
|
* const modules = loader.load('./bindings/');
|
|
44
|
-
* const strict = loader.load('foo.binding.yaml',
|
|
48
|
+
* const strict = loader.load('foo.binding.yaml', true, false);
|
|
45
49
|
* ```
|
|
46
50
|
*/
|
|
47
51
|
export class BindingLoader extends BindingParser {
|
|
48
52
|
/**
|
|
49
53
|
* Load one file or every `*.binding.yaml` in a directory.
|
|
50
54
|
*
|
|
55
|
+
* @param filePath - Path to a single `.binding.yaml` file or a directory.
|
|
56
|
+
* @param strict - When `true`, also require `input_schema` and `output_schema`. Default: `false`.
|
|
57
|
+
* @param recursive - When `true`, recurse into subdirectories. Default: `false`.
|
|
51
58
|
* @throws {BindingLoadError} when the path is missing, YAML is malformed,
|
|
52
59
|
* or any entry fails validation.
|
|
53
60
|
*/
|
|
54
|
-
load(filePath,
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
load(filePath, strict, recursive) {
|
|
62
|
+
strict = strict ?? false;
|
|
63
|
+
recursive = recursive ?? false;
|
|
57
64
|
let stat;
|
|
58
65
|
try {
|
|
59
66
|
stat = fs.statSync(filePath);
|
|
@@ -74,9 +81,16 @@ export class BindingLoader extends BindingParser {
|
|
|
74
81
|
files = this._collectRecursive(filePath).sort();
|
|
75
82
|
}
|
|
76
83
|
else {
|
|
77
|
-
|
|
84
|
+
const allEntries = fs
|
|
78
85
|
.readdirSync(filePath)
|
|
79
|
-
.filter((f) => f.endsWith('.binding.yaml'))
|
|
86
|
+
.filter((f) => f.endsWith('.binding.yaml'));
|
|
87
|
+
if (allEntries.length > MAX_BINDING_FILES_PER_DIR) {
|
|
88
|
+
throw new BindingLoadError({
|
|
89
|
+
reason: `too many files in directory: ${allEntries.length} exceeds limit of ${MAX_BINDING_FILES_PER_DIR}`,
|
|
90
|
+
filePath,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
files = allEntries
|
|
80
94
|
.sort()
|
|
81
95
|
.map((f) => path.join(filePath, f));
|
|
82
96
|
}
|
|
@@ -89,6 +103,23 @@ export class BindingLoader extends BindingParser {
|
|
|
89
103
|
}
|
|
90
104
|
const modules = [];
|
|
91
105
|
for (const f of files) {
|
|
106
|
+
// Enforce per-file size cap before reading
|
|
107
|
+
let fileStat;
|
|
108
|
+
try {
|
|
109
|
+
fileStat = fs.statSync(f);
|
|
110
|
+
}
|
|
111
|
+
catch (exc) {
|
|
112
|
+
throw new BindingLoadError({
|
|
113
|
+
reason: `failed to stat file: ${exc.message}`,
|
|
114
|
+
filePath: f,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (fileStat.size > MAX_BINDING_FILE_SIZE) {
|
|
118
|
+
throw new BindingLoadError({
|
|
119
|
+
reason: `file too large: ${fileStat.size} bytes exceeds limit of ${MAX_BINDING_FILE_SIZE} bytes (16 MiB)`,
|
|
120
|
+
filePath: f,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
92
123
|
let content;
|
|
93
124
|
try {
|
|
94
125
|
content = fs.readFileSync(f, 'utf-8');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"binding-loader.js","sourceRoot":"","sources":["../src/binding-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAI7B,qEAAqE;AACrE,yEAAyE;AACzE,sEAAsE;AACtE,kDAAkD;AAClD,sEAAsE;AACtE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAG5F,uEAAuE;AACvE,6EAA6E;AAC7E,6EAA6E;AAC7E,wEAAwE;AACxE,mEAAmE;AACnE,0BAA0B;AAC1B,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,aAAc,SAAQ,aAAa;IAC9C
|
|
1
|
+
{"version":3,"file":"binding-loader.js","sourceRoot":"","sources":["../src/binding-loader.ts"],"names":[],"mappings":"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"}
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -12,6 +12,6 @@ export type { WriteResult, VerifyResult, Verifier } from '../output/types.js';
|
|
|
12
12
|
export { createWriteResult } from '../output/types.js';
|
|
13
13
|
export { WriteError, InvalidFormatError } from '../output/errors.js';
|
|
14
14
|
export { RegistryVerifier, runVerifierChain } from '../output/verify-core.js';
|
|
15
|
-
export { HTTPProxyRegistryWriter,
|
|
15
|
+
export { HTTPProxyRegistryWriter, HTTPProxyRegistryWriterError, } from '../output/http-proxy-writer.js';
|
|
16
16
|
export type { HTTPProxyRegistryWriterOptions, ProxyRegistry, } from '../output/http-proxy-writer.js';
|
|
17
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAkBA,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAOpD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAK/D,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAMrE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAO9E,OAAO,EACL,uBAAuB,EACvB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAkBA,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAOpD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAK/D,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAMrE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAO9E,OAAO,EACL,uBAAuB,EACvB,4BAA4B,GAC7B,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,8BAA8B,EAC9B,aAAa,GACd,MAAM,gCAAgC,CAAC"}
|
package/dist/browser/index.js
CHANGED
|
@@ -42,5 +42,5 @@ export { RegistryVerifier, runVerifierChain } from '../output/verify-core.js';
|
|
|
42
42
|
// registry — each module's `execute()` forwards inputs to a backend URL.
|
|
43
43
|
// Works in any environment where `fetch` is available (Node 20+, browsers,
|
|
44
44
|
// Deno, workers).
|
|
45
|
-
export { HTTPProxyRegistryWriter,
|
|
45
|
+
export { HTTPProxyRegistryWriter, HTTPProxyRegistryWriterError, } from '../output/http-proxy-writer.js';
|
|
46
46
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAC1E,wEAAwE;AACxE,uEAAuE;AACvE,sBAAsB;AACtB,EAAE;AACF,6EAA6E;AAC7E,wEAAwE;AACxE,0EAA0E;AAC1E,0EAA0E;AAC1E,wEAAwE;AACxE,qEAAqE;AACrE,yEAAyE;AACzE,MAAM;AAIN,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,6EAA6E;AAC7E,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,6EAA6E;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAEvB,6EAA6E;AAC7E,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,6EAA6E;AAC7E,4EAA4E;AAC5E,6EAA6E;AAC7E,2EAA2E;AAC3E,qDAAqD;AACrD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAErE,6EAA6E;AAC7E,gFAAgF;AAChF,2EAA2E;AAC3E,4BAA4B;AAC5B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE9E,6EAA6E;AAC7E,sEAAsE;AACtE,yEAAyE;AACzE,2EAA2E;AAC3E,kBAAkB;AAClB,OAAO,EACL,uBAAuB,EACvB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAC1E,wEAAwE;AACxE,uEAAuE;AACvE,sBAAsB;AACtB,EAAE;AACF,6EAA6E;AAC7E,wEAAwE;AACxE,0EAA0E;AAC1E,0EAA0E;AAC1E,wEAAwE;AACxE,qEAAqE;AACrE,yEAAyE;AACzE,MAAM;AAIN,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,6EAA6E;AAC7E,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,6EAA6E;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAEvB,6EAA6E;AAC7E,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,6EAA6E;AAC7E,4EAA4E;AAC5E,6EAA6E;AAC7E,2EAA2E;AAC3E,qDAAqD;AACrD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAErE,6EAA6E;AAC7E,gFAAgF;AAChF,2EAA2E;AAC3E,4BAA4B;AAC5B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE9E,6EAA6E;AAC7E,sEAAsE;AACtE,yEAAyE;AACzE,2EAA2E;AAC3E,kBAAkB;AAClB,OAAO,EACL,uBAAuB,EACvB,4BAA4B,GAC7B,MAAM,gCAAgC,CAAC"}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { toMarkdown } from './markdown.js';
|
|
2
|
+
export { formatSchema, formatModule, formatModules, } from './surface.js';
|
|
3
|
+
export type { SchemaStyle, ModuleStyle, GroupBy, FormatSchemaOptions, FormatModuleOptions, FormatModulesOptions, } from './surface.js';
|
|
2
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formatting/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formatting/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,cAAc,CAAC"}
|
package/dist/formatting/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/formatting/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/formatting/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface-aware formatters.
|
|
3
|
+
*
|
|
4
|
+
* Render `ScannedModule` and JSON Schema for specific consumer surfaces:
|
|
5
|
+
* LLM context (markdown), agent skill files (skill), CLI listings (table-row),
|
|
6
|
+
* and programmatic APIs (json). See
|
|
7
|
+
* `apcore-toolkit/docs/features/formatting.md`.
|
|
8
|
+
*/
|
|
9
|
+
import type { ScannedModule } from '../types.js';
|
|
10
|
+
export type SchemaStyle = 'prose' | 'table' | 'json';
|
|
11
|
+
export type ModuleStyle = 'markdown' | 'skill' | 'table-row' | 'json';
|
|
12
|
+
export type GroupBy = 'tag' | 'prefix';
|
|
13
|
+
export interface FormatSchemaOptions {
|
|
14
|
+
style?: SchemaStyle;
|
|
15
|
+
maxDepth?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface FormatModuleOptions {
|
|
18
|
+
style?: ModuleStyle;
|
|
19
|
+
display?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface FormatModulesOptions {
|
|
22
|
+
style?: ModuleStyle;
|
|
23
|
+
groupBy?: GroupBy | null;
|
|
24
|
+
display?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Render a JSON Schema for a specific surface.
|
|
28
|
+
* See `Contract: format_schema` in
|
|
29
|
+
* `apcore-toolkit/docs/features/formatting.md`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatSchema(schema: Record<string, unknown>, options?: FormatSchemaOptions): string | Record<string, unknown>;
|
|
32
|
+
/**
|
|
33
|
+
* Render a single ScannedModule for the chosen surface.
|
|
34
|
+
* See `Contract: format_module` in
|
|
35
|
+
* `apcore-toolkit/docs/features/formatting.md`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function formatModule(module: ScannedModule, options?: FormatModuleOptions): string | Record<string, unknown>;
|
|
38
|
+
/**
|
|
39
|
+
* Render a sequence of ScannedModule for the chosen surface.
|
|
40
|
+
* See `Contract: format_modules` in
|
|
41
|
+
* `apcore-toolkit/docs/features/formatting.md`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function formatModules(modules: ScannedModule[], options?: FormatModulesOptions): string | Record<string, unknown>[];
|
|
44
|
+
//# sourceMappingURL=surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/formatting/surface.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AASjD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,MAAM,CAAC;AACtE,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAMvC,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,GAAE,mBAAwB,GAChC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwClC;AAyED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,mBAAwB,GAChC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA+BlC;AAoJD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,aAAa,EAAE,EACxB,OAAO,GAAE,oBAAyB,GACjC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAyCpC"}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface-aware formatters.
|
|
3
|
+
*
|
|
4
|
+
* Render `ScannedModule` and JSON Schema for specific consumer surfaces:
|
|
5
|
+
* LLM context (markdown), agent skill files (skill), CLI listings (table-row),
|
|
6
|
+
* and programmatic APIs (json). See
|
|
7
|
+
* `apcore-toolkit/docs/features/formatting.md`.
|
|
8
|
+
*/
|
|
9
|
+
import { DEFAULT_ANNOTATIONS } from 'apcore-js';
|
|
10
|
+
import { annotationsToDict, moduleToDict } from '../serializers.js';
|
|
11
|
+
// Snake-case dict of every default-valued annotation field. Used by the
|
|
12
|
+
// behavior-table renderer to skip fields that match the protocol default,
|
|
13
|
+
// keeping the table focused on what is actually non-default about the module.
|
|
14
|
+
const DEFAULT_ANNOTATIONS_DICT = annotationsToDict(DEFAULT_ANNOTATIONS) ?? {};
|
|
15
|
+
const SCHEMA_STYLES = ['prose', 'table', 'json'];
|
|
16
|
+
const MODULE_STYLES = ['markdown', 'skill', 'table-row', 'json'];
|
|
17
|
+
const GROUP_BY_VALUES = ['tag', 'prefix'];
|
|
18
|
+
/**
|
|
19
|
+
* Render a JSON Schema for a specific surface.
|
|
20
|
+
* See `Contract: format_schema` in
|
|
21
|
+
* `apcore-toolkit/docs/features/formatting.md`.
|
|
22
|
+
*/
|
|
23
|
+
export function formatSchema(schema, options = {}) {
|
|
24
|
+
const style = options.style ?? 'prose';
|
|
25
|
+
const maxDepth = options.maxDepth ?? 3;
|
|
26
|
+
if (!SCHEMA_STYLES.includes(style)) {
|
|
27
|
+
throw new Error(`formatSchema: unknown style ${JSON.stringify(style)}; expected one of ${JSON.stringify(SCHEMA_STYLES)}`);
|
|
28
|
+
}
|
|
29
|
+
if (style === 'json') {
|
|
30
|
+
return schema;
|
|
31
|
+
}
|
|
32
|
+
if (!schema || typeof schema !== 'object') {
|
|
33
|
+
return '';
|
|
34
|
+
}
|
|
35
|
+
const type = schema['type'];
|
|
36
|
+
const properties = schema['properties'];
|
|
37
|
+
if (type !== 'object' || !properties || typeof properties !== 'object') {
|
|
38
|
+
if (type && type !== 'object') {
|
|
39
|
+
return `_schema accepts ${type}_`;
|
|
40
|
+
}
|
|
41
|
+
if (style === 'prose') {
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
return '| Name | Type | Required | Default | Description |\n|---|---|---|---|---|\n';
|
|
45
|
+
}
|
|
46
|
+
const required = new Set(Array.isArray(schema['required'])
|
|
47
|
+
? schema['required']
|
|
48
|
+
: []);
|
|
49
|
+
if (style === 'prose') {
|
|
50
|
+
return formatSchemaProse(properties, required, maxDepth, 0);
|
|
51
|
+
}
|
|
52
|
+
return formatSchemaTable(properties, required);
|
|
53
|
+
}
|
|
54
|
+
function formatSchemaProse(properties, required, maxDepth, depth) {
|
|
55
|
+
const lines = [];
|
|
56
|
+
for (const [name, propRaw] of Object.entries(properties)) {
|
|
57
|
+
const prop = (typeof propRaw === 'object' && propRaw !== null) ? propRaw : {};
|
|
58
|
+
const type = prop['type'] ?? 'any';
|
|
59
|
+
const reqLabel = required.has(name) ? 'required' : 'optional';
|
|
60
|
+
const desc = (prop['description'] ?? '').trim();
|
|
61
|
+
let head = `- \`${name}\` (${type}, ${reqLabel})`;
|
|
62
|
+
if (desc) {
|
|
63
|
+
head += ` — ${desc}`;
|
|
64
|
+
}
|
|
65
|
+
lines.push(head);
|
|
66
|
+
if (prop['type'] === 'object' &&
|
|
67
|
+
typeof prop['properties'] === 'object' &&
|
|
68
|
+
prop['properties'] !== null) {
|
|
69
|
+
if (depth + 1 >= maxDepth) {
|
|
70
|
+
lines.push(' ```json');
|
|
71
|
+
for (const jsonLine of JSON.stringify(prop, null, 2).split('\n')) {
|
|
72
|
+
lines.push(` ${jsonLine}`);
|
|
73
|
+
}
|
|
74
|
+
lines.push(' ```');
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const nestedRequired = new Set(Array.isArray(prop['required']) ? prop['required'] : []);
|
|
78
|
+
const nested = formatSchemaProse(prop['properties'], nestedRequired, maxDepth, depth + 1);
|
|
79
|
+
for (const nestedLine of nested.split('\n')) {
|
|
80
|
+
lines.push(` ${nestedLine}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return lines.join('\n');
|
|
86
|
+
}
|
|
87
|
+
function formatSchemaTable(properties, required) {
|
|
88
|
+
const rows = [
|
|
89
|
+
'| Name | Type | Required | Default | Description |',
|
|
90
|
+
'|---|---|---|---|---|',
|
|
91
|
+
];
|
|
92
|
+
for (const [name, propRaw] of Object.entries(properties)) {
|
|
93
|
+
const prop = (typeof propRaw === 'object' && propRaw !== null) ? propRaw : {};
|
|
94
|
+
const type = prop['type'] ?? 'any';
|
|
95
|
+
const reqLabel = required.has(name) ? 'yes' : 'no';
|
|
96
|
+
const desc = (prop['description'] ?? '').trim();
|
|
97
|
+
let defaultStr = '';
|
|
98
|
+
if (prop['default'] !== undefined) {
|
|
99
|
+
const d = prop['default'];
|
|
100
|
+
defaultStr = typeof d === 'object' ? JSON.stringify(d) : String(d);
|
|
101
|
+
}
|
|
102
|
+
rows.push(`| \`${name}\` | ${type} | ${reqLabel} | ${defaultStr} | ${desc} |`);
|
|
103
|
+
}
|
|
104
|
+
return rows.join('\n');
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Render a single ScannedModule for the chosen surface.
|
|
108
|
+
* See `Contract: format_module` in
|
|
109
|
+
* `apcore-toolkit/docs/features/formatting.md`.
|
|
110
|
+
*/
|
|
111
|
+
export function formatModule(module, options = {}) {
|
|
112
|
+
const style = options.style ?? 'markdown';
|
|
113
|
+
const display = options.display ?? true;
|
|
114
|
+
if (!MODULE_STYLES.includes(style)) {
|
|
115
|
+
throw new Error(`formatModule: unknown style ${JSON.stringify(style)}; expected one of ${JSON.stringify(MODULE_STYLES)}`);
|
|
116
|
+
}
|
|
117
|
+
if (style === 'json') {
|
|
118
|
+
return moduleToDict(module);
|
|
119
|
+
}
|
|
120
|
+
const { title, description, guidance, tags } = resolveDisplayFields(module, display);
|
|
121
|
+
if (style === 'table-row') {
|
|
122
|
+
const alias = title !== module.moduleId ? title : '';
|
|
123
|
+
const tagStr = tags.length > 0 ? tags.join(', ') : '';
|
|
124
|
+
return `\`${module.moduleId}\` │ \`${alias}\` │ ${description} │ ${tagStr}`;
|
|
125
|
+
}
|
|
126
|
+
const body = renderModuleMarkdownBody(module, title, description, guidance, tags);
|
|
127
|
+
if (style === 'skill') {
|
|
128
|
+
const oneLine = description.replace(/\n/g, ' ').trim();
|
|
129
|
+
const frontmatter = `---\nname: ${title}\ndescription: ${yamlScalar(oneLine)}\n---\n\n`;
|
|
130
|
+
return frontmatter + body;
|
|
131
|
+
}
|
|
132
|
+
return body;
|
|
133
|
+
}
|
|
134
|
+
function resolveDisplayFields(module, useDisplay) {
|
|
135
|
+
const rawTitle = module.moduleId;
|
|
136
|
+
const rawDesc = module.description ?? '';
|
|
137
|
+
const rawTags = module.tags ? [...module.tags] : [];
|
|
138
|
+
if (!useDisplay || !module.display) {
|
|
139
|
+
return { title: rawTitle, description: rawDesc, guidance: null, tags: rawTags };
|
|
140
|
+
}
|
|
141
|
+
const overlay = module.display;
|
|
142
|
+
const title = overlay['alias'] || rawTitle;
|
|
143
|
+
const description = overlay['description'] || rawDesc;
|
|
144
|
+
const guidance = overlay['guidance'] || null;
|
|
145
|
+
const tagsOverlay = overlay['tags'];
|
|
146
|
+
const tags = Array.isArray(tagsOverlay) && tagsOverlay.length > 0
|
|
147
|
+
? tagsOverlay
|
|
148
|
+
: rawTags;
|
|
149
|
+
return { title, description, guidance, tags: [...tags] };
|
|
150
|
+
}
|
|
151
|
+
function renderModuleMarkdownBody(module, title, description, guidance, tags) {
|
|
152
|
+
const sections = [];
|
|
153
|
+
sections.push(`# ${title}`);
|
|
154
|
+
if (description) {
|
|
155
|
+
sections.push(description);
|
|
156
|
+
}
|
|
157
|
+
if (guidance) {
|
|
158
|
+
sections.push(`_${guidance}_`);
|
|
159
|
+
}
|
|
160
|
+
sections.push('## Parameters');
|
|
161
|
+
const paramsProse = formatSchema(module.inputSchema ?? {}, { style: 'prose' });
|
|
162
|
+
sections.push(paramsProse ? paramsProse : '_(no parameters)_');
|
|
163
|
+
sections.push('## Returns');
|
|
164
|
+
const returnsProse = formatSchema(module.outputSchema ?? {}, { style: 'prose' });
|
|
165
|
+
sections.push(returnsProse ? returnsProse : '_(no return schema)_');
|
|
166
|
+
const annotationTable = renderAnnotationsTable(module.annotations);
|
|
167
|
+
if (annotationTable) {
|
|
168
|
+
sections.push('## Behavior');
|
|
169
|
+
sections.push(annotationTable);
|
|
170
|
+
}
|
|
171
|
+
if (module.examples && module.examples.length > 0) {
|
|
172
|
+
sections.push('## Examples');
|
|
173
|
+
let idx = 1;
|
|
174
|
+
for (const example of module.examples) {
|
|
175
|
+
sections.push(`### Example ${idx}`);
|
|
176
|
+
sections.push('```json');
|
|
177
|
+
sections.push(JSON.stringify(example, null, 2));
|
|
178
|
+
sections.push('```');
|
|
179
|
+
idx += 1;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (tags.length > 0) {
|
|
183
|
+
sections.push('## Tags');
|
|
184
|
+
sections.push(tags.map((t) => `\`${t}\``).join(', '));
|
|
185
|
+
}
|
|
186
|
+
return sections.join('\n\n') + '\n';
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Render `ModuleAnnotations` as a Markdown fact table.
|
|
190
|
+
*
|
|
191
|
+
* Cross-SDK alignment rules (see
|
|
192
|
+
* `apcore-toolkit/docs/features/formatting.md` § Annotations Rendering):
|
|
193
|
+
*
|
|
194
|
+
* 1. Emit only fields whose value differs from `DEFAULT_ANNOTATIONS`.
|
|
195
|
+
* 2. The `extra` free-form bag is always skipped.
|
|
196
|
+
* 3. Rows are sorted alphabetically by snake_case key.
|
|
197
|
+
* 4. Bool values render as lowercase `true` / `false`; objects/arrays use
|
|
198
|
+
* `JSON.stringify`; everything else uses `String()`.
|
|
199
|
+
*
|
|
200
|
+
* Returns `null` when the resulting table would be empty (i.e. every
|
|
201
|
+
* annotation field equals its default), causing the caller to omit the
|
|
202
|
+
* `## Behavior` section entirely.
|
|
203
|
+
*/
|
|
204
|
+
function renderAnnotationsTable(annotations) {
|
|
205
|
+
const data = annotationsToDict(annotations);
|
|
206
|
+
if (!data)
|
|
207
|
+
return null;
|
|
208
|
+
const entries = [];
|
|
209
|
+
for (const [key, value] of Object.entries(data)) {
|
|
210
|
+
if (key === 'extra')
|
|
211
|
+
continue;
|
|
212
|
+
if (deepEqual(value, DEFAULT_ANNOTATIONS_DICT[key]))
|
|
213
|
+
continue;
|
|
214
|
+
entries.push([key, value]);
|
|
215
|
+
}
|
|
216
|
+
if (entries.length === 0)
|
|
217
|
+
return null;
|
|
218
|
+
entries.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
219
|
+
const rows = ['| Flag | Value |', '|---|---|'];
|
|
220
|
+
for (const [key, value] of entries) {
|
|
221
|
+
let rendered;
|
|
222
|
+
if (value === true) {
|
|
223
|
+
rendered = 'true';
|
|
224
|
+
}
|
|
225
|
+
else if (value === false) {
|
|
226
|
+
rendered = 'false';
|
|
227
|
+
}
|
|
228
|
+
else if (typeof value === 'object' && value !== null) {
|
|
229
|
+
rendered = JSON.stringify(value);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
rendered = String(value);
|
|
233
|
+
}
|
|
234
|
+
rows.push(`| \`${key}\` | ${rendered} |`);
|
|
235
|
+
}
|
|
236
|
+
return rows.join('\n');
|
|
237
|
+
}
|
|
238
|
+
function deepEqual(a, b) {
|
|
239
|
+
if (a === b)
|
|
240
|
+
return true;
|
|
241
|
+
if (a === null || b === null)
|
|
242
|
+
return false;
|
|
243
|
+
if (typeof a !== typeof b)
|
|
244
|
+
return false;
|
|
245
|
+
if (typeof a !== 'object')
|
|
246
|
+
return false;
|
|
247
|
+
if (Array.isArray(a) !== Array.isArray(b))
|
|
248
|
+
return false;
|
|
249
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
250
|
+
if (a.length !== b.length)
|
|
251
|
+
return false;
|
|
252
|
+
return a.every((v, i) => deepEqual(v, b[i]));
|
|
253
|
+
}
|
|
254
|
+
const aKeys = Object.keys(a).sort();
|
|
255
|
+
const bKeys = Object.keys(b).sort();
|
|
256
|
+
if (aKeys.length !== bKeys.length)
|
|
257
|
+
return false;
|
|
258
|
+
if (!aKeys.every((k, i) => k === bKeys[i]))
|
|
259
|
+
return false;
|
|
260
|
+
return aKeys.every((k) => deepEqual(a[k], b[k]));
|
|
261
|
+
}
|
|
262
|
+
function yamlScalar(text) {
|
|
263
|
+
if (text === '')
|
|
264
|
+
return '""';
|
|
265
|
+
const needsQuote = /[:#{}[\]'"\n&*!|>]/.test(text);
|
|
266
|
+
if (!needsQuote && !/^[-?%@`]/.test(text)) {
|
|
267
|
+
return text;
|
|
268
|
+
}
|
|
269
|
+
const escaped = text.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
270
|
+
return `"${escaped}"`;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Render a sequence of ScannedModule for the chosen surface.
|
|
274
|
+
* See `Contract: format_modules` in
|
|
275
|
+
* `apcore-toolkit/docs/features/formatting.md`.
|
|
276
|
+
*/
|
|
277
|
+
export function formatModules(modules, options = {}) {
|
|
278
|
+
const style = options.style ?? 'markdown';
|
|
279
|
+
const groupBy = options.groupBy ?? null;
|
|
280
|
+
const display = options.display ?? true;
|
|
281
|
+
if (!MODULE_STYLES.includes(style)) {
|
|
282
|
+
throw new Error(`formatModules: unknown style ${JSON.stringify(style)}; expected one of ${JSON.stringify(MODULE_STYLES)}`);
|
|
283
|
+
}
|
|
284
|
+
if (groupBy !== null && !GROUP_BY_VALUES.includes(groupBy)) {
|
|
285
|
+
throw new Error(`formatModules: unknown groupBy ${JSON.stringify(groupBy)}; expected one of ${JSON.stringify(GROUP_BY_VALUES)} or null`);
|
|
286
|
+
}
|
|
287
|
+
if (style === 'json') {
|
|
288
|
+
return modules.map((m) => moduleToDict(m));
|
|
289
|
+
}
|
|
290
|
+
const joiner = (style === 'markdown' || style === 'skill') ? '\n\n' : '\n';
|
|
291
|
+
if (groupBy === null) {
|
|
292
|
+
return modules
|
|
293
|
+
.map((m) => formatModule(m, { style, display }))
|
|
294
|
+
.join(joiner);
|
|
295
|
+
}
|
|
296
|
+
const groups = groupModules(modules, groupBy);
|
|
297
|
+
const out = [];
|
|
298
|
+
for (const [groupName, groupMembers] of groups) {
|
|
299
|
+
if (style === 'markdown' || style === 'skill') {
|
|
300
|
+
out.push(`## ${groupName}`);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
out.push(`── ${groupName} ──`);
|
|
304
|
+
}
|
|
305
|
+
for (const m of groupMembers) {
|
|
306
|
+
out.push(formatModule(m, { style, display }));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return out.join(joiner);
|
|
310
|
+
}
|
|
311
|
+
function groupModules(modules, groupBy) {
|
|
312
|
+
const groups = new Map();
|
|
313
|
+
for (const module of modules) {
|
|
314
|
+
if (groupBy === 'prefix') {
|
|
315
|
+
const idx = module.moduleId.indexOf('.');
|
|
316
|
+
const prefix = idx >= 0 ? module.moduleId.slice(0, idx) : module.moduleId;
|
|
317
|
+
const arr = groups.get(prefix) ?? [];
|
|
318
|
+
arr.push(module);
|
|
319
|
+
groups.set(prefix, arr);
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
// groupBy === 'tag'
|
|
323
|
+
if (!module.tags || module.tags.length === 0) {
|
|
324
|
+
const arr = groups.get('(untagged)') ?? [];
|
|
325
|
+
arr.push(module);
|
|
326
|
+
groups.set('(untagged)', arr);
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
for (const tag of module.tags) {
|
|
330
|
+
const arr = groups.get(tag) ?? [];
|
|
331
|
+
arr.push(module);
|
|
332
|
+
groups.set(tag, arr);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return groups;
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=surface.js.map
|