crewly 1.8.7 → 1.8.9
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/backend/backend/src/constants.d.ts +12 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +12 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/browser/browser.controller.js +17 -0
- package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +8 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +15 -7
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts +7 -0
- package/dist/backend/backend/src/services/browser/browser-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js +69 -12
- package/dist/backend/backend/src/services/browser/browser-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts +122 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js +252 -17
- package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.d.ts +37 -3
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.js +140 -23
- package/dist/backend/backend/src/services/browser/browser-relay-adapter.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts +75 -0
- package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-client.service.js +164 -12
- package/dist/backend/backend/src/services/cloud/cloud-client.service.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +12 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +12 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/cli/src/index.js +0 -0
- package/package.json +1 -1
- package/config/constants.d.ts.map +0 -1
- package/config/index.d.ts.map +0 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +0 -169
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +0 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +0 -1779
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts +0 -513
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js +0 -1568
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-runner.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts +0 -86
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js +0 -147
- package/dist/backend/backend/src/services/agent/crewly-agent/agent-worker.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts +0 -68
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js +0 -131
- package/dist/backend/backend/src/services/agent/crewly-agent/api-client.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts +0 -130
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js +0 -263
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-log.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts +0 -74
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js +0 -140
- package/dist/backend/backend/src/services/agent/crewly-agent/audit-trail.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts +0 -29
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js +0 -279
- package/dist/backend/backend/src/services/agent/crewly-agent/auditor-tools.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts +0 -340
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js +0 -1176
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-runtime.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts +0 -79
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js +0 -145
- package/dist/backend/backend/src/services/agent/crewly-agent/deepseek-sse-transform.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts +0 -79
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js +0 -218
- package/dist/backend/backend/src/services/agent/crewly-agent/env-isolation.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts +0 -16
- package/dist/backend/backend/src/services/agent/crewly-agent/index.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/index.js +0 -16
- package/dist/backend/backend/src/services/agent/crewly-agent/index.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts +0 -135
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js +0 -185
- package/dist/backend/backend/src/services/agent/crewly-agent/mcp-tool-bridge.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts +0 -141
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js +0 -310
- package/dist/backend/backend/src/services/agent/crewly-agent/model-manager.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts +0 -91
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js +0 -143
- package/dist/backend/backend/src/services/agent/crewly-agent/output-filter.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts +0 -103
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js +0 -256
- package/dist/backend/backend/src/services/agent/crewly-agent/prompt-guard.service.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts +0 -143
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js +0 -264
- package/dist/backend/backend/src/services/agent/crewly-agent/rate-limiter.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts +0 -13
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js +0 -91
- package/dist/backend/backend/src/services/agent/crewly-agent/smoke-test.js.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts +0 -135
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.d.ts.map +0 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js +0 -1937
- package/dist/backend/backend/src/services/agent/crewly-agent/tool-registry.js.map +0 -1
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts +0 -429
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.js +0 -852
- package/dist/backend/backend/src/services/autonomous/auto-assign.service.js.map +0 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +0 -171
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.js +0 -725
- package/dist/backend/backend/src/services/project/task-tracking.service.js.map +0 -1
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts +0 -118
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.js +0 -326
- package/dist/backend/backend/src/services/v3/project-task-watcher.service.js.map +0 -1
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts +0 -74
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts.map +0 -1
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js +0 -154
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js.map +0 -1
- package/dist/backend/backend/src/types/auto-assign.types.d.ts +0 -271
- package/dist/backend/backend/src/types/auto-assign.types.d.ts.map +0 -1
- package/dist/backend/backend/src/types/auto-assign.types.js +0 -136
- package/dist/backend/backend/src/types/auto-assign.types.js.map +0 -1
- package/dist/backend/backend/src/utils/esm-require.utils.d.ts +0 -111
- package/dist/backend/backend/src/utils/esm-require.utils.d.ts.map +0 -1
- package/dist/backend/backend/src/utils/esm-require.utils.js +0 -124
- package/dist/backend/backend/src/utils/esm-require.utils.js.map +0 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts +0 -220
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts.map +0 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js +0 -37
- package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts +0 -56
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js +0 -91
- package/dist/cli/backend/src/services/knowledge/fts5-search-strategy.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts +0 -159
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.js +0 -304
- package/dist/cli/backend/src/services/knowledge/learnings-index.service.js.map +0 -1
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts +0 -115
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js +0 -215
- package/dist/cli/backend/src/services/knowledge/wiki-compiler.service.js.map +0 -1
- package/dist/cli/backend/src/services/memory/embedding-provider.d.ts +0 -78
- package/dist/cli/backend/src/services/memory/embedding-provider.d.ts.map +0 -1
- package/dist/cli/backend/src/services/memory/embedding-provider.js +0 -179
- package/dist/cli/backend/src/services/memory/embedding-provider.js.map +0 -1
- package/dist/cli/backend/src/services/memory/vector-store.service.d.ts +0 -331
- package/dist/cli/backend/src/services/memory/vector-store.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/memory/vector-store.service.js +0 -814
- package/dist/cli/backend/src/services/memory/vector-store.service.js.map +0 -1
- package/dist/cli/backend/src/services/project/task-tracking.service.d.ts +0 -171
- package/dist/cli/backend/src/services/project/task-tracking.service.d.ts.map +0 -1
- package/dist/cli/backend/src/services/project/task-tracking.service.js +0 -725
- package/dist/cli/backend/src/services/project/task-tracking.service.js.map +0 -1
- package/dist/cli/backend/src/types/auto-assign.types.d.ts +0 -271
- package/dist/cli/backend/src/types/auto-assign.types.d.ts.map +0 -1
- package/dist/cli/backend/src/types/auto-assign.types.js +0 -136
- package/dist/cli/backend/src/types/auto-assign.types.js.map +0 -1
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Persistent Audit Log Service (SQLite)
|
|
3
|
-
*
|
|
4
|
-
* Provides durable, queryable audit logging using better-sqlite3.
|
|
5
|
-
* Replaces the append-only JSONL approach with a proper relational store
|
|
6
|
-
* that supports efficient filtering, pagination, and aggregation.
|
|
7
|
-
*
|
|
8
|
-
* Single WAL-mode database shared across all sessions. Thread-safe for
|
|
9
|
-
* the single-threaded Node.js event loop (better-sqlite3 is synchronous).
|
|
10
|
-
*
|
|
11
|
-
* @module services/agent/crewly-agent/audit-log.service
|
|
12
|
-
*/
|
|
13
|
-
import type { AuditEntry, AuditLogFilters, ToolSensitivity } from './types.js';
|
|
14
|
-
/**
|
|
15
|
-
* Extended audit entry stored in the database.
|
|
16
|
-
* Adds an auto-incremented row ID and an action field for approval events.
|
|
17
|
-
*/
|
|
18
|
-
export interface AuditLogRow extends AuditEntry {
|
|
19
|
-
/** Auto-incremented row ID */
|
|
20
|
-
id: number;
|
|
21
|
-
/** Action type: 'tool_call' | 'approval_granted' | 'approval_rejected' | 'approval_expired' */
|
|
22
|
-
action: string;
|
|
23
|
-
/** Who resolved an approval (e.g. 'api', 'auditor', 'auto-expire') */
|
|
24
|
-
resolvedBy?: string;
|
|
25
|
-
/** Approval ID if this entry relates to an approval event */
|
|
26
|
-
approvalId?: string;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Query filters for the audit log, extending the base AuditLogFilters.
|
|
30
|
-
*/
|
|
31
|
-
export interface AuditLogQueryFilters extends AuditLogFilters {
|
|
32
|
-
/** Filter by session name */
|
|
33
|
-
sessionName?: string;
|
|
34
|
-
/** Filter by action type */
|
|
35
|
-
action?: string;
|
|
36
|
-
/** Filter entries after this ISO timestamp */
|
|
37
|
-
since?: string;
|
|
38
|
-
/** Filter entries before this ISO timestamp */
|
|
39
|
-
until?: string;
|
|
40
|
-
/** Offset for pagination */
|
|
41
|
-
offset?: number;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* SQLite-backed persistent audit log service.
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* ```typescript
|
|
48
|
-
* const log = new AuditLogService('/path/to/.crewly');
|
|
49
|
-
* log.initialize();
|
|
50
|
-
* log.append(auditEntry);
|
|
51
|
-
* log.logApprovalEvent('approval-123', 'session-1', 'edit_file', 'destructive', 'approved', 'api');
|
|
52
|
-
* const entries = log.query({ limit: 50, sessionName: 'session-1' });
|
|
53
|
-
* log.close();
|
|
54
|
-
* ```
|
|
55
|
-
*/
|
|
56
|
-
export declare class AuditLogService {
|
|
57
|
-
private db;
|
|
58
|
-
private dbPath;
|
|
59
|
-
private initialized;
|
|
60
|
-
/** Prepared statements for performance */
|
|
61
|
-
private stmtInsert;
|
|
62
|
-
private stmtInsertApproval;
|
|
63
|
-
/**
|
|
64
|
-
* Create a new AuditLogService.
|
|
65
|
-
*
|
|
66
|
-
* @param crewlyHome - Path to the .crewly directory
|
|
67
|
-
* @param dbFilename - Database filename (default: audit-log.sqlite)
|
|
68
|
-
*/
|
|
69
|
-
constructor(crewlyHome: string, dbFilename?: string);
|
|
70
|
-
/**
|
|
71
|
-
* Initialize the database, creating tables if needed.
|
|
72
|
-
* Enables WAL mode for better concurrent read performance.
|
|
73
|
-
*/
|
|
74
|
-
initialize(): void;
|
|
75
|
-
/**
|
|
76
|
-
* Append a tool-call audit entry.
|
|
77
|
-
*
|
|
78
|
-
* @param entry - The AuditEntry from the agent runtime
|
|
79
|
-
*/
|
|
80
|
-
append(entry: AuditEntry): void;
|
|
81
|
-
/**
|
|
82
|
-
* Log an approval lifecycle event (granted, rejected, expired).
|
|
83
|
-
*
|
|
84
|
-
* @param approvalId - The approval request ID
|
|
85
|
-
* @param sessionName - Agent session name
|
|
86
|
-
* @param toolName - Tool that was approved/rejected
|
|
87
|
-
* @param sensitivity - Sensitivity classification
|
|
88
|
-
* @param action - 'approval_granted' | 'approval_rejected' | 'approval_expired'
|
|
89
|
-
* @param resolvedBy - Who resolved it
|
|
90
|
-
*/
|
|
91
|
-
logApprovalEvent(approvalId: string, sessionName: string, toolName: string, sensitivity: ToolSensitivity, action: 'approval_granted' | 'approval_rejected' | 'approval_expired', resolvedBy: string): void;
|
|
92
|
-
/**
|
|
93
|
-
* Query audit log entries with filters and pagination.
|
|
94
|
-
*
|
|
95
|
-
* @param filters - Query filters
|
|
96
|
-
* @returns Array of audit log rows, most recent first
|
|
97
|
-
*/
|
|
98
|
-
query(filters: AuditLogQueryFilters): AuditLogRow[];
|
|
99
|
-
/**
|
|
100
|
-
* Get total count of entries matching filters (for pagination).
|
|
101
|
-
*
|
|
102
|
-
* @param filters - Same filters as query (limit/offset ignored)
|
|
103
|
-
* @returns Total matching row count
|
|
104
|
-
*/
|
|
105
|
-
count(filters?: Partial<AuditLogQueryFilters>): number;
|
|
106
|
-
/**
|
|
107
|
-
* Get the database file path.
|
|
108
|
-
*
|
|
109
|
-
* @returns Absolute path to the SQLite database
|
|
110
|
-
*/
|
|
111
|
-
getDbPath(): string;
|
|
112
|
-
/**
|
|
113
|
-
* Check if the service is initialized.
|
|
114
|
-
*
|
|
115
|
-
* @returns True if initialize() has been called
|
|
116
|
-
*/
|
|
117
|
-
isInitialized(): boolean;
|
|
118
|
-
/**
|
|
119
|
-
* Close the database connection.
|
|
120
|
-
* Safe to call multiple times.
|
|
121
|
-
*/
|
|
122
|
-
close(): void;
|
|
123
|
-
/**
|
|
124
|
-
* Ensure the service is initialized before operations.
|
|
125
|
-
*
|
|
126
|
-
* @throws Error if not initialized
|
|
127
|
-
*/
|
|
128
|
-
private ensureInitialized;
|
|
129
|
-
}
|
|
130
|
-
//# sourceMappingURL=audit-log.service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-log.service.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/agent/crewly-agent/audit-log.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAW/E;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,8BAA8B;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,+FAA+F;IAC/F,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IAC3D,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,EAAE,CAAkC;IAC5C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAS;IAE5B,0CAA0C;IAC1C,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,kBAAkB,CAAmC;IAE7D;;;;;OAKG;gBACS,UAAU,EAAE,MAAM,EAAE,UAAU,GAAE,MAAoB;IAKhE;;;OAGG;IACH,UAAU,IAAI,IAAI;IA8ClB;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAc/B;;;;;;;;;OASG;IACH,gBAAgB,CACd,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,eAAe,EAC5B,MAAM,EAAE,kBAAkB,GAAG,mBAAmB,GAAG,kBAAkB,EACrE,UAAU,EAAE,MAAM,GACjB,IAAI;IAcP;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,oBAAoB,GAAG,WAAW,EAAE;IAiEnD;;;;;OAKG;IACH,KAAK,CAAC,OAAO,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAAG,MAAM;IAqB1D;;;;OAIG;IACH,SAAS,IAAI,MAAM;IAInB;;;;OAIG;IACH,aAAa,IAAI,OAAO;IAIxB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAUb;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;CAK1B"}
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Persistent Audit Log Service (SQLite)
|
|
3
|
-
*
|
|
4
|
-
* Provides durable, queryable audit logging using better-sqlite3.
|
|
5
|
-
* Replaces the append-only JSONL approach with a proper relational store
|
|
6
|
-
* that supports efficient filtering, pagination, and aggregation.
|
|
7
|
-
*
|
|
8
|
-
* Single WAL-mode database shared across all sessions. Thread-safe for
|
|
9
|
-
* the single-threaded Node.js event loop (better-sqlite3 is synchronous).
|
|
10
|
-
*
|
|
11
|
-
* @module services/agent/crewly-agent/audit-log.service
|
|
12
|
-
*/
|
|
13
|
-
import Database from 'better-sqlite3';
|
|
14
|
-
import { join } from 'path';
|
|
15
|
-
import { mkdirSync } from 'fs';
|
|
16
|
-
/** Default database filename */
|
|
17
|
-
const DB_FILENAME = 'audit-log.sqlite';
|
|
18
|
-
/** Default directory under .crewly */
|
|
19
|
-
const AUDIT_DIR = 'audit-logs';
|
|
20
|
-
/** Maximum rows returned by a single query */
|
|
21
|
-
const MAX_QUERY_LIMIT = 10000;
|
|
22
|
-
/**
|
|
23
|
-
* SQLite-backed persistent audit log service.
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```typescript
|
|
27
|
-
* const log = new AuditLogService('/path/to/.crewly');
|
|
28
|
-
* log.initialize();
|
|
29
|
-
* log.append(auditEntry);
|
|
30
|
-
* log.logApprovalEvent('approval-123', 'session-1', 'edit_file', 'destructive', 'approved', 'api');
|
|
31
|
-
* const entries = log.query({ limit: 50, sessionName: 'session-1' });
|
|
32
|
-
* log.close();
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export class AuditLogService {
|
|
36
|
-
db = null;
|
|
37
|
-
dbPath;
|
|
38
|
-
initialized = false;
|
|
39
|
-
/** Prepared statements for performance */
|
|
40
|
-
stmtInsert = null;
|
|
41
|
-
stmtInsertApproval = null;
|
|
42
|
-
/**
|
|
43
|
-
* Create a new AuditLogService.
|
|
44
|
-
*
|
|
45
|
-
* @param crewlyHome - Path to the .crewly directory
|
|
46
|
-
* @param dbFilename - Database filename (default: audit-log.sqlite)
|
|
47
|
-
*/
|
|
48
|
-
constructor(crewlyHome, dbFilename = DB_FILENAME) {
|
|
49
|
-
const dir = join(crewlyHome, AUDIT_DIR);
|
|
50
|
-
this.dbPath = join(dir, dbFilename);
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Initialize the database, creating tables if needed.
|
|
54
|
-
* Enables WAL mode for better concurrent read performance.
|
|
55
|
-
*/
|
|
56
|
-
initialize() {
|
|
57
|
-
if (this.initialized)
|
|
58
|
-
return;
|
|
59
|
-
// Ensure directory exists
|
|
60
|
-
const dir = join(this.dbPath, '..');
|
|
61
|
-
mkdirSync(dir, { recursive: true });
|
|
62
|
-
this.db = new Database(this.dbPath);
|
|
63
|
-
this.db.pragma('journal_mode = WAL');
|
|
64
|
-
this.db.pragma('foreign_keys = ON');
|
|
65
|
-
this.db.exec(`
|
|
66
|
-
CREATE TABLE IF NOT EXISTS audit_log (
|
|
67
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
68
|
-
timestamp TEXT NOT NULL,
|
|
69
|
-
session_name TEXT,
|
|
70
|
-
tool_name TEXT NOT NULL,
|
|
71
|
-
sensitivity TEXT NOT NULL,
|
|
72
|
-
args TEXT NOT NULL DEFAULT '{}',
|
|
73
|
-
success INTEGER NOT NULL DEFAULT 1,
|
|
74
|
-
error TEXT,
|
|
75
|
-
duration_ms REAL NOT NULL DEFAULT 0,
|
|
76
|
-
action TEXT NOT NULL DEFAULT 'tool_call',
|
|
77
|
-
resolved_by TEXT,
|
|
78
|
-
approval_id TEXT
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_log(timestamp);
|
|
82
|
-
CREATE INDEX IF NOT EXISTS idx_audit_session ON audit_log(session_name);
|
|
83
|
-
CREATE INDEX IF NOT EXISTS idx_audit_action ON audit_log(action);
|
|
84
|
-
CREATE INDEX IF NOT EXISTS idx_audit_tool ON audit_log(tool_name);
|
|
85
|
-
`);
|
|
86
|
-
this.stmtInsert = this.db.prepare(`
|
|
87
|
-
INSERT INTO audit_log (timestamp, session_name, tool_name, sensitivity, args, success, error, duration_ms, action)
|
|
88
|
-
VALUES (@timestamp, @sessionName, @toolName, @sensitivity, @args, @success, @error, @durationMs, 'tool_call')
|
|
89
|
-
`);
|
|
90
|
-
this.stmtInsertApproval = this.db.prepare(`
|
|
91
|
-
INSERT INTO audit_log (timestamp, session_name, tool_name, sensitivity, args, success, duration_ms, action, resolved_by, approval_id)
|
|
92
|
-
VALUES (@timestamp, @sessionName, @toolName, @sensitivity, @args, 1, 0, @action, @resolvedBy, @approvalId)
|
|
93
|
-
`);
|
|
94
|
-
this.initialized = true;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Append a tool-call audit entry.
|
|
98
|
-
*
|
|
99
|
-
* @param entry - The AuditEntry from the agent runtime
|
|
100
|
-
*/
|
|
101
|
-
append(entry) {
|
|
102
|
-
this.ensureInitialized();
|
|
103
|
-
this.stmtInsert.run({
|
|
104
|
-
timestamp: entry.timestamp,
|
|
105
|
-
sessionName: entry.sessionName ?? null,
|
|
106
|
-
toolName: entry.toolName,
|
|
107
|
-
sensitivity: entry.sensitivity,
|
|
108
|
-
args: JSON.stringify(entry.args),
|
|
109
|
-
success: entry.success ? 1 : 0,
|
|
110
|
-
error: entry.error ?? null,
|
|
111
|
-
durationMs: entry.durationMs,
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Log an approval lifecycle event (granted, rejected, expired).
|
|
116
|
-
*
|
|
117
|
-
* @param approvalId - The approval request ID
|
|
118
|
-
* @param sessionName - Agent session name
|
|
119
|
-
* @param toolName - Tool that was approved/rejected
|
|
120
|
-
* @param sensitivity - Sensitivity classification
|
|
121
|
-
* @param action - 'approval_granted' | 'approval_rejected' | 'approval_expired'
|
|
122
|
-
* @param resolvedBy - Who resolved it
|
|
123
|
-
*/
|
|
124
|
-
logApprovalEvent(approvalId, sessionName, toolName, sensitivity, action, resolvedBy) {
|
|
125
|
-
this.ensureInitialized();
|
|
126
|
-
this.stmtInsertApproval.run({
|
|
127
|
-
timestamp: new Date().toISOString(),
|
|
128
|
-
sessionName,
|
|
129
|
-
toolName,
|
|
130
|
-
sensitivity,
|
|
131
|
-
args: '{}',
|
|
132
|
-
action,
|
|
133
|
-
resolvedBy,
|
|
134
|
-
approvalId,
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Query audit log entries with filters and pagination.
|
|
139
|
-
*
|
|
140
|
-
* @param filters - Query filters
|
|
141
|
-
* @returns Array of audit log rows, most recent first
|
|
142
|
-
*/
|
|
143
|
-
query(filters) {
|
|
144
|
-
this.ensureInitialized();
|
|
145
|
-
const conditions = [];
|
|
146
|
-
const params = {};
|
|
147
|
-
if (filters.sessionName) {
|
|
148
|
-
conditions.push('session_name = @sessionName');
|
|
149
|
-
params.sessionName = filters.sessionName;
|
|
150
|
-
}
|
|
151
|
-
if (filters.sensitivity) {
|
|
152
|
-
conditions.push('sensitivity = @sensitivity');
|
|
153
|
-
params.sensitivity = filters.sensitivity;
|
|
154
|
-
}
|
|
155
|
-
if (filters.toolName) {
|
|
156
|
-
conditions.push('tool_name = @toolName');
|
|
157
|
-
params.toolName = filters.toolName;
|
|
158
|
-
}
|
|
159
|
-
if (filters.action) {
|
|
160
|
-
conditions.push('action = @action');
|
|
161
|
-
params.action = filters.action;
|
|
162
|
-
}
|
|
163
|
-
if (filters.since) {
|
|
164
|
-
conditions.push('timestamp >= @since');
|
|
165
|
-
params.since = filters.since;
|
|
166
|
-
}
|
|
167
|
-
if (filters.until) {
|
|
168
|
-
conditions.push('timestamp <= @until');
|
|
169
|
-
params.until = filters.until;
|
|
170
|
-
}
|
|
171
|
-
const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
172
|
-
const limit = Math.min(filters.limit || 100, MAX_QUERY_LIMIT);
|
|
173
|
-
const offset = filters.offset || 0;
|
|
174
|
-
const sql = `
|
|
175
|
-
SELECT id, timestamp, session_name, tool_name, sensitivity, args,
|
|
176
|
-
success, error, duration_ms, action, resolved_by, approval_id
|
|
177
|
-
FROM audit_log
|
|
178
|
-
${where}
|
|
179
|
-
ORDER BY id DESC
|
|
180
|
-
LIMIT @limit OFFSET @offset
|
|
181
|
-
`;
|
|
182
|
-
params.limit = limit;
|
|
183
|
-
params.offset = offset;
|
|
184
|
-
const rows = this.db.prepare(sql).all(params);
|
|
185
|
-
return rows.map(row => ({
|
|
186
|
-
id: row.id,
|
|
187
|
-
timestamp: row.timestamp,
|
|
188
|
-
sessionName: row.session_name,
|
|
189
|
-
toolName: row.tool_name,
|
|
190
|
-
sensitivity: row.sensitivity,
|
|
191
|
-
args: JSON.parse(row.args || '{}'),
|
|
192
|
-
success: row.success === 1,
|
|
193
|
-
error: row.error,
|
|
194
|
-
durationMs: row.duration_ms,
|
|
195
|
-
action: row.action,
|
|
196
|
-
resolvedBy: row.resolved_by,
|
|
197
|
-
approvalId: row.approval_id,
|
|
198
|
-
}));
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Get total count of entries matching filters (for pagination).
|
|
202
|
-
*
|
|
203
|
-
* @param filters - Same filters as query (limit/offset ignored)
|
|
204
|
-
* @returns Total matching row count
|
|
205
|
-
*/
|
|
206
|
-
count(filters = {}) {
|
|
207
|
-
this.ensureInitialized();
|
|
208
|
-
const conditions = [];
|
|
209
|
-
const params = {};
|
|
210
|
-
if (filters.sessionName) {
|
|
211
|
-
conditions.push('session_name = @sessionName');
|
|
212
|
-
params.sessionName = filters.sessionName;
|
|
213
|
-
}
|
|
214
|
-
if (filters.action) {
|
|
215
|
-
conditions.push('action = @action');
|
|
216
|
-
params.action = filters.action;
|
|
217
|
-
}
|
|
218
|
-
const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
219
|
-
const sql = `SELECT COUNT(*) as cnt FROM audit_log ${where}`;
|
|
220
|
-
const row = this.db.prepare(sql).get(params);
|
|
221
|
-
return row.cnt;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Get the database file path.
|
|
225
|
-
*
|
|
226
|
-
* @returns Absolute path to the SQLite database
|
|
227
|
-
*/
|
|
228
|
-
getDbPath() {
|
|
229
|
-
return this.dbPath;
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Check if the service is initialized.
|
|
233
|
-
*
|
|
234
|
-
* @returns True if initialize() has been called
|
|
235
|
-
*/
|
|
236
|
-
isInitialized() {
|
|
237
|
-
return this.initialized;
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Close the database connection.
|
|
241
|
-
* Safe to call multiple times.
|
|
242
|
-
*/
|
|
243
|
-
close() {
|
|
244
|
-
if (this.db) {
|
|
245
|
-
this.db.close();
|
|
246
|
-
this.db = null;
|
|
247
|
-
this.stmtInsert = null;
|
|
248
|
-
this.stmtInsertApproval = null;
|
|
249
|
-
this.initialized = false;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Ensure the service is initialized before operations.
|
|
254
|
-
*
|
|
255
|
-
* @throws Error if not initialized
|
|
256
|
-
*/
|
|
257
|
-
ensureInitialized() {
|
|
258
|
-
if (!this.initialized || !this.db) {
|
|
259
|
-
throw new Error('AuditLogService not initialized. Call initialize() first.');
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
//# sourceMappingURL=audit-log.service.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-log.service.js","sourceRoot":"","sources":["../../../../../../../backend/src/services/agent/crewly-agent/audit-log.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Audit Trail Service
|
|
3
|
-
*
|
|
4
|
-
* Provides file-based persistence for the security audit trail.
|
|
5
|
-
* Writes audit entries as append-only JSONL (one JSON object per line)
|
|
6
|
-
* for structured, queryable audit logging.
|
|
7
|
-
*
|
|
8
|
-
* @module services/agent/crewly-agent/audit-trail.service
|
|
9
|
-
*/
|
|
10
|
-
import type { AuditEntry, AuditLogFilters } from './types.js';
|
|
11
|
-
/**
|
|
12
|
-
* File-based audit trail service.
|
|
13
|
-
*
|
|
14
|
-
* Persists audit entries as append-only JSONL files organized by session.
|
|
15
|
-
* Each session gets its own log file for easy per-agent auditing.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```typescript
|
|
19
|
-
* const trail = new AuditTrailService('/path/to/.crewly', 'agent-session-1');
|
|
20
|
-
* await trail.initialize();
|
|
21
|
-
* await trail.append(auditEntry);
|
|
22
|
-
* const entries = await trail.query({ limit: 50 });
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export declare class AuditTrailService {
|
|
26
|
-
private crewlyHome;
|
|
27
|
-
private sessionName;
|
|
28
|
-
private logDir;
|
|
29
|
-
private logFile;
|
|
30
|
-
private initialized;
|
|
31
|
-
/**
|
|
32
|
-
* Create a new AuditTrailService.
|
|
33
|
-
*
|
|
34
|
-
* @param crewlyHome - Path to the .crewly directory
|
|
35
|
-
* @param sessionName - Agent session name for log file naming
|
|
36
|
-
*/
|
|
37
|
-
constructor(crewlyHome: string, sessionName: string);
|
|
38
|
-
/**
|
|
39
|
-
* Initialize the audit trail by ensuring the log directory exists.
|
|
40
|
-
*
|
|
41
|
-
* @throws Error if directory creation fails
|
|
42
|
-
*/
|
|
43
|
-
initialize(): Promise<void>;
|
|
44
|
-
/**
|
|
45
|
-
* Append an audit entry to the log file.
|
|
46
|
-
*
|
|
47
|
-
* @param entry - Audit entry to persist
|
|
48
|
-
* @throws Error if not initialized or write fails
|
|
49
|
-
*/
|
|
50
|
-
append(entry: AuditEntry): Promise<void>;
|
|
51
|
-
/**
|
|
52
|
-
* Query persisted audit entries with optional filters.
|
|
53
|
-
*
|
|
54
|
-
* Reads the log file and returns matching entries in reverse
|
|
55
|
-
* chronological order (most recent first).
|
|
56
|
-
*
|
|
57
|
-
* @param filters - Query filters for limit, sensitivity, and toolName
|
|
58
|
-
* @returns Filtered audit entries
|
|
59
|
-
*/
|
|
60
|
-
query(filters: AuditLogFilters): Promise<AuditEntry[]>;
|
|
61
|
-
/**
|
|
62
|
-
* Get the path to the audit log file.
|
|
63
|
-
*
|
|
64
|
-
* @returns Absolute path to the JSONL log file
|
|
65
|
-
*/
|
|
66
|
-
getLogFilePath(): string;
|
|
67
|
-
/**
|
|
68
|
-
* Check if the service has been initialized.
|
|
69
|
-
*
|
|
70
|
-
* @returns True if initialize() has been called successfully
|
|
71
|
-
*/
|
|
72
|
-
isInitialized(): boolean;
|
|
73
|
-
}
|
|
74
|
-
//# sourceMappingURL=audit-trail.service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-trail.service.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/agent/crewly-agent/audit-trail.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAQ9D;;;;;;;;;;;;;GAaG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAS;IAE5B;;;;;OAKG;gBACS,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAOnD;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C;;;;;;;;OAQG;IACG,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAmC5D;;;;OAIG;IACH,cAAc,IAAI,MAAM;IAIxB;;;;OAIG;IACH,aAAa,IAAI,OAAO;CAGzB"}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Audit Trail Service
|
|
3
|
-
*
|
|
4
|
-
* Provides file-based persistence for the security audit trail.
|
|
5
|
-
* Writes audit entries as append-only JSONL (one JSON object per line)
|
|
6
|
-
* for structured, queryable audit logging.
|
|
7
|
-
*
|
|
8
|
-
* @module services/agent/crewly-agent/audit-trail.service
|
|
9
|
-
*/
|
|
10
|
-
import { promises as fsPromises } from 'fs';
|
|
11
|
-
import { join } from 'path';
|
|
12
|
-
/** Default directory name for audit logs under .crewly */
|
|
13
|
-
const AUDIT_DIR = 'audit-logs';
|
|
14
|
-
/** Maximum lines to read when querying the log file */
|
|
15
|
-
const MAX_QUERY_LINES = 10000;
|
|
16
|
-
/**
|
|
17
|
-
* File-based audit trail service.
|
|
18
|
-
*
|
|
19
|
-
* Persists audit entries as append-only JSONL files organized by session.
|
|
20
|
-
* Each session gets its own log file for easy per-agent auditing.
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```typescript
|
|
24
|
-
* const trail = new AuditTrailService('/path/to/.crewly', 'agent-session-1');
|
|
25
|
-
* await trail.initialize();
|
|
26
|
-
* await trail.append(auditEntry);
|
|
27
|
-
* const entries = await trail.query({ limit: 50 });
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
export class AuditTrailService {
|
|
31
|
-
crewlyHome;
|
|
32
|
-
sessionName;
|
|
33
|
-
logDir;
|
|
34
|
-
logFile;
|
|
35
|
-
initialized = false;
|
|
36
|
-
/**
|
|
37
|
-
* Create a new AuditTrailService.
|
|
38
|
-
*
|
|
39
|
-
* @param crewlyHome - Path to the .crewly directory
|
|
40
|
-
* @param sessionName - Agent session name for log file naming
|
|
41
|
-
*/
|
|
42
|
-
constructor(crewlyHome, sessionName) {
|
|
43
|
-
this.crewlyHome = crewlyHome;
|
|
44
|
-
this.sessionName = sessionName;
|
|
45
|
-
this.logDir = join(crewlyHome, AUDIT_DIR);
|
|
46
|
-
this.logFile = join(this.logDir, `${sanitizeFilename(sessionName)}.jsonl`);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Initialize the audit trail by ensuring the log directory exists.
|
|
50
|
-
*
|
|
51
|
-
* @throws Error if directory creation fails
|
|
52
|
-
*/
|
|
53
|
-
async initialize() {
|
|
54
|
-
await fsPromises.mkdir(this.logDir, { recursive: true });
|
|
55
|
-
this.initialized = true;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Append an audit entry to the log file.
|
|
59
|
-
*
|
|
60
|
-
* @param entry - Audit entry to persist
|
|
61
|
-
* @throws Error if not initialized or write fails
|
|
62
|
-
*/
|
|
63
|
-
async append(entry) {
|
|
64
|
-
if (!this.initialized) {
|
|
65
|
-
throw new Error('AuditTrailService not initialized. Call initialize() first.');
|
|
66
|
-
}
|
|
67
|
-
const line = JSON.stringify(entry) + '\n';
|
|
68
|
-
await fsPromises.appendFile(this.logFile, line, 'utf8');
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Query persisted audit entries with optional filters.
|
|
72
|
-
*
|
|
73
|
-
* Reads the log file and returns matching entries in reverse
|
|
74
|
-
* chronological order (most recent first).
|
|
75
|
-
*
|
|
76
|
-
* @param filters - Query filters for limit, sensitivity, and toolName
|
|
77
|
-
* @returns Filtered audit entries
|
|
78
|
-
*/
|
|
79
|
-
async query(filters) {
|
|
80
|
-
if (!this.initialized) {
|
|
81
|
-
throw new Error('AuditTrailService not initialized. Call initialize() first.');
|
|
82
|
-
}
|
|
83
|
-
let content;
|
|
84
|
-
try {
|
|
85
|
-
content = await fsPromises.readFile(this.logFile, 'utf8');
|
|
86
|
-
}
|
|
87
|
-
catch (err) {
|
|
88
|
-
// File doesn't exist yet — no entries
|
|
89
|
-
if (err.code === 'ENOENT') {
|
|
90
|
-
return [];
|
|
91
|
-
}
|
|
92
|
-
throw err;
|
|
93
|
-
}
|
|
94
|
-
const lines = content.trim().split('\n').filter(Boolean);
|
|
95
|
-
// Parse from end (most recent first), apply filters
|
|
96
|
-
let entries = [];
|
|
97
|
-
const startIdx = Math.max(0, lines.length - MAX_QUERY_LINES);
|
|
98
|
-
for (let i = lines.length - 1; i >= startIdx && entries.length < filters.limit; i--) {
|
|
99
|
-
try {
|
|
100
|
-
const entry = JSON.parse(lines[i]);
|
|
101
|
-
if (filters.sensitivity && entry.sensitivity !== filters.sensitivity)
|
|
102
|
-
continue;
|
|
103
|
-
if (filters.toolName && entry.toolName !== filters.toolName)
|
|
104
|
-
continue;
|
|
105
|
-
entries.push(entry);
|
|
106
|
-
}
|
|
107
|
-
catch {
|
|
108
|
-
// Skip malformed lines
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return entries;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Get the path to the audit log file.
|
|
115
|
-
*
|
|
116
|
-
* @returns Absolute path to the JSONL log file
|
|
117
|
-
*/
|
|
118
|
-
getLogFilePath() {
|
|
119
|
-
return this.logFile;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Check if the service has been initialized.
|
|
123
|
-
*
|
|
124
|
-
* @returns True if initialize() has been called successfully
|
|
125
|
-
*/
|
|
126
|
-
isInitialized() {
|
|
127
|
-
return this.initialized;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Sanitize a session name for use as a filename.
|
|
132
|
-
* Replaces non-alphanumeric characters (except hyphens and underscores) with hyphens.
|
|
133
|
-
*
|
|
134
|
-
* @param name - Raw session name
|
|
135
|
-
* @returns Sanitized filename-safe string
|
|
136
|
-
*/
|
|
137
|
-
function sanitizeFilename(name) {
|
|
138
|
-
return name.replace(/[^a-zA-Z0-9_-]/g, '-');
|
|
139
|
-
}
|
|
140
|
-
//# sourceMappingURL=audit-trail.service.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit-trail.service.js","sourceRoot":"","sources":["../../../../../../../backend/src/services/agent/crewly-agent/audit-trail.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Crewly Auditor Tool Registry
|
|
3
|
-
*
|
|
4
|
-
* Read-only tools for the Auditor agent. These tools allow the auditor
|
|
5
|
-
* to observe agent activity, read logs, check task alignment, and write
|
|
6
|
-
* structured bug reports — without any ability to modify system state.
|
|
7
|
-
*
|
|
8
|
-
* @module services/agent/crewly-agent/auditor-tools
|
|
9
|
-
*/
|
|
10
|
-
import type { CrewlyApiClient } from './api-client.js';
|
|
11
|
-
import type { ToolDefinition } from './types.js';
|
|
12
|
-
/**
|
|
13
|
-
* Create the auditor tool set for the Crewly Auditor agent.
|
|
14
|
-
*
|
|
15
|
-
* All tools are read-only except `write_audit_report` which appends
|
|
16
|
-
* to the audit log file.
|
|
17
|
-
*
|
|
18
|
-
* @param client - API client for Crewly REST API calls
|
|
19
|
-
* @param projectPath - Project root path for file operations
|
|
20
|
-
* @returns Object of named tools for the auditor agent
|
|
21
|
-
*/
|
|
22
|
-
export declare function createAuditorTools(client: CrewlyApiClient, projectPath: string): Record<string, ToolDefinition>;
|
|
23
|
-
/**
|
|
24
|
-
* Get the list of auditor tool names.
|
|
25
|
-
*
|
|
26
|
-
* @returns Array of auditor tool name strings
|
|
27
|
-
*/
|
|
28
|
-
export declare function getAuditorToolNames(): string[];
|
|
29
|
-
//# sourceMappingURL=auditor-tools.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auditor-tools.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/agent/crewly-agent/auditor-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAMjD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,MAAM,GAClB,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAwQhC;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAM9C"}
|