@kadi.build/core 0.0.1-alpha.1 → 0.0.1-alpha.11
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 +361 -230
- package/dist/abilities/AbilityCache.d.ts +242 -0
- package/dist/abilities/AbilityCache.d.ts.map +1 -0
- package/dist/abilities/AbilityCache.js +285 -0
- package/dist/abilities/AbilityCache.js.map +1 -0
- package/dist/abilities/AbilityContext.d.ts +215 -0
- package/dist/abilities/AbilityContext.d.ts.map +1 -0
- package/dist/abilities/AbilityContext.js +36 -0
- package/dist/abilities/AbilityContext.js.map +1 -0
- package/dist/abilities/AbilityLoader.d.ts +203 -0
- package/dist/abilities/AbilityLoader.d.ts.map +1 -0
- package/dist/abilities/AbilityLoader.js +343 -0
- package/dist/abilities/AbilityLoader.js.map +1 -0
- package/dist/abilities/AbilityProxy.d.ts +496 -0
- package/dist/abilities/AbilityProxy.d.ts.map +1 -0
- package/dist/abilities/AbilityProxy.js +551 -0
- package/dist/abilities/AbilityProxy.js.map +1 -0
- package/dist/abilities/AbilityValidator.d.ts +172 -0
- package/dist/abilities/AbilityValidator.d.ts.map +1 -0
- package/dist/abilities/AbilityValidator.js +253 -0
- package/dist/abilities/AbilityValidator.js.map +1 -0
- package/dist/abilities/index.d.ts +26 -0
- package/dist/abilities/index.d.ts.map +1 -0
- package/dist/abilities/index.js +23 -0
- package/dist/abilities/index.js.map +1 -0
- package/dist/abilities/types.d.ts +223 -0
- package/dist/abilities/types.d.ts.map +1 -0
- package/dist/abilities/types.js +10 -0
- package/dist/abilities/types.js.map +1 -0
- package/dist/api/index.d.ts +92 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +124 -0
- package/dist/api/index.js.map +1 -0
- package/dist/broker/BrokerConnection.d.ts +253 -0
- package/dist/broker/BrokerConnection.d.ts.map +1 -0
- package/dist/broker/BrokerConnection.js +434 -0
- package/dist/broker/BrokerConnection.js.map +1 -0
- package/dist/broker/BrokerConnectionManager.d.ts +216 -0
- package/dist/broker/BrokerConnectionManager.d.ts.map +1 -0
- package/dist/broker/BrokerConnectionManager.js +305 -0
- package/dist/broker/BrokerConnectionManager.js.map +1 -0
- package/dist/broker/BrokerProtocol.d.ts +280 -0
- package/dist/broker/BrokerProtocol.d.ts.map +1 -0
- package/dist/broker/BrokerProtocol.js +466 -0
- package/dist/broker/BrokerProtocol.js.map +1 -0
- package/dist/broker/index.d.ts +9 -0
- package/dist/broker/index.d.ts.map +1 -0
- package/dist/broker/index.js +9 -0
- package/dist/broker/index.js.map +1 -0
- package/dist/client/KadiClient.d.ts +459 -0
- package/dist/client/KadiClient.d.ts.map +1 -0
- package/dist/client/KadiClient.js +902 -0
- package/dist/client/KadiClient.js.map +1 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/config/ConfigLoader.d.ts +138 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +226 -0
- package/dist/config/ConfigLoader.js.map +1 -0
- package/dist/config/ConfigResolver.d.ts +135 -0
- package/dist/config/ConfigResolver.d.ts.map +1 -0
- package/dist/config/ConfigResolver.js +282 -0
- package/dist/config/ConfigResolver.js.map +1 -0
- package/dist/config/index.d.ts +8 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +8 -0
- package/dist/config/index.js.map +1 -0
- package/dist/errors/index.d.ts +9 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +8 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/events/EventHub.d.ts +172 -0
- package/dist/events/EventHub.d.ts.map +1 -0
- package/dist/events/EventHub.js +333 -0
- package/dist/events/EventHub.js.map +1 -0
- package/dist/events/index.d.ts +7 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +7 -0
- package/dist/events/index.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/messages/index.d.ts +33 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +33 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/schemas/index.d.ts +22 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +27 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/kadi-extensions.d.ts +231 -0
- package/dist/schemas/kadi-extensions.d.ts.map +1 -0
- package/dist/schemas/kadi-extensions.js +14 -0
- package/dist/schemas/kadi-extensions.js.map +1 -0
- package/dist/schemas/mcp/schema.d.ts +1399 -0
- package/dist/schemas/mcp/schema.d.ts.map +1 -0
- package/dist/schemas/mcp/schema.js +53 -0
- package/dist/schemas/mcp/schema.js.map +1 -0
- package/dist/schemas/mcp/version.d.ts +37 -0
- package/dist/schemas/mcp/version.d.ts.map +1 -0
- package/dist/schemas/mcp/version.js +39 -0
- package/dist/schemas/mcp/version.js.map +1 -0
- package/dist/schemas/schema-builders.d.ts +178 -0
- package/dist/schemas/schema-builders.d.ts.map +1 -0
- package/dist/schemas/schema-builders.js +258 -0
- package/dist/schemas/schema-builders.js.map +1 -0
- package/dist/schemas/zod-helpers.d.ts +129 -0
- package/dist/schemas/zod-helpers.d.ts.map +1 -0
- package/dist/schemas/zod-helpers.js +225 -0
- package/dist/schemas/zod-helpers.js.map +1 -0
- package/dist/schemas/zod-to-json-schema.d.ts +159 -0
- package/dist/schemas/zod-to-json-schema.d.ts.map +1 -0
- package/dist/schemas/zod-to-json-schema.js +154 -0
- package/dist/schemas/zod-to-json-schema.js.map +1 -0
- package/dist/tools/ToolRegistry.d.ts +256 -0
- package/dist/tools/ToolRegistry.d.ts.map +1 -0
- package/dist/tools/ToolRegistry.js +340 -0
- package/dist/tools/ToolRegistry.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +7 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/transports/BrokerTransport.d.ts +151 -0
- package/dist/transports/BrokerTransport.d.ts.map +1 -0
- package/dist/transports/BrokerTransport.js +261 -0
- package/dist/transports/BrokerTransport.js.map +1 -0
- package/dist/transports/NativeTransport.d.ts +178 -0
- package/dist/transports/NativeTransport.d.ts.map +1 -0
- package/dist/transports/NativeTransport.js +397 -0
- package/dist/transports/NativeTransport.js.map +1 -0
- package/dist/transports/StdioTransport.d.ts +250 -0
- package/dist/transports/StdioTransport.d.ts.map +1 -0
- package/dist/transports/StdioTransport.js +487 -0
- package/dist/transports/StdioTransport.js.map +1 -0
- package/dist/transports/index.d.ts +10 -0
- package/dist/transports/index.d.ts.map +1 -0
- package/dist/transports/index.js +9 -0
- package/dist/transports/index.js.map +1 -0
- package/dist/types/broker.d.ts +279 -0
- package/dist/types/broker.d.ts.map +1 -0
- package/dist/types/broker.js +19 -0
- package/dist/types/broker.js.map +1 -0
- package/dist/types/config.d.ts +325 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +17 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/errors.d.ts +178 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +165 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/events.d.ts +210 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +8 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/protocol.d.ts +48 -0
- package/dist/types/protocol.d.ts.map +1 -0
- package/dist/types/protocol.js +11 -0
- package/dist/types/protocol.js.map +1 -0
- package/dist/types/tools.d.ts +67 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +16 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/types/transport.d.ts +250 -0
- package/dist/types/transport.d.ts.map +1 -0
- package/dist/types/transport.js +18 -0
- package/dist/types/transport.js.map +1 -0
- package/dist/types/zod-tools.d.ts +198 -0
- package/dist/types/zod-tools.d.ts.map +1 -0
- package/dist/types/zod-tools.js +14 -0
- package/dist/types/zod-tools.js.map +1 -0
- package/dist/utils/StdioMessageReader.d.ts +122 -0
- package/dist/utils/StdioMessageReader.d.ts.map +1 -0
- package/dist/utils/StdioMessageReader.js +209 -0
- package/dist/utils/StdioMessageReader.js.map +1 -0
- package/dist/utils/StdioMessageWriter.d.ts +104 -0
- package/dist/utils/StdioMessageWriter.d.ts.map +1 -0
- package/dist/utils/StdioMessageWriter.js +162 -0
- package/dist/utils/StdioMessageWriter.js.map +1 -0
- package/dist/validation/SchemaValidator.d.ts +208 -0
- package/dist/validation/SchemaValidator.d.ts.map +1 -0
- package/dist/validation/SchemaValidator.js +411 -0
- package/dist/validation/SchemaValidator.js.map +1 -0
- package/dist/validation/index.d.ts +11 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +10 -0
- package/dist/validation/index.js.map +1 -0
- package/package.json +70 -5
- package/agent.json +0 -18
- package/broker.js +0 -214
- package/index.js +0 -370
- package/ipc.js +0 -220
- package/ipcInterfaces/pythonAbilityIPC.py +0 -177
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ability Validator
|
|
3
|
+
*
|
|
4
|
+
* Runtime validation to ensure loaded abilities meet expectations.
|
|
5
|
+
* Catches mismatches early with clear, actionable error messages.
|
|
6
|
+
*
|
|
7
|
+
* @module abilities/AbilityValidator
|
|
8
|
+
*/
|
|
9
|
+
import type { LoadedAbility } from './AbilityProxy.js';
|
|
10
|
+
/**
|
|
11
|
+
* Validation options
|
|
12
|
+
*/
|
|
13
|
+
export interface ValidationOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Expected method names
|
|
16
|
+
*
|
|
17
|
+
* If provided, validator checks these methods exist.
|
|
18
|
+
*/
|
|
19
|
+
expectedMethods?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Whether to require at least one method
|
|
22
|
+
*
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
requireMethods?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Allow additional methods beyond expected
|
|
28
|
+
*
|
|
29
|
+
* @default true
|
|
30
|
+
*/
|
|
31
|
+
allowAdditional?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Ability Validator
|
|
35
|
+
*
|
|
36
|
+
* Ensures loaded abilities are valid and meet expectations before
|
|
37
|
+
* returning them to developers.
|
|
38
|
+
*
|
|
39
|
+
* **Why Runtime Validation?**
|
|
40
|
+
*
|
|
41
|
+
* TypeScript provides compile-time types, but those can lie:
|
|
42
|
+
* ```typescript
|
|
43
|
+
* interface CalcAPI {
|
|
44
|
+
* add(): Promise<number>;
|
|
45
|
+
* }
|
|
46
|
+
* const calc = await client.load<CalcAPI>('calculator');
|
|
47
|
+
* // TypeScript happy, but what if ability doesn't have add()?
|
|
48
|
+
* await calc.add(); // Runtime error!
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* Runtime validation catches this early with helpful errors.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* // Basic validation - just check ability has methods
|
|
56
|
+
* AbilityValidator.validate(ability);
|
|
57
|
+
*
|
|
58
|
+
* // Validate specific methods
|
|
59
|
+
* AbilityValidator.validate(ability, {
|
|
60
|
+
* expectedMethods: ['add', 'subtract', 'multiply']
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare class AbilityValidator {
|
|
65
|
+
/**
|
|
66
|
+
* Validate ability meets expectations
|
|
67
|
+
*
|
|
68
|
+
* Checks:
|
|
69
|
+
* 1. Ability is properly initialized
|
|
70
|
+
* 2. Ability has methods (not empty)
|
|
71
|
+
* 3. Expected methods exist (if specified)
|
|
72
|
+
*
|
|
73
|
+
* @param ability - Loaded ability to validate
|
|
74
|
+
* @param options - Validation options
|
|
75
|
+
*
|
|
76
|
+
* @throws {KadiError} If validation fails
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* // Basic validation
|
|
81
|
+
* AbilityValidator.validate(ability);
|
|
82
|
+
*
|
|
83
|
+
* // Validate has specific methods
|
|
84
|
+
* AbilityValidator.validate(ability, {
|
|
85
|
+
* expectedMethods: ['process', 'analyze']
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
static validate(ability: LoadedAbility, options?: ValidationOptions): void;
|
|
90
|
+
/**
|
|
91
|
+
* Validate expected methods exist
|
|
92
|
+
*
|
|
93
|
+
* Checks that all expected methods are present in ability.
|
|
94
|
+
* Optionally checks for unexpected extra methods.
|
|
95
|
+
*
|
|
96
|
+
* @param ability - Loaded ability
|
|
97
|
+
* @param expectedMethods - Methods that should exist
|
|
98
|
+
* @param availableMethods - Methods that actually exist
|
|
99
|
+
* @param allowAdditional - Whether to allow extra methods
|
|
100
|
+
*
|
|
101
|
+
* @throws {KadiError} If validation fails
|
|
102
|
+
*/
|
|
103
|
+
private static validateExpectedMethods;
|
|
104
|
+
/**
|
|
105
|
+
* Suggest similar method names (typo detection)
|
|
106
|
+
*
|
|
107
|
+
* Uses simple string similarity to suggest corrections.
|
|
108
|
+
*
|
|
109
|
+
* @param missingMethods - Methods not found
|
|
110
|
+
* @param availableMethods - Methods that exist
|
|
111
|
+
* @returns Array of suggestions
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* suggestSimilarMethods(['proces'], ['process', 'analyze'])
|
|
116
|
+
* // Returns: ['process'] (close match)
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
private static suggestSimilarMethods;
|
|
120
|
+
/**
|
|
121
|
+
* Check if two strings are similar (typo detection)
|
|
122
|
+
*
|
|
123
|
+
* Simple heuristic: strings are similar if:
|
|
124
|
+
* - Length difference ≤ 2
|
|
125
|
+
* - Share at least 70% of characters
|
|
126
|
+
*
|
|
127
|
+
* @param str1 - First string
|
|
128
|
+
* @param str2 - Second string
|
|
129
|
+
* @returns true if similar
|
|
130
|
+
*/
|
|
131
|
+
private static isSimilar;
|
|
132
|
+
/**
|
|
133
|
+
* Validate ability is connected
|
|
134
|
+
*
|
|
135
|
+
* Ensures ability transport is active before use.
|
|
136
|
+
*
|
|
137
|
+
* @param ability - Loaded ability
|
|
138
|
+
*
|
|
139
|
+
* @throws {KadiError} If not connected
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* AbilityValidator.validateConnected(ability);
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
static validateConnected(ability: LoadedAbility): void;
|
|
147
|
+
/**
|
|
148
|
+
* Extract method names from TypeScript interface type
|
|
149
|
+
*
|
|
150
|
+
* Helper to get expected methods from type definition.
|
|
151
|
+
* Uses TypeScript compiler API if available.
|
|
152
|
+
*
|
|
153
|
+
* This is a placeholder for future type-based validation.
|
|
154
|
+
*
|
|
155
|
+
* @template T - Interface type (marker for future implementation)
|
|
156
|
+
* @returns Array of method names
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* interface CalcAPI {
|
|
161
|
+
* add(): Promise<number>;
|
|
162
|
+
* subtract(): Promise<number>;
|
|
163
|
+
* }
|
|
164
|
+
*
|
|
165
|
+
* // Future: Extract methods from type
|
|
166
|
+
* const methods = AbilityValidator.extractMethodsFromType<CalcAPI>();
|
|
167
|
+
* // Would return: ['add', 'subtract']
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
static extractMethodsFromType<T>(): string[];
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=AbilityValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbilityValidator.d.ts","sourceRoot":"","sources":["../../src/abilities/AbilityValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAE3B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,gBAAgB;IAC3B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,QAAQ,CACb,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,iBAAsB,GAC9B,IAAI;IAkCP;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAmEtC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAmBpC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IAuBxB;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAiBtD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IAEH,MAAM,CAAC,sBAAsB,CAAC,CAAC,KAAK,MAAM,EAAE;CAO7C"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ability Validator
|
|
3
|
+
*
|
|
4
|
+
* Runtime validation to ensure loaded abilities meet expectations.
|
|
5
|
+
* Catches mismatches early with clear, actionable error messages.
|
|
6
|
+
*
|
|
7
|
+
* @module abilities/AbilityValidator
|
|
8
|
+
*/
|
|
9
|
+
import { KadiError, ErrorCode } from '../types/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Ability Validator
|
|
12
|
+
*
|
|
13
|
+
* Ensures loaded abilities are valid and meet expectations before
|
|
14
|
+
* returning them to developers.
|
|
15
|
+
*
|
|
16
|
+
* **Why Runtime Validation?**
|
|
17
|
+
*
|
|
18
|
+
* TypeScript provides compile-time types, but those can lie:
|
|
19
|
+
* ```typescript
|
|
20
|
+
* interface CalcAPI {
|
|
21
|
+
* add(): Promise<number>;
|
|
22
|
+
* }
|
|
23
|
+
* const calc = await client.load<CalcAPI>('calculator');
|
|
24
|
+
* // TypeScript happy, but what if ability doesn't have add()?
|
|
25
|
+
* await calc.add(); // Runtime error!
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* Runtime validation catches this early with helpful errors.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* // Basic validation - just check ability has methods
|
|
33
|
+
* AbilityValidator.validate(ability);
|
|
34
|
+
*
|
|
35
|
+
* // Validate specific methods
|
|
36
|
+
* AbilityValidator.validate(ability, {
|
|
37
|
+
* expectedMethods: ['add', 'subtract', 'multiply']
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export class AbilityValidator {
|
|
42
|
+
/**
|
|
43
|
+
* Validate ability meets expectations
|
|
44
|
+
*
|
|
45
|
+
* Checks:
|
|
46
|
+
* 1. Ability is properly initialized
|
|
47
|
+
* 2. Ability has methods (not empty)
|
|
48
|
+
* 3. Expected methods exist (if specified)
|
|
49
|
+
*
|
|
50
|
+
* @param ability - Loaded ability to validate
|
|
51
|
+
* @param options - Validation options
|
|
52
|
+
*
|
|
53
|
+
* @throws {KadiError} If validation fails
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* // Basic validation
|
|
58
|
+
* AbilityValidator.validate(ability);
|
|
59
|
+
*
|
|
60
|
+
* // Validate has specific methods
|
|
61
|
+
* AbilityValidator.validate(ability, {
|
|
62
|
+
* expectedMethods: ['process', 'analyze']
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
static validate(ability, options = {}) {
|
|
67
|
+
// Step 1: Get available methods from ability
|
|
68
|
+
const availableMethods = ability.__getMethods();
|
|
69
|
+
const abilityName = ability.__name;
|
|
70
|
+
const transport = ability.__transport;
|
|
71
|
+
// Step 2: Check ability has at least one method (unless disabled)
|
|
72
|
+
const requireMethods = options.requireMethods ?? true;
|
|
73
|
+
if (requireMethods && availableMethods.length === 0) {
|
|
74
|
+
throw new KadiError(`Ability '${abilityName}' has no methods`, ErrorCode.ABILITY_INVALID, 500, {
|
|
75
|
+
abilityName,
|
|
76
|
+
transport,
|
|
77
|
+
reason: 'Ability initialized but exposes no methods',
|
|
78
|
+
suggestion: 'Check ability implementation exports methods correctly',
|
|
79
|
+
hint: 'Ability should implement and expose at least one method'
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// Step 3: Validate expected methods if specified
|
|
83
|
+
if (options.expectedMethods && options.expectedMethods.length > 0) {
|
|
84
|
+
this.validateExpectedMethods(ability, options.expectedMethods, availableMethods, options.allowAdditional ?? true);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Validate expected methods exist
|
|
89
|
+
*
|
|
90
|
+
* Checks that all expected methods are present in ability.
|
|
91
|
+
* Optionally checks for unexpected extra methods.
|
|
92
|
+
*
|
|
93
|
+
* @param ability - Loaded ability
|
|
94
|
+
* @param expectedMethods - Methods that should exist
|
|
95
|
+
* @param availableMethods - Methods that actually exist
|
|
96
|
+
* @param allowAdditional - Whether to allow extra methods
|
|
97
|
+
*
|
|
98
|
+
* @throws {KadiError} If validation fails
|
|
99
|
+
*/
|
|
100
|
+
static validateExpectedMethods(ability, expectedMethods, availableMethods, allowAdditional) {
|
|
101
|
+
const abilityName = ability.__name;
|
|
102
|
+
const transport = ability.__transport;
|
|
103
|
+
// Step 1: Find missing methods
|
|
104
|
+
const missingMethods = expectedMethods.filter(method => !availableMethods.includes(method));
|
|
105
|
+
// Step 2: Check if any methods missing
|
|
106
|
+
if (missingMethods.length > 0) {
|
|
107
|
+
// Generate helpful error message
|
|
108
|
+
const suggestions = this.suggestSimilarMethods(missingMethods, availableMethods);
|
|
109
|
+
throw new KadiError(`Ability '${abilityName}' missing expected methods: ${missingMethods.join(', ')}`, ErrorCode.ABILITY_INVALID, 500, {
|
|
110
|
+
abilityName,
|
|
111
|
+
transport,
|
|
112
|
+
missingMethods,
|
|
113
|
+
availableMethods,
|
|
114
|
+
expectedMethods,
|
|
115
|
+
reason: 'Ability does not implement all expected methods',
|
|
116
|
+
suggestion: suggestions.length > 0
|
|
117
|
+
? `Did you mean: ${suggestions.join(', ')}?`
|
|
118
|
+
: `Available methods: ${availableMethods.join(', ')}`,
|
|
119
|
+
hint: 'Check ability version matches expected interface'
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// Step 3: Check for unexpected methods (if strict mode)
|
|
123
|
+
if (!allowAdditional) {
|
|
124
|
+
const unexpectedMethods = availableMethods.filter(method => !expectedMethods.includes(method));
|
|
125
|
+
if (unexpectedMethods.length > 0) {
|
|
126
|
+
throw new KadiError(`Ability '${abilityName}' has unexpected methods: ${unexpectedMethods.join(', ')}`, ErrorCode.ABILITY_INVALID, 500, {
|
|
127
|
+
abilityName,
|
|
128
|
+
transport,
|
|
129
|
+
unexpectedMethods,
|
|
130
|
+
expectedMethods,
|
|
131
|
+
availableMethods,
|
|
132
|
+
reason: 'Ability implements methods not in expected interface',
|
|
133
|
+
suggestion: 'Update expected interface or set allowAdditional: true',
|
|
134
|
+
hint: 'Strict validation prevents interface drift'
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Suggest similar method names (typo detection)
|
|
141
|
+
*
|
|
142
|
+
* Uses simple string similarity to suggest corrections.
|
|
143
|
+
*
|
|
144
|
+
* @param missingMethods - Methods not found
|
|
145
|
+
* @param availableMethods - Methods that exist
|
|
146
|
+
* @returns Array of suggestions
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* suggestSimilarMethods(['proces'], ['process', 'analyze'])
|
|
151
|
+
* // Returns: ['process'] (close match)
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
static suggestSimilarMethods(missingMethods, availableMethods) {
|
|
155
|
+
const suggestions = [];
|
|
156
|
+
// For each missing method, find similar available methods
|
|
157
|
+
for (const missing of missingMethods) {
|
|
158
|
+
for (const available of availableMethods) {
|
|
159
|
+
// Simple similarity check: Levenshtein distance
|
|
160
|
+
if (this.isSimilar(missing, available)) {
|
|
161
|
+
suggestions.push(available);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return [...new Set(suggestions)]; // Remove duplicates
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Check if two strings are similar (typo detection)
|
|
169
|
+
*
|
|
170
|
+
* Simple heuristic: strings are similar if:
|
|
171
|
+
* - Length difference ≤ 2
|
|
172
|
+
* - Share at least 70% of characters
|
|
173
|
+
*
|
|
174
|
+
* @param str1 - First string
|
|
175
|
+
* @param str2 - Second string
|
|
176
|
+
* @returns true if similar
|
|
177
|
+
*/
|
|
178
|
+
static isSimilar(str1, str2) {
|
|
179
|
+
// Quick check: length difference
|
|
180
|
+
const lengthDiff = Math.abs(str1.length - str2.length);
|
|
181
|
+
if (lengthDiff > 2) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
// Count matching characters
|
|
185
|
+
const s1 = str1.toLowerCase();
|
|
186
|
+
const s2 = str2.toLowerCase();
|
|
187
|
+
let matches = 0;
|
|
188
|
+
for (let i = 0; i < Math.min(s1.length, s2.length); i++) {
|
|
189
|
+
if (s1[i] === s2[i]) {
|
|
190
|
+
matches++;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Similar if >70% characters match
|
|
194
|
+
const similarity = matches / Math.max(s1.length, s2.length);
|
|
195
|
+
return similarity >= 0.7;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Validate ability is connected
|
|
199
|
+
*
|
|
200
|
+
* Ensures ability transport is active before use.
|
|
201
|
+
*
|
|
202
|
+
* @param ability - Loaded ability
|
|
203
|
+
*
|
|
204
|
+
* @throws {KadiError} If not connected
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```typescript
|
|
208
|
+
* AbilityValidator.validateConnected(ability);
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
static validateConnected(ability) {
|
|
212
|
+
if (!ability.__isConnected()) {
|
|
213
|
+
throw new KadiError(`Ability '${ability.__name}' is not connected`, ErrorCode.ABILITY_NOT_CONNECTED, 503, {
|
|
214
|
+
abilityName: ability.__name,
|
|
215
|
+
transport: ability.__transport,
|
|
216
|
+
reason: 'Ability transport disconnected or never initialized',
|
|
217
|
+
suggestion: 'Reload ability: await client.load(...)',
|
|
218
|
+
hint: 'Check if ability was disconnected or connection lost'
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Extract method names from TypeScript interface type
|
|
224
|
+
*
|
|
225
|
+
* Helper to get expected methods from type definition.
|
|
226
|
+
* Uses TypeScript compiler API if available.
|
|
227
|
+
*
|
|
228
|
+
* This is a placeholder for future type-based validation.
|
|
229
|
+
*
|
|
230
|
+
* @template T - Interface type (marker for future implementation)
|
|
231
|
+
* @returns Array of method names
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```typescript
|
|
235
|
+
* interface CalcAPI {
|
|
236
|
+
* add(): Promise<number>;
|
|
237
|
+
* subtract(): Promise<number>;
|
|
238
|
+
* }
|
|
239
|
+
*
|
|
240
|
+
* // Future: Extract methods from type
|
|
241
|
+
* const methods = AbilityValidator.extractMethodsFromType<CalcAPI>();
|
|
242
|
+
* // Would return: ['add', 'subtract']
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
// @ts-expect-error - T is placeholder for future type introspection feature
|
|
246
|
+
static extractMethodsFromType() {
|
|
247
|
+
// TODO: Implement type introspection
|
|
248
|
+
// This would require TypeScript compiler API at runtime
|
|
249
|
+
// For now, developers must explicitly list expected methods
|
|
250
|
+
return [];
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=AbilityValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbilityValidator.js","sourceRoot":"","sources":["../../src/abilities/AbilityValidator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abilities Module
|
|
3
|
+
*
|
|
4
|
+
* Complete ability loading system with excellent developer experience:
|
|
5
|
+
* - Explicit transport selection
|
|
6
|
+
* - Intelligent caching
|
|
7
|
+
* - Runtime validation
|
|
8
|
+
* - Type-safe options
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { AbilityLoader } from '@kadi.build/core/abilities';
|
|
13
|
+
*
|
|
14
|
+
* const loader = new AbilityLoader();
|
|
15
|
+
* const ability = await loader.load('calculator', 'broker', {}, brokerClient);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export { AbilityLoader } from './AbilityLoader.js';
|
|
19
|
+
export { AbilityProxy } from './AbilityProxy.js';
|
|
20
|
+
export { AbilityCache } from './AbilityCache.js';
|
|
21
|
+
export { AbilityValidator } from './AbilityValidator.js';
|
|
22
|
+
export type { LoadedAbility, AbilityFramework, DynamicMethods, TransportType } from './AbilityProxy.js';
|
|
23
|
+
export type { AgentJson, LoadOptions, BrokerLoadOptions, NativeLoadOptions, StdioLoadOptions, TransportType as LoadTransportType } from './types.js';
|
|
24
|
+
export type { CacheKey } from './AbilityCache.js';
|
|
25
|
+
export type { ValidationOptions } from './AbilityValidator.js';
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/abilities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,aAAa,EACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,IAAI,iBAAiB,EACnC,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abilities Module
|
|
3
|
+
*
|
|
4
|
+
* Complete ability loading system with excellent developer experience:
|
|
5
|
+
* - Explicit transport selection
|
|
6
|
+
* - Intelligent caching
|
|
7
|
+
* - Runtime validation
|
|
8
|
+
* - Type-safe options
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { AbilityLoader } from '@kadi.build/core/abilities';
|
|
13
|
+
*
|
|
14
|
+
* const loader = new AbilityLoader();
|
|
15
|
+
* const ability = await loader.load('calculator', 'broker', {}, brokerClient);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
// Core classes
|
|
19
|
+
export { AbilityLoader } from './AbilityLoader.js';
|
|
20
|
+
export { AbilityProxy } from './AbilityProxy.js';
|
|
21
|
+
export { AbilityCache } from './AbilityCache.js';
|
|
22
|
+
export { AbilityValidator } from './AbilityValidator.js';
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/abilities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAe;AACf,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|