capman 0.1.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/CONTRIBUTING.md +108 -0
- package/README.md +208 -0
- package/bin/capman.js +192 -0
- package/dist/generator.d.ts +8 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +224 -0
- package/dist/generator.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +22 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +53 -0
- package/dist/logger.js.map +1 -0
- package/dist/matcher.d.ts +7 -0
- package/dist/matcher.d.ts.map +1 -0
- package/dist/matcher.js +194 -0
- package/dist/matcher.js.map +1 -0
- package/dist/resolver.d.ts +19 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +164 -0
- package/dist/resolver.js.map +1 -0
- package/dist/schema.d.ts +741 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +94 -0
- package/dist/schema.js.map +1 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/package.json +43 -0
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Contributing to capman
|
|
2
|
+
|
|
3
|
+
First off — thank you for taking the time to contribute.
|
|
4
|
+
capman is an open source project and welcomes contributions of all kinds.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## What we're building
|
|
9
|
+
|
|
10
|
+
capman is a developer tool that lets AI agents interact with applications
|
|
11
|
+
efficiently — without navigating the UI. If you're here, you probably
|
|
12
|
+
have an idea to make that better. Let's hear it.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Ways to contribute
|
|
17
|
+
|
|
18
|
+
- **Bug reports** — something broke? Open an issue with steps to reproduce
|
|
19
|
+
- **Feature suggestions** — have an idea? Open an issue and describe it
|
|
20
|
+
- **Code contributions** — fix a bug or build a feature via pull request
|
|
21
|
+
- **New test configs** — tested capman against a real app? Add it to test/
|
|
22
|
+
- **Documentation** — spotted something unclear in the README? Fix it
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Getting started locally
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Clone the repo
|
|
30
|
+
git clone https://github.com/your-username/capman.git
|
|
31
|
+
cd capman
|
|
32
|
+
|
|
33
|
+
# Install dependencies
|
|
34
|
+
npm install
|
|
35
|
+
|
|
36
|
+
# Build
|
|
37
|
+
npm run build
|
|
38
|
+
|
|
39
|
+
# Run the example
|
|
40
|
+
npm run example
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Project structure
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
src/
|
|
49
|
+
types.ts — all TypeScript types (the contract)
|
|
50
|
+
generator.ts — generate(), validate(), loadConfig()
|
|
51
|
+
matcher.ts — match() and matchWithLLM()
|
|
52
|
+
resolver.ts — resolve() for API, nav, and hybrid
|
|
53
|
+
index.ts — public SDK entry point + ask()
|
|
54
|
+
bin/
|
|
55
|
+
capman.js — CLI (init, generate, validate, inspect)
|
|
56
|
+
examples/
|
|
57
|
+
basic.ts — simple runnable example
|
|
58
|
+
test/
|
|
59
|
+
conduit.config.js — real world test config (Conduit app)
|
|
60
|
+
test-conduit.ts — keyword matcher tests
|
|
61
|
+
test-conduit-llm.ts — LLM matcher tests
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Before submitting a pull request
|
|
67
|
+
|
|
68
|
+
1. Run `npm run build` — make sure it compiles clean
|
|
69
|
+
2. Run `npx ts-node examples/basic.ts` — make sure the example works
|
|
70
|
+
3. If you changed matching logic, run `npx ts-node test/test-conduit.ts`
|
|
71
|
+
4. Keep pull requests focused — one thing per PR
|
|
72
|
+
5. Write clear commit messages — say what changed and why
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Adding a new test config
|
|
77
|
+
|
|
78
|
+
If you've tested capman against a real app, we'd love to include it.
|
|
79
|
+
|
|
80
|
+
1. Create `test/your-app.config.js`
|
|
81
|
+
2. Create `test/test-your-app.ts`
|
|
82
|
+
3. Open a pull request with both files
|
|
83
|
+
4. Include your test results in the PR description
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Reporting a bug
|
|
88
|
+
|
|
89
|
+
Open an issue and include:
|
|
90
|
+
- What you ran
|
|
91
|
+
- What you expected
|
|
92
|
+
- What actually happened
|
|
93
|
+
- Your Node.js version (`node --version`)
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Code style
|
|
98
|
+
|
|
99
|
+
- TypeScript everywhere in `src/`
|
|
100
|
+
- No external runtime dependencies in core src/
|
|
101
|
+
- Keep functions small and focused
|
|
102
|
+
- Add a comment if something isn't obvious
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Questions?
|
|
107
|
+
|
|
108
|
+
Open an issue — no question is too small.
|
package/README.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Capman — Capability Manifest Engine
|
|
2
|
+
|
|
3
|
+
Let AI agents interact with your app **without navigating the UI**.
|
|
4
|
+
|
|
5
|
+
Instead of an AI blindly clicking through screens to find information,
|
|
6
|
+
capman lets your app declare what it can do — and the AI uses that map
|
|
7
|
+
to get answers directly.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## The Problem
|
|
12
|
+
|
|
13
|
+
When an AI agent needs to answer "are there available seats for Friday?",
|
|
14
|
+
today it navigates your entire app like a tourist with no map:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
AI clicks → Home → Explore → Events → Category → Detail → Availability
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
That's slow, wasteful, and exposes parts of your app the AI shouldn't see.
|
|
21
|
+
|
|
22
|
+
## The Solution
|
|
23
|
+
|
|
24
|
+
Your app publishes a **capability manifest** — a machine-readable list of
|
|
25
|
+
everything it can do, what API to call, and what data scope is allowed.
|
|
26
|
+
|
|
27
|
+
The AI reads the manifest and goes directly to the answer.
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
User query → match capability → resolve via API or nav → done
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install capman
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
**1. Create a config file**
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npx capman init
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This creates a `capman.config.js` in your project. Edit it to define
|
|
52
|
+
your app's capabilities.
|
|
53
|
+
|
|
54
|
+
**2. Generate the manifest**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx capman generate
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This reads your config and outputs a `manifest.json`.
|
|
61
|
+
|
|
62
|
+
**3. Use the SDK in your AI agent**
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { match, resolve, readManifest } from 'capman'
|
|
66
|
+
|
|
67
|
+
const manifest = readManifest()
|
|
68
|
+
|
|
69
|
+
// Match a user query to a capability
|
|
70
|
+
const matchResult = match("show me my account details", manifest)
|
|
71
|
+
|
|
72
|
+
// Resolve it
|
|
73
|
+
const result = await resolve(matchResult, {}, {
|
|
74
|
+
baseUrl: 'https://api.your-app.com'
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
console.log(result.apiCalls) // [{ method: 'GET', url: '...' }]
|
|
78
|
+
console.log(result.navTarget) // '/dashboard/profile'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## CLI Commands
|
|
84
|
+
|
|
85
|
+
| Command | What it does |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `capman init` | Create a starter `capman.config.js` |
|
|
88
|
+
| `capman generate` | Generate `manifest.json` from config |
|
|
89
|
+
| `capman validate` | Validate your manifest for errors |
|
|
90
|
+
| `capman inspect` | Print all capabilities in the manifest |
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## SDK Reference
|
|
95
|
+
|
|
96
|
+
### `match(query, manifest)`
|
|
97
|
+
Matches a user query to the best capability using keyword scoring.
|
|
98
|
+
Returns a `MatchResult` with the capability, confidence score, and intent.
|
|
99
|
+
|
|
100
|
+
### `matchWithLLM(query, manifest, { llm })`
|
|
101
|
+
Same as `match()` but uses an LLM for higher accuracy on ambiguous queries.
|
|
102
|
+
Pass in any LLM function — works with Anthropic, OpenAI, or any local model.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
const result = await matchWithLLM("find me something", manifest, {
|
|
106
|
+
llm: async (prompt) => {
|
|
107
|
+
const res = await anthropic.messages.create({
|
|
108
|
+
model: 'claude-sonnet-4-20250514',
|
|
109
|
+
max_tokens: 500,
|
|
110
|
+
messages: [{ role: 'user', content: prompt }]
|
|
111
|
+
})
|
|
112
|
+
return res.content[0].text
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### `resolve(matchResult, params, options)`
|
|
118
|
+
Executes a matched capability via API call, navigation, or both.
|
|
119
|
+
|
|
120
|
+
### `ask(query, manifest, options)`
|
|
121
|
+
Convenience function — match + resolve in one call.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
const { match, resolution } = await ask("go to settings", manifest)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Capability Config
|
|
130
|
+
|
|
131
|
+
Each capability in your `capman.config.js` looks like this:
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
{
|
|
135
|
+
id: 'get_resource',
|
|
136
|
+
name: 'Get a resource',
|
|
137
|
+
description: 'Fetch a resource by ID or name.', // used for matching
|
|
138
|
+
examples: [ // improves accuracy
|
|
139
|
+
'Show me resource details',
|
|
140
|
+
'Find resource by ID',
|
|
141
|
+
],
|
|
142
|
+
params: [
|
|
143
|
+
{
|
|
144
|
+
name: 'resource_id',
|
|
145
|
+
description: 'The resource ID',
|
|
146
|
+
required: true,
|
|
147
|
+
source: 'user_query', // or 'session', 'context', 'static'
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
returns: ['resource', 'metadata'],
|
|
151
|
+
resolver: {
|
|
152
|
+
type: 'api', // 'api', 'nav', or 'hybrid'
|
|
153
|
+
endpoints: [
|
|
154
|
+
{ method: 'GET', path: '/resources/{resource_id}' }
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
privacy: {
|
|
158
|
+
level: 'public', // 'public', 'user_owned', or 'admin'
|
|
159
|
+
note: 'No auth required'
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Privacy Scopes
|
|
167
|
+
|
|
168
|
+
| Level | Meaning |
|
|
169
|
+
|---|---|
|
|
170
|
+
| `public` | No auth required |
|
|
171
|
+
| `user_owned` | Requires auth, scoped to current user only |
|
|
172
|
+
| `admin` | Restricted to admin roles |
|
|
173
|
+
|
|
174
|
+
Privacy scope is declared **per capability** — the AI is scoped to only
|
|
175
|
+
what each capability allows, before resolution happens.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Resolver Types
|
|
180
|
+
|
|
181
|
+
| Type | When to use |
|
|
182
|
+
|---|---|
|
|
183
|
+
| `api` | Answer lives in a backend API call |
|
|
184
|
+
| `nav` | User needs to be routed to a screen |
|
|
185
|
+
| `hybrid` | Both — fetch data AND navigate |
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Honest Limits
|
|
190
|
+
|
|
191
|
+
**Works well:**
|
|
192
|
+
- Structured data retrieval via APIs
|
|
193
|
+
- Navigating to known app screens
|
|
194
|
+
- Multi-endpoint aggregation
|
|
195
|
+
- Privacy scoping per capability
|
|
196
|
+
- Auto-updating on deploy
|
|
197
|
+
|
|
198
|
+
**Current limits:**
|
|
199
|
+
- Real-time infra status (is the server down?)
|
|
200
|
+
- UI-only state with no API backing
|
|
201
|
+
- Cross-app orchestration
|
|
202
|
+
- Very ambiguous queries without LLM matcher
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT
|
package/bin/capman.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
|
|
7
|
+
const args = process.argv.slice(2)
|
|
8
|
+
const command = args[0]
|
|
9
|
+
const flags = args.slice(1)
|
|
10
|
+
|
|
11
|
+
const getFlag = (name) => {
|
|
12
|
+
const i = flags.indexOf(name)
|
|
13
|
+
return i !== -1 ? flags[i + 1] : undefined
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const c = {
|
|
17
|
+
reset: '\x1b[0m',
|
|
18
|
+
bold: '\x1b[1m',
|
|
19
|
+
teal: '\x1b[36m',
|
|
20
|
+
yellow: '\x1b[33m',
|
|
21
|
+
red: '\x1b[31m',
|
|
22
|
+
green: '\x1b[32m',
|
|
23
|
+
gray: '\x1b[90m',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const log = {
|
|
27
|
+
info: (...a) => console.log(`${c.teal}i${c.reset}`, ...a),
|
|
28
|
+
success: (...a) => console.log(`${c.green}✓${c.reset}`, ...a),
|
|
29
|
+
warn: (...a) => console.log(`${c.yellow}⚠${c.reset}`, ...a),
|
|
30
|
+
error: (...a) => console.error(`${c.red}✗${c.reset}`, ...a),
|
|
31
|
+
blank: () => console.log(),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function header() {
|
|
35
|
+
console.log()
|
|
36
|
+
console.log(`${c.bold}${c.teal} capman${c.reset} ${c.gray}v0.1.0 — Capability Manifest Engine${c.reset}`)
|
|
37
|
+
console.log(`${c.gray} ─────────────────────────────────────────${c.reset}`)
|
|
38
|
+
console.log()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function requireSrc() {
|
|
42
|
+
const distPath = path.join(__dirname, '..', 'dist', 'index.js')
|
|
43
|
+
if (fs.existsSync(distPath)) return require(distPath)
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
require('ts-node/register')
|
|
47
|
+
return require(path.join(__dirname, '..', 'src', 'index.ts'))
|
|
48
|
+
} catch {
|
|
49
|
+
log.error('Cannot find dist/. Run: npx tsc')
|
|
50
|
+
process.exit(1)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function cmdHelp() {
|
|
55
|
+
header()
|
|
56
|
+
console.log(`${c.bold} Usage:${c.reset} node bin/capman.js <command>`)
|
|
57
|
+
console.log()
|
|
58
|
+
console.log(`${c.bold} Commands:${c.reset}`)
|
|
59
|
+
console.log(` ${c.teal}init${c.reset} Create a starter capman.config.js`)
|
|
60
|
+
console.log(` ${c.teal}generate${c.reset} Generate manifest.json from config`)
|
|
61
|
+
console.log(` ${c.teal}validate${c.reset} Validate an existing manifest.json`)
|
|
62
|
+
console.log(` ${c.teal}inspect${c.reset} Print all capabilities in manifest`)
|
|
63
|
+
console.log()
|
|
64
|
+
console.log(`${c.bold} Options:${c.reset}`)
|
|
65
|
+
console.log(` ${c.gray}--config Path to config file (default: capman.config.js)${c.reset}`)
|
|
66
|
+
console.log(` ${c.gray}--out Output path (default: manifest.json)${c.reset}`)
|
|
67
|
+
console.log(` ${c.gray}--manifest Manifest to read (default: manifest.json)${c.reset}`)
|
|
68
|
+
console.log()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function cmdInit() {
|
|
72
|
+
header()
|
|
73
|
+
const outPath = path.resolve(process.cwd(), 'capman.config.js')
|
|
74
|
+
if (fs.existsSync(outPath)) {
|
|
75
|
+
log.warn('capman.config.js already exists — not overwriting.')
|
|
76
|
+
process.exit(0)
|
|
77
|
+
}
|
|
78
|
+
const { generateStarterConfig } = requireSrc()
|
|
79
|
+
fs.writeFileSync(outPath, generateStarterConfig())
|
|
80
|
+
log.success(`Created ${c.bold}capman.config.js${c.reset}`)
|
|
81
|
+
log.info(`Edit it with your app's capabilities, then run:`)
|
|
82
|
+
console.log(`\n node bin/capman.js generate\n`)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function cmdGenerate() {
|
|
86
|
+
header()
|
|
87
|
+
const { loadConfig, generate, writeManifest, validate } = requireSrc()
|
|
88
|
+
|
|
89
|
+
const configPath = getFlag('--config')
|
|
90
|
+
const outPath = getFlag('--out') ?? 'manifest.json'
|
|
91
|
+
|
|
92
|
+
log.info('Loading config...')
|
|
93
|
+
let config
|
|
94
|
+
try {
|
|
95
|
+
config = loadConfig(configPath)
|
|
96
|
+
} catch (e) {
|
|
97
|
+
log.error(e.message)
|
|
98
|
+
process.exit(1)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
log.info(`Generating manifest for ${c.bold}${config.app}${c.reset}...`)
|
|
102
|
+
const manifest = generate(config)
|
|
103
|
+
const result = validate(manifest)
|
|
104
|
+
|
|
105
|
+
for (const w of result.warnings) log.warn(w)
|
|
106
|
+
for (const e of result.errors) log.error(e)
|
|
107
|
+
|
|
108
|
+
if (!result.valid) {
|
|
109
|
+
log.error('Manifest has errors — fix them before writing.')
|
|
110
|
+
process.exit(1)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const written = writeManifest(manifest, outPath)
|
|
114
|
+
log.blank()
|
|
115
|
+
log.success(`Manifest written to ${c.bold}${written}${c.reset}`)
|
|
116
|
+
log.info(`${manifest.capabilities.length} capabilities registered`)
|
|
117
|
+
console.log()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function cmdValidate() {
|
|
121
|
+
header()
|
|
122
|
+
const { readManifest, validate } = requireSrc()
|
|
123
|
+
|
|
124
|
+
const manifestPath = getFlag('--manifest') ?? 'manifest.json'
|
|
125
|
+
let manifest
|
|
126
|
+
try {
|
|
127
|
+
manifest = readManifest(manifestPath)
|
|
128
|
+
} catch (e) {
|
|
129
|
+
log.error(e.message)
|
|
130
|
+
process.exit(1)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
log.info(`Validating ${c.bold}${manifestPath}${c.reset}...`)
|
|
134
|
+
const result = validate(manifest)
|
|
135
|
+
log.blank()
|
|
136
|
+
|
|
137
|
+
for (const w of result.warnings) log.warn(w)
|
|
138
|
+
for (const e of result.errors) log.error(e)
|
|
139
|
+
|
|
140
|
+
if (result.valid) {
|
|
141
|
+
log.success(`${manifest.capabilities.length} capabilities — all valid`)
|
|
142
|
+
} else {
|
|
143
|
+
log.error(`${result.errors.length} error(s) found.`)
|
|
144
|
+
process.exit(1)
|
|
145
|
+
}
|
|
146
|
+
console.log()
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function cmdInspect() {
|
|
150
|
+
header()
|
|
151
|
+
const { readManifest } = requireSrc()
|
|
152
|
+
|
|
153
|
+
const manifestPath = getFlag('--manifest') ?? 'manifest.json'
|
|
154
|
+
let manifest
|
|
155
|
+
try {
|
|
156
|
+
manifest = readManifest(manifestPath)
|
|
157
|
+
} catch (e) {
|
|
158
|
+
log.error(e.message)
|
|
159
|
+
process.exit(1)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
console.log(`${c.bold} App:${c.reset} ${manifest.app}`)
|
|
163
|
+
console.log(`${c.bold} Generated:${c.reset} ${manifest.generatedAt}`)
|
|
164
|
+
console.log(`${c.bold} Capabilities:${c.reset} ${manifest.capabilities.length}`)
|
|
165
|
+
console.log()
|
|
166
|
+
|
|
167
|
+
for (const cap of manifest.capabilities) {
|
|
168
|
+
const col = cap.resolver.type === 'api' ? c.teal : cap.resolver.type === 'nav' ? c.teal : c.yellow
|
|
169
|
+
console.log(` ${c.bold}${cap.name}${c.reset} ${col}[${cap.resolver.type}]${c.reset} ${c.gray}${cap.privacy.level}${c.reset}`)
|
|
170
|
+
console.log(` ${c.gray}id: ${cap.id}${c.reset}`)
|
|
171
|
+
console.log(` ${cap.description}`)
|
|
172
|
+
if (cap.examples?.length) {
|
|
173
|
+
console.log(` ${c.gray}e.g. "${cap.examples[0]}"${c.reset}`)
|
|
174
|
+
}
|
|
175
|
+
console.log()
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
switch (command) {
|
|
180
|
+
case 'init': cmdInit(); break
|
|
181
|
+
case 'generate': cmdGenerate(); break
|
|
182
|
+
case 'validate': cmdValidate(); break
|
|
183
|
+
case 'inspect': cmdInspect(); break
|
|
184
|
+
case undefined:
|
|
185
|
+
case '--help':
|
|
186
|
+
case '-h': cmdHelp(); break
|
|
187
|
+
default:
|
|
188
|
+
header()
|
|
189
|
+
log.error(`Unknown command: ${command}`)
|
|
190
|
+
console.log(` Run: node bin/capman.js --help\n`)
|
|
191
|
+
process.exit(1)
|
|
192
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CapmanConfig, Manifest, ValidationResult } from './types';
|
|
2
|
+
export declare function generate(config: CapmanConfig): Manifest;
|
|
3
|
+
export declare function loadConfig(configPath?: string): CapmanConfig;
|
|
4
|
+
export declare function writeManifest(manifest: Manifest, outputPath?: string): string;
|
|
5
|
+
export declare function readManifest(manifestPath?: string): Manifest;
|
|
6
|
+
export declare function validate(manifest: Manifest): ValidationResult;
|
|
7
|
+
export declare function generateStarterConfig(): string;
|
|
8
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAIvE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,CAOvD;AAED,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CAsD5D;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,SAAkB,GAAG,MAAM,CAItF;AAED,wBAAgB,YAAY,CAAC,YAAY,SAAkB,GAAG,QAAQ,CAgBrE;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,gBAAgB,CA4B7D;AACD,wBAAgB,qBAAqB,IAAI,MAAM,CAoF9C"}
|