openvole 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +3250 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +676 -0
- package/dist/index.js +2242 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
import { ZodSchema } from 'zod';
|
|
2
|
+
import { Emitter } from 'mitt';
|
|
3
|
+
|
|
4
|
+
/** Error codes for categorizing failures in the agent loop */
|
|
5
|
+
type ActionErrorCode = 'TOOL_TIMEOUT' | 'TOOL_EXCEPTION' | 'TOOL_NOT_FOUND' | 'PERMISSION_DENIED' | 'PAW_CRASHED' | 'BRAIN_ERROR' | 'INVALID_PLAN';
|
|
6
|
+
/** Structured error attached to a failed action */
|
|
7
|
+
interface ActionError {
|
|
8
|
+
code: ActionErrorCode;
|
|
9
|
+
message: string;
|
|
10
|
+
toolName?: string;
|
|
11
|
+
pawName?: string;
|
|
12
|
+
details?: unknown;
|
|
13
|
+
}
|
|
14
|
+
/** Result of a single tool execution during the Act phase */
|
|
15
|
+
interface ActionResult {
|
|
16
|
+
toolName: string;
|
|
17
|
+
pawName: string;
|
|
18
|
+
success: boolean;
|
|
19
|
+
output?: unknown;
|
|
20
|
+
error?: ActionError;
|
|
21
|
+
durationMs: number;
|
|
22
|
+
}
|
|
23
|
+
/** Create a structured ActionError */
|
|
24
|
+
declare function createActionError(code: ActionErrorCode, message: string, opts?: {
|
|
25
|
+
toolName?: string;
|
|
26
|
+
pawName?: string;
|
|
27
|
+
details?: unknown;
|
|
28
|
+
}): ActionError;
|
|
29
|
+
/** Create a successful ActionResult */
|
|
30
|
+
declare function successResult(toolName: string, pawName: string, output: unknown, durationMs: number): ActionResult;
|
|
31
|
+
/** Create a failed ActionResult */
|
|
32
|
+
declare function failureResult(toolName: string, pawName: string, error: ActionError, durationMs: number): ActionResult;
|
|
33
|
+
|
|
34
|
+
/** Summary of a tool available to the Brain */
|
|
35
|
+
interface ToolSummary {
|
|
36
|
+
name: string;
|
|
37
|
+
description: string;
|
|
38
|
+
pawName: string;
|
|
39
|
+
}
|
|
40
|
+
/** A Skill whose required tools are all satisfied (compact — Brain reads full instructions on demand) */
|
|
41
|
+
interface ActiveSkill {
|
|
42
|
+
name: string;
|
|
43
|
+
description: string;
|
|
44
|
+
satisfiedBy: string[];
|
|
45
|
+
}
|
|
46
|
+
/** A single message in the agent's reasoning history */
|
|
47
|
+
interface AgentMessage {
|
|
48
|
+
role: 'user' | 'brain' | 'tool_result' | 'error';
|
|
49
|
+
content: string;
|
|
50
|
+
toolCall?: {
|
|
51
|
+
name: string;
|
|
52
|
+
params: unknown;
|
|
53
|
+
};
|
|
54
|
+
timestamp: number;
|
|
55
|
+
}
|
|
56
|
+
/** The shared data structure that flows through the agent loop */
|
|
57
|
+
interface AgentContext {
|
|
58
|
+
taskId: string;
|
|
59
|
+
messages: AgentMessage[];
|
|
60
|
+
availableTools: ToolSummary[];
|
|
61
|
+
activeSkills: ActiveSkill[];
|
|
62
|
+
metadata: Record<string, unknown>;
|
|
63
|
+
iteration: number;
|
|
64
|
+
maxIterations: number;
|
|
65
|
+
}
|
|
66
|
+
/** Create an empty AgentContext for a new task */
|
|
67
|
+
declare function createAgentContext(taskId: string, maxIterations: number): AgentContext;
|
|
68
|
+
|
|
69
|
+
/** A tool definition as provided by a Paw */
|
|
70
|
+
interface ToolDefinition {
|
|
71
|
+
name: string;
|
|
72
|
+
description: string;
|
|
73
|
+
parameters: ZodSchema;
|
|
74
|
+
execute: (params: unknown) => Promise<unknown>;
|
|
75
|
+
}
|
|
76
|
+
/** An entry in the tool registry — includes ownership metadata */
|
|
77
|
+
interface ToolRegistryEntry {
|
|
78
|
+
name: string;
|
|
79
|
+
description: string;
|
|
80
|
+
parameters: ZodSchema;
|
|
81
|
+
pawName: string;
|
|
82
|
+
inProcess: boolean;
|
|
83
|
+
execute: (params: unknown) => Promise<unknown>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Pluggable I/O interface for user-facing communication */
|
|
87
|
+
interface VoleIO {
|
|
88
|
+
/** Ask the user for a yes/no confirmation */
|
|
89
|
+
confirm(message: string): Promise<boolean>;
|
|
90
|
+
/** Ask the user for free-form input */
|
|
91
|
+
prompt(message: string): Promise<string>;
|
|
92
|
+
/** Send a notification to the user (fire-and-forget) */
|
|
93
|
+
notify(message: string): void;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** The plan returned by a Brain Paw during the Think phase */
|
|
97
|
+
interface AgentPlan {
|
|
98
|
+
actions: PlannedAction[];
|
|
99
|
+
execution?: 'parallel' | 'sequential';
|
|
100
|
+
response?: string;
|
|
101
|
+
done?: boolean;
|
|
102
|
+
}
|
|
103
|
+
/** A single tool call the Brain wants to execute */
|
|
104
|
+
interface PlannedAction {
|
|
105
|
+
tool: string;
|
|
106
|
+
params: unknown;
|
|
107
|
+
}
|
|
108
|
+
/** Hook called once when a task starts — initialize Paw state for this task */
|
|
109
|
+
type BootstrapHook = (context: AgentContext) => Promise<AgentContext>;
|
|
110
|
+
/** Hook called during the Perceive phase — enrich context before Think */
|
|
111
|
+
type PerceiveHook = (context: AgentContext) => Promise<AgentContext>;
|
|
112
|
+
/** Hook called during the Observe phase — fire-and-forget side effect */
|
|
113
|
+
type ObserveHook = (result: ActionResult) => Promise<void>;
|
|
114
|
+
/** Hook called when context exceeds size threshold — compress/summarize */
|
|
115
|
+
type CompactHook = (context: AgentContext) => Promise<AgentContext>;
|
|
116
|
+
/** A cron-triggered schedule hook */
|
|
117
|
+
interface ScheduleHook {
|
|
118
|
+
cron: string;
|
|
119
|
+
handler: () => Promise<AgentTaskInput>;
|
|
120
|
+
}
|
|
121
|
+
/** Input for creating a new agent task */
|
|
122
|
+
interface AgentTaskInput {
|
|
123
|
+
input: string;
|
|
124
|
+
source?: 'user' | 'schedule' | 'paw';
|
|
125
|
+
}
|
|
126
|
+
/** The full Paw definition — the contract every Paw must implement */
|
|
127
|
+
interface PawDefinition {
|
|
128
|
+
name: string;
|
|
129
|
+
version: string;
|
|
130
|
+
description: string;
|
|
131
|
+
brain?: boolean;
|
|
132
|
+
inProcess?: boolean;
|
|
133
|
+
config?: ZodSchema;
|
|
134
|
+
hooks?: {
|
|
135
|
+
onBootstrap?: BootstrapHook;
|
|
136
|
+
onPerceive?: PerceiveHook;
|
|
137
|
+
onObserve?: ObserveHook;
|
|
138
|
+
onCompact?: CompactHook;
|
|
139
|
+
onSchedule?: ScheduleHook[];
|
|
140
|
+
};
|
|
141
|
+
tools?: ToolDefinition[];
|
|
142
|
+
think?: (context: AgentContext) => Promise<AgentPlan>;
|
|
143
|
+
io?: VoleIO;
|
|
144
|
+
onLoad?: (config: unknown) => Promise<void>;
|
|
145
|
+
onUnload?: () => Promise<void>;
|
|
146
|
+
}
|
|
147
|
+
/** Transport type for IPC communication */
|
|
148
|
+
type TransportType = 'ipc' | 'stdio';
|
|
149
|
+
/** Paw manifest as read from vole-paw.json */
|
|
150
|
+
interface PawManifest {
|
|
151
|
+
name: string;
|
|
152
|
+
version: string;
|
|
153
|
+
description: string;
|
|
154
|
+
entry: string;
|
|
155
|
+
brain: boolean;
|
|
156
|
+
inProcess?: boolean;
|
|
157
|
+
transport?: TransportType;
|
|
158
|
+
tools: Array<{
|
|
159
|
+
name: string;
|
|
160
|
+
description: string;
|
|
161
|
+
}>;
|
|
162
|
+
permissions?: {
|
|
163
|
+
network?: string[];
|
|
164
|
+
listen?: number[];
|
|
165
|
+
filesystem?: string[];
|
|
166
|
+
env?: string[];
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/** Paw configuration in vole.config.ts */
|
|
170
|
+
interface PawConfig {
|
|
171
|
+
name: string;
|
|
172
|
+
hooks?: {
|
|
173
|
+
perceive?: {
|
|
174
|
+
order?: number;
|
|
175
|
+
pipeline?: boolean;
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
allow?: {
|
|
179
|
+
network?: string[];
|
|
180
|
+
listen?: number[];
|
|
181
|
+
filesystem?: string[];
|
|
182
|
+
env?: string[];
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/** Runtime state of a loaded Paw */
|
|
186
|
+
interface PawInstance {
|
|
187
|
+
name: string;
|
|
188
|
+
manifest: PawManifest;
|
|
189
|
+
config: PawConfig;
|
|
190
|
+
healthy: boolean;
|
|
191
|
+
transport: TransportType;
|
|
192
|
+
inProcess: boolean;
|
|
193
|
+
definition?: PawDefinition;
|
|
194
|
+
process?: {
|
|
195
|
+
kill: () => void;
|
|
196
|
+
pid?: number;
|
|
197
|
+
};
|
|
198
|
+
sendRequest?: (method: string, params?: unknown) => Promise<unknown>;
|
|
199
|
+
/** Bus events this Paw has subscribed to */
|
|
200
|
+
subscriptions?: string[];
|
|
201
|
+
}
|
|
202
|
+
/** Effective permissions = intersection of manifest requests and config grants */
|
|
203
|
+
interface EffectivePermissions {
|
|
204
|
+
network: string[];
|
|
205
|
+
listen: number[];
|
|
206
|
+
filesystem: string[];
|
|
207
|
+
env: string[];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Rate limit configuration */
|
|
211
|
+
interface RateLimits {
|
|
212
|
+
/** Max LLM (Brain) calls per minute */
|
|
213
|
+
llmCallsPerMinute?: number;
|
|
214
|
+
/** Max LLM (Brain) calls per hour */
|
|
215
|
+
llmCallsPerHour?: number;
|
|
216
|
+
/** Max tool executions per single task */
|
|
217
|
+
toolExecutionsPerTask?: number;
|
|
218
|
+
/** Max tasks per hour, keyed by source */
|
|
219
|
+
tasksPerHour?: Record<string, number>;
|
|
220
|
+
}
|
|
221
|
+
/** Loop configuration */
|
|
222
|
+
interface LoopConfig {
|
|
223
|
+
maxIterations: number;
|
|
224
|
+
confirmBeforeAct: boolean;
|
|
225
|
+
taskConcurrency: number;
|
|
226
|
+
/** Max messages before triggering compact hooks (0 = disabled) */
|
|
227
|
+
compactThreshold: number;
|
|
228
|
+
logLevel: 'debug' | 'info' | 'warn' | 'error';
|
|
229
|
+
/** Rate limits (undefined = no limits) */
|
|
230
|
+
rateLimits?: RateLimits;
|
|
231
|
+
}
|
|
232
|
+
/** Tool profile — restricts which tools a task source can use */
|
|
233
|
+
interface ToolProfile {
|
|
234
|
+
/** Tools allowed (if set, only these tools can be used) */
|
|
235
|
+
allow?: string[];
|
|
236
|
+
/** Tools denied (if set, these tools are blocked) */
|
|
237
|
+
deny?: string[];
|
|
238
|
+
}
|
|
239
|
+
/** Heartbeat configuration */
|
|
240
|
+
interface HeartbeatConfig {
|
|
241
|
+
enabled: boolean;
|
|
242
|
+
intervalMinutes: number;
|
|
243
|
+
}
|
|
244
|
+
/** The full OpenVole configuration */
|
|
245
|
+
interface VoleConfig {
|
|
246
|
+
brain?: string;
|
|
247
|
+
paws: Array<PawConfig | string>;
|
|
248
|
+
skills: string[];
|
|
249
|
+
loop: LoopConfig;
|
|
250
|
+
heartbeat: HeartbeatConfig;
|
|
251
|
+
/** Tool profiles per task source — restrict which tools can be used */
|
|
252
|
+
toolProfiles?: Record<string, ToolProfile>;
|
|
253
|
+
}
|
|
254
|
+
/** CLI-managed lock file — tracks installed paws and skills */
|
|
255
|
+
interface VoleLock {
|
|
256
|
+
paws: Array<{
|
|
257
|
+
name: string;
|
|
258
|
+
version: string;
|
|
259
|
+
allow?: PawConfig['allow'];
|
|
260
|
+
}>;
|
|
261
|
+
skills: Array<{
|
|
262
|
+
name: string;
|
|
263
|
+
version: string;
|
|
264
|
+
}>;
|
|
265
|
+
}
|
|
266
|
+
/** Create a VoleConfig with defaults applied */
|
|
267
|
+
declare function defineConfig(config: Partial<VoleConfig>): VoleConfig;
|
|
268
|
+
/** Load configuration — merges vole.config.{ts,mjs,js} with vole.lock.json */
|
|
269
|
+
declare function loadConfig(configPath: string): Promise<VoleConfig>;
|
|
270
|
+
/** Read the lock file */
|
|
271
|
+
declare function readLockFile(projectRoot: string): Promise<VoleLock>;
|
|
272
|
+
/** Write the lock file */
|
|
273
|
+
declare function writeLockFile(projectRoot: string, lock: VoleLock): Promise<void>;
|
|
274
|
+
/** Add a Paw to the lock file */
|
|
275
|
+
declare function addPawToLock(projectRoot: string, name: string, version: string, allow?: PawConfig['allow']): Promise<void>;
|
|
276
|
+
/** Remove a Paw from the lock file */
|
|
277
|
+
declare function removePawFromLock(projectRoot: string, name: string): Promise<void>;
|
|
278
|
+
/** Add a Skill to the lock file */
|
|
279
|
+
declare function addSkillToLock(projectRoot: string, name: string, version: string): Promise<void>;
|
|
280
|
+
/** Remove a Skill from the lock file */
|
|
281
|
+
declare function removeSkillFromLock(projectRoot: string, name: string): Promise<void>;
|
|
282
|
+
|
|
283
|
+
/** Events emitted on the message bus */
|
|
284
|
+
type BusEvents = {
|
|
285
|
+
'tool:registered': {
|
|
286
|
+
toolName: string;
|
|
287
|
+
pawName: string;
|
|
288
|
+
};
|
|
289
|
+
'tool:unregistered': {
|
|
290
|
+
toolName: string;
|
|
291
|
+
pawName: string;
|
|
292
|
+
};
|
|
293
|
+
'paw:registered': {
|
|
294
|
+
pawName: string;
|
|
295
|
+
};
|
|
296
|
+
'paw:unregistered': {
|
|
297
|
+
pawName: string;
|
|
298
|
+
};
|
|
299
|
+
'paw:crashed': {
|
|
300
|
+
pawName: string;
|
|
301
|
+
error?: unknown;
|
|
302
|
+
};
|
|
303
|
+
'task:queued': {
|
|
304
|
+
taskId: string;
|
|
305
|
+
};
|
|
306
|
+
'task:started': {
|
|
307
|
+
taskId: string;
|
|
308
|
+
};
|
|
309
|
+
'task:completed': {
|
|
310
|
+
taskId: string;
|
|
311
|
+
result?: string;
|
|
312
|
+
};
|
|
313
|
+
'task:failed': {
|
|
314
|
+
taskId: string;
|
|
315
|
+
error?: unknown;
|
|
316
|
+
};
|
|
317
|
+
'task:cancelled': {
|
|
318
|
+
taskId: string;
|
|
319
|
+
};
|
|
320
|
+
'rate:limited': {
|
|
321
|
+
bucket: string;
|
|
322
|
+
source?: string;
|
|
323
|
+
};
|
|
324
|
+
};
|
|
325
|
+
type MessageBus = Emitter<BusEvents>;
|
|
326
|
+
/** Create a new message bus instance */
|
|
327
|
+
declare function createMessageBus(): MessageBus;
|
|
328
|
+
|
|
329
|
+
declare class ToolRegistry {
|
|
330
|
+
private bus;
|
|
331
|
+
private tools;
|
|
332
|
+
constructor(bus: MessageBus);
|
|
333
|
+
/** Register tools from a Paw. Skips tools with conflicting names. */
|
|
334
|
+
register(pawName: string, tools: ToolDefinition[], inProcess: boolean): void;
|
|
335
|
+
/** Remove all tools owned by a specific Paw */
|
|
336
|
+
unregister(pawName: string): void;
|
|
337
|
+
/** Get a tool entry by name */
|
|
338
|
+
get(toolName: string): ToolRegistryEntry | undefined;
|
|
339
|
+
/** List all registered tools */
|
|
340
|
+
list(): ToolRegistryEntry[];
|
|
341
|
+
/** Check if a tool exists */
|
|
342
|
+
has(toolName: string): boolean;
|
|
343
|
+
/** Get tool summaries for AgentContext */
|
|
344
|
+
summaries(): ToolSummary[];
|
|
345
|
+
/** Get all tool names owned by a specific Paw */
|
|
346
|
+
toolsForPaw(pawName: string): string[];
|
|
347
|
+
/** Clear all tools (for shutdown) */
|
|
348
|
+
clear(): void;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** Interface for queryable registries (avoids circular imports) */
|
|
352
|
+
interface QueryableSkillRegistry {
|
|
353
|
+
list(): Array<{
|
|
354
|
+
name: string;
|
|
355
|
+
active: boolean;
|
|
356
|
+
missingTools: string[];
|
|
357
|
+
definition: {
|
|
358
|
+
description: string;
|
|
359
|
+
};
|
|
360
|
+
}>;
|
|
361
|
+
}
|
|
362
|
+
interface QueryableTaskQueue {
|
|
363
|
+
list(): Array<{
|
|
364
|
+
id: string;
|
|
365
|
+
source: string;
|
|
366
|
+
input: string;
|
|
367
|
+
status: string;
|
|
368
|
+
createdAt: number;
|
|
369
|
+
}>;
|
|
370
|
+
enqueue(input: string, source?: 'user' | 'schedule' | 'paw', options?: {
|
|
371
|
+
sessionId?: string;
|
|
372
|
+
metadata?: Record<string, unknown>;
|
|
373
|
+
}): {
|
|
374
|
+
id: string;
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
interface QueryableScheduler {
|
|
378
|
+
list(): Array<{
|
|
379
|
+
id: string;
|
|
380
|
+
input: string;
|
|
381
|
+
intervalMinutes: number;
|
|
382
|
+
createdAt: number;
|
|
383
|
+
}>;
|
|
384
|
+
}
|
|
385
|
+
/** Manages loaded Paws and their lifecycle */
|
|
386
|
+
declare class PawRegistry {
|
|
387
|
+
private bus;
|
|
388
|
+
private toolRegistry;
|
|
389
|
+
private projectRoot;
|
|
390
|
+
private paws;
|
|
391
|
+
private transports;
|
|
392
|
+
private perceiveHooks;
|
|
393
|
+
private observeHookPaws;
|
|
394
|
+
private bootstrapPaws;
|
|
395
|
+
private compactPaws;
|
|
396
|
+
private brainPawName;
|
|
397
|
+
/** Maps config path → manifest name (e.g. "./paws/paw-ollama" → "@openvole/paw-ollama") */
|
|
398
|
+
private configToManifest;
|
|
399
|
+
private skillRegistry?;
|
|
400
|
+
private taskQueue?;
|
|
401
|
+
private scheduler?;
|
|
402
|
+
constructor(bus: MessageBus, toolRegistry: ToolRegistry, projectRoot: string);
|
|
403
|
+
/** Inject queryable registries (called after construction to avoid circular deps) */
|
|
404
|
+
setQuerySources(skills: QueryableSkillRegistry, tasks: QueryableTaskQueue, scheduler?: QueryableScheduler): void;
|
|
405
|
+
/** Load and register a Paw */
|
|
406
|
+
load(config: PawConfig): Promise<boolean>;
|
|
407
|
+
/** Unload a Paw (accepts config path or manifest name) */
|
|
408
|
+
unload(name: string): Promise<boolean>;
|
|
409
|
+
/** Resolve a config name to its manifest name */
|
|
410
|
+
resolveManifestName(configName: string): string;
|
|
411
|
+
/** Set the Brain Paw name (accepts config path or manifest name) */
|
|
412
|
+
setBrain(name: string): void;
|
|
413
|
+
/** Get the Brain Paw name */
|
|
414
|
+
getBrainName(): string | undefined;
|
|
415
|
+
/** Get a Paw instance */
|
|
416
|
+
get(name: string): PawInstance | undefined;
|
|
417
|
+
/** List all loaded Paws */
|
|
418
|
+
list(): PawInstance[];
|
|
419
|
+
/** Check if a Paw is healthy */
|
|
420
|
+
isHealthy(name: string): boolean;
|
|
421
|
+
/**
|
|
422
|
+
* Run GLOBAL perceive hooks — only Paws without tools.
|
|
423
|
+
* Paws with tools use lazy perceive (called just before their tool executes).
|
|
424
|
+
*/
|
|
425
|
+
runGlobalPerceiveHooks(context: AgentContext): Promise<AgentContext>;
|
|
426
|
+
/**
|
|
427
|
+
* Run LAZY perceive for a specific Paw — called just before its tool executes.
|
|
428
|
+
* Only runs if the Paw has an onPerceive hook registered.
|
|
429
|
+
*/
|
|
430
|
+
runLazyPerceive(pawName: string, context: AgentContext): Promise<AgentContext>;
|
|
431
|
+
/** Run all Observe hooks concurrently (fire-and-forget) */
|
|
432
|
+
runObserveHooks(result: ActionResult): void;
|
|
433
|
+
/** Run bootstrap hooks — called once at the start of a task */
|
|
434
|
+
runBootstrapHooks(context: AgentContext): Promise<AgentContext>;
|
|
435
|
+
/**
|
|
436
|
+
* Run compact hooks — called when context exceeds size threshold.
|
|
437
|
+
* Paws can compress/summarize messages to free up context window space.
|
|
438
|
+
*/
|
|
439
|
+
runCompactHooks(context: AgentContext): Promise<AgentContext>;
|
|
440
|
+
/** Call the Brain Paw's think function */
|
|
441
|
+
think(context: AgentContext): Promise<AgentPlan | null>;
|
|
442
|
+
/** Execute a tool on a subprocess Paw */
|
|
443
|
+
executeRemoteTool(pawName: string, toolName: string, params: unknown): Promise<unknown>;
|
|
444
|
+
private callPerceive;
|
|
445
|
+
private callObserve;
|
|
446
|
+
private registerInProcessTools;
|
|
447
|
+
private setupTransportHandlers;
|
|
448
|
+
/** Forward bus events to a Paw that subscribed */
|
|
449
|
+
private setupBusForwarding;
|
|
450
|
+
/** Handle state queries from Paws */
|
|
451
|
+
private handleQuery;
|
|
452
|
+
private waitForRegistration;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/** A Skill definition — parsed from SKILL.md */
|
|
456
|
+
interface SkillDefinition {
|
|
457
|
+
name: string;
|
|
458
|
+
description: string;
|
|
459
|
+
version?: string;
|
|
460
|
+
requiredTools: string[];
|
|
461
|
+
optionalTools: string[];
|
|
462
|
+
instructions: string;
|
|
463
|
+
tags: string[];
|
|
464
|
+
/** OpenClaw compatibility — runtime requirements */
|
|
465
|
+
requires?: SkillRequirements;
|
|
466
|
+
}
|
|
467
|
+
/** Runtime requirements (OpenClaw-compatible) */
|
|
468
|
+
interface SkillRequirements {
|
|
469
|
+
/** Environment variables the skill expects */
|
|
470
|
+
env: string[];
|
|
471
|
+
/** CLI binaries that must all be installed */
|
|
472
|
+
bins: string[];
|
|
473
|
+
/** CLI binaries where at least one must exist */
|
|
474
|
+
anyBins: string[];
|
|
475
|
+
}
|
|
476
|
+
/** Runtime state of a loaded Skill */
|
|
477
|
+
interface SkillInstance {
|
|
478
|
+
name: string;
|
|
479
|
+
definition: SkillDefinition;
|
|
480
|
+
/** Path to the skill directory */
|
|
481
|
+
path: string;
|
|
482
|
+
active: boolean;
|
|
483
|
+
missingTools: string[];
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/** Manages loaded Skills and their activation state */
|
|
487
|
+
declare class SkillRegistry {
|
|
488
|
+
private bus;
|
|
489
|
+
private toolRegistry;
|
|
490
|
+
private projectRoot;
|
|
491
|
+
private skills;
|
|
492
|
+
constructor(bus: MessageBus, toolRegistry: ToolRegistry, projectRoot: string);
|
|
493
|
+
/** Load a Skill from a directory containing SKILL.md */
|
|
494
|
+
load(nameOrPath: string): Promise<boolean>;
|
|
495
|
+
/** Unload a Skill */
|
|
496
|
+
unload(name: string): boolean;
|
|
497
|
+
/** Re-run the resolver against the current tool registry */
|
|
498
|
+
resolve(): void;
|
|
499
|
+
/** Get all Skill instances */
|
|
500
|
+
list(): SkillInstance[];
|
|
501
|
+
/** Get active Skills only */
|
|
502
|
+
active(): SkillInstance[];
|
|
503
|
+
/** Get a Skill by name */
|
|
504
|
+
get(name: string): SkillInstance | undefined;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Sliding window counter rate limiter.
|
|
509
|
+
* Tracks timestamps per bucket and checks against limits.
|
|
510
|
+
*/
|
|
511
|
+
declare class RateLimiter {
|
|
512
|
+
private buckets;
|
|
513
|
+
/**
|
|
514
|
+
* Try to consume one token from the bucket.
|
|
515
|
+
* Returns true if the request is under the limit, false if rate-limited.
|
|
516
|
+
*/
|
|
517
|
+
tryConsume(bucket: string, limit: number, windowMs: number): boolean;
|
|
518
|
+
/**
|
|
519
|
+
* Returns the number of remaining tokens in the bucket for the current window.
|
|
520
|
+
*/
|
|
521
|
+
remaining(bucket: string, limit: number, windowMs: number): number;
|
|
522
|
+
/**
|
|
523
|
+
* Remove expired timestamps from a bucket.
|
|
524
|
+
*/
|
|
525
|
+
private cleanup;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/** Task states */
|
|
529
|
+
type TaskStatus = 'queued' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
530
|
+
/** A discrete unit of work for the agent loop */
|
|
531
|
+
interface AgentTask {
|
|
532
|
+
id: string;
|
|
533
|
+
source: 'user' | 'schedule' | 'heartbeat' | 'paw';
|
|
534
|
+
input: string;
|
|
535
|
+
status: TaskStatus;
|
|
536
|
+
createdAt: number;
|
|
537
|
+
startedAt?: number;
|
|
538
|
+
completedAt?: number;
|
|
539
|
+
result?: string;
|
|
540
|
+
error?: string;
|
|
541
|
+
sessionId?: string;
|
|
542
|
+
metadata?: Record<string, unknown>;
|
|
543
|
+
}
|
|
544
|
+
type TaskRunner = (task: AgentTask) => Promise<void>;
|
|
545
|
+
/** FIFO task queue with configurable concurrency */
|
|
546
|
+
declare class TaskQueue {
|
|
547
|
+
private bus;
|
|
548
|
+
private concurrency;
|
|
549
|
+
private rateLimiter?;
|
|
550
|
+
private rateLimits?;
|
|
551
|
+
private queue;
|
|
552
|
+
private running;
|
|
553
|
+
private completed;
|
|
554
|
+
private runner;
|
|
555
|
+
private draining;
|
|
556
|
+
constructor(bus: MessageBus, concurrency?: number, rateLimiter?: RateLimiter | undefined, rateLimits?: RateLimits | undefined);
|
|
557
|
+
/** Set the task runner function (called by the agent loop) */
|
|
558
|
+
setRunner(runner: TaskRunner): void;
|
|
559
|
+
/** Enqueue a new task */
|
|
560
|
+
enqueue(input: string, source?: 'user' | 'schedule' | 'heartbeat' | 'paw', options?: {
|
|
561
|
+
sessionId?: string;
|
|
562
|
+
metadata?: Record<string, unknown>;
|
|
563
|
+
}): AgentTask;
|
|
564
|
+
/** Cancel a task by ID */
|
|
565
|
+
cancel(taskId: string): boolean;
|
|
566
|
+
/** Get all tasks (queued + running + completed) */
|
|
567
|
+
list(): AgentTask[];
|
|
568
|
+
/** Get a task by ID */
|
|
569
|
+
get(taskId: string): AgentTask | undefined;
|
|
570
|
+
/** Check if a task has been cancelled */
|
|
571
|
+
isCancelled(taskId: string): boolean;
|
|
572
|
+
private drain;
|
|
573
|
+
private runTask;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
interface LoopDependencies {
|
|
577
|
+
bus: MessageBus;
|
|
578
|
+
toolRegistry: ToolRegistry;
|
|
579
|
+
pawRegistry: PawRegistry;
|
|
580
|
+
skillRegistry: SkillRegistry;
|
|
581
|
+
io: VoleIO;
|
|
582
|
+
config: LoopConfig;
|
|
583
|
+
toolProfiles?: Record<string, ToolProfile>;
|
|
584
|
+
rateLimiter?: RateLimiter;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Run the agent loop for a single task.
|
|
588
|
+
* Perceive → Think → Act → Observe → loop
|
|
589
|
+
*/
|
|
590
|
+
declare function runAgentLoop(task: AgentTask, deps: LoopDependencies): Promise<void>;
|
|
591
|
+
|
|
592
|
+
/** In-memory store for brain-created recurring schedules */
|
|
593
|
+
declare class SchedulerStore {
|
|
594
|
+
private schedules;
|
|
595
|
+
/** Create or replace a recurring schedule */
|
|
596
|
+
add(id: string, input: string, intervalMinutes: number, onTick: () => void): void;
|
|
597
|
+
/** Cancel a schedule by ID */
|
|
598
|
+
cancel(id: string): boolean;
|
|
599
|
+
/** List all active schedules */
|
|
600
|
+
list(): Array<{
|
|
601
|
+
id: string;
|
|
602
|
+
input: string;
|
|
603
|
+
intervalMinutes: number;
|
|
604
|
+
createdAt: number;
|
|
605
|
+
}>;
|
|
606
|
+
/** Clear all schedules (for shutdown) */
|
|
607
|
+
clearAll(): void;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Hook phase definitions.
|
|
612
|
+
*
|
|
613
|
+
* The actual hook execution logic lives in PawRegistry (perceive/observe hooks)
|
|
614
|
+
* and the agent loop (think/act orchestration). This module defines the hook
|
|
615
|
+
* lifecycle constants and types used across the system.
|
|
616
|
+
*/
|
|
617
|
+
/** The four phases of the agent loop */
|
|
618
|
+
type LoopPhase = 'perceive' | 'think' | 'act' | 'observe';
|
|
619
|
+
/** Phase ordering for logging and tracing */
|
|
620
|
+
declare const PHASE_ORDER: readonly LoopPhase[];
|
|
621
|
+
|
|
622
|
+
/** Resolve a Paw package path from its name */
|
|
623
|
+
declare function resolvePawPath(name: string, projectRoot: string): string;
|
|
624
|
+
/** Read and validate a vole-paw.json manifest */
|
|
625
|
+
declare function readPawManifest(pawPath: string): Promise<PawManifest | null>;
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Compute effective permissions as the intersection of
|
|
629
|
+
* what the manifest requests and what the config grants.
|
|
630
|
+
*/
|
|
631
|
+
declare function computeEffectivePermissions(manifest: PawManifest, config: PawConfig): EffectivePermissions;
|
|
632
|
+
/**
|
|
633
|
+
* Validate that a Paw's manifest permissions are reasonable.
|
|
634
|
+
* Returns warnings (non-blocking) for review.
|
|
635
|
+
*/
|
|
636
|
+
declare function validatePermissions(manifest: PawManifest, config: PawConfig): string[];
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Resolve Skill activation based on the current tool registry
|
|
640
|
+
* and runtime requirements (env vars, binaries).
|
|
641
|
+
*
|
|
642
|
+
* A Skill is active if:
|
|
643
|
+
* - All requiredTools are registered in the tool registry
|
|
644
|
+
* - All requires.env vars are set in the environment
|
|
645
|
+
* - All requires.bins are available on PATH
|
|
646
|
+
* - At least one of requires.anyBins is available (if specified)
|
|
647
|
+
*/
|
|
648
|
+
declare function resolveSkills(skills: SkillInstance[], toolRegistry: ToolRegistry): void;
|
|
649
|
+
/** Build ActiveSkill entries for the AgentContext */
|
|
650
|
+
declare function buildActiveSkills(skills: SkillInstance[], toolRegistry: ToolRegistry): ActiveSkill[];
|
|
651
|
+
|
|
652
|
+
/** Default TTY I/O implementation using stdin/stdout */
|
|
653
|
+
declare function createTtyIO(): VoleIO;
|
|
654
|
+
|
|
655
|
+
interface VoleEngine {
|
|
656
|
+
bus: ReturnType<typeof createMessageBus>;
|
|
657
|
+
toolRegistry: ToolRegistry;
|
|
658
|
+
pawRegistry: PawRegistry;
|
|
659
|
+
skillRegistry: SkillRegistry;
|
|
660
|
+
taskQueue: TaskQueue;
|
|
661
|
+
io: VoleIO;
|
|
662
|
+
config: VoleConfig;
|
|
663
|
+
/** Start the engine — load Paws and Skills */
|
|
664
|
+
start(): Promise<void>;
|
|
665
|
+
/** Submit a task for execution */
|
|
666
|
+
run(input: string, source?: 'user' | 'schedule' | 'heartbeat' | 'paw', sessionId?: string): void;
|
|
667
|
+
/** Graceful shutdown */
|
|
668
|
+
shutdown(): Promise<void>;
|
|
669
|
+
}
|
|
670
|
+
/** Create and initialize the OpenVole engine */
|
|
671
|
+
declare function createEngine(projectRoot: string, options?: {
|
|
672
|
+
io?: VoleIO;
|
|
673
|
+
configPath?: string;
|
|
674
|
+
}): Promise<VoleEngine>;
|
|
675
|
+
|
|
676
|
+
export { type ActionError, type ActionErrorCode, type ActionResult, type ActiveSkill, type AgentContext, type AgentMessage, type AgentPlan, type AgentTask, type BootstrapHook, type BusEvents, type CompactHook, type EffectivePermissions, type HeartbeatConfig, type LoopConfig, type LoopDependencies, type LoopPhase, type MessageBus, type ObserveHook, PHASE_ORDER, type PawConfig, type PawDefinition, type PawInstance, type PawManifest, PawRegistry, type PerceiveHook, type PlannedAction, RateLimiter, type RateLimits, type ScheduleHook, SchedulerStore, type SkillDefinition, type SkillInstance, SkillRegistry, TaskQueue, type TaskStatus, type ToolDefinition, ToolRegistry, type ToolRegistryEntry, type ToolSummary, type TransportType, type VoleConfig, type VoleEngine, type VoleIO, type VoleLock, addPawToLock, addSkillToLock, buildActiveSkills, computeEffectivePermissions, createActionError, createAgentContext, createEngine, createMessageBus, createTtyIO, defineConfig, failureResult, loadConfig, readLockFile, readPawManifest, removePawFromLock, removeSkillFromLock, resolvePawPath, resolveSkills, runAgentLoop, successResult, validatePermissions, writeLockFile };
|