@eddacraft/anvil-kindling-integration 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +14 -0
- package/README.md +542 -0
- package/dist/adapter.d.ts +49 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +100 -0
- package/dist/config.d.ts +89 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +173 -0
- package/dist/emitters/action-emitter.d.ts +40 -0
- package/dist/emitters/action-emitter.d.ts.map +1 -0
- package/dist/emitters/action-emitter.js +52 -0
- package/dist/emitters/constraint-emitter.d.ts +32 -0
- package/dist/emitters/constraint-emitter.d.ts.map +1 -0
- package/dist/emitters/constraint-emitter.js +41 -0
- package/dist/emitters/error-emitter.d.ts +33 -0
- package/dist/emitters/error-emitter.d.ts.map +1 -0
- package/dist/emitters/error-emitter.js +50 -0
- package/dist/emitters/gate-emitter.d.ts +37 -0
- package/dist/emitters/gate-emitter.d.ts.map +1 -0
- package/dist/emitters/gate-emitter.js +53 -0
- package/dist/emitters/human-input-emitter.d.ts +30 -0
- package/dist/emitters/human-input-emitter.d.ts.map +1 -0
- package/dist/emitters/human-input-emitter.js +38 -0
- package/dist/emitters/index.d.ts +13 -0
- package/dist/emitters/index.d.ts.map +1 -0
- package/dist/emitters/index.js +19 -0
- package/dist/emitters/plan-emitter.d.ts +75 -0
- package/dist/emitters/plan-emitter.d.ts.map +1 -0
- package/dist/emitters/plan-emitter.js +116 -0
- package/dist/emitters/session-emitter.d.ts +57 -0
- package/dist/emitters/session-emitter.d.ts.map +1 -0
- package/dist/emitters/session-emitter.js +80 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +111 -0
- package/dist/kindling-service.d.ts +122 -0
- package/dist/kindling-service.d.ts.map +1 -0
- package/dist/kindling-service.js +203 -0
- package/dist/observation-contract.d.ts +561 -0
- package/dist/observation-contract.d.ts.map +1 -0
- package/dist/observation-contract.js +391 -0
- package/dist/query-contract.d.ts +463 -0
- package/dist/query-contract.d.ts.map +1 -0
- package/dist/query-contract.js +314 -0
- package/dist/query-limits.d.ts +40 -0
- package/dist/query-limits.d.ts.map +1 -0
- package/dist/query-limits.js +79 -0
- package/dist/query-service.d.ts +109 -0
- package/dist/query-service.d.ts.map +1 -0
- package/dist/query-service.js +140 -0
- package/dist/retention.d.ts +79 -0
- package/dist/retention.d.ts.map +1 -0
- package/dist/retention.js +81 -0
- package/dist/sensitive-data-validator.d.ts +47 -0
- package/dist/sensitive-data-validator.d.ts.map +1 -0
- package/dist/sensitive-data-validator.js +135 -0
- package/dist/status.d.ts +104 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +136 -0
- package/dist/utils/debug.d.ts +9 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +55 -0
- package/package.json +114 -0
- package/src/adapter.ts +117 -0
- package/src/config.ts +202 -0
- package/src/emitters/action-emitter.ts +90 -0
- package/src/emitters/constraint-emitter.ts +73 -0
- package/src/emitters/error-emitter.ts +86 -0
- package/src/emitters/gate-emitter.ts +87 -0
- package/src/emitters/human-input-emitter.ts +71 -0
- package/src/emitters/index.ts +40 -0
- package/src/emitters/plan-emitter.ts +183 -0
- package/src/emitters/session-emitter.ts +131 -0
- package/src/index.ts +254 -0
- package/src/kindling-service.ts +272 -0
- package/src/malicious-ai.test.ts +949 -0
- package/src/observation-contract.ts +500 -0
- package/src/query-contract.ts +389 -0
- package/src/query-limits.ts +106 -0
- package/src/query-service.ts +217 -0
- package/src/retention.ts +153 -0
- package/src/sensitive-data-validator.ts +167 -0
- package/src/status.ts +221 -0
- package/src/utils/debug.ts +65 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KindlingService (KINDLING-001)
|
|
3
|
+
*
|
|
4
|
+
* Core service wrapper that mediates between Anvil and the Kindling store.
|
|
5
|
+
* Handles validation, sensitive-data checks, and delegation to the store adapter.
|
|
6
|
+
*
|
|
7
|
+
* The service is built against the abstract `IKindlingStore` interface so that
|
|
8
|
+
* it compiles without @kindling/core or @kindling/store-sqlite installed.
|
|
9
|
+
* The actual storage backend is plugged in at runtime via the factory function.
|
|
10
|
+
*
|
|
11
|
+
* When no store is provided, the service operates in "disabled mode" using a
|
|
12
|
+
* no-op store that silently discards all observations.
|
|
13
|
+
*/
|
|
14
|
+
import type { Observation } from './observation-contract.js';
|
|
15
|
+
import type { QueryRequest, QueryResponse } from './query-contract.js';
|
|
16
|
+
import type { KindlingConfig } from './config.js';
|
|
17
|
+
/**
|
|
18
|
+
* Abstract storage adapter interface.
|
|
19
|
+
*
|
|
20
|
+
* Implementations must provide emit (write), query (read), and close (cleanup).
|
|
21
|
+
* This decouples the service layer from any concrete Kindling SDK dependency.
|
|
22
|
+
*/
|
|
23
|
+
export interface IKindlingStore {
|
|
24
|
+
/**
|
|
25
|
+
* Persist an observation to the store.
|
|
26
|
+
* The observation has already been validated and redacted by the service layer.
|
|
27
|
+
*/
|
|
28
|
+
emit(observation: Observation): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Execute a bounded query against the store.
|
|
31
|
+
* The request has already been validated by the service layer.
|
|
32
|
+
*/
|
|
33
|
+
query(request: QueryRequest): Promise<QueryResponse>;
|
|
34
|
+
/**
|
|
35
|
+
* Release resources (close database connections, flush buffers, etc.)
|
|
36
|
+
*/
|
|
37
|
+
close(): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* No-op store used when Kindling is disabled or no store is provided.
|
|
41
|
+
* All operations succeed silently without side effects.
|
|
42
|
+
*/
|
|
43
|
+
export declare class NoOpKindlingStore implements IKindlingStore {
|
|
44
|
+
emit(_observation: Observation): Promise<void>;
|
|
45
|
+
query(_request: QueryRequest): Promise<QueryResponse>;
|
|
46
|
+
close(): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Error thrown when observation validation fails
|
|
50
|
+
*/
|
|
51
|
+
export declare class ObservationValidationError extends Error {
|
|
52
|
+
readonly issues: string[];
|
|
53
|
+
constructor(message: string, issues: string[]);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Error thrown when query validation fails
|
|
57
|
+
*/
|
|
58
|
+
export declare class QueryValidationError extends Error {
|
|
59
|
+
constructor(message: string);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Core Kindling service that wraps the store adapter with validation,
|
|
63
|
+
* sensitive-data checks, and config-driven behavior.
|
|
64
|
+
*/
|
|
65
|
+
export declare class KindlingService {
|
|
66
|
+
private readonly store;
|
|
67
|
+
private readonly config;
|
|
68
|
+
private closed;
|
|
69
|
+
constructor(store: IKindlingStore, config: KindlingConfig);
|
|
70
|
+
/**
|
|
71
|
+
* Whether the service is enabled (will actually emit observations)
|
|
72
|
+
*/
|
|
73
|
+
get enabled(): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* The active configuration
|
|
76
|
+
*/
|
|
77
|
+
get configuration(): Readonly<KindlingConfig>;
|
|
78
|
+
/**
|
|
79
|
+
* Emit an observation to the Kindling store.
|
|
80
|
+
*
|
|
81
|
+
* This method is designed to be async and non-blocking. It:
|
|
82
|
+
* 1. Checks if the service is enabled and the observation kind should be captured
|
|
83
|
+
* 2. Validates the observation against the contract schema
|
|
84
|
+
* 3. Checks for and redacts sensitive data
|
|
85
|
+
* 4. Delegates to the store adapter
|
|
86
|
+
*
|
|
87
|
+
* Validation errors are thrown. Store errors are thrown (callers should catch
|
|
88
|
+
* if they want fire-and-forget semantics -- see emitters).
|
|
89
|
+
*
|
|
90
|
+
* @param observation - The observation to emit
|
|
91
|
+
* @throws ObservationValidationError if the observation is invalid
|
|
92
|
+
*/
|
|
93
|
+
emit(observation: Observation): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Execute a query against the Kindling store.
|
|
96
|
+
*
|
|
97
|
+
* Validates the query request against the contract schema and enforces
|
|
98
|
+
* configured query limits before delegating to the store.
|
|
99
|
+
*
|
|
100
|
+
* @param request - The query request
|
|
101
|
+
* @returns Query response with observations
|
|
102
|
+
* @throws QueryValidationError if the request is invalid
|
|
103
|
+
*/
|
|
104
|
+
query(request: QueryRequest): Promise<QueryResponse>;
|
|
105
|
+
/**
|
|
106
|
+
* Close the service and release underlying store resources.
|
|
107
|
+
* After calling close(), emit() becomes a no-op and query() throws.
|
|
108
|
+
*/
|
|
109
|
+
close(): Promise<void>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create a KindlingService instance.
|
|
113
|
+
*
|
|
114
|
+
* If no store is provided, the service operates in disabled mode with a no-op store.
|
|
115
|
+
* This allows code to unconditionally call emit/query without checking for null.
|
|
116
|
+
*
|
|
117
|
+
* @param config - Kindling configuration (defaults to disabled config)
|
|
118
|
+
* @param store - Optional store adapter (defaults to NoOpKindlingStore)
|
|
119
|
+
* @returns Configured KindlingService instance
|
|
120
|
+
*/
|
|
121
|
+
export declare function createKindlingService(config?: KindlingConfig, store?: IKindlingStore): KindlingService;
|
|
122
|
+
//# sourceMappingURL=kindling-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kindling-service.d.ts","sourceRoot":"","sources":["../src/kindling-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAWlD;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAErD;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAMD;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IAChD,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAcrD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAMD;;GAEG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;aAGjC,MAAM,EAAE,MAAM,EAAE;gBADhC,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM,EAAE;CAKnC;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAMD;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,MAAM,CAAS;gBAEX,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc;IAMzD;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACH,IAAI,aAAa,IAAI,QAAQ,CAAC,cAAc,CAAC,CAE5C;IAED;;;;;;;;;;;;;;OAcG;IACG,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCnD;;;;;;;;;OASG;IACG,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IA8B1D;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B;AAMD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,GAAE,cAAwC,EAChD,KAAK,CAAC,EAAE,cAAc,GACrB,eAAe,CAIjB"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KindlingService (KINDLING-001)
|
|
3
|
+
*
|
|
4
|
+
* Core service wrapper that mediates between Anvil and the Kindling store.
|
|
5
|
+
* Handles validation, sensitive-data checks, and delegation to the store adapter.
|
|
6
|
+
*
|
|
7
|
+
* The service is built against the abstract `IKindlingStore` interface so that
|
|
8
|
+
* it compiles without @kindling/core or @kindling/store-sqlite installed.
|
|
9
|
+
* The actual storage backend is plugged in at runtime via the factory function.
|
|
10
|
+
*
|
|
11
|
+
* When no store is provided, the service operates in "disabled mode" using a
|
|
12
|
+
* no-op store that silently discards all observations.
|
|
13
|
+
*/
|
|
14
|
+
import { validateObservation } from './observation-contract.js';
|
|
15
|
+
import { QueryRequestSchema } from './query-contract.js';
|
|
16
|
+
import { DEFAULT_KINDLING_CONFIG, shouldCapture } from './config.js';
|
|
17
|
+
import { validateNoSensitiveData, redactSensitiveFields } from './sensitive-data-validator.js';
|
|
18
|
+
import { createDebugger } from './utils/debug.js';
|
|
19
|
+
const debug = createDebugger('kindling');
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// No-Op Store (Disabled Mode)
|
|
22
|
+
// =============================================================================
|
|
23
|
+
/**
|
|
24
|
+
* No-op store used when Kindling is disabled or no store is provided.
|
|
25
|
+
* All operations succeed silently without side effects.
|
|
26
|
+
*/
|
|
27
|
+
export class NoOpKindlingStore {
|
|
28
|
+
async emit(_observation) {
|
|
29
|
+
// Intentionally empty -- disabled mode
|
|
30
|
+
}
|
|
31
|
+
async query(_request) {
|
|
32
|
+
return {
|
|
33
|
+
metadata: {
|
|
34
|
+
query_id: crypto.randomUUID(),
|
|
35
|
+
executed_at: new Date().toISOString(),
|
|
36
|
+
contract_version: '1.0.0',
|
|
37
|
+
result_count: 0,
|
|
38
|
+
truncated: false,
|
|
39
|
+
truncation_reason: 'none',
|
|
40
|
+
},
|
|
41
|
+
observations: [],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async close() {
|
|
45
|
+
// Intentionally empty -- nothing to close
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// Service Errors
|
|
50
|
+
// =============================================================================
|
|
51
|
+
/**
|
|
52
|
+
* Error thrown when observation validation fails
|
|
53
|
+
*/
|
|
54
|
+
export class ObservationValidationError extends Error {
|
|
55
|
+
issues;
|
|
56
|
+
constructor(message, issues) {
|
|
57
|
+
super(message);
|
|
58
|
+
this.issues = issues;
|
|
59
|
+
this.name = 'ObservationValidationError';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Error thrown when query validation fails
|
|
64
|
+
*/
|
|
65
|
+
export class QueryValidationError extends Error {
|
|
66
|
+
constructor(message) {
|
|
67
|
+
super(message);
|
|
68
|
+
this.name = 'QueryValidationError';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// =============================================================================
|
|
72
|
+
// KindlingService
|
|
73
|
+
// =============================================================================
|
|
74
|
+
/**
|
|
75
|
+
* Core Kindling service that wraps the store adapter with validation,
|
|
76
|
+
* sensitive-data checks, and config-driven behavior.
|
|
77
|
+
*/
|
|
78
|
+
export class KindlingService {
|
|
79
|
+
store;
|
|
80
|
+
config;
|
|
81
|
+
closed = false;
|
|
82
|
+
constructor(store, config) {
|
|
83
|
+
this.store = store;
|
|
84
|
+
this.config = config;
|
|
85
|
+
debug('KindlingService created', { enabled: config.enabled });
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Whether the service is enabled (will actually emit observations)
|
|
89
|
+
*/
|
|
90
|
+
get enabled() {
|
|
91
|
+
return this.config.enabled;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The active configuration
|
|
95
|
+
*/
|
|
96
|
+
get configuration() {
|
|
97
|
+
return this.config;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Emit an observation to the Kindling store.
|
|
101
|
+
*
|
|
102
|
+
* This method is designed to be async and non-blocking. It:
|
|
103
|
+
* 1. Checks if the service is enabled and the observation kind should be captured
|
|
104
|
+
* 2. Validates the observation against the contract schema
|
|
105
|
+
* 3. Checks for and redacts sensitive data
|
|
106
|
+
* 4. Delegates to the store adapter
|
|
107
|
+
*
|
|
108
|
+
* Validation errors are thrown. Store errors are thrown (callers should catch
|
|
109
|
+
* if they want fire-and-forget semantics -- see emitters).
|
|
110
|
+
*
|
|
111
|
+
* @param observation - The observation to emit
|
|
112
|
+
* @throws ObservationValidationError if the observation is invalid
|
|
113
|
+
*/
|
|
114
|
+
async emit(observation) {
|
|
115
|
+
if (this.closed) {
|
|
116
|
+
debug('emit skipped: service is closed');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// Check if this kind should be captured
|
|
120
|
+
if (!shouldCapture(this.config, observation.kind)) {
|
|
121
|
+
debug('emit skipped: kind not captured', observation.kind);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// Validate against the contract schema
|
|
125
|
+
const validation = validateObservation(observation);
|
|
126
|
+
if (!validation.success) {
|
|
127
|
+
debug('emit validation failed', validation.error);
|
|
128
|
+
throw new ObservationValidationError(`Invalid observation: ${validation.error}`, [
|
|
129
|
+
validation.error ?? 'Unknown validation error',
|
|
130
|
+
]);
|
|
131
|
+
}
|
|
132
|
+
// Check for sensitive data and redact if found
|
|
133
|
+
const sensitiveCheck = validateNoSensitiveData(observation);
|
|
134
|
+
let safeObservation = observation;
|
|
135
|
+
if (sensitiveCheck.hasSensitiveData) {
|
|
136
|
+
debug('sensitive data detected, redacting', sensitiveCheck.issues);
|
|
137
|
+
safeObservation = redactSensitiveFields(observation);
|
|
138
|
+
}
|
|
139
|
+
// Delegate to store (async, non-blocking from caller's perspective)
|
|
140
|
+
debug('emitting observation', { kind: observation.kind, session_id: observation.session_id });
|
|
141
|
+
await this.store.emit(safeObservation);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Execute a query against the Kindling store.
|
|
145
|
+
*
|
|
146
|
+
* Validates the query request against the contract schema and enforces
|
|
147
|
+
* configured query limits before delegating to the store.
|
|
148
|
+
*
|
|
149
|
+
* @param request - The query request
|
|
150
|
+
* @returns Query response with observations
|
|
151
|
+
* @throws QueryValidationError if the request is invalid
|
|
152
|
+
*/
|
|
153
|
+
async query(request) {
|
|
154
|
+
if (this.closed) {
|
|
155
|
+
debug('query rejected: service is closed');
|
|
156
|
+
throw new QueryValidationError('Service is closed');
|
|
157
|
+
}
|
|
158
|
+
// Validate the request
|
|
159
|
+
const validation = QueryRequestSchema.safeParse(request);
|
|
160
|
+
if (!validation.success) {
|
|
161
|
+
debug('query validation failed', validation.error.format());
|
|
162
|
+
throw new QueryValidationError(`Invalid query request: ${validation.error.format()._errors.join(', ')}`);
|
|
163
|
+
}
|
|
164
|
+
debug('executing query', { scope: request.scope });
|
|
165
|
+
// Enforce configured query limits (use config defaults if request has higher values)
|
|
166
|
+
const limitedRequest = {
|
|
167
|
+
...validation.data,
|
|
168
|
+
max_results: Math.min(validation.data.max_results, this.config.query_limits.max_results),
|
|
169
|
+
max_payload_bytes: Math.min(validation.data.max_payload_bytes, this.config.query_limits.max_payload_bytes),
|
|
170
|
+
};
|
|
171
|
+
return this.store.query(limitedRequest);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Close the service and release underlying store resources.
|
|
175
|
+
* After calling close(), emit() becomes a no-op and query() throws.
|
|
176
|
+
*/
|
|
177
|
+
async close() {
|
|
178
|
+
if (this.closed) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
debug('closing KindlingService');
|
|
182
|
+
this.closed = true;
|
|
183
|
+
await this.store.close();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// =============================================================================
|
|
187
|
+
// Factory
|
|
188
|
+
// =============================================================================
|
|
189
|
+
/**
|
|
190
|
+
* Create a KindlingService instance.
|
|
191
|
+
*
|
|
192
|
+
* If no store is provided, the service operates in disabled mode with a no-op store.
|
|
193
|
+
* This allows code to unconditionally call emit/query without checking for null.
|
|
194
|
+
*
|
|
195
|
+
* @param config - Kindling configuration (defaults to disabled config)
|
|
196
|
+
* @param store - Optional store adapter (defaults to NoOpKindlingStore)
|
|
197
|
+
* @returns Configured KindlingService instance
|
|
198
|
+
*/
|
|
199
|
+
export function createKindlingService(config = DEFAULT_KINDLING_CONFIG, store) {
|
|
200
|
+
const effectiveStore = store ?? new NoOpKindlingStore();
|
|
201
|
+
debug('creating KindlingService', { enabled: config.enabled, hasStore: !!store });
|
|
202
|
+
return new KindlingService(effectiveStore, config);
|
|
203
|
+
}
|