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/index.cjs CHANGED
@@ -34,10 +34,12 @@ __export(index_exports, {
34
34
  AISNITCH_EVENT_TYPES: () => AISNITCH_EVENT_TYPES,
35
35
  AISNITCH_PACKAGE_NAME: () => AISNITCH_PACKAGE_NAME,
36
36
  AISNITCH_VERSION: () => AISNITCH_VERSION,
37
+ AISnitchError: () => AISnitchError,
37
38
  AISnitchEventSchema: () => AISnitchEventSchema,
38
39
  AISnitchEventTypeSchema: () => AISnitchEventTypeSchema,
39
40
  AUTO_UPDATE_MANAGERS: () => AUTO_UPDATE_MANAGERS,
40
41
  AdapterConfigSchema: () => AdapterConfigSchema,
42
+ AdapterError: () => AdapterError,
41
43
  AdapterRegistry: () => AdapterRegistry,
42
44
  AiderAdapter: () => AiderAdapter,
43
45
  App: () => App,
@@ -46,6 +48,8 @@ __export(index_exports, {
46
48
  CESPCategorySchema: () => CESPCategorySchema,
47
49
  CESP_CATEGORIES: () => CESP_CATEGORIES,
48
50
  CESP_MAP: () => CESP_MAP,
51
+ CircuitBreaker: () => CircuitBreaker,
52
+ CircuitOpenError: () => CircuitOpenError,
49
53
  ClaudeCodeAdapter: () => ClaudeCodeAdapter,
50
54
  CodexAdapter: () => CodexAdapter,
51
55
  ConfigSchema: () => ConfigSchema,
@@ -53,8 +57,10 @@ __export(index_exports, {
53
57
  CopilotCLIAdapter: () => CopilotCLIAdapter,
54
58
  CursorAdapter: () => CursorAdapter,
55
59
  DEFAULT_CONFIG: () => DEFAULT_CONFIG,
60
+ DEFAULT_TIMEOUTS: () => DEFAULT_TIMEOUTS,
56
61
  DEFAULT_TUI_FILTERS: () => DEFAULT_TUI_FILTERS,
57
62
  DEFAULT_VISIBLE_EVENT_COUNT: () => DEFAULT_VISIBLE_EVENT_COUNT,
63
+ DefaultRetryOptions: () => DefaultRetryOptions,
58
64
  DevinAdapter: () => DevinAdapter,
59
65
  ERROR_TYPES: () => ERROR_TYPES,
60
66
  EVENT_COLORS: () => EVENT_COLORS,
@@ -66,33 +72,51 @@ __export(index_exports, {
66
72
  EventLine: () => EventLine,
67
73
  EventStream: () => EventStream,
68
74
  FilterBar: () => FilterBar,
75
+ FinalMessageSchema: () => FinalMessageSchema,
69
76
  GeminiCLIAdapter: () => GeminiCLIAdapter,
70
77
  GenericPTYSession: () => GenericPTYSession,
71
78
  GlobalBadge: () => GlobalBadge,
72
79
  GooseAdapter: () => GooseAdapter,
80
+ GracefulShutdownManager: () => GracefulShutdownManager,
73
81
  HTTPReceiver: () => HTTPReceiver,
74
82
  Header: () => Header,
75
83
  HelpOverlay: () => HelpOverlay,
76
84
  KiloAdapter: () => KiloAdapter,
77
85
  LOG_LEVELS: () => LOG_LEVELS,
86
+ MAX_GENERIC_STRING_LENGTH: () => MAX_GENERIC_STRING_LENGTH,
87
+ MAX_LABEL_LENGTH: () => MAX_LABEL_LENGTH,
88
+ MAX_PATH_LENGTH: () => MAX_PATH_LENGTH,
89
+ MAX_PORT: () => MAX_PORT,
90
+ MIN_PORT: () => MIN_PORT,
78
91
  ManagedDaemonApp: () => ManagedDaemonApp,
92
+ MessageContentSchema: () => MessageContentSchema,
93
+ NetworkError: () => NetworkError,
79
94
  OpenClawAdapter: () => OpenClawAdapter,
80
95
  OpenCodeAdapter: () => OpenCodeAdapter,
81
96
  Panel: () => Panel,
82
97
  PanelStack: () => PanelStack,
98
+ PiAdapter: () => PiAdapter,
83
99
  Pipeline: () => Pipeline,
100
+ PipelineError: () => PipelineError,
84
101
  RingBuffer: () => RingBuffer,
85
102
  SESSION_STALE_AFTER_MS: () => SESSION_STALE_AFTER_MS,
103
+ SHARED_BREAKERS: () => SHARED_BREAKERS,
86
104
  SessionPanel: () => SessionPanel,
87
105
  StatusBar: () => StatusBar,
88
106
  TOOL_COLORS: () => TOOL_COLORS,
89
107
  TOOL_NAMES: () => TOOL_NAMES,
90
108
  TUI_THEME: () => TUI_THEME,
91
109
  TUI_VIEW_MODES: () => TUI_VIEW_MODES,
110
+ ThinkingContentSchema: () => ThinkingContentSchema,
111
+ TimeoutError: () => TimeoutError,
112
+ ToolCallNameSchema: () => ToolCallNameSchema,
92
113
  ToolInputSchema: () => ToolInputSchema,
93
114
  ToolNameSchema: () => ToolNameSchema,
115
+ ToolResultSchema: () => ToolResultSchema,
94
116
  UDSServer: () => UDSServer,
117
+ ValidationError: () => ValidationError,
95
118
  WSServer: () => WSServer,
119
+ ZedAdapter: () => ZedAdapter,
96
120
  analyzeTerminalOutputChunk: () => analyzeTerminalOutputChunk,
97
121
  appendEventToStream: () => appendEventToStream,
98
122
  applyEventFilters: () => applyEventFilters,
@@ -106,6 +130,9 @@ __export(index_exports, {
106
130
  deriveGlobalActivityStatus: () => deriveGlobalActivityStatus,
107
131
  deriveSessions: () => deriveSessions,
108
132
  ensureConfigDir: () => ensureConfigDir,
133
+ err: () => err,
134
+ fireAndForgetRetry: () => fireAndForgetRetry,
135
+ flatMap: () => flatMap,
109
136
  formatEventDetail: () => formatEventDetail,
110
137
  formatEventLine: () => formatEventLine,
111
138
  formatEventTime: () => formatEventTime,
@@ -113,16 +140,42 @@ __export(index_exports, {
113
140
  formatSessionLabelFromEvent: () => formatSessionLabelFromEvent,
114
141
  formatSessionShortId: () => formatSessionShortId,
115
142
  formatWelcomeLine: () => formatWelcomeLine,
143
+ fromPromise: () => fromPromise,
144
+ fromSync: () => fromSync,
116
145
  getAISnitchHomePath: () => getAISnitchHomePath,
146
+ getArray: () => getArray,
147
+ getBoolean: () => getBoolean2,
117
148
  getCESPCategory: () => getCESPCategory,
118
149
  getConfigPath: () => getConfigPath,
150
+ getNumber: () => getNumber9,
151
+ getObject: () => getObject,
119
152
  getPackageScaffoldInfo: () => getPackageScaffoldInfo,
120
153
  getPendingFrozenEventCount: () => getPendingFrozenEventCount,
154
+ getPort: () => getPort,
155
+ getPositiveNumber: () => getPositiveNumber,
156
+ getSafeInteger: () => getSafeInteger,
157
+ getSeqnum: () => getSeqnum,
121
158
  getSocketPath: () => getSocketPath,
159
+ getString: () => getString11,
160
+ getStringWithMaxLength: () => getStringWithMaxLength,
161
+ getTimeout: () => getTimeout,
122
162
  getVisibleEventWindow: () => getVisibleEventWindow,
163
+ isAISnitchError: () => isAISnitchError,
164
+ isErr: () => isErr,
123
165
  isGenericSessionId: () => isGenericSessionId,
166
+ isNotNull: () => isNotNull,
167
+ isOk: () => isOk,
168
+ isRecord: () => isRecord11,
169
+ isRetryableError: () => isRetryableError,
170
+ isTimeoutError: () => isTimeoutError,
171
+ isValidPathLength: () => isValidPathLength,
172
+ isValidPort: () => isValidPort,
173
+ isValidStringLength: () => isValidStringLength,
124
174
  loadConfig: () => loadConfig,
125
175
  logger: () => logger,
176
+ mapErr: () => mapErr,
177
+ mapOk: () => mapOk,
178
+ ok: () => ok,
126
179
  parseAiderHistoryMarkdown: () => parseAiderHistoryMarkdown,
127
180
  renderAttachedTui: () => renderAttachedTui,
128
181
  renderForegroundTui: () => renderForegroundTui,
@@ -131,9 +184,17 @@ __export(index_exports, {
131
184
  resolveSessionId: () => resolveSessionId,
132
185
  saveConfig: () => saveConfig,
133
186
  setLoggerLevel: () => setLoggerLevel,
187
+ shutdownInOrder: () => shutdownInOrder,
188
+ sleep: () => sleep,
189
+ timeoutWarning: () => timeoutWarning,
134
190
  useEventStream: () => useEventStream,
135
191
  useKeyBinds: () => useKeyBinds,
136
- useSessions: () => useSessions
192
+ useSessions: () => useSessions,
193
+ withOverallShutdownTimeout: () => withOverallShutdownTimeout,
194
+ withRetry: () => withRetry,
195
+ withRetryOn: () => withRetryOn,
196
+ withShutdownTimeout: () => withShutdownTimeout,
197
+ withTimeout: () => withTimeout
137
198
  });
138
199
  module.exports = __toCommonJS(index_exports);
139
200
 
@@ -258,6 +319,399 @@ function sanitizeToken(value) {
258
319
  var import_node_os = require("os");
259
320
  var import_zod2 = require("zod");
260
321
 
322
+ // src/core/errors.ts
323
+ var AISnitchError = class _AISnitchError extends Error {
324
+ /**
325
+ * Machine-readable error code for programmatic handling.
326
+ * Format: `SUBCATEGORY_SPECIFIC_DETAIL` (uppercase with underscores).
327
+ */
328
+ code;
329
+ /**
330
+ * Arbitrary context bag forwarded to the logger for structured debugging.
331
+ */
332
+ context;
333
+ constructor(message, code, context) {
334
+ super(message);
335
+ this.name = "AISnitchError";
336
+ this.code = code;
337
+ this.context = context;
338
+ if (Error.captureStackTrace) {
339
+ Error.captureStackTrace(this, _AISnitchError);
340
+ }
341
+ }
342
+ /**
343
+ * Full error chain for logging: `[name] code — message`.
344
+ */
345
+ toString() {
346
+ return `${this.name} [${this.code}] \u2014 ${this.message}`;
347
+ }
348
+ /**
349
+ * JSON serialization friendly to pino serializers.
350
+ */
351
+ toJSON() {
352
+ return {
353
+ name: this.name,
354
+ code: this.code,
355
+ message: this.message,
356
+ context: this.context,
357
+ stack: this.stack
358
+ };
359
+ }
360
+ };
361
+ var AdapterError = class _AdapterError extends AISnitchError {
362
+ constructor(message, code, context) {
363
+ super(message, code, context);
364
+ this.name = "AdapterError";
365
+ if (Error.captureStackTrace) {
366
+ Error.captureStackTrace(this, _AdapterError);
367
+ }
368
+ }
369
+ /**
370
+ * Factory for adapter-specific errors with auto-generated codes.
371
+ */
372
+ static withAutoCode(message, tool, context) {
373
+ const sanitizedTool = tool.replace(/[^a-z0-9]/gi, "_").toUpperCase();
374
+ const code = `ADAPTER_${sanitizedTool}_ERROR`;
375
+ return new _AdapterError(message, code, { tool, ...context });
376
+ }
377
+ };
378
+ var PipelineError = class _PipelineError extends AISnitchError {
379
+ constructor(message, code, context) {
380
+ super(message, code, context);
381
+ this.name = "PipelineError";
382
+ if (Error.captureStackTrace) {
383
+ Error.captureStackTrace(this, _PipelineError);
384
+ }
385
+ }
386
+ };
387
+ var ValidationError = class _ValidationError extends AISnitchError {
388
+ constructor(message, code, context) {
389
+ super(message, code, context);
390
+ this.name = "ValidationError";
391
+ if (Error.captureStackTrace) {
392
+ Error.captureStackTrace(this, _ValidationError);
393
+ }
394
+ }
395
+ };
396
+ var NetworkError = class _NetworkError extends AISnitchError {
397
+ constructor(message, code, context) {
398
+ super(message, code, context);
399
+ this.name = "NetworkError";
400
+ if (Error.captureStackTrace) {
401
+ Error.captureStackTrace(this, _NetworkError);
402
+ }
403
+ }
404
+ };
405
+ var TimeoutError = class _TimeoutError extends AISnitchError {
406
+ constructor(message, code, context) {
407
+ super(message, code, context);
408
+ this.name = "TimeoutError";
409
+ if (Error.captureStackTrace) {
410
+ Error.captureStackTrace(this, _TimeoutError);
411
+ }
412
+ }
413
+ };
414
+ function isAISnitchError(error) {
415
+ return error instanceof AISnitchError;
416
+ }
417
+ function isRetryableError(error) {
418
+ if (!isAISnitchError(error)) {
419
+ if (error instanceof Error) {
420
+ const code = error.code;
421
+ const retryableCodes = /* @__PURE__ */ new Set([
422
+ "ECONNREFUSED",
423
+ "ECONNRESET",
424
+ "ETIMEDOUT",
425
+ "ENOTFOUND",
426
+ "EHOSTUNREACH",
427
+ "EPIPE",
428
+ "EPERM"
429
+ // sometimes transient on macOS file locks
430
+ ]);
431
+ if (typeof code === "string" && retryableCodes.has(code)) {
432
+ return true;
433
+ }
434
+ }
435
+ return false;
436
+ }
437
+ const retryableCategories = /* @__PURE__ */ new Set(["TIMEOUT", "NETWORK"]);
438
+ for (const category of retryableCategories) {
439
+ if (error.code.startsWith(category)) {
440
+ return true;
441
+ }
442
+ }
443
+ const retryablePatterns = [
444
+ /^ADAPTER_.*_(FILE_IO|NETWORK|PROCESS_DETECT)_ERROR$/,
445
+ /^PIPELINE_.*_(RETRY|RECONNECT)_ERROR$/
446
+ ];
447
+ for (const pattern of retryablePatterns) {
448
+ if (pattern.test(error.code)) {
449
+ return true;
450
+ }
451
+ }
452
+ return false;
453
+ }
454
+
455
+ // src/core/circuit-breaker.ts
456
+ var CircuitOpenError = class _CircuitOpenError extends AISnitchError {
457
+ constructor(circuitId, state) {
458
+ super(
459
+ `Circuit "${circuitId}" is OPEN \u2014 operation rejected`,
460
+ "CIRCUIT_OPEN",
461
+ { circuitId, failures: state.failures, lastFailureAt: state.lastFailureAt }
462
+ );
463
+ this.circuitId = circuitId;
464
+ this.state = state;
465
+ this.name = "CircuitOpenError";
466
+ if (Error.captureStackTrace) {
467
+ Error.captureStackTrace(this, _CircuitOpenError);
468
+ }
469
+ }
470
+ toString() {
471
+ return `${this.name} [${this.code}] "${this.circuitId}" \u2014 failures=${this.state.failures}`;
472
+ }
473
+ };
474
+ var DEFAULT_OPTIONS = {
475
+ failureThreshold: 5,
476
+ halfOpenAfterMs: 3e4,
477
+ id: "unnamed",
478
+ resetOnSuccess: true,
479
+ shouldCountAsFailure: isRetryableError,
480
+ windowMs: 6e4
481
+ };
482
+ var CircuitBreaker = class {
483
+ failures = 0;
484
+ lastFailureAt = null;
485
+ state = "closed";
486
+ halfOpenTestStartedAt = null;
487
+ options;
488
+ constructor(options = {}) {
489
+ this.options = {
490
+ ...DEFAULT_OPTIONS,
491
+ ...options,
492
+ // Re-spread to ensure all fields have defaults
493
+ failureThreshold: options.failureThreshold ?? DEFAULT_OPTIONS.failureThreshold,
494
+ halfOpenAfterMs: options.halfOpenAfterMs ?? DEFAULT_OPTIONS.halfOpenAfterMs,
495
+ id: options.id ?? DEFAULT_OPTIONS.id,
496
+ resetOnSuccess: options.resetOnSuccess ?? DEFAULT_OPTIONS.resetOnSuccess,
497
+ shouldCountAsFailure: options.shouldCountAsFailure ?? DEFAULT_OPTIONS.shouldCountAsFailure,
498
+ windowMs: options.windowMs ?? DEFAULT_OPTIONS.windowMs
499
+ };
500
+ }
501
+ /**
502
+ * Executes an async operation through the circuit breaker.
503
+ *
504
+ * - If the circuit is CLOSED → runs `fn` and updates state based on result
505
+ * - If the circuit is HALF-OPEN → runs `fn` once to test recovery
506
+ * - If the circuit is OPEN → throws `CircuitOpenError` immediately (no call)
507
+ *
508
+ * @param fn - The async operation to protect
509
+ * @returns The result of `fn` if successful
510
+ * @throws CircuitOpenError if the circuit is OPEN
511
+ * @throws The error from `fn` if it throws (and `shouldCountAsFailure` returns true)
512
+ */
513
+ async execute(fn) {
514
+ switch (this.state) {
515
+ case "closed":
516
+ return this.executeClosed(fn);
517
+ case "half-open":
518
+ return this.executeHalfOpen(fn);
519
+ case "open":
520
+ if (this.shouldTransitionToHalfOpen()) {
521
+ this.transitionToHalfOpen();
522
+ return this.executeHalfOpen(fn);
523
+ }
524
+ throw new CircuitOpenError(this.options.id, this.getState());
525
+ }
526
+ }
527
+ /**
528
+ * Returns the current observable circuit state.
529
+ */
530
+ getState() {
531
+ return {
532
+ failures: this.failures,
533
+ lastFailureAt: this.lastFailureAt,
534
+ state: this.state
535
+ };
536
+ }
537
+ /**
538
+ * Forces the circuit to CLOSED (resets failure count and state).
539
+ * Useful for manual recovery after a known-fix or after a maintenance window.
540
+ */
541
+ reset() {
542
+ this.failures = 0;
543
+ this.lastFailureAt = null;
544
+ this.state = "closed";
545
+ this.halfOpenTestStartedAt = null;
546
+ logger.debug({ circuitId: this.options.id }, "Circuit breaker manually reset");
547
+ }
548
+ /**
549
+ * Pre-warms the circuit by performing one test call in HALF-OPEN state.
550
+ * If the circuit is already HALF-OPEN, this does nothing.
551
+ * If the circuit is CLOSED, this does nothing.
552
+ */
553
+ async preWarm(fn) {
554
+ if (this.state !== "open") {
555
+ return;
556
+ }
557
+ this.transitionToHalfOpen();
558
+ try {
559
+ await fn();
560
+ this.transitionToClosed();
561
+ } catch {
562
+ this.transitionToOpen();
563
+ }
564
+ }
565
+ // ─────────────────────────────────────────────────────────────────────────
566
+ // Private methods
567
+ // ─────────────────────────────────────────────────────────────────────────
568
+ async executeClosed(fn) {
569
+ try {
570
+ const result = await fn();
571
+ this.onSuccess();
572
+ return result;
573
+ } catch (error) {
574
+ this.onFailure(error);
575
+ throw error;
576
+ }
577
+ }
578
+ async executeHalfOpen(fn) {
579
+ this.halfOpenTestStartedAt = Date.now();
580
+ try {
581
+ const result = await fn();
582
+ this.transitionToClosed();
583
+ return result;
584
+ } catch (error) {
585
+ this.transitionToOpen();
586
+ throw error;
587
+ }
588
+ }
589
+ onSuccess() {
590
+ if (this.options.resetOnSuccess) {
591
+ this.failures = 0;
592
+ this.lastFailureAt = null;
593
+ } else {
594
+ this.failures = Math.max(0, this.failures - 1);
595
+ if (this.failures === 0) {
596
+ this.lastFailureAt = null;
597
+ }
598
+ }
599
+ logger.debug(
600
+ {
601
+ circuitId: this.options.id,
602
+ failures: this.failures
603
+ },
604
+ "Circuit breaker operation succeeded"
605
+ );
606
+ }
607
+ onFailure(error) {
608
+ if (!this.options.shouldCountAsFailure(error)) {
609
+ logger.debug(
610
+ { circuitId: this.options.id, error },
611
+ "Circuit breaker operation failed but error is not counted as failure"
612
+ );
613
+ return;
614
+ }
615
+ this.failures += 1;
616
+ this.lastFailureAt = Date.now();
617
+ if (this.failures >= this.options.failureThreshold) {
618
+ this.transitionToOpen();
619
+ } else {
620
+ logger.debug(
621
+ {
622
+ circuitId: this.options.id,
623
+ failures: this.failures,
624
+ threshold: this.options.failureThreshold
625
+ },
626
+ "Circuit breaker recorded failure"
627
+ );
628
+ }
629
+ }
630
+ transitionToOpen() {
631
+ if (this.state === "open") {
632
+ return;
633
+ }
634
+ this.state = "open";
635
+ this.halfOpenTestStartedAt = null;
636
+ logger.warn(
637
+ {
638
+ circuitId: this.options.id,
639
+ failures: this.failures,
640
+ windowMs: this.options.windowMs
641
+ },
642
+ "\u{1F534} Circuit breaker OPEN \u2014 blocking operations"
643
+ );
644
+ }
645
+ transitionToHalfOpen() {
646
+ this.state = "half-open";
647
+ this.halfOpenTestStartedAt = Date.now();
648
+ logger.info(
649
+ { circuitId: this.options.id },
650
+ "\u{1F7E1} Circuit breaker HALF-OPEN \u2014 testing recovery"
651
+ );
652
+ }
653
+ transitionToClosed() {
654
+ this.state = "closed";
655
+ this.failures = 0;
656
+ this.lastFailureAt = null;
657
+ this.halfOpenTestStartedAt = null;
658
+ logger.info(
659
+ { circuitId: this.options.id },
660
+ "\u{1F7E2} Circuit breaker CLOSED \u2014 recovery successful"
661
+ );
662
+ }
663
+ shouldTransitionToHalfOpen() {
664
+ if (this.lastFailureAt === null) {
665
+ return true;
666
+ }
667
+ const elapsed = Date.now() - this.lastFailureAt;
668
+ return elapsed >= this.options.halfOpenAfterMs;
669
+ }
670
+ };
671
+ var SHARED_BREAKERS = Object.freeze({
672
+ /**
673
+ * Breaker for adapter event emission.
674
+ * Threshold: 5 failures in 60s → open for 30s → half-open test.
675
+ */
676
+ adapterEmit: new CircuitBreaker({
677
+ id: "adapter.emit",
678
+ failureThreshold: 5,
679
+ halfOpenAfterMs: 3e4,
680
+ shouldCountAsFailure: isRetryableError,
681
+ windowMs: 6e4
682
+ }),
683
+ /**
684
+ * Breaker for file system operations (transcript reading, config loading).
685
+ * More tolerant: 10 failures in 60s → open for 30s.
686
+ */
687
+ fileSystem: new CircuitBreaker({
688
+ id: "filesystem",
689
+ failureThreshold: 10,
690
+ halfOpenAfterMs: 3e4,
691
+ windowMs: 6e4
692
+ }),
693
+ /**
694
+ * Breaker for HTTP/HTTPS requests.
695
+ * Stricter: 3 failures in 30s → open for 15s.
696
+ */
697
+ httpRequest: new CircuitBreaker({
698
+ id: "http-request",
699
+ failureThreshold: 3,
700
+ halfOpenAfterMs: 15e3,
701
+ windowMs: 3e4
702
+ }),
703
+ /**
704
+ * Breaker for process detection operations.
705
+ * Most tolerant: 20 failures in 60s → open for 10s.
706
+ */
707
+ processDetection: new CircuitBreaker({
708
+ id: "process-detection",
709
+ failureThreshold: 20,
710
+ halfOpenAfterMs: 1e4,
711
+ windowMs: 6e4
712
+ })
713
+ });
714
+
261
715
  // src/core/events/schema.ts
262
716
  var import_uuid = require("uuid");
263
717
  var import_zod = require("zod");
@@ -296,6 +750,8 @@ var TOOL_NAMES = [
296
750
  "kiro",
297
751
  "augment-code",
298
752
  "mistral",
753
+ "zed",
754
+ "pi",
299
755
  "unknown"
300
756
  ];
301
757
  var ERROR_TYPES = [
@@ -337,47 +793,58 @@ function createUuidV7() {
337
793
  return (0, import_uuid.v7)();
338
794
  }
339
795
  var ToolInputSchema = import_zod.z.strictObject({
340
- filePath: import_zod.z.string().min(1).optional(),
341
- command: import_zod.z.string().min(1).optional()
796
+ filePath: import_zod.z.string().min(1).max(4096).optional(),
797
+ command: import_zod.z.string().min(1).max(1e4).optional()
342
798
  }).refine(
343
799
  (value) => value.filePath !== void 0 || value.command !== void 0,
344
800
  "toolInput must include filePath or command"
345
801
  );
802
+ var ThinkingContentSchema = import_zod.z.string().max(1e5).describe("Raw thinking/reasoning content from the AI model");
803
+ var ToolCallNameSchema = import_zod.z.string().min(1).max(100).describe("Name of the tool being invoked (e.g., Edit, Bash, Grep)");
804
+ var FinalMessageSchema = import_zod.z.string().max(5e4).describe("End-of-run summary or completion message");
805
+ var ToolResultSchema = import_zod.z.string().max(1e4).describe("Tool execution result or output");
806
+ var MessageContentSchema = import_zod.z.string().max(1e5).describe("Raw text content from AI messages");
346
807
  var ToolNameSchema = import_zod.z.enum(TOOL_NAMES);
347
808
  var AISnitchEventTypeSchema = import_zod.z.enum(AISNITCH_EVENT_TYPES);
348
809
  var ErrorTypeSchema = import_zod.z.enum(ERROR_TYPES);
349
810
  var CESPCategorySchema = import_zod.z.enum(CESP_CATEGORIES);
350
811
  var EventDataSchema = import_zod.z.strictObject({
351
812
  state: AISnitchEventTypeSchema,
352
- project: import_zod.z.string().min(1).optional(),
353
- projectPath: import_zod.z.string().min(1).optional(),
813
+ project: import_zod.z.string().min(1).max(255).optional(),
814
+ projectPath: import_zod.z.string().min(1).max(4096).optional(),
354
815
  duration: import_zod.z.number().int().min(0).optional(),
355
- toolName: import_zod.z.string().min(1).optional(),
816
+ toolName: import_zod.z.string().min(1).max(100).optional(),
356
817
  toolInput: ToolInputSchema.optional(),
357
- activeFile: import_zod.z.string().min(1).optional(),
358
- model: import_zod.z.string().min(1).optional(),
818
+ activeFile: import_zod.z.string().min(1).max(4096).optional(),
819
+ model: import_zod.z.string().min(1).max(200).optional(),
359
820
  tokensUsed: import_zod.z.number().int().min(0).optional(),
360
- errorMessage: import_zod.z.string().min(1).optional(),
821
+ errorMessage: import_zod.z.string().min(1).max(1e4).optional(),
361
822
  errorType: ErrorTypeSchema.optional(),
362
823
  raw: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional(),
363
- terminal: import_zod.z.string().min(1).optional(),
364
- cwd: import_zod.z.string().min(1).optional(),
824
+ terminal: import_zod.z.string().min(1).max(100).optional(),
825
+ cwd: import_zod.z.string().min(1).max(4096).optional(),
365
826
  pid: import_zod.z.number().int().positive().optional(),
366
- instanceId: import_zod.z.string().min(1).optional(),
827
+ instanceId: import_zod.z.string().min(1).max(255).optional(),
367
828
  instanceIndex: import_zod.z.number().int().min(1).optional(),
368
- instanceTotal: import_zod.z.number().int().min(1).optional()
829
+ instanceTotal: import_zod.z.number().int().min(1).optional(),
830
+ // New fields for enhanced content capture
831
+ thinkingContent: ThinkingContentSchema.optional(),
832
+ toolCallName: ToolCallNameSchema.optional(),
833
+ finalMessage: FinalMessageSchema.optional(),
834
+ toolResult: ToolResultSchema.optional(),
835
+ messageContent: MessageContentSchema.optional()
369
836
  });
370
837
  var AISnitchEventSchema = import_zod.z.strictObject({
371
838
  specversion: import_zod.z.literal("1.0"),
372
839
  id: import_zod.z.string().refine(isUuidV7, "id must be a valid UUIDv7 string"),
373
- source: import_zod.z.string().refine(
840
+ source: import_zod.z.string().max(2e3).refine(
374
841
  isValidUriReference,
375
842
  "source must be a valid non-empty CloudEvents URI-reference"
376
843
  ),
377
844
  type: AISnitchEventTypeSchema,
378
845
  time: ISO_TIMESTAMP_SCHEMA,
379
846
  "aisnitch.tool": ToolNameSchema,
380
- "aisnitch.sessionid": import_zod.z.string().min(1),
847
+ "aisnitch.sessionid": import_zod.z.string().min(1).max(500),
381
848
  "aisnitch.seqnum": import_zod.z.number().int().min(1),
382
849
  data: EventDataSchema
383
850
  });
@@ -491,20 +958,29 @@ var BaseAdapter = class {
491
958
  });
492
959
  let published;
493
960
  try {
494
- published = await this.publishEventImplementation(event, {
495
- cwd: context.cwd,
496
- env: context.env,
497
- hookPayload: context.hookPayload,
498
- pid: context.pid,
499
- sessionId,
500
- source: context.source,
501
- transcriptPath: context.transcriptPath
961
+ published = await SHARED_BREAKERS.adapterEmit.execute(async () => {
962
+ return await this.publishEventImplementation(event, {
963
+ cwd: context.cwd,
964
+ env: context.env,
965
+ hookPayload: context.hookPayload,
966
+ pid: context.pid,
967
+ sessionId,
968
+ source: context.source,
969
+ transcriptPath: context.transcriptPath
970
+ });
502
971
  });
503
972
  } catch (error) {
504
- logger.error(
505
- { error, eventType: type, adapter: this.name, sessionId },
506
- "\u{1F4D6} Failed to publish event \u2014 swallowing to prevent daemon crash"
507
- );
973
+ if (error instanceof Error && error.name === "CircuitOpenError") {
974
+ logger.warn(
975
+ { error, eventType: type, adapter: this.name },
976
+ "\u{1F4D6} Adapter emit blocked by open circuit \u2014 event dropped"
977
+ );
978
+ } else {
979
+ logger.error(
980
+ { error, eventType: type, adapter: this.name, sessionId },
981
+ "\u{1F4D6} Failed to publish event \u2014 swallowing to prevent daemon crash"
982
+ );
983
+ }
508
984
  published = false;
509
985
  }
510
986
  if (published) {
@@ -1518,7 +1994,11 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
1518
1994
  return;
1519
1995
  }
1520
1996
  case "SessionEnd": {
1521
- await this.emitStateChange("session.end", sharedData, context);
1997
+ const finalMessage = extractFinalMessageFromPayload(payload);
1998
+ await this.emitStateChange("session.end", {
1999
+ ...sharedData,
2000
+ finalMessage
2001
+ }, context);
1522
2002
  return;
1523
2003
  }
1524
2004
  case "UserPromptSubmit":
@@ -1535,12 +2015,22 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
1535
2015
  return;
1536
2016
  }
1537
2017
  case "PreToolUse": {
1538
- await this.emitStateChange("agent.tool_call", sharedData, context);
2018
+ const toolCallName = extractToolNameFromPayload(payload);
2019
+ await this.emitStateChange("agent.tool_call", {
2020
+ ...sharedData,
2021
+ toolCallName
2022
+ }, context);
1539
2023
  return;
1540
2024
  }
1541
2025
  case "PostToolUse": {
2026
+ const toolCallName = extractToolNameFromPayload(payload);
2027
+ const toolResult = extractToolResultFromPayload(payload);
1542
2028
  const emittedType = isClaudeCodingTool(sharedData.toolName) ? "agent.coding" : "agent.tool_call";
1543
- await this.emitStateChange(emittedType, sharedData, context);
2029
+ await this.emitStateChange(emittedType, {
2030
+ ...sharedData,
2031
+ toolCallName,
2032
+ toolResult
2033
+ }, context);
1544
2034
  return;
1545
2035
  }
1546
2036
  case "PostToolUseFailure":
@@ -1742,21 +2232,50 @@ function extractClaudeTranscriptObservations(payload, transcriptPath) {
1742
2232
  };
1743
2233
  const observations = [];
1744
2234
  if (contentParts.some((part) => part.type === "thinking")) {
2235
+ const thinkingParts = contentParts.filter((part) => part.type === "thinking");
2236
+ const thinkingText = thinkingParts.map((part) => {
2237
+ const text = part.text;
2238
+ return typeof text === "string" ? text : void 0;
2239
+ }).filter((text) => text !== void 0).join("\n");
1745
2240
  observations.push({
1746
2241
  context: sharedContext,
1747
- data: sharedData,
2242
+ data: {
2243
+ ...sharedData,
2244
+ thinkingContent: thinkingText.length > 0 ? thinkingText : void 0
2245
+ },
1748
2246
  type: "agent.thinking"
1749
2247
  });
1750
2248
  }
1751
2249
  if (contentParts.some(
1752
2250
  (part) => part.type === "text" && typeof part.text === "string" && part.text.trim().length > 0
1753
2251
  )) {
2252
+ const messageTexts = contentParts.filter((part) => part.type === "text").map((part) => part.text).filter((text) => text.trim().length > 0);
2253
+ const messageContent = messageTexts.join("\n");
1754
2254
  observations.push({
1755
2255
  context: sharedContext,
1756
- data: sharedData,
2256
+ data: {
2257
+ ...sharedData,
2258
+ messageContent: messageContent.length > 0 ? messageContent : void 0
2259
+ },
1757
2260
  type: "agent.streaming"
1758
2261
  });
1759
2262
  }
2263
+ const toolUseParts = contentParts.filter(
2264
+ (part) => part.type === "tool_use" || part.type === "toolUse"
2265
+ );
2266
+ if (toolUseParts.length > 0) {
2267
+ const toolName = getString(toolUseParts[0], "name") ?? getString(toolUseParts[0], "tool");
2268
+ if (toolName) {
2269
+ observations.push({
2270
+ context: sharedContext,
2271
+ data: {
2272
+ ...sharedData,
2273
+ toolCallName: toolName
2274
+ },
2275
+ type: "agent.tool_call"
2276
+ });
2277
+ }
2278
+ }
1760
2279
  return observations;
1761
2280
  }
1762
2281
  function extractClaudeContentParts(payload) {
@@ -1879,6 +2398,51 @@ function getString(payload, key) {
1879
2398
  const value = payload[key];
1880
2399
  return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1881
2400
  }
2401
+ function extractToolNameFromPayload(payload) {
2402
+ const directToolName = getString(payload, "tool_name") ?? getString(payload, "toolName");
2403
+ if (directToolName) {
2404
+ return directToolName;
2405
+ }
2406
+ const toolUse = getRecord(payload.tool_use) ?? getRecord(payload.toolUse);
2407
+ if (toolUse) {
2408
+ return getString(toolUse, "name") ?? getString(toolUse, "tool");
2409
+ }
2410
+ const toolInput = getRecord(payload.tool_input) ?? getRecord(payload.toolInput);
2411
+ if (toolInput) {
2412
+ return getString(toolInput, "tool_name") ?? getString(toolInput, "type");
2413
+ }
2414
+ return void 0;
2415
+ }
2416
+ function extractToolResultFromPayload(payload) {
2417
+ const directResult = getString(payload, "result") ?? getString(payload, "output");
2418
+ if (directResult) {
2419
+ return directResult;
2420
+ }
2421
+ const toolResult = getRecord(payload.tool_result) ?? getRecord(payload.toolResult);
2422
+ if (toolResult) {
2423
+ return getString(toolResult, "content") ?? getString(toolResult, "output");
2424
+ }
2425
+ const errorField = getString(payload, "error") ?? getString(payload, "error_message");
2426
+ if (errorField) {
2427
+ return errorField;
2428
+ }
2429
+ return void 0;
2430
+ }
2431
+ function extractFinalMessageFromPayload(payload) {
2432
+ const directMessage = getString(payload, "final_message") ?? getString(payload, "finalMessage") ?? getString(payload, "summary") ?? getString(payload, "completion_message");
2433
+ if (directMessage) {
2434
+ return directMessage;
2435
+ }
2436
+ const result = getString(payload, "result") ?? getString(payload, "output") ?? getString(payload, "message");
2437
+ if (result) {
2438
+ return result;
2439
+ }
2440
+ const stats = getRecord(payload.stats);
2441
+ if (stats) {
2442
+ return getString(stats, "summary") ?? getString(stats, "completion_summary");
2443
+ }
2444
+ return void 0;
2445
+ }
1882
2446
 
1883
2447
  // src/adapters/copilot-cli.ts
1884
2448
  var import_node_child_process3 = require("child_process");
@@ -6852,7 +7416,11 @@ var OpenCodeAdapter = class extends BaseAdapter {
6852
7416
  return;
6853
7417
  }
6854
7418
  case "session.deleted": {
6855
- await this.emitStateChange("session.end", sharedData, context);
7419
+ const finalMessage = extractOpenCodeFinalMessage(payload);
7420
+ await this.emitStateChange("session.end", {
7421
+ ...sharedData,
7422
+ finalMessage
7423
+ }, context);
6856
7424
  return;
6857
7425
  }
6858
7426
  case "session.error": {
@@ -6877,12 +7445,22 @@ var OpenCodeAdapter = class extends BaseAdapter {
6877
7445
  return;
6878
7446
  }
6879
7447
  case "tool.execute.before": {
6880
- await this.emitStateChange("agent.tool_call", sharedData, context);
7448
+ const toolCallName = extractOpenCodeToolName(payload);
7449
+ await this.emitStateChange("agent.tool_call", {
7450
+ ...sharedData,
7451
+ toolCallName
7452
+ }, context);
6881
7453
  return;
6882
7454
  }
6883
7455
  case "tool.execute.after": {
7456
+ const toolCallName = extractOpenCodeToolName(payload);
7457
+ const toolResult = extractOpenCodeToolResult(payload);
6884
7458
  const emittedType = isOpenCodeCodingTool(sharedData.toolName) ? "agent.coding" : "agent.tool_call";
6885
- await this.emitStateChange(emittedType, sharedData, context);
7459
+ await this.emitStateChange(emittedType, {
7460
+ ...sharedData,
7461
+ toolCallName,
7462
+ toolResult
7463
+ }, context);
6886
7464
  return;
6887
7465
  }
6888
7466
  default: {
@@ -7049,68 +7627,597 @@ function getString10(payload, key) {
7049
7627
  const value = payload[key];
7050
7628
  return typeof value === "string" && value.trim().length > 0 ? value : void 0;
7051
7629
  }
7052
-
7053
- // src/adapters/registry.ts
7054
- var AdapterRegistry = class {
7055
- adapters = /* @__PURE__ */ new Map();
7056
- /**
7057
- * Registers one built-in or community adapter instance.
7058
- */
7059
- register(adapter) {
7060
- if (this.adapters.has(adapter.name)) {
7061
- throw new Error(`Adapter "${adapter.name}" is already registered.`);
7062
- }
7063
- this.adapters.set(adapter.name, adapter);
7630
+ function extractOpenCodeFinalMessage(payload) {
7631
+ const directMessage = getString10(payload, "final_message") ?? getString10(payload, "finalMessage") ?? getString10(payload, "summary") ?? getString10(payload, "completion_message");
7632
+ if (directMessage) {
7633
+ return directMessage;
7064
7634
  }
7065
- /**
7066
- * Returns one adapter instance by its tool name.
7067
- */
7068
- get(toolName) {
7069
- return this.adapters.get(toolName);
7635
+ const result = getString10(payload, "result") ?? getString10(payload, "output") ?? getString10(getRecord9(payload.properties), "result");
7636
+ if (result) {
7637
+ return result;
7070
7638
  }
7071
- /**
7072
- * Lists every registered adapter.
7073
- */
7074
- list() {
7075
- return [...this.adapters.values()];
7639
+ return void 0;
7640
+ }
7641
+ function extractOpenCodeToolResult(payload) {
7642
+ const directResult = getString10(payload, "result") ?? getString10(payload, "output") ?? getString10(payload, "toolResult");
7643
+ if (directResult) {
7644
+ return directResult;
7076
7645
  }
7077
- /**
7078
- * Returns one status snapshot per registered adapter.
7079
- */
7080
- getStatus() {
7081
- return this.list().map((adapter) => adapter.getStatus());
7646
+ const toolResult = getRecord9(payload.tool_result) ?? getRecord9(payload.toolResult);
7647
+ if (toolResult) {
7648
+ return getString10(toolResult, "content") ?? getString10(toolResult, "output");
7082
7649
  }
7083
- /**
7084
- * Starts every adapter enabled in the current AISnitch config.
7085
- * 📖 Each adapter is started independently — one failure does not prevent
7086
- * the others from starting.
7087
- */
7088
- async startAll(config) {
7089
- for (const adapter of this.list()) {
7090
- if (config.adapters[adapter.name]?.enabled !== true) {
7091
- continue;
7092
- }
7093
- try {
7094
- await adapter.start();
7095
- } catch (error) {
7096
- logger.error(
7097
- { error, adapter: adapter.name },
7098
- `\u{1F4D6} Failed to start adapter "${adapter.name}" \u2014 skipping`
7099
- );
7100
- }
7650
+ const props = getRecord9(payload.properties);
7651
+ if (props) {
7652
+ const nestedResult = getRecord9(props.tool_result) ?? getRecord9(props.toolResult);
7653
+ if (nestedResult) {
7654
+ return getString10(nestedResult, "content") ?? getString10(nestedResult, "output");
7101
7655
  }
7102
7656
  }
7103
- /**
7104
- * Stops every adapter in reverse registration order.
7105
- * 📖 Each adapter is stopped independently — one failure does not prevent
7106
- * the others from being stopped.
7107
- */
7108
- async stopAll() {
7109
- const adapters = this.list().reverse();
7110
- for (const adapter of adapters) {
7111
- try {
7112
- await adapter.stop();
7113
- } catch (error) {
7657
+ return void 0;
7658
+ }
7659
+
7660
+ // src/adapters/pi.ts
7661
+ var import_node_child_process12 = require("child_process");
7662
+ var import_node_path12 = require("path");
7663
+ var import_node_util12 = require("util");
7664
+ var execFileAsync = (0, import_node_util12.promisify)(import_node_child_process12.execFile);
7665
+ var PiAdapter = class extends BaseAdapter {
7666
+ displayName = "Pi (MiniMax)";
7667
+ name = "pi";
7668
+ strategies = [
7669
+ "process-detect",
7670
+ "api-client",
7671
+ "log-watch"
7672
+ ];
7673
+ apiPort = 7890;
7674
+ logPath;
7675
+ poller = null;
7676
+ activePiSessions = /* @__PURE__ */ new Map();
7677
+ lastCheckedTime = 0;
7678
+ constructor(options) {
7679
+ super(options);
7680
+ this.logPath = (0, import_node_path12.join)(
7681
+ options.homeDirectory ?? process.env.HOME ?? "",
7682
+ ".pi",
7683
+ "agent.log"
7684
+ );
7685
+ }
7686
+ start() {
7687
+ if (this.getStatus().running) {
7688
+ return Promise.resolve();
7689
+ }
7690
+ this.setRunning(true);
7691
+ this.startPolling();
7692
+ logger.info({ adapter: this.name }, "Pi adapter started");
7693
+ return Promise.resolve();
7694
+ }
7695
+ stop() {
7696
+ if (this.poller !== null) {
7697
+ clearInterval(this.poller);
7698
+ this.poller = null;
7699
+ }
7700
+ this.setRunning(false);
7701
+ logger.info({ adapter: this.name }, "Pi adapter stopped");
7702
+ return Promise.resolve();
7703
+ }
7704
+ async handleHook(payload) {
7705
+ const normalized = this.parseNormalizedHookPayload(payload);
7706
+ if (normalized === null) {
7707
+ return;
7708
+ }
7709
+ const context = {
7710
+ cwd: normalized.cwd,
7711
+ pid: normalized.pid,
7712
+ sessionId: normalized.sessionId,
7713
+ source: "pi-hook"
7714
+ };
7715
+ const eventType = this.mapEventType(normalized.type ?? "");
7716
+ const eventData = this.buildEventData(eventType, normalized);
7717
+ await this.emit(eventType, eventData, context);
7718
+ }
7719
+ startPolling() {
7720
+ this.poller = setInterval(() => {
7721
+ void this.pollPiActivity();
7722
+ }, 2e3);
7723
+ }
7724
+ async pollPiActivity() {
7725
+ const running = await this.detectPiInstance();
7726
+ if (!running) {
7727
+ for (const [sessionId, activity] of this.activePiSessions) {
7728
+ if (activity.state !== "idle") {
7729
+ activity.state = "idle";
7730
+ await this.emitIdle(sessionId);
7731
+ }
7732
+ }
7733
+ return;
7734
+ }
7735
+ try {
7736
+ const response = await fetch(
7737
+ `http://127.0.0.1:${this.apiPort}/api/status`,
7738
+ {
7739
+ signal: AbortSignal.timeout(500)
7740
+ }
7741
+ );
7742
+ if (response.ok) {
7743
+ const data = await response.json();
7744
+ await this.processPiApiResponse(data);
7745
+ }
7746
+ } catch {
7747
+ await this.checkMiniMaxApi();
7748
+ }
7749
+ }
7750
+ async detectPiInstance() {
7751
+ try {
7752
+ const result = await execFileAsync("pgrep", ["-l", "pi|minimax"]);
7753
+ if (result.stdout.includes("pi") || result.stdout.includes("minimax")) {
7754
+ return true;
7755
+ }
7756
+ } catch {
7757
+ }
7758
+ try {
7759
+ const response = await fetch(
7760
+ `http://127.0.0.1:${this.apiPort}/health`,
7761
+ {
7762
+ signal: AbortSignal.timeout(200)
7763
+ }
7764
+ );
7765
+ if (response.ok) {
7766
+ return true;
7767
+ }
7768
+ } catch {
7769
+ }
7770
+ return false;
7771
+ }
7772
+ async checkMiniMaxApi() {
7773
+ try {
7774
+ const response = await fetch("http://127.0.0.1:3000/api/agent/status", {
7775
+ signal: AbortSignal.timeout(500)
7776
+ });
7777
+ if (response.ok) {
7778
+ const data = await response.json();
7779
+ await this.processPiApiResponse(data);
7780
+ }
7781
+ } catch {
7782
+ }
7783
+ }
7784
+ async processPiApiResponse(data) {
7785
+ const rawSession = data.sessionId ?? data.project ?? "default";
7786
+ const sessionId = `pi:${rawSession.replace(/[^a-zA-Z0-9-_]/g, "-")}`;
7787
+ let activity = this.activePiSessions.get(sessionId);
7788
+ if (!activity) {
7789
+ activity = { sessionId, state: "idle" };
7790
+ this.activePiSessions.set(sessionId, activity);
7791
+ await this.emitSessionStart(sessionId, data);
7792
+ }
7793
+ const rawState = data.state ?? "idle";
7794
+ const state = rawState;
7795
+ if (state !== activity.state) {
7796
+ switch (state) {
7797
+ case "thinking": {
7798
+ const rawThinking = data.thinking;
7799
+ if (rawThinking) {
7800
+ await this.emitThinking(sessionId, rawThinking);
7801
+ }
7802
+ break;
7803
+ }
7804
+ case "tool": {
7805
+ const rawFilePath = data.filePath;
7806
+ const rawCommand = data.command;
7807
+ const rawToolName = data.toolName ?? "unknown";
7808
+ await this.emitToolCall(
7809
+ sessionId,
7810
+ {
7811
+ filePath: rawFilePath ?? "",
7812
+ command: rawCommand ?? ""
7813
+ },
7814
+ rawToolName
7815
+ );
7816
+ break;
7817
+ }
7818
+ case "output": {
7819
+ const rawOutput = data.output;
7820
+ if (rawOutput) {
7821
+ await this.emitOutput(sessionId, rawOutput);
7822
+ }
7823
+ break;
7824
+ }
7825
+ case "error": {
7826
+ const rawError = data.error ?? "Unknown error";
7827
+ await this.emitError(sessionId, rawError);
7828
+ break;
7829
+ }
7830
+ case "idle":
7831
+ await this.emitIdle(sessionId);
7832
+ break;
7833
+ }
7834
+ activity.state = state;
7835
+ }
7836
+ }
7837
+ async emitSessionStart(sessionId, data) {
7838
+ const rawProject = data.project ?? "pi-project";
7839
+ const rawModel = data.model ?? "minimax/moonshot";
7840
+ const eventData = {
7841
+ state: "session.start",
7842
+ project: rawProject,
7843
+ model: rawModel,
7844
+ raw: data
7845
+ };
7846
+ await this.emit("session.start", eventData, { sessionId });
7847
+ }
7848
+ async emitThinking(sessionId, content) {
7849
+ if (!content) return;
7850
+ const eventData = {
7851
+ state: "agent.thinking",
7852
+ thinkingContent: content
7853
+ };
7854
+ await this.emit("agent.thinking", eventData, { sessionId });
7855
+ }
7856
+ async emitToolCall(sessionId, toolInput, toolName) {
7857
+ const eventData = {
7858
+ state: "agent.tool_call",
7859
+ toolCallName: toolName,
7860
+ toolInput,
7861
+ activeFile: toolInput.filePath
7862
+ };
7863
+ await this.emit("agent.tool_call", eventData, { sessionId });
7864
+ }
7865
+ async emitOutput(sessionId, content) {
7866
+ if (!content) return;
7867
+ const eventData = {
7868
+ state: "agent.streaming",
7869
+ messageContent: content
7870
+ };
7871
+ await this.emit("agent.streaming", eventData, { sessionId });
7872
+ }
7873
+ async emitError(sessionId, errorMessage) {
7874
+ const eventData = {
7875
+ state: "agent.error",
7876
+ errorMessage,
7877
+ errorType: "api_error"
7878
+ };
7879
+ await this.emit("agent.error", eventData, { sessionId });
7880
+ }
7881
+ async emitIdle(sessionId) {
7882
+ const eventData = {
7883
+ state: "agent.idle"
7884
+ };
7885
+ await this.emit("agent.idle", eventData, { sessionId });
7886
+ }
7887
+ mapEventType(type) {
7888
+ const mapping = {
7889
+ "session.start": "session.start",
7890
+ "session.end": "session.end",
7891
+ "task.start": "task.start",
7892
+ "task.complete": "task.complete",
7893
+ thinking: "agent.thinking",
7894
+ tool: "agent.tool_call",
7895
+ coding: "agent.coding",
7896
+ output: "agent.streaming",
7897
+ message: "agent.streaming",
7898
+ ask: "agent.asking_user",
7899
+ error: "agent.error",
7900
+ idle: "agent.idle",
7901
+ compact: "agent.compact"
7902
+ };
7903
+ return mapping[type] ?? "agent.streaming";
7904
+ }
7905
+ buildEventData(eventType, payload) {
7906
+ const data = payload.data ?? {};
7907
+ return {
7908
+ state: eventType,
7909
+ project: data.project,
7910
+ activeFile: data.activeFile,
7911
+ model: data.model,
7912
+ toolInput: data.toolInput,
7913
+ toolCallName: data.toolCallName,
7914
+ thinkingContent: data.thinkingContent,
7915
+ messageContent: data.messageContent,
7916
+ finalMessage: data.finalMessage,
7917
+ toolResult: data.toolResult,
7918
+ errorMessage: data.errorMessage,
7919
+ errorType: data.errorType,
7920
+ raw: data.raw
7921
+ };
7922
+ }
7923
+ };
7924
+
7925
+ // src/adapters/zed.ts
7926
+ var import_promises11 = require("fs/promises");
7927
+ var import_node_path13 = require("path");
7928
+ var ZedAdapter = class extends BaseAdapter {
7929
+ displayName = "Zed AI";
7930
+ name = "zed";
7931
+ strategies = [
7932
+ "process-detect",
7933
+ "api-client"
7934
+ ];
7935
+ logPaths;
7936
+ apiPort = 9876;
7937
+ pollIntervalMs;
7938
+ poller = null;
7939
+ lastEventTime = 0;
7940
+ activeZedSessions = /* @__PURE__ */ new Map();
7941
+ constructor(options) {
7942
+ super(options);
7943
+ this.pollIntervalMs = 2e3;
7944
+ this.logPaths = [
7945
+ (0, import_node_path13.join)(options.homeDirectory ?? process.env.HOME ?? "", ".config", "zed", "logs", "agent.log"),
7946
+ "/tmp/zed-agent.log"
7947
+ ];
7948
+ }
7949
+ start() {
7950
+ if (this.getStatus().running) {
7951
+ return Promise.resolve();
7952
+ }
7953
+ this.setRunning(true);
7954
+ this.startPolling();
7955
+ logger.info({ adapter: this.name }, "Zed adapter started");
7956
+ return Promise.resolve();
7957
+ }
7958
+ stop() {
7959
+ if (this.poller !== null) {
7960
+ clearInterval(this.poller);
7961
+ this.poller = null;
7962
+ }
7963
+ this.setRunning(false);
7964
+ logger.info({ adapter: this.name }, "Zed adapter stopped");
7965
+ return Promise.resolve();
7966
+ }
7967
+ async handleHook(payload) {
7968
+ const normalized = this.parseNormalizedHookPayload(payload);
7969
+ if (normalized === null) {
7970
+ return;
7971
+ }
7972
+ const context = {
7973
+ cwd: normalized.cwd,
7974
+ pid: normalized.pid,
7975
+ sessionId: normalized.sessionId,
7976
+ source: "zed-hook"
7977
+ };
7978
+ const eventType = this.mapEventType(normalized.type ?? "");
7979
+ const eventData = this.buildEventData(eventType, normalized);
7980
+ await this.emit(eventType, eventData, context);
7981
+ }
7982
+ startPolling() {
7983
+ this.poller = setInterval(() => {
7984
+ void this.pollZedStatus();
7985
+ }, this.pollIntervalMs);
7986
+ }
7987
+ async pollZedStatus() {
7988
+ try {
7989
+ const response = await fetch(`http://127.0.0.1:${this.apiPort}/api/agent/status`, {
7990
+ signal: AbortSignal.timeout(1e3)
7991
+ });
7992
+ if (response.ok) {
7993
+ const data = await response.json();
7994
+ if (data.sessionId && typeof data.sessionId === "string") {
7995
+ const sessionId = `zed:${data.sessionId}`;
7996
+ if (!this.activeZedSessions.has(sessionId)) {
7997
+ this.activeZedSessions.set(sessionId, sessionId);
7998
+ await this.emitSessionStart(sessionId, data);
7999
+ }
8000
+ if (data.state === "thinking" && this.lastEventTime < Date.now() - 5e3) {
8001
+ const rawThinking = data.thinking;
8002
+ if (rawThinking) {
8003
+ await this.emitThinking(sessionId, rawThinking);
8004
+ }
8005
+ } else if (data.state === "tool" && data.toolName) {
8006
+ const rawFilePath = data.filePath;
8007
+ const rawCommand = data.command;
8008
+ const rawToolName = data.toolName ?? "unknown";
8009
+ await this.emitToolCall(
8010
+ sessionId,
8011
+ {
8012
+ filePath: rawFilePath ?? "",
8013
+ command: rawCommand ?? ""
8014
+ },
8015
+ rawToolName
8016
+ );
8017
+ } else if (data.state === "idle") {
8018
+ await this.emitIdle(sessionId);
8019
+ }
8020
+ }
8021
+ }
8022
+ } catch {
8023
+ await this.checkLogFiles();
8024
+ }
8025
+ }
8026
+ async checkLogFiles() {
8027
+ for (const logPath of this.logPaths) {
8028
+ try {
8029
+ const content = await (0, import_promises11.readFile)(logPath, "utf8");
8030
+ await this.parseLogContent(content);
8031
+ } catch {
8032
+ }
8033
+ }
8034
+ }
8035
+ async parseLogContent(content) {
8036
+ const lines = content.split("\n").filter((line) => line.trim());
8037
+ for (const line of lines) {
8038
+ if (this.lastEventTime > 0 && this.lastEventTime >= Date.now() - 2e3) {
8039
+ continue;
8040
+ }
8041
+ const event = this.extractZedEventFromLog(line);
8042
+ if (event) {
8043
+ await this.handleHook(event);
8044
+ this.lastEventTime = Date.now();
8045
+ }
8046
+ }
8047
+ }
8048
+ extractZedEventFromLog(line) {
8049
+ try {
8050
+ const parsed = JSON.parse(line);
8051
+ if (!parsed.type || typeof parsed.type !== "string") {
8052
+ return null;
8053
+ }
8054
+ const rawSessionId = parsed.sessionId;
8055
+ const rawWorkspace = parsed.workspace;
8056
+ const sessionId = rawSessionId ? rawSessionId : rawWorkspace ? `zed:${(0, import_node_path13.basename)(rawWorkspace)}` : `zed:${Date.now()}`;
8057
+ const rawCwd = parsed.cwd ?? rawWorkspace;
8058
+ return {
8059
+ type: parsed.type,
8060
+ sessionId,
8061
+ cwd: rawCwd,
8062
+ data: {
8063
+ project: parsed.project ?? rawWorkspace ? (0, import_node_path13.basename)(String(rawWorkspace)) : void 0,
8064
+ model: parsed.model,
8065
+ state: parsed.type,
8066
+ thinkingContent: parsed.thinking,
8067
+ toolCallName: parsed.toolName,
8068
+ toolInput: parsed.toolInput,
8069
+ messageContent: parsed.message ?? parsed.output,
8070
+ errorMessage: parsed.error,
8071
+ raw: parsed
8072
+ }
8073
+ };
8074
+ } catch {
8075
+ if (line.includes("[zed:agent]")) {
8076
+ const cleaned = line.replace(/^\[.*?\] \[.*?\] /, "");
8077
+ if (cleaned.includes("Thinking:")) {
8078
+ return { type: "thinking", thinkingContent: cleaned.replace("Thinking:", "").trim() };
8079
+ }
8080
+ if (cleaned.includes("Executing tool:")) {
8081
+ return { type: "tool", toolCallName: cleaned.replace("Executing tool:", "").trim() };
8082
+ }
8083
+ if (cleaned.includes("Error:")) {
8084
+ return { type: "error", errorMessage: cleaned.replace("Error:", "").trim() };
8085
+ }
8086
+ }
8087
+ return null;
8088
+ }
8089
+ }
8090
+ async emitSessionStart(sessionId, _data) {
8091
+ const eventData = {
8092
+ state: "session.start",
8093
+ project: sessionId.split(":")[1] ?? "unknown"
8094
+ };
8095
+ await this.emit("session.start", eventData, { sessionId });
8096
+ }
8097
+ async emitThinking(sessionId, content) {
8098
+ if (!content) return;
8099
+ const eventData = {
8100
+ state: "agent.thinking",
8101
+ thinkingContent: content
8102
+ };
8103
+ await this.emit("agent.thinking", eventData, { sessionId });
8104
+ this.lastEventTime = Date.now();
8105
+ }
8106
+ async emitToolCall(sessionId, toolInput, toolName) {
8107
+ const eventData = {
8108
+ state: "agent.tool_call",
8109
+ toolCallName: toolName,
8110
+ toolInput,
8111
+ activeFile: toolInput.filePath
8112
+ };
8113
+ await this.emit("agent.tool_call", eventData, { sessionId });
8114
+ this.lastEventTime = Date.now();
8115
+ }
8116
+ async emitIdle(sessionId) {
8117
+ const eventData = {
8118
+ state: "agent.idle"
8119
+ };
8120
+ await this.emit("agent.idle", eventData, { sessionId });
8121
+ }
8122
+ mapEventType(type) {
8123
+ const mapping = {
8124
+ "session.start": "session.start",
8125
+ "session.end": "session.end",
8126
+ "task.start": "task.start",
8127
+ "task.complete": "task.complete",
8128
+ thinking: "agent.thinking",
8129
+ tool: "agent.tool_call",
8130
+ coding: "agent.coding",
8131
+ output: "agent.streaming",
8132
+ message: "agent.streaming",
8133
+ ask: "agent.asking_user",
8134
+ error: "agent.error",
8135
+ idle: "agent.idle",
8136
+ compact: "agent.compact"
8137
+ };
8138
+ return mapping[type] ?? "agent.streaming";
8139
+ }
8140
+ buildEventData(eventType, payload) {
8141
+ const data = payload.data ?? {};
8142
+ return {
8143
+ state: eventType,
8144
+ project: data.project,
8145
+ activeFile: data.activeFile,
8146
+ model: data.model,
8147
+ toolInput: data.toolInput,
8148
+ toolCallName: data.toolCallName,
8149
+ thinkingContent: data.thinkingContent,
8150
+ messageContent: data.messageContent,
8151
+ finalMessage: data.finalMessage,
8152
+ toolResult: data.toolResult,
8153
+ errorMessage: data.errorMessage,
8154
+ errorType: data.errorType,
8155
+ raw: data.raw
8156
+ };
8157
+ }
8158
+ };
8159
+
8160
+ // src/adapters/registry.ts
8161
+ var AdapterRegistry = class {
8162
+ adapters = /* @__PURE__ */ new Map();
8163
+ /**
8164
+ * Registers one built-in or community adapter instance.
8165
+ */
8166
+ register(adapter) {
8167
+ if (this.adapters.has(adapter.name)) {
8168
+ throw new Error(`Adapter "${adapter.name}" is already registered.`);
8169
+ }
8170
+ this.adapters.set(adapter.name, adapter);
8171
+ }
8172
+ /**
8173
+ * Returns one adapter instance by its tool name.
8174
+ */
8175
+ get(toolName) {
8176
+ return this.adapters.get(toolName);
8177
+ }
8178
+ /**
8179
+ * Lists every registered adapter.
8180
+ */
8181
+ list() {
8182
+ return [...this.adapters.values()];
8183
+ }
8184
+ /**
8185
+ * Returns one status snapshot per registered adapter.
8186
+ */
8187
+ getStatus() {
8188
+ return this.list().map((adapter) => adapter.getStatus());
8189
+ }
8190
+ /**
8191
+ * Starts every adapter enabled in the current AISnitch config.
8192
+ * 📖 Each adapter is started independently — one failure does not prevent
8193
+ * the others from starting.
8194
+ */
8195
+ async startAll(config) {
8196
+ for (const adapter of this.list()) {
8197
+ if (config.adapters[adapter.name]?.enabled !== true) {
8198
+ continue;
8199
+ }
8200
+ try {
8201
+ await adapter.start();
8202
+ } catch (error) {
8203
+ logger.error(
8204
+ { error, adapter: adapter.name },
8205
+ `\u{1F4D6} Failed to start adapter "${adapter.name}" \u2014 skipping`
8206
+ );
8207
+ }
8208
+ }
8209
+ }
8210
+ /**
8211
+ * Stops every adapter in reverse registration order.
8212
+ * 📖 Each adapter is stopped independently — one failure does not prevent
8213
+ * the others from being stopped.
8214
+ */
8215
+ async stopAll() {
8216
+ const adapters = this.list().reverse();
8217
+ for (const adapter of adapters) {
8218
+ try {
8219
+ await adapter.stop();
8220
+ } catch (error) {
7114
8221
  logger.warn(
7115
8222
  { error, adapter: adapter.name },
7116
8223
  `\u{1F4D6} Error stopping adapter "${adapter.name}" \u2014 continuing`
@@ -7121,16 +8228,16 @@ var AdapterRegistry = class {
7121
8228
  };
7122
8229
 
7123
8230
  // src/adapters/generic-pty.ts
7124
- var import_node_path13 = require("path");
8231
+ var import_node_path15 = require("path");
7125
8232
  var import_node_pty = require("@lydell/node-pty");
7126
8233
  var import_strip_ansi = __toESM(require("strip-ansi"), 1);
7127
8234
 
7128
8235
  // src/core/engine/context-detector.ts
7129
- var import_node_child_process12 = require("child_process");
7130
- var import_node_path12 = require("path");
7131
- var import_node_util12 = require("util");
8236
+ var import_node_child_process13 = require("child_process");
8237
+ var import_node_path14 = require("path");
8238
+ var import_node_util13 = require("util");
7132
8239
  var import_pid_cwd3 = __toESM(require("pid-cwd"), 1);
7133
- var execFile12 = (0, import_node_util12.promisify)(import_node_child_process12.execFile);
8240
+ var execFile13 = (0, import_node_util13.promisify)(import_node_child_process13.execFile);
7134
8241
  var TERM_PROGRAM_MAP = {
7135
8242
  Apple_Terminal: "Terminal.app",
7136
8243
  Hyper: "Hyper",
@@ -7173,9 +8280,11 @@ var TOOL_BINARY_MAP = {
7173
8280
  "openhands": "openhands",
7174
8281
  "openclaw": "openclaw",
7175
8282
  "opencode": "opencode",
8283
+ "pi": "pi",
7176
8284
  "qwen-code": "qwen",
7177
8285
  "unknown": "unknown",
7178
- "windsurf": "windsurf"
8286
+ "windsurf": "windsurf",
8287
+ "zed": "zed"
7179
8288
  };
7180
8289
  var ContextDetector = class {
7181
8290
  cache = /* @__PURE__ */ new Map();
@@ -7241,7 +8350,7 @@ var ContextDetector = class {
7241
8350
  return "unknown";
7242
8351
  }
7243
8352
  const nextPid = Number.parseInt(parentPidToken, 10);
7244
- const normalizedProcessName = (0, import_node_path12.basename)(commandText).replace(/\.app$/u, "");
8353
+ const normalizedProcessName = (0, import_node_path14.basename)(commandText).replace(/\.app$/u, "");
7245
8354
  const mappedTerminal = PROCESS_NAME_MAP[normalizedProcessName] ?? PROCESS_NAME_MAP[commandText.trim()];
7246
8355
  if (mappedTerminal) {
7247
8356
  return mappedTerminal;
@@ -7425,7 +8534,7 @@ var ContextDetector = class {
7425
8534
  return cwd ?? void 0;
7426
8535
  }
7427
8536
  async defaultExecCommand(command, args, options = {}) {
7428
- const result = await execFile12(command, [...args], {
8537
+ const result = await execFile13(command, [...args], {
7429
8538
  encoding: "utf8",
7430
8539
  timeout: options.timeoutMs ?? this.commandTimeoutMs,
7431
8540
  maxBuffer: 1024 * 1024
@@ -7505,7 +8614,7 @@ var GenericPTYSession = class {
7505
8614
  {
7506
8615
  cwd: this.cwd,
7507
8616
  pid: pty.pid,
7508
- project: (0, import_node_path13.basename)(this.cwd) || this.cwd,
8617
+ project: (0, import_node_path15.basename)(this.cwd) || this.cwd,
7509
8618
  projectPath: this.cwd,
7510
8619
  raw: {
7511
8620
  args: this.args,
@@ -7516,7 +8625,7 @@ var GenericPTYSession = class {
7516
8625
  toolInput: {
7517
8626
  command: this.commandLine
7518
8627
  },
7519
- toolName: (0, import_node_path13.basename)(this.command) || this.command
8628
+ toolName: (0, import_node_path15.basename)(this.command) || this.command
7520
8629
  }
7521
8630
  );
7522
8631
  await this.emitEvent(
@@ -7526,7 +8635,7 @@ var GenericPTYSession = class {
7526
8635
  {
7527
8636
  cwd: this.cwd,
7528
8637
  pid: pty.pid,
7529
- project: (0, import_node_path13.basename)(this.cwd) || this.cwd,
8638
+ project: (0, import_node_path15.basename)(this.cwd) || this.cwd,
7530
8639
  projectPath: this.cwd,
7531
8640
  raw: {
7532
8641
  args: this.args,
@@ -7676,7 +8785,7 @@ var GenericPTYSession = class {
7676
8785
  await this.emitEvent(pty.pid, sessionId, observation.type, {
7677
8786
  cwd: this.cwd,
7678
8787
  pid: pty.pid,
7679
- project: (0, import_node_path13.basename)(this.cwd) || this.cwd,
8788
+ project: (0, import_node_path15.basename)(this.cwd) || this.cwd,
7680
8789
  projectPath: this.cwd,
7681
8790
  terminal,
7682
8791
  ...observation.data
@@ -7786,7 +8895,7 @@ function analyzeTerminalOutputChunk(input) {
7786
8895
  } : {
7787
8896
  command: input.commandLine
7788
8897
  },
7789
- toolName: activeFile ? "file-edit" : (0, import_node_path13.basename)(input.commandLine) || "shell"
8898
+ toolName: activeFile ? "file-edit" : (0, import_node_path15.basename)(input.commandLine) || "shell"
7790
8899
  },
7791
8900
  fingerprint: createPtyFingerprint("agent.coding", normalizedText, activeFile),
7792
8901
  type: "agent.coding"
@@ -7816,7 +8925,7 @@ function normalizePtyEnvironment(env) {
7816
8925
  );
7817
8926
  }
7818
8927
  function inferWrappedToolName(command, args) {
7819
- const commandBaseName = (0, import_node_path13.basename)(command).toLowerCase();
8928
+ const commandBaseName = (0, import_node_path15.basename)(command).toLowerCase();
7820
8929
  const fullCommandLine = [commandBaseName, ...args].join(" ").toLowerCase();
7821
8930
  const toolMatchers = [
7822
8931
  ["aider", /\baider\b/u],
@@ -7902,7 +9011,9 @@ function createDefaultAdapters(options) {
7902
9011
  new KiloAdapter(options),
7903
9012
  new CodexAdapter(options),
7904
9013
  new OpenClawAdapter(options),
7905
- new OpenCodeAdapter(options)
9014
+ new OpenCodeAdapter(options),
9015
+ new PiAdapter(options),
9016
+ new ZedAdapter(options)
7906
9017
  ];
7907
9018
  }
7908
9019
 
@@ -7950,35 +9061,35 @@ var DEFAULT_CONFIG = {
7950
9061
  };
7951
9062
 
7952
9063
  // src/core/config/loader.ts
7953
- var import_promises11 = require("fs/promises");
9064
+ var import_promises12 = require("fs/promises");
7954
9065
  var import_node_net = require("net");
7955
9066
  var import_node_os2 = require("os");
7956
- var import_node_path14 = require("path");
9067
+ var import_node_path16 = require("path");
7957
9068
  function getAISnitchHomePath(options = {}) {
7958
9069
  if (options.configPath && options.configPath.trim().length > 0) {
7959
- return (0, import_node_path14.dirname)((0, import_node_path14.resolve)(options.configPath));
9070
+ return (0, import_node_path16.dirname)((0, import_node_path16.resolve)(options.configPath));
7960
9071
  }
7961
9072
  const configuredHome = options.env?.AISNITCH_HOME;
7962
9073
  if (configuredHome && configuredHome.trim().length > 0) {
7963
- return (0, import_node_path14.resolve)(configuredHome);
9074
+ return (0, import_node_path16.resolve)(configuredHome);
7964
9075
  }
7965
- return (0, import_node_path14.join)(options.homeDirectory ?? (0, import_node_os2.homedir)(), ".aisnitch");
9076
+ return (0, import_node_path16.join)(options.homeDirectory ?? (0, import_node_os2.homedir)(), ".aisnitch");
7966
9077
  }
7967
9078
  function getConfigPath(options = {}) {
7968
9079
  if (options.configPath && options.configPath.trim().length > 0) {
7969
- return (0, import_node_path14.resolve)(options.configPath);
9080
+ return (0, import_node_path16.resolve)(options.configPath);
7970
9081
  }
7971
- return (0, import_node_path14.join)(getAISnitchHomePath(options), "config.json");
9082
+ return (0, import_node_path16.join)(getAISnitchHomePath(options), "config.json");
7972
9083
  }
7973
9084
  async function ensureConfigDir(options = {}) {
7974
9085
  const directoryPath = getAISnitchHomePath(options);
7975
- await (0, import_promises11.mkdir)(directoryPath, { recursive: true });
9086
+ await (0, import_promises12.mkdir)(directoryPath, { recursive: true });
7976
9087
  return directoryPath;
7977
9088
  }
7978
9089
  async function loadConfig(options = {}) {
7979
9090
  const configPath = getConfigPath(options);
7980
9091
  try {
7981
- const rawConfig = await (0, import_promises11.readFile)(configPath, "utf8");
9092
+ const rawConfig = await (0, import_promises12.readFile)(configPath, "utf8");
7982
9093
  const parsedJson = JSON.parse(rawConfig);
7983
9094
  return ConfigSchema.parse(parsedJson);
7984
9095
  } catch (error) {
@@ -7997,7 +9108,7 @@ async function saveConfig(config, options = {}) {
7997
9108
  const validatedConfig = ConfigSchema.parse(config);
7998
9109
  const configPath = getConfigPath(options);
7999
9110
  await ensureConfigDir(options);
8000
- await (0, import_promises11.writeFile)(
9111
+ await (0, import_promises12.writeFile)(
8001
9112
  configPath,
8002
9113
  `${JSON.stringify(validatedConfig, null, 2)}
8003
9114
  `,
@@ -8241,7 +9352,7 @@ var import_ws = require("ws");
8241
9352
 
8242
9353
  // src/package-info.ts
8243
9354
  var AISNITCH_PACKAGE_NAME = "aisnitch";
8244
- var AISNITCH_VERSION = "0.2.19";
9355
+ var AISNITCH_VERSION = "0.2.21";
8245
9356
  var AISNITCH_DESCRIPTION = "Universal bridge for AI coding tool activity \u2014 capture, normalize, stream.";
8246
9357
  function getPackageScaffoldInfo() {
8247
9358
  return {
@@ -8621,7 +9732,7 @@ var HTTPReceiver = class {
8621
9732
  };
8622
9733
 
8623
9734
  // src/core/engine/uds-server.ts
8624
- var import_promises12 = require("fs/promises");
9735
+ var import_promises13 = require("fs/promises");
8625
9736
  var import_node_fs = require("fs");
8626
9737
  var import_node_net2 = require("net");
8627
9738
  var import_node_readline = require("readline");
@@ -8680,7 +9791,7 @@ var UDSServer = class {
8680
9791
  });
8681
9792
  }
8682
9793
  if (this.socketPath && process.platform !== "win32") {
8683
- await (0, import_promises12.rm)(this.socketPath, { force: true });
9794
+ await (0, import_promises13.rm)(this.socketPath, { force: true });
8684
9795
  }
8685
9796
  this.socketPath = null;
8686
9797
  logger.info("UDS server stopped");
@@ -8747,7 +9858,7 @@ var UDSServer = class {
8747
9858
  return;
8748
9859
  }
8749
9860
  try {
8750
- await (0, import_promises12.access)(socketPath, import_node_fs.constants.F_OK);
9861
+ await (0, import_promises13.access)(socketPath, import_node_fs.constants.F_OK);
8751
9862
  } catch (error) {
8752
9863
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
8753
9864
  return;
@@ -8771,12 +9882,12 @@ var UDSServer = class {
8771
9882
  if (!staleSocket) {
8772
9883
  throw new Error(`Socket path is already in use: ${socketPath}`);
8773
9884
  }
8774
- await (0, import_promises12.rm)(socketPath, { force: true });
9885
+ await (0, import_promises13.rm)(socketPath, { force: true });
8775
9886
  }
8776
9887
  };
8777
9888
 
8778
9889
  // src/core/engine/pipeline.ts
8779
- var import_node_path15 = require("path");
9890
+ var import_node_path17 = require("path");
8780
9891
  var import_zod4 = require("zod");
8781
9892
 
8782
9893
  // src/core/events/cesp.ts
@@ -8816,7 +9927,7 @@ function getSocketPath(aisnitchHomePath) {
8816
9927
  if (process.platform === "win32") {
8817
9928
  return "\\\\.\\pipe\\aisnitch.sock";
8818
9929
  }
8819
- return (0, import_node_path15.join)(aisnitchHomePath, "aisnitch.sock");
9930
+ return (0, import_node_path17.join)(aisnitchHomePath, "aisnitch.sock");
8820
9931
  }
8821
9932
  var Pipeline = class {
8822
9933
  eventBus = new EventBus();
@@ -9021,6 +10132,30 @@ var Pipeline = class {
9021
10132
  getEventBus() {
9022
10133
  return this.eventBus;
9023
10134
  }
10135
+ /**
10136
+ * Returns the adapter registry for graceful shutdown coordination.
10137
+ */
10138
+ getAdapterRegistry() {
10139
+ return this.adapterRegistry ?? void 0;
10140
+ }
10141
+ /**
10142
+ * Returns the HTTP receiver for graceful shutdown coordination.
10143
+ */
10144
+ getHttpReceiver() {
10145
+ return this.httpReceiver;
10146
+ }
10147
+ /**
10148
+ * Returns the UDS server for graceful shutdown coordination.
10149
+ */
10150
+ getUdsServer() {
10151
+ return this.udsServer;
10152
+ }
10153
+ /**
10154
+ * Returns the WebSocket server for graceful shutdown coordination.
10155
+ */
10156
+ getWsServer() {
10157
+ return this.wsServer;
10158
+ }
9024
10159
  getHealthSnapshot() {
9025
10160
  const status = this.getStatus();
9026
10161
  return {
@@ -9101,6 +10236,483 @@ var Pipeline = class {
9101
10236
  }
9102
10237
  };
9103
10238
 
10239
+ // src/core/timeout.ts
10240
+ var DEFAULT_TIMEOUTS = Object.freeze({
10241
+ /**
10242
+ * File read/write operations (JSONL transcripts, config files).
10243
+ * Default: 5 seconds
10244
+ */
10245
+ fileOperation: 5e3,
10246
+ /**
10247
+ * HTTP requests to health endpoint or external APIs.
10248
+ * Default: 30 seconds
10249
+ */
10250
+ httpRequest: 3e4,
10251
+ /**
10252
+ * Process detection commands (`pgrep`, `ps aux`).
10253
+ * Default: 3 seconds
10254
+ */
10255
+ processDetection: 3e3,
10256
+ /**
10257
+ * Adapter startup (file watchers, hook bridges, pollers).
10258
+ * Default: 10 seconds
10259
+ */
10260
+ adapterStartup: 1e4,
10261
+ /**
10262
+ * Adapter shutdown (graceful cleanup, watcher close).
10263
+ * Default: 5 seconds — after this, resources are force-closed
10264
+ */
10265
+ adapterShutdown: 5e3,
10266
+ /**
10267
+ * Daemon graceful shutdown (stop all components in order).
10268
+ * Default: 30 seconds
10269
+ */
10270
+ daemonShutdown: 3e4,
10271
+ /**
10272
+ * WebSocket connection establishment.
10273
+ * Default: 10 seconds
10274
+ */
10275
+ wsConnection: 1e4,
10276
+ /**
10277
+ * Overall pipeline start (all components).
10278
+ * Default: 15 seconds
10279
+ */
10280
+ pipelineStartup: 15e3
10281
+ });
10282
+ function withTimeout(promise, timeoutMs, context) {
10283
+ if (timeoutMs <= 0) {
10284
+ throw new TimeoutError(
10285
+ `Invalid timeout value: ${timeoutMs}ms (must be > 0)`,
10286
+ "TIMEOUT_INVALID_VALUE",
10287
+ { context, timeoutMs }
10288
+ );
10289
+ }
10290
+ return Promise.race([
10291
+ promise,
10292
+ new Promise((_, reject) => {
10293
+ const timeoutId = setTimeout(() => {
10294
+ reject(
10295
+ new TimeoutError(
10296
+ `Operation exceeded ${timeoutMs}ms deadline`,
10297
+ "TIMEOUT_EXCEEDED",
10298
+ { context, timeoutMs }
10299
+ )
10300
+ );
10301
+ }, timeoutMs);
10302
+ timeoutId.unref();
10303
+ })
10304
+ ]);
10305
+ }
10306
+ async function timeoutWarning(promise, timeoutMs, context) {
10307
+ try {
10308
+ return await withTimeout(promise, timeoutMs, context);
10309
+ } catch (error) {
10310
+ if (error instanceof TimeoutError) {
10311
+ logger.warn(
10312
+ { context: error.context, timeoutMs: error.context },
10313
+ `Best-effort operation timed out after ${timeoutMs}ms`
10314
+ );
10315
+ return await promise;
10316
+ }
10317
+ throw error;
10318
+ }
10319
+ }
10320
+ function getTimeout(name) {
10321
+ return DEFAULT_TIMEOUTS[name];
10322
+ }
10323
+ function isTimeoutError(error) {
10324
+ return error instanceof TimeoutError;
10325
+ }
10326
+
10327
+ // src/core/graceful-shutdown.ts
10328
+ async function withShutdownTimeout(fn, timeoutMs, component) {
10329
+ if (timeoutMs <= 0) {
10330
+ await fn();
10331
+ return;
10332
+ }
10333
+ const timeoutPromise = new Promise((resolve2) => {
10334
+ setTimeout(() => {
10335
+ resolve2("timed_out");
10336
+ }, timeoutMs).unref();
10337
+ });
10338
+ const result = await Promise.race([
10339
+ fn().then(() => "completed"),
10340
+ timeoutPromise
10341
+ ]);
10342
+ if (result === "timed_out") {
10343
+ logger.warn(
10344
+ { component, timeoutMs },
10345
+ `Graceful shutdown exceeded ${timeoutMs}ms timeout \u2014 forcing through`
10346
+ );
10347
+ }
10348
+ }
10349
+ async function shutdownInOrder(components, timeouts, label) {
10350
+ const getTimeout2 = (key) => {
10351
+ return timeouts[key] ?? DEFAULT_TIMEOUTS.daemonShutdown;
10352
+ };
10353
+ const stopSafely = async (key, fn) => {
10354
+ const timeoutMs = getTimeout2(key);
10355
+ try {
10356
+ await withShutdownTimeout(fn, timeoutMs, `${label}.${key}`);
10357
+ } catch (error) {
10358
+ logger.warn(
10359
+ { error, key, label },
10360
+ `Error during shutdown of ${key} \u2014 continuing with remaining components`
10361
+ );
10362
+ }
10363
+ };
10364
+ if (components.cleanupFns) {
10365
+ for (const cleanupFn of components.cleanupFns) {
10366
+ try {
10367
+ await withShutdownTimeout(
10368
+ async () => {
10369
+ const result = cleanupFn();
10370
+ if (result instanceof Promise) {
10371
+ await result;
10372
+ }
10373
+ },
10374
+ 1e3,
10375
+ `${label}.cleanup`
10376
+ );
10377
+ } catch (error) {
10378
+ logger.warn({ error, label }, "Cleanup function failed");
10379
+ }
10380
+ }
10381
+ }
10382
+ if (components.eventBus) {
10383
+ components.eventBus.unsubscribeAll();
10384
+ }
10385
+ await stopSafely("wsServer", () => components.wsServer.stop());
10386
+ await stopSafely("udsServer", () => components.udsServer.stop());
10387
+ await stopSafely("httpReceiver", () => components.httpReceiver.stop());
10388
+ if (components.adapterRegistry) {
10389
+ await stopSafely("adapterRegistry", () => components.adapterRegistry.stopAll());
10390
+ }
10391
+ }
10392
+ var GracefulShutdownManager = class {
10393
+ /**
10394
+ * Creates a new shutdown manager.
10395
+ *
10396
+ * @param options - Configuration options
10397
+ * @param options.onShutdown - Async function called when shutdown is triggered
10398
+ * @param options.exitCode - Exit code to use (default: 0 for graceful, 1 for errors)
10399
+ * @param options.exitDelayMs - Delay before `process.exit()` (default: 100ms for flush)
10400
+ */
10401
+ constructor(options) {
10402
+ this.options = options;
10403
+ }
10404
+ shuttingDown = false;
10405
+ pendingHandlers = /* @__PURE__ */ new Set();
10406
+ /**
10407
+ * Synchronous handler function suitable for `process.on()`.
10408
+ *
10409
+ * Multiple calls are safe — only the first call executes `onShutdown`.
10410
+ * Subsequent calls queue to the internal pending set and run after the
10411
+ * first shutdown completes.
10412
+ */
10413
+ get handler() {
10414
+ return (signal) => {
10415
+ if (!this.shuttingDown) {
10416
+ this.shuttingDown = true;
10417
+ void this.runShutdown(signal);
10418
+ } else {
10419
+ this.pendingHandlers.add(() => {
10420
+ void this.runShutdown(signal);
10421
+ });
10422
+ }
10423
+ };
10424
+ }
10425
+ /**
10426
+ * Manually triggers shutdown from async code (e.g., TUI quit button).
10427
+ *
10428
+ * @param signal - Signal name (for logging)
10429
+ */
10430
+ shutdown(signal = "manual") {
10431
+ this.handler(signal);
10432
+ }
10433
+ /**
10434
+ * Returns whether shutdown is currently in progress.
10435
+ */
10436
+ isShuttingDown() {
10437
+ return this.shuttingDown;
10438
+ }
10439
+ async runShutdown(signal) {
10440
+ const exitCode = this.options.exitCode ?? (signal === "uncaughtException" || signal === "unhandledRejection" ? 1 : 0);
10441
+ const exitDelayMs = this.options.exitDelayMs ?? 100;
10442
+ try {
10443
+ await this.options.onShutdown(signal);
10444
+ } catch (error) {
10445
+ logger.error(
10446
+ { error, signal },
10447
+ "Error during graceful shutdown \u2014 forcing exit"
10448
+ );
10449
+ } finally {
10450
+ await new Promise((resolve2) => {
10451
+ setTimeout(resolve2, exitDelayMs).unref();
10452
+ });
10453
+ for (const pendingHandler of this.pendingHandlers) {
10454
+ pendingHandler();
10455
+ }
10456
+ process.exit(exitCode);
10457
+ }
10458
+ }
10459
+ };
10460
+ async function withOverallShutdownTimeout(shutdownPromise, timeoutMs, label) {
10461
+ try {
10462
+ await withTimeout(shutdownPromise, timeoutMs, `${label}-overall-shutdown`);
10463
+ } catch (error) {
10464
+ if (isTimeoutError(error)) {
10465
+ logger.error(
10466
+ { timeoutMs, label },
10467
+ `Overall shutdown timeout exceeded \u2014 forcing process exit`
10468
+ );
10469
+ }
10470
+ process.exit(1);
10471
+ }
10472
+ }
10473
+
10474
+ // src/core/result.ts
10475
+ function isOk(result) {
10476
+ return result.success === true;
10477
+ }
10478
+ function isErr(result) {
10479
+ return result.success === false;
10480
+ }
10481
+ function ok(value) {
10482
+ return Object.freeze({ success: true, value });
10483
+ }
10484
+ function err(error) {
10485
+ return Object.freeze({ success: false, error });
10486
+ }
10487
+ function mapOk(result, fn) {
10488
+ if (!result.success) {
10489
+ return result;
10490
+ }
10491
+ return ok(fn(result.value));
10492
+ }
10493
+ function mapErr(result, fn) {
10494
+ if (result.success) {
10495
+ return result;
10496
+ }
10497
+ return err(fn(result.error));
10498
+ }
10499
+ async function flatMap(result, fn) {
10500
+ if (!result.success) {
10501
+ return result;
10502
+ }
10503
+ const mapped = await fn(result.value);
10504
+ if (!mapped.success) {
10505
+ return mapped;
10506
+ }
10507
+ return ok(mapped.value);
10508
+ }
10509
+ async function fromPromise(promise, mapError) {
10510
+ try {
10511
+ const value = await promise;
10512
+ return ok(value);
10513
+ } catch (reason) {
10514
+ return err(mapError(reason));
10515
+ }
10516
+ }
10517
+ function fromSync(fn, mapError) {
10518
+ try {
10519
+ return ok(fn());
10520
+ } catch (reason) {
10521
+ return err(mapError(reason));
10522
+ }
10523
+ }
10524
+
10525
+ // src/core/retry.ts
10526
+ var DefaultRetryOptions = {
10527
+ attempts: 3,
10528
+ backoff: 2,
10529
+ context: "unknown",
10530
+ delayMs: 500,
10531
+ jitter: true,
10532
+ maxTotalDelayMs: 3e4,
10533
+ shouldRetry: isRetryableError
10534
+ };
10535
+ function sleep(ms) {
10536
+ return new Promise((resolve2) => {
10537
+ setTimeout(resolve2, ms).unref();
10538
+ });
10539
+ }
10540
+ function computeDelay(attempt, baseDelayMs, backoff, jitter) {
10541
+ const exponentialDelay = baseDelayMs * Math.pow(backoff, attempt - 1);
10542
+ if (!jitter) {
10543
+ return exponentialDelay;
10544
+ }
10545
+ const jitterFactor = 0.75 + Math.random() * 0.5;
10546
+ return Math.round(exponentialDelay * jitterFactor);
10547
+ }
10548
+ async function withRetry(fn, options) {
10549
+ const {
10550
+ attempts = DefaultRetryOptions.attempts,
10551
+ backoff = DefaultRetryOptions.backoff,
10552
+ delayMs = DefaultRetryOptions.delayMs,
10553
+ maxTotalDelayMs = DefaultRetryOptions.maxTotalDelayMs,
10554
+ jitter = DefaultRetryOptions.jitter,
10555
+ shouldRetry = DefaultRetryOptions.shouldRetry
10556
+ } = options;
10557
+ let lastError;
10558
+ let totalDelayMs = 0;
10559
+ const shouldRetryWithDefault = shouldRetry ?? DefaultRetryOptions.shouldRetry;
10560
+ for (let attempt = 1; attempt <= attempts; attempt++) {
10561
+ try {
10562
+ return await fn();
10563
+ } catch (error) {
10564
+ lastError = error;
10565
+ const retryable = shouldRetryWithDefault(error);
10566
+ const attemptsRemaining = attempt < attempts;
10567
+ if (!retryable || !attemptsRemaining) {
10568
+ if (!retryable) {
10569
+ logger.debug(
10570
+ { attempt, context: options.context, error },
10571
+ "Non-retryable error \u2014 giving up immediately"
10572
+ );
10573
+ } else {
10574
+ logger.error(
10575
+ { attempt, attempts, context: options.context, error },
10576
+ "All retry attempts exhausted"
10577
+ );
10578
+ }
10579
+ throw error;
10580
+ }
10581
+ const delay = computeDelay(attempt, delayMs, backoff, jitter ?? false);
10582
+ totalDelayMs += delay;
10583
+ if (totalDelayMs > maxTotalDelayMs) {
10584
+ logger.warn(
10585
+ { attempt, delay, totalDelayMs, maxTotalDelayMs, context: options.context },
10586
+ "Retry max total delay exceeded \u2014 giving up"
10587
+ );
10588
+ throw lastError;
10589
+ }
10590
+ logger.debug(
10591
+ { attempt, attempts, delay, nextDelayMs: delay, context: options.context },
10592
+ `Operation failed \u2014 retrying in ${delay}ms`
10593
+ );
10594
+ await sleep(delay);
10595
+ }
10596
+ }
10597
+ throw lastError;
10598
+ }
10599
+ function fireAndForgetRetry(fn, options) {
10600
+ void withRetry(fn, {
10601
+ ...options,
10602
+ attempts: options.attempts ?? 2
10603
+ }).catch((error) => {
10604
+ logger.warn(
10605
+ { error, context: options.context },
10606
+ "Fire-and-forget retry also failed \u2014 giving up silently"
10607
+ );
10608
+ });
10609
+ }
10610
+ function withRetryOn(fn, options) {
10611
+ return ((...args) => withRetry(() => fn(...args), options));
10612
+ }
10613
+
10614
+ // src/core/safety.ts
10615
+ var MAX_PORT = 65535;
10616
+ var MIN_PORT = 1;
10617
+ var MAX_PATH_LENGTH = 4096;
10618
+ var MAX_GENERIC_STRING_LENGTH = 1e4;
10619
+ var MAX_LABEL_LENGTH = 255;
10620
+ function getString11(record, key) {
10621
+ const value = record[key];
10622
+ if (typeof value !== "string") {
10623
+ return void 0;
10624
+ }
10625
+ const trimmed = value.trim();
10626
+ return trimmed.length > 0 ? trimmed : void 0;
10627
+ }
10628
+ function getStringWithMaxLength(record, key, maxLength) {
10629
+ const value = getString11(record, key);
10630
+ if (value === void 0) {
10631
+ return void 0;
10632
+ }
10633
+ return value.length > maxLength ? value.slice(0, maxLength) : value;
10634
+ }
10635
+ function getNumber9(record, key) {
10636
+ const value = record[key];
10637
+ if (typeof value !== "number" || !Number.isFinite(value)) {
10638
+ return void 0;
10639
+ }
10640
+ return value;
10641
+ }
10642
+ function getSafeInteger(record, key, options = {}) {
10643
+ const value = getNumber9(record, key);
10644
+ if (value === void 0) {
10645
+ return void 0;
10646
+ }
10647
+ if (!Number.isInteger(value)) {
10648
+ return void 0;
10649
+ }
10650
+ if (options.min !== void 0 && value < options.min) {
10651
+ return void 0;
10652
+ }
10653
+ if (options.max !== void 0 && value > options.max) {
10654
+ return void 0;
10655
+ }
10656
+ return value;
10657
+ }
10658
+ function getPositiveNumber(record, key) {
10659
+ const value = getNumber9(record, key);
10660
+ return value !== void 0 && value > 0 ? value : void 0;
10661
+ }
10662
+ function getBoolean2(record, key) {
10663
+ const value = record[key];
10664
+ if (typeof value === "boolean") {
10665
+ return value;
10666
+ }
10667
+ if (typeof value === "string") {
10668
+ const lower = value.toLowerCase();
10669
+ if (lower === "true" || lower === "1") {
10670
+ return true;
10671
+ }
10672
+ if (lower === "false" || lower === "0") {
10673
+ return false;
10674
+ }
10675
+ }
10676
+ return void 0;
10677
+ }
10678
+ function getArray(record, key) {
10679
+ const value = record[key];
10680
+ return Array.isArray(value) ? value : void 0;
10681
+ }
10682
+ function getObject(record, key) {
10683
+ const value = record[key];
10684
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
10685
+ return void 0;
10686
+ }
10687
+ return value;
10688
+ }
10689
+ function isValidPort(port) {
10690
+ return port !== void 0 && Number.isInteger(port) && port >= MIN_PORT && port <= MAX_PORT;
10691
+ }
10692
+ function isValidPathLength(path) {
10693
+ return path !== void 0 && path.length > 0 && path.length <= MAX_PATH_LENGTH;
10694
+ }
10695
+ function isValidStringLength(value, maxLength) {
10696
+ return value !== void 0 && value.length <= maxLength;
10697
+ }
10698
+ function isRecord11(value) {
10699
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
10700
+ return false;
10701
+ }
10702
+ const proto = Object.prototype.toString.call(value);
10703
+ return proto === "[object Object]";
10704
+ }
10705
+ function isNotNull(value) {
10706
+ return value != null;
10707
+ }
10708
+ function getPort(record, key) {
10709
+ const value = getSafeInteger(record, key, { min: MIN_PORT, max: MAX_PORT });
10710
+ return value;
10711
+ }
10712
+ function getSeqnum(record, key) {
10713
+ return getSafeInteger(record, key, { min: 1 });
10714
+ }
10715
+
9104
10716
  // src/tui/index.tsx
9105
10717
  var import_ink13 = require("ink");
9106
10718
  var import_fullscreen_ink = require("fullscreen-ink");
@@ -9162,7 +10774,7 @@ function getEventDetailSegments(event) {
9162
10774
  break;
9163
10775
  case "agent.asking_user":
9164
10776
  segments.push(
9165
- getString11(raw, "notification_type") ?? getString11(raw, "notificationType") ?? getString11(raw, "type")
10777
+ getString12(raw, "notification_type") ?? getString12(raw, "notificationType") ?? getString12(raw, "type")
9166
10778
  );
9167
10779
  segments.push(event.data.errorMessage ?? extractLooseString3(raw, [
9168
10780
  "message",
@@ -9236,10 +10848,10 @@ function extractContentPart(raw, partType, valueKey) {
9236
10848
  }
9237
10849
  for (const part of content) {
9238
10850
  const record = getRecord10(part);
9239
- if (!record || getString11(record, "type") !== partType) {
10851
+ if (!record || getString12(record, "type") !== partType) {
9240
10852
  continue;
9241
10853
  }
9242
- const value = getString11(record, valueKey);
10854
+ const value = getString12(record, valueKey);
9243
10855
  if (value) {
9244
10856
  return value;
9245
10857
  }
@@ -9251,12 +10863,12 @@ function extractLooseString3(raw, keys) {
9251
10863
  return void 0;
9252
10864
  }
9253
10865
  for (const key of keys) {
9254
- const directValue = getString11(raw, key);
10866
+ const directValue = getString12(raw, key);
9255
10867
  if (directValue) {
9256
10868
  return directValue;
9257
10869
  }
9258
10870
  const nestedRecord = getRecord10(raw[key]);
9259
- const nestedValue = getString11(nestedRecord, "text") ?? getString11(nestedRecord, "message") ?? getString11(nestedRecord, "content");
10871
+ const nestedValue = getString12(nestedRecord, "text") ?? getString12(nestedRecord, "message") ?? getString12(nestedRecord, "content");
9260
10872
  if (nestedValue) {
9261
10873
  return nestedValue;
9262
10874
  }
@@ -9270,13 +10882,13 @@ function truncateSegment(value) {
9270
10882
  }
9271
10883
  return `${normalized.slice(0, DETAIL_SEGMENT_LIMIT - 1)}\u2026`;
9272
10884
  }
9273
- function isRecord11(value) {
10885
+ function isRecord12(value) {
9274
10886
  return typeof value === "object" && value !== null && !Array.isArray(value);
9275
10887
  }
9276
10888
  function getRecord10(value) {
9277
- return isRecord11(value) ? value : void 0;
10889
+ return isRecord12(value) ? value : void 0;
9278
10890
  }
9279
- function getString11(payload, key) {
10891
+ function getString12(payload, key) {
9280
10892
  if (!payload) {
9281
10893
  return void 0;
9282
10894
  }
@@ -9304,9 +10916,11 @@ var TOOL_COLORS = {
9304
10916
  "openhands": "#facc15",
9305
10917
  "openclaw": "#ef4444",
9306
10918
  "opencode": "#10b981",
10919
+ "pi": "#1db954",
9307
10920
  "qwen-code": "#22c55e",
9308
10921
  "unknown": "#94a3b8",
9309
- "windsurf": "#a855f7"
10922
+ "windsurf": "#a855f7",
10923
+ "zed": "#e85d04"
9310
10924
  };
9311
10925
  var EVENT_COLORS = {
9312
10926
  "agent.asking_user": "#ef4444",
@@ -11156,10 +12770,12 @@ async function renderManagedTui(options) {
11156
12770
  AISNITCH_EVENT_TYPES,
11157
12771
  AISNITCH_PACKAGE_NAME,
11158
12772
  AISNITCH_VERSION,
12773
+ AISnitchError,
11159
12774
  AISnitchEventSchema,
11160
12775
  AISnitchEventTypeSchema,
11161
12776
  AUTO_UPDATE_MANAGERS,
11162
12777
  AdapterConfigSchema,
12778
+ AdapterError,
11163
12779
  AdapterRegistry,
11164
12780
  AiderAdapter,
11165
12781
  App,
@@ -11168,6 +12784,8 @@ async function renderManagedTui(options) {
11168
12784
  CESPCategorySchema,
11169
12785
  CESP_CATEGORIES,
11170
12786
  CESP_MAP,
12787
+ CircuitBreaker,
12788
+ CircuitOpenError,
11171
12789
  ClaudeCodeAdapter,
11172
12790
  CodexAdapter,
11173
12791
  ConfigSchema,
@@ -11175,8 +12793,10 @@ async function renderManagedTui(options) {
11175
12793
  CopilotCLIAdapter,
11176
12794
  CursorAdapter,
11177
12795
  DEFAULT_CONFIG,
12796
+ DEFAULT_TIMEOUTS,
11178
12797
  DEFAULT_TUI_FILTERS,
11179
12798
  DEFAULT_VISIBLE_EVENT_COUNT,
12799
+ DefaultRetryOptions,
11180
12800
  DevinAdapter,
11181
12801
  ERROR_TYPES,
11182
12802
  EVENT_COLORS,
@@ -11188,33 +12808,51 @@ async function renderManagedTui(options) {
11188
12808
  EventLine,
11189
12809
  EventStream,
11190
12810
  FilterBar,
12811
+ FinalMessageSchema,
11191
12812
  GeminiCLIAdapter,
11192
12813
  GenericPTYSession,
11193
12814
  GlobalBadge,
11194
12815
  GooseAdapter,
12816
+ GracefulShutdownManager,
11195
12817
  HTTPReceiver,
11196
12818
  Header,
11197
12819
  HelpOverlay,
11198
12820
  KiloAdapter,
11199
12821
  LOG_LEVELS,
12822
+ MAX_GENERIC_STRING_LENGTH,
12823
+ MAX_LABEL_LENGTH,
12824
+ MAX_PATH_LENGTH,
12825
+ MAX_PORT,
12826
+ MIN_PORT,
11200
12827
  ManagedDaemonApp,
12828
+ MessageContentSchema,
12829
+ NetworkError,
11201
12830
  OpenClawAdapter,
11202
12831
  OpenCodeAdapter,
11203
12832
  Panel,
11204
12833
  PanelStack,
12834
+ PiAdapter,
11205
12835
  Pipeline,
12836
+ PipelineError,
11206
12837
  RingBuffer,
11207
12838
  SESSION_STALE_AFTER_MS,
12839
+ SHARED_BREAKERS,
11208
12840
  SessionPanel,
11209
12841
  StatusBar,
11210
12842
  TOOL_COLORS,
11211
12843
  TOOL_NAMES,
11212
12844
  TUI_THEME,
11213
12845
  TUI_VIEW_MODES,
12846
+ ThinkingContentSchema,
12847
+ TimeoutError,
12848
+ ToolCallNameSchema,
11214
12849
  ToolInputSchema,
11215
12850
  ToolNameSchema,
12851
+ ToolResultSchema,
11216
12852
  UDSServer,
12853
+ ValidationError,
11217
12854
  WSServer,
12855
+ ZedAdapter,
11218
12856
  analyzeTerminalOutputChunk,
11219
12857
  appendEventToStream,
11220
12858
  applyEventFilters,
@@ -11228,6 +12866,9 @@ async function renderManagedTui(options) {
11228
12866
  deriveGlobalActivityStatus,
11229
12867
  deriveSessions,
11230
12868
  ensureConfigDir,
12869
+ err,
12870
+ fireAndForgetRetry,
12871
+ flatMap,
11231
12872
  formatEventDetail,
11232
12873
  formatEventLine,
11233
12874
  formatEventTime,
@@ -11235,16 +12876,42 @@ async function renderManagedTui(options) {
11235
12876
  formatSessionLabelFromEvent,
11236
12877
  formatSessionShortId,
11237
12878
  formatWelcomeLine,
12879
+ fromPromise,
12880
+ fromSync,
11238
12881
  getAISnitchHomePath,
12882
+ getArray,
12883
+ getBoolean,
11239
12884
  getCESPCategory,
11240
12885
  getConfigPath,
12886
+ getNumber,
12887
+ getObject,
11241
12888
  getPackageScaffoldInfo,
11242
12889
  getPendingFrozenEventCount,
12890
+ getPort,
12891
+ getPositiveNumber,
12892
+ getSafeInteger,
12893
+ getSeqnum,
11243
12894
  getSocketPath,
12895
+ getString,
12896
+ getStringWithMaxLength,
12897
+ getTimeout,
11244
12898
  getVisibleEventWindow,
12899
+ isAISnitchError,
12900
+ isErr,
11245
12901
  isGenericSessionId,
12902
+ isNotNull,
12903
+ isOk,
12904
+ isRecord,
12905
+ isRetryableError,
12906
+ isTimeoutError,
12907
+ isValidPathLength,
12908
+ isValidPort,
12909
+ isValidStringLength,
11246
12910
  loadConfig,
11247
12911
  logger,
12912
+ mapErr,
12913
+ mapOk,
12914
+ ok,
11248
12915
  parseAiderHistoryMarkdown,
11249
12916
  renderAttachedTui,
11250
12917
  renderForegroundTui,
@@ -11253,8 +12920,16 @@ async function renderManagedTui(options) {
11253
12920
  resolveSessionId,
11254
12921
  saveConfig,
11255
12922
  setLoggerLevel,
12923
+ shutdownInOrder,
12924
+ sleep,
12925
+ timeoutWarning,
11256
12926
  useEventStream,
11257
12927
  useKeyBinds,
11258
- useSessions
12928
+ useSessions,
12929
+ withOverallShutdownTimeout,
12930
+ withRetry,
12931
+ withRetryOn,
12932
+ withShutdownTimeout,
12933
+ withTimeout
11259
12934
  });
11260
12935
  //# sourceMappingURL=index.cjs.map