@animalabs/agent-framework 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/framework.d.ts +13 -0
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +133 -10
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +5 -0
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +104 -6
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/gate/types.d.ts +31 -0
- package/dist/src/gate/types.d.ts.map +1 -1
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +16 -2
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +101 -6
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/push-handler.js +1 -1
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +17 -2
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +66 -3
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/tool-policy.d.ts +24 -0
- package/dist/src/mcpl/tool-policy.d.ts.map +1 -0
- package/dist/src/mcpl/tool-policy.js +46 -0
- package/dist/src/mcpl/tool-policy.js.map +1 -0
- package/dist/src/mcpl/types.d.ts +31 -0
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +43 -1
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +246 -32
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/sync.d.ts +7 -2
- package/dist/src/modules/workspace/sync.d.ts.map +1 -1
- package/dist/src/modules/workspace/sync.js +2 -2
- package/dist/src/modules/workspace/sync.js.map +1 -1
- package/dist/src/modules/workspace/types.d.ts +55 -3
- package/dist/src/modules/workspace/types.d.ts.map +1 -1
- package/dist/src/modules/workspace/types.js +8 -1
- package/dist/src/modules/workspace/types.js.map +1 -1
- package/dist/src/modules/workspace/watcher.d.ts +40 -3
- package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
- package/dist/src/modules/workspace/watcher.js +80 -13
- package/dist/src/modules/workspace/watcher.js.map +1 -1
- package/dist/src/types/trace.d.ts +20 -0
- package/dist/src/types/trace.d.ts.map +1 -1
- package/dist/src/usage/index.d.ts +3 -0
- package/dist/src/usage/index.d.ts.map +1 -0
- package/dist/src/usage/index.js +2 -0
- package/dist/src/usage/index.js.map +1 -0
- package/dist/src/usage/types.d.ts +28 -0
- package/dist/src/usage/types.d.ts.map +1 -0
- package/dist/src/usage/types.js +2 -0
- package/dist/src/usage/types.js.map +1 -0
- package/dist/src/usage/usage-tracker.d.ts +33 -0
- package/dist/src/usage/usage-tracker.d.ts.map +1 -0
- package/dist/src/usage/usage-tracker.js +115 -0
- package/dist/src/usage/usage-tracker.js.map +1 -0
- package/dist/test/channel-registry-typing.test.d.ts +2 -0
- package/dist/test/channel-registry-typing.test.d.ts.map +1 -0
- package/dist/test/channel-registry-typing.test.js +82 -0
- package/dist/test/channel-registry-typing.test.js.map +1 -0
- package/dist/test/event-gate.test.js +135 -16
- package/dist/test/event-gate.test.js.map +1 -1
- package/dist/test/mcpl-gate-roundtrip.test.d.ts +2 -0
- package/dist/test/mcpl-gate-roundtrip.test.d.ts.map +1 -0
- package/dist/test/mcpl-gate-roundtrip.test.js +140 -0
- package/dist/test/mcpl-gate-roundtrip.test.js.map +1 -0
- package/dist/test/tool-policy.test.d.ts +2 -0
- package/dist/test/tool-policy.test.d.ts.map +1 -0
- package/dist/test/tool-policy.test.js +51 -0
- package/dist/test/tool-policy.test.js.map +1 -0
- package/dist/test/usage-tracker.test.d.ts +2 -0
- package/dist/test/usage-tracker.test.d.ts.map +1 -0
- package/dist/test/usage-tracker.test.js +129 -0
- package/dist/test/usage-tracker.test.js.map +1 -0
- package/dist/test/workspace-watcher.test.d.ts +2 -0
- package/dist/test/workspace-watcher.test.d.ts.map +1 -0
- package/dist/test/workspace-watcher.test.js +117 -0
- package/dist/test/workspace-watcher.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/framework.ts +148 -10
- package/src/gate/event-gate.ts +106 -6
- package/src/gate/types.ts +28 -0
- package/src/index.ts +7 -0
- package/src/mcpl/channel-registry.ts +120 -8
- package/src/mcpl/push-handler.ts +1 -1
- package/src/mcpl/server-connection.ts +78 -3
- package/src/mcpl/tool-policy.ts +52 -0
- package/src/mcpl/types.ts +34 -0
- package/src/modules/workspace/index.ts +269 -38
- package/src/modules/workspace/sync.ts +11 -4
- package/src/modules/workspace/types.ts +70 -3
- package/src/modules/workspace/watcher.ts +104 -15
- package/src/types/trace.ts +26 -1
- package/src/usage/index.ts +2 -0
- package/src/usage/types.ts +27 -0
- package/src/usage/usage-tracker.ts +141 -0
|
@@ -31,6 +31,25 @@ export interface MountConfig {
|
|
|
31
31
|
followSymlinks?: boolean;
|
|
32
32
|
/** Maximum file size in bytes (default: 5MB) */
|
|
33
33
|
maxFileSize?: number;
|
|
34
|
+
/**
|
|
35
|
+
* If set, filesystem changes on this mount request inference.
|
|
36
|
+
* - `true` — wake on any op (created | modified | deleted)
|
|
37
|
+
* - array — wake only for the listed ops
|
|
38
|
+
*
|
|
39
|
+
* Self-writes through the module's own tools are already suppressed by the
|
|
40
|
+
* watcher, so a mount shared between agents only wakes on external writes.
|
|
41
|
+
* The EventGate still has final say — use gate policies for path-glob
|
|
42
|
+
* filtering or to disable wake temporarily via hot-reload.
|
|
43
|
+
*/
|
|
44
|
+
wakeOnChange?: boolean | Array<'created' | 'modified' | 'deleted'>;
|
|
45
|
+
/**
|
|
46
|
+
* If true, writes/edits/deletes via the module's tools materialize to the
|
|
47
|
+
* filesystem immediately (not just into Chronicle tree state). Required for
|
|
48
|
+
* any mount shared across agents as a communication channel — without it,
|
|
49
|
+
* another agent's watcher on the same directory sees nothing. The watcher
|
|
50
|
+
* suppresses its own echoes, so this doesn't cause self-wake loops.
|
|
51
|
+
*/
|
|
52
|
+
autoMaterialize?: boolean;
|
|
34
53
|
}
|
|
35
54
|
/**
|
|
36
55
|
* Configuration for the WorkspaceModule.
|
|
@@ -63,6 +82,15 @@ export interface MountState {
|
|
|
63
82
|
lastMaterializedBranchId: string | null;
|
|
64
83
|
/** Per-file hash at time of last materialization — baseline for conflict detection */
|
|
65
84
|
materializedHashes: Map<string, string>;
|
|
85
|
+
/**
|
|
86
|
+
* Wall-clock time chokidar emitted `ready` for this mount, or null if the
|
|
87
|
+
* watcher hasn't finished its initial scan. null after session start =
|
|
88
|
+
* watcher attach silently failed; a set value with empty tree = attached
|
|
89
|
+
* to an empty directory.
|
|
90
|
+
*/
|
|
91
|
+
watcherReadyAt: number | null;
|
|
92
|
+
/** Most recent chokidar error for this mount, if any. */
|
|
93
|
+
watcherError: string | null;
|
|
66
94
|
}
|
|
67
95
|
/**
|
|
68
96
|
* Persisted module state (via Chronicle snapshot).
|
|
@@ -72,6 +100,8 @@ export interface WorkspaceModuleState {
|
|
|
72
100
|
mounts: Record<string, {
|
|
73
101
|
lastMaterializedSeq: number;
|
|
74
102
|
lastMaterializedBranchId?: string;
|
|
103
|
+
watcherReadyAt?: number | null;
|
|
104
|
+
watcherError?: string | null;
|
|
75
105
|
}>;
|
|
76
106
|
/** Branch ID considered "active" for materialization */
|
|
77
107
|
activeBranchId?: string;
|
|
@@ -144,13 +174,32 @@ export interface SyncInput {
|
|
|
144
174
|
/** Specific mount (optional — defaults to all) */
|
|
145
175
|
mount?: string;
|
|
146
176
|
}
|
|
147
|
-
export
|
|
148
|
-
|
|
177
|
+
export type WorkspaceFsOp = 'created' | 'modified' | 'deleted';
|
|
178
|
+
/**
|
|
179
|
+
* Fired when files in a mount are created. `paths` are mount-prefixed
|
|
180
|
+
* (e.g. "tickets/2026-04-20-foo.md"). Conflicts are reported when Chronicle
|
|
181
|
+
* sync detected divergence between the filesystem and the tree state.
|
|
182
|
+
*/
|
|
183
|
+
export interface WorkspaceCreatedEvent {
|
|
184
|
+
type: 'workspace:created';
|
|
149
185
|
paths: string[];
|
|
150
186
|
mount: string;
|
|
151
187
|
conflicts?: string[];
|
|
152
188
|
[key: string]: unknown;
|
|
153
189
|
}
|
|
190
|
+
export interface WorkspaceModifiedEvent {
|
|
191
|
+
type: 'workspace:modified';
|
|
192
|
+
paths: string[];
|
|
193
|
+
mount: string;
|
|
194
|
+
conflicts?: string[];
|
|
195
|
+
[key: string]: unknown;
|
|
196
|
+
}
|
|
197
|
+
export interface WorkspaceDeletedEvent {
|
|
198
|
+
type: 'workspace:deleted';
|
|
199
|
+
paths: string[];
|
|
200
|
+
mount: string;
|
|
201
|
+
[key: string]: unknown;
|
|
202
|
+
}
|
|
154
203
|
export interface WorkspaceMountedEvent {
|
|
155
204
|
type: 'workspace:mounted';
|
|
156
205
|
mount: string;
|
|
@@ -162,5 +211,8 @@ export interface WorkspaceUnmountedEvent {
|
|
|
162
211
|
mount: string;
|
|
163
212
|
[key: string]: unknown;
|
|
164
213
|
}
|
|
165
|
-
export type WorkspaceEvent =
|
|
214
|
+
export type WorkspaceEvent = WorkspaceCreatedEvent | WorkspaceModifiedEvent | WorkspaceDeletedEvent | WorkspaceMountedEvent | WorkspaceUnmountedEvent;
|
|
215
|
+
export declare const WORKSPACE_FS_EVENT_TYPES: readonly ["workspace:created", "workspace:modified", "workspace:deleted"];
|
|
216
|
+
export type WorkspaceFsEventType = typeof WORKSPACE_FS_EVENT_TYPES[number];
|
|
217
|
+
export declare function opToEventType(op: WorkspaceFsOp): WorkspaceFsEventType;
|
|
166
218
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/modules/workspace/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,IAAI,EAAE,YAAY,GAAG,WAAW,CAAC;IACjC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,QAAQ,GAAG,iBAAiB,GAAG,OAAO,CAAC;IAC/C,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kDAAkD;IAClD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/modules/workspace/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Types for the Workspace module
|
|
3
3
|
*/
|
|
4
|
-
export
|
|
4
|
+
export const WORKSPACE_FS_EVENT_TYPES = [
|
|
5
|
+
'workspace:created',
|
|
6
|
+
'workspace:modified',
|
|
7
|
+
'workspace:deleted',
|
|
8
|
+
];
|
|
9
|
+
export function opToEventType(op) {
|
|
10
|
+
return `workspace:${op}`;
|
|
11
|
+
}
|
|
5
12
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/modules/workspace/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/modules/workspace/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgQH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,mBAAmB;IACnB,oBAAoB;IACpB,mBAAmB;CACX,CAAC;AAIX,MAAM,UAAU,aAAa,CAAC,EAAiB;IAC7C,OAAO,aAAa,EAAE,EAA0B,CAAC;AACnD,CAAC"}
|
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Filesystem watcher with debounce, ignore patterns, and suppression.
|
|
3
|
+
*
|
|
4
|
+
* Events are carried through with their op type (created/modified/deleted) so
|
|
5
|
+
* downstream wake policies can key on creation vs. modification vs. deletion.
|
|
3
6
|
*/
|
|
4
7
|
import { type MountConfig } from './types.js';
|
|
8
|
+
export type FsOp = 'created' | 'modified' | 'deleted';
|
|
9
|
+
export interface FsChange {
|
|
10
|
+
path: string;
|
|
11
|
+
op: FsOp;
|
|
12
|
+
}
|
|
5
13
|
export interface WatcherEvents {
|
|
6
|
-
onChange(
|
|
14
|
+
onChange(changes: FsChange[]): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Optional lifecycle callbacks. Without these, chokidar's `ready` and `error`
|
|
18
|
+
* events are silently dropped — which is how a failed attach can look
|
|
19
|
+
* identical to an empty directory in the recorded state.
|
|
20
|
+
*/
|
|
21
|
+
export interface WatcherLifecycle {
|
|
22
|
+
/** Fires once, when chokidar completes its initial scan. */
|
|
23
|
+
onReady?: () => void;
|
|
24
|
+
/** Fires on any chokidar-reported error (ENOENT, EACCES, platform faults). */
|
|
25
|
+
onError?: (err: Error) => void;
|
|
7
26
|
}
|
|
8
27
|
/**
|
|
9
28
|
* Manages filesystem watching for a single mount.
|
|
@@ -18,7 +37,8 @@ export declare class MountWatcher {
|
|
|
18
37
|
private readonly debounceMs;
|
|
19
38
|
private readonly config;
|
|
20
39
|
private readonly onChangeCallback;
|
|
21
|
-
|
|
40
|
+
private readonly lifecycle;
|
|
41
|
+
constructor(config: MountConfig, onChange: (changes: FsChange[]) => void, lifecycle?: WatcherLifecycle);
|
|
22
42
|
/**
|
|
23
43
|
* Start watching the filesystem.
|
|
24
44
|
*/
|
|
@@ -30,13 +50,30 @@ export declare class MountWatcher {
|
|
|
30
50
|
/**
|
|
31
51
|
* Suppress watcher events for a path temporarily.
|
|
32
52
|
* Used after materializing to avoid echo events.
|
|
33
|
-
* After the cooldown, the path is re-checked via the recheckCallback.
|
|
34
53
|
*/
|
|
35
54
|
suppress(relativePath: string, cooldownMs?: number): void;
|
|
36
55
|
/**
|
|
37
56
|
* Check if a path is currently suppressed.
|
|
38
57
|
*/
|
|
39
58
|
isSuppressed(relativePath: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Merge a new op for a path into the pending batch. Chokidar can fire
|
|
61
|
+
* multiple events per path inside one debounce window; collapse them to the
|
|
62
|
+
* single op that reflects the net effect at end-of-window.
|
|
63
|
+
*
|
|
64
|
+
* Transitions (prev → op → result):
|
|
65
|
+
* ∅ → * → op
|
|
66
|
+
* * → deleted → deleted (trailing delete wins)
|
|
67
|
+
* deleted → created → modified (atomic save: unlink+rename;
|
|
68
|
+
* file exists with new contents)
|
|
69
|
+
* created → modified → created (still net-new this window)
|
|
70
|
+
* created → created → created
|
|
71
|
+
* modified → created → created (shouldn't happen, but keep
|
|
72
|
+
* created to avoid a false
|
|
73
|
+
* delete->recreate signal)
|
|
74
|
+
* modified → modified → modified
|
|
75
|
+
*/
|
|
76
|
+
private mergeOp;
|
|
40
77
|
private scheduleFire;
|
|
41
78
|
private toRelative;
|
|
42
79
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../../../src/modules/workspace/watcher.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../../../src/modules/workspace/watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,MAAM,IAAI,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAEtD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,IAAI,CAAC;CACV;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;CACrC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC;AAED;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAA0B;IAGzC,OAAO,CAAC,cAAc,CAA2B;IACjD,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,iBAAiB,CAAoD;IAC7E,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAgC;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;gBAG3C,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,IAAI,EACvC,SAAS,GAAE,gBAAqB;IAQlC;;OAEG;IACH,KAAK,IAAI,IAAI;IA0Db;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3B;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,SAAM,GAAG,IAAI;IActD;;OAEG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI3C;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,OAAO;IAqBf,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,UAAU;CASnB"}
|
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Filesystem watcher with debounce, ignore patterns, and suppression.
|
|
3
|
+
*
|
|
4
|
+
* Events are carried through with their op type (created/modified/deleted) so
|
|
5
|
+
* downstream wake policies can key on creation vs. modification vs. deletion.
|
|
3
6
|
*/
|
|
4
7
|
import { watch } from 'chokidar';
|
|
8
|
+
import { mkdirSync } from 'node:fs';
|
|
5
9
|
/**
|
|
6
10
|
* Manages filesystem watching for a single mount.
|
|
7
11
|
* Handles debouncing, ignore patterns, and write suppression.
|
|
8
12
|
*/
|
|
9
13
|
export class MountWatcher {
|
|
10
14
|
watcher = null;
|
|
11
|
-
|
|
15
|
+
// Most recent op seen per path within the current debounce window.
|
|
16
|
+
// create -> modify collapses to 'created' (single batch); delete always wins.
|
|
17
|
+
pendingChanges = new Map();
|
|
12
18
|
debounceTimer = null;
|
|
13
19
|
suppressedPaths = new Set();
|
|
14
20
|
suppressionTimers = new Map();
|
|
15
21
|
debounceMs;
|
|
16
22
|
config;
|
|
17
23
|
onChangeCallback;
|
|
18
|
-
|
|
24
|
+
lifecycle;
|
|
25
|
+
constructor(config, onChange, lifecycle = {}) {
|
|
19
26
|
this.config = config;
|
|
20
27
|
this.debounceMs = config.watchDebounceMs ?? 300;
|
|
21
28
|
this.onChangeCallback = onChange;
|
|
29
|
+
this.lifecycle = lifecycle;
|
|
22
30
|
}
|
|
23
31
|
/**
|
|
24
32
|
* Start watching the filesystem.
|
|
@@ -26,6 +34,21 @@ export class MountWatcher {
|
|
|
26
34
|
start() {
|
|
27
35
|
if (this.watcher)
|
|
28
36
|
return;
|
|
37
|
+
// Read-write mounts: ensure the path exists before chokidar attaches.
|
|
38
|
+
// chokidar 4's fs.watch-based backend silently fails to fire events when
|
|
39
|
+
// the watched path OR any of its parent directories don't exist at
|
|
40
|
+
// subscribe time (see case C in the WSL/Linux repro). `ready` still fires,
|
|
41
|
+
// so the failure is indistinguishable from an empty directory without
|
|
42
|
+
// this defensive mkdir. Read-only mounts are left alone — creating
|
|
43
|
+
// directories a user asked us only to read would be surprising.
|
|
44
|
+
if (this.config.mode === 'read-write') {
|
|
45
|
+
try {
|
|
46
|
+
mkdirSync(this.config.path, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
this.lifecycle.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
29
52
|
const ignored = this.config.ignore ?? [];
|
|
30
53
|
this.watcher = watch(this.config.path, {
|
|
31
54
|
ignored: ignored.length > 0 ? ignored : undefined,
|
|
@@ -37,20 +60,29 @@ export class MountWatcher {
|
|
|
37
60
|
pollInterval: 50,
|
|
38
61
|
},
|
|
39
62
|
});
|
|
40
|
-
const handleEvent = (filePath) => {
|
|
41
|
-
// Convert absolute path to mount-relative
|
|
63
|
+
const handleEvent = (op) => (filePath) => {
|
|
42
64
|
const relative = this.toRelative(filePath);
|
|
43
65
|
if (!relative)
|
|
44
66
|
return;
|
|
45
|
-
// Skip if this path is suppressed (we just wrote it)
|
|
67
|
+
// Skip if this path is suppressed (we just wrote it).
|
|
68
|
+
// Suppression covers all ops — a materialize-then-delete by the module
|
|
69
|
+
// should not echo either the add or the unlink.
|
|
46
70
|
if (this.suppressedPaths.has(relative))
|
|
47
71
|
return;
|
|
48
|
-
this.
|
|
72
|
+
this.mergeOp(relative, op);
|
|
49
73
|
this.scheduleFire();
|
|
50
74
|
};
|
|
51
|
-
this.watcher.on('add', handleEvent);
|
|
52
|
-
this.watcher.on('change', handleEvent);
|
|
53
|
-
this.watcher.on('unlink', handleEvent);
|
|
75
|
+
this.watcher.on('add', handleEvent('created'));
|
|
76
|
+
this.watcher.on('change', handleEvent('modified'));
|
|
77
|
+
this.watcher.on('unlink', handleEvent('deleted'));
|
|
78
|
+
if (this.lifecycle.onReady) {
|
|
79
|
+
this.watcher.once('ready', this.lifecycle.onReady);
|
|
80
|
+
}
|
|
81
|
+
if (this.lifecycle.onError) {
|
|
82
|
+
this.watcher.on('error', (err) => {
|
|
83
|
+
this.lifecycle.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
84
|
+
});
|
|
85
|
+
}
|
|
54
86
|
}
|
|
55
87
|
/**
|
|
56
88
|
* Stop watching.
|
|
@@ -74,11 +106,9 @@ export class MountWatcher {
|
|
|
74
106
|
/**
|
|
75
107
|
* Suppress watcher events for a path temporarily.
|
|
76
108
|
* Used after materializing to avoid echo events.
|
|
77
|
-
* After the cooldown, the path is re-checked via the recheckCallback.
|
|
78
109
|
*/
|
|
79
110
|
suppress(relativePath, cooldownMs = 500) {
|
|
80
111
|
this.suppressedPaths.add(relativePath);
|
|
81
|
-
// Clear existing timer for this path
|
|
82
112
|
const existing = this.suppressionTimers.get(relativePath);
|
|
83
113
|
if (existing)
|
|
84
114
|
clearTimeout(existing);
|
|
@@ -94,6 +124,43 @@ export class MountWatcher {
|
|
|
94
124
|
isSuppressed(relativePath) {
|
|
95
125
|
return this.suppressedPaths.has(relativePath);
|
|
96
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Merge a new op for a path into the pending batch. Chokidar can fire
|
|
129
|
+
* multiple events per path inside one debounce window; collapse them to the
|
|
130
|
+
* single op that reflects the net effect at end-of-window.
|
|
131
|
+
*
|
|
132
|
+
* Transitions (prev → op → result):
|
|
133
|
+
* ∅ → * → op
|
|
134
|
+
* * → deleted → deleted (trailing delete wins)
|
|
135
|
+
* deleted → created → modified (atomic save: unlink+rename;
|
|
136
|
+
* file exists with new contents)
|
|
137
|
+
* created → modified → created (still net-new this window)
|
|
138
|
+
* created → created → created
|
|
139
|
+
* modified → created → created (shouldn't happen, but keep
|
|
140
|
+
* created to avoid a false
|
|
141
|
+
* delete->recreate signal)
|
|
142
|
+
* modified → modified → modified
|
|
143
|
+
*/
|
|
144
|
+
mergeOp(path, op) {
|
|
145
|
+
const prev = this.pendingChanges.get(path);
|
|
146
|
+
if (!prev) {
|
|
147
|
+
this.pendingChanges.set(path, op);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (op === 'deleted') {
|
|
151
|
+
this.pendingChanges.set(path, 'deleted');
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (prev === 'deleted' && op === 'created') {
|
|
155
|
+
this.pendingChanges.set(path, 'modified');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (prev === 'created') {
|
|
159
|
+
this.pendingChanges.set(path, 'created');
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
this.pendingChanges.set(path, op);
|
|
163
|
+
}
|
|
97
164
|
scheduleFire() {
|
|
98
165
|
if (this.debounceTimer) {
|
|
99
166
|
clearTimeout(this.debounceTimer);
|
|
@@ -101,9 +168,9 @@ export class MountWatcher {
|
|
|
101
168
|
this.debounceTimer = setTimeout(() => {
|
|
102
169
|
this.debounceTimer = null;
|
|
103
170
|
if (this.pendingChanges.size > 0) {
|
|
104
|
-
const
|
|
171
|
+
const changes = [...this.pendingChanges].map(([path, op]) => ({ path, op }));
|
|
105
172
|
this.pendingChanges.clear();
|
|
106
|
-
this.onChangeCallback(
|
|
173
|
+
this.onChangeCallback(changes);
|
|
107
174
|
}
|
|
108
175
|
}, this.debounceMs);
|
|
109
176
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../../../src/modules/workspace/watcher.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../../../src/modules/workspace/watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ProcessEvent } from './events.js';
|
|
2
2
|
import type { ModuleProcessResponse } from './framework.js';
|
|
3
|
+
import type { SessionUsage } from '../usage/types.js';
|
|
3
4
|
/**
|
|
4
5
|
* Base for all trace events.
|
|
5
6
|
* TraceEvents are observability-only — they NEVER drive logic.
|
|
@@ -76,6 +77,8 @@ export type TraceEvent = (TraceEventBase & {
|
|
|
76
77
|
tokenUsage: {
|
|
77
78
|
input: number;
|
|
78
79
|
output: number;
|
|
80
|
+
cacheCreation?: number;
|
|
81
|
+
cacheRead?: number;
|
|
79
82
|
};
|
|
80
83
|
}) | (TraceEventBase & {
|
|
81
84
|
type: 'inference:stream_resumed';
|
|
@@ -154,6 +157,19 @@ export type TraceEvent = (TraceEventBase & {
|
|
|
154
157
|
type: 'gate:config-reloaded';
|
|
155
158
|
configPath: string;
|
|
156
159
|
policyCount: number;
|
|
160
|
+
}) | (TraceEventBase & {
|
|
161
|
+
type: 'gate:decision';
|
|
162
|
+
eventType: string;
|
|
163
|
+
serverId?: string;
|
|
164
|
+
channelId?: string;
|
|
165
|
+
matchedPolicy: string | null;
|
|
166
|
+
trigger: boolean;
|
|
167
|
+
behavior: string;
|
|
168
|
+
}) | (TraceEventBase & {
|
|
169
|
+
type: 'usage:updated';
|
|
170
|
+
totals: SessionUsage;
|
|
171
|
+
agentName: string;
|
|
172
|
+
inferenceCount: number;
|
|
157
173
|
}) | (TraceEventBase & {
|
|
158
174
|
type: 'undo:completed';
|
|
159
175
|
agentName: string;
|
|
@@ -165,6 +181,10 @@ export type TraceEvent = (TraceEventBase & {
|
|
|
165
181
|
agentName: string;
|
|
166
182
|
fromBranch: string;
|
|
167
183
|
toBranch: string;
|
|
184
|
+
}) | (TraceEventBase & {
|
|
185
|
+
type: 'mcpl:server-stderr';
|
|
186
|
+
serverId: string;
|
|
187
|
+
line: string;
|
|
168
188
|
});
|
|
169
189
|
/**
|
|
170
190
|
* Listener for trace events.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../../src/types/trace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../../src/types/trace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/usage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/usage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface SessionUsage {
|
|
2
|
+
inputTokens: number;
|
|
3
|
+
outputTokens: number;
|
|
4
|
+
cacheCreationTokens: number;
|
|
5
|
+
cacheReadTokens: number;
|
|
6
|
+
estimatedCost?: {
|
|
7
|
+
total: number;
|
|
8
|
+
currency: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export interface AgentUsage {
|
|
12
|
+
agentName: string;
|
|
13
|
+
usage: SessionUsage;
|
|
14
|
+
inferenceCount: number;
|
|
15
|
+
}
|
|
16
|
+
export interface SessionUsageSnapshot {
|
|
17
|
+
totals: SessionUsage;
|
|
18
|
+
byAgent: AgentUsage[];
|
|
19
|
+
inferenceCount: number;
|
|
20
|
+
}
|
|
21
|
+
/** Trace event emitted by UsageTracker after each inference completion. */
|
|
22
|
+
export interface UsageUpdatedEvent {
|
|
23
|
+
type: 'usage:updated';
|
|
24
|
+
totals: SessionUsage;
|
|
25
|
+
agentName: string;
|
|
26
|
+
inferenceCount: number;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/usage/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,YAAY,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/usage/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { SessionUsage, SessionUsageSnapshot, UsageUpdatedEvent } from './types.js';
|
|
2
|
+
export interface PersistedUsageState {
|
|
3
|
+
totals: SessionUsage;
|
|
4
|
+
byAgent: Array<{
|
|
5
|
+
agentName: string;
|
|
6
|
+
usage: SessionUsage;
|
|
7
|
+
inferenceCount: number;
|
|
8
|
+
}>;
|
|
9
|
+
inferenceCount: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class UsageTracker {
|
|
12
|
+
private totals;
|
|
13
|
+
private byAgent;
|
|
14
|
+
private inferenceCount;
|
|
15
|
+
private emitTrace;
|
|
16
|
+
constructor(opts: {
|
|
17
|
+
emitTrace: (event: UsageUpdatedEvent) => void;
|
|
18
|
+
restored?: PersistedUsageState;
|
|
19
|
+
});
|
|
20
|
+
private restoreFrom;
|
|
21
|
+
toJSON(): PersistedUsageState;
|
|
22
|
+
onInferenceCompleted(agentName: string, usage: {
|
|
23
|
+
inputTokens: number;
|
|
24
|
+
outputTokens: number;
|
|
25
|
+
cacheCreationTokens?: number;
|
|
26
|
+
cacheReadTokens?: number;
|
|
27
|
+
}, estimatedCost?: {
|
|
28
|
+
total: number;
|
|
29
|
+
currency: string;
|
|
30
|
+
}): void;
|
|
31
|
+
getSnapshot(): SessionUsageSnapshot;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=usage-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-tracker.d.ts","sourceRoot":"","sources":["../../../src/usage/usage-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA6CxF,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,YAAY,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnF,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAiG;IAC/G,OAAO,CAAC,OAAO,CAA2E;IAC1F,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,SAAS,CAAqC;gBAE1C,IAAI,EAAE;QAChB,SAAS,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;QAC9C,QAAQ,CAAC,EAAE,mBAAmB,CAAC;KAChC;IAOD,OAAO,CAAC,WAAW;IAkBnB,MAAM,IAAI,mBAAmB;IAY7B,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE;QAC7C,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,EAAE,aAAa,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IA2B7D,WAAW,IAAI,oBAAoB;CAWpC"}
|