@vibe-agent-toolkit/resources 0.1.38 → 0.1.39-rc.10
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/README.md +33 -24
- package/dist/frontmatter-link-validator.d.ts +9 -9
- package/dist/frontmatter-link-validator.d.ts.map +1 -1
- package/dist/frontmatter-link-validator.js +28 -27
- package/dist/frontmatter-link-validator.js.map +1 -1
- package/dist/frontmatter-validator.d.ts +3 -2
- package/dist/frontmatter-validator.d.ts.map +1 -1
- package/dist/frontmatter-validator.js +8 -14
- package/dist/frontmatter-validator.js.map +1 -1
- package/dist/html-link-parser.d.ts +47 -0
- package/dist/html-link-parser.d.ts.map +1 -0
- package/dist/html-link-parser.js +111 -0
- package/dist/html-link-parser.js.map +1 -0
- package/dist/html-transform.d.ts +45 -0
- package/dist/html-transform.d.ts.map +1 -0
- package/dist/html-transform.js +116 -0
- package/dist/html-transform.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/link-parser.d.ts +26 -2
- package/dist/link-parser.d.ts.map +1 -1
- package/dist/link-parser.js +40 -6
- package/dist/link-parser.js.map +1 -1
- package/dist/link-validator.d.ts +53 -6
- package/dist/link-validator.d.ts.map +1 -1
- package/dist/link-validator.js +100 -131
- package/dist/link-validator.js.map +1 -1
- package/dist/multi-schema-validator.d.ts.map +1 -1
- package/dist/multi-schema-validator.js +6 -8
- package/dist/multi-schema-validator.js.map +1 -1
- package/dist/resource-registry.d.ts +56 -13
- package/dist/resource-registry.d.ts.map +1 -1
- package/dist/resource-registry.js +165 -66
- package/dist/resource-registry.js.map +1 -1
- package/dist/schemas/link-auth.d.ts +382 -0
- package/dist/schemas/link-auth.d.ts.map +1 -0
- package/dist/schemas/link-auth.js +124 -0
- package/dist/schemas/link-auth.js.map +1 -0
- package/dist/schemas/project-config.d.ts +3277 -171
- package/dist/schemas/project-config.d.ts.map +1 -1
- package/dist/schemas/project-config.js +68 -0
- package/dist/schemas/project-config.js.map +1 -1
- package/dist/schemas/resource-metadata.d.ts +46 -10
- package/dist/schemas/resource-metadata.d.ts.map +1 -1
- package/dist/schemas/resource-metadata.js +14 -1
- package/dist/schemas/resource-metadata.js.map +1 -1
- package/dist/schemas/validation-result.d.ts +36 -57
- package/dist/schemas/validation-result.d.ts.map +1 -1
- package/dist/schemas/validation-result.js +5 -27
- package/dist/schemas/validation-result.js.map +1 -1
- package/dist/types/resources.d.ts +1 -1
- package/dist/types/resources.d.ts.map +1 -1
- package/dist/types/resources.js.map +1 -1
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +14 -0
- package/dist/utils.js.map +1 -1
- package/package.json +4 -3
- package/src/frontmatter-link-validator.ts +28 -30
- package/src/frontmatter-validator.ts +19 -16
- package/src/html-link-parser.ts +140 -0
- package/src/html-transform.ts +157 -0
- package/src/index.ts +10 -1
- package/src/link-parser.ts +60 -11
- package/src/link-validator.ts +175 -145
- package/src/multi-schema-validator.ts +10 -8
- package/src/resource-registry.ts +205 -72
- package/src/schemas/link-auth.ts +146 -0
- package/src/schemas/project-config.ts +76 -0
- package/src/schemas/resource-metadata.ts +17 -1
- package/src/schemas/validation-result.ts +5 -29
- package/src/types/resources.ts +2 -1
- package/src/utils.ts +15 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schema for `resources.linkAuth` config.
|
|
3
|
+
*
|
|
4
|
+
* Validates the shape of an adopter's linkAuth configuration: providers
|
|
5
|
+
* (each either a `use: <macro>` reference or a full inline provider) plus
|
|
6
|
+
* an optional cache config. Strict — typos in provider field names are
|
|
7
|
+
* errors, per Postel's law ("writing our output → conservative").
|
|
8
|
+
*
|
|
9
|
+
* Provider entries accept EITHER:
|
|
10
|
+
* - `{ use: <name>, ...overrides }` — reference a shipped macro by name;
|
|
11
|
+
* override fields are deep-merged on top at expansion time. Overrides
|
|
12
|
+
* are NOT strictly typed at this layer because they must match the
|
|
13
|
+
* macro's shape, which we cannot see until expansion. A typo in an
|
|
14
|
+
* override silently no-ops; the full provider shape is validated
|
|
15
|
+
* after expansion (slice 2 wires that).
|
|
16
|
+
* - A full inline `{ match, rewrite, auth, token, check }` — every field
|
|
17
|
+
* required, every nested object strict.
|
|
18
|
+
*
|
|
19
|
+
* Mirrors the runtime types in `@vibe-agent-toolkit/utils`'s `link-auth/`
|
|
20
|
+
* module. Keep these aligned: a config that parses here must satisfy the
|
|
21
|
+
* `Provider` / `LinkAuthConfig` interfaces over there.
|
|
22
|
+
*
|
|
23
|
+
* Per design issue #113 §4 (vocabulary) and §5 (macros).
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { z } from 'zod';
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Leaf types
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
export const ProviderMatchSchema = z
|
|
33
|
+
.object({
|
|
34
|
+
host: z.string().min(1).describe('Glob matched against URL hostname'),
|
|
35
|
+
excludeHost: z
|
|
36
|
+
.array(z.string().min(1))
|
|
37
|
+
.optional()
|
|
38
|
+
.describe('Globs that, if any match the hostname, exclude this provider'),
|
|
39
|
+
})
|
|
40
|
+
.strict()
|
|
41
|
+
.describe('Provider selection — match.host + optional excludeHost globs');
|
|
42
|
+
|
|
43
|
+
export const RewriteRuleSchema = z
|
|
44
|
+
.object({
|
|
45
|
+
when: z.string().min(1).describe('Regex source (RFC-style, JavaScript-compatible) matched against the URL'),
|
|
46
|
+
vars: z
|
|
47
|
+
.record(z.string(), z.string())
|
|
48
|
+
.optional()
|
|
49
|
+
.describe('Computed variables, each a template that references captures from `when`'),
|
|
50
|
+
to: z.string().min(1).describe('URL template — interpolates ${capture} and ${var}'),
|
|
51
|
+
})
|
|
52
|
+
.strict()
|
|
53
|
+
.describe('A single rewrite rule (one entry in a provider\'s ordered rewrite list)');
|
|
54
|
+
|
|
55
|
+
export const ProviderAuthSchema = z
|
|
56
|
+
.object({
|
|
57
|
+
headers: z
|
|
58
|
+
.record(z.string(), z.string())
|
|
59
|
+
.describe('Header name → value template. Values interpolate ${token} and any capture/var.'),
|
|
60
|
+
})
|
|
61
|
+
.strict()
|
|
62
|
+
.describe('Auth headers attached to the authenticated fetch');
|
|
63
|
+
|
|
64
|
+
export const TokenSourceSchema = z
|
|
65
|
+
.union([
|
|
66
|
+
z.object({ env: z.string().min(1) }).strict(),
|
|
67
|
+
z
|
|
68
|
+
.object({
|
|
69
|
+
command: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]),
|
|
70
|
+
})
|
|
71
|
+
.strict(),
|
|
72
|
+
])
|
|
73
|
+
.describe('A single token source — env var, or argv command (preferred), or convenience string');
|
|
74
|
+
|
|
75
|
+
export const ProviderCheckSchema = z
|
|
76
|
+
.object({
|
|
77
|
+
method: z.enum(['GET', 'HEAD']),
|
|
78
|
+
aliveStatus: z
|
|
79
|
+
.array(z.number().int().min(100).max(599))
|
|
80
|
+
.min(1)
|
|
81
|
+
.describe('HTTP status codes meaning the URL is alive (per host semantics)'),
|
|
82
|
+
notFoundMeaning: z
|
|
83
|
+
.enum(['ambiguous', 'dead'])
|
|
84
|
+
.describe(
|
|
85
|
+
'Per-host: does 404 mean "dead" (honest 404 host like Graph) or "ambiguous" (masking host like GitHub)?',
|
|
86
|
+
),
|
|
87
|
+
})
|
|
88
|
+
.strict()
|
|
89
|
+
.describe('Status-to-outcome classifier (consumed by the resources layer, not the pure engine)');
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Provider entry (inline OR macro reference)
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
const InlineProviderSchema = z
|
|
96
|
+
.object({
|
|
97
|
+
match: ProviderMatchSchema,
|
|
98
|
+
rewrite: z.array(RewriteRuleSchema).min(1).describe('Ordered rewrite rules — first matching wins'),
|
|
99
|
+
auth: ProviderAuthSchema,
|
|
100
|
+
token: z.array(TokenSourceSchema).describe('Ordered token sources — first non-empty wins'),
|
|
101
|
+
check: ProviderCheckSchema,
|
|
102
|
+
})
|
|
103
|
+
.strict();
|
|
104
|
+
|
|
105
|
+
const MacroProviderSchema = z
|
|
106
|
+
.object({
|
|
107
|
+
use: z.string().min(1).describe('Macro name (e.g. "github", "sharepoint")'),
|
|
108
|
+
})
|
|
109
|
+
.passthrough()
|
|
110
|
+
.describe(
|
|
111
|
+
'Reference a shipped macro by name. Override fields (match/rewrite/auth/token/check) deep-merge on top at expansion time.',
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
export const ProviderEntrySchema = z
|
|
115
|
+
.union([MacroProviderSchema, InlineProviderSchema])
|
|
116
|
+
.describe('A provider entry — either { use: <macro>, ...overrides } or a full inline provider');
|
|
117
|
+
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Top-level linkAuth config
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
export const LinkAuthCacheSchema = z
|
|
123
|
+
.object({
|
|
124
|
+
ttlMinutes: z
|
|
125
|
+
.number()
|
|
126
|
+
.int()
|
|
127
|
+
.positive()
|
|
128
|
+
.optional()
|
|
129
|
+
.describe('Content cache TTL in minutes (default 30 — used by slice 3 content-fetch)'),
|
|
130
|
+
})
|
|
131
|
+
.strict();
|
|
132
|
+
|
|
133
|
+
export const LinkAuthConfigSchema = z
|
|
134
|
+
.object({
|
|
135
|
+
cache: LinkAuthCacheSchema.optional(),
|
|
136
|
+
providers: z
|
|
137
|
+
.array(ProviderEntrySchema)
|
|
138
|
+
.describe('Ordered list of providers — first claiming-by-host wins'),
|
|
139
|
+
})
|
|
140
|
+
.strict()
|
|
141
|
+
.describe('`resources.linkAuth` — authenticated external link resolution config');
|
|
142
|
+
|
|
143
|
+
export type LinkAuthConfig = z.infer<typeof LinkAuthConfigSchema>;
|
|
144
|
+
export type ProviderEntry = z.infer<typeof ProviderEntrySchema>;
|
|
145
|
+
export type RewriteRule = z.infer<typeof RewriteRuleSchema>;
|
|
146
|
+
export type TokenSource = z.infer<typeof TokenSourceSchema>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ValidationConfigSchema } from '@vibe-agent-toolkit/agent-schema';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
|
+
import { LinkAuthConfigSchema } from './link-auth.js';
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* Official semver regex from https://semver.org/ (anchored).
|
|
6
8
|
*
|
|
@@ -96,6 +98,10 @@ export const ResourcesConfigSchema = z.object({
|
|
|
96
98
|
.describe('Global default exclude patterns (not used by collections in Phase 2)'),
|
|
97
99
|
collections: z.record(z.string(), CollectionConfigSchema).optional()
|
|
98
100
|
.describe('Named collections of resources'),
|
|
101
|
+
validation: ValidationConfigSchema.optional()
|
|
102
|
+
.describe('Validation framework config: severity overrides and per-code allow entries (applied inside ResourceRegistry.validate)'),
|
|
103
|
+
linkAuth: LinkAuthConfigSchema.optional()
|
|
104
|
+
.describe('Authenticated external link resolution config (issue #113 / link-auth engine)'),
|
|
99
105
|
}).describe('Resources section of project configuration');
|
|
100
106
|
|
|
101
107
|
export type ResourcesConfig = z.infer<typeof ResourcesConfigSchema>;
|
|
@@ -134,6 +140,72 @@ export const SkillFileEntrySchema = z.object({
|
|
|
134
140
|
|
|
135
141
|
export type SkillFileEntry = z.infer<typeof SkillFileEntrySchema>;
|
|
136
142
|
|
|
143
|
+
/**
|
|
144
|
+
* A typed "skill source" descriptor as it appears in vibe-agent-toolkit.config.yaml.
|
|
145
|
+
*
|
|
146
|
+
* This is the CONFIG representation. Task 13's staging maps it onto Plan 1's
|
|
147
|
+
* runtime `SkillSource` union before calling `resolveSkillSource`. Kept here so
|
|
148
|
+
* `configure`/`run` parse a single strict source of truth.
|
|
149
|
+
*/
|
|
150
|
+
export const SkillSourceDescriptorSchema = z.union([
|
|
151
|
+
z.object({ workspace: z.string().min(1) }).strict(),
|
|
152
|
+
z.object({ npm: z.string().min(1) }).strict(),
|
|
153
|
+
z.object({ url: z.string().min(1), sha256: z.string().min(1).optional() }).strict(),
|
|
154
|
+
z.object({ path: z.string().min(1) }).strict(),
|
|
155
|
+
z.object({ vendored: z.literal(true) }).strict(),
|
|
156
|
+
]).describe('Typed skill source: workspace | npm | url(+sha256) | path | vendored');
|
|
157
|
+
|
|
158
|
+
export type SkillSourceDescriptor = z.infer<typeof SkillSourceDescriptorSchema>;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Per-skill `test:` block for `vat skill test`. Strict — unknown keys are a
|
|
162
|
+
* config error (Postel: this is vat-produced/validated data, §schema strategy).
|
|
163
|
+
* Every field is optional; omitted knobs fall back to built-in defaults.
|
|
164
|
+
*/
|
|
165
|
+
export const TestConfigSchema = z.object({
|
|
166
|
+
model: z.string().min(1).optional()
|
|
167
|
+
.describe('Pinned model for reproducibility (default: a fixed model, not "whatever the caller has")'),
|
|
168
|
+
maxTurns: z.number().int().positive().optional()
|
|
169
|
+
.describe('Cap on experimenter turns'),
|
|
170
|
+
maxBudgetUsd: z.number().positive().optional()
|
|
171
|
+
.describe('Hard USD budget cap passed to the CLI'),
|
|
172
|
+
timeout: z.number().int().positive().optional()
|
|
173
|
+
.describe('Wall-clock timeout in seconds'),
|
|
174
|
+
stall: z.number().int().positive().optional()
|
|
175
|
+
.describe('Stall-watchdog seconds (kill on no stream output)'),
|
|
176
|
+
evals: z.string().min(1).optional()
|
|
177
|
+
.describe('Path to evals.json (relative to skill source)'),
|
|
178
|
+
experimenterPrompt: z.string().min(1).optional()
|
|
179
|
+
.describe('Path to an override experimenter prompt (must preserve §6c invariants)'),
|
|
180
|
+
auth: z.enum(['inherit', 'subscription', 'api-key', 'auto']).optional()
|
|
181
|
+
.describe('Auth-mechanism selection (default: inherit)'),
|
|
182
|
+
requireAuth: z.enum(['subscription', 'api-key']).optional()
|
|
183
|
+
.describe('Fail-fast guard: preflight exits 2 if effective mechanism is not this'),
|
|
184
|
+
baseline: z.boolean().optional()
|
|
185
|
+
.describe('Run the opt-in with/without A/B baseline (default: false)'),
|
|
186
|
+
skillCreator: SkillSourceDescriptorSchema.optional()
|
|
187
|
+
.describe('Source for skill-creator (default: { vendored: true })'),
|
|
188
|
+
with: z.array(SkillSourceDescriptorSchema).optional()
|
|
189
|
+
.describe('Declared-dependency skills/plugins to stage'),
|
|
190
|
+
optional: z.array(SkillSourceDescriptorSchema).optional()
|
|
191
|
+
.describe('Optional dependencies, absent by default'),
|
|
192
|
+
/**
|
|
193
|
+
* Shell command to run once, before staging, to generate build artifacts.
|
|
194
|
+
* Runs with cwd = config root (directory containing vibe-agent-toolkit.config.yaml).
|
|
195
|
+
* Useful when a skill references a generated file (e.g. `node scripts/report.mjs`)
|
|
196
|
+
* that is produced by a bundler step and not committed to source.
|
|
197
|
+
* A non-zero exit code aborts the run (preflight failure, exit 2).
|
|
198
|
+
*/
|
|
199
|
+
env: z.record(z.string(), z.string()).optional()
|
|
200
|
+
.describe('Feature B: explicit env var injections for the experimenter spawn. Values support ${fixturesDir}, ${stagedSkillDir}, ${harnessRoot}, ${resultsDir} interpolation (resolved at stage time). Protected names (PATH, auth, model, admin) cannot be overridden.'),
|
|
201
|
+
passEnv: z.array(z.string().min(1)).optional()
|
|
202
|
+
.describe('Feature A: names of host env vars to forward to the experimenter spawn if present. Protected names are ignored with a warning.'),
|
|
203
|
+
build: z.string().min(1).optional()
|
|
204
|
+
.describe('Shell command run once, before staging, to generate build artifacts (cwd = config root)'),
|
|
205
|
+
}).strict().describe('Per-skill vat skill test configuration');
|
|
206
|
+
|
|
207
|
+
export type TestConfig = z.infer<typeof TestConfigSchema>;
|
|
208
|
+
|
|
137
209
|
/**
|
|
138
210
|
* Skill packaging configuration.
|
|
139
211
|
*
|
|
@@ -153,10 +225,14 @@ export const SkillPackagingConfigSchema = z.object({
|
|
|
153
225
|
targets: z.array(z.enum(['claude-chat', 'claude-cowork', 'claude-code'])).optional()
|
|
154
226
|
.describe('Declared runtime targets for this skill. Suppresses non-applicable compat verdicts.'),
|
|
155
227
|
files: z.array(SkillFileEntrySchema).optional().describe('Explicit source→dest file mappings for build artifacts, unlinked files, or routing overrides'),
|
|
228
|
+
test: TestConfigSchema.optional()
|
|
229
|
+
.describe('vat skill test configuration for this skill'),
|
|
156
230
|
}).strict().describe('Skill packaging configuration');
|
|
157
231
|
|
|
158
232
|
export type SkillPackagingConfig = z.infer<typeof SkillPackagingConfigSchema>;
|
|
159
233
|
|
|
234
|
+
// NOTE: project-config has no generated JSON Schema generator (unlike packages with generate:schemas script); Zod schema is the tracked source of truth.
|
|
235
|
+
|
|
160
236
|
/**
|
|
161
237
|
* Skills discovery and packaging configuration.
|
|
162
238
|
*
|
|
@@ -6,6 +6,7 @@ import { SHA256Schema } from './checksum.js';
|
|
|
6
6
|
* Type of link found in markdown resources.
|
|
7
7
|
*
|
|
8
8
|
* - `local_file`: Link to a local file (relative or absolute path)
|
|
9
|
+
* - `local_directory`: Link to a local directory, e.g. a ref ending in `/`
|
|
9
10
|
* - `anchor`: Link to a heading anchor (e.g., #heading-slug)
|
|
10
11
|
* - `external`: HTTP/HTTPS URL to external resource
|
|
11
12
|
* - `email`: Mailto link
|
|
@@ -13,6 +14,7 @@ import { SHA256Schema } from './checksum.js';
|
|
|
13
14
|
*/
|
|
14
15
|
export const LinkTypeSchema = z.enum([
|
|
15
16
|
'local_file',
|
|
17
|
+
'local_directory',
|
|
16
18
|
'anchor',
|
|
17
19
|
'external',
|
|
18
20
|
'email',
|
|
@@ -36,6 +38,16 @@ export const LinkNodeTypeSchema = z.enum([
|
|
|
36
38
|
|
|
37
39
|
export type LinkNodeType = z.infer<typeof LinkNodeTypeSchema>;
|
|
38
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Zod schema for an HTML well-formedness diagnostic.
|
|
43
|
+
*/
|
|
44
|
+
export const HtmlParseErrorSchema = z.object({
|
|
45
|
+
message: z.string().describe('parse5 error code (e.g. "missing-end-tag")'),
|
|
46
|
+
line: z.number().int().positive().optional().describe('1-based source line, when known'),
|
|
47
|
+
}).describe('HTML well-formedness diagnostic');
|
|
48
|
+
|
|
49
|
+
export type HtmlParseError = z.infer<typeof HtmlParseErrorSchema>;
|
|
50
|
+
|
|
39
51
|
/**
|
|
40
52
|
* Represents a heading node in the document's table of contents.
|
|
41
53
|
*
|
|
@@ -96,6 +108,10 @@ export const ResourceMetadataSchema = z.object({
|
|
|
96
108
|
filePath: z.string().describe('Absolute path to the resource file'),
|
|
97
109
|
links: z.array(ResourceLinkSchema).describe('All links found in the resource'),
|
|
98
110
|
headings: z.array(HeadingNodeSchema).describe('Document table of contents (top-level headings only; children are nested)'),
|
|
111
|
+
anchors: z.array(z.string()).optional()
|
|
112
|
+
.describe('Fragment targets for anchor validation (HTML id/name attributes)'),
|
|
113
|
+
parseErrors: z.array(HtmlParseErrorSchema).optional()
|
|
114
|
+
.describe('HTML well-formedness diagnostics (populated for HTML resources only)'),
|
|
99
115
|
frontmatter: z.record(z.string(), z.unknown()).optional()
|
|
100
116
|
.describe('Parsed YAML frontmatter (if present in markdown file)'),
|
|
101
117
|
frontmatterError: z.string().optional()
|
|
@@ -106,6 +122,6 @@ export const ResourceMetadataSchema = z.object({
|
|
|
106
122
|
checksum: SHA256Schema.describe('SHA-256 checksum of file content'),
|
|
107
123
|
collections: z.array(z.string()).optional()
|
|
108
124
|
.describe('Collection names this resource belongs to (populated when using config-based discovery)'),
|
|
109
|
-
}).describe('Complete metadata for a markdown resource');
|
|
125
|
+
}).strict().describe('Complete metadata for a markdown resource');
|
|
110
126
|
|
|
111
127
|
export type ResourceMetadata = z.infer<typeof ResourceMetadataSchema>;
|
|
@@ -1,32 +1,7 @@
|
|
|
1
|
+
import { ValidationIssueSchema } from '@vibe-agent-toolkit/agent-schema';
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
* A single validation issue found during link validation.
|
|
5
|
-
*
|
|
6
|
-
* Issue types:
|
|
7
|
-
* - broken_file: Local file link points to non-existent file
|
|
8
|
-
* - broken_anchor: Anchor link points to non-existent heading
|
|
9
|
-
* - frontmatter_missing: Schema requires frontmatter, file has none
|
|
10
|
-
* - frontmatter_invalid_yaml: YAML syntax error in frontmatter
|
|
11
|
-
* - frontmatter_schema_error: Frontmatter fails JSON Schema validation
|
|
12
|
-
* - external_url_dead: External URL returned error status (4xx, 5xx)
|
|
13
|
-
* - external_url_timeout: External URL request timed out
|
|
14
|
-
* - external_url_error: External URL validation failed (DNS, network, etc.)
|
|
15
|
-
* - unknown_link: Unknown link type
|
|
16
|
-
*
|
|
17
|
-
* Includes details about what went wrong, where it occurred, and optionally
|
|
18
|
-
* how to fix it.
|
|
19
|
-
*/
|
|
20
|
-
export const ValidationIssueSchema = z.object({
|
|
21
|
-
resourcePath: z.string().describe('Absolute path to the resource containing the issue'),
|
|
22
|
-
line: z.number().int().positive().optional().describe('Line number where the issue occurs'),
|
|
23
|
-
type: z.string().describe('Issue type identifier (e.g., "broken_file", "broken_anchor", "frontmatter_schema_error", "unknown_link")'),
|
|
24
|
-
link: z.string().describe('The problematic link'),
|
|
25
|
-
message: z.string().describe('Human-readable description of the issue'),
|
|
26
|
-
suggestion: z.string().optional().describe('Optional suggestion for fixing the issue'),
|
|
27
|
-
}).describe('A single validation issue found during link validation');
|
|
28
|
-
|
|
29
|
-
export type ValidationIssue = z.infer<typeof ValidationIssueSchema>;
|
|
4
|
+
export { type ValidationIssue, ValidationIssueSchema } from '@vibe-agent-toolkit/agent-schema';
|
|
30
5
|
|
|
31
6
|
/**
|
|
32
7
|
* Complete results from validating a collection of resources.
|
|
@@ -38,9 +13,10 @@ export const ValidationResultSchema = z.object({
|
|
|
38
13
|
totalResources: z.number().int().nonnegative().describe('Total number of resources validated'),
|
|
39
14
|
totalLinks: z.number().int().nonnegative().describe('Total number of links found across all resources'),
|
|
40
15
|
linksByType: z.record(z.string(), z.number().int().nonnegative()).describe('Count of links by type (e.g., {"local_file": 10, "external": 5})'),
|
|
41
|
-
issues: z.array(ValidationIssueSchema).describe('
|
|
42
|
-
errorCount: z.number().int().nonnegative().describe('Number of issues
|
|
16
|
+
issues: z.array(ValidationIssueSchema).describe('Emitted validation issues (allow-filtered + severity-resolved; ignored issues dropped)'),
|
|
17
|
+
errorCount: z.number().int().nonnegative().describe('Number of emitted issues'),
|
|
43
18
|
passed: z.boolean().describe('True if validation succeeded (errorCount === 0)'),
|
|
19
|
+
hasErrors: z.boolean().describe('True when any emitted issue has resolved severity "error"'),
|
|
44
20
|
durationMs: z.number().nonnegative().describe('Validation duration in milliseconds'),
|
|
45
21
|
timestamp: z.date().describe('When validation was performed'),
|
|
46
22
|
}).describe('Complete results from validating a collection of resources');
|
package/src/types/resources.ts
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* with optional absolutePath for runtime operations.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { ValidationIssue } from '@vibe-agent-toolkit/agent-schema';
|
|
10
|
+
|
|
9
11
|
import type { SHA256 } from '../schemas/checksum.js';
|
|
10
|
-
import type { ValidationIssue } from '../schemas/validation-result.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Resource type discriminator for type-safe handling
|
package/src/utils.ts
CHANGED
|
@@ -9,6 +9,21 @@ import path from 'node:path';
|
|
|
9
9
|
import { toForwardSlash, safePath } from '@vibe-agent-toolkit/utils';
|
|
10
10
|
import picomatch from 'picomatch';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Compute a `ValidationIssue.location`: the (absolute) source file path made
|
|
14
|
+
* relative to the project root. When no project root is known, fall back to the
|
|
15
|
+
* source path forward-slashed so the location is still useful and stable.
|
|
16
|
+
*
|
|
17
|
+
* @param sourceFilePath - Absolute path to the file the issue was found in.
|
|
18
|
+
* @param projectRoot - Project root, or undefined when none could be determined.
|
|
19
|
+
* @returns Forward-slashed relative location (or the forward-slashed absolute path).
|
|
20
|
+
*/
|
|
21
|
+
export function issueLocation(sourceFilePath: string, projectRoot: string | undefined): string {
|
|
22
|
+
return projectRoot === undefined
|
|
23
|
+
? toForwardSlash(sourceFilePath)
|
|
24
|
+
: safePath.relative(projectRoot, sourceFilePath);
|
|
25
|
+
}
|
|
26
|
+
|
|
12
27
|
/**
|
|
13
28
|
* Check if a file path matches a glob pattern.
|
|
14
29
|
*
|