capman 0.6.0 → 0.6.2
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/CODEBASE.md +6 -5
- package/dist/cjs/cache.d.ts +9 -0
- package/dist/cjs/cache.d.ts.map +1 -1
- package/dist/cjs/cache.js +37 -7
- package/dist/cjs/cache.js.map +1 -1
- package/dist/cjs/concurrent.d.ts +53 -0
- package/dist/cjs/concurrent.d.ts.map +1 -0
- package/dist/cjs/concurrent.js +71 -0
- package/dist/cjs/concurrent.js.map +1 -0
- package/dist/cjs/engine.d.ts +92 -7
- package/dist/cjs/engine.d.ts.map +1 -1
- package/dist/cjs/engine.js +269 -57
- package/dist/cjs/engine.js.map +1 -1
- package/dist/cjs/generator.d.ts.map +1 -1
- package/dist/cjs/generator.js +28 -6
- package/dist/cjs/generator.js.map +1 -1
- package/dist/cjs/index.d.ts +3 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +5 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/learning.d.ts +16 -1
- package/dist/cjs/learning.d.ts.map +1 -1
- package/dist/cjs/learning.js +95 -14
- package/dist/cjs/learning.js.map +1 -1
- package/dist/cjs/matcher.d.ts +51 -2
- package/dist/cjs/matcher.d.ts.map +1 -1
- package/dist/cjs/matcher.js +173 -33
- package/dist/cjs/matcher.js.map +1 -1
- package/dist/cjs/parser.js +27 -9
- package/dist/cjs/parser.js.map +1 -1
- package/dist/cjs/resolver.d.ts +2 -2
- package/dist/cjs/resolver.d.ts.map +1 -1
- package/dist/cjs/resolver.js +66 -26
- package/dist/cjs/resolver.js.map +1 -1
- package/dist/cjs/schema.d.ts +821 -68
- package/dist/cjs/schema.d.ts.map +1 -1
- package/dist/cjs/schema.js +62 -13
- package/dist/cjs/schema.js.map +1 -1
- package/dist/cjs/types.d.ts +156 -9
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/cache.d.ts +9 -0
- package/dist/esm/cache.js +37 -7
- package/dist/esm/concurrent.d.ts +52 -0
- package/dist/esm/concurrent.js +66 -0
- package/dist/esm/engine.d.ts +92 -7
- package/dist/esm/engine.js +270 -58
- package/dist/esm/generator.js +28 -6
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/learning.d.ts +16 -1
- package/dist/esm/learning.js +95 -14
- package/dist/esm/matcher.d.ts +51 -2
- package/dist/esm/matcher.js +170 -33
- package/dist/esm/parser.js +27 -9
- package/dist/esm/resolver.d.ts +2 -2
- package/dist/esm/resolver.js +66 -26
- package/dist/esm/schema.d.ts +821 -68
- package/dist/esm/schema.js +62 -13
- package/dist/esm/types.d.ts +156 -9
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +1 -1
package/dist/esm/schema.js
CHANGED
|
@@ -5,17 +5,22 @@ const CapabilityParamSchema = z.object({
|
|
|
5
5
|
description: z.string().min(1, 'param description is required'),
|
|
6
6
|
required: z.boolean(),
|
|
7
7
|
source: z.enum(['user_query', 'session']),
|
|
8
|
-
default: z.union([z.string(), z.number(), z.boolean()]).optional(),
|
|
9
8
|
pattern: z.string().optional(),
|
|
10
|
-
|
|
9
|
+
type: z.enum(['string', 'number', 'boolean', 'date', 'email', 'url', 'enum', 'object']).optional(),
|
|
10
|
+
enum: z.array(z.string()).optional(),
|
|
11
|
+
example: z.string().optional(),
|
|
12
|
+
}).refine(p => !(p.type === 'enum' && (!p.enum || p.enum.length === 0)), { message: 'enum values required when type is "enum"' });
|
|
11
13
|
// ─── Resolver Schemas ─────────────────────────────────────────────────────────
|
|
14
|
+
const EndpointSchema = z.object({
|
|
15
|
+
method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']),
|
|
16
|
+
path: z.string().min(1, 'endpoint path is required'),
|
|
17
|
+
params: z.array(z.string()).optional(),
|
|
18
|
+
idempotent: z.boolean().optional(),
|
|
19
|
+
idempotencyKey: z.string().optional(),
|
|
20
|
+
});
|
|
12
21
|
const ApiResolverSchema = z.object({
|
|
13
22
|
type: z.literal('api'),
|
|
14
|
-
endpoints: z.array(
|
|
15
|
-
method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),
|
|
16
|
-
path: z.string().min(1, 'endpoint path is required'),
|
|
17
|
-
params: z.array(z.string()).optional(),
|
|
18
|
-
})).min(1, 'at least one endpoint is required'),
|
|
23
|
+
endpoints: z.array(EndpointSchema).min(1, 'at least one endpoint is required'),
|
|
19
24
|
});
|
|
20
25
|
const NavResolverSchema = z.object({
|
|
21
26
|
type: z.literal('nav'),
|
|
@@ -25,11 +30,7 @@ const NavResolverSchema = z.object({
|
|
|
25
30
|
const HybridResolverSchema = z.object({
|
|
26
31
|
type: z.literal('hybrid'),
|
|
27
32
|
api: z.object({
|
|
28
|
-
endpoints: z.array(
|
|
29
|
-
method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),
|
|
30
|
-
path: z.string().min(1),
|
|
31
|
-
params: z.array(z.string()).optional(),
|
|
32
|
-
})).min(1),
|
|
33
|
+
endpoints: z.array(EndpointSchema).min(1),
|
|
33
34
|
}),
|
|
34
35
|
nav: z.object({
|
|
35
36
|
destination: z.string().min(1),
|
|
@@ -46,6 +47,22 @@ const PrivacyScopeSchema = z.object({
|
|
|
46
47
|
level: z.enum(['public', 'user_owned', 'admin']),
|
|
47
48
|
note: z.string().optional(),
|
|
48
49
|
});
|
|
50
|
+
const LifecycleInfoSchema = z.object({
|
|
51
|
+
status: z.enum(['stable', 'beta', 'experimental', 'deprecated']),
|
|
52
|
+
deprecatedAt: z.string().datetime().optional(),
|
|
53
|
+
sunsetAt: z.string().datetime().optional(),
|
|
54
|
+
successor: z.string().optional(),
|
|
55
|
+
note: z.string().optional(),
|
|
56
|
+
});
|
|
57
|
+
const MatchHintSchema = z.object({
|
|
58
|
+
preferredMode: z.enum(['cheap', 'balanced', 'accurate']).optional(),
|
|
59
|
+
});
|
|
60
|
+
const CapabilityErrorSchema = z.object({
|
|
61
|
+
code: z.string().min(1, 'error code is required'),
|
|
62
|
+
description: z.string().min(1, 'error description is required'),
|
|
63
|
+
httpStatus: z.number().int().min(400).max(599).optional(),
|
|
64
|
+
retryable: z.boolean().optional(),
|
|
65
|
+
});
|
|
49
66
|
// ─── Capability Schema ────────────────────────────────────────────────────────
|
|
50
67
|
const CapabilitySchema = z.object({
|
|
51
68
|
id: z.string().min(1, 'capability id is required')
|
|
@@ -59,24 +76,56 @@ const CapabilitySchema = z.object({
|
|
|
59
76
|
returns: z.array(z.string()),
|
|
60
77
|
resolver: ResolverSchema,
|
|
61
78
|
privacy: PrivacyScopeSchema,
|
|
79
|
+
lifecycle: LifecycleInfoSchema.optional(),
|
|
80
|
+
tags: z.array(z.string().min(1)).optional(),
|
|
81
|
+
errors: z.array(CapabilityErrorSchema).optional(),
|
|
82
|
+
matchHint: MatchHintSchema.optional(),
|
|
83
|
+
});
|
|
84
|
+
const ServerSchema = z.object({
|
|
85
|
+
url: z.string().url('server url must be a valid URL'),
|
|
86
|
+
description: z.string().optional(),
|
|
87
|
+
environment: z.string().optional(),
|
|
88
|
+
});
|
|
89
|
+
// ─── ManifestInfo Schema ──────────────────────────────────────────────────────
|
|
90
|
+
const ManifestInfoSchema = z.object({
|
|
91
|
+
title: z.string().optional(),
|
|
92
|
+
description: z.string().optional(),
|
|
93
|
+
version: z.string().optional(),
|
|
94
|
+
homepage: z.string().url().optional(),
|
|
95
|
+
contact: z.object({
|
|
96
|
+
name: z.string().optional(),
|
|
97
|
+
email: z.string().email().optional(),
|
|
98
|
+
url: z.string().url().optional(),
|
|
99
|
+
}).optional(),
|
|
100
|
+
license: z.object({
|
|
101
|
+
name: z.string().min(1, 'license name is required'),
|
|
102
|
+
url: z.string().url().optional(),
|
|
103
|
+
}).optional(),
|
|
62
104
|
});
|
|
63
105
|
// ─── Config Schema ────────────────────────────────────────────────────────────
|
|
64
106
|
export const CapmanConfigSchema = z.object({
|
|
65
107
|
app: z.string().min(1, 'app name is required'),
|
|
66
108
|
baseUrl: z.string().url().optional(),
|
|
109
|
+
info: ManifestInfoSchema.optional(),
|
|
110
|
+
servers: z.array(ServerSchema).optional(),
|
|
111
|
+
tagRegistry: z.record(z.object({ description: z.string() })).optional(),
|
|
67
112
|
capabilities: z.array(CapabilitySchema)
|
|
68
113
|
.min(1, 'at least one capability is required')
|
|
69
114
|
.refine(caps => new Set(caps.map(c => c.id)).size === caps.length, 'capability ids must be unique'),
|
|
70
115
|
}).refine(cfg => {
|
|
71
116
|
const needsBaseUrl = cfg.capabilities.some(c => c.resolver.type === 'api' || c.resolver.type === 'hybrid');
|
|
72
|
-
return !needsBaseUrl || !!cfg.baseUrl;
|
|
117
|
+
return !needsBaseUrl || !!cfg.baseUrl || (cfg.servers?.length ?? 0) > 0;
|
|
73
118
|
}, { message: 'baseUrl is required when any capability uses an api or hybrid resolver' });
|
|
74
119
|
// ─── Manifest Schema ──────────────────────────────────────────────────────────
|
|
75
120
|
export const ManifestSchema = z.object({
|
|
121
|
+
schemaVersion: z.string().min(1, 'schemaVersion is required'),
|
|
76
122
|
version: z.string(),
|
|
77
123
|
app: z.string().min(1),
|
|
78
124
|
generatedAt: z.string().datetime(),
|
|
79
125
|
capabilities: z.array(CapabilitySchema).min(1),
|
|
126
|
+
tagRegistry: z.record(z.object({ description: z.string() })).optional(),
|
|
127
|
+
servers: z.array(ServerSchema).optional(),
|
|
128
|
+
info: ManifestInfoSchema.optional(),
|
|
80
129
|
});
|
|
81
130
|
export function validateConfig(config) {
|
|
82
131
|
const result = CapmanConfigSchema.safeParse(config);
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type ResolverType = 'api' | 'nav' | 'hybrid';
|
|
2
|
-
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
2
|
+
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
3
|
+
export type ParamType = 'string' | 'number' | 'boolean' | 'date' | 'email' | 'url' | 'enum' | 'object';
|
|
3
4
|
export interface CapabilityParam {
|
|
4
5
|
name: string;
|
|
5
6
|
description: string;
|
|
@@ -9,17 +10,49 @@ export interface CapabilityParam {
|
|
|
9
10
|
* Optional extraction hint. Either a named type or an example template.
|
|
10
11
|
* Named types: 'email' | 'date' | 'orderId' | 'url'
|
|
11
12
|
* Example template: "order {paramName}" — extracts token after "order"
|
|
12
|
-
* When provided, pattern matching runs before keyword heuristics.
|
|
13
13
|
*/
|
|
14
14
|
pattern?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Semantic type of the parameter value.
|
|
17
|
+
* When set, implies a TYPE_PATTERNS match without requiring pattern to be set.
|
|
18
|
+
* 'email', 'date', 'url' map directly to TYPE_PATTERNS regex.
|
|
19
|
+
* 'enum' requires the enum field to be set with allowed values.
|
|
20
|
+
* 'number', 'boolean', 'object' affect coercion in LLM extraction.
|
|
21
|
+
*/
|
|
22
|
+
type?: ParamType;
|
|
23
|
+
/**
|
|
24
|
+
* Allowed values when type === 'enum'.
|
|
25
|
+
* Extracted values not in this list are rejected and added to missingParams.
|
|
26
|
+
*/
|
|
27
|
+
enum?: string[];
|
|
28
|
+
/**
|
|
29
|
+
* Single concrete example for LLM param prompting.
|
|
30
|
+
* Helps the LLM understand what a valid value looks like.
|
|
31
|
+
* e.g. example: "ORD-12345"
|
|
32
|
+
*/
|
|
33
|
+
example?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface Endpoint {
|
|
36
|
+
method: HttpMethod;
|
|
37
|
+
path: string;
|
|
38
|
+
params?: string[];
|
|
39
|
+
/**
|
|
40
|
+
* Whether this endpoint is idempotent — safe to retry on failure.
|
|
41
|
+
* Defaults: true for GET/HEAD/OPTIONS, false for POST/PUT/PATCH/DELETE.
|
|
42
|
+
* Set explicitly to override — e.g. `idempotent: true` on a POST
|
|
43
|
+
* with an idempotency key allows retries without `retryAllMethods: true`.
|
|
44
|
+
*/
|
|
45
|
+
idempotent?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Name of the param whose value is sent as the `Idempotency-Key` header.
|
|
48
|
+
* When set and the param is available, the header is injected automatically.
|
|
49
|
+
* e.g. idempotencyKey: 'order_id' → `Idempotency-Key: ORD-12345`
|
|
50
|
+
*/
|
|
51
|
+
idempotencyKey?: string;
|
|
15
52
|
}
|
|
16
53
|
export interface ApiResolver {
|
|
17
54
|
type: 'api';
|
|
18
|
-
endpoints:
|
|
19
|
-
method: HttpMethod;
|
|
20
|
-
path: string;
|
|
21
|
-
params?: string[];
|
|
22
|
-
}>;
|
|
55
|
+
endpoints: Endpoint[];
|
|
23
56
|
}
|
|
24
57
|
export interface NavResolver {
|
|
25
58
|
type: 'nav';
|
|
@@ -36,6 +69,50 @@ export interface PrivacyScope {
|
|
|
36
69
|
level: 'public' | 'user_owned' | 'admin';
|
|
37
70
|
note?: string;
|
|
38
71
|
}
|
|
72
|
+
export type LifecycleStatus = 'stable' | 'beta' | 'experimental' | 'deprecated';
|
|
73
|
+
export interface LifecycleInfo {
|
|
74
|
+
status: LifecycleStatus;
|
|
75
|
+
/** ISO 8601 — when the capability was deprecated */
|
|
76
|
+
deprecatedAt?: string;
|
|
77
|
+
/** ISO 8601 — when the capability will stop working */
|
|
78
|
+
sunsetAt?: string;
|
|
79
|
+
/** Capability id to use instead of this one */
|
|
80
|
+
successor?: string;
|
|
81
|
+
/** Human-readable note for consumers */
|
|
82
|
+
note?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Optional embedding provider for semantic similarity matching.
|
|
86
|
+
* Zero mandatory dependency — only used when passed to EngineOptions.
|
|
87
|
+
* Implement with any model: OpenAI, local ONNX, Transformers.js, etc.
|
|
88
|
+
*/
|
|
89
|
+
export interface EmbeddingProvider {
|
|
90
|
+
/** Encode a batch of texts into fixed-length float vectors. */
|
|
91
|
+
encode(texts: string[]): Promise<number[][]>;
|
|
92
|
+
}
|
|
93
|
+
export interface MatchHint {
|
|
94
|
+
/**
|
|
95
|
+
* Advisory preferred matching mode for this capability.
|
|
96
|
+
* The engine logs when it ignores the hint (e.g. engine is in cheap mode
|
|
97
|
+
* but capability prefers accurate). Never enforced — library must not
|
|
98
|
+
* restrict what consumers can do.
|
|
99
|
+
*/
|
|
100
|
+
preferredMode?: MatchMode;
|
|
101
|
+
}
|
|
102
|
+
export interface CapabilityError {
|
|
103
|
+
/** Machine-readable error code e.g. "ORDER_NOT_FOUND", "INSUFFICIENT_FUNDS" */
|
|
104
|
+
code: string;
|
|
105
|
+
/** Human-readable description for developers */
|
|
106
|
+
description: string;
|
|
107
|
+
/** HTTP status code this error maps to */
|
|
108
|
+
httpStatus?: number;
|
|
109
|
+
/**
|
|
110
|
+
* Whether the agent should retry after this error.
|
|
111
|
+
* true — transient (503, timeout) — retry is safe
|
|
112
|
+
* false — permanent (422, 404) — retrying won't help, ask user
|
|
113
|
+
*/
|
|
114
|
+
retryable?: boolean;
|
|
115
|
+
}
|
|
39
116
|
export interface Capability {
|
|
40
117
|
id: string;
|
|
41
118
|
name: string;
|
|
@@ -45,17 +122,82 @@ export interface Capability {
|
|
|
45
122
|
returns: string[];
|
|
46
123
|
resolver: Resolver;
|
|
47
124
|
privacy: PrivacyScope;
|
|
125
|
+
/** Lifecycle status — defaults to 'stable' when absent */
|
|
126
|
+
lifecycle?: LifecycleInfo;
|
|
127
|
+
/** Tags for grouping and filtering capabilities */
|
|
128
|
+
tags?: string[];
|
|
129
|
+
errors?: CapabilityError[];
|
|
130
|
+
matchHint?: MatchHint;
|
|
131
|
+
}
|
|
132
|
+
export interface ManifestInfo {
|
|
133
|
+
/** Human-readable title for the app */
|
|
134
|
+
title?: string;
|
|
135
|
+
/** Brief description of what the app does */
|
|
136
|
+
description?: string;
|
|
137
|
+
/** App's own version — distinct from capman package version */
|
|
138
|
+
version?: string;
|
|
139
|
+
/** URL to the app's homepage or documentation */
|
|
140
|
+
homepage?: string;
|
|
141
|
+
contact?: {
|
|
142
|
+
name?: string;
|
|
143
|
+
email?: string;
|
|
144
|
+
url?: string;
|
|
145
|
+
};
|
|
146
|
+
license?: {
|
|
147
|
+
/** SPDX license identifier e.g. "MIT", "Apache-2.0" */
|
|
148
|
+
name: string;
|
|
149
|
+
url?: string;
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
export interface Server {
|
|
153
|
+
url: string;
|
|
154
|
+
description?: string;
|
|
155
|
+
/**
|
|
156
|
+
* Environment this server belongs to.
|
|
157
|
+
* Engine selects server by matching EngineOptions.environment.
|
|
158
|
+
* Fallback: first server in array when no environment matches.
|
|
159
|
+
*/
|
|
160
|
+
environment?: 'production' | 'staging' | 'development' | string;
|
|
48
161
|
}
|
|
49
162
|
export interface Manifest {
|
|
163
|
+
/**
|
|
164
|
+
* Manifest format version — independent of the capman package version.
|
|
165
|
+
* Consumers use this to determine which parser/validator to apply.
|
|
166
|
+
* "1" = v0.6+ schema (tags, lifecycle, typed params, servers, etc.)
|
|
167
|
+
*/
|
|
168
|
+
schemaVersion: string;
|
|
169
|
+
/** capman package version that generated this manifest */
|
|
50
170
|
version: string;
|
|
51
171
|
app: string;
|
|
52
172
|
generatedAt: string;
|
|
53
173
|
capabilities: Capability[];
|
|
174
|
+
/**
|
|
175
|
+
* Optional registry of known tags with descriptions.
|
|
176
|
+
* Used for documentation and validation — not required for tags to work.
|
|
177
|
+
*/
|
|
178
|
+
tagRegistry?: Record<string, {
|
|
179
|
+
description: string;
|
|
180
|
+
}>;
|
|
181
|
+
/** Optional metadata block for documentation and provenance */
|
|
182
|
+
info?: ManifestInfo;
|
|
183
|
+
/**
|
|
184
|
+
* Server definitions. When present, engine selects baseUrl from this list.
|
|
185
|
+
* Falls back to EngineOptions.baseUrl if servers is absent or no match found.
|
|
186
|
+
*/
|
|
187
|
+
servers?: Server[];
|
|
54
188
|
}
|
|
55
189
|
export interface CapmanConfig {
|
|
56
190
|
app: string;
|
|
57
191
|
baseUrl?: string;
|
|
58
192
|
capabilities: Capability[];
|
|
193
|
+
/** Optional metadata — written to manifest.info */
|
|
194
|
+
info?: ManifestInfo;
|
|
195
|
+
/** Optional tag registry — written to manifest.tagRegistry */
|
|
196
|
+
tagRegistry?: Record<string, {
|
|
197
|
+
description: string;
|
|
198
|
+
}>;
|
|
199
|
+
/** Server definitions — written to manifest.servers */
|
|
200
|
+
servers?: Server[];
|
|
59
201
|
}
|
|
60
202
|
export interface MatchResult {
|
|
61
203
|
capability: Capability | null;
|
|
@@ -74,15 +216,20 @@ export interface ApiCallResult {
|
|
|
74
216
|
status?: number;
|
|
75
217
|
/** Parsed JSON response body — only present when actually executed */
|
|
76
218
|
data?: unknown;
|
|
219
|
+
/** Error message — only present on network-level failure (status 0) */
|
|
220
|
+
error?: string;
|
|
77
221
|
}
|
|
78
222
|
export interface ResolveResult {
|
|
79
223
|
success: boolean;
|
|
80
224
|
resolverType: ResolverType | null;
|
|
225
|
+
error?: string;
|
|
226
|
+
/** Structured error from capability.errors[] when httpStatus matches */
|
|
227
|
+
matchedError?: CapabilityError;
|
|
81
228
|
apiCalls?: ApiCallResult[];
|
|
82
229
|
navTarget?: string;
|
|
83
|
-
|
|
230
|
+
status?: number;
|
|
231
|
+
data?: unknown;
|
|
84
232
|
durationMs?: number;
|
|
85
|
-
error?: string;
|
|
86
233
|
}
|
|
87
234
|
export interface ValidationResult {
|
|
88
235
|
valid: boolean;
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.6.1";
|
package/dist/esm/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by scripts/version.js — do not edit manually
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.6.1';
|
package/package.json
CHANGED