@lovelybunch/core 1.0.66 → 1.0.68

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.
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Event kind taxonomy for Coconut activity logging
3
+ * @module logging/kinds
4
+ *
5
+ * Event kinds follow a hierarchical naming convention:
6
+ * {entity}.{action}.{qualifier}
7
+ *
8
+ * Examples:
9
+ * - proposal.create
10
+ * - agent.session.start
11
+ * - code.commit
12
+ */
13
+ /**
14
+ * Proposal-related events
15
+ */
16
+ export const ProposalKinds = {
17
+ CREATE: "proposal.create",
18
+ UPDATE: "proposal.update",
19
+ RUN_START: "proposal.run.start",
20
+ RUN_END: "proposal.run.end",
21
+ STATUS_CHANGE: "proposal.status.change",
22
+ };
23
+ /**
24
+ * Agent and session events
25
+ */
26
+ export const AgentKinds = {
27
+ SESSION_START: "agent.session.start",
28
+ SESSION_STDOUT: "agent.session.stdout",
29
+ SESSION_END: "agent.session.end",
30
+ SESSION_ERROR: "agent.session.error",
31
+ };
32
+ /**
33
+ * Code and git-related events
34
+ */
35
+ export const CodeKinds = {
36
+ EDIT: "code.edit",
37
+ COMMIT: "code.commit",
38
+ BRANCH_CREATE: "code.branch.create",
39
+ WORKTREE_ADD: "code.worktree.add",
40
+ };
41
+ /**
42
+ * Knowledge base events
43
+ */
44
+ export const KnowledgeKinds = {
45
+ CREATE: "knowledge.create",
46
+ UPDATE: "knowledge.update",
47
+ DELETE: "knowledge.delete",
48
+ };
49
+ /**
50
+ * Job scheduling and execution events
51
+ */
52
+ export const JobKinds = {
53
+ SCHEDULE: "job.schedule",
54
+ RUN_START: "job.run.start",
55
+ RUN_END: "job.run.end",
56
+ RUN_ERROR: "job.run.error",
57
+ };
58
+ /**
59
+ * Resource management events
60
+ */
61
+ export const ResourceKinds = {
62
+ UPLOAD: "resource.upload",
63
+ DELETE: "resource.delete",
64
+ };
65
+ /**
66
+ * Authentication events (when auth is enabled)
67
+ */
68
+ export const AuthKinds = {
69
+ LOGIN: "auth.login",
70
+ LOGOUT: "auth.logout",
71
+ API_KEY_USE: "auth.api.key.use",
72
+ API_KEY_CREATE: "auth.api.key.create",
73
+ API_KEY_DELETE: "auth.api.key.delete",
74
+ };
75
+ /**
76
+ * All event kinds in a single object
77
+ */
78
+ export const EventKinds = {
79
+ ...ProposalKinds,
80
+ ...AgentKinds,
81
+ ...CodeKinds,
82
+ ...KnowledgeKinds,
83
+ ...JobKinds,
84
+ ...ResourceKinds,
85
+ ...AuthKinds,
86
+ };
87
+ /**
88
+ * Helper to validate if a string is a known event kind
89
+ */
90
+ export function isValidEventKind(kind) {
91
+ return Object.values(EventKinds).includes(kind);
92
+ }
93
+ /**
94
+ * Registry of event kinds with metadata
95
+ * Useful for documentation and validation
96
+ */
97
+ export const EventKindRegistry = {
98
+ [ProposalKinds.CREATE]: {
99
+ description: "A new change proposal was created",
100
+ tags: ["proposal"],
101
+ },
102
+ [ProposalKinds.UPDATE]: {
103
+ description: "A change proposal was updated",
104
+ tags: ["proposal"],
105
+ },
106
+ [ProposalKinds.RUN_START]: {
107
+ description: "Implementation of a proposal started",
108
+ tags: ["proposal", "execution"],
109
+ },
110
+ [ProposalKinds.RUN_END]: {
111
+ description: "Implementation of a proposal completed",
112
+ tags: ["proposal", "execution"],
113
+ },
114
+ [ProposalKinds.STATUS_CHANGE]: {
115
+ description: "Proposal status changed",
116
+ tags: ["proposal"],
117
+ },
118
+ [AgentKinds.SESSION_START]: {
119
+ description: "Agent session started",
120
+ tags: ["agent", "session"],
121
+ },
122
+ [AgentKinds.SESSION_STDOUT]: {
123
+ description: "Agent session output",
124
+ tags: ["agent", "session"],
125
+ },
126
+ [AgentKinds.SESSION_END]: {
127
+ description: "Agent session ended",
128
+ tags: ["agent", "session"],
129
+ },
130
+ [AgentKinds.SESSION_ERROR]: {
131
+ description: "Agent session encountered an error",
132
+ tags: ["agent", "session", "error"],
133
+ },
134
+ [CodeKinds.EDIT]: {
135
+ description: "Code was edited",
136
+ tags: ["code"],
137
+ },
138
+ [CodeKinds.COMMIT]: {
139
+ description: "Git commit was created",
140
+ tags: ["code", "git"],
141
+ },
142
+ [CodeKinds.BRANCH_CREATE]: {
143
+ description: "Git branch was created",
144
+ tags: ["code", "git"],
145
+ },
146
+ [CodeKinds.WORKTREE_ADD]: {
147
+ description: "Git worktree was added",
148
+ tags: ["code", "git"],
149
+ },
150
+ [KnowledgeKinds.CREATE]: {
151
+ description: "Knowledge base entry created",
152
+ tags: ["knowledge"],
153
+ },
154
+ [KnowledgeKinds.UPDATE]: {
155
+ description: "Knowledge base entry updated",
156
+ tags: ["knowledge"],
157
+ },
158
+ [KnowledgeKinds.DELETE]: {
159
+ description: "Knowledge base entry deleted",
160
+ tags: ["knowledge"],
161
+ },
162
+ [JobKinds.SCHEDULE]: {
163
+ description: "Job was scheduled",
164
+ tags: ["job"],
165
+ },
166
+ [JobKinds.RUN_START]: {
167
+ description: "Job run started",
168
+ tags: ["job", "execution"],
169
+ },
170
+ [JobKinds.RUN_END]: {
171
+ description: "Job run completed",
172
+ tags: ["job", "execution"],
173
+ },
174
+ [JobKinds.RUN_ERROR]: {
175
+ description: "Job run failed with error",
176
+ tags: ["job", "execution", "error"],
177
+ },
178
+ [ResourceKinds.UPLOAD]: {
179
+ description: "Resource was uploaded",
180
+ tags: ["resource"],
181
+ },
182
+ [ResourceKinds.DELETE]: {
183
+ description: "Resource was deleted",
184
+ tags: ["resource"],
185
+ },
186
+ [AuthKinds.LOGIN]: {
187
+ description: "User logged in",
188
+ tags: ["auth"],
189
+ },
190
+ [AuthKinds.LOGOUT]: {
191
+ description: "User logged out",
192
+ tags: ["auth"],
193
+ },
194
+ [AuthKinds.API_KEY_USE]: {
195
+ description: "API key was used for authentication",
196
+ tags: ["auth", "api"],
197
+ },
198
+ [AuthKinds.API_KEY_CREATE]: {
199
+ description: "API key was created",
200
+ tags: ["auth", "api"],
201
+ },
202
+ [AuthKinds.API_KEY_DELETE]: {
203
+ description: "API key was deleted",
204
+ tags: ["auth", "api"],
205
+ },
206
+ };
207
+ //# sourceMappingURL=kinds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kinds.js","sourceRoot":"","sources":["../../src/logging/kinds.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Logger facade for Coconut activity logging
3
+ * @module logging/logger
4
+ */
5
+ import type { Logger, LoggerOptions } from "./types";
6
+ /**
7
+ * Get or create the global logger instance
8
+ *
9
+ * This function returns a singleton logger that can be used throughout the application.
10
+ * The logger automatically fills in system fields (v, seq, ts, coconut) and applies
11
+ * redaction to scrub sensitive data.
12
+ *
13
+ * @param opts - Logger configuration options (only used on first call)
14
+ * @returns Logger instance
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { getLogger } from "@lovelybunch/core/logging/logger";
19
+ *
20
+ * const logger = getLogger();
21
+ * logger.log({
22
+ * kind: "proposal.create",
23
+ * actor: "human:sarah@company.com",
24
+ * subject: "proposal:cp-123",
25
+ * tags: ["proposal"],
26
+ * payload: { intent: "Add dark mode" }
27
+ * });
28
+ * ```
29
+ */
30
+ export declare function getLogger(opts?: Partial<LoggerOptions>): Logger;
31
+ /**
32
+ * Reset the singleton logger (primarily for testing)
33
+ */
34
+ export declare function resetLogger(): void;
35
+ /**
36
+ * Check if a logger instance exists
37
+ */
38
+ export declare function hasLogger(): boolean;
39
+ export type { LogEventBase, Logger, LoggerOptions, LogLevel } from "./types";
40
+ export { EventKinds } from "./kinds.js";
41
+ export { defaultRedactor, createRedactor, noRedactor } from "./redact.js";
42
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/logging/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAgB,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAOnE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,MAAM,CAwC/D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAKlC;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAGD,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Logger facade for Coconut activity logging
3
+ * @module logging/logger
4
+ */
5
+ import path from "node:path";
6
+ import { JsonlWriter } from "./jsonl-writer.js";
7
+ import { defaultRedactor } from "./redact.js";
8
+ /**
9
+ * Singleton logger instance
10
+ */
11
+ let singleton = null;
12
+ /**
13
+ * Get or create the global logger instance
14
+ *
15
+ * This function returns a singleton logger that can be used throughout the application.
16
+ * The logger automatically fills in system fields (v, seq, ts, coconut) and applies
17
+ * redaction to scrub sensitive data.
18
+ *
19
+ * @param opts - Logger configuration options (only used on first call)
20
+ * @returns Logger instance
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * import { getLogger } from "@lovelybunch/core/logging/logger";
25
+ *
26
+ * const logger = getLogger();
27
+ * logger.log({
28
+ * kind: "proposal.create",
29
+ * actor: "human:sarah@company.com",
30
+ * subject: "proposal:cp-123",
31
+ * tags: ["proposal"],
32
+ * payload: { intent: "Add dark mode" }
33
+ * });
34
+ * ```
35
+ */
36
+ export function getLogger(opts) {
37
+ if (singleton) {
38
+ return singleton;
39
+ }
40
+ // Resolve configuration with defaults
41
+ const coconutId = opts?.coconutId ?? process.env.COCONUT_ID ?? "unknown.coconut";
42
+ const logsDir = opts?.logsDir ?? path.resolve(".nut/logs");
43
+ const rotateBytes = opts?.rotateBytes ?? 128 * 1024 * 1024; // 128MB default
44
+ const redactor = opts?.redactor ?? defaultRedactor;
45
+ // Create the JSONL writer
46
+ const writer = new JsonlWriter(logsDir, coconutId, rotateBytes);
47
+ // Create and cache the logger instance
48
+ singleton = {
49
+ log(event) {
50
+ // Apply redaction to the event
51
+ const sanitized = redactor(event);
52
+ // Auto-fill system fields and enqueue
53
+ writer.nextEvent(sanitized);
54
+ },
55
+ async flush() {
56
+ return writer.flush();
57
+ },
58
+ getSeq() {
59
+ return writer.getSeq();
60
+ },
61
+ async close() {
62
+ await writer.close();
63
+ singleton = null;
64
+ },
65
+ };
66
+ return singleton;
67
+ }
68
+ /**
69
+ * Reset the singleton logger (primarily for testing)
70
+ */
71
+ export function resetLogger() {
72
+ if (singleton) {
73
+ void singleton.close();
74
+ }
75
+ singleton = null;
76
+ }
77
+ /**
78
+ * Check if a logger instance exists
79
+ */
80
+ export function hasLogger() {
81
+ return singleton !== null;
82
+ }
83
+ export { EventKinds } from "./kinds.js";
84
+ export { defaultRedactor, createRedactor, noRedactor } from "./redact.js";
85
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logging/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C;;GAEG;AACH,IAAI,SAAS,GAAkB,IAAI,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,SAAS,CAAC,IAA6B;IACrD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,sCAAsC;IACtC,MAAM,SAAS,GACb,IAAI,EAAE,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,iBAAiB,CAAC;IACjE,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,gBAAgB;IAC5E,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,eAAe,CAAC;IAEnD,0BAA0B;IAC1B,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAEhE,uCAAuC;IACvC,SAAS,GAAG;QACV,GAAG,CAAC,KAAmB;YACrB,+BAA+B;YAC/B,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAElC,sCAAsC;YACtC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC9B,CAAC;QAED,KAAK,CAAC,KAAK;YACT,OAAO,MAAM,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;QAED,MAAM;YACJ,OAAO,MAAM,CAAC,MAAM,EAAE,CAAC;QACzB,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;KACF,CAAC;IAEF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;IACD,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,SAAS,KAAK,IAAI,CAAC;AAC5B,CAAC;AAID,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Payload redaction utilities for scrubbing sensitive data from log events
3
+ * @module logging/redact
4
+ */
5
+ import type { LogEventBase } from "./types";
6
+ /**
7
+ * Default redactor function that scrubs sensitive data from log events
8
+ *
9
+ * This function:
10
+ * - Removes sensitive fields from the payload
11
+ * - Redacts known patterns (API keys, tokens, etc.)
12
+ * - Preserves the overall structure of the event
13
+ *
14
+ * @param event - The log event to redact
15
+ * @returns A new event with sensitive data removed
16
+ */
17
+ export declare function defaultRedactor(event: LogEventBase): LogEventBase;
18
+ /**
19
+ * Create a custom redactor that combines the default redactor with additional rules
20
+ *
21
+ * @param additionalRedactor - Custom redaction function to apply after default redaction
22
+ * @returns Combined redactor function
23
+ */
24
+ export declare function createRedactor(additionalRedactor?: (event: LogEventBase) => LogEventBase): (event: LogEventBase) => LogEventBase;
25
+ /**
26
+ * No-op redactor that returns the event unchanged
27
+ * Useful for testing or when redaction is not needed
28
+ */
29
+ export declare function noRedactor(event: LogEventBase): LogEventBase;
30
+ //# sourceMappingURL=redact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/logging/redact.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAsG5C;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAqBjE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,YAAY,GACzD,CAAC,KAAK,EAAE,YAAY,KAAK,YAAY,CASvC;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CAE5D"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Payload redaction utilities for scrubbing sensitive data from log events
3
+ * @module logging/redact
4
+ */
5
+ /**
6
+ * List of field names that commonly contain sensitive data
7
+ */
8
+ const SENSITIVE_FIELD_NAMES = [
9
+ "password",
10
+ "passwordHash",
11
+ "secret",
12
+ "apiKey",
13
+ "api_key",
14
+ "token",
15
+ "accessToken",
16
+ "access_token",
17
+ "refreshToken",
18
+ "refresh_token",
19
+ "clientSecret",
20
+ "client_secret",
21
+ "privateKey",
22
+ "private_key",
23
+ "authorization",
24
+ "cookie",
25
+ "sessionSecret",
26
+ "session_secret",
27
+ ];
28
+ /**
29
+ * Regular expressions to detect sensitive data patterns
30
+ */
31
+ const SENSITIVE_PATTERNS = [
32
+ /sk-[a-zA-Z0-9]{20,}/g, // OpenAI API keys
33
+ /sk_live_[a-zA-Z0-9]{20,}/g, // Stripe live keys
34
+ /sk_test_[a-zA-Z0-9]{20,}/g, // Stripe test keys
35
+ /ghp_[a-zA-Z0-9]{36}/g, // GitHub personal access tokens
36
+ /gho_[a-zA-Z0-9]{36}/g, // GitHub OAuth tokens
37
+ /Bearer\s+[a-zA-Z0-9\-._~+/]+=*/g, // Bearer tokens
38
+ ];
39
+ /**
40
+ * Placeholder text for redacted content
41
+ */
42
+ const REDACTED = "[REDACTED]";
43
+ /**
44
+ * Check if a field name is sensitive
45
+ */
46
+ function isSensitiveFieldName(fieldName) {
47
+ const lowerField = fieldName.toLowerCase();
48
+ return SENSITIVE_FIELD_NAMES.some((sensitive) => lowerField.includes(sensitive.toLowerCase()));
49
+ }
50
+ /**
51
+ * Recursively redact sensitive fields from an object
52
+ */
53
+ function redactObject(obj, depth = 0) {
54
+ // Prevent infinite recursion
55
+ if (depth > 10) {
56
+ return obj;
57
+ }
58
+ if (obj === null || obj === undefined) {
59
+ return obj;
60
+ }
61
+ if (Array.isArray(obj)) {
62
+ return obj.map((item) => redactObject(item, depth + 1));
63
+ }
64
+ if (typeof obj === "object") {
65
+ const result = {};
66
+ for (const [key, value] of Object.entries(obj)) {
67
+ if (isSensitiveFieldName(key)) {
68
+ result[key] = REDACTED;
69
+ }
70
+ else if (typeof value === "string") {
71
+ result[key] = redactString(value);
72
+ }
73
+ else {
74
+ result[key] = redactObject(value, depth + 1);
75
+ }
76
+ }
77
+ return result;
78
+ }
79
+ if (typeof obj === "string") {
80
+ return redactString(obj);
81
+ }
82
+ return obj;
83
+ }
84
+ /**
85
+ * Redact sensitive patterns from a string
86
+ */
87
+ function redactString(str) {
88
+ let result = str;
89
+ for (const pattern of SENSITIVE_PATTERNS) {
90
+ result = result.replace(pattern, REDACTED);
91
+ }
92
+ return result;
93
+ }
94
+ /**
95
+ * Default redactor function that scrubs sensitive data from log events
96
+ *
97
+ * This function:
98
+ * - Removes sensitive fields from the payload
99
+ * - Redacts known patterns (API keys, tokens, etc.)
100
+ * - Preserves the overall structure of the event
101
+ *
102
+ * @param event - The log event to redact
103
+ * @returns A new event with sensitive data removed
104
+ */
105
+ export function defaultRedactor(event) {
106
+ const redacted = {
107
+ ...event,
108
+ };
109
+ // Redact the payload if present
110
+ if (event.payload) {
111
+ redacted.payload = redactObject(event.payload);
112
+ }
113
+ // Redact actor field if it looks like an email with sensitive content
114
+ if (event.actor && typeof event.actor === "string") {
115
+ redacted.actor = redactString(event.actor);
116
+ }
117
+ // Redact subject field if needed
118
+ if (event.subject && typeof event.subject === "string") {
119
+ redacted.subject = redactString(event.subject);
120
+ }
121
+ return redacted;
122
+ }
123
+ /**
124
+ * Create a custom redactor that combines the default redactor with additional rules
125
+ *
126
+ * @param additionalRedactor - Custom redaction function to apply after default redaction
127
+ * @returns Combined redactor function
128
+ */
129
+ export function createRedactor(additionalRedactor) {
130
+ if (!additionalRedactor) {
131
+ return defaultRedactor;
132
+ }
133
+ return (event) => {
134
+ const defaultRedacted = defaultRedactor(event);
135
+ return additionalRedactor(defaultRedacted);
136
+ };
137
+ }
138
+ /**
139
+ * No-op redactor that returns the event unchanged
140
+ * Useful for testing or when redaction is not needed
141
+ */
142
+ export function noRedactor(event) {
143
+ return event;
144
+ }
145
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/logging/redact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Core logging types for Coconut activity logging system
3
+ * @module logging/types
4
+ */
5
+ /**
6
+ * Log level enumeration
7
+ */
8
+ export type LogLevel = "debug" | "info" | "warn" | "error";
9
+ /**
10
+ * Base event structure for logging
11
+ * All events share these common fields, with additional payload data specific to the event type
12
+ */
13
+ export interface LogEventBase {
14
+ /** Optional tenant identifier for multi-tenant deployments */
15
+ tenant?: string;
16
+ /** Event kind/type from the taxonomy (e.g., "proposal.create", "agent.session.start") */
17
+ kind: string;
18
+ /** Actor performing the action (e.g., "human:email@example.com", "agent:coder") */
19
+ actor?: string;
20
+ /** Subject entity this event is about (e.g., "proposal:cp-123", "session:abc123") */
21
+ subject?: string;
22
+ /** Correlation ID for tracing related events across operations */
23
+ trace?: string;
24
+ /** Optional parent trace hop for nested operations */
25
+ parent?: string;
26
+ /** Event severity level */
27
+ level?: LogLevel;
28
+ /** Queryable tags for filtering and categorization */
29
+ tags?: string[];
30
+ /** Event-specific payload data */
31
+ payload?: unknown;
32
+ /** Override timestamp (primarily for backfilling historical data) */
33
+ ts?: string;
34
+ }
35
+ /**
36
+ * Complete event structure with system-filled fields
37
+ */
38
+ export interface LogEvent extends Omit<LogEventBase, 'ts'> {
39
+ /** Schema version for the event format */
40
+ v: number;
41
+ /** Monotonic sequence number within this Coconut instance */
42
+ seq: number;
43
+ /** ISO 8601 timestamp (required in final event) */
44
+ ts: string;
45
+ /** Stable Coconut instance identifier */
46
+ coconut: string;
47
+ }
48
+ /**
49
+ * Configuration options for the logger
50
+ */
51
+ export interface LoggerOptions {
52
+ /** Unique identifier for this Coconut instance */
53
+ coconutId: string;
54
+ /** Directory where log files are stored (default: ".nut/logs") */
55
+ logsDir?: string;
56
+ /** File size threshold for rotation in bytes (default: 128MB) */
57
+ rotateBytes?: number;
58
+ /** Optional redaction function to scrub sensitive data from payloads */
59
+ redactor?: (event: LogEventBase) => LogEventBase;
60
+ }
61
+ /**
62
+ * Logger interface for emitting events
63
+ */
64
+ export interface Logger {
65
+ /** Enqueue an event for writing (non-blocking) */
66
+ log(event: LogEventBase): void;
67
+ /** Flush pending events to disk (best-effort fsync) */
68
+ flush(): Promise<void>;
69
+ /** Get the last assigned sequence number */
70
+ getSeq(): number;
71
+ /** Close the logger and cleanup resources */
72
+ close(): Promise<void>;
73
+ }
74
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/logging/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IAEb,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,QAAQ,CAAC;IAEjB,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,qEAAqE;IACrE,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC;IACxD,0CAA0C;IAC1C,CAAC,EAAE,MAAM,CAAC;IAEV,6DAA6D;IAC7D,GAAG,EAAE,MAAM,CAAC;IAEZ,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IAEX,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAElB,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,YAAY,CAAC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,kDAAkD;IAClD,GAAG,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAE/B,uDAAuD;IACvD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB,4CAA4C;IAC5C,MAAM,IAAI,MAAM,CAAC;IAEjB,6CAA6C;IAC7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Core logging types for Coconut activity logging system
3
+ * @module logging/types
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/logging/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovelybunch/core",
3
- "version": "1.0.66",
3
+ "version": "1.0.68",
4
4
  "description": "Core Coconut functionality",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -9,6 +9,10 @@
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.js"
12
+ },
13
+ "./logging": {
14
+ "types": "./dist/logging/index.d.ts",
15
+ "import": "./dist/logging/index.js"
12
16
  }
13
17
  },
14
18
  "files": [
@@ -31,7 +35,7 @@
31
35
  "test": "vitest run"
32
36
  },
33
37
  "dependencies": {
34
- "@lovelybunch/types": "^1.0.66",
38
+ "@lovelybunch/types": "^1.0.68",
35
39
  "gray-matter": "^4.0.3",
36
40
  "fuse.js": "^7.0.0",
37
41
  "nanoid": "^5.0.6"
@@ -1,6 +0,0 @@
1
- /**
2
- * Built-in workflow templates
3
- * These are created in .nut/agents/workflows/ during nut init
4
- */
5
- export declare const workflowTemplates: Record<string, string>;
6
- //# sourceMappingURL=workflow-templates.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"workflow-templates.d.ts","sourceRoot":"","sources":["../src/workflow-templates.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAyDpD,CAAC"}