aisnitch 0.2.19 → 0.2.21
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/cli/index.cjs +1246 -100
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +1222 -76
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +1808 -133
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1491 -4
- package/dist/index.d.ts +1491 -4
- package/dist/index.js +1736 -122
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -68,6 +68,8 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
68
68
|
kiro: "kiro";
|
|
69
69
|
"augment-code": "augment-code";
|
|
70
70
|
mistral: "mistral";
|
|
71
|
+
zed: "zed";
|
|
72
|
+
pi: "pi";
|
|
71
73
|
unknown: "unknown";
|
|
72
74
|
}> & z.core.$partial, z.ZodObject<{
|
|
73
75
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -106,7 +108,7 @@ type AISnitchConfig = infer<typeof ConfigSchema>;
|
|
|
106
108
|
* @description Runtime Zod schemas and constants for the AISnitch CloudEvents-based event contract.
|
|
107
109
|
* @functions
|
|
108
110
|
* → createUuidV7
|
|
109
|
-
* @exports AISNITCH_EVENT_TYPES, TOOL_NAMES, ERROR_TYPES, CESP_CATEGORIES, ToolInputSchema, EventDataSchema, AISnitchEventTypeSchema, ToolNameSchema, ErrorTypeSchema, CESPCategorySchema, AISnitchEventSchema, createUuidV7
|
|
111
|
+
* @exports AISNITCH_EVENT_TYPES, TOOL_NAMES, ERROR_TYPES, CESP_CATEGORIES, ToolInputSchema, ToolCallNameSchema, ThinkingContentSchema, FinalMessageSchema, ToolResultSchema, MessageContentSchema, EventDataSchema, AISnitchEventTypeSchema, ToolNameSchema, ErrorTypeSchema, CESPCategorySchema, AISnitchEventSchema, createUuidV7
|
|
110
112
|
* @see ./types.ts
|
|
111
113
|
* @see ./cesp.ts
|
|
112
114
|
* @see ./factory.ts
|
|
@@ -119,7 +121,7 @@ declare const AISNITCH_EVENT_TYPES: readonly ["session.start", "session.end", "t
|
|
|
119
121
|
/**
|
|
120
122
|
* Supported AI tool identifiers recognized by AISnitch.
|
|
121
123
|
*/
|
|
122
|
-
declare const TOOL_NAMES: readonly ["claude-code", "opencode", "gemini-cli", "codex", "goose", "copilot-cli", "cursor", "aider", "amp", "cline", "continue", "windsurf", "qwen-code", "openclaw", "openhands", "kilo", "devin", "kiro", "augment-code", "mistral", "unknown"];
|
|
124
|
+
declare const TOOL_NAMES: readonly ["claude-code", "opencode", "gemini-cli", "codex", "goose", "copilot-cli", "cursor", "aider", "amp", "cline", "continue", "windsurf", "qwen-code", "openclaw", "openhands", "kilo", "devin", "kiro", "augment-code", "mistral", "zed", "pi", "unknown"];
|
|
123
125
|
/**
|
|
124
126
|
* Normalized error categories attached to `agent.error` events.
|
|
125
127
|
*/
|
|
@@ -139,6 +141,34 @@ declare const ToolInputSchema: z.ZodObject<{
|
|
|
139
141
|
filePath: z.ZodOptional<z.ZodString>;
|
|
140
142
|
command: z.ZodOptional<z.ZodString>;
|
|
141
143
|
}, z.core.$strict>;
|
|
144
|
+
/**
|
|
145
|
+
* 📖 Thinking content extracted from AI model reasoning chains.
|
|
146
|
+
* This field captures the internal "thinking" or reasoning output that
|
|
147
|
+
* models like Claude produce before generating their final response.
|
|
148
|
+
*/
|
|
149
|
+
declare const ThinkingContentSchema: z.ZodString;
|
|
150
|
+
/**
|
|
151
|
+
* 📖 Tool call name — the specific tool being invoked.
|
|
152
|
+
* Examples: "Edit", "Bash", "Grep", "Read", "Write", "WebSearch"
|
|
153
|
+
* Different from `toolInput` which contains the tool's parameters.
|
|
154
|
+
*/
|
|
155
|
+
declare const ToolCallNameSchema: z.ZodString;
|
|
156
|
+
/**
|
|
157
|
+
* 📖 Final message shown at the end of an AI run.
|
|
158
|
+
* This is typically a summary, completion message, or result text
|
|
159
|
+
* displayed to the user after the agent finishes its work.
|
|
160
|
+
*/
|
|
161
|
+
declare const FinalMessageSchema: z.ZodString;
|
|
162
|
+
/**
|
|
163
|
+
* 📖 Tool execution result — short result from a tool call.
|
|
164
|
+
* Can include success messages, error messages, or short outputs.
|
|
165
|
+
*/
|
|
166
|
+
declare const ToolResultSchema: z.ZodString;
|
|
167
|
+
/**
|
|
168
|
+
* 📖 Raw message content from AI responses.
|
|
169
|
+
* Captures the actual text generated by the model before tool calls.
|
|
170
|
+
*/
|
|
171
|
+
declare const MessageContentSchema: z.ZodString;
|
|
142
172
|
/**
|
|
143
173
|
* Runtime schema for the supported tool names.
|
|
144
174
|
*/
|
|
@@ -163,6 +193,8 @@ declare const ToolNameSchema: z.ZodEnum<{
|
|
|
163
193
|
kiro: "kiro";
|
|
164
194
|
"augment-code": "augment-code";
|
|
165
195
|
mistral: "mistral";
|
|
196
|
+
zed: "zed";
|
|
197
|
+
pi: "pi";
|
|
166
198
|
unknown: "unknown";
|
|
167
199
|
}>;
|
|
168
200
|
/**
|
|
@@ -248,6 +280,11 @@ declare const EventDataSchema: z.ZodObject<{
|
|
|
248
280
|
instanceId: z.ZodOptional<z.ZodString>;
|
|
249
281
|
instanceIndex: z.ZodOptional<z.ZodNumber>;
|
|
250
282
|
instanceTotal: z.ZodOptional<z.ZodNumber>;
|
|
283
|
+
thinkingContent: z.ZodOptional<z.ZodString>;
|
|
284
|
+
toolCallName: z.ZodOptional<z.ZodString>;
|
|
285
|
+
finalMessage: z.ZodOptional<z.ZodString>;
|
|
286
|
+
toolResult: z.ZodOptional<z.ZodString>;
|
|
287
|
+
messageContent: z.ZodOptional<z.ZodString>;
|
|
251
288
|
}, z.core.$strict>;
|
|
252
289
|
/**
|
|
253
290
|
* Runtime schema for the full normalized AISnitch event envelope.
|
|
@@ -292,6 +329,8 @@ declare const AISnitchEventSchema: z.ZodObject<{
|
|
|
292
329
|
kiro: "kiro";
|
|
293
330
|
"augment-code": "augment-code";
|
|
294
331
|
mistral: "mistral";
|
|
332
|
+
zed: "zed";
|
|
333
|
+
pi: "pi";
|
|
295
334
|
unknown: "unknown";
|
|
296
335
|
}>;
|
|
297
336
|
'aisnitch.sessionid': z.ZodString;
|
|
@@ -336,6 +375,11 @@ declare const AISnitchEventSchema: z.ZodObject<{
|
|
|
336
375
|
instanceId: z.ZodOptional<z.ZodString>;
|
|
337
376
|
instanceIndex: z.ZodOptional<z.ZodNumber>;
|
|
338
377
|
instanceTotal: z.ZodOptional<z.ZodNumber>;
|
|
378
|
+
thinkingContent: z.ZodOptional<z.ZodString>;
|
|
379
|
+
toolCallName: z.ZodOptional<z.ZodString>;
|
|
380
|
+
finalMessage: z.ZodOptional<z.ZodString>;
|
|
381
|
+
toolResult: z.ZodOptional<z.ZodString>;
|
|
382
|
+
messageContent: z.ZodOptional<z.ZodString>;
|
|
339
383
|
}, z.core.$strict>;
|
|
340
384
|
}, z.core.$strict>;
|
|
341
385
|
|
|
@@ -440,6 +484,11 @@ declare const NormalizedAdapterHookPayloadSchema: z.ZodObject<{
|
|
|
440
484
|
instanceId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
441
485
|
instanceIndex: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
|
|
442
486
|
instanceTotal: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
|
|
487
|
+
thinkingContent: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
488
|
+
toolCallName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
489
|
+
finalMessage: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
490
|
+
toolResult: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
491
|
+
messageContent: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
443
492
|
}, z.core.$strict>>;
|
|
444
493
|
pid: z.ZodOptional<z.ZodNumber>;
|
|
445
494
|
transcriptPath: z.ZodOptional<z.ZodString>;
|
|
@@ -1036,6 +1085,91 @@ declare class OpenCodeAdapter extends BaseAdapter {
|
|
|
1036
1085
|
private pollOpenCodeProcesses;
|
|
1037
1086
|
}
|
|
1038
1087
|
|
|
1088
|
+
/**
|
|
1089
|
+
* @file src/adapters/pi.ts
|
|
1090
|
+
* @description Pi AI Agent adapter using Pi's local API and log monitoring.
|
|
1091
|
+
* @functions
|
|
1092
|
+
* → detectPiInstance
|
|
1093
|
+
* @exports PiAdapter
|
|
1094
|
+
* @see ./base.ts
|
|
1095
|
+
* @see ../core/events/types.ts
|
|
1096
|
+
*/
|
|
1097
|
+
|
|
1098
|
+
/**
|
|
1099
|
+
* 📖 Pi is a coding agent by MiniMax. This adapter detects Pi activity through:
|
|
1100
|
+
* 1. Process detection (pgrep for pi processes)
|
|
1101
|
+
* 2. MiniMax API / local socket detection
|
|
1102
|
+
* 3. Log file monitoring
|
|
1103
|
+
*/
|
|
1104
|
+
declare class PiAdapter extends BaseAdapter {
|
|
1105
|
+
readonly displayName = "Pi (MiniMax)";
|
|
1106
|
+
readonly name: "pi";
|
|
1107
|
+
readonly strategies: readonly InterceptionStrategy[];
|
|
1108
|
+
private readonly apiPort;
|
|
1109
|
+
private readonly logPath;
|
|
1110
|
+
private poller;
|
|
1111
|
+
private activePiSessions;
|
|
1112
|
+
private lastCheckedTime;
|
|
1113
|
+
constructor(options: AdapterRuntimeOptions);
|
|
1114
|
+
start(): Promise<void>;
|
|
1115
|
+
stop(): Promise<void>;
|
|
1116
|
+
handleHook(payload: unknown): Promise<void>;
|
|
1117
|
+
private startPolling;
|
|
1118
|
+
private pollPiActivity;
|
|
1119
|
+
private detectPiInstance;
|
|
1120
|
+
private checkMiniMaxApi;
|
|
1121
|
+
private processPiApiResponse;
|
|
1122
|
+
private emitSessionStart;
|
|
1123
|
+
private emitThinking;
|
|
1124
|
+
private emitToolCall;
|
|
1125
|
+
private emitOutput;
|
|
1126
|
+
private emitError;
|
|
1127
|
+
private emitIdle;
|
|
1128
|
+
private mapEventType;
|
|
1129
|
+
private buildEventData;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
/**
|
|
1133
|
+
* @file src/adapters/zed.ts
|
|
1134
|
+
* @description Zed AI Agent adapter using log file monitoring and IPC detection.
|
|
1135
|
+
* @functions
|
|
1136
|
+
* → extractZedEventFromLog
|
|
1137
|
+
* @exports ZedAdapter
|
|
1138
|
+
* @see ./base.ts
|
|
1139
|
+
* @see ../core/events/types.ts
|
|
1140
|
+
*/
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* 📖 Zed Agent (zed.dev) exposes a local HTTP API on port 9876 for its agent.
|
|
1144
|
+
* This adapter polls that endpoint and watches Zed's log file for activity.
|
|
1145
|
+
*/
|
|
1146
|
+
declare class ZedAdapter extends BaseAdapter {
|
|
1147
|
+
readonly displayName = "Zed AI";
|
|
1148
|
+
readonly name: "zed";
|
|
1149
|
+
readonly strategies: readonly InterceptionStrategy[];
|
|
1150
|
+
private readonly logPaths;
|
|
1151
|
+
private readonly apiPort;
|
|
1152
|
+
private readonly pollIntervalMs;
|
|
1153
|
+
private poller;
|
|
1154
|
+
private lastEventTime;
|
|
1155
|
+
private activeZedSessions;
|
|
1156
|
+
constructor(options: AdapterRuntimeOptions);
|
|
1157
|
+
start(): Promise<void>;
|
|
1158
|
+
stop(): Promise<void>;
|
|
1159
|
+
handleHook(payload: unknown): Promise<void>;
|
|
1160
|
+
private startPolling;
|
|
1161
|
+
private pollZedStatus;
|
|
1162
|
+
private checkLogFiles;
|
|
1163
|
+
private parseLogContent;
|
|
1164
|
+
private extractZedEventFromLog;
|
|
1165
|
+
private emitSessionStart;
|
|
1166
|
+
private emitThinking;
|
|
1167
|
+
private emitToolCall;
|
|
1168
|
+
private emitIdle;
|
|
1169
|
+
private mapEventType;
|
|
1170
|
+
private buildEventData;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1039
1173
|
/**
|
|
1040
1174
|
* @file src/adapters/registry.ts
|
|
1041
1175
|
* @description Adapter registry that owns built-in adapter instances and orchestrates their lifecycle.
|
|
@@ -1164,12 +1298,402 @@ declare function analyzeTerminalOutputChunk(input: {
|
|
|
1164
1298
|
* @see ./codex.ts
|
|
1165
1299
|
* @see ./openclaw.ts
|
|
1166
1300
|
* @see ./opencode.ts
|
|
1301
|
+
* @see ./pi.ts
|
|
1302
|
+
* @see ./zed.ts
|
|
1167
1303
|
*/
|
|
1168
1304
|
|
|
1169
1305
|
/**
|
|
1170
1306
|
* Instantiates the built-in adapters that ship with AISnitch.
|
|
1171
1307
|
*/
|
|
1172
|
-
declare function createDefaultAdapters(options: AdapterRuntimeOptions): readonly [AiderAdapter, ClaudeCodeAdapter, CopilotCLIAdapter, CursorAdapter, DevinAdapter, GeminiCLIAdapter, GooseAdapter, KiloAdapter, CodexAdapter, OpenClawAdapter, OpenCodeAdapter];
|
|
1308
|
+
declare function createDefaultAdapters(options: AdapterRuntimeOptions): readonly [AiderAdapter, ClaudeCodeAdapter, CopilotCLIAdapter, CursorAdapter, DevinAdapter, GeminiCLIAdapter, GooseAdapter, KiloAdapter, CodexAdapter, OpenClawAdapter, OpenCodeAdapter, PiAdapter, ZedAdapter];
|
|
1309
|
+
|
|
1310
|
+
/**
|
|
1311
|
+
* @file src/core/errors.ts
|
|
1312
|
+
* @description Centralized error hierarchy for AISnitch with typed error codes and context.
|
|
1313
|
+
*
|
|
1314
|
+
* This module provides a consistent error taxonomy across the entire application:
|
|
1315
|
+
* - `AISnitchError` — base class for all AISnitch-specific errors
|
|
1316
|
+
* - `AdapterError` — adapter lifecycle, parsing, or emission failures
|
|
1317
|
+
* - `PipelineError` — pipeline orchestration, component startup, or shutdown failures
|
|
1318
|
+
* - `ValidationError` — Zod parsing failures and schema violations
|
|
1319
|
+
* - `NetworkError` — HTTP, WebSocket, or Unix Domain Socket failures
|
|
1320
|
+
* - `TimeoutError` — async operations that exceed their deadline
|
|
1321
|
+
*
|
|
1322
|
+
* Each error carries a machine-readable `code` field for programmatic handling
|
|
1323
|
+
* and an optional `context` bag for debugging. Errors serialize cleanly to JSON
|
|
1324
|
+
* so they can be logged via pino without losing structure.
|
|
1325
|
+
*
|
|
1326
|
+
* @functions
|
|
1327
|
+
* → none
|
|
1328
|
+
* @exports AISnitchError, AdapterError, PipelineError, ValidationError, NetworkError, TimeoutError, isAISnitchError, isRetryableError
|
|
1329
|
+
* @see ./result.ts
|
|
1330
|
+
* @see ./retry.ts
|
|
1331
|
+
* @see ./timeout.ts
|
|
1332
|
+
*/
|
|
1333
|
+
/**
|
|
1334
|
+
* Base class for all AISnitch-specific errors.
|
|
1335
|
+
*
|
|
1336
|
+
* @example
|
|
1337
|
+
* ```typescript
|
|
1338
|
+
* throw new AISnitchError(
|
|
1339
|
+
* 'Event validation failed',
|
|
1340
|
+
* 'EVENT_VALIDATION_ERROR',
|
|
1341
|
+
* { eventId: event.id, issues: parseResult.error.issues }
|
|
1342
|
+
* );
|
|
1343
|
+
* ```
|
|
1344
|
+
*/
|
|
1345
|
+
declare class AISnitchError extends Error {
|
|
1346
|
+
/**
|
|
1347
|
+
* Machine-readable error code for programmatic handling.
|
|
1348
|
+
* Format: `SUBCATEGORY_SPECIFIC_DETAIL` (uppercase with underscores).
|
|
1349
|
+
*/
|
|
1350
|
+
readonly code: string;
|
|
1351
|
+
/**
|
|
1352
|
+
* Arbitrary context bag forwarded to the logger for structured debugging.
|
|
1353
|
+
*/
|
|
1354
|
+
readonly context?: Readonly<Record<string, unknown>>;
|
|
1355
|
+
constructor(message: string, code: string, context?: Readonly<Record<string, unknown>>);
|
|
1356
|
+
/**
|
|
1357
|
+
* Full error chain for logging: `[name] code — message`.
|
|
1358
|
+
*/
|
|
1359
|
+
toString(): string;
|
|
1360
|
+
/**
|
|
1361
|
+
* JSON serialization friendly to pino serializers.
|
|
1362
|
+
*/
|
|
1363
|
+
toJSON(): object;
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* Errors originating from adapter lifecycle, payload parsing, or event emission.
|
|
1367
|
+
*
|
|
1368
|
+
* @example
|
|
1369
|
+
* ```typescript
|
|
1370
|
+
* throw new AdapterError(
|
|
1371
|
+
* 'Claude Code transcript read failed',
|
|
1372
|
+
* 'ADAPTER_CLAUDE_CODE_FILE_ERROR',
|
|
1373
|
+
* { filePath: transcriptPath, cause: error }
|
|
1374
|
+
* );
|
|
1375
|
+
* ```
|
|
1376
|
+
*/
|
|
1377
|
+
declare class AdapterError extends AISnitchError {
|
|
1378
|
+
constructor(message: string, code: string, context?: Readonly<Record<string, unknown>>);
|
|
1379
|
+
/**
|
|
1380
|
+
* Factory for adapter-specific errors with auto-generated codes.
|
|
1381
|
+
*/
|
|
1382
|
+
static withAutoCode(message: string, tool: string, context?: Readonly<Record<string, unknown>>): AdapterError;
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Errors originating from pipeline orchestration, component startup, or shutdown.
|
|
1386
|
+
*
|
|
1387
|
+
* @example
|
|
1388
|
+
* ```typescript
|
|
1389
|
+
* throw new PipelineError(
|
|
1390
|
+
* 'Failed to start WebSocket server',
|
|
1391
|
+
* 'PIPELINE_WS_START_FAILED',
|
|
1392
|
+
* { port: configuredPort, cause: error }
|
|
1393
|
+
* );
|
|
1394
|
+
* ```
|
|
1395
|
+
*/
|
|
1396
|
+
declare class PipelineError extends AISnitchError {
|
|
1397
|
+
constructor(message: string, code: string, context?: Readonly<Record<string, unknown>>);
|
|
1398
|
+
}
|
|
1399
|
+
/**
|
|
1400
|
+
* Errors from Zod schema parsing failures and data validation violations.
|
|
1401
|
+
*
|
|
1402
|
+
* @example
|
|
1403
|
+
* ```typescript
|
|
1404
|
+
* const result = EventDataSchema.safeParse(rawPayload);
|
|
1405
|
+
* if (!result.success) {
|
|
1406
|
+
* throw new ValidationError(
|
|
1407
|
+
* 'Invalid event data payload',
|
|
1408
|
+
* 'VALIDATION_EVENT_DATA_INVALID',
|
|
1409
|
+
* { issues: result.error.issues }
|
|
1410
|
+
* );
|
|
1411
|
+
* }
|
|
1412
|
+
* ```
|
|
1413
|
+
*/
|
|
1414
|
+
declare class ValidationError extends AISnitchError {
|
|
1415
|
+
constructor(message: string, code: string, context?: Readonly<Record<string, unknown>>);
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* Errors from network operations: HTTP requests, WebSocket connections, UDS.
|
|
1419
|
+
*
|
|
1420
|
+
* @example
|
|
1421
|
+
* ```typescript
|
|
1422
|
+
* throw new NetworkError(
|
|
1423
|
+
* 'Health endpoint unreachable',
|
|
1424
|
+
* 'NETWORK_HTTP_CONNECT_FAILED',
|
|
1425
|
+
* { host: '127.0.0.1', port: 4821, cause: error }
|
|
1426
|
+
* );
|
|
1427
|
+
* ```
|
|
1428
|
+
*/
|
|
1429
|
+
declare class NetworkError extends AISnitchError {
|
|
1430
|
+
constructor(message: string, code: string, context?: Readonly<Record<string, unknown>>);
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Errors from async operations that exceed their configured deadline.
|
|
1434
|
+
*
|
|
1435
|
+
* @example
|
|
1436
|
+
* ```typescript
|
|
1437
|
+
* throw new TimeoutError(
|
|
1438
|
+
* 'Adapter stop timed out after 5 seconds',
|
|
1439
|
+
* 'TIMEOUT_SHUTDOWN',
|
|
1440
|
+
* { component: 'ClaudeCodeAdapter', timeoutMs: 5_000 }
|
|
1441
|
+
* );
|
|
1442
|
+
* ```
|
|
1443
|
+
*/
|
|
1444
|
+
declare class TimeoutError extends AISnitchError {
|
|
1445
|
+
constructor(message: string, code: string, context?: Readonly<Record<string, unknown>>);
|
|
1446
|
+
}
|
|
1447
|
+
/**
|
|
1448
|
+
* Type guard to narrow any `unknown` error to an AISnitch error.
|
|
1449
|
+
*
|
|
1450
|
+
* @example
|
|
1451
|
+
* ```typescript
|
|
1452
|
+
* } catch (error: unknown) {
|
|
1453
|
+
* if (isAISnitchError(error)) {
|
|
1454
|
+
* console.error(`AISnitch error ${error.code}: ${error.message}`);
|
|
1455
|
+
* } else {
|
|
1456
|
+
* console.error('Unexpected error', error);
|
|
1457
|
+
* }
|
|
1458
|
+
* }
|
|
1459
|
+
* ```
|
|
1460
|
+
*/
|
|
1461
|
+
declare function isAISnitchError(error: unknown): error is AISnitchError;
|
|
1462
|
+
/**
|
|
1463
|
+
* Determines whether an error is safe to retry (transient vs. permanent).
|
|
1464
|
+
*
|
|
1465
|
+
* Returns `true` for network timeouts, connection reset, and rate-limit errors.
|
|
1466
|
+
* Returns `false` for validation errors, authentication failures, and programming bugs.
|
|
1467
|
+
*
|
|
1468
|
+
* @example
|
|
1469
|
+
* ```typescript
|
|
1470
|
+
* try {
|
|
1471
|
+
* return await operation();
|
|
1472
|
+
* } catch (error: unknown) {
|
|
1473
|
+
* if (isRetryableError(error)) {
|
|
1474
|
+
* throw error; // let retry logic handle it
|
|
1475
|
+
* }
|
|
1476
|
+
* throw error; // propagate as-is (non-retryable)
|
|
1477
|
+
* }
|
|
1478
|
+
* ```
|
|
1479
|
+
*/
|
|
1480
|
+
declare function isRetryableError(error: unknown): boolean;
|
|
1481
|
+
|
|
1482
|
+
/**
|
|
1483
|
+
* @file src/core/circuit-breaker.ts
|
|
1484
|
+
* @description Circuit breaker pattern implementation for resilient adapter operation.
|
|
1485
|
+
*
|
|
1486
|
+
* The circuit breaker prevents cascading failures when an adapter repeatedly fails:
|
|
1487
|
+
*
|
|
1488
|
+
* ```
|
|
1489
|
+
* CLOSED (normal) ──[N failures]──→ OPEN (failing fast)
|
|
1490
|
+
* ↑ │
|
|
1491
|
+
* │ [half-open after timeout]
|
|
1492
|
+
* │ ↓
|
|
1493
|
+
* └──────[success]──── HALF-OPEN (testing recovery)
|
|
1494
|
+
* ```
|
|
1495
|
+
*
|
|
1496
|
+
* When an adapter fails `threshold` times within `windowMs`, the breaker opens:
|
|
1497
|
+
* - Subsequent calls fail immediately with `CircuitOpenError` (no network round-trips)
|
|
1498
|
+
* - After `halfOpenAfterMs`, one test call is allowed to check recovery
|
|
1499
|
+
* - If it succeeds → close the circuit (back to normal operation)
|
|
1500
|
+
* - If it fails → reopen and wait again
|
|
1501
|
+
*
|
|
1502
|
+
* ## When to use this
|
|
1503
|
+
*
|
|
1504
|
+
* - Adapter `emit()` calls that can fail repeatedly (file system errors, hook timeouts)
|
|
1505
|
+
* - Network operations with unreliable backends
|
|
1506
|
+
* - Any operation where persistent failure is worse than temporary unavailability
|
|
1507
|
+
*
|
|
1508
|
+
* ## When NOT to use this
|
|
1509
|
+
*
|
|
1510
|
+
* - One-off errors that are unlikely to repeat
|
|
1511
|
+
* - Validation failures (these indicate a programming bug, not a transient fault)
|
|
1512
|
+
* - Operations that are already idempotent with built-in retry (prefer `withRetry`)
|
|
1513
|
+
*
|
|
1514
|
+
* @functions
|
|
1515
|
+
* → none
|
|
1516
|
+
* @exports CircuitState, CircuitOpenError, CircuitBreaker
|
|
1517
|
+
* @see ./errors.ts
|
|
1518
|
+
* @see ./retry.ts
|
|
1519
|
+
* @see ./timeout.ts
|
|
1520
|
+
*/
|
|
1521
|
+
|
|
1522
|
+
/**
|
|
1523
|
+
* Observable state of a circuit breaker.
|
|
1524
|
+
*/
|
|
1525
|
+
interface CircuitState {
|
|
1526
|
+
/**
|
|
1527
|
+
* Number of consecutive failures since last success.
|
|
1528
|
+
*/
|
|
1529
|
+
readonly failures: number;
|
|
1530
|
+
/**
|
|
1531
|
+
* Timestamp of the last failure (ms since epoch), or null if never failed.
|
|
1532
|
+
*/
|
|
1533
|
+
readonly lastFailureAt: number | null;
|
|
1534
|
+
/**
|
|
1535
|
+
* Current state of the circuit.
|
|
1536
|
+
* - `closed`: Normal operation, requests pass through
|
|
1537
|
+
* - `open`: Failing fast, requests are rejected immediately
|
|
1538
|
+
* - `half-open`: Testing recovery, one request is allowed through
|
|
1539
|
+
*/
|
|
1540
|
+
readonly state: 'closed' | 'open' | 'half-open';
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
* Error thrown when a circuit is open and the operation is rejected.
|
|
1544
|
+
*/
|
|
1545
|
+
declare class CircuitOpenError extends AISnitchError {
|
|
1546
|
+
readonly circuitId: string;
|
|
1547
|
+
readonly state: CircuitState;
|
|
1548
|
+
constructor(circuitId: string, state: CircuitState);
|
|
1549
|
+
toString(): string;
|
|
1550
|
+
}
|
|
1551
|
+
/**
|
|
1552
|
+
* Configuration for a circuit breaker instance.
|
|
1553
|
+
*/
|
|
1554
|
+
interface CircuitBreakerOptions {
|
|
1555
|
+
/**
|
|
1556
|
+
* Number of consecutive failures before opening the circuit.
|
|
1557
|
+
* @default 5
|
|
1558
|
+
*/
|
|
1559
|
+
readonly failureThreshold?: number;
|
|
1560
|
+
/**
|
|
1561
|
+
* Time window in milliseconds to count failures within.
|
|
1562
|
+
* @default 60_000 (1 minute)
|
|
1563
|
+
*/
|
|
1564
|
+
readonly windowMs?: number;
|
|
1565
|
+
/**
|
|
1566
|
+
* Time to wait before transitioning from OPEN to HALF-OPEN.
|
|
1567
|
+
* @default 30_000 (30 seconds)
|
|
1568
|
+
*/
|
|
1569
|
+
readonly halfOpenAfterMs?: number;
|
|
1570
|
+
/**
|
|
1571
|
+
* Human-readable identifier for this circuit (shown in logs).
|
|
1572
|
+
* @default 'unnamed'
|
|
1573
|
+
*/
|
|
1574
|
+
readonly id?: string;
|
|
1575
|
+
/**
|
|
1576
|
+
* Optional predicate to decide which errors count toward the threshold.
|
|
1577
|
+
* Return `true` to count as a failure, `false` to ignore (success-like failure).
|
|
1578
|
+
* @default isRetryableError
|
|
1579
|
+
*/
|
|
1580
|
+
readonly shouldCountAsFailure?: (error: unknown) => boolean;
|
|
1581
|
+
/**
|
|
1582
|
+
* Set to `true` to reset the failure counter after any success in CLOSED state.
|
|
1583
|
+
* Set to `false` to only reset after `failureThreshold` successes.
|
|
1584
|
+
* @default true
|
|
1585
|
+
*/
|
|
1586
|
+
readonly resetOnSuccess?: boolean;
|
|
1587
|
+
}
|
|
1588
|
+
/**
|
|
1589
|
+
* Circuit breaker state machine.
|
|
1590
|
+
*
|
|
1591
|
+
* ## State transitions
|
|
1592
|
+
*
|
|
1593
|
+
* ```
|
|
1594
|
+
* CLOSED ──[failure + threshold reached]──→ OPEN
|
|
1595
|
+
* ▲ │
|
|
1596
|
+
* │ [halfOpenAfterMs elapsed]
|
|
1597
|
+
* │ ↓
|
|
1598
|
+
* │ HALF-OPEN
|
|
1599
|
+
* │ │
|
|
1600
|
+
* │ [test call succeeds]
|
|
1601
|
+
* │ ↓
|
|
1602
|
+
* └────────────[reset]───────────────────┘
|
|
1603
|
+
* ```
|
|
1604
|
+
*
|
|
1605
|
+
* ## Usage
|
|
1606
|
+
*
|
|
1607
|
+
* ```typescript
|
|
1608
|
+
* const breaker = new CircuitBreaker({
|
|
1609
|
+
* id: 'claude-code.emit',
|
|
1610
|
+
* failureThreshold: 3,
|
|
1611
|
+
* windowMs: 60_000,
|
|
1612
|
+
* });
|
|
1613
|
+
*
|
|
1614
|
+
* async function safeEmit(event: AISnitchEvent) {
|
|
1615
|
+
* return breaker.execute(() => adapter.emit(event));
|
|
1616
|
+
* }
|
|
1617
|
+
* ```
|
|
1618
|
+
*/
|
|
1619
|
+
declare class CircuitBreaker {
|
|
1620
|
+
private failures;
|
|
1621
|
+
private lastFailureAt;
|
|
1622
|
+
private state;
|
|
1623
|
+
private halfOpenTestStartedAt;
|
|
1624
|
+
private readonly options;
|
|
1625
|
+
constructor(options?: CircuitBreakerOptions);
|
|
1626
|
+
/**
|
|
1627
|
+
* Executes an async operation through the circuit breaker.
|
|
1628
|
+
*
|
|
1629
|
+
* - If the circuit is CLOSED → runs `fn` and updates state based on result
|
|
1630
|
+
* - If the circuit is HALF-OPEN → runs `fn` once to test recovery
|
|
1631
|
+
* - If the circuit is OPEN → throws `CircuitOpenError` immediately (no call)
|
|
1632
|
+
*
|
|
1633
|
+
* @param fn - The async operation to protect
|
|
1634
|
+
* @returns The result of `fn` if successful
|
|
1635
|
+
* @throws CircuitOpenError if the circuit is OPEN
|
|
1636
|
+
* @throws The error from `fn` if it throws (and `shouldCountAsFailure` returns true)
|
|
1637
|
+
*/
|
|
1638
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
1639
|
+
/**
|
|
1640
|
+
* Returns the current observable circuit state.
|
|
1641
|
+
*/
|
|
1642
|
+
getState(): CircuitState;
|
|
1643
|
+
/**
|
|
1644
|
+
* Forces the circuit to CLOSED (resets failure count and state).
|
|
1645
|
+
* Useful for manual recovery after a known-fix or after a maintenance window.
|
|
1646
|
+
*/
|
|
1647
|
+
reset(): void;
|
|
1648
|
+
/**
|
|
1649
|
+
* Pre-warms the circuit by performing one test call in HALF-OPEN state.
|
|
1650
|
+
* If the circuit is already HALF-OPEN, this does nothing.
|
|
1651
|
+
* If the circuit is CLOSED, this does nothing.
|
|
1652
|
+
*/
|
|
1653
|
+
preWarm(fn: () => Promise<void>): Promise<void>;
|
|
1654
|
+
private executeClosed;
|
|
1655
|
+
private executeHalfOpen;
|
|
1656
|
+
private onSuccess;
|
|
1657
|
+
private onFailure;
|
|
1658
|
+
private transitionToOpen;
|
|
1659
|
+
private transitionToHalfOpen;
|
|
1660
|
+
private transitionToClosed;
|
|
1661
|
+
private shouldTransitionToHalfOpen;
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Shared circuit breaker instances for common AISnitch operations.
|
|
1665
|
+
* These are module-level singletons to avoid creating new breakers on every call.
|
|
1666
|
+
*
|
|
1667
|
+
* Usage:
|
|
1668
|
+
* ```typescript
|
|
1669
|
+
* import { SHARED_BREAKERS } from './circuit-breaker.js';
|
|
1670
|
+
*
|
|
1671
|
+
* // Wrap an adapter emit call
|
|
1672
|
+
* await SHARED_BREAKERS.adapterEmit.execute(() => adapter.emit(event));
|
|
1673
|
+
* ```
|
|
1674
|
+
*/
|
|
1675
|
+
declare const SHARED_BREAKERS: Readonly<{
|
|
1676
|
+
/**
|
|
1677
|
+
* Breaker for adapter event emission.
|
|
1678
|
+
* Threshold: 5 failures in 60s → open for 30s → half-open test.
|
|
1679
|
+
*/
|
|
1680
|
+
adapterEmit: CircuitBreaker;
|
|
1681
|
+
/**
|
|
1682
|
+
* Breaker for file system operations (transcript reading, config loading).
|
|
1683
|
+
* More tolerant: 10 failures in 60s → open for 30s.
|
|
1684
|
+
*/
|
|
1685
|
+
fileSystem: CircuitBreaker;
|
|
1686
|
+
/**
|
|
1687
|
+
* Breaker for HTTP/HTTPS requests.
|
|
1688
|
+
* Stricter: 3 failures in 30s → open for 15s.
|
|
1689
|
+
*/
|
|
1690
|
+
httpRequest: CircuitBreaker;
|
|
1691
|
+
/**
|
|
1692
|
+
* Breaker for process detection operations.
|
|
1693
|
+
* Most tolerant: 20 failures in 60s → open for 10s.
|
|
1694
|
+
*/
|
|
1695
|
+
processDetection: CircuitBreaker;
|
|
1696
|
+
}>;
|
|
1173
1697
|
|
|
1174
1698
|
/**
|
|
1175
1699
|
* @file src/core/config/defaults.ts
|
|
@@ -1762,12 +2286,815 @@ declare class Pipeline {
|
|
|
1762
2286
|
* Returns the in-process event bus for direct wiring in tests or future TUI code.
|
|
1763
2287
|
*/
|
|
1764
2288
|
getEventBus(): EventBus;
|
|
2289
|
+
/**
|
|
2290
|
+
* Returns the adapter registry for graceful shutdown coordination.
|
|
2291
|
+
*/
|
|
2292
|
+
getAdapterRegistry(): AdapterRegistry | undefined;
|
|
2293
|
+
/**
|
|
2294
|
+
* Returns the HTTP receiver for graceful shutdown coordination.
|
|
2295
|
+
*/
|
|
2296
|
+
getHttpReceiver(): HTTPReceiver;
|
|
2297
|
+
/**
|
|
2298
|
+
* Returns the UDS server for graceful shutdown coordination.
|
|
2299
|
+
*/
|
|
2300
|
+
getUdsServer(): UDSServer;
|
|
2301
|
+
/**
|
|
2302
|
+
* Returns the WebSocket server for graceful shutdown coordination.
|
|
2303
|
+
*/
|
|
2304
|
+
getWsServer(): WSServer;
|
|
1765
2305
|
private getHealthSnapshot;
|
|
1766
2306
|
private handleHook;
|
|
1767
2307
|
private handleHookInner;
|
|
1768
2308
|
private isPlainRecord;
|
|
1769
2309
|
}
|
|
1770
2310
|
|
|
2311
|
+
/**
|
|
2312
|
+
* @file src/core/graceful-shutdown.ts
|
|
2313
|
+
* @description Graceful shutdown coordination to prevent orphaned resources and partial state.
|
|
2314
|
+
*
|
|
2315
|
+
* Graceful shutdown is critical for a long-running daemon like AISnitch:
|
|
2316
|
+
* - **No orphaned servers**: HTTP/WebSocket/UDS servers must be closed cleanly
|
|
2317
|
+
* - **No resource leaks**: file watchers, pollers, timers must be stopped
|
|
2318
|
+
* - **Clean PID files**: stale PID files confuse subsequent launches
|
|
2319
|
+
* - **Clean state files**: daemon-state.json must be removed on exit
|
|
2320
|
+
*
|
|
2321
|
+
* This module provides:
|
|
2322
|
+
* - `withShutdownTimeout()` — wrap a shutdown function with a deadline
|
|
2323
|
+
* - `shutdownInOrder()` — stop components in reverse dependency order
|
|
2324
|
+
* - `GracefulShutdownManager` — coordinates all shutdown signals (SIGTERM, SIGINT, SIGHUP)
|
|
2325
|
+
*
|
|
2326
|
+
* ## Shutdown order for AISnitch pipeline
|
|
2327
|
+
*
|
|
2328
|
+
* ```
|
|
2329
|
+
* 1. adapters.stopAll() — stop watching files, kill pollers, close watchers
|
|
2330
|
+
* 2. httpReceiver.stop() — close HTTP server
|
|
2331
|
+
* 3. udsServer.stop() — close Unix Domain Socket
|
|
2332
|
+
* 4. wsServer.stop() — close WebSocket server (consumers get disconnected)
|
|
2333
|
+
* 5. eventBus.unsubscribeAll() — remove all listeners
|
|
2334
|
+
* 6. cleanup PID/state files — prevent stale state on next launch
|
|
2335
|
+
* ```
|
|
2336
|
+
*
|
|
2337
|
+
* @functions
|
|
2338
|
+
* → withShutdownTimeout
|
|
2339
|
+
* → shutdownInOrder
|
|
2340
|
+
* @exports GracefulShutdownManager, ShutdownComponents, withShutdownTimeout, shutdownInOrder
|
|
2341
|
+
* @see ./errors.ts (TimeoutError)
|
|
2342
|
+
* @see ./timeout.ts (DEFAULT_TIMEOUTS)
|
|
2343
|
+
* @see ../cli/runtime.ts (shutdown orchestration)
|
|
2344
|
+
*/
|
|
2345
|
+
/**
|
|
2346
|
+
* All AISnitch components that participate in graceful shutdown.
|
|
2347
|
+
* Stopped in reverse dependency order (last-started = first-stopped).
|
|
2348
|
+
*/
|
|
2349
|
+
interface ShutdownComponents {
|
|
2350
|
+
readonly adapterRegistry?: {
|
|
2351
|
+
stopAll: () => Promise<void>;
|
|
2352
|
+
};
|
|
2353
|
+
readonly httpReceiver?: {
|
|
2354
|
+
stop: () => Promise<void>;
|
|
2355
|
+
};
|
|
2356
|
+
readonly udsServer?: {
|
|
2357
|
+
stop: () => Promise<void>;
|
|
2358
|
+
};
|
|
2359
|
+
readonly wsServer?: {
|
|
2360
|
+
stop: () => Promise<void>;
|
|
2361
|
+
};
|
|
2362
|
+
readonly eventBus?: {
|
|
2363
|
+
unsubscribeAll: () => void;
|
|
2364
|
+
};
|
|
2365
|
+
readonly cleanupFns?: ReadonlyArray<() => Promise<void> | void>;
|
|
2366
|
+
}
|
|
2367
|
+
/**
|
|
2368
|
+
* Wraps an async shutdown operation with a deadline.
|
|
2369
|
+
*
|
|
2370
|
+
* If the shutdown completes within `timeoutMs`, returns normally.
|
|
2371
|
+
* If the timeout fires first, logs a warning and continues (forces through).
|
|
2372
|
+
*
|
|
2373
|
+
* This ensures that a misbehaving component can never indefinitely block
|
|
2374
|
+
* daemon shutdown and leave the system in a half-dead state.
|
|
2375
|
+
*
|
|
2376
|
+
* @example
|
|
2377
|
+
* ```typescript
|
|
2378
|
+
* await withShutdownTimeout(
|
|
2379
|
+
* () => adapter.stop(),
|
|
2380
|
+
* DEFAULT_TIMEOUTS.adapterShutdown,
|
|
2381
|
+
* 'ClaudeCodeAdapter'
|
|
2382
|
+
* );
|
|
2383
|
+
* ```
|
|
2384
|
+
*
|
|
2385
|
+
* @param fn - Async shutdown function to execute
|
|
2386
|
+
* @param timeoutMs - Maximum time to wait in milliseconds
|
|
2387
|
+
* @param component - Human-readable name for logging
|
|
2388
|
+
*/
|
|
2389
|
+
declare function withShutdownTimeout(fn: () => Promise<void>, timeoutMs: number, component: string): Promise<void>;
|
|
2390
|
+
/**
|
|
2391
|
+
* Stops AISnitch components in safe reverse-dependency order with individual timeouts.
|
|
2392
|
+
*
|
|
2393
|
+
* ## Why reverse order?
|
|
2394
|
+
*
|
|
2395
|
+
* The pipeline starts: adapters → HTTP → UDS → WS → eventBus
|
|
2396
|
+
* If we stop WS before HTTP, new connections keep arriving at HTTP.
|
|
2397
|
+
* If we stop eventBus before WS, consumers get events from the bus but can't send them.
|
|
2398
|
+
* Therefore, stop in reverse: eventBus → WS → UDS → HTTP → adapters.
|
|
2399
|
+
*
|
|
2400
|
+
* @example
|
|
2401
|
+
* ```typescript
|
|
2402
|
+
* await shutdownInOrder(
|
|
2403
|
+
* {
|
|
2404
|
+
* eventBus: pipeline.getEventBus(),
|
|
2405
|
+
* wsServer: pipeline.getWSServer(),
|
|
2406
|
+
* httpReceiver: pipeline.getHTTPReceiver(),
|
|
2407
|
+
* udsServer: pipeline.getUDSServer(),
|
|
2408
|
+
* adapterRegistry: pipeline.getAdapterRegistry(),
|
|
2409
|
+
* cleanupFns: [
|
|
2410
|
+
* () => removePid(pathOptions),
|
|
2411
|
+
* () => removeDaemonState(pathOptions),
|
|
2412
|
+
* ],
|
|
2413
|
+
* },
|
|
2414
|
+
* {
|
|
2415
|
+
* eventBus: 1_000,
|
|
2416
|
+
* wsServer: 3_000,
|
|
2417
|
+
* httpReceiver: 2_000,
|
|
2418
|
+
* udsServer: 2_000,
|
|
2419
|
+
* adapterRegistry: 5_000,
|
|
2420
|
+
* },
|
|
2421
|
+
* 'AISnitch pipeline'
|
|
2422
|
+
* );
|
|
2423
|
+
* ```
|
|
2424
|
+
*
|
|
2425
|
+
* @param components - Components to shut down
|
|
2426
|
+
* @param timeouts - Per-component timeout in milliseconds
|
|
2427
|
+
* @param label - Human-readable label for logging
|
|
2428
|
+
*/
|
|
2429
|
+
declare function shutdownInOrder(components: ShutdownComponents, timeouts: Partial<Record<keyof ShutdownComponents, number>>, label: string): Promise<void>;
|
|
2430
|
+
/**
|
|
2431
|
+
* Coordinates all shutdown signals (SIGTERM, SIGINT, SIGHUP) for a process.
|
|
2432
|
+
*
|
|
2433
|
+
* ## Why a manager class?
|
|
2434
|
+
*
|
|
2435
|
+
* - Multiple signals can arrive in quick succession (e.g., SIGTERM then SIGINT)
|
|
2436
|
+
* - Handlers must be idempotent (second call does nothing)
|
|
2437
|
+
* - The manager tracks whether shutdown is already in progress
|
|
2438
|
+
* - It ensures the main process exits with the correct exit code
|
|
2439
|
+
*
|
|
2440
|
+
* @example
|
|
2441
|
+
* ```typescript
|
|
2442
|
+
* const manager = new GracefulShutdownManager({
|
|
2443
|
+
* onShutdown: async (signal) => {
|
|
2444
|
+
* await shutdownInOrder(pipeline, timeouts, 'pipeline');
|
|
2445
|
+
* await cleanupFiles(pathOptions);
|
|
2446
|
+
* },
|
|
2447
|
+
* signal: 'SIGTERM',
|
|
2448
|
+
* });
|
|
2449
|
+
*
|
|
2450
|
+
* process.on('SIGTERM', manager.handler);
|
|
2451
|
+
* process.on('SIGINT', manager.handler);
|
|
2452
|
+
*
|
|
2453
|
+
* // Call handler manually to trigger shutdown from anywhere
|
|
2454
|
+
* await manager.shutdown('manual-trigger');
|
|
2455
|
+
* ```
|
|
2456
|
+
*/
|
|
2457
|
+
declare class GracefulShutdownManager {
|
|
2458
|
+
private readonly options;
|
|
2459
|
+
private shuttingDown;
|
|
2460
|
+
private readonly pendingHandlers;
|
|
2461
|
+
/**
|
|
2462
|
+
* Creates a new shutdown manager.
|
|
2463
|
+
*
|
|
2464
|
+
* @param options - Configuration options
|
|
2465
|
+
* @param options.onShutdown - Async function called when shutdown is triggered
|
|
2466
|
+
* @param options.exitCode - Exit code to use (default: 0 for graceful, 1 for errors)
|
|
2467
|
+
* @param options.exitDelayMs - Delay before `process.exit()` (default: 100ms for flush)
|
|
2468
|
+
*/
|
|
2469
|
+
constructor(options: {
|
|
2470
|
+
readonly onShutdown: (signal: string) => Promise<void>;
|
|
2471
|
+
readonly exitCode?: number;
|
|
2472
|
+
readonly exitDelayMs?: number;
|
|
2473
|
+
});
|
|
2474
|
+
/**
|
|
2475
|
+
* Synchronous handler function suitable for `process.on()`.
|
|
2476
|
+
*
|
|
2477
|
+
* Multiple calls are safe — only the first call executes `onShutdown`.
|
|
2478
|
+
* Subsequent calls queue to the internal pending set and run after the
|
|
2479
|
+
* first shutdown completes.
|
|
2480
|
+
*/
|
|
2481
|
+
get handler(): (signal: string) => void;
|
|
2482
|
+
/**
|
|
2483
|
+
* Manually triggers shutdown from async code (e.g., TUI quit button).
|
|
2484
|
+
*
|
|
2485
|
+
* @param signal - Signal name (for logging)
|
|
2486
|
+
*/
|
|
2487
|
+
shutdown(signal?: string): void;
|
|
2488
|
+
/**
|
|
2489
|
+
* Returns whether shutdown is currently in progress.
|
|
2490
|
+
*/
|
|
2491
|
+
isShuttingDown(): boolean;
|
|
2492
|
+
private runShutdown;
|
|
2493
|
+
}
|
|
2494
|
+
/**
|
|
2495
|
+
* Wraps a shutdown promise with an overall deadline.
|
|
2496
|
+
* If the overall shutdown exceeds the deadline, forces the process to exit.
|
|
2497
|
+
*
|
|
2498
|
+
* This is the last resort: no shutdown operation should ever take this long,
|
|
2499
|
+
* but a runaway deadlock could theoretically block forever without it.
|
|
2500
|
+
*
|
|
2501
|
+
* @example
|
|
2502
|
+
* ```typescript
|
|
2503
|
+
* const shutdownComplete = shutdownInOrder(components, timeouts, 'pipeline');
|
|
2504
|
+
* await withOverallShutdownTimeout(shutdownComplete, DEFAULT_TIMEOUTS.daemonShutdown, 'AISnitch');
|
|
2505
|
+
* ```
|
|
2506
|
+
*/
|
|
2507
|
+
declare function withOverallShutdownTimeout(shutdownPromise: Promise<void>, timeoutMs: number, label: string): Promise<void>;
|
|
2508
|
+
|
|
2509
|
+
/**
|
|
2510
|
+
* @file src/core/result.ts
|
|
2511
|
+
* @description Simple Result type for explicit error handling without relying on try/catch.
|
|
2512
|
+
*
|
|
2513
|
+
* This is a lightweight alternative to fp-ts Either for cases where you want to force
|
|
2514
|
+
* callers to handle the error case explicitly but don't need the full fp-ts ecosystem.
|
|
2515
|
+
*
|
|
2516
|
+
* The `Result<T, E>` type has two states:
|
|
2517
|
+
* - `{ success: true, value: T }` — operation succeeded with a value
|
|
2518
|
+
* - `{ success: false, error: E }` — operation failed with an error
|
|
2519
|
+
*
|
|
2520
|
+
* Usage pattern:
|
|
2521
|
+
* ```typescript
|
|
2522
|
+
* function parseConfig(raw: unknown): Result<AISnitchConfig, ValidationError> {
|
|
2523
|
+
* const result = ConfigSchema.safeParse(raw);
|
|
2524
|
+
* if (!result.success) {
|
|
2525
|
+
* return err(new ValidationError(
|
|
2526
|
+
* 'Invalid config', 'VALIDATION_CONFIG_INVALID',
|
|
2527
|
+
* { issues: result.error.issues }
|
|
2528
|
+
* ));
|
|
2529
|
+
* }
|
|
2530
|
+
* return ok(result.data);
|
|
2531
|
+
* }
|
|
2532
|
+
*
|
|
2533
|
+
* // Caller must handle both cases
|
|
2534
|
+
* const result = parseConfig(raw);
|
|
2535
|
+
* if (isErr(result)) {
|
|
2536
|
+
* logger.error({ error: result.error }, 'Config parsing failed');
|
|
2537
|
+
* return;
|
|
2538
|
+
* }
|
|
2539
|
+
* // result.value is guaranteed to exist here
|
|
2540
|
+
* useConfig(result.value);
|
|
2541
|
+
* ```
|
|
2542
|
+
*
|
|
2543
|
+
* @functions
|
|
2544
|
+
* → ok
|
|
2545
|
+
* → err
|
|
2546
|
+
* → isOk
|
|
2547
|
+
* → isErr
|
|
2548
|
+
* → mapOk
|
|
2549
|
+
* → mapErr
|
|
2550
|
+
* → flatMap
|
|
2551
|
+
* → fromPromise
|
|
2552
|
+
* @exports Result, ok, err, isOk, isErr, mapOk, mapErr, flatMap, fromPromise
|
|
2553
|
+
* @see ./errors.ts
|
|
2554
|
+
* @see ./retry.ts
|
|
2555
|
+
*/
|
|
2556
|
+
/**
|
|
2557
|
+
* Discriminated union representing either a successful value or a failure error.
|
|
2558
|
+
*
|
|
2559
|
+
* @typeParam T - The success value type
|
|
2560
|
+
* @typeParam E - The error type (defaults to `Error`)
|
|
2561
|
+
*/
|
|
2562
|
+
type Result<T, E = Error> = {
|
|
2563
|
+
readonly success: true;
|
|
2564
|
+
readonly value: T;
|
|
2565
|
+
} | {
|
|
2566
|
+
readonly success: false;
|
|
2567
|
+
readonly error: E;
|
|
2568
|
+
};
|
|
2569
|
+
/**
|
|
2570
|
+
* Narrowing type guard for the success case.
|
|
2571
|
+
*
|
|
2572
|
+
* @example
|
|
2573
|
+
* ```typescript
|
|
2574
|
+
* const result = maybeDoSomething();
|
|
2575
|
+
* if (isOk(result)) {
|
|
2576
|
+
* console.log(result.value); // TypeScript knows result.value exists
|
|
2577
|
+
* }
|
|
2578
|
+
* ```
|
|
2579
|
+
*/
|
|
2580
|
+
declare function isOk<T, E>(result: Result<T, E>): result is {
|
|
2581
|
+
success: true;
|
|
2582
|
+
value: T;
|
|
2583
|
+
};
|
|
2584
|
+
/**
|
|
2585
|
+
* Narrowing type guard for the error case.
|
|
2586
|
+
*
|
|
2587
|
+
* @example
|
|
2588
|
+
* ```typescript
|
|
2589
|
+
* const result = maybeDoSomething();
|
|
2590
|
+
* if (isErr(result)) {
|
|
2591
|
+
* console.error(result.error); // TypeScript knows result.error exists
|
|
2592
|
+
* }
|
|
2593
|
+
* ```
|
|
2594
|
+
*/
|
|
2595
|
+
declare function isErr<T, E>(result: Result<T, E>): result is {
|
|
2596
|
+
success: false;
|
|
2597
|
+
error: E;
|
|
2598
|
+
};
|
|
2599
|
+
/**
|
|
2600
|
+
* Constructs a successful result with a value.
|
|
2601
|
+
*
|
|
2602
|
+
* @example
|
|
2603
|
+
* ```typescript
|
|
2604
|
+
* const result = ok({ userId: 42, name: 'Alice' });
|
|
2605
|
+
* // { success: true, value: { userId: 42, name: 'Alice' } }
|
|
2606
|
+
* ```
|
|
2607
|
+
*/
|
|
2608
|
+
declare function ok<T>(value: T): Result<T, never>;
|
|
2609
|
+
/**
|
|
2610
|
+
* Constructs a failed result with an error.
|
|
2611
|
+
*
|
|
2612
|
+
* @example
|
|
2613
|
+
* ```typescript
|
|
2614
|
+
* const result = err(new Error('Not found'));
|
|
2615
|
+
* // { success: false, error: Error('Not found') }
|
|
2616
|
+
* ```
|
|
2617
|
+
*/
|
|
2618
|
+
declare function err<E extends Error = Error>(error: E): Result<never, E>;
|
|
2619
|
+
/**
|
|
2620
|
+
* Maps the success value through a transformation function.
|
|
2621
|
+
* Errors pass through unchanged.
|
|
2622
|
+
*
|
|
2623
|
+
* @example
|
|
2624
|
+
* ```typescript
|
|
2625
|
+
* const result: Result<User, Error> = ok({ id: 1, name: 'Alice' });
|
|
2626
|
+
* const mapped = mapOk(result, (user) => user.name.toUpperCase());
|
|
2627
|
+
* // { success: true, value: 'ALICE' }
|
|
2628
|
+
* ```
|
|
2629
|
+
*/
|
|
2630
|
+
declare function mapOk<T, E, U>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;
|
|
2631
|
+
/**
|
|
2632
|
+
* Maps the error value through a transformation function.
|
|
2633
|
+
* Success values pass through unchanged.
|
|
2634
|
+
*
|
|
2635
|
+
* @example
|
|
2636
|
+
* ```typescript
|
|
2637
|
+
* const result: Result<User, Error> = err(new Error('original'));
|
|
2638
|
+
* const mapped = mapErr(result, (error) => new CustomError(error.message));
|
|
2639
|
+
* // { success: false, error: CustomError('original') }
|
|
2640
|
+
* ```
|
|
2641
|
+
*/
|
|
2642
|
+
declare function mapErr<T, E, F extends Error>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;
|
|
2643
|
+
/**
|
|
2644
|
+
* Chains Result operations: if the first Result succeeds, apply `fn` to its value.
|
|
2645
|
+
* If it fails, propagate the error without calling `fn`.
|
|
2646
|
+
*
|
|
2647
|
+
* @example
|
|
2648
|
+
* ```typescript
|
|
2649
|
+
* const result = await flatMap(
|
|
2650
|
+
* await parseConfig(raw),
|
|
2651
|
+
* (config) => validateAdapters(config.adapters)
|
|
2652
|
+
* );
|
|
2653
|
+
* // Either returns parseConfig's error, or the error from validateAdapters
|
|
2654
|
+
* ```
|
|
2655
|
+
*/
|
|
2656
|
+
declare function flatMap<T, E, U, F extends Error>(result: Result<T, E>, fn: (value: T) => Result<U, F> | Promise<Result<U, F>>): Promise<Result<U, E | F>>;
|
|
2657
|
+
/**
|
|
2658
|
+
* Converts a Promise to a Result, catching errors automatically.
|
|
2659
|
+
* Rejections become `{ success: false, error: E }`.
|
|
2660
|
+
*
|
|
2661
|
+
* @example
|
|
2662
|
+
* ```typescript
|
|
2663
|
+
* const result = await fromPromise(
|
|
2664
|
+
* fetch('http://127.0.0.1:4821/health'),
|
|
2665
|
+
* (error) => new NetworkError(
|
|
2666
|
+
* 'Health check failed',
|
|
2667
|
+
* 'NETWORK_HTTP_CONNECT_FAILED',
|
|
2668
|
+
* { cause: error }
|
|
2669
|
+
* )
|
|
2670
|
+
* );
|
|
2671
|
+
* if (isErr(result)) {
|
|
2672
|
+
* logger.warn({ error: result.error }, 'Daemon health check failed');
|
|
2673
|
+
* return null;
|
|
2674
|
+
* }
|
|
2675
|
+
* const health = await result.value.json();
|
|
2676
|
+
* ```
|
|
2677
|
+
*/
|
|
2678
|
+
declare function fromPromise<T, E extends Error>(promise: Promise<T>, mapError: (reason: unknown) => E): Promise<Result<T, E>>;
|
|
2679
|
+
/**
|
|
2680
|
+
* Synchronous version of `fromPromise` for non-async functions.
|
|
2681
|
+
*
|
|
2682
|
+
* @example
|
|
2683
|
+
* ```typescript
|
|
2684
|
+
* const result = fromSync(() => JSON.parse(rawJson), (e) =>
|
|
2685
|
+
* new ValidationError('Invalid JSON', 'VALIDATION_JSON_PARSE', { cause: e })
|
|
2686
|
+
* );
|
|
2687
|
+
* ```
|
|
2688
|
+
*/
|
|
2689
|
+
declare function fromSync<T, E extends Error>(fn: () => T, mapError: (reason: unknown) => E): Result<T, E>;
|
|
2690
|
+
|
|
2691
|
+
/**
|
|
2692
|
+
* @file src/core/retry.ts
|
|
2693
|
+
* @description Exponential backoff retry utilities for transient operations.
|
|
2694
|
+
*
|
|
2695
|
+
* Retry logic is essential for resilience against:
|
|
2696
|
+
* - Network flakiness (connection refused, timeouts, DNS failures)
|
|
2697
|
+
* - Transient file-system contention (file locked, directory not ready)
|
|
2698
|
+
* - External API rate limits (backoff on 429 Too Many Requests)
|
|
2699
|
+
*
|
|
2700
|
+
* This module provides:
|
|
2701
|
+
* - `withRetry()` — async function with exponential backoff
|
|
2702
|
+
* - `RetryOptions` — configurable retry parameters
|
|
2703
|
+
* - `DefaultRetryOptions` — sensible defaults for AISnitch workloads
|
|
2704
|
+
*
|
|
2705
|
+
* Usage:
|
|
2706
|
+
* ```typescript
|
|
2707
|
+
* const result = await withRetry(
|
|
2708
|
+
* () => fetchHealth(daemonPort),
|
|
2709
|
+
* {
|
|
2710
|
+
* attempts: 3,
|
|
2711
|
+
* delayMs: 500,
|
|
2712
|
+
* backoff: 2,
|
|
2713
|
+
* context: 'daemon-health-check',
|
|
2714
|
+
* }
|
|
2715
|
+
* );
|
|
2716
|
+
* ```
|
|
2717
|
+
*
|
|
2718
|
+
* @functions
|
|
2719
|
+
* → withRetry
|
|
2720
|
+
* → sleep
|
|
2721
|
+
* → DefaultRetryOptions
|
|
2722
|
+
* @exports RetryOptions, DefaultRetryOptions, withRetry, sleep
|
|
2723
|
+
* @see ./errors.ts
|
|
2724
|
+
* @see ./result.ts
|
|
2725
|
+
*/
|
|
2726
|
+
/**
|
|
2727
|
+
* Configuration for retry behaviour.
|
|
2728
|
+
*/
|
|
2729
|
+
interface RetryOptions {
|
|
2730
|
+
/**
|
|
2731
|
+
* Maximum number of attempts before giving up.
|
|
2732
|
+
* @default 3
|
|
2733
|
+
*/
|
|
2734
|
+
readonly attempts: number;
|
|
2735
|
+
/**
|
|
2736
|
+
* Initial delay in milliseconds between retries.
|
|
2737
|
+
* @default 500
|
|
2738
|
+
*/
|
|
2739
|
+
readonly delayMs: number;
|
|
2740
|
+
/**
|
|
2741
|
+
* Multiplicative factor for delay after each attempt.
|
|
2742
|
+
* @default 2
|
|
2743
|
+
*/
|
|
2744
|
+
readonly backoff: number;
|
|
2745
|
+
/**
|
|
2746
|
+
* Maximum total time in milliseconds across all retries.
|
|
2747
|
+
* @default 30_000
|
|
2748
|
+
*/
|
|
2749
|
+
readonly maxTotalDelayMs: number;
|
|
2750
|
+
/**
|
|
2751
|
+
* Human-readable label used in log messages for traceability.
|
|
2752
|
+
*/
|
|
2753
|
+
readonly context: string;
|
|
2754
|
+
/**
|
|
2755
|
+
* Optional predicate to filter which errors trigger a retry.
|
|
2756
|
+
* By default, `isRetryableError()` is used.
|
|
2757
|
+
* Return `true` to retry, `false` to give up immediately.
|
|
2758
|
+
*/
|
|
2759
|
+
readonly shouldRetry?: (error: unknown) => boolean;
|
|
2760
|
+
/**
|
|
2761
|
+
* Set to `true` to jitter the delay slightly (±25%) to avoid thundering herd.
|
|
2762
|
+
* @default true
|
|
2763
|
+
*/
|
|
2764
|
+
readonly jitter?: boolean;
|
|
2765
|
+
}
|
|
2766
|
+
/**
|
|
2767
|
+
* Sensible defaults tuned for AISnitch workloads:
|
|
2768
|
+
* - Quick first retry (500ms) for responsiveness
|
|
2769
|
+
* - Exponential backoff to back off gracefully
|
|
2770
|
+
* - 3 attempts to avoid long stalls
|
|
2771
|
+
* - Jitter enabled to spread load
|
|
2772
|
+
*/
|
|
2773
|
+
declare const DefaultRetryOptions: Readonly<RetryOptions>;
|
|
2774
|
+
/**
|
|
2775
|
+
* Blocks the current async execution for the given number of milliseconds.
|
|
2776
|
+
*
|
|
2777
|
+
* @example
|
|
2778
|
+
* ```typescript
|
|
2779
|
+
* await sleep(1000); // wait 1 second
|
|
2780
|
+
* ```
|
|
2781
|
+
*/
|
|
2782
|
+
declare function sleep(ms: number): Promise<void>;
|
|
2783
|
+
/**
|
|
2784
|
+
* Wraps an async operation with exponential-backoff retry logic.
|
|
2785
|
+
*
|
|
2786
|
+
* ## How it works
|
|
2787
|
+
*
|
|
2788
|
+
* 1. Executes `fn` immediately (no initial delay)
|
|
2789
|
+
* 2. If it succeeds → returns the result
|
|
2790
|
+
* 3. If it throws and `shouldRetry(error)` returns `true` and attempts remain:
|
|
2791
|
+
* - Logs a warning at attempt level (warn) and at failure level (error)
|
|
2792
|
+
* - Waits `delayMs * backoff^attempt` milliseconds (with optional jitter)
|
|
2793
|
+
* - Repeats from step 1
|
|
2794
|
+
* 4. If it throws and `shouldRetry(error)` returns `false` → throws immediately
|
|
2795
|
+
* 5. If all attempts are exhausted → throws the last error
|
|
2796
|
+
*
|
|
2797
|
+
* ## When NOT to use this
|
|
2798
|
+
*
|
|
2799
|
+
* - **Permanent failures** (e.g., validation errors, missing required files)
|
|
2800
|
+
* → Use `isRetryableError()` to filter these out automatically
|
|
2801
|
+
* - **Operations that are not idempotent** → only retry if `fn` is safe to re-execute
|
|
2802
|
+
* - **User-facing latency-sensitive paths** → use a shorter `delayMs` and fewer `attempts`
|
|
2803
|
+
*
|
|
2804
|
+
* @example
|
|
2805
|
+
* ```typescript
|
|
2806
|
+
* // Retry a flaky health check up to 3 times
|
|
2807
|
+
* const health = await withRetry(
|
|
2808
|
+
* () => fetch('http://127.0.0.1:4821/health').then(r => r.json()),
|
|
2809
|
+
* {
|
|
2810
|
+
* ...DefaultRetryOptions,
|
|
2811
|
+
* context: 'daemon-health-check',
|
|
2812
|
+
* }
|
|
2813
|
+
* );
|
|
2814
|
+
* ```
|
|
2815
|
+
*/
|
|
2816
|
+
declare function withRetry<T>(fn: () => Promise<T>, options: Partial<RetryOptions> & {
|
|
2817
|
+
context: string;
|
|
2818
|
+
}): Promise<T>;
|
|
2819
|
+
/**
|
|
2820
|
+
* Convenience wrapper for fire-and-forget retries (no return value needed).
|
|
2821
|
+
* Logs failures but never throws — useful for non-critical background tasks.
|
|
2822
|
+
*
|
|
2823
|
+
* @example
|
|
2824
|
+
* ```typescript
|
|
2825
|
+
* // Best-effort metric reporting — don't fail the main flow
|
|
2826
|
+
* fireAndForgetRetry(
|
|
2827
|
+
* () => sendMetrics(metrics),
|
|
2828
|
+
* { context: 'metrics-report', attempts: 2 }
|
|
2829
|
+
* );
|
|
2830
|
+
* ```
|
|
2831
|
+
*/
|
|
2832
|
+
declare function fireAndForgetRetry<T>(fn: () => Promise<T>, options: Partial<RetryOptions> & {
|
|
2833
|
+
context: string;
|
|
2834
|
+
}): void;
|
|
2835
|
+
/**
|
|
2836
|
+
* Builds a retry-enabled version of any async function.
|
|
2837
|
+
* The returned function will automatically retry on retryable errors.
|
|
2838
|
+
*
|
|
2839
|
+
* @example
|
|
2840
|
+
* ```typescript
|
|
2841
|
+
* const safeReadFile = withRetryOn(
|
|
2842
|
+
* (path: string) => readFile(path, 'utf8'),
|
|
2843
|
+
* { attempts: 3, delayMs: 200, context: 'file-read' }
|
|
2844
|
+
* );
|
|
2845
|
+
*
|
|
2846
|
+
* const content = await safeReadFile('/path/to/file.txt');
|
|
2847
|
+
* ```
|
|
2848
|
+
*/
|
|
2849
|
+
declare function withRetryOn<T extends (...args: never[]) => Promise<unknown>>(fn: T, options: Partial<RetryOptions> & {
|
|
2850
|
+
context: string;
|
|
2851
|
+
}): T;
|
|
2852
|
+
|
|
2853
|
+
/**
|
|
2854
|
+
* @file src/core/safety.ts
|
|
2855
|
+
* @description Type-safe extraction helpers for working with untyped record data.
|
|
2856
|
+
*
|
|
2857
|
+
* AISnitch often deals with loosely-typed payloads:
|
|
2858
|
+
* - Hook payloads from third-party tools (Claude Code, OpenCode, etc.)
|
|
2859
|
+
* - JSONL transcript observations parsed from raw JSON
|
|
2860
|
+
* - Config files loaded from disk
|
|
2861
|
+
* - Event data fields that may be undefined
|
|
2862
|
+
*
|
|
2863
|
+
* This module provides:
|
|
2864
|
+
* - `getString()` / `getNumber()` / `getBoolean()` — safe extractors with type narrowing
|
|
2865
|
+
* - `getStringOrDefault()` / `getNumberOrDefault()` — with fallback defaults
|
|
2866
|
+
* - `getArray()` / `getObject()` — structural validation
|
|
2867
|
+
* - `getSafeInteger()` — integer with bounds checking
|
|
2868
|
+
* - `getPositiveNumber()` — positive values only
|
|
2869
|
+
* - `isValidPort()` — network port validation (1-65535)
|
|
2870
|
+
* - `isValidPathLength()` — POSIX path limit check (4096 chars)
|
|
2871
|
+
* - `isValidStringLength()` — max string length check
|
|
2872
|
+
*
|
|
2873
|
+
* ## Why not just use optional chaining?
|
|
2874
|
+
*
|
|
2875
|
+
* Optional chaining (`?.`) protects against null/undefined access chains, but it:
|
|
2876
|
+
* - Does NOT validate the type of the value (e.g., `obj.key` could be `string | number | null`)
|
|
2877
|
+
* - Does NOT enforce constraints (e.g., port range, string max length)
|
|
2878
|
+
* - Does NOT normalize values (e.g., trimming strings, clamping numbers)
|
|
2879
|
+
*
|
|
2880
|
+
* These helpers do all of the above in one call.
|
|
2881
|
+
*
|
|
2882
|
+
* @functions
|
|
2883
|
+
* → getString
|
|
2884
|
+
* → getNumber
|
|
2885
|
+
* → getBoolean
|
|
2886
|
+
* → getSafeInteger
|
|
2887
|
+
* → getPositiveNumber
|
|
2888
|
+
* → isValidPort
|
|
2889
|
+
* → isValidPathLength
|
|
2890
|
+
* → isValidStringLength
|
|
2891
|
+
* → getArray
|
|
2892
|
+
* → getObject
|
|
2893
|
+
* @exports getString, getNumber, getBoolean, getSafeInteger, getPositiveNumber, isValidPort, isValidPathLength, isValidStringLength, getArray, getObject
|
|
2894
|
+
* @see ./errors.ts
|
|
2895
|
+
* @see ./result.ts
|
|
2896
|
+
*/
|
|
2897
|
+
/**
|
|
2898
|
+
* Maximum valid TCP/UDP port number.
|
|
2899
|
+
* Ports below 1024 require root privileges on Unix.
|
|
2900
|
+
*/
|
|
2901
|
+
declare const MAX_PORT = 65535;
|
|
2902
|
+
/**
|
|
2903
|
+
* Minimum valid TCP/UDP port number.
|
|
2904
|
+
*/
|
|
2905
|
+
declare const MIN_PORT = 1;
|
|
2906
|
+
/**
|
|
2907
|
+
* Maximum path length per POSIX (NAME_MAX).
|
|
2908
|
+
* Most filesystems support 255 bytes per path component, but the total path
|
|
2909
|
+
* can grow much longer. 4096 is a safe upper bound for in-memory validation.
|
|
2910
|
+
*/
|
|
2911
|
+
declare const MAX_PATH_LENGTH = 4096;
|
|
2912
|
+
/**
|
|
2913
|
+
* Maximum string length for most AISnitch fields (file paths, model names, etc.).
|
|
2914
|
+
* Beyond this, truncation or rejection is safer than silent truncation.
|
|
2915
|
+
*/
|
|
2916
|
+
declare const MAX_GENERIC_STRING_LENGTH = 10000;
|
|
2917
|
+
/**
|
|
2918
|
+
* Maximum length for short labels (tool names, session IDs, event types).
|
|
2919
|
+
* These should always be kept short for display.
|
|
2920
|
+
*/
|
|
2921
|
+
declare const MAX_LABEL_LENGTH = 255;
|
|
2922
|
+
/**
|
|
2923
|
+
* Extracts a non-empty trimmed string from a record field.
|
|
2924
|
+
*
|
|
2925
|
+
* @example
|
|
2926
|
+
* ```typescript
|
|
2927
|
+
* const model = getString(payload, 'model');
|
|
2928
|
+
* // → 'claude-sonnet-4-20250514' | undefined
|
|
2929
|
+
* ```
|
|
2930
|
+
*/
|
|
2931
|
+
declare function getString(record: Record<string, unknown>, key: string): string | undefined;
|
|
2932
|
+
/**
|
|
2933
|
+
* Extracts a string and enforces a maximum length.
|
|
2934
|
+
* If the string exceeds `maxLength`, it is truncated to that length.
|
|
2935
|
+
*
|
|
2936
|
+
* @example
|
|
2937
|
+
* ```typescript
|
|
2938
|
+
* const truncated = getStringWithMaxLength(payload, 'errorMessage', 10_000);
|
|
2939
|
+
* ```
|
|
2940
|
+
*/
|
|
2941
|
+
declare function getStringWithMaxLength(record: Record<string, unknown>, key: string, maxLength: number): string | undefined;
|
|
2942
|
+
/**
|
|
2943
|
+
* Extracts a finite number from a record field.
|
|
2944
|
+
*
|
|
2945
|
+
* Filters out `NaN`, `Infinity`, `-Infinity`.
|
|
2946
|
+
*
|
|
2947
|
+
* @example
|
|
2948
|
+
* ```typescript
|
|
2949
|
+
* const pid = getNumber(payload, 'pid');
|
|
2950
|
+
* // → 12345 | undefined
|
|
2951
|
+
* ```
|
|
2952
|
+
*/
|
|
2953
|
+
declare function getNumber(record: Record<string, unknown>, key: string): number | undefined;
|
|
2954
|
+
/**
|
|
2955
|
+
* Extracts a finite integer within a range.
|
|
2956
|
+
*
|
|
2957
|
+
* @example
|
|
2958
|
+
* ```typescript
|
|
2959
|
+
* const seqnum = getSafeInteger(payload, 'seqnum', { min: 1 });
|
|
2960
|
+
* // → 42 | undefined
|
|
2961
|
+
* ```
|
|
2962
|
+
*/
|
|
2963
|
+
declare function getSafeInteger(record: Record<string, unknown>, key: string, options?: {
|
|
2964
|
+
min?: number;
|
|
2965
|
+
max?: number;
|
|
2966
|
+
}): number | undefined;
|
|
2967
|
+
/**
|
|
2968
|
+
* Extracts a positive number ( > 0).
|
|
2969
|
+
*
|
|
2970
|
+
* @example
|
|
2971
|
+
* ```typescript
|
|
2972
|
+
* const tokens = getPositiveNumber(payload, 'tokensUsed');
|
|
2973
|
+
* // → 1500 | undefined (rejects 0, negative)
|
|
2974
|
+
* ```
|
|
2975
|
+
*/
|
|
2976
|
+
declare function getPositiveNumber(record: Record<string, unknown>, key: string): number | undefined;
|
|
2977
|
+
/**
|
|
2978
|
+
* Extracts a boolean from a record field.
|
|
2979
|
+
*
|
|
2980
|
+
* Handles the common "stringified boolean" pattern where config files
|
|
2981
|
+
* or query parameters store booleans as strings ('true', 'false').
|
|
2982
|
+
*
|
|
2983
|
+
* @example
|
|
2984
|
+
* ```typescript
|
|
2985
|
+
* const enabled = getBoolean(record, 'enabled');
|
|
2986
|
+
* // → true | false | undefined
|
|
2987
|
+
* ```
|
|
2988
|
+
*/
|
|
2989
|
+
declare function getBoolean(record: Record<string, unknown>, key: string): boolean | undefined;
|
|
2990
|
+
/**
|
|
2991
|
+
* Extracts an array from a record field.
|
|
2992
|
+
*
|
|
2993
|
+
* @example
|
|
2994
|
+
* ```typescript
|
|
2995
|
+
* const parts = getArray(payload, 'content');
|
|
2996
|
+
* // → unknown[] | undefined
|
|
2997
|
+
* ```
|
|
2998
|
+
*/
|
|
2999
|
+
declare function getArray<T = unknown>(record: Record<string, unknown>, key: string): T[] | undefined;
|
|
3000
|
+
/**
|
|
3001
|
+
* Extracts a plain object from a record field.
|
|
3002
|
+
*
|
|
3003
|
+
* Returns `undefined` for arrays, class instances, `null`, primitives.
|
|
3004
|
+
*
|
|
3005
|
+
* @example
|
|
3006
|
+
* ```typescript
|
|
3007
|
+
* const toolInput = getObject(payload, 'tool_input');
|
|
3008
|
+
* // → Record<string, unknown> | undefined
|
|
3009
|
+
* ```
|
|
3010
|
+
*/
|
|
3011
|
+
declare function getObject(record: Record<string, unknown>, key: string): Record<string, unknown> | undefined;
|
|
3012
|
+
/**
|
|
3013
|
+
* Validates whether a port number is within the valid TCP/UDP range (1-65535).
|
|
3014
|
+
*
|
|
3015
|
+
* @example
|
|
3016
|
+
* ```typescript
|
|
3017
|
+
* const port = getSafeInteger(payload, 'port', { min: 1, max: 65535 });
|
|
3018
|
+
* if (isValidPort(port)) {
|
|
3019
|
+
* server.listen(port);
|
|
3020
|
+
* }
|
|
3021
|
+
* ```
|
|
3022
|
+
*/
|
|
3023
|
+
declare function isValidPort(port: number | undefined): port is number;
|
|
3024
|
+
/**
|
|
3025
|
+
* Validates whether a path string is within the POSIX NAME_MAX limit.
|
|
3026
|
+
*
|
|
3027
|
+
* Uses the conservative 4096-character limit (actual NAME_MAX varies by FS).
|
|
3028
|
+
* This check is useful for in-memory validation before file system operations.
|
|
3029
|
+
*
|
|
3030
|
+
* @example
|
|
3031
|
+
* ```typescript
|
|
3032
|
+
* const filePath = getString(payload, 'filePath');
|
|
3033
|
+
* if (filePath && isValidPathLength(filePath)) {
|
|
3034
|
+
* readFile(filePath);
|
|
3035
|
+
* }
|
|
3036
|
+
* ```
|
|
3037
|
+
*/
|
|
3038
|
+
declare function isValidPathLength(path: string | undefined): path is string;
|
|
3039
|
+
/**
|
|
3040
|
+
* Validates whether a string does not exceed a maximum length.
|
|
3041
|
+
*
|
|
3042
|
+
* @example
|
|
3043
|
+
* ```typescript
|
|
3044
|
+
* const message = getString(payload, 'errorMessage');
|
|
3045
|
+
* if (message && isValidStringLength(message, 10_000)) {
|
|
3046
|
+
* log(message);
|
|
3047
|
+
* }
|
|
3048
|
+
* ```
|
|
3049
|
+
*/
|
|
3050
|
+
declare function isValidStringLength(value: string | undefined, maxLength: number): value is string;
|
|
3051
|
+
/**
|
|
3052
|
+
* Checks whether a value is a plain object (not null, not array, not class instance).
|
|
3053
|
+
*
|
|
3054
|
+
* Uses `Object.prototype.toString` to detect class instances:
|
|
3055
|
+
* - Plain objects return `'[object Object]'`
|
|
3056
|
+
* - Class instances return `'[object ClassName]'`
|
|
3057
|
+
*
|
|
3058
|
+
* @example
|
|
3059
|
+
* ```typescript
|
|
3060
|
+
* if (isRecord(payload)) {
|
|
3061
|
+
* const value = payload[key]; // TypeScript narrows to Record<string, unknown>
|
|
3062
|
+
* }
|
|
3063
|
+
* ```
|
|
3064
|
+
*/
|
|
3065
|
+
declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
3066
|
+
/**
|
|
3067
|
+
* Type guard to narrow any `unknown` to a non-null value.
|
|
3068
|
+
*
|
|
3069
|
+
* @example
|
|
3070
|
+
* ```typescript
|
|
3071
|
+
* const cleaned = value != null ? value : defaultValue;
|
|
3072
|
+
* // or using the guard:
|
|
3073
|
+
* if (isNotNull(value)) { ... }
|
|
3074
|
+
* ```
|
|
3075
|
+
*/
|
|
3076
|
+
declare function isNotNull<T>(value: T): value is T & NonNullable<unknown>;
|
|
3077
|
+
/**
|
|
3078
|
+
* Extracts a port number with full validation (in range, integer, finite).
|
|
3079
|
+
*
|
|
3080
|
+
* @example
|
|
3081
|
+
* ```typescript
|
|
3082
|
+
* const port = getPort(record, 'httpPort');
|
|
3083
|
+
* // → 4821 | undefined
|
|
3084
|
+
* ```
|
|
3085
|
+
*/
|
|
3086
|
+
declare function getPort(record: Record<string, unknown>, key: string): number | undefined;
|
|
3087
|
+
/**
|
|
3088
|
+
* Extracts a sequence number (positive integer >= 1).
|
|
3089
|
+
*
|
|
3090
|
+
* @example
|
|
3091
|
+
* ```typescript
|
|
3092
|
+
* const seqnum = getSeqnum(record, 'seqnum');
|
|
3093
|
+
* // → 42 | undefined
|
|
3094
|
+
* ```
|
|
3095
|
+
*/
|
|
3096
|
+
declare function getSeqnum(record: Record<string, unknown>, key: string): number | undefined;
|
|
3097
|
+
|
|
1771
3098
|
/**
|
|
1772
3099
|
* @file src/core/session-identity.ts
|
|
1773
3100
|
* @description Shared helpers for deriving stable session ids and readable session labels from partial runtime metadata.
|
|
@@ -1821,6 +3148,166 @@ declare function formatSessionShortId(tool: ToolName, sessionId: string | undefi
|
|
|
1821
3148
|
*/
|
|
1822
3149
|
declare function formatSessionLabelFromEvent(event: AISnitchEvent): string;
|
|
1823
3150
|
|
|
3151
|
+
/**
|
|
3152
|
+
* @file src/core/timeout.ts
|
|
3153
|
+
* @description Async operation timeout wrappers to prevent indefinite blocking.
|
|
3154
|
+
*
|
|
3155
|
+
* AISnitch processes many async operations (file reads, HTTP requests, process
|
|
3156
|
+
* detection, file watchers, adapter startup/shutdown). Without explicit timeouts,
|
|
3157
|
+
* any of these can block the entire daemon indefinitely if the underlying resource
|
|
3158
|
+
* becomes unresponsive (e.g., NFS mount stuck, disk I/O stalled, external API hanging).
|
|
3159
|
+
*
|
|
3160
|
+
* This module provides:
|
|
3161
|
+
* - `withTimeout()` — race a promise against a deadline
|
|
3162
|
+
* - `TimeoutError` — typed error thrown on timeout
|
|
3163
|
+
* - `DEFAULT_TIMEOUTS` — sane defaults per operation type
|
|
3164
|
+
*
|
|
3165
|
+
* Usage:
|
|
3166
|
+
* ```typescript
|
|
3167
|
+
* // Fail-fast: don't wait more than 3s for a file read
|
|
3168
|
+
* const content = await withTimeout(
|
|
3169
|
+
* readFile('/path/to/transcript.jsonl', 'utf8'),
|
|
3170
|
+
* 3_000,
|
|
3171
|
+
* 'claude-transcript-read'
|
|
3172
|
+
* );
|
|
3173
|
+
* ```
|
|
3174
|
+
*
|
|
3175
|
+
* @functions
|
|
3176
|
+
* → withTimeout
|
|
3177
|
+
* → DEFAULT_TIMEOUTS
|
|
3178
|
+
* @exports DEFAULT_TIMEOUTS, withTimeout
|
|
3179
|
+
* @see ./errors.ts (TimeoutError)
|
|
3180
|
+
* @see ./graceful-shutdown.ts
|
|
3181
|
+
*/
|
|
3182
|
+
|
|
3183
|
+
/**
|
|
3184
|
+
* Named timeout windows for common AISnitch operations.
|
|
3185
|
+
*
|
|
3186
|
+
* These defaults are conservative but reasonable for local development:
|
|
3187
|
+
* - File operations: fast on local SSDs, need headroom for larger logs
|
|
3188
|
+
* - HTTP requests: generous (30s) because AI tool hooks can be slow
|
|
3189
|
+
* - Process detection: frequent polling, keep each poll short
|
|
3190
|
+
* - Adapter lifecycle: moderate (10s) for graceful shutdowns
|
|
3191
|
+
*
|
|
3192
|
+
* Override per-call via the `withTimeout()` `timeoutMs` parameter.
|
|
3193
|
+
*/
|
|
3194
|
+
declare const DEFAULT_TIMEOUTS: Readonly<{
|
|
3195
|
+
/**
|
|
3196
|
+
* File read/write operations (JSONL transcripts, config files).
|
|
3197
|
+
* Default: 5 seconds
|
|
3198
|
+
*/
|
|
3199
|
+
readonly fileOperation: 5000;
|
|
3200
|
+
/**
|
|
3201
|
+
* HTTP requests to health endpoint or external APIs.
|
|
3202
|
+
* Default: 30 seconds
|
|
3203
|
+
*/
|
|
3204
|
+
readonly httpRequest: 30000;
|
|
3205
|
+
/**
|
|
3206
|
+
* Process detection commands (`pgrep`, `ps aux`).
|
|
3207
|
+
* Default: 3 seconds
|
|
3208
|
+
*/
|
|
3209
|
+
readonly processDetection: 3000;
|
|
3210
|
+
/**
|
|
3211
|
+
* Adapter startup (file watchers, hook bridges, pollers).
|
|
3212
|
+
* Default: 10 seconds
|
|
3213
|
+
*/
|
|
3214
|
+
readonly adapterStartup: 10000;
|
|
3215
|
+
/**
|
|
3216
|
+
* Adapter shutdown (graceful cleanup, watcher close).
|
|
3217
|
+
* Default: 5 seconds — after this, resources are force-closed
|
|
3218
|
+
*/
|
|
3219
|
+
readonly adapterShutdown: 5000;
|
|
3220
|
+
/**
|
|
3221
|
+
* Daemon graceful shutdown (stop all components in order).
|
|
3222
|
+
* Default: 30 seconds
|
|
3223
|
+
*/
|
|
3224
|
+
readonly daemonShutdown: 30000;
|
|
3225
|
+
/**
|
|
3226
|
+
* WebSocket connection establishment.
|
|
3227
|
+
* Default: 10 seconds
|
|
3228
|
+
*/
|
|
3229
|
+
readonly wsConnection: 10000;
|
|
3230
|
+
/**
|
|
3231
|
+
* Overall pipeline start (all components).
|
|
3232
|
+
* Default: 15 seconds
|
|
3233
|
+
*/
|
|
3234
|
+
readonly pipelineStartup: 15000;
|
|
3235
|
+
}>;
|
|
3236
|
+
/**
|
|
3237
|
+
* Type representing the keys of `DEFAULT_TIMEOUTS`.
|
|
3238
|
+
*/
|
|
3239
|
+
type TimeoutName = keyof typeof DEFAULT_TIMEOUTS;
|
|
3240
|
+
/**
|
|
3241
|
+
* Races a promise against a deadline.
|
|
3242
|
+
*
|
|
3243
|
+
* If the promise resolves first, returns the resolved value.
|
|
3244
|
+
* If the timeout fires first, throws a `TimeoutError`.
|
|
3245
|
+
*
|
|
3246
|
+
* The timeout is implemented via `Promise.race()` so it does not
|
|
3247
|
+
* forcefully abort the underlying promise — the promise continues
|
|
3248
|
+
* running in the background. For truly cancellable operations,
|
|
3249
|
+
* consider `AbortController` in addition to this utility.
|
|
3250
|
+
*
|
|
3251
|
+
* @example
|
|
3252
|
+
* ```typescript
|
|
3253
|
+
* try {
|
|
3254
|
+
* const result = await withTimeout(
|
|
3255
|
+
* fetch('http://example.com/slow-endpoint'),
|
|
3256
|
+
* 5_000,
|
|
3257
|
+
* 'external-api-call'
|
|
3258
|
+
* );
|
|
3259
|
+
* return await result.json();
|
|
3260
|
+
* } catch (error) {
|
|
3261
|
+
* if (error instanceof TimeoutError) {
|
|
3262
|
+
* logger.warn({ context: error.context }, 'Operation timed out');
|
|
3263
|
+
* return null;
|
|
3264
|
+
* }
|
|
3265
|
+
* throw error;
|
|
3266
|
+
* }
|
|
3267
|
+
* ```
|
|
3268
|
+
*
|
|
3269
|
+
* @param promise - The async operation to race
|
|
3270
|
+
* @param timeoutMs - Maximum time to wait in milliseconds
|
|
3271
|
+
* @param context - Human-readable label for logging and error context
|
|
3272
|
+
* @returns The resolved value if `promise` wins the race
|
|
3273
|
+
* @throws TimeoutError if the timeout fires first
|
|
3274
|
+
*/
|
|
3275
|
+
declare function withTimeout<T>(promise: Promise<T>, timeoutMs: number, context: string): Promise<T>;
|
|
3276
|
+
/**
|
|
3277
|
+
* Wraps a promise with a timeout and logs a warning if it times out.
|
|
3278
|
+
* Unlike `withTimeout()`, this never throws — it falls through to the
|
|
3279
|
+
* original promise's result (or error) if the timeout fires first.
|
|
3280
|
+
*
|
|
3281
|
+
* Best-effort: useful for non-critical background operations where a
|
|
3282
|
+
* timeout should log a warning but not crash the flow.
|
|
3283
|
+
*
|
|
3284
|
+
* @example
|
|
3285
|
+
* ```typescript
|
|
3286
|
+
* // Log a warning but don't fail if process detection hangs
|
|
3287
|
+
* await timeoutWarning(
|
|
3288
|
+
* listProcesses(processListCommand),
|
|
3289
|
+
* DEFAULT_TIMEOUTS.processDetection,
|
|
3290
|
+
* 'claude-process-detection'
|
|
3291
|
+
* );
|
|
3292
|
+
* ```
|
|
3293
|
+
*/
|
|
3294
|
+
declare function timeoutWarning<T>(promise: Promise<T>, timeoutMs: number, context: string): Promise<T>;
|
|
3295
|
+
/**
|
|
3296
|
+
* Gets the timeout value for a named operation.
|
|
3297
|
+
*
|
|
3298
|
+
* @example
|
|
3299
|
+
* ```typescript
|
|
3300
|
+
* const timeoutMs = getTimeout('adapterShutdown');
|
|
3301
|
+
* // → 5_000
|
|
3302
|
+
* ```
|
|
3303
|
+
*/
|
|
3304
|
+
declare function getTimeout(name: TimeoutName): number;
|
|
3305
|
+
/**
|
|
3306
|
+
* Checks whether an error is a TimeoutError.
|
|
3307
|
+
* Shorthand for `error instanceof TimeoutError` with explicit return type.
|
|
3308
|
+
*/
|
|
3309
|
+
declare function isTimeoutError(error: unknown): error is TimeoutError;
|
|
3310
|
+
|
|
1824
3311
|
/**
|
|
1825
3312
|
* @file src/package-info.ts
|
|
1826
3313
|
* @description Shared package metadata constants consumed by the public index, CLI, and TUI without creating import cycles.
|
|
@@ -2596,4 +4083,4 @@ declare function renderAttachedTui(options: AttachedTuiOptions): Promise<void>;
|
|
|
2596
4083
|
*/
|
|
2597
4084
|
declare function renderManagedTui(options: ManagedTuiOptions): Promise<void>;
|
|
2598
4085
|
|
|
2599
|
-
export { AISNITCH_DESCRIPTION, AISNITCH_EVENT_TYPES, AISNITCH_PACKAGE_NAME, AISNITCH_VERSION, type AISnitchConfig, type AISnitchEvent, AISnitchEventSchema, type AISnitchEventType, AISnitchEventTypeSchema, type AISnitchLoggerLevel, type AISnitchScaffoldInfo, AUTO_UPDATE_MANAGERS, type AdapterConfig, AdapterConfigSchema, type AdapterPublishContext, AdapterRegistry, type AdapterRuntimeOptions, type AdapterStatus, AiderAdapter, type AiderAdapterOptions, type AiderHistoryObservation, type AiderHistoryParseResult, App, type AppProps, type AttachedTuiOptions, type AutoUpdateConfig, AutoUpdateConfigSchema, BaseAdapter, type CESPCategory, CESPCategorySchema, CESP_CATEGORIES, CESP_MAP, ClaudeCodeAdapter, type ClaudeCodeAdapterOptions, CodexAdapter, type CodexAdapterOptions, type ConfigPathOptions, ConfigSchema, ContextDetector, CopilotCLIAdapter, type CopilotCLIAdapterOptions, type CreateEventInput, CursorAdapter, type CursorAdapterOptions, DEFAULT_CONFIG, DEFAULT_TUI_FILTERS, DEFAULT_VISIBLE_EVENT_COUNT, DevinAdapter, type DevinAdapterOptions, ERROR_TYPES, EVENT_COLORS, EVENT_ICONS, EVENT_STREAM_LIMIT, type EnrichedContextFields, type ErrorType, ErrorTypeSchema, EventBus, type EventBusStats, type EventData, EventDataSchema, type EventHandler, EventLine, type EventLineProps, EventStream, type EventStreamProps, type EventStreamSource, FilterBar, type FilterBarProps, type FocusedPanel, type ForegroundTuiOptions, GeminiCLIAdapter, type GeminiCLIAdapterOptions, type GenericPTYObservation, GenericPTYSession, type GenericPTYSessionOptions, type GlobalActivityStatus, GlobalBadge, type GlobalBadgeProps, GooseAdapter, type GooseAdapterOptions, HTTPReceiver, type HTTPReceiverStartOptions, type HTTPReceiverStats, Header, type HeaderProps, type HealthSnapshot, HelpOverlay, type HookHandler, type InterceptionStrategy, KiloAdapter, type KiloAdapterOptions, LOG_LEVELS, ManagedDaemonApp, type ManagedDaemonAppProps, type ManagedTuiOptions, type ManagedTuiSnapshot, type MonitorCloseHandler, type MonitorOutput, type NormalizedAdapterHookPayload, OpenClawAdapter, type OpenClawAdapterOptions, OpenCodeAdapter, type OpenCodeAdapterOptions, Panel, type PanelProps, PanelStack, type PanelStackProps, Pipeline, type PipelineStartOptions, type PipelineStatus, type PortResolutionOptions, type ProcessContext, type ProcessInfo, RingBuffer, SESSION_STALE_AFTER_MS, type SelectorOption, type SessionFilterTarget, type SessionIdentityInput, SessionPanel, type SessionPanelProps, type SessionState, StatusBar, type StatusBarProps, TOOL_COLORS, TOOL_NAMES, TUI_THEME, TUI_VIEW_MODES, type ToolInput, ToolInputSchema, type ToolName, ToolNameSchema, type TuiDaemonSnapshot, type TuiFilters, type TuiInitialFilters, type TuiInteractionMode, type TuiStatusSnapshot, type TuiThemeColor, type TuiViewMode, UDSServer, type UDSServerStartOptions, type UDSServerStats, type UseEventStreamOptions, type UseEventStreamState, type UseKeyBindsOptions, type UseKeyBindsState, WSServer, type WSServerStartOptions, type WSServerStats, type WelcomeMessage, analyzeTerminalOutputChunk, appendEventToStream, applyEventFilters, applySessionFilters, attachEventBusMonitor, attachWebSocketMonitor, countActiveFilters, createDefaultAdapters, createEvent, createUuidV7, deriveGlobalActivityStatus, deriveSessions, ensureConfigDir, formatEventDetail, formatEventLine, formatEventTime, formatSessionLabel, formatSessionLabelFromEvent, formatSessionShortId, formatWelcomeLine, getAISnitchHomePath, getCESPCategory, getConfigPath, getPackageScaffoldInfo, getPendingFrozenEventCount, getSocketPath, getVisibleEventWindow, isGenericSessionId, loadConfig, logger, parseAiderHistoryMarkdown, renderAttachedTui, renderForegroundTui, renderManagedTui, resolveAvailablePort, resolveSessionId, saveConfig, setLoggerLevel, useEventStream, useKeyBinds, useSessions };
|
|
4086
|
+
export { AISNITCH_DESCRIPTION, AISNITCH_EVENT_TYPES, AISNITCH_PACKAGE_NAME, AISNITCH_VERSION, type AISnitchConfig, AISnitchError, type AISnitchEvent, AISnitchEventSchema, type AISnitchEventType, AISnitchEventTypeSchema, type AISnitchLoggerLevel, type AISnitchScaffoldInfo, AUTO_UPDATE_MANAGERS, type AdapterConfig, AdapterConfigSchema, AdapterError, type AdapterPublishContext, AdapterRegistry, type AdapterRuntimeOptions, type AdapterStatus, AiderAdapter, type AiderAdapterOptions, type AiderHistoryObservation, type AiderHistoryParseResult, App, type AppProps, type AttachedTuiOptions, type AutoUpdateConfig, AutoUpdateConfigSchema, BaseAdapter, type CESPCategory, CESPCategorySchema, CESP_CATEGORIES, CESP_MAP, CircuitBreaker, type CircuitBreakerOptions, CircuitOpenError, type CircuitState, ClaudeCodeAdapter, type ClaudeCodeAdapterOptions, CodexAdapter, type CodexAdapterOptions, type ConfigPathOptions, ConfigSchema, ContextDetector, CopilotCLIAdapter, type CopilotCLIAdapterOptions, type CreateEventInput, CursorAdapter, type CursorAdapterOptions, DEFAULT_CONFIG, DEFAULT_TIMEOUTS, DEFAULT_TUI_FILTERS, DEFAULT_VISIBLE_EVENT_COUNT, DefaultRetryOptions, DevinAdapter, type DevinAdapterOptions, ERROR_TYPES, EVENT_COLORS, EVENT_ICONS, EVENT_STREAM_LIMIT, type EnrichedContextFields, type ErrorType, ErrorTypeSchema, EventBus, type EventBusStats, type EventData, EventDataSchema, type EventHandler, EventLine, type EventLineProps, EventStream, type EventStreamProps, type EventStreamSource, FilterBar, type FilterBarProps, FinalMessageSchema, type FocusedPanel, type ForegroundTuiOptions, GeminiCLIAdapter, type GeminiCLIAdapterOptions, type GenericPTYObservation, GenericPTYSession, type GenericPTYSessionOptions, type GlobalActivityStatus, GlobalBadge, type GlobalBadgeProps, GooseAdapter, type GooseAdapterOptions, GracefulShutdownManager, HTTPReceiver, type HTTPReceiverStartOptions, type HTTPReceiverStats, Header, type HeaderProps, type HealthSnapshot, HelpOverlay, type HookHandler, type InterceptionStrategy, KiloAdapter, type KiloAdapterOptions, LOG_LEVELS, MAX_GENERIC_STRING_LENGTH, MAX_LABEL_LENGTH, MAX_PATH_LENGTH, MAX_PORT, MIN_PORT, ManagedDaemonApp, type ManagedDaemonAppProps, type ManagedTuiOptions, type ManagedTuiSnapshot, MessageContentSchema, type MonitorCloseHandler, type MonitorOutput, NetworkError, type NormalizedAdapterHookPayload, OpenClawAdapter, type OpenClawAdapterOptions, OpenCodeAdapter, type OpenCodeAdapterOptions, Panel, type PanelProps, PanelStack, type PanelStackProps, PiAdapter, Pipeline, PipelineError, type PipelineStartOptions, type PipelineStatus, type PortResolutionOptions, type ProcessContext, type ProcessInfo, type Result, type RetryOptions, RingBuffer, SESSION_STALE_AFTER_MS, SHARED_BREAKERS, type SelectorOption, type SessionFilterTarget, type SessionIdentityInput, SessionPanel, type SessionPanelProps, type SessionState, type ShutdownComponents, StatusBar, type StatusBarProps, TOOL_COLORS, TOOL_NAMES, TUI_THEME, TUI_VIEW_MODES, ThinkingContentSchema, TimeoutError, type TimeoutName, ToolCallNameSchema, type ToolInput, ToolInputSchema, type ToolName, ToolNameSchema, ToolResultSchema, type TuiDaemonSnapshot, type TuiFilters, type TuiInitialFilters, type TuiInteractionMode, type TuiStatusSnapshot, type TuiThemeColor, type TuiViewMode, UDSServer, type UDSServerStartOptions, type UDSServerStats, type UseEventStreamOptions, type UseEventStreamState, type UseKeyBindsOptions, type UseKeyBindsState, ValidationError, WSServer, type WSServerStartOptions, type WSServerStats, type WelcomeMessage, ZedAdapter, analyzeTerminalOutputChunk, appendEventToStream, applyEventFilters, applySessionFilters, attachEventBusMonitor, attachWebSocketMonitor, countActiveFilters, createDefaultAdapters, createEvent, createUuidV7, deriveGlobalActivityStatus, deriveSessions, ensureConfigDir, err, fireAndForgetRetry, flatMap, formatEventDetail, formatEventLine, formatEventTime, formatSessionLabel, formatSessionLabelFromEvent, formatSessionShortId, formatWelcomeLine, fromPromise, fromSync, getAISnitchHomePath, getArray, getBoolean, getCESPCategory, getConfigPath, getNumber, getObject, getPackageScaffoldInfo, getPendingFrozenEventCount, getPort, getPositiveNumber, getSafeInteger, getSeqnum, getSocketPath, getString, getStringWithMaxLength, getTimeout, getVisibleEventWindow, isAISnitchError, isErr, isGenericSessionId, isNotNull, isOk, isRecord, isRetryableError, isTimeoutError, isValidPathLength, isValidPort, isValidStringLength, loadConfig, logger, mapErr, mapOk, ok, parseAiderHistoryMarkdown, renderAttachedTui, renderForegroundTui, renderManagedTui, resolveAvailablePort, resolveSessionId, saveConfig, setLoggerLevel, shutdownInOrder, sleep, timeoutWarning, useEventStream, useKeyBinds, useSessions, withOverallShutdownTimeout, withRetry, withRetryOn, withShutdownTimeout, withTimeout };
|