@kadi.build/core 0.12.0 → 0.14.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/README.md +143 -0
- package/agent.json +1 -1
- package/dist/client.d.ts +19 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +48 -0
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +113 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +271 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +50 -0
- package/src/config.ts +368 -0
- package/src/index.ts +4 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader for KADI agents and abilities.
|
|
3
|
+
*
|
|
4
|
+
* Provides standardized config.yml discovery with a 2-tier fallback:
|
|
5
|
+
* 1. **Project-level** — walk up from startDir looking for config.yml
|
|
6
|
+
* 2. **Global-level** — ~/.kadi/config.yml (shared KADI infrastructure settings)
|
|
7
|
+
*
|
|
8
|
+
* Resolution order per-field (highest-priority first):
|
|
9
|
+
* 1. Environment variables (PREFIX_KEY)
|
|
10
|
+
* 2. Project config.yml section
|
|
11
|
+
* 3. Global config.yml section (~/.kadi/config.yml)
|
|
12
|
+
* 4. Built-in defaults
|
|
13
|
+
*
|
|
14
|
+
* Secrets (API keys, tokens) should NEVER appear in config.yml.
|
|
15
|
+
* Use secret-ability / kadi-secret for credentials.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { loadConfig } from '@kadi.build/core';
|
|
20
|
+
*
|
|
21
|
+
* const { config, configPath, source } = loadConfig({
|
|
22
|
+
* section: 'memory',
|
|
23
|
+
* envPrefix: 'MEMORY',
|
|
24
|
+
* defaults: { database: 'kadi_memory', embedding_model: 'text-embedding-3-small' },
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* TypeScript equivalent of: kadi-core-py/src/kadi/config.py
|
|
29
|
+
*/
|
|
30
|
+
/** How the config file was discovered. */
|
|
31
|
+
export type ConfigSource = 'project' | 'global' | 'default';
|
|
32
|
+
/** Options for {@link loadConfig}. */
|
|
33
|
+
export interface LoadConfigOptions {
|
|
34
|
+
/**
|
|
35
|
+
* YAML section key to extract (e.g. `'tunnel'`, `'memory'`, `'kadi_agent'`).
|
|
36
|
+
* The top-level key in config.yml whose value becomes the config object.
|
|
37
|
+
*/
|
|
38
|
+
section: string;
|
|
39
|
+
/**
|
|
40
|
+
* Directory to start the upward walk from.
|
|
41
|
+
* @default process.cwd()
|
|
42
|
+
*/
|
|
43
|
+
startDir?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Config filename to search for.
|
|
46
|
+
* @default 'config.yml'
|
|
47
|
+
*/
|
|
48
|
+
filename?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Environment variable prefix for automatic overrides.
|
|
51
|
+
*
|
|
52
|
+
* When set, loadConfig will scan `process.env` for keys starting with
|
|
53
|
+
* `PREFIX_` and merge them into the config (highest priority).
|
|
54
|
+
*
|
|
55
|
+
* Mapping: `PREFIX_KEY_NAME` → config field `key_name` (lowercased).
|
|
56
|
+
*
|
|
57
|
+
* @example envPrefix: 'MEMORY' → MEMORY_DATABASE overrides config.database
|
|
58
|
+
*/
|
|
59
|
+
envPrefix?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Built-in defaults (lowest priority).
|
|
62
|
+
* These are used when neither env vars nor config.yml provide a value.
|
|
63
|
+
*/
|
|
64
|
+
defaults?: Record<string, unknown>;
|
|
65
|
+
}
|
|
66
|
+
/** Result of {@link loadConfig}. */
|
|
67
|
+
export interface ConfigResult<T = Record<string, unknown>> {
|
|
68
|
+
/** Merged config object: env > project config.yml > global config.yml > defaults. */
|
|
69
|
+
config: T;
|
|
70
|
+
/** Absolute path to the config.yml that was loaded, or null if none found. */
|
|
71
|
+
configPath: string | null;
|
|
72
|
+
/** Where the primary config was found. */
|
|
73
|
+
source: ConfigSource;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Walk up the directory tree looking for a file.
|
|
77
|
+
*
|
|
78
|
+
* @param filename - File to search for (default: `'config.yml'`)
|
|
79
|
+
* @param startDir - Directory to start from (default: `process.cwd()`)
|
|
80
|
+
* @returns Absolute path if found, `null` otherwise.
|
|
81
|
+
*/
|
|
82
|
+
export declare function findConfigFile(filename?: string, startDir?: string): string | null;
|
|
83
|
+
/**
|
|
84
|
+
* Find the global KADI config file.
|
|
85
|
+
*
|
|
86
|
+
* @param filename - Config filename (default: `'config.yml'`)
|
|
87
|
+
* @returns Absolute path to `~/.kadi/<filename>` if it exists, `null` otherwise.
|
|
88
|
+
*/
|
|
89
|
+
export declare function findGlobalConfigFile(filename?: string): string | null;
|
|
90
|
+
/**
|
|
91
|
+
* Load configuration for a KADI agent or ability.
|
|
92
|
+
*
|
|
93
|
+
* Resolution order per-field (highest-priority first):
|
|
94
|
+
* 1. Environment variables (`envPrefix` + `_KEY`)
|
|
95
|
+
* 2. Project `config.yml` section (walk-up from startDir)
|
|
96
|
+
* 3. Global `~/.kadi/config.yml` section
|
|
97
|
+
* 4. Built-in `defaults`
|
|
98
|
+
*
|
|
99
|
+
* @typeParam T - The shape of the merged config object.
|
|
100
|
+
* @param options - Configuration loading options.
|
|
101
|
+
* @returns Merged config with metadata about where it was found.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const { config } = loadConfig<TunnelConfig>({
|
|
106
|
+
* section: 'tunnel',
|
|
107
|
+
* envPrefix: 'KADI_TUNNEL',
|
|
108
|
+
* defaults: { default_service: 'kadi', server_port: 7000 },
|
|
109
|
+
* });
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export declare function loadConfig<T = Record<string, unknown>>(options: LoadConfigOptions): ConfigResult<T>;
|
|
113
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAuDH,0CAA0C;AAC1C,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE5D,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,oCAAoC;AACpC,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACvD,qFAAqF;IACrF,MAAM,EAAE,CAAC,CAAC;IACV,8EAA8E;IAC9E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,0CAA0C;IAC1C,MAAM,EAAE,YAAY,CAAC;CACtB;AAMD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,GAAE,MAAyB,EACnC,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAmBf;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,GAAE,MAAyB,GAClC,MAAM,GAAG,IAAI,CAUf;AAgFD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpD,OAAO,EAAE,iBAAiB,GACzB,YAAY,CAAC,CAAC,CAAC,CAsDjB"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader for KADI agents and abilities.
|
|
3
|
+
*
|
|
4
|
+
* Provides standardized config.yml discovery with a 2-tier fallback:
|
|
5
|
+
* 1. **Project-level** — walk up from startDir looking for config.yml
|
|
6
|
+
* 2. **Global-level** — ~/.kadi/config.yml (shared KADI infrastructure settings)
|
|
7
|
+
*
|
|
8
|
+
* Resolution order per-field (highest-priority first):
|
|
9
|
+
* 1. Environment variables (PREFIX_KEY)
|
|
10
|
+
* 2. Project config.yml section
|
|
11
|
+
* 3. Global config.yml section (~/.kadi/config.yml)
|
|
12
|
+
* 4. Built-in defaults
|
|
13
|
+
*
|
|
14
|
+
* Secrets (API keys, tokens) should NEVER appear in config.yml.
|
|
15
|
+
* Use secret-ability / kadi-secret for credentials.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { loadConfig } from '@kadi.build/core';
|
|
20
|
+
*
|
|
21
|
+
* const { config, configPath, source } = loadConfig({
|
|
22
|
+
* section: 'memory',
|
|
23
|
+
* envPrefix: 'MEMORY',
|
|
24
|
+
* defaults: { database: 'kadi_memory', embedding_model: 'text-embedding-3-small' },
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* TypeScript equivalent of: kadi-core-py/src/kadi/config.py
|
|
29
|
+
*/
|
|
30
|
+
import * as fs from 'node:fs';
|
|
31
|
+
import * as path from 'node:path';
|
|
32
|
+
import * as os from 'node:os';
|
|
33
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
34
|
+
// YAML import — optional runtime dependency
|
|
35
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
36
|
+
/**
|
|
37
|
+
* We lazy-import js-yaml so that kadi-core does NOT require it as a hard
|
|
38
|
+
* dependency. Consumers that use loadConfig() need js-yaml installed;
|
|
39
|
+
* everything else in kadi-core works without it.
|
|
40
|
+
*
|
|
41
|
+
* In practice every KADI agent/ability already has js-yaml, so this is
|
|
42
|
+
* a formality rather than a real constraint.
|
|
43
|
+
*/
|
|
44
|
+
let yaml = null;
|
|
45
|
+
let yamlResolved = false;
|
|
46
|
+
function requireYaml() {
|
|
47
|
+
if (!yamlResolved) {
|
|
48
|
+
yamlResolved = true;
|
|
49
|
+
try {
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
51
|
+
yaml = require('js-yaml');
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
try {
|
|
55
|
+
// ESM fallback — createRequire for pure-ESM environments
|
|
56
|
+
const { createRequire } = require('node:module');
|
|
57
|
+
const localRequire = createRequire(process.cwd() + '/');
|
|
58
|
+
yaml = localRequire('js-yaml');
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
yaml = null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return yaml;
|
|
66
|
+
}
|
|
67
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
68
|
+
// Constants
|
|
69
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
70
|
+
/** Default config filename. */
|
|
71
|
+
const DEFAULT_FILENAME = 'config.yml';
|
|
72
|
+
/** Global KADI config directory. */
|
|
73
|
+
const GLOBAL_KADI_DIR = path.join(os.homedir(), '.kadi');
|
|
74
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
75
|
+
// File discovery
|
|
76
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
77
|
+
/**
|
|
78
|
+
* Walk up the directory tree looking for a file.
|
|
79
|
+
*
|
|
80
|
+
* @param filename - File to search for (default: `'config.yml'`)
|
|
81
|
+
* @param startDir - Directory to start from (default: `process.cwd()`)
|
|
82
|
+
* @returns Absolute path if found, `null` otherwise.
|
|
83
|
+
*/
|
|
84
|
+
export function findConfigFile(filename = DEFAULT_FILENAME, startDir) {
|
|
85
|
+
let dir = path.resolve(startDir ?? process.cwd());
|
|
86
|
+
// eslint-disable-next-line no-constant-condition
|
|
87
|
+
while (true) {
|
|
88
|
+
const candidate = path.join(dir, filename);
|
|
89
|
+
try {
|
|
90
|
+
if (fs.statSync(candidate).isFile()) {
|
|
91
|
+
return candidate;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Not found, keep walking
|
|
96
|
+
}
|
|
97
|
+
const parent = path.dirname(dir);
|
|
98
|
+
if (parent === dir)
|
|
99
|
+
break; // Filesystem root
|
|
100
|
+
dir = parent;
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Find the global KADI config file.
|
|
106
|
+
*
|
|
107
|
+
* @param filename - Config filename (default: `'config.yml'`)
|
|
108
|
+
* @returns Absolute path to `~/.kadi/<filename>` if it exists, `null` otherwise.
|
|
109
|
+
*/
|
|
110
|
+
export function findGlobalConfigFile(filename = DEFAULT_FILENAME) {
|
|
111
|
+
const globalPath = path.join(GLOBAL_KADI_DIR, filename);
|
|
112
|
+
try {
|
|
113
|
+
if (fs.statSync(globalPath).isFile()) {
|
|
114
|
+
return globalPath;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// Not found
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
123
|
+
// Section extraction
|
|
124
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
125
|
+
/**
|
|
126
|
+
* Parse a YAML file and extract a top-level section.
|
|
127
|
+
*/
|
|
128
|
+
function readSection(filePath, section) {
|
|
129
|
+
const lib = requireYaml();
|
|
130
|
+
if (!lib)
|
|
131
|
+
return {};
|
|
132
|
+
try {
|
|
133
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
134
|
+
const parsed = lib.load(content);
|
|
135
|
+
if (!parsed || typeof parsed !== 'object')
|
|
136
|
+
return {};
|
|
137
|
+
const sectionData = parsed[section];
|
|
138
|
+
if (!sectionData || typeof sectionData !== 'object')
|
|
139
|
+
return {};
|
|
140
|
+
return sectionData;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return {};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
147
|
+
// Environment variable overlay
|
|
148
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
149
|
+
/**
|
|
150
|
+
* Build an overrides object from environment variables matching a prefix.
|
|
151
|
+
*
|
|
152
|
+
* `PREFIX_KEY_NAME=value` → `{ key_name: value }`
|
|
153
|
+
*
|
|
154
|
+
* Numeric strings are auto-coerced to numbers.
|
|
155
|
+
* `'true'` / `'false'` are coerced to booleans.
|
|
156
|
+
*/
|
|
157
|
+
function envOverrides(prefix, knownKeys) {
|
|
158
|
+
const result = {};
|
|
159
|
+
const prefixUpper = prefix.toUpperCase() + '_';
|
|
160
|
+
for (const [envKey, envVal] of Object.entries(process.env)) {
|
|
161
|
+
if (!envKey.startsWith(prefixUpper) || envVal === undefined)
|
|
162
|
+
continue;
|
|
163
|
+
const configKey = envKey.slice(prefixUpper.length).toLowerCase();
|
|
164
|
+
// Skip if we have a known-keys set and this key isn't in it
|
|
165
|
+
if (knownKeys && !knownKeys.has(configKey))
|
|
166
|
+
continue;
|
|
167
|
+
result[configKey] = coerce(envVal);
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Coerce a string environment value to its natural JS type.
|
|
173
|
+
*/
|
|
174
|
+
function coerce(value) {
|
|
175
|
+
if (value === 'true')
|
|
176
|
+
return true;
|
|
177
|
+
if (value === 'false')
|
|
178
|
+
return false;
|
|
179
|
+
if (value === '')
|
|
180
|
+
return value;
|
|
181
|
+
// Attempt numeric coercion only for things that look numeric
|
|
182
|
+
const num = Number(value);
|
|
183
|
+
if (!Number.isNaN(num) && value.trim() !== '')
|
|
184
|
+
return num;
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
187
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
188
|
+
// Main API
|
|
189
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
190
|
+
/**
|
|
191
|
+
* Load configuration for a KADI agent or ability.
|
|
192
|
+
*
|
|
193
|
+
* Resolution order per-field (highest-priority first):
|
|
194
|
+
* 1. Environment variables (`envPrefix` + `_KEY`)
|
|
195
|
+
* 2. Project `config.yml` section (walk-up from startDir)
|
|
196
|
+
* 3. Global `~/.kadi/config.yml` section
|
|
197
|
+
* 4. Built-in `defaults`
|
|
198
|
+
*
|
|
199
|
+
* @typeParam T - The shape of the merged config object.
|
|
200
|
+
* @param options - Configuration loading options.
|
|
201
|
+
* @returns Merged config with metadata about where it was found.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```typescript
|
|
205
|
+
* const { config } = loadConfig<TunnelConfig>({
|
|
206
|
+
* section: 'tunnel',
|
|
207
|
+
* envPrefix: 'KADI_TUNNEL',
|
|
208
|
+
* defaults: { default_service: 'kadi', server_port: 7000 },
|
|
209
|
+
* });
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
export function loadConfig(options) {
|
|
213
|
+
const { section, startDir, filename = DEFAULT_FILENAME, envPrefix, defaults = {}, } = options;
|
|
214
|
+
// ── Layer 4: Defaults ──────────────────────────────────────────────
|
|
215
|
+
let merged = { ...defaults };
|
|
216
|
+
// ── Layer 3: Global config.yml (~/.kadi/config.yml) ────────────────
|
|
217
|
+
let configPath = null;
|
|
218
|
+
let source = 'default';
|
|
219
|
+
const globalPath = findGlobalConfigFile(filename);
|
|
220
|
+
if (globalPath) {
|
|
221
|
+
const globalSection = readSection(globalPath, section);
|
|
222
|
+
if (Object.keys(globalSection).length > 0) {
|
|
223
|
+
merged = shallowMerge(merged, globalSection);
|
|
224
|
+
configPath = globalPath;
|
|
225
|
+
source = 'global';
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// ── Layer 2: Project config.yml (walk-up) ──────────────────────────
|
|
229
|
+
const projectPath = findConfigFile(filename, startDir);
|
|
230
|
+
if (projectPath) {
|
|
231
|
+
// Only use project config if it's not the same file as global
|
|
232
|
+
const isDistinct = !globalPath || path.resolve(projectPath) !== path.resolve(globalPath);
|
|
233
|
+
if (isDistinct) {
|
|
234
|
+
const projectSection = readSection(projectPath, section);
|
|
235
|
+
if (Object.keys(projectSection).length > 0) {
|
|
236
|
+
merged = shallowMerge(merged, projectSection);
|
|
237
|
+
configPath = projectPath;
|
|
238
|
+
source = 'project';
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// ── Layer 1: Environment variables (highest priority) ──────────────
|
|
243
|
+
if (envPrefix) {
|
|
244
|
+
const env = envOverrides(envPrefix);
|
|
245
|
+
if (Object.keys(env).length > 0) {
|
|
246
|
+
merged = shallowMerge(merged, env);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
config: merged,
|
|
251
|
+
configPath,
|
|
252
|
+
source,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
256
|
+
// Helpers
|
|
257
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
258
|
+
/**
|
|
259
|
+
* Shallow merge — source keys overwrite target keys.
|
|
260
|
+
* Only copies defined (non-undefined) values.
|
|
261
|
+
*/
|
|
262
|
+
function shallowMerge(target, source) {
|
|
263
|
+
const result = { ...target };
|
|
264
|
+
for (const [key, val] of Object.entries(source)) {
|
|
265
|
+
if (val !== undefined) {
|
|
266
|
+
result[key] = val;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ export type { ClientConfig, BrokerEntry, ResolvedConfig, ToolDefinition, BrokerT
|
|
|
32
32
|
export { AgentJsonManager } from './agent-json.js';
|
|
33
33
|
export { ProcessManager, ManagedProcess } from './process-manager.js';
|
|
34
34
|
export { getByPath, setByPath, deleteByPath, deepMerge } from './utils.js';
|
|
35
|
+
export { loadConfig, findConfigFile, findGlobalConfigFile } from './config.js';
|
|
36
|
+
export type { LoadConfigOptions, ConfigResult, ConfigSource } from './config.js';
|
|
35
37
|
export { StdioMessageReader, StdioMessageWriter } from './stdio-framing.js';
|
|
36
38
|
export { zodToJsonSchema, isZodSchema } from './zod.js';
|
|
37
39
|
export { findProjectRoot, readLockFile, findAbilityEntry, resolveAbilityPath, resolveAbilityEntry, getInstalledAbilityNames, } from './lockfile.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3D,YAAY,EAEV,YAAY,EACZ,WAAW,EACX,cAAc,EAGd,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,UAAU,EACV,cAAc,EAGd,aAAa,EACb,aAAa,EACb,aAAa,EACb,YAAY,EAGZ,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EAGnB,WAAW,EACX,YAAY,EACZ,cAAc,EACd,iBAAiB,EAGjB,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,WAAW,EAGX,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,cAAc,EAGd,aAAa,EACb,gBAAgB,EAGhB,cAAc,EAGd,SAAS,EACT,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,WAAW,EACX,cAAc,EAGd,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG3E,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG5E,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGxD,OAAO,EACL,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGrE,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAG1C,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AACjF,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3D,YAAY,EAEV,YAAY,EACZ,WAAW,EACX,cAAc,EAGd,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,UAAU,EACV,cAAc,EAGd,aAAa,EACb,aAAa,EACb,aAAa,EACb,YAAY,EAGZ,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EAGnB,WAAW,EACX,YAAY,EACZ,cAAc,EACd,iBAAiB,EAGjB,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,WAAW,EAGX,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,cAAc,EAGd,aAAa,EACb,gBAAgB,EAGhB,cAAc,EAGd,SAAS,EACT,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,WAAW,EACX,cAAc,EAGd,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG3E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC/E,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGjF,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG5E,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGxD,OAAO,EACL,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGrE,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAG1C,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AACjF,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,8 @@ export { AgentJsonManager } from './agent-json.js';
|
|
|
36
36
|
export { ProcessManager, ManagedProcess } from './process-manager.js';
|
|
37
37
|
// Dot-path utilities
|
|
38
38
|
export { getByPath, setByPath, deleteByPath, deepMerge } from './utils.js';
|
|
39
|
+
// Config loader (walk-up config.yml + ~/.kadi/ global fallback)
|
|
40
|
+
export { loadConfig, findConfigFile, findGlobalConfigFile } from './config.js';
|
|
39
41
|
// Stdio framing (for advanced use cases — building custom bridge protocols)
|
|
40
42
|
export { StdioMessageReader, StdioMessageWriter } from './stdio-framing.js';
|
|
41
43
|
// Zod utilities
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,uCAAuC;AACvC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAiFxC,qBAAqB;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtE,qBAAqB;AACrB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE3E,4EAA4E;AAC5E,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE5E,gBAAgB;AAChB,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAExD,sBAAsB;AACtB,OAAO,EACL,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AAEvB,sCAAsC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAG7D,4BAA4B;AAC5B,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,kDAAkD;AAClD,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,uCAAuC;AACvC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAiFxC,qBAAqB;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtE,qBAAqB;AACrB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE3E,gEAAgE;AAChE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAG/E,4EAA4E;AAC5E,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE5E,gBAAgB;AAChB,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAExD,sBAAsB;AACtB,OAAO,EACL,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AAEvB,sCAAsC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAG7D,4BAA4B;AAC5B,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,kDAAkD;AAClD,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC"}
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -206,6 +206,9 @@ export class KadiClient {
|
|
|
206
206
|
/** Registered disconnect hooks */
|
|
207
207
|
private readonly disconnectHooks: Array<() => Promise<void>> = [];
|
|
208
208
|
|
|
209
|
+
/** Registered reconnect hooks */
|
|
210
|
+
private readonly reconnectHooks: Array<(brokerName: string) => void | Promise<void>> = [];
|
|
211
|
+
|
|
209
212
|
/** Lazy-initialized AgentJsonManager */
|
|
210
213
|
private _agentJson: AgentJsonManager | null = null;
|
|
211
214
|
|
|
@@ -1698,9 +1701,36 @@ export class KadiClient {
|
|
|
1698
1701
|
// Finalize connection (heartbeat + status)
|
|
1699
1702
|
this.finalizeConnection(state);
|
|
1700
1703
|
|
|
1704
|
+
// Re-subscribe event patterns that were active before disconnect.
|
|
1705
|
+
// cleanupBroker() cleared subscribedPatterns but preserved eventHandlers,
|
|
1706
|
+
// so we replay broker-side subscriptions for every pattern that still has handlers.
|
|
1707
|
+
if (state.eventHandlers.size > 0) {
|
|
1708
|
+
const patterns = [...state.eventHandlers.keys()];
|
|
1709
|
+
console.error(`[KADI] Re-subscribing ${patterns.length} event pattern(s) on broker "${state.name}"`);
|
|
1710
|
+
for (const pattern of patterns) {
|
|
1711
|
+
try {
|
|
1712
|
+
await this.sendRequest(state, protocol.eventSubscribe(this.nextRequestId++, pattern));
|
|
1713
|
+
state.subscribedPatterns.add(pattern);
|
|
1714
|
+
} catch (err) {
|
|
1715
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1716
|
+
console.error(`[KADI] Failed to re-subscribe "${pattern}" on broker "${state.name}": ${msg}`);
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1701
1721
|
// Success!
|
|
1702
1722
|
console.error(`[KADI] Reconnected to broker "${state.name}" after ${state.reconnectAttempts} attempts`);
|
|
1703
1723
|
state.reconnectAttempts = 0;
|
|
1724
|
+
|
|
1725
|
+
// Fire reconnect hooks (best-effort, don't let a failing hook break reconnect)
|
|
1726
|
+
for (const hook of this.reconnectHooks) {
|
|
1727
|
+
try {
|
|
1728
|
+
await hook(state.name);
|
|
1729
|
+
} catch (err) {
|
|
1730
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1731
|
+
console.error(`[KADI] Reconnect hook error for broker "${state.name}": ${msg}`);
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1704
1734
|
} catch (error) {
|
|
1705
1735
|
// Log the error and try again
|
|
1706
1736
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1722,6 +1752,26 @@ export class KadiClient {
|
|
|
1722
1752
|
this.disconnectHooks.push(hook);
|
|
1723
1753
|
}
|
|
1724
1754
|
|
|
1755
|
+
/**
|
|
1756
|
+
* Register a hook to run after a successful broker reconnection.
|
|
1757
|
+
*
|
|
1758
|
+
* Event subscriptions are automatically re-established on reconnect,
|
|
1759
|
+
* so most agents won't need this. Use it for additional recovery logic:
|
|
1760
|
+
* re-fetching state, logging, sending a "I'm back" message, etc.
|
|
1761
|
+
*
|
|
1762
|
+
* @param hook - Called with the broker name after each successful reconnect.
|
|
1763
|
+
*
|
|
1764
|
+
* @example
|
|
1765
|
+
* ```typescript
|
|
1766
|
+
* client.onReconnect(async (brokerName) => {
|
|
1767
|
+
* console.log(`Reconnected to ${brokerName} — re-initializing state`);
|
|
1768
|
+
* });
|
|
1769
|
+
* ```
|
|
1770
|
+
*/
|
|
1771
|
+
onReconnect(hook: (brokerName: string) => void | Promise<void>): void {
|
|
1772
|
+
this.reconnectHooks.push(hook);
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1725
1775
|
/**
|
|
1726
1776
|
* Disconnect from broker(s) and run registered cleanup hooks.
|
|
1727
1777
|
*
|