@telora/daemon-core 0.2.5
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/dist/activity-tracker.d.ts +69 -0
- package/dist/activity-tracker.d.ts.map +1 -0
- package/dist/activity-tracker.js +155 -0
- package/dist/activity-tracker.js.map +1 -0
- package/dist/api-client.d.ts +94 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +145 -0
- package/dist/api-client.js.map +1 -0
- package/dist/config.d.ts +117 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +348 -0
- package/dist/config.js.map +1 -0
- package/dist/engine.d.ts +120 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +18 -0
- package/dist/engine.js.map +1 -0
- package/dist/escalation-types.d.ts +31 -0
- package/dist/escalation-types.d.ts.map +1 -0
- package/dist/escalation-types.js +24 -0
- package/dist/escalation-types.js.map +1 -0
- package/dist/event-logger.d.ts +13 -0
- package/dist/event-logger.d.ts.map +1 -0
- package/dist/event-logger.js +82 -0
- package/dist/event-logger.js.map +1 -0
- package/dist/git.d.ts +39 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +72 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle.d.ts +104 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +192 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/log-manager.d.ts +83 -0
- package/dist/log-manager.d.ts.map +1 -0
- package/dist/log-manager.js +217 -0
- package/dist/log-manager.js.map +1 -0
- package/dist/otel-env.d.ts +29 -0
- package/dist/otel-env.d.ts.map +1 -0
- package/dist/otel-env.js +44 -0
- package/dist/otel-env.js.map +1 -0
- package/dist/resilience.d.ts +127 -0
- package/dist/resilience.d.ts.map +1 -0
- package/dist/resilience.js +300 -0
- package/dist/resilience.js.map +1 -0
- package/dist/resource-governor.d.ts +83 -0
- package/dist/resource-governor.d.ts.map +1 -0
- package/dist/resource-governor.js +184 -0
- package/dist/resource-governor.js.map +1 -0
- package/dist/spawn.d.ts +72 -0
- package/dist/spawn.d.ts.map +1 -0
- package/dist/spawn.js +82 -0
- package/dist/spawn.js.map +1 -0
- package/dist/stream-json.d.ts +885 -0
- package/dist/stream-json.d.ts.map +1 -0
- package/dist/stream-json.js +298 -0
- package/dist/stream-json.js.map +1 -0
- package/dist/token-usage.d.ts +67 -0
- package/dist/token-usage.d.ts.map +1 -0
- package/dist/token-usage.js +150 -0
- package/dist/token-usage.js.map +1 -0
- package/dist/transforms.d.ts +64 -0
- package/dist/transforms.d.ts.map +1 -0
- package/dist/transforms.js +78 -0
- package/dist/transforms.js.map +1 -0
- package/dist/unified-config.d.ts +62 -0
- package/dist/unified-config.d.ts.map +1 -0
- package/dist/unified-config.js +155 -0
- package/dist/unified-config.js.map +1 -0
- package/dist/workflow-types.d.ts +202 -0
- package/dist/workflow-types.d.ts.map +1 -0
- package/dist/workflow-types.js +15 -0
- package/dist/workflow-types.js.map +1 -0
- package/dist/worktree.d.ts +92 -0
- package/dist/worktree.d.ts.map +1 -0
- package/dist/worktree.js +221 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +57 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared configuration infrastructure for Telora daemon and factory engines.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - BaseConfig interface with fields common to both DaemonConfig and FactoryConfig
|
|
6
|
+
* - Generic config file loader (JSON from disk)
|
|
7
|
+
* - Base config resolver (env vars over file config)
|
|
8
|
+
* - Base config validator (collects errors without throwing)
|
|
9
|
+
*
|
|
10
|
+
* Each engine imports these and layers its own fields on top.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
13
|
+
import { resolve, dirname, basename } from 'node:path';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Constants
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/** Regex for UUID v1-v8 (loose check). */
|
|
19
|
+
export const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20
|
+
/**
|
|
21
|
+
* Derive a short human-readable label for a product entry.
|
|
22
|
+
* Uses the basename of the product's repoPath (e.g., "/home/user/repos/telora" → "telora").
|
|
23
|
+
* Falls back to an 8-char ID slice if repoPath is empty.
|
|
24
|
+
*/
|
|
25
|
+
export function productLabel(product) {
|
|
26
|
+
if (product.repoPath) {
|
|
27
|
+
const name = basename(product.repoPath);
|
|
28
|
+
if (name && name !== '.')
|
|
29
|
+
return name;
|
|
30
|
+
}
|
|
31
|
+
return product.id.slice(0, 8);
|
|
32
|
+
}
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Config file loader
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
/**
|
|
37
|
+
* Load a JSON config file from disk.
|
|
38
|
+
*
|
|
39
|
+
* Search order (when no explicit configPath):
|
|
40
|
+
* 1. ~/.telora/{defaultFilename} (global config, multi-product)
|
|
41
|
+
* 2. .telora/{defaultFilename} in cwd (repo-local, legacy)
|
|
42
|
+
*
|
|
43
|
+
* @param configPath Explicit path to a config file, or undefined to use defaults.
|
|
44
|
+
* @param defaultFilename Filename to look for inside `.telora/` (e.g. `daemon.json`).
|
|
45
|
+
* @returns Parsed JSON object, or an empty object if no config file is found.
|
|
46
|
+
* @throws If an explicit configPath is provided but the file does not exist,
|
|
47
|
+
* or if the file cannot be parsed as JSON.
|
|
48
|
+
*/
|
|
49
|
+
export function loadConfigFile(configPath, defaultFilename) {
|
|
50
|
+
if (configPath) {
|
|
51
|
+
// Explicit path -- must exist
|
|
52
|
+
if (!existsSync(configPath)) {
|
|
53
|
+
throw new Error(`Config file not found: ${configPath}`);
|
|
54
|
+
}
|
|
55
|
+
return parseConfigFile(configPath);
|
|
56
|
+
}
|
|
57
|
+
// Try global config first: ~/.telora/{defaultFilename}
|
|
58
|
+
const globalPath = resolve(homedir(), '.telora', defaultFilename);
|
|
59
|
+
if (existsSync(globalPath)) {
|
|
60
|
+
return parseConfigFile(globalPath);
|
|
61
|
+
}
|
|
62
|
+
// Fall back to repo-local: .telora/{defaultFilename} in cwd
|
|
63
|
+
const localPath = resolve(process.cwd(), '.telora', defaultFilename);
|
|
64
|
+
if (existsSync(localPath)) {
|
|
65
|
+
const localConfig = parseConfigFile(localPath);
|
|
66
|
+
// Auto-migrate: repo-local config exists but no global config.
|
|
67
|
+
// Convert legacy single-product format to multi-product and write to global location.
|
|
68
|
+
const migrated = migrateToGlobalConfig(localConfig, process.cwd(), globalPath);
|
|
69
|
+
if (migrated) {
|
|
70
|
+
return parseConfigFile(globalPath);
|
|
71
|
+
}
|
|
72
|
+
return localConfig;
|
|
73
|
+
}
|
|
74
|
+
// No config file found -- return empty (env vars or init wizard will provide values)
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
/** Parse and validate a JSON config file. */
|
|
78
|
+
function parseConfigFile(path) {
|
|
79
|
+
try {
|
|
80
|
+
const content = readFileSync(path, 'utf-8');
|
|
81
|
+
const config = JSON.parse(content);
|
|
82
|
+
if (typeof config !== 'object' || config === null || Array.isArray(config)) {
|
|
83
|
+
throw new Error('Config file must contain a JSON object');
|
|
84
|
+
}
|
|
85
|
+
console.log(`Loaded config from ${path}`);
|
|
86
|
+
return config;
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
throw new Error(`Failed to parse config file ${path}: ${err.message}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Migrate a repo-local legacy config to the global ~/.telora/ location.
|
|
94
|
+
*
|
|
95
|
+
* Converts legacy single-product format (productId + repoPath at top level)
|
|
96
|
+
* to the multi-product format (products array). If the config already has a
|
|
97
|
+
* products array, it is written as-is to the global location.
|
|
98
|
+
*
|
|
99
|
+
* @returns true if migration succeeded, false if skipped (e.g. already multi-product format in place)
|
|
100
|
+
*/
|
|
101
|
+
function migrateToGlobalConfig(localConfig, repoPath, globalPath) {
|
|
102
|
+
try {
|
|
103
|
+
const migrated = { ...localConfig };
|
|
104
|
+
// Convert legacy single-product fields to products array
|
|
105
|
+
if (!Array.isArray(migrated.products)) {
|
|
106
|
+
const productId = typeof migrated.productId === 'string' ? migrated.productId : '';
|
|
107
|
+
const configRepoPath = typeof migrated.repoPath === 'string'
|
|
108
|
+
? migrated.repoPath
|
|
109
|
+
: repoPath;
|
|
110
|
+
if (productId) {
|
|
111
|
+
migrated.products = [{ id: productId, repoPath: configRepoPath }];
|
|
112
|
+
// Remove legacy fields from the migrated config
|
|
113
|
+
delete migrated.productId;
|
|
114
|
+
delete migrated.repoPath;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Ensure the global directory exists
|
|
118
|
+
const globalDir = dirname(globalPath);
|
|
119
|
+
if (!existsSync(globalDir)) {
|
|
120
|
+
mkdirSync(globalDir, { recursive: true });
|
|
121
|
+
}
|
|
122
|
+
writeFileSync(globalPath, JSON.stringify(migrated, null, 2) + '\n');
|
|
123
|
+
console.log(`Migrated config from repo-local to ${globalPath}. ` +
|
|
124
|
+
`The repo-local .telora/daemon.json can be removed.`);
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
console.warn(`Failed to migrate config to global location: ${err.message}. ` +
|
|
129
|
+
`Using repo-local config.`);
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Env-var mapping for base fields
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
/**
|
|
137
|
+
* Mapping from BaseConfig field name to the environment variable that provides it.
|
|
138
|
+
* Used by resolveBaseConfig to prioritise env vars over file config.
|
|
139
|
+
* Note: `products` is excluded -- it's resolved separately via resolveProducts().
|
|
140
|
+
*/
|
|
141
|
+
const BASE_ENV_MAP = {
|
|
142
|
+
teloraUrl: 'TELORA_URL',
|
|
143
|
+
trackerId: 'TELORA_TRACKER_ID',
|
|
144
|
+
organizationId: 'TELORA_ORGANIZATION_ID',
|
|
145
|
+
productId: 'TELORA_PRODUCT_ID',
|
|
146
|
+
repoPath: 'TELORA_REPO_PATH',
|
|
147
|
+
claudeCodePath: 'CLAUDE_CODE_PATH',
|
|
148
|
+
logDir: 'TELORA_LOG_DIR',
|
|
149
|
+
sessionTimeoutMs: 'SESSION_TIMEOUT_MS',
|
|
150
|
+
mcpConfigPath: 'MCP_CONFIG_PATH',
|
|
151
|
+
};
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
// Base config resolver
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
/**
|
|
156
|
+
* Resolve BaseConfig fields from a combination of file config and environment
|
|
157
|
+
* variables. Environment variables take priority over file config values.
|
|
158
|
+
*
|
|
159
|
+
* Returns a Partial<BaseConfig> so each engine can merge it with its own
|
|
160
|
+
* engine-specific fields. Fields that are not set in either source are omitted.
|
|
161
|
+
*
|
|
162
|
+
* Multi-product resolution:
|
|
163
|
+
* 1. If `products` array exists in config file, use it directly
|
|
164
|
+
* 2. If TELORA_PRODUCT_ID + TELORA_REPO_PATH env vars are set, they produce
|
|
165
|
+
* a single-entry products array (useful for CI/testing)
|
|
166
|
+
* 3. If only legacy `productId` + `repoPath` in config, normalize to products array
|
|
167
|
+
* 4. `productId` and `repoPath` on the result always reflect the first product
|
|
168
|
+
*
|
|
169
|
+
* @param fileConfig Parsed JSON from the config file (keys are camelCase field names).
|
|
170
|
+
* @param envOverrides Environment variables -- typically pass `process.env`.
|
|
171
|
+
*/
|
|
172
|
+
export function resolveBaseConfig(fileConfig, envOverrides) {
|
|
173
|
+
const result = {};
|
|
174
|
+
for (const [field, envKey] of Object.entries(BASE_ENV_MAP)) {
|
|
175
|
+
const envVal = envOverrides[envKey];
|
|
176
|
+
const fileVal = fileConfig[field];
|
|
177
|
+
if (field === 'sessionTimeoutMs') {
|
|
178
|
+
// Numeric field -- parse from env string if present
|
|
179
|
+
if (envVal !== undefined && envVal !== '') {
|
|
180
|
+
result[field] = parseInt(envVal, 10);
|
|
181
|
+
}
|
|
182
|
+
else if (typeof fileVal === 'number') {
|
|
183
|
+
result[field] = fileVal;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else if (field === 'mcpConfigPath') {
|
|
187
|
+
// Nullable string -- env takes priority, then file, leave out if neither set
|
|
188
|
+
if (envVal !== undefined && envVal !== '') {
|
|
189
|
+
result[field] = envVal;
|
|
190
|
+
}
|
|
191
|
+
else if (typeof fileVal === 'string') {
|
|
192
|
+
result[field] = fileVal;
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
result[field] = null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
// Regular string fields
|
|
200
|
+
if (envVal !== undefined && envVal !== '') {
|
|
201
|
+
result[field] = envVal;
|
|
202
|
+
}
|
|
203
|
+
else if (typeof fileVal === 'string' && fileVal !== '') {
|
|
204
|
+
result[field] = fileVal;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// ── Multi-product resolution ──────────────────────────────────────
|
|
209
|
+
const products = resolveProducts(fileConfig, envOverrides, result);
|
|
210
|
+
if (products.length > 0) {
|
|
211
|
+
result.products = products;
|
|
212
|
+
// Keep productId/repoPath in sync with the first product for backward compat
|
|
213
|
+
result.productId = products[0].id;
|
|
214
|
+
result.repoPath = products[0].repoPath;
|
|
215
|
+
}
|
|
216
|
+
// Warn when legacy fields coexist with products array in config file
|
|
217
|
+
if (Array.isArray(fileConfig.products) && fileConfig.products.length > 0) {
|
|
218
|
+
if (typeof fileConfig.productId === 'string' || typeof fileConfig.repoPath === 'string') {
|
|
219
|
+
console.warn('WARNING: Config file has both "products" array and legacy "productId"/"repoPath" fields. ' +
|
|
220
|
+
'The "products" array takes precedence. Remove the legacy fields to silence this warning.');
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Resolve the products array from config file and env vars.
|
|
227
|
+
*
|
|
228
|
+
* Priority:
|
|
229
|
+
* 1. TELORA_PRODUCT_ID + TELORA_REPO_PATH env vars → single-entry array
|
|
230
|
+
* 2. `products` array in config file → use directly
|
|
231
|
+
* 3. Legacy `productId` + `repoPath` in config file → normalize to single-entry
|
|
232
|
+
*/
|
|
233
|
+
function resolveProducts(fileConfig, envOverrides, resolvedBase) {
|
|
234
|
+
// Env-var override: single product from env (CI/testing use case)
|
|
235
|
+
const envProductId = envOverrides.TELORA_PRODUCT_ID;
|
|
236
|
+
const envRepoPath = envOverrides.TELORA_REPO_PATH;
|
|
237
|
+
if (envProductId && envProductId !== '') {
|
|
238
|
+
return [{
|
|
239
|
+
id: envProductId,
|
|
240
|
+
repoPath: envRepoPath && envRepoPath !== '' ? envRepoPath : process.cwd(),
|
|
241
|
+
}];
|
|
242
|
+
}
|
|
243
|
+
// Multi-product array in config file
|
|
244
|
+
const fileProducts = fileConfig.products;
|
|
245
|
+
if (Array.isArray(fileProducts) && fileProducts.length > 0) {
|
|
246
|
+
const entries = [];
|
|
247
|
+
for (const item of fileProducts) {
|
|
248
|
+
if (typeof item === 'object' && item !== null && !Array.isArray(item)) {
|
|
249
|
+
const obj = item;
|
|
250
|
+
const id = typeof obj.id === 'string' ? obj.id : '';
|
|
251
|
+
const repoPath = typeof obj.repoPath === 'string' ? obj.repoPath : '';
|
|
252
|
+
if (id) {
|
|
253
|
+
entries.push({ id, repoPath: repoPath || process.cwd() });
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (entries.length > 0)
|
|
258
|
+
return entries;
|
|
259
|
+
}
|
|
260
|
+
// Legacy single-product: normalize from resolved productId/repoPath
|
|
261
|
+
const productId = resolvedBase.productId;
|
|
262
|
+
const repoPath = resolvedBase.repoPath;
|
|
263
|
+
if (productId) {
|
|
264
|
+
return [{ id: productId, repoPath: repoPath || process.cwd() }];
|
|
265
|
+
}
|
|
266
|
+
return [];
|
|
267
|
+
}
|
|
268
|
+
// ---------------------------------------------------------------------------
|
|
269
|
+
// Base config validator
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
/**
|
|
272
|
+
* Validate the shared BaseConfig fields.
|
|
273
|
+
*
|
|
274
|
+
* Returns an array of human-readable error messages (never throws).
|
|
275
|
+
* Engines should call this, then append their own engine-specific validation
|
|
276
|
+
* errors before deciding whether to throw.
|
|
277
|
+
*
|
|
278
|
+
* @param config Partial base config to validate. Missing required fields
|
|
279
|
+
* are reported as errors.
|
|
280
|
+
*/
|
|
281
|
+
export function validateBaseConfig(config) {
|
|
282
|
+
const errors = [];
|
|
283
|
+
// ---- Required string fields must be present and non-empty ----
|
|
284
|
+
if (!config.teloraUrl || !config.teloraUrl.trim()) {
|
|
285
|
+
errors.push('teloraUrl is required (set TELORA_URL or teloraUrl in config file)');
|
|
286
|
+
}
|
|
287
|
+
if (!config.trackerId || !config.trackerId.trim()) {
|
|
288
|
+
errors.push('trackerId is required (set TELORA_TRACKER_ID or trackerId in config file)');
|
|
289
|
+
}
|
|
290
|
+
if (!config.organizationId || !config.organizationId.trim()) {
|
|
291
|
+
errors.push('organizationId is required (set TELORA_ORGANIZATION_ID or organizationId in config file)');
|
|
292
|
+
}
|
|
293
|
+
// ---- Products array validation ----
|
|
294
|
+
if (config.products && config.products.length > 0) {
|
|
295
|
+
// Validate via products array (preferred)
|
|
296
|
+
const seenIds = new Set();
|
|
297
|
+
for (let i = 0; i < config.products.length; i++) {
|
|
298
|
+
const product = config.products[i];
|
|
299
|
+
if (!product.id || !product.id.trim()) {
|
|
300
|
+
errors.push(`products[${i}].id is required`);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
if (!UUID_REGEX.test(product.id)) {
|
|
304
|
+
errors.push(`products[${i}].id is not a valid UUID: "${product.id}"`);
|
|
305
|
+
}
|
|
306
|
+
if (seenIds.has(product.id)) {
|
|
307
|
+
errors.push(`Duplicate product ID: "${product.id}"`);
|
|
308
|
+
}
|
|
309
|
+
seenIds.add(product.id);
|
|
310
|
+
}
|
|
311
|
+
if (!product.repoPath || !product.repoPath.trim()) {
|
|
312
|
+
errors.push(`products[${i}].repoPath is required`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
// Fallback to legacy single-product validation
|
|
318
|
+
if (!config.productId || !config.productId.trim()) {
|
|
319
|
+
errors.push('At least one product is required (set products array, or TELORA_PRODUCT_ID)');
|
|
320
|
+
}
|
|
321
|
+
if (!config.repoPath || !config.repoPath.trim()) {
|
|
322
|
+
errors.push('repoPath is required (set TELORA_REPO_PATH or repoPath in config file)');
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// ---- URL format ----
|
|
326
|
+
if (config.teloraUrl && config.teloraUrl.trim()) {
|
|
327
|
+
try {
|
|
328
|
+
new URL(config.teloraUrl);
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
errors.push(`teloraUrl is not a valid URL: "${config.teloraUrl}"`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// ---- UUID format for org ID ----
|
|
335
|
+
if (config.organizationId && config.organizationId.trim()) {
|
|
336
|
+
if (!UUID_REGEX.test(config.organizationId)) {
|
|
337
|
+
errors.push(`organizationId is not a valid UUID: "${config.organizationId}"`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// Legacy productId UUID validation (when not using products array)
|
|
341
|
+
if (config.productId && config.productId.trim() && (!config.products || config.products.length === 0)) {
|
|
342
|
+
if (!UUID_REGEX.test(config.productId)) {
|
|
343
|
+
errors.push(`productId is not a valid UUID: "${config.productId}"`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return errors;
|
|
347
|
+
}
|
|
348
|
+
//# 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/engine.d.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExecutionEngine interface -- the formal contract between the unified daemon
|
|
3
|
+
* process shell and individual execution engines (strategy, factory, etc.).
|
|
4
|
+
*
|
|
5
|
+
* The process shell manages lifecycle primitives (PID lock, signal handlers,
|
|
6
|
+
* config loading) and delegates engine-specific behavior through this interface.
|
|
7
|
+
* This allows adding future engines without modifying the shell.
|
|
8
|
+
*
|
|
9
|
+
* Lifecycle sequence (called by the process shell):
|
|
10
|
+
* 1. engine.init(config) -- store config, validate, connect
|
|
11
|
+
* 2. engine.recoverFromCrash() -- reconcile orphaned state (uses stored config)
|
|
12
|
+
* 3. engine.start() -- begin polling / listening loops
|
|
13
|
+
* ... running ...
|
|
14
|
+
* 4. engine.stop() -- stop accepting new work
|
|
15
|
+
* 5. engine.shutdown() -- graceful cleanup (kill processes, WIP commit, drain)
|
|
16
|
+
*/
|
|
17
|
+
import type { BaseConfig } from './config.js';
|
|
18
|
+
import type { ResourceGovernor } from './resource-governor.js';
|
|
19
|
+
/** Health status of an execution engine. */
|
|
20
|
+
export interface EngineHealth {
|
|
21
|
+
/** Overall health status. */
|
|
22
|
+
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
23
|
+
/** Number of active work items (strategy teams, factory instances, etc.). */
|
|
24
|
+
activeWorkItems: number;
|
|
25
|
+
/** Engine-specific details for status reporting. */
|
|
26
|
+
details: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
/** Resource usage snapshot for an execution engine. */
|
|
29
|
+
export interface ResourceUsage {
|
|
30
|
+
/** Number of active Claude Code processes managed by this engine. */
|
|
31
|
+
activeClaudeProcesses: number;
|
|
32
|
+
/** Number of active git worktrees managed by this engine. */
|
|
33
|
+
activeWorktrees: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Contract that every execution engine must implement.
|
|
37
|
+
*
|
|
38
|
+
* The process shell treats engines as opaque boxes -- it only interacts
|
|
39
|
+
* through this interface. Engine internals (polling loops, state machines,
|
|
40
|
+
* spawn logic) are encapsulated within each engine's implementation.
|
|
41
|
+
*/
|
|
42
|
+
export interface ExecutionEngine {
|
|
43
|
+
/** Human-readable engine identifier (e.g. 'strategy', 'factory'). */
|
|
44
|
+
readonly name: string;
|
|
45
|
+
/**
|
|
46
|
+
* Initialize the engine with its configuration.
|
|
47
|
+
*
|
|
48
|
+
* Responsibilities:
|
|
49
|
+
* - Store and validate engine-specific config
|
|
50
|
+
* - Initialize API clients, database connections, git state
|
|
51
|
+
* - Prepare internal state structures
|
|
52
|
+
*
|
|
53
|
+
* Called once before any other method. The config is a BaseConfig merged
|
|
54
|
+
* with engine-specific fields (e.g. DaemonConfig, FactoryConfig).
|
|
55
|
+
*/
|
|
56
|
+
init(config: BaseConfig & Record<string, unknown>): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Recover from a previous crash.
|
|
59
|
+
*
|
|
60
|
+
* Responsibilities:
|
|
61
|
+
* - Reconcile orphaned worktrees, stale sessions, stuck work items
|
|
62
|
+
* - Rebuild in-memory state from database and disk
|
|
63
|
+
* - Resolve git state inconsistencies
|
|
64
|
+
*
|
|
65
|
+
* Called after init(), before start(). Uses the config stored during init().
|
|
66
|
+
*/
|
|
67
|
+
recoverFromCrash(): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Start the engine's polling / listening loops.
|
|
70
|
+
*
|
|
71
|
+
* After this call the engine is actively processing work. The shell
|
|
72
|
+
* should not call start() more than once without an intervening stop().
|
|
73
|
+
*/
|
|
74
|
+
start(): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Stop accepting new work.
|
|
77
|
+
*
|
|
78
|
+
* In-progress work items continue, but no new work is picked up.
|
|
79
|
+
* This is the first phase of a graceful shutdown sequence.
|
|
80
|
+
*/
|
|
81
|
+
stop(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Graceful shutdown with full cleanup.
|
|
84
|
+
*
|
|
85
|
+
* Responsibilities:
|
|
86
|
+
* - Kill or wait for active child processes
|
|
87
|
+
* - WIP commit uncommitted changes in worktrees
|
|
88
|
+
* - Drain pending async updates
|
|
89
|
+
* - Release engine-specific resources
|
|
90
|
+
*
|
|
91
|
+
* Called after stop(). The engine should be inert after this returns.
|
|
92
|
+
*/
|
|
93
|
+
shutdown(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Return a snapshot of the engine's health.
|
|
96
|
+
*
|
|
97
|
+
* Used by the process shell for status reporting (SIGUSR1, CLI status)
|
|
98
|
+
* and heartbeat payloads.
|
|
99
|
+
*/
|
|
100
|
+
healthCheck(): EngineHealth;
|
|
101
|
+
/**
|
|
102
|
+
* Return a snapshot of the engine's resource usage.
|
|
103
|
+
*
|
|
104
|
+
* Used by the resource governor for concurrency decisions and by
|
|
105
|
+
* the status command for utilization reporting.
|
|
106
|
+
*/
|
|
107
|
+
getResourceUsage(): ResourceUsage;
|
|
108
|
+
/**
|
|
109
|
+
* Inject a resource governor for cross-engine concurrency control.
|
|
110
|
+
*
|
|
111
|
+
* Called by the process shell after engine construction but before start().
|
|
112
|
+
* Engines that support concurrency limits should store the governor and
|
|
113
|
+
* use it to acquire/release slots when spawning work items.
|
|
114
|
+
*
|
|
115
|
+
* Optional: engines that do not need governor-based concurrency control
|
|
116
|
+
* may omit this method.
|
|
117
|
+
*/
|
|
118
|
+
setGovernor?(gov: ResourceGovernor): void;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAM/D,4CAA4C;AAC5C,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IAC7C,6EAA6E;IAC7E,eAAe,EAAE,MAAM,CAAC;IACxB,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAMD,uDAAuD;AACvD,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,6DAA6D;IAC7D,eAAe,EAAE,MAAM,CAAC;CACzB;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE;;;;;;;;;OASG;IACH,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;;;;OAKG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;;;OAKG;IACH,IAAI,IAAI,IAAI,CAAC;IAEb;;;;;;;;;;OAUG;IACH,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B;;;;;OAKG;IACH,WAAW,IAAI,YAAY,CAAC;IAE5B;;;;;OAKG;IACH,gBAAgB,IAAI,aAAa,CAAC;IAElC;;;;;;;;;OASG;IACH,WAAW,CAAC,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC3C"}
|
package/dist/engine.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExecutionEngine interface -- the formal contract between the unified daemon
|
|
3
|
+
* process shell and individual execution engines (strategy, factory, etc.).
|
|
4
|
+
*
|
|
5
|
+
* The process shell manages lifecycle primitives (PID lock, signal handlers,
|
|
6
|
+
* config loading) and delegates engine-specific behavior through this interface.
|
|
7
|
+
* This allows adding future engines without modifying the shell.
|
|
8
|
+
*
|
|
9
|
+
* Lifecycle sequence (called by the process shell):
|
|
10
|
+
* 1. engine.init(config) -- store config, validate, connect
|
|
11
|
+
* 2. engine.recoverFromCrash() -- reconcile orphaned state (uses stored config)
|
|
12
|
+
* 3. engine.start() -- begin polling / listening loops
|
|
13
|
+
* ... running ...
|
|
14
|
+
* 4. engine.stop() -- stop accepting new work
|
|
15
|
+
* 5. engine.shutdown() -- graceful cleanup (kill processes, WIP commit, drain)
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared escalation reason types for daemon and factory engines.
|
|
3
|
+
*
|
|
4
|
+
* The `reason_type` column in agent_escalations uses these values to
|
|
5
|
+
* classify what kind of help the agent needs from a human.
|
|
6
|
+
*
|
|
7
|
+
* Both engines should import from here to stay in sync with the DB enum.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Union of valid escalation reason types.
|
|
11
|
+
*
|
|
12
|
+
* These correspond to the values accepted by the agent_escalations table
|
|
13
|
+
* and the Telora API escalation endpoints.
|
|
14
|
+
*/
|
|
15
|
+
export type EscalationReasonType = 'decision_needed' | 'error_encountered' | 'out_of_scope' | 'blocked_by_external' | 'needs_clarification' | 'security_concern';
|
|
16
|
+
/**
|
|
17
|
+
* Const object of all valid escalation reason types.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* import { ESCALATION_REASONS } from '@telora/daemon-core';
|
|
21
|
+
* createEscalation({ reasonType: ESCALATION_REASONS.ERROR_ENCOUNTERED, ... });
|
|
22
|
+
*/
|
|
23
|
+
export declare const ESCALATION_REASONS: {
|
|
24
|
+
DECISION_NEEDED: "decision_needed";
|
|
25
|
+
ERROR_ENCOUNTERED: "error_encountered";
|
|
26
|
+
OUT_OF_SCOPE: "out_of_scope";
|
|
27
|
+
BLOCKED_BY_EXTERNAL: "blocked_by_external";
|
|
28
|
+
NEEDS_CLARIFICATION: "needs_clarification";
|
|
29
|
+
SECURITY_CONCERN: "security_concern";
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=escalation-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escalation-types.d.ts","sourceRoot":"","sources":["../src/escalation-types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAC5B,iBAAiB,GACjB,mBAAmB,GACnB,cAAc,GACd,qBAAqB,GACrB,qBAAqB,GACrB,kBAAkB,CAAC;AAEvB;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB;;;;;;;CAOiB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared escalation reason types for daemon and factory engines.
|
|
3
|
+
*
|
|
4
|
+
* The `reason_type` column in agent_escalations uses these values to
|
|
5
|
+
* classify what kind of help the agent needs from a human.
|
|
6
|
+
*
|
|
7
|
+
* Both engines should import from here to stay in sync with the DB enum.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Const object of all valid escalation reason types.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* import { ESCALATION_REASONS } from '@telora/daemon-core';
|
|
14
|
+
* createEscalation({ reasonType: ESCALATION_REASONS.ERROR_ENCOUNTERED, ... });
|
|
15
|
+
*/
|
|
16
|
+
export const ESCALATION_REASONS = {
|
|
17
|
+
DECISION_NEEDED: 'decision_needed',
|
|
18
|
+
ERROR_ENCOUNTERED: 'error_encountered',
|
|
19
|
+
OUT_OF_SCOPE: 'out_of_scope',
|
|
20
|
+
BLOCKED_BY_EXTERNAL: 'blocked_by_external',
|
|
21
|
+
NEEDS_CLARIFICATION: 'needs_clarification',
|
|
22
|
+
SECURITY_CONCERN: 'security_concern',
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=escalation-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escalation-types.js","sourceRoot":"","sources":["../src/escalation-types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAoBH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,eAAe,EAAE,iBAA0B;IAC3C,iBAAiB,EAAE,mBAA4B;IAC/C,YAAY,EAAE,cAAuB;IACrC,mBAAmB,EAAE,qBAA8B;IACnD,mBAAmB,EAAE,qBAA8B;IACnD,gBAAgB,EAAE,kBAA2B;CACC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event logger - formats stream-json events for human-readable log output.
|
|
3
|
+
*
|
|
4
|
+
* Converts structured NDJSON events from Claude Code's stream-json output
|
|
5
|
+
* into concise log lines for the agent's stdout log file.
|
|
6
|
+
*/
|
|
7
|
+
import type { OutputEvent } from './stream-json.js';
|
|
8
|
+
/**
|
|
9
|
+
* Format a stream-json event as a human-readable log line.
|
|
10
|
+
* Returns null for events that don't need logging.
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatEventForLog(event: OutputEvent): string | null;
|
|
13
|
+
//# sourceMappingURL=event-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-logger.d.ts","sourceRoot":"","sources":["../src/event-logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,WAAW,EAUZ,MAAM,kBAAkB,CAAC;AAE1B;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CA2EnE"}
|