@jean.gnc/harness-kit 0.5.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/LICENSE +21 -0
- package/README.md +190 -0
- package/dist/agent/index.d.ts +3 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +2 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/schema.d.ts +20 -0
- package/dist/agent/schema.d.ts.map +1 -0
- package/dist/agent/schema.js +20 -0
- package/dist/agent/schema.js.map +1 -0
- package/dist/build.d.ts +9 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +18 -0
- package/dist/build.js.map +1 -0
- package/dist/check/index.d.ts +27 -0
- package/dist/check/index.d.ts.map +1 -0
- package/dist/check/index.js +160 -0
- package/dist/check/index.js.map +1 -0
- package/dist/check/kinds.d.ts +11 -0
- package/dist/check/kinds.d.ts.map +1 -0
- package/dist/check/kinds.js +65 -0
- package/dist/check/kinds.js.map +1 -0
- package/dist/check/suggest.d.ts +2 -0
- package/dist/check/suggest.d.ts.map +1 -0
- package/dist/check/suggest.js +37 -0
- package/dist/check/suggest.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +146 -0
- package/dist/cli.js.map +1 -0
- package/dist/command/index.d.ts +3 -0
- package/dist/command/index.d.ts.map +1 -0
- package/dist/command/index.js +2 -0
- package/dist/command/index.js.map +1 -0
- package/dist/command/schema.d.ts +23 -0
- package/dist/command/schema.d.ts.map +1 -0
- package/dist/command/schema.js +21 -0
- package/dist/command/schema.js.map +1 -0
- package/dist/compile/discovery.d.ts +2 -0
- package/dist/compile/discovery.d.ts.map +1 -0
- package/dist/compile/discovery.js +4 -0
- package/dist/compile/discovery.js.map +1 -0
- package/dist/compile/emit.d.ts +15 -0
- package/dist/compile/emit.d.ts.map +1 -0
- package/dist/compile/emit.js +123 -0
- package/dist/compile/emit.js.map +1 -0
- package/dist/compile/frontmatter.d.ts +7 -0
- package/dist/compile/frontmatter.d.ts.map +1 -0
- package/dist/compile/frontmatter.js +44 -0
- package/dist/compile/frontmatter.js.map +1 -0
- package/dist/compile/index.d.ts +9 -0
- package/dist/compile/index.d.ts.map +1 -0
- package/dist/compile/index.js +123 -0
- package/dist/compile/index.js.map +1 -0
- package/dist/compile/validators.d.ts +9 -0
- package/dist/compile/validators.d.ts.map +1 -0
- package/dist/compile/validators.js +112 -0
- package/dist/compile/validators.js.map +1 -0
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +2 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/zod.d.ts +3 -0
- package/dist/errors/zod.d.ts.map +1 -0
- package/dist/errors/zod.js +4 -0
- package/dist/errors/zod.js.map +1 -0
- package/dist/fs.d.ts +2 -0
- package/dist/fs.d.ts.map +1 -0
- package/dist/fs.js +11 -0
- package/dist/fs.js.map +1 -0
- package/dist/ids.d.ts +5 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +9 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/install/claude.d.ts +4 -0
- package/dist/install/claude.d.ts.map +1 -0
- package/dist/install/claude.js +37 -0
- package/dist/install/claude.js.map +1 -0
- package/dist/install/codex.d.ts +4 -0
- package/dist/install/codex.d.ts.map +1 -0
- package/dist/install/codex.js +29 -0
- package/dist/install/codex.js.map +1 -0
- package/dist/install/discovery.d.ts +21 -0
- package/dist/install/discovery.d.ts.map +1 -0
- package/dist/install/discovery.js +51 -0
- package/dist/install/discovery.js.map +1 -0
- package/dist/install/index.d.ts +28 -0
- package/dist/install/index.d.ts.map +1 -0
- package/dist/install/index.js +44 -0
- package/dist/install/index.js.map +1 -0
- package/dist/install/runner.d.ts +4 -0
- package/dist/install/runner.d.ts.map +1 -0
- package/dist/install/runner.js +15 -0
- package/dist/install/runner.js.map +1 -0
- package/dist/installed.d.ts +36 -0
- package/dist/installed.d.ts.map +1 -0
- package/dist/installed.js +155 -0
- package/dist/installed.js.map +1 -0
- package/dist/layout/index.d.ts +63 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +159 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/lint.d.ts +9 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +27 -0
- package/dist/lint.js.map +1 -0
- package/dist/marketplace/index.d.ts +3 -0
- package/dist/marketplace/index.d.ts.map +1 -0
- package/dist/marketplace/index.js +2 -0
- package/dist/marketplace/index.js.map +1 -0
- package/dist/marketplace/schema.d.ts +495 -0
- package/dist/marketplace/schema.d.ts.map +1 -0
- package/dist/marketplace/schema.js +92 -0
- package/dist/marketplace/schema.js.map +1 -0
- package/dist/parsing/frontmatter.d.ts +16 -0
- package/dist/parsing/frontmatter.d.ts.map +1 -0
- package/dist/parsing/frontmatter.js +45 -0
- package/dist/parsing/frontmatter.js.map +1 -0
- package/dist/parsing/index.d.ts +3 -0
- package/dist/parsing/index.d.ts.map +1 -0
- package/dist/parsing/index.js +2 -0
- package/dist/parsing/index.js.map +1 -0
- package/dist/placeholders/index.d.ts +5 -0
- package/dist/placeholders/index.d.ts.map +1 -0
- package/dist/placeholders/index.js +3 -0
- package/dist/placeholders/index.js.map +1 -0
- package/dist/placeholders/source-position.d.ts +6 -0
- package/dist/placeholders/source-position.d.ts.map +1 -0
- package/dist/placeholders/source-position.js +13 -0
- package/dist/placeholders/source-position.js.map +1 -0
- package/dist/placeholders/tokens.d.ts +26 -0
- package/dist/placeholders/tokens.d.ts.map +1 -0
- package/dist/placeholders/tokens.js +50 -0
- package/dist/placeholders/tokens.js.map +1 -0
- package/dist/plugin/index.d.ts +3 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +2 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/schema.d.ts +164 -0
- package/dist/plugin/schema.d.ts.map +1 -0
- package/dist/plugin/schema.js +61 -0
- package/dist/plugin/schema.js.map +1 -0
- package/dist/readme/index.d.ts +24 -0
- package/dist/readme/index.d.ts.map +1 -0
- package/dist/readme/index.js +119 -0
- package/dist/readme/index.js.map +1 -0
- package/dist/result.d.ts +10 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +7 -0
- package/dist/result.js.map +1 -0
- package/dist/skill/includes.d.ts +29 -0
- package/dist/skill/includes.d.ts.map +1 -0
- package/dist/skill/includes.js +81 -0
- package/dist/skill/includes.js.map +1 -0
- package/dist/skill/index.d.ts +8 -0
- package/dist/skill/index.d.ts.map +1 -0
- package/dist/skill/index.js +5 -0
- package/dist/skill/index.js.map +1 -0
- package/dist/skill/invariants.d.ts +3 -0
- package/dist/skill/invariants.d.ts.map +1 -0
- package/dist/skill/invariants.js +17 -0
- package/dist/skill/invariants.js.map +1 -0
- package/dist/skill/schema.d.ts +50 -0
- package/dist/skill/schema.d.ts.map +1 -0
- package/dist/skill/schema.js +36 -0
- package/dist/skill/schema.js.map +1 -0
- package/dist/skill/source.d.ts +48 -0
- package/dist/skill/source.d.ts.map +1 -0
- package/dist/skill/source.js +114 -0
- package/dist/skill/source.js.map +1 -0
- package/package.json +91 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jean Gonçalves
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Harness Kit
|
|
2
|
+
|
|
3
|
+
Typed framework for authoring Claude Code skills. A skill is a single `SKILL.md` file — frontmatter plus a Markdown body. The compiler validates references, expands placeholders, and emits the `SKILL.md` files Claude Code expects. A typed `SKILL.ts` form is also available when you want schema-checked metadata.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Node ≥ 20
|
|
8
|
+
- A package manager (pnpm, npm, yarn — pnpm is what this repo uses)
|
|
9
|
+
- The `claude` and/or `codex` CLIs on `$PATH` — only needed to run `harness-kit install` / `uninstall`
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
pnpm add @jean.gnc/harness-kit
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Authoring a skill
|
|
18
|
+
|
|
19
|
+
Lay your sources out as a marketplace of plugins, each containing skills:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
src/
|
|
23
|
+
.claude-plugin/
|
|
24
|
+
marketplace.json # marketplace metadata, read by `install`
|
|
25
|
+
plugins/
|
|
26
|
+
<plugin>/
|
|
27
|
+
.claude-plugin/plugin.json # claude target manifest
|
|
28
|
+
.codex-plugin/plugin.json # codex target manifest (optional)
|
|
29
|
+
skills/
|
|
30
|
+
<skill>/
|
|
31
|
+
SKILL.md
|
|
32
|
+
<companion>.md # optional
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Skills are auto-discovered by walking `<srcRoot>/plugins/<plugin>/skills/<name>/SKILL.md`. The `name` field in frontmatter must match the skill's folder name.
|
|
36
|
+
|
|
37
|
+
```md
|
|
38
|
+
<!-- SKILL.md -->
|
|
39
|
+
---
|
|
40
|
+
name: my-skill
|
|
41
|
+
description: What the skill does — single line.
|
|
42
|
+
companions:
|
|
43
|
+
- file: details.md
|
|
44
|
+
summary: Deeper notes.
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
# My Skill
|
|
48
|
+
|
|
49
|
+
For type safety conventions, see {{skill:dev-tools:typescript}}.
|
|
50
|
+
For TDD discipline, see {{ext:superpowers:test-driven-development}}.
|
|
51
|
+
For details, see {{ref:details.md}}.
|
|
52
|
+
|
|
53
|
+
{{companions}}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Compiles to:
|
|
57
|
+
|
|
58
|
+
```md
|
|
59
|
+
<!-- dist/plugins/<plugin>/skills/my-skill/SKILL.md -->
|
|
60
|
+
---
|
|
61
|
+
name: my-skill
|
|
62
|
+
description: What the skill does — single line.
|
|
63
|
+
companions:
|
|
64
|
+
- file: details.md
|
|
65
|
+
summary: Deeper notes.
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
# My Skill
|
|
69
|
+
|
|
70
|
+
For type safety conventions, see `dev-tools:typescript`.
|
|
71
|
+
For TDD discipline, see `superpowers:test-driven-development`.
|
|
72
|
+
For details, see `details.md`.
|
|
73
|
+
|
|
74
|
+
## Companion files (read on demand)
|
|
75
|
+
|
|
76
|
+
- `details.md` — Deeper notes.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Composing with includes
|
|
80
|
+
|
|
81
|
+
Use `{{include:./fragment.md}}` to inline another Markdown file verbatim into the body. Includes expand recursively (an included file may itself contain `{{include:...}}`), and any other placeholders inside the inlined content are resolved against the **host skill**, not the include source.
|
|
82
|
+
|
|
83
|
+
Constraints:
|
|
84
|
+
|
|
85
|
+
- Path must be relative and stay inside the skill directory.
|
|
86
|
+
- Target must end in `.md`.
|
|
87
|
+
- Cycles are detected and fail the build.
|
|
88
|
+
- Included files are not copied into `dist/` and are not flagged as undeclared companions.
|
|
89
|
+
|
|
90
|
+
### Authoring with TypeScript (alternative)
|
|
91
|
+
|
|
92
|
+
If you prefer typed metadata, use `SKILL.ts` + sibling `body.md` instead of a single `SKILL.md`:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
// SKILL.ts
|
|
96
|
+
import { defineSkill } from "@jean.gnc/harness-kit";
|
|
97
|
+
|
|
98
|
+
export default defineSkill({
|
|
99
|
+
name: "my-skill",
|
|
100
|
+
description: "What the skill does — single line.",
|
|
101
|
+
companions: [{ file: "details.md", summary: "Deeper notes." }],
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
```md
|
|
106
|
+
<!-- body.md -->
|
|
107
|
+
# My Skill
|
|
108
|
+
|
|
109
|
+
For type safety conventions, see {{skill:dev-tools:typescript}}.
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
A skill folder must contain exactly one of `SKILL.md` or `SKILL.ts`. Both forms run through the same placeholder pipeline and produce identical `dist/` output.
|
|
113
|
+
|
|
114
|
+
## Building
|
|
115
|
+
|
|
116
|
+
The package ships a `harness-kit` CLI bin:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
harness-kit build # compile typed sources to dist/
|
|
120
|
+
harness-kit lint # lint compiled markdown under dist/ with default rules
|
|
121
|
+
harness-kit check # validate {{ext:...}} refs against installed plugins
|
|
122
|
+
harness-kit install # install dist/ plugins into Claude + Codex
|
|
123
|
+
harness-kit uninstall # remove them
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
In your `package.json`:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"scripts": {
|
|
131
|
+
"build": "harness-kit build",
|
|
132
|
+
"lint": "harness-kit build && harness-kit lint",
|
|
133
|
+
"install:plugins": "harness-kit install",
|
|
134
|
+
"uninstall:plugins": "harness-kit uninstall"
|
|
135
|
+
},
|
|
136
|
+
"dependencies": {
|
|
137
|
+
"@jean.gnc/harness-kit": "latest"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`build` defaults: `./src` → `./dist`. Override with `--src` and `--out`.
|
|
143
|
+
|
|
144
|
+
`lint` defaults: `./dist`. Runs `markdownlint-cli2` against `plugins/**/*.md` with harness-kit's bundled rules — `MD013` (line length), `MD041` (first-line h1), and `MD033` (inline HTML) disabled; `MD024` scoped to `siblings_only`; `MD031` allows omitting blank lines around fences inside list items. Override with `--out`.
|
|
145
|
+
|
|
146
|
+
`install` / `uninstall` defaults: reads `./dist`, targets both Claude and Codex. Filter with `--targets claude` or `--targets codex`. The marketplace name is read from `./dist/.claude-plugin/marketplace.json`, and the `claude` / `codex` CLIs must be on `$PATH`.
|
|
147
|
+
|
|
148
|
+
For programmatic use:
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
import {
|
|
152
|
+
build,
|
|
153
|
+
lint,
|
|
154
|
+
install,
|
|
155
|
+
uninstall,
|
|
156
|
+
compile,
|
|
157
|
+
defineSkill,
|
|
158
|
+
parsePlaceholders,
|
|
159
|
+
substitute,
|
|
160
|
+
checkCompanionFiles,
|
|
161
|
+
} from "@jean.gnc/harness-kit";
|
|
162
|
+
|
|
163
|
+
await build({
|
|
164
|
+
srcRoot: "./src",
|
|
165
|
+
outRoot: "./dist",
|
|
166
|
+
bodyInvariants: [
|
|
167
|
+
/* (body) => string[] — extra checks to run on every skill body */
|
|
168
|
+
],
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
await install({ targets: ["claude", "codex"] });
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`bodyInvariants` are consumer-supplied predicates of type `(body: string) => string[]`. Each runs on every skill body (after `{{include:...}}` expansion, before placeholder substitution) during compile; any returned strings are reported as invariant violations and fail the build.
|
|
175
|
+
|
|
176
|
+
## Placeholder reference
|
|
177
|
+
|
|
178
|
+
Local skills are auto-discovered by walking `<srcRoot>/plugins/<plugin>/skills/<name>/`. Use `{{skill:...}}` for local references (build fails on typos) and `{{ext:...}}` for cross-plugin references (rendered as-is, no validation).
|
|
179
|
+
|
|
180
|
+
| Placeholder | Renders to | Validation |
|
|
181
|
+
| --- | --- | --- |
|
|
182
|
+
| `{{skill:<plugin>:<name>}}` | `` `<plugin>:<name>` `` | Must be a discovered local skill |
|
|
183
|
+
| `{{ext:<plugin>:<skill>}}` | `` `<plugin>:<skill>` `` | None — opaque external reference |
|
|
184
|
+
| `{{ref:<relative-path>}}` | `` `<relative-path>` `` | Must be a file under the skill directory |
|
|
185
|
+
| `{{include:<relative-path.md>}}` | Inlined content of the target file | Must be a `.md` file inside the skill, no cycles |
|
|
186
|
+
| `{{companions}}` | Companion files section | Required iff companions are declared |
|
|
187
|
+
|
|
188
|
+
## Contributing
|
|
189
|
+
|
|
190
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const AgentSchema: z.ZodObject<{
|
|
3
|
+
name: z.ZodString;
|
|
4
|
+
description: z.ZodEffects<z.ZodString, string, string>;
|
|
5
|
+
tools: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
6
|
+
model: z.ZodOptional<z.ZodString>;
|
|
7
|
+
}, "strict", z.ZodTypeAny, {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
tools?: string | string[] | undefined;
|
|
11
|
+
model?: string | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
tools?: string | string[] | undefined;
|
|
16
|
+
model?: string | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export type Agent = z.infer<typeof AgentSchema>;
|
|
19
|
+
export declare function defineAgent(agent: Agent): Agent;
|
|
20
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/agent/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;EAcb,CAAC;AAEZ,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE/C"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const AgentSchema = z
|
|
3
|
+
.object({
|
|
4
|
+
name: z
|
|
5
|
+
.string()
|
|
6
|
+
.min(1)
|
|
7
|
+
.regex(/^[a-z0-9-]+$/, "name must be lowercase kebab-case"),
|
|
8
|
+
description: z
|
|
9
|
+
.string()
|
|
10
|
+
.min(1)
|
|
11
|
+
.max(1024)
|
|
12
|
+
.refine((s) => !s.includes("\n"), "description cannot contain newlines"),
|
|
13
|
+
tools: z.union([z.string().min(1), z.array(z.string().min(1))]).optional(),
|
|
14
|
+
model: z.string().min(1).optional(),
|
|
15
|
+
})
|
|
16
|
+
.strict();
|
|
17
|
+
export function defineAgent(agent) {
|
|
18
|
+
return AgentSchema.parse(agent);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/agent/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC;KACzB,MAAM,CAAC;IACN,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,KAAK,CAAC,cAAc,EAAE,mCAAmC,CAAC;IAC7D,WAAW,EAAE,CAAC;SACX,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,IAAI,CAAC;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,qCAAqC,CAAC;IAC1E,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC1E,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACpC,CAAC;KACD,MAAM,EAAE,CAAC;AAIZ,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,OAAO,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC"}
|
package/dist/build.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BodyInvariant } from "./compile/index.js";
|
|
2
|
+
export interface BuildOptions {
|
|
3
|
+
readonly srcRoot?: string;
|
|
4
|
+
readonly outRoot?: string;
|
|
5
|
+
readonly bodyInvariants?: readonly BodyInvariant[];
|
|
6
|
+
readonly silent?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function build(options?: BuildOptions): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAarE"}
|
package/dist/build.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { rm } from "node:fs/promises";
|
|
2
|
+
import { resolve, join } from "node:path";
|
|
3
|
+
import { compile } from "./compile/index.js";
|
|
4
|
+
export async function build(options = {}) {
|
|
5
|
+
const srcRoot = resolve(options.srcRoot ?? "./src");
|
|
6
|
+
const outRoot = resolve(options.outRoot ?? "./dist");
|
|
7
|
+
await rm(join(outRoot, "plugins"), { recursive: true, force: true });
|
|
8
|
+
await rm(join(outRoot, ".claude-plugin"), { recursive: true, force: true });
|
|
9
|
+
await compile({
|
|
10
|
+
srcRoot,
|
|
11
|
+
outRoot,
|
|
12
|
+
...(options.bodyInvariants ? { bodyInvariants: options.bodyInvariants } : {}),
|
|
13
|
+
});
|
|
14
|
+
if (!options.silent) {
|
|
15
|
+
console.log(`compiled → ${outRoot}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAU7C,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,UAAwB,EAAE;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,MAAM,OAAO,CAAC;QACZ,OAAO;QACP,OAAO;QACP,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9E,CAAC,CAAC;IACH,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type PluginSource } from "../installed.js";
|
|
2
|
+
export type CheckMode = "local" | "installed" | "all";
|
|
3
|
+
export interface CheckOptions {
|
|
4
|
+
readonly srcRoot: string;
|
|
5
|
+
readonly mode?: CheckMode;
|
|
6
|
+
readonly sources?: readonly PluginSource[];
|
|
7
|
+
}
|
|
8
|
+
export type ExtViolationKind = "malformed" | "unresolved";
|
|
9
|
+
export interface ExtViolation {
|
|
10
|
+
readonly kind: ExtViolationKind;
|
|
11
|
+
readonly token: string;
|
|
12
|
+
readonly file: string;
|
|
13
|
+
readonly line: number;
|
|
14
|
+
readonly column: number;
|
|
15
|
+
readonly message: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SourceSummary {
|
|
18
|
+
readonly source: string;
|
|
19
|
+
readonly skillCount: number;
|
|
20
|
+
}
|
|
21
|
+
export interface CheckResult {
|
|
22
|
+
readonly violations: readonly ExtViolation[];
|
|
23
|
+
readonly checkedFiles: number;
|
|
24
|
+
readonly indexedSources: readonly SourceSummary[];
|
|
25
|
+
}
|
|
26
|
+
export declare function check(options: CheckOptions): Promise<CheckResult>;
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/check/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAKzB,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,WAAW,GAAG,KAAK,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CAC5C;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,YAAY,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,CAAC;CACnD;AASD,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAsCvE"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { pathExists } from "../fs.js";
|
|
4
|
+
import { FQ_ID } from "../ids.js";
|
|
5
|
+
import { offsetToLineCol, parsePlaceholders } from "../placeholders/index.js";
|
|
6
|
+
import { findSkillFile, formatLoadSkillError, loadSkill } from "../skill/index.js";
|
|
7
|
+
import { collectLocalIds, loadLayout, } from "../layout/index.js";
|
|
8
|
+
import { defaultSources, discoverInstalled, indexInstalled, } from "../installed.js";
|
|
9
|
+
import { installedKindConfigs, localKindConfigs } from "./kinds.js";
|
|
10
|
+
import { closestMatch } from "./suggest.js";
|
|
11
|
+
export async function check(options) {
|
|
12
|
+
const mode = options.mode ?? "installed";
|
|
13
|
+
const kinds = new Map();
|
|
14
|
+
let indexedSources = [];
|
|
15
|
+
let localAdapter = null;
|
|
16
|
+
if (mode === "installed" || mode === "all") {
|
|
17
|
+
const sources = options.sources ?? defaultSources();
|
|
18
|
+
const artifacts = await discoverInstalled(sources);
|
|
19
|
+
const index = indexInstalled(artifacts);
|
|
20
|
+
indexedSources = sources.map((s) => ({
|
|
21
|
+
source: s.name,
|
|
22
|
+
skillCount: artifacts.skills.filter((i) => i.source === s.name).length,
|
|
23
|
+
}));
|
|
24
|
+
for (const [prefix, cfg] of installedKindConfigs(index))
|
|
25
|
+
kinds.set(prefix, cfg);
|
|
26
|
+
}
|
|
27
|
+
if (mode === "local" || mode === "all") {
|
|
28
|
+
const loaded = await loadLayout(options.srcRoot);
|
|
29
|
+
if (!loaded.ok)
|
|
30
|
+
throw new Error(`failed to load layout: ${loaded.error.kind}`);
|
|
31
|
+
localAdapter = loaded.value;
|
|
32
|
+
const ids = await collectLocalIds(localAdapter);
|
|
33
|
+
for (const [prefix, cfg] of localKindConfigs(ids))
|
|
34
|
+
kinds.set(prefix, cfg);
|
|
35
|
+
}
|
|
36
|
+
const sources = await collectBodySources({
|
|
37
|
+
srcRoot: options.srcRoot,
|
|
38
|
+
mode,
|
|
39
|
+
adapter: localAdapter,
|
|
40
|
+
});
|
|
41
|
+
const violations = [];
|
|
42
|
+
for (const source of sources) {
|
|
43
|
+
for (const violation of validateBody(source, kinds)) {
|
|
44
|
+
violations.push(violation);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { violations, checkedFiles: sources.length, indexedSources };
|
|
48
|
+
}
|
|
49
|
+
async function collectBodySources(opts) {
|
|
50
|
+
const seen = new Set();
|
|
51
|
+
const out = [];
|
|
52
|
+
const push = async (filePath, body, bodyOffset) => {
|
|
53
|
+
if (seen.has(filePath))
|
|
54
|
+
return;
|
|
55
|
+
seen.add(filePath);
|
|
56
|
+
const fileText = await readFile(filePath, "utf8");
|
|
57
|
+
out.push({ body, bodyOffset, fileText, filePath });
|
|
58
|
+
};
|
|
59
|
+
if (opts.mode === "installed" || opts.mode === "all") {
|
|
60
|
+
for await (const skillDir of findSkillDirs(opts.srcRoot)) {
|
|
61
|
+
const loaded = await loadSkill(skillDir);
|
|
62
|
+
if (!loaded.ok) {
|
|
63
|
+
throw new Error(`failed to load skill at ${skillDir}:\n - ${formatLoadSkillError(loaded.error).join("\n - ")}`);
|
|
64
|
+
}
|
|
65
|
+
await push(loaded.value.bodyFilePath, loaded.value.body, loaded.value.bodyOffset);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if ((opts.mode === "local" || opts.mode === "all") && opts.adapter) {
|
|
69
|
+
for (const plugin of opts.adapter.plugins) {
|
|
70
|
+
for (const file of await collectPluginBodies(plugin)) {
|
|
71
|
+
await push(file.filePath, file.body, file.bodyOffset);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
async function collectPluginBodies(plugin) {
|
|
78
|
+
const out = [];
|
|
79
|
+
if (await pathExists(plugin.skillsDir)) {
|
|
80
|
+
for (const entry of await readdir(plugin.skillsDir, { withFileTypes: true })) {
|
|
81
|
+
if (!entry.isDirectory())
|
|
82
|
+
continue;
|
|
83
|
+
const skillDir = join(plugin.skillsDir, entry.name);
|
|
84
|
+
const found = await findSkillFile(skillDir);
|
|
85
|
+
if (!found.ok || !found.value)
|
|
86
|
+
continue;
|
|
87
|
+
const loaded = await loadSkill(skillDir);
|
|
88
|
+
if (!loaded.ok) {
|
|
89
|
+
throw new Error(`failed to load skill at ${skillDir}:\n - ${formatLoadSkillError(loaded.error).join("\n - ")}`);
|
|
90
|
+
}
|
|
91
|
+
out.push({
|
|
92
|
+
filePath: loaded.value.bodyFilePath,
|
|
93
|
+
body: loaded.value.body,
|
|
94
|
+
bodyOffset: loaded.value.bodyOffset,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
for (const dir of [plugin.commandsDir, plugin.agentsDir]) {
|
|
99
|
+
if (!(await pathExists(dir)))
|
|
100
|
+
continue;
|
|
101
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
102
|
+
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
103
|
+
continue;
|
|
104
|
+
const filePath = join(dir, entry.name);
|
|
105
|
+
const body = await readFile(filePath, "utf8");
|
|
106
|
+
out.push({ filePath, body, bodyOffset: 0 });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
function validateBody(source, kinds) {
|
|
112
|
+
const violations = [];
|
|
113
|
+
for (const token of parsePlaceholders(source.body)) {
|
|
114
|
+
const kind = kinds.get(token.prefix);
|
|
115
|
+
if (!kind)
|
|
116
|
+
continue;
|
|
117
|
+
const { line, column } = offsetToLineCol(source.fileText, source.bodyOffset + token.start);
|
|
118
|
+
const at = { token: token.raw, file: source.filePath, line, column };
|
|
119
|
+
if (token.value === null || !FQ_ID.test(token.value)) {
|
|
120
|
+
violations.push({ ...at, kind: "malformed", message: kind.malformedHint });
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (kind.haystack.has(token.value))
|
|
124
|
+
continue;
|
|
125
|
+
const suggestion = closestMatch(token.value, [...kind.haystack]);
|
|
126
|
+
violations.push({
|
|
127
|
+
...at,
|
|
128
|
+
kind: "unresolved",
|
|
129
|
+
message: suggestion
|
|
130
|
+
? `\`${token.value}\` ${kind.noun} ${kind.missingHint} (did you mean \`${suggestion}\`?)`
|
|
131
|
+
: `\`${token.value}\` ${kind.noun} ${kind.missingHint}`,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return violations;
|
|
135
|
+
}
|
|
136
|
+
async function* findSkillDirs(srcRoot) {
|
|
137
|
+
if (!(await pathExists(srcRoot)))
|
|
138
|
+
return;
|
|
139
|
+
for await (const dir of walkDirs(srcRoot)) {
|
|
140
|
+
const found = await findSkillFile(dir);
|
|
141
|
+
if (!found.ok || found.value)
|
|
142
|
+
yield dir;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async function* walkDirs(dir) {
|
|
146
|
+
yield dir;
|
|
147
|
+
let entries;
|
|
148
|
+
try {
|
|
149
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
for (const entry of entries) {
|
|
155
|
+
if (entry.isDirectory() && !entry.isSymbolicLink()) {
|
|
156
|
+
yield* walkDirs(join(dir, entry.name));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/check/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { InstalledIndex } from "../installed.js";
|
|
2
|
+
import type { LocalIds } from "../layout/index.js";
|
|
3
|
+
export interface KindConfig {
|
|
4
|
+
readonly noun: string;
|
|
5
|
+
readonly missingHint: string;
|
|
6
|
+
readonly malformedHint: string;
|
|
7
|
+
readonly haystack: ReadonlySet<string>;
|
|
8
|
+
}
|
|
9
|
+
export declare function installedKindConfigs(index: InstalledIndex): ReadonlyMap<string, KindConfig>;
|
|
10
|
+
export declare function localKindConfigs(ids: LocalIds): ReadonlyMap<string, KindConfig>;
|
|
11
|
+
//# sourceMappingURL=kinds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kinds.d.ts","sourceRoot":"","sources":["../../src/check/kinds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACxC;AAKD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,GAAG,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CA8B3F;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CA8B/E"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const INSTALLED_MISSING = "not installed";
|
|
2
|
+
const LOCAL_MISSING = "not found in this marketplace";
|
|
3
|
+
export function installedKindConfigs(index) {
|
|
4
|
+
return new Map([
|
|
5
|
+
[
|
|
6
|
+
"ext",
|
|
7
|
+
{
|
|
8
|
+
noun: "skill",
|
|
9
|
+
missingHint: INSTALLED_MISSING,
|
|
10
|
+
malformedHint: "expected `{{ext:<plugin>:<skill>}}` in kebab-case",
|
|
11
|
+
haystack: new Set(index.skills.keys()),
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
[
|
|
15
|
+
"ext-command",
|
|
16
|
+
{
|
|
17
|
+
noun: "command",
|
|
18
|
+
missingHint: INSTALLED_MISSING,
|
|
19
|
+
malformedHint: "expected `{{ext-command:<plugin>:<command>}}` in kebab-case",
|
|
20
|
+
haystack: new Set(index.commands.keys()),
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
[
|
|
24
|
+
"ext-agent",
|
|
25
|
+
{
|
|
26
|
+
noun: "agent",
|
|
27
|
+
missingHint: INSTALLED_MISSING,
|
|
28
|
+
malformedHint: "expected `{{ext-agent:<plugin>:<agent>}}` in kebab-case",
|
|
29
|
+
haystack: new Set(index.agents.keys()),
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
]);
|
|
33
|
+
}
|
|
34
|
+
export function localKindConfigs(ids) {
|
|
35
|
+
return new Map([
|
|
36
|
+
[
|
|
37
|
+
"skill",
|
|
38
|
+
{
|
|
39
|
+
noun: "skill",
|
|
40
|
+
missingHint: LOCAL_MISSING,
|
|
41
|
+
malformedHint: "expected `{{skill:<plugin>:<skill>}}` in kebab-case",
|
|
42
|
+
haystack: ids.skills,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
[
|
|
46
|
+
"command",
|
|
47
|
+
{
|
|
48
|
+
noun: "command",
|
|
49
|
+
missingHint: LOCAL_MISSING,
|
|
50
|
+
malformedHint: "expected `{{command:<plugin>:<command>}}` in kebab-case",
|
|
51
|
+
haystack: ids.commands,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
[
|
|
55
|
+
"agent",
|
|
56
|
+
{
|
|
57
|
+
noun: "agent",
|
|
58
|
+
missingHint: LOCAL_MISSING,
|
|
59
|
+
malformedHint: "expected `{{agent:<plugin>:<agent>}}` in kebab-case",
|
|
60
|
+
haystack: ids.agents,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=kinds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kinds.js","sourceRoot":"","sources":["../../src/check/kinds.ts"],"names":[],"mappings":"AAUA,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAC1C,MAAM,aAAa,GAAG,+BAA+B,CAAC;AAEtD,MAAM,UAAU,oBAAoB,CAAC,KAAqB;IACxD,OAAO,IAAI,GAAG,CAAqB;QACjC;YACE,KAAK;YACL;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,iBAAiB;gBAC9B,aAAa,EAAE,mDAAmD;gBAClE,QAAQ,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;aACvC;SACF;QACD;YACE,aAAa;YACb;gBACE,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE,iBAAiB;gBAC9B,aAAa,EAAE,6DAA6D;gBAC5E,QAAQ,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;aACzC;SACF;QACD;YACE,WAAW;YACX;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,iBAAiB;gBAC9B,aAAa,EAAE,yDAAyD;gBACxE,QAAQ,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;aACvC;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAa;IAC5C,OAAO,IAAI,GAAG,CAAqB;QACjC;YACE,OAAO;YACP;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,aAAa;gBAC1B,aAAa,EAAE,qDAAqD;gBACpE,QAAQ,EAAE,GAAG,CAAC,MAAM;aACrB;SACF;QACD;YACE,SAAS;YACT;gBACE,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE,aAAa;gBAC1B,aAAa,EAAE,yDAAyD;gBACxE,QAAQ,EAAE,GAAG,CAAC,QAAQ;aACvB;SACF;QACD;YACE,OAAO;YACP;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,aAAa;gBAC1B,aAAa,EAAE,qDAAqD;gBACpE,QAAQ,EAAE,GAAG,CAAC,MAAM;aACrB;SACF;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../src/check/suggest.ts"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAYvF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const SUGGESTION_DISTANCE_FLOOR = 2;
|
|
2
|
+
const SUGGESTION_DISTANCE_DIVISOR = 3;
|
|
3
|
+
export function closestMatch(needle, haystack) {
|
|
4
|
+
let best = null;
|
|
5
|
+
const threshold = Math.max(SUGGESTION_DISTANCE_FLOOR, Math.floor(needle.length / SUGGESTION_DISTANCE_DIVISOR));
|
|
6
|
+
for (const candidate of haystack) {
|
|
7
|
+
const distance = levenshtein(needle, candidate);
|
|
8
|
+
if (distance > threshold)
|
|
9
|
+
continue;
|
|
10
|
+
if (!best || distance < best.distance)
|
|
11
|
+
best = { value: candidate, distance };
|
|
12
|
+
}
|
|
13
|
+
return best?.value ?? null;
|
|
14
|
+
}
|
|
15
|
+
function levenshtein(a, b) {
|
|
16
|
+
if (a === b)
|
|
17
|
+
return 0;
|
|
18
|
+
if (a.length === 0)
|
|
19
|
+
return b.length;
|
|
20
|
+
if (b.length === 0)
|
|
21
|
+
return a.length;
|
|
22
|
+
let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
23
|
+
let curr = new Array(b.length + 1).fill(0);
|
|
24
|
+
for (let i = 1; i <= a.length; i += 1) {
|
|
25
|
+
curr[0] = i;
|
|
26
|
+
for (let j = 1; j <= b.length; j += 1) {
|
|
27
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
28
|
+
const deletion = (curr[j - 1] ?? 0) + 1;
|
|
29
|
+
const insertion = (prev[j] ?? 0) + 1;
|
|
30
|
+
const substitution = (prev[j - 1] ?? 0) + cost;
|
|
31
|
+
curr[j] = Math.min(deletion, insertion, substitution);
|
|
32
|
+
}
|
|
33
|
+
[prev, curr] = [curr, prev];
|
|
34
|
+
}
|
|
35
|
+
return prev[b.length] ?? 0;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=suggest.js.map
|