@velvetmonkey/vault-core 1.27.26 → 1.27.28
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.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/logging/index.d.ts +7 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +7 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/operationLogger.d.ts +59 -0
- package/dist/logging/operationLogger.d.ts.map +1 -0
- package/dist/logging/operationLogger.js +282 -0
- package/dist/logging/operationLogger.js.map +1 -0
- package/dist/logging/sessionManager.d.ts +35 -0
- package/dist/logging/sessionManager.d.ts.map +1 -0
- package/dist/logging/sessionManager.js +68 -0
- package/dist/logging/sessionManager.js.map +1 -0
- package/dist/logging/types.d.ts +123 -0
- package/dist/logging/types.d.ts.map +1 -0
- package/dist/logging/types.js +23 -0
- package/dist/logging/types.js.map +1 -0
- package/dist/types.d.ts +49 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/wikilinks.d.ts +30 -1
- package/dist/wikilinks.d.ts.map +1 -1
- package/dist/wikilinks.js +222 -0
- package/dist/wikilinks.js.map +1 -1
- package/package.json +3 -2
- package/LICENSE +0 -201
- package/README.md +0 -137
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* Shared vault utilities for the Flywheel ecosystem.
|
|
5
5
|
* Used by both Flywheel (read) and Flywheel-Crank (write).
|
|
6
6
|
*/
|
|
7
|
-
export type { EntityIndex, EntityCategory, EntityWithAliases, Entity, EntityWithType, ProtectedZone, ProtectedZoneType, ScanOptions, WikilinkOptions, WikilinkResult, } from './types.js';
|
|
7
|
+
export type { EntityIndex, EntityCategory, EntityWithAliases, Entity, EntityWithType, ProtectedZone, ProtectedZoneType, ScanOptions, WikilinkOptions, WikilinkResult, ImplicitEntityConfig, ExtendedWikilinkOptions, ImplicitEntityMatch, } from './types.js';
|
|
8
8
|
export { scanVaultEntities, getAllEntities, getAllEntitiesWithTypes, getEntityName, getEntityAliases, filterPeriodicNotes, loadEntityCache, saveEntityCache, ENTITY_CACHE_VERSION, } from './entities.js';
|
|
9
9
|
export { getProtectedZones, isInProtectedZone, rangeOverlapsProtectedZone, findFrontmatterEnd, } from './protectedZones.js';
|
|
10
|
-
export { applyWikilinks, suggestWikilinks, } from './wikilinks.js';
|
|
10
|
+
export { applyWikilinks, suggestWikilinks, detectImplicitEntities, processWikilinks, } from './wikilinks.js';
|
|
11
|
+
export { OperationLogger, createLoggerFromConfig, generateSessionId, getSessionId, setSessionId, clearSession, createChildSession, getParentSession, isChildSession, DEFAULT_LOGGING_CONFIG, } from './logging/index.js';
|
|
12
|
+
export type { OperationLogEntry, SessionMetrics, AggregatedMetrics, LoggingConfig, ProductId, } from './logging/index.js';
|
|
11
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,MAAM,EACN,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,MAAM,EACN,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EACV,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,SAAS,GACV,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -9,5 +9,7 @@ export { scanVaultEntities, getAllEntities, getAllEntitiesWithTypes, getEntityNa
|
|
|
9
9
|
// Protected zones
|
|
10
10
|
export { getProtectedZones, isInProtectedZone, rangeOverlapsProtectedZone, findFrontmatterEnd, } from './protectedZones.js';
|
|
11
11
|
// Wikilinks
|
|
12
|
-
export { applyWikilinks, suggestWikilinks, } from './wikilinks.js';
|
|
12
|
+
export { applyWikilinks, suggestWikilinks, detectImplicitEntities, processWikilinks, } from './wikilinks.js';
|
|
13
|
+
// Logging (unified cross-product logging)
|
|
14
|
+
export { OperationLogger, createLoggerFromConfig, generateSessionId, getSessionId, setSessionId, clearSession, createChildSession, getParentSession, isChildSession, DEFAULT_LOGGING_CONFIG, } from './logging/index.js';
|
|
13
15
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH,kBAAkB;AAClB,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAEvB,kBAAkB;AAClB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,YAAY;AACZ,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,0CAA0C;AAC1C,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,sBAAsB,GACvB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging module exports
|
|
3
|
+
*/
|
|
4
|
+
export { OperationLogger, createLoggerFromConfig } from './operationLogger.js';
|
|
5
|
+
export { generateSessionId, getSessionId, setSessionId, clearSession, createChildSession, getParentSession, isChildSession, } from './sessionManager.js';
|
|
6
|
+
export { DEFAULT_LOGGING_CONFIG, type OperationLogEntry, type SessionMetrics, type AggregatedMetrics, type LoggingConfig, type ProductId, } from './types.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging module exports
|
|
3
|
+
*/
|
|
4
|
+
export { OperationLogger, createLoggerFromConfig } from './operationLogger.js';
|
|
5
|
+
export { generateSessionId, getSessionId, setSessionId, clearSession, createChildSession, getParentSession, isChildSession, } from './sessionManager.js';
|
|
6
|
+
export { DEFAULT_LOGGING_CONFIG, } from './types.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,sBAAsB,GAMvB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared OperationLogger for Flywheel ecosystem
|
|
3
|
+
*
|
|
4
|
+
* Provides unified logging for both Flywheel (read) and Flywheel-Crank (write)
|
|
5
|
+
* with session correlation, metrics aggregation, and privacy controls.
|
|
6
|
+
*/
|
|
7
|
+
import type { OperationLogEntry, SessionMetrics, AggregatedMetrics, LoggingConfig, ProductId } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Shared operation logger
|
|
10
|
+
*/
|
|
11
|
+
export declare class OperationLogger {
|
|
12
|
+
private config;
|
|
13
|
+
private vaultPath;
|
|
14
|
+
private product;
|
|
15
|
+
private writeQueue;
|
|
16
|
+
private flushTimeout;
|
|
17
|
+
constructor(vaultPath: string, product: ProductId, config?: Partial<LoggingConfig>);
|
|
18
|
+
/**
|
|
19
|
+
* Check if logging is enabled
|
|
20
|
+
*/
|
|
21
|
+
get enabled(): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Log an operation
|
|
24
|
+
*/
|
|
25
|
+
log(entry: Omit<OperationLogEntry, 'ts' | 'product' | 'session'>): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Wrap an async operation with automatic logging
|
|
28
|
+
*/
|
|
29
|
+
wrap<T>(tool: string, operation: () => Promise<T>, getDetails?: (result: T) => Partial<OperationLogEntry>): Promise<T>;
|
|
30
|
+
/**
|
|
31
|
+
* Get metrics for current session
|
|
32
|
+
*/
|
|
33
|
+
getSessionMetrics(): Promise<SessionMetrics | null>;
|
|
34
|
+
/**
|
|
35
|
+
* Get aggregated metrics for time period
|
|
36
|
+
*/
|
|
37
|
+
getMetrics(since?: Date, until?: Date): Promise<AggregatedMetrics>;
|
|
38
|
+
/**
|
|
39
|
+
* Flush write queue to disk
|
|
40
|
+
*/
|
|
41
|
+
flush(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Read all log entries
|
|
44
|
+
*/
|
|
45
|
+
private readEntries;
|
|
46
|
+
/**
|
|
47
|
+
* Anonymize vault path for privacy
|
|
48
|
+
*/
|
|
49
|
+
private anonymizePath;
|
|
50
|
+
/**
|
|
51
|
+
* Schedule a flush with debounce
|
|
52
|
+
*/
|
|
53
|
+
private scheduleFlush;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Create logger from vault's .flywheel.json config
|
|
57
|
+
*/
|
|
58
|
+
export declare function createLoggerFromConfig(vaultPath: string, product: ProductId): Promise<OperationLogger>;
|
|
59
|
+
//# sourceMappingURL=operationLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operationLogger.d.ts","sourceRoot":"","sources":["../../src/logging/operationLogger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,SAAS,EACV,MAAM,YAAY,CAAC;AAIpB;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,YAAY,CAA8C;gBAEtD,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAMlF;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACG,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,IAAI,GAAG,SAAS,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BtF;;OAEG;IACG,IAAI,CAAC,CAAC,EACV,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,iBAAiB,CAAC,GACrD,OAAO,CAAC,CAAC,CAAC;IA8Bb;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAsCzD;;OAEG;IACG,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyFxE;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B;;OAEG;YACW,WAAW;IAuBzB;;OAEG;IACH,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACH,OAAO,CAAC,aAAa;CAUtB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,eAAe,CAAC,CAW1B"}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared OperationLogger for Flywheel ecosystem
|
|
3
|
+
*
|
|
4
|
+
* Provides unified logging for both Flywheel (read) and Flywheel-Crank (write)
|
|
5
|
+
* with session correlation, metrics aggregation, and privacy controls.
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'fs/promises';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { DEFAULT_LOGGING_CONFIG } from './types.js';
|
|
10
|
+
import { getSessionId } from './sessionManager.js';
|
|
11
|
+
/**
|
|
12
|
+
* Shared operation logger
|
|
13
|
+
*/
|
|
14
|
+
export class OperationLogger {
|
|
15
|
+
config;
|
|
16
|
+
vaultPath;
|
|
17
|
+
product;
|
|
18
|
+
writeQueue = [];
|
|
19
|
+
flushTimeout = null;
|
|
20
|
+
constructor(vaultPath, product, config) {
|
|
21
|
+
this.vaultPath = vaultPath;
|
|
22
|
+
this.product = product;
|
|
23
|
+
this.config = { ...DEFAULT_LOGGING_CONFIG, ...config };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Check if logging is enabled
|
|
27
|
+
*/
|
|
28
|
+
get enabled() {
|
|
29
|
+
return this.config.enabled;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Log an operation
|
|
33
|
+
*/
|
|
34
|
+
async log(entry) {
|
|
35
|
+
if (!this.config.enabled) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const fullEntry = {
|
|
39
|
+
...entry,
|
|
40
|
+
ts: new Date().toISOString(),
|
|
41
|
+
product: this.product,
|
|
42
|
+
session: this.config.includeSessionIds ? getSessionId() : undefined,
|
|
43
|
+
};
|
|
44
|
+
// Apply privacy filters
|
|
45
|
+
if (!this.config.includeToolNames) {
|
|
46
|
+
fullEntry.tool = 'operation';
|
|
47
|
+
}
|
|
48
|
+
if (!this.config.includeDurations) {
|
|
49
|
+
fullEntry.duration_ms = 0;
|
|
50
|
+
}
|
|
51
|
+
if (!this.config.includeResults) {
|
|
52
|
+
delete fullEntry.results;
|
|
53
|
+
}
|
|
54
|
+
this.writeQueue.push(fullEntry);
|
|
55
|
+
this.scheduleFlush();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Wrap an async operation with automatic logging
|
|
59
|
+
*/
|
|
60
|
+
async wrap(tool, operation, getDetails) {
|
|
61
|
+
const startTime = Date.now();
|
|
62
|
+
let success = true;
|
|
63
|
+
let error;
|
|
64
|
+
let result;
|
|
65
|
+
try {
|
|
66
|
+
result = await operation();
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
success = false;
|
|
71
|
+
error = e instanceof Error ? e.message : String(e);
|
|
72
|
+
throw e;
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
const duration_ms = Date.now() - startTime;
|
|
76
|
+
const details = success && result !== undefined && getDetails
|
|
77
|
+
? getDetails(result)
|
|
78
|
+
: {};
|
|
79
|
+
await this.log({
|
|
80
|
+
tool,
|
|
81
|
+
vault: this.anonymizePath(this.vaultPath),
|
|
82
|
+
duration_ms,
|
|
83
|
+
success,
|
|
84
|
+
error,
|
|
85
|
+
...details,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get metrics for current session
|
|
91
|
+
*/
|
|
92
|
+
async getSessionMetrics() {
|
|
93
|
+
const sessionId = getSessionId();
|
|
94
|
+
const entries = await this.readEntries();
|
|
95
|
+
const sessionEntries = entries.filter(e => e.session === sessionId);
|
|
96
|
+
if (sessionEntries.length === 0) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const operations = {
|
|
100
|
+
flywheel: {},
|
|
101
|
+
crank: {},
|
|
102
|
+
};
|
|
103
|
+
let successCount = 0;
|
|
104
|
+
let minTs = sessionEntries[0].ts;
|
|
105
|
+
let maxTs = sessionEntries[0].ts;
|
|
106
|
+
for (const entry of sessionEntries) {
|
|
107
|
+
const prod = entry.product;
|
|
108
|
+
operations[prod][entry.tool] = (operations[prod][entry.tool] || 0) + 1;
|
|
109
|
+
if (entry.success)
|
|
110
|
+
successCount++;
|
|
111
|
+
if (entry.ts < minTs)
|
|
112
|
+
minTs = entry.ts;
|
|
113
|
+
if (entry.ts > maxTs)
|
|
114
|
+
maxTs = entry.ts;
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
session: sessionId,
|
|
118
|
+
duration_ms: new Date(maxTs).getTime() - new Date(minTs).getTime(),
|
|
119
|
+
operations,
|
|
120
|
+
total_operations: sessionEntries.length,
|
|
121
|
+
success_rate: (successCount / sessionEntries.length) * 100,
|
|
122
|
+
started: minTs,
|
|
123
|
+
ended: maxTs,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get aggregated metrics for time period
|
|
128
|
+
*/
|
|
129
|
+
async getMetrics(since, until) {
|
|
130
|
+
const entries = await this.readEntries();
|
|
131
|
+
const filtered = entries.filter(e => {
|
|
132
|
+
const ts = new Date(e.ts);
|
|
133
|
+
if (since && ts < since)
|
|
134
|
+
return false;
|
|
135
|
+
if (until && ts > until)
|
|
136
|
+
return false;
|
|
137
|
+
return true;
|
|
138
|
+
});
|
|
139
|
+
const durations = filtered.map(e => e.duration_ms);
|
|
140
|
+
const sorted = [...durations].sort((a, b) => a - b);
|
|
141
|
+
const byTool = {};
|
|
142
|
+
const byProduct = {
|
|
143
|
+
flywheel: { count: 0, success_rate: 0, mean_ms: 0 },
|
|
144
|
+
crank: { count: 0, success_rate: 0, mean_ms: 0 },
|
|
145
|
+
};
|
|
146
|
+
const productDurations = {
|
|
147
|
+
flywheel: [],
|
|
148
|
+
crank: [],
|
|
149
|
+
};
|
|
150
|
+
const productSuccess = {
|
|
151
|
+
flywheel: 0,
|
|
152
|
+
crank: 0,
|
|
153
|
+
};
|
|
154
|
+
for (const entry of filtered) {
|
|
155
|
+
// By tool
|
|
156
|
+
if (!byTool[entry.tool]) {
|
|
157
|
+
byTool[entry.tool] = {
|
|
158
|
+
count: 0,
|
|
159
|
+
success_rate: 0,
|
|
160
|
+
mean_ms: 0,
|
|
161
|
+
p95_ms: 0,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
byTool[entry.tool].count++;
|
|
165
|
+
// By product
|
|
166
|
+
byProduct[entry.product].count++;
|
|
167
|
+
productDurations[entry.product].push(entry.duration_ms);
|
|
168
|
+
if (entry.success) {
|
|
169
|
+
productSuccess[entry.product]++;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Calculate product metrics
|
|
173
|
+
for (const prod of ['flywheel', 'crank']) {
|
|
174
|
+
const ds = productDurations[prod];
|
|
175
|
+
if (ds.length > 0) {
|
|
176
|
+
byProduct[prod].mean_ms = ds.reduce((a, b) => a + b, 0) / ds.length;
|
|
177
|
+
byProduct[prod].success_rate = (productSuccess[prod] / ds.length) * 100;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Calculate tool metrics
|
|
181
|
+
for (const tool of Object.keys(byTool)) {
|
|
182
|
+
const toolEntries = filtered.filter(e => e.tool === tool);
|
|
183
|
+
const toolDurations = toolEntries.map(e => e.duration_ms).sort((a, b) => a - b);
|
|
184
|
+
const successCount = toolEntries.filter(e => e.success).length;
|
|
185
|
+
byTool[tool].mean_ms = toolDurations.reduce((a, b) => a + b, 0) / toolDurations.length;
|
|
186
|
+
byTool[tool].success_rate = (successCount / toolEntries.length) * 100;
|
|
187
|
+
byTool[tool].p95_ms = toolDurations[Math.floor(toolDurations.length * 0.95)] || 0;
|
|
188
|
+
}
|
|
189
|
+
const successCount = filtered.filter(e => e.success).length;
|
|
190
|
+
return {
|
|
191
|
+
periodStart: since?.toISOString() || filtered[0]?.ts || new Date().toISOString(),
|
|
192
|
+
periodEnd: until?.toISOString() || filtered[filtered.length - 1]?.ts || new Date().toISOString(),
|
|
193
|
+
totalOperations: filtered.length,
|
|
194
|
+
successfulOperations: successCount,
|
|
195
|
+
failedOperations: filtered.length - successCount,
|
|
196
|
+
timing: {
|
|
197
|
+
mean_ms: durations.length > 0 ? durations.reduce((a, b) => a + b, 0) / durations.length : 0,
|
|
198
|
+
p50_ms: sorted[Math.floor(sorted.length * 0.5)] || 0,
|
|
199
|
+
p95_ms: sorted[Math.floor(sorted.length * 0.95)] || 0,
|
|
200
|
+
p99_ms: sorted[Math.floor(sorted.length * 0.99)] || 0,
|
|
201
|
+
min_ms: sorted[0] || 0,
|
|
202
|
+
max_ms: sorted[sorted.length - 1] || 0,
|
|
203
|
+
},
|
|
204
|
+
byTool,
|
|
205
|
+
byProduct,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Flush write queue to disk
|
|
210
|
+
*/
|
|
211
|
+
async flush() {
|
|
212
|
+
if (this.writeQueue.length === 0) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const entries = this.writeQueue.splice(0, this.writeQueue.length);
|
|
216
|
+
const logPath = path.join(this.vaultPath, this.config.logPath);
|
|
217
|
+
// Ensure directory exists
|
|
218
|
+
await fs.mkdir(path.dirname(logPath), { recursive: true });
|
|
219
|
+
// Append entries as JSONL
|
|
220
|
+
const lines = entries.map(e => JSON.stringify(e)).join('\n') + '\n';
|
|
221
|
+
await fs.appendFile(logPath, lines);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Read all log entries
|
|
225
|
+
*/
|
|
226
|
+
async readEntries() {
|
|
227
|
+
const logPath = path.join(this.vaultPath, this.config.logPath);
|
|
228
|
+
try {
|
|
229
|
+
const content = await fs.readFile(logPath, 'utf-8');
|
|
230
|
+
const entries = [];
|
|
231
|
+
for (const line of content.split('\n')) {
|
|
232
|
+
if (line.trim()) {
|
|
233
|
+
try {
|
|
234
|
+
entries.push(JSON.parse(line));
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
// Skip malformed lines
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return entries;
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
return [];
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Anonymize vault path for privacy
|
|
249
|
+
*/
|
|
250
|
+
anonymizePath(vaultPath) {
|
|
251
|
+
// Use last directory name only
|
|
252
|
+
return path.basename(vaultPath);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Schedule a flush with debounce
|
|
256
|
+
*/
|
|
257
|
+
scheduleFlush() {
|
|
258
|
+
if (this.flushTimeout) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
this.flushTimeout = setTimeout(async () => {
|
|
262
|
+
this.flushTimeout = null;
|
|
263
|
+
await this.flush();
|
|
264
|
+
}, 1000); // 1 second debounce
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Create logger from vault's .flywheel.json config
|
|
269
|
+
*/
|
|
270
|
+
export async function createLoggerFromConfig(vaultPath, product) {
|
|
271
|
+
const configPath = path.join(vaultPath, '.flywheel.json');
|
|
272
|
+
try {
|
|
273
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
274
|
+
const config = JSON.parse(content);
|
|
275
|
+
return new OperationLogger(vaultPath, product, config.logging);
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
// No config or invalid - use defaults
|
|
279
|
+
return new OperationLogger(vaultPath, product);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=operationLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operationLogger.js","sourceRoot":"","sources":["../../src/logging/operationLogger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session ID management for workflow correlation
|
|
3
|
+
*
|
|
4
|
+
* Allows tracking operations across a single agent workflow,
|
|
5
|
+
* correlating reads (Flywheel) and writes (Crank).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Generate a unique session ID
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateSessionId(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Get session ID from environment or generate new one
|
|
13
|
+
*/
|
|
14
|
+
export declare function getSessionId(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Set the session ID explicitly (for agent orchestration)
|
|
17
|
+
*/
|
|
18
|
+
export declare function setSessionId(sessionId: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Clear the session (start fresh)
|
|
21
|
+
*/
|
|
22
|
+
export declare function clearSession(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Create a child session for sub-workflows
|
|
25
|
+
*/
|
|
26
|
+
export declare function createChildSession(parentSession: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Extract parent session from child session ID
|
|
29
|
+
*/
|
|
30
|
+
export declare function getParentSession(sessionId: string): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Check if session ID is a child of another
|
|
33
|
+
*/
|
|
34
|
+
export declare function isChildSession(sessionId: string, parentId: string): boolean;
|
|
35
|
+
//# sourceMappingURL=sessionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionManager.d.ts","sourceRoot":"","sources":["../../src/logging/sessionManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAarC;AAKD;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGpD;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAGnC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMjE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE3E"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session ID management for workflow correlation
|
|
3
|
+
*
|
|
4
|
+
* Allows tracking operations across a single agent workflow,
|
|
5
|
+
* correlating reads (Flywheel) and writes (Crank).
|
|
6
|
+
*/
|
|
7
|
+
import { randomBytes } from 'crypto';
|
|
8
|
+
/**
|
|
9
|
+
* Generate a unique session ID
|
|
10
|
+
*/
|
|
11
|
+
export function generateSessionId() {
|
|
12
|
+
return randomBytes(8).toString('hex');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get session ID from environment or generate new one
|
|
16
|
+
*/
|
|
17
|
+
export function getSessionId() {
|
|
18
|
+
// Check environment variable first (for agent-provided session)
|
|
19
|
+
const envSession = process.env.FLYWHEEL_SESSION_ID;
|
|
20
|
+
if (envSession) {
|
|
21
|
+
return envSession;
|
|
22
|
+
}
|
|
23
|
+
// Check for cached session in process
|
|
24
|
+
if (!globalSessionId) {
|
|
25
|
+
globalSessionId = generateSessionId();
|
|
26
|
+
}
|
|
27
|
+
return globalSessionId;
|
|
28
|
+
}
|
|
29
|
+
// Module-level session cache
|
|
30
|
+
let globalSessionId = null;
|
|
31
|
+
/**
|
|
32
|
+
* Set the session ID explicitly (for agent orchestration)
|
|
33
|
+
*/
|
|
34
|
+
export function setSessionId(sessionId) {
|
|
35
|
+
globalSessionId = sessionId;
|
|
36
|
+
process.env.FLYWHEEL_SESSION_ID = sessionId;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Clear the session (start fresh)
|
|
40
|
+
*/
|
|
41
|
+
export function clearSession() {
|
|
42
|
+
globalSessionId = null;
|
|
43
|
+
delete process.env.FLYWHEEL_SESSION_ID;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create a child session for sub-workflows
|
|
47
|
+
*/
|
|
48
|
+
export function createChildSession(parentSession) {
|
|
49
|
+
const childId = randomBytes(4).toString('hex');
|
|
50
|
+
return `${parentSession}.${childId}`;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Extract parent session from child session ID
|
|
54
|
+
*/
|
|
55
|
+
export function getParentSession(sessionId) {
|
|
56
|
+
const parts = sessionId.split('.');
|
|
57
|
+
if (parts.length < 2) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
return parts.slice(0, -1).join('.');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if session ID is a child of another
|
|
64
|
+
*/
|
|
65
|
+
export function isChildSession(sessionId, parentId) {
|
|
66
|
+
return sessionId.startsWith(parentId + '.');
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=sessionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionManager.js","sourceRoot":"","sources":["../../src/logging/sessionManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,gEAAgE;IAChE,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IACnD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,sCAAsC;IACtC,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,eAAe,GAAG,iBAAiB,EAAE,CAAC;IACxC,CAAC;IAED,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,6BAA6B;AAC7B,IAAI,eAAe,GAAkB,IAAI,CAAC;AAE1C;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,eAAe,GAAG,SAAS,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,mBAAmB,GAAG,SAAS,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,eAAe,GAAG,IAAI,CAAC;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,aAAqB;IACtD,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,GAAG,aAAa,IAAI,OAAO,EAAE,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,QAAgB;IAChE,OAAO,SAAS,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared logging types for Flywheel ecosystem
|
|
3
|
+
*
|
|
4
|
+
* Used by both Flywheel (read) and Flywheel-Crank (write) for
|
|
5
|
+
* unified operation logging and metrics.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Product identifier for log entries
|
|
9
|
+
*/
|
|
10
|
+
export type ProductId = 'flywheel' | 'crank';
|
|
11
|
+
/**
|
|
12
|
+
* Single operation log entry
|
|
13
|
+
*/
|
|
14
|
+
export interface OperationLogEntry {
|
|
15
|
+
/** ISO timestamp */
|
|
16
|
+
ts: string;
|
|
17
|
+
/** Product that performed the operation */
|
|
18
|
+
product: ProductId;
|
|
19
|
+
/** Tool/function name */
|
|
20
|
+
tool: string;
|
|
21
|
+
/** Vault path (may be anonymized) */
|
|
22
|
+
vault: string;
|
|
23
|
+
/** Duration in milliseconds */
|
|
24
|
+
duration_ms: number;
|
|
25
|
+
/** Whether operation succeeded */
|
|
26
|
+
success: boolean;
|
|
27
|
+
/** Error message if failed */
|
|
28
|
+
error?: string;
|
|
29
|
+
/** Session ID for workflow correlation */
|
|
30
|
+
session?: string;
|
|
31
|
+
/** Number of results returned (for queries) */
|
|
32
|
+
results?: number;
|
|
33
|
+
/** Additional metadata */
|
|
34
|
+
metadata?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Session metrics for workflow tracking
|
|
38
|
+
*/
|
|
39
|
+
export interface SessionMetrics {
|
|
40
|
+
/** Session ID */
|
|
41
|
+
session: string;
|
|
42
|
+
/** Total duration in ms */
|
|
43
|
+
duration_ms: number;
|
|
44
|
+
/** Operations by product */
|
|
45
|
+
operations: {
|
|
46
|
+
flywheel: Record<string, number>;
|
|
47
|
+
crank: Record<string, number>;
|
|
48
|
+
};
|
|
49
|
+
/** Total operation count */
|
|
50
|
+
total_operations: number;
|
|
51
|
+
/** Success rate (0-100) */
|
|
52
|
+
success_rate: number;
|
|
53
|
+
/** First operation timestamp */
|
|
54
|
+
started: string;
|
|
55
|
+
/** Last operation timestamp */
|
|
56
|
+
ended: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Aggregated metrics over time period
|
|
60
|
+
*/
|
|
61
|
+
export interface AggregatedMetrics {
|
|
62
|
+
/** Period start (ISO) */
|
|
63
|
+
periodStart: string;
|
|
64
|
+
/** Period end (ISO) */
|
|
65
|
+
periodEnd: string;
|
|
66
|
+
/** Total operations */
|
|
67
|
+
totalOperations: number;
|
|
68
|
+
/** Successful operations */
|
|
69
|
+
successfulOperations: number;
|
|
70
|
+
/** Failed operations */
|
|
71
|
+
failedOperations: number;
|
|
72
|
+
/** Timing stats */
|
|
73
|
+
timing: {
|
|
74
|
+
mean_ms: number;
|
|
75
|
+
p50_ms: number;
|
|
76
|
+
p95_ms: number;
|
|
77
|
+
p99_ms: number;
|
|
78
|
+
min_ms: number;
|
|
79
|
+
max_ms: number;
|
|
80
|
+
};
|
|
81
|
+
/** Metrics by tool */
|
|
82
|
+
byTool: Record<string, {
|
|
83
|
+
count: number;
|
|
84
|
+
success_rate: number;
|
|
85
|
+
mean_ms: number;
|
|
86
|
+
p95_ms: number;
|
|
87
|
+
}>;
|
|
88
|
+
/** Metrics by product */
|
|
89
|
+
byProduct: Record<ProductId, {
|
|
90
|
+
count: number;
|
|
91
|
+
success_rate: number;
|
|
92
|
+
mean_ms: number;
|
|
93
|
+
}>;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Logging configuration
|
|
97
|
+
*/
|
|
98
|
+
export interface LoggingConfig {
|
|
99
|
+
/** Master switch (default: false) */
|
|
100
|
+
enabled: boolean;
|
|
101
|
+
/** Path to log file (relative to vault root) */
|
|
102
|
+
logPath: string;
|
|
103
|
+
/** Include tool names in logs */
|
|
104
|
+
includeToolNames: boolean;
|
|
105
|
+
/** Include timing data */
|
|
106
|
+
includeDurations: boolean;
|
|
107
|
+
/** Include session IDs for workflow correlation */
|
|
108
|
+
includeSessionIds: boolean;
|
|
109
|
+
/** Include result counts (may reveal vault size) */
|
|
110
|
+
includeResults: boolean;
|
|
111
|
+
/** Log rotation settings */
|
|
112
|
+
rotation?: {
|
|
113
|
+
maxSize: string;
|
|
114
|
+
maxFiles: number;
|
|
115
|
+
};
|
|
116
|
+
/** Retention in days */
|
|
117
|
+
retentionDays?: number;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Default logging configuration (disabled by default)
|
|
121
|
+
*/
|
|
122
|
+
export declare const DEFAULT_LOGGING_CONFIG: LoggingConfig;
|
|
123
|
+
//# sourceMappingURL=types.d.ts.map
|