@animalabs/agent-framework 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/src/framework.d.ts +8 -0
  2. package/dist/src/framework.d.ts.map +1 -1
  3. package/dist/src/framework.js +42 -2
  4. package/dist/src/framework.js.map +1 -1
  5. package/dist/src/index.d.ts +1 -0
  6. package/dist/src/index.d.ts.map +1 -1
  7. package/dist/src/index.js +2 -0
  8. package/dist/src/index.js.map +1 -1
  9. package/dist/src/mcpl/channel-registry.d.ts +5 -2
  10. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  11. package/dist/src/mcpl/channel-registry.js +61 -5
  12. package/dist/src/mcpl/channel-registry.js.map +1 -1
  13. package/dist/src/mcpl/server-connection.d.ts +17 -2
  14. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  15. package/dist/src/mcpl/server-connection.js +66 -3
  16. package/dist/src/mcpl/server-connection.js.map +1 -1
  17. package/dist/src/mcpl/tool-policy.d.ts +24 -0
  18. package/dist/src/mcpl/tool-policy.d.ts.map +1 -0
  19. package/dist/src/mcpl/tool-policy.js +46 -0
  20. package/dist/src/mcpl/tool-policy.js.map +1 -0
  21. package/dist/src/mcpl/types.d.ts +16 -0
  22. package/dist/src/mcpl/types.d.ts.map +1 -1
  23. package/dist/src/mcpl/types.js.map +1 -1
  24. package/dist/src/modules/workspace/index.d.ts +7 -0
  25. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  26. package/dist/src/modules/workspace/index.js +81 -1
  27. package/dist/src/modules/workspace/index.js.map +1 -1
  28. package/dist/src/modules/workspace/types.d.ts +11 -0
  29. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  30. package/dist/src/modules/workspace/types.js.map +1 -1
  31. package/dist/src/modules/workspace/watcher.d.ts +13 -1
  32. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  33. package/dist/src/modules/workspace/watcher.js +27 -1
  34. package/dist/src/modules/workspace/watcher.js.map +1 -1
  35. package/dist/src/types/trace.d.ts +4 -0
  36. package/dist/src/types/trace.d.ts.map +1 -1
  37. package/dist/test/channel-registry-typing.test.d.ts +2 -0
  38. package/dist/test/channel-registry-typing.test.d.ts.map +1 -0
  39. package/dist/test/channel-registry-typing.test.js +82 -0
  40. package/dist/test/channel-registry-typing.test.js.map +1 -0
  41. package/dist/test/tool-policy.test.d.ts +2 -0
  42. package/dist/test/tool-policy.test.d.ts.map +1 -0
  43. package/dist/test/tool-policy.test.js +51 -0
  44. package/dist/test/tool-policy.test.js.map +1 -0
  45. package/dist/test/workspace-watcher.test.js +28 -1
  46. package/dist/test/workspace-watcher.test.js.map +1 -1
  47. package/dist/tsconfig.tsbuildinfo +1 -1
  48. package/package.json +1 -1
  49. package/src/framework.ts +44 -2
  50. package/src/index.ts +3 -0
  51. package/src/mcpl/channel-registry.ts +75 -7
  52. package/src/mcpl/server-connection.ts +78 -3
  53. package/src/mcpl/tool-policy.ts +52 -0
  54. package/src/mcpl/types.ts +18 -0
  55. package/src/modules/workspace/index.ts +88 -4
  56. package/src/modules/workspace/types.ts +11 -0
  57. package/src/modules/workspace/watcher.ts +40 -0
  58. package/src/types/trace.ts +7 -0
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  import { watch, type FSWatcher } from 'chokidar';
9
+ import { mkdirSync } from 'node:fs';
9
10
  import { type MountConfig } from './types.js';
10
11
 
11
12
  export type FsOp = 'created' | 'modified' | 'deleted';
@@ -19,6 +20,18 @@ export interface WatcherEvents {
19
20
  onChange(changes: FsChange[]): void;
20
21
  }
21
22
 
23
+ /**
24
+ * Optional lifecycle callbacks. Without these, chokidar's `ready` and `error`
25
+ * events are silently dropped — which is how a failed attach can look
26
+ * identical to an empty directory in the recorded state.
27
+ */
28
+ export interface WatcherLifecycle {
29
+ /** Fires once, when chokidar completes its initial scan. */
30
+ onReady?: () => void;
31
+ /** Fires on any chokidar-reported error (ENOENT, EACCES, platform faults). */
32
+ onError?: (err: Error) => void;
33
+ }
34
+
22
35
  /**
23
36
  * Manages filesystem watching for a single mount.
24
37
  * Handles debouncing, ignore patterns, and write suppression.
@@ -34,14 +47,17 @@ export class MountWatcher {
34
47
  private readonly debounceMs: number;
35
48
  private readonly config: MountConfig;
36
49
  private readonly onChangeCallback: (changes: FsChange[]) => void;
50
+ private readonly lifecycle: WatcherLifecycle;
37
51
 
38
52
  constructor(
39
53
  config: MountConfig,
40
54
  onChange: (changes: FsChange[]) => void,
55
+ lifecycle: WatcherLifecycle = {},
41
56
  ) {
42
57
  this.config = config;
43
58
  this.debounceMs = config.watchDebounceMs ?? 300;
44
59
  this.onChangeCallback = onChange;
60
+ this.lifecycle = lifecycle;
45
61
  }
46
62
 
47
63
  /**
@@ -50,6 +66,21 @@ export class MountWatcher {
50
66
  start(): void {
51
67
  if (this.watcher) return;
52
68
 
69
+ // Read-write mounts: ensure the path exists before chokidar attaches.
70
+ // chokidar 4's fs.watch-based backend silently fails to fire events when
71
+ // the watched path OR any of its parent directories don't exist at
72
+ // subscribe time (see case C in the WSL/Linux repro). `ready` still fires,
73
+ // so the failure is indistinguishable from an empty directory without
74
+ // this defensive mkdir. Read-only mounts are left alone — creating
75
+ // directories a user asked us only to read would be surprising.
76
+ if (this.config.mode === 'read-write') {
77
+ try {
78
+ mkdirSync(this.config.path, { recursive: true });
79
+ } catch (err) {
80
+ this.lifecycle.onError?.(err instanceof Error ? err : new Error(String(err)));
81
+ }
82
+ }
83
+
53
84
  const ignored = this.config.ignore ?? [];
54
85
 
55
86
  this.watcher = watch(this.config.path, {
@@ -79,6 +110,15 @@ export class MountWatcher {
79
110
  this.watcher.on('add', handleEvent('created'));
80
111
  this.watcher.on('change', handleEvent('modified'));
81
112
  this.watcher.on('unlink', handleEvent('deleted'));
113
+
114
+ if (this.lifecycle.onReady) {
115
+ this.watcher.once('ready', this.lifecycle.onReady);
116
+ }
117
+ if (this.lifecycle.onError) {
118
+ this.watcher.on('error', (err) => {
119
+ this.lifecycle.onError?.(err instanceof Error ? err : new Error(String(err)));
120
+ });
121
+ }
82
122
  }
83
123
 
84
124
  /**
@@ -206,6 +206,13 @@ export type TraceEvent =
206
206
  agentName: string;
207
207
  fromBranch: string;
208
208
  toBranch: string;
209
+ })
210
+
211
+ // MCPL subprocess stderr (one trace per line, for receipts when things break)
212
+ | (TraceEventBase & {
213
+ type: 'mcpl:server-stderr';
214
+ serverId: string;
215
+ line: string;
209
216
  });
210
217
 
211
218
  /**