@mondaydotcomorg/atp-runtime 0.17.14
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/README.md +389 -0
- package/dist/approval/handler.d.ts +12 -0
- package/dist/approval/handler.d.ts.map +1 -0
- package/dist/approval/handler.js +17 -0
- package/dist/approval/handler.js.map +1 -0
- package/dist/approval/index.d.ts +17 -0
- package/dist/approval/index.d.ts.map +1 -0
- package/dist/approval/index.js +94 -0
- package/dist/approval/index.js.map +1 -0
- package/dist/approval/types.d.ts +21 -0
- package/dist/approval/types.d.ts.map +1 -0
- package/dist/approval/types.js +5 -0
- package/dist/approval/types.js.map +1 -0
- package/dist/cache/backends.d.ts +39 -0
- package/dist/cache/backends.d.ts.map +1 -0
- package/dist/cache/backends.js +167 -0
- package/dist/cache/backends.js.map +1 -0
- package/dist/cache/index.d.ts +32 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +103 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/types.d.ts +20 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +2 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/embedding/index.d.ts +39 -0
- package/dist/embedding/index.d.ts.map +1 -0
- package/dist/embedding/index.js +162 -0
- package/dist/embedding/index.js.map +1 -0
- package/dist/embedding/types.d.ts +28 -0
- package/dist/embedding/types.d.ts.map +1 -0
- package/dist/embedding/types.js +5 -0
- package/dist/embedding/types.js.map +1 -0
- package/dist/embedding/utils.d.ts +11 -0
- package/dist/embedding/utils.d.ts.map +1 -0
- package/dist/embedding/utils.js +30 -0
- package/dist/embedding/utils.js.map +1 -0
- package/dist/embedding/vector-store.d.ts +64 -0
- package/dist/embedding/vector-store.d.ts.map +1 -0
- package/dist/embedding/vector-store.js +142 -0
- package/dist/embedding/vector-store.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/callback.d.ts +13 -0
- package/dist/llm/callback.d.ts.map +1 -0
- package/dist/llm/callback.js +19 -0
- package/dist/llm/callback.js.map +1 -0
- package/dist/llm/index.d.ts +29 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +118 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/replay.d.ts +47 -0
- package/dist/llm/replay.d.ts.map +1 -0
- package/dist/llm/replay.js +114 -0
- package/dist/llm/replay.js.map +1 -0
- package/dist/llm/types.d.ts +24 -0
- package/dist/llm/types.d.ts.map +1 -0
- package/dist/llm/types.js +2 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/log/index.d.ts +12 -0
- package/dist/log/index.d.ts.map +1 -0
- package/dist/log/index.js +166 -0
- package/dist/log/index.js.map +1 -0
- package/dist/log/types.d.ts +19 -0
- package/dist/log/types.d.ts.map +1 -0
- package/dist/log/types.js +5 -0
- package/dist/log/types.js.map +1 -0
- package/dist/metadata/decorators.d.ts +27 -0
- package/dist/metadata/decorators.d.ts.map +1 -0
- package/dist/metadata/decorators.js +38 -0
- package/dist/metadata/decorators.js.map +1 -0
- package/dist/metadata/generated.d.ts +18 -0
- package/dist/metadata/generated.d.ts.map +1 -0
- package/dist/metadata/generated.js +290 -0
- package/dist/metadata/generated.js.map +1 -0
- package/dist/metadata/index.d.ts +11 -0
- package/dist/metadata/index.d.ts.map +1 -0
- package/dist/metadata/index.js +45 -0
- package/dist/metadata/index.js.map +1 -0
- package/dist/metadata/types.d.ts +22 -0
- package/dist/metadata/types.d.ts.map +1 -0
- package/dist/metadata/types.js +6 -0
- package/dist/metadata/types.js.map +1 -0
- package/dist/pause/index.d.ts +11 -0
- package/dist/pause/index.d.ts.map +1 -0
- package/dist/pause/index.js +15 -0
- package/dist/pause/index.js.map +1 -0
- package/dist/pause/types.d.ts +46 -0
- package/dist/pause/types.d.ts.map +1 -0
- package/dist/pause/types.js +57 -0
- package/dist/pause/types.js.map +1 -0
- package/dist/progress/index.d.ts +19 -0
- package/dist/progress/index.d.ts.map +1 -0
- package/dist/progress/index.js +61 -0
- package/dist/progress/index.js.map +1 -0
- package/dist/progress/types.d.ts +7 -0
- package/dist/progress/types.d.ts.map +1 -0
- package/dist/progress/types.js +2 -0
- package/dist/progress/types.js.map +1 -0
- package/dist/registry.d.ts +16 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +16 -0
- package/dist/registry.js.map +1 -0
- package/dist/utils.d.ts +11 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +31 -0
- package/dist/utils.js.map +1 -0
- package/package.json +51 -0
- package/src/approval/handler.ts +26 -0
- package/src/approval/index.ts +95 -0
- package/src/approval/types.ts +23 -0
- package/src/cache/backends.ts +196 -0
- package/src/cache/index.ts +74 -0
- package/src/cache/types.ts +20 -0
- package/src/embedding/index.ts +153 -0
- package/src/embedding/types.ts +31 -0
- package/src/embedding/utils.ts +34 -0
- package/src/embedding/vector-store.ts +164 -0
- package/src/index.ts +35 -0
- package/src/llm/callback.ts +24 -0
- package/src/llm/index.ts +121 -0
- package/src/llm/replay.ts +141 -0
- package/src/llm/types.ts +29 -0
- package/src/log/index.ts +167 -0
- package/src/log/types.ts +21 -0
- package/src/metadata/decorators.ts +44 -0
- package/src/metadata/generated.ts +293 -0
- package/src/metadata/index.ts +61 -0
- package/src/metadata/types.ts +24 -0
- package/src/pause/index.ts +28 -0
- package/src/pause/types.ts +57 -0
- package/src/progress/index.ts +50 -0
- package/src/progress/types.ts +6 -0
- package/src/registry.ts +22 -0
- package/src/utils.ts +37 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export * from './llm/index.js';
|
|
2
|
+
export * from './progress/index.js';
|
|
3
|
+
export * from './cache/index.js';
|
|
4
|
+
export * from './utils.js';
|
|
5
|
+
export * from './approval/index.js';
|
|
6
|
+
export * from './embedding/index.js';
|
|
7
|
+
export * from './registry.js';
|
|
8
|
+
export * from './metadata/index.js';
|
|
9
|
+
|
|
10
|
+
export { log, initializeLogger, shutdownLogger } from './log/index.js';
|
|
11
|
+
export type { LogLevel, LoggerConfig, Logger } from './log/index.js';
|
|
12
|
+
|
|
13
|
+
export { GENERATED_METADATA } from './metadata/generated.js';
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
setClientLLMCallback,
|
|
17
|
+
setPauseForClient,
|
|
18
|
+
setReplayMode,
|
|
19
|
+
getCallSequenceNumber,
|
|
20
|
+
} from './llm/index.js';
|
|
21
|
+
export { initializeCache } from './cache/index.js';
|
|
22
|
+
export { initializeApproval } from './approval/index.js';
|
|
23
|
+
export { setProgressCallback } from './progress/index.js';
|
|
24
|
+
export { initializeVectorStore, clearVectorStore, getVectorStore } from './embedding/index.js';
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
PauseExecutionError,
|
|
28
|
+
isPauseError,
|
|
29
|
+
pauseForCallback,
|
|
30
|
+
CallbackType,
|
|
31
|
+
LLMOperation,
|
|
32
|
+
EmbeddingOperation,
|
|
33
|
+
ApprovalOperation,
|
|
34
|
+
ToolOperation,
|
|
35
|
+
} from './pause/index.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*/
|
|
3
|
+
import type { ClientLLMCallback } from './types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Client callback handler for LLM operations
|
|
7
|
+
* When set, LLM calls will be routed to client instead of server LLM
|
|
8
|
+
*/
|
|
9
|
+
let clientLLMCallback: ClientLLMCallback | undefined;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Sets a client callback handler for LLM operations
|
|
13
|
+
* @param callback - Client callback handler
|
|
14
|
+
*/
|
|
15
|
+
export function setClientLLMCallback(callback: ClientLLMCallback | undefined): void {
|
|
16
|
+
clientLLMCallback = callback;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Gets the current client callback handler
|
|
21
|
+
*/
|
|
22
|
+
export function getClientLLMCallback(): ClientLLMCallback | undefined {
|
|
23
|
+
return clientLLMCallback;
|
|
24
|
+
}
|
package/src/llm/index.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM API - Clean refactored version with decorators and extracted modules
|
|
3
|
+
*
|
|
4
|
+
* Benefits:
|
|
5
|
+
* - No duplication between implementation and metadata
|
|
6
|
+
* - Types auto-detected from TypeScript signatures
|
|
7
|
+
* - Clean separation of concerns (replay, callback, API)
|
|
8
|
+
*/
|
|
9
|
+
import { pauseForCallback, CallbackType, LLMOperation } from '../pause/index.js';
|
|
10
|
+
import { RuntimeAPI, RuntimeMethod } from '../metadata/decorators.js';
|
|
11
|
+
import { nextSequenceNumber, getCachedResult, isReplayMode } from './replay.js';
|
|
12
|
+
import type { LLMCallOptions, LLMExtractOptions, LLMClassifyOptions } from './types';
|
|
13
|
+
|
|
14
|
+
export type {
|
|
15
|
+
LLMCallOptions,
|
|
16
|
+
LLMExtractOptions,
|
|
17
|
+
LLMClassifyOptions,
|
|
18
|
+
ClientLLMCallback,
|
|
19
|
+
} from './types';
|
|
20
|
+
export { setClientLLMCallback, getClientLLMCallback } from './callback.js';
|
|
21
|
+
export {
|
|
22
|
+
setPauseForClient,
|
|
23
|
+
setReplayMode,
|
|
24
|
+
getCallSequenceNumber,
|
|
25
|
+
nextSequenceNumber,
|
|
26
|
+
getCachedResult,
|
|
27
|
+
runInExecutionContext,
|
|
28
|
+
setCurrentExecutionId,
|
|
29
|
+
clearCurrentExecutionId,
|
|
30
|
+
} from './replay.js';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* LLM Runtime API
|
|
34
|
+
*
|
|
35
|
+
* Provides client-side LLM operations with pause/resume support.
|
|
36
|
+
* All calls pause execution and route to client-provided LLM.
|
|
37
|
+
*/
|
|
38
|
+
@RuntimeAPI(
|
|
39
|
+
'llm',
|
|
40
|
+
'LLM API - Large Language Model calls using client-provided LLM (requires client.provideLLM())'
|
|
41
|
+
)
|
|
42
|
+
class LLMAPI {
|
|
43
|
+
/**
|
|
44
|
+
* Makes a standard LLM call
|
|
45
|
+
* Always pauses execution and routes to client-provided LLM
|
|
46
|
+
*/
|
|
47
|
+
@RuntimeMethod('Make an LLM call with a prompt', {
|
|
48
|
+
options: {
|
|
49
|
+
description: 'LLM call options including prompt',
|
|
50
|
+
type: 'LLMCallOptions',
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
async call(options: LLMCallOptions): Promise<string> {
|
|
54
|
+
const currentSequence = nextSequenceNumber();
|
|
55
|
+
|
|
56
|
+
const cachedResult = getCachedResult(currentSequence);
|
|
57
|
+
if (cachedResult !== undefined) {
|
|
58
|
+
return cachedResult as string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
pauseForCallback(CallbackType.LLM, LLMOperation.CALL, {
|
|
62
|
+
prompt: options.prompt,
|
|
63
|
+
options,
|
|
64
|
+
sequenceNumber: currentSequence,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Extracts structured data using LLM
|
|
70
|
+
* Always pauses execution and routes to client-provided LLM
|
|
71
|
+
*/
|
|
72
|
+
@RuntimeMethod('Extract structured data from text using an LLM', {
|
|
73
|
+
options: {
|
|
74
|
+
description: 'Extraction options with JSON schema',
|
|
75
|
+
type: 'LLMExtractOptions',
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
async extract<T>(options: LLMExtractOptions): Promise<T> {
|
|
79
|
+
const currentSequence = nextSequenceNumber();
|
|
80
|
+
|
|
81
|
+
const cachedResult = getCachedResult(currentSequence);
|
|
82
|
+
if (cachedResult !== undefined) {
|
|
83
|
+
return cachedResult as T;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
pauseForCallback(CallbackType.LLM, LLMOperation.EXTRACT, {
|
|
87
|
+
prompt: options.prompt,
|
|
88
|
+
schema: options.schema,
|
|
89
|
+
options,
|
|
90
|
+
sequenceNumber: currentSequence,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Classifies text into one of the provided categories
|
|
96
|
+
* Always pauses execution and routes to client-provided LLM
|
|
97
|
+
*/
|
|
98
|
+
@RuntimeMethod('Classify text into one of the provided categories', {
|
|
99
|
+
options: {
|
|
100
|
+
description: 'Classification options with categories',
|
|
101
|
+
type: 'LLMClassifyOptions',
|
|
102
|
+
},
|
|
103
|
+
})
|
|
104
|
+
async classify(options: LLMClassifyOptions): Promise<string> {
|
|
105
|
+
const currentSequence = nextSequenceNumber();
|
|
106
|
+
|
|
107
|
+
const cachedResult = getCachedResult(currentSequence);
|
|
108
|
+
if (cachedResult !== undefined) {
|
|
109
|
+
return cachedResult as string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
pauseForCallback(CallbackType.LLM, LLMOperation.CLASSIFY, {
|
|
113
|
+
text: options.text,
|
|
114
|
+
categories: options.categories,
|
|
115
|
+
options,
|
|
116
|
+
sequenceNumber: currentSequence,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export const llm = new LLMAPI();
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Execution-scoped state
|
|
5
|
+
*/
|
|
6
|
+
interface ExecutionState {
|
|
7
|
+
shouldPauseForClient: boolean;
|
|
8
|
+
replayResults: Map<number, unknown> | undefined;
|
|
9
|
+
callSequenceNumber: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Map of executionId -> ExecutionState
|
|
14
|
+
* Each execution has its own isolated state
|
|
15
|
+
*/
|
|
16
|
+
const executionStates = new Map<string, ExecutionState>();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* AsyncLocalStorage for execution ID - provides proper async context isolation
|
|
20
|
+
* This ensures each async execution chain has its own isolated execution ID
|
|
21
|
+
*/
|
|
22
|
+
const executionContext = new AsyncLocalStorage<string>();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Current execution ID - set by runtime API wrappers
|
|
26
|
+
* This is a thread-local variable that's set before each runtime API call
|
|
27
|
+
* and cleared after, providing isolation even when AsyncLocalStorage fails
|
|
28
|
+
*/
|
|
29
|
+
let currentExecutionId: string | null = null;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Sets the current execution ID for this call
|
|
33
|
+
* Called by executor before each runtime API invocation
|
|
34
|
+
*/
|
|
35
|
+
export function setCurrentExecutionId(executionId: string): void {
|
|
36
|
+
currentExecutionId = executionId;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Clears the current execution ID after a call
|
|
41
|
+
* Called by executor after each runtime API invocation
|
|
42
|
+
*/
|
|
43
|
+
export function clearCurrentExecutionId(): void {
|
|
44
|
+
currentExecutionId = null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Gets the current execution state, creating it if needed
|
|
49
|
+
*/
|
|
50
|
+
function getCurrentState(): ExecutionState {
|
|
51
|
+
let executionId = currentExecutionId;
|
|
52
|
+
|
|
53
|
+
if (!executionId) {
|
|
54
|
+
executionId = executionContext.getStore() || null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!executionId) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
'No execution context set. Executor must call setCurrentExecutionId() before runtime API calls.'
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let state = executionStates.get(executionId);
|
|
64
|
+
if (!state) {
|
|
65
|
+
state = {
|
|
66
|
+
shouldPauseForClient: false,
|
|
67
|
+
replayResults: undefined,
|
|
68
|
+
callSequenceNumber: 0,
|
|
69
|
+
};
|
|
70
|
+
executionStates.set(executionId, state);
|
|
71
|
+
}
|
|
72
|
+
return state;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Runs a function within an execution context
|
|
77
|
+
* @param executionId - Unique ID for this execution
|
|
78
|
+
* @param fn - Function to run within the context
|
|
79
|
+
*/
|
|
80
|
+
export function runInExecutionContext<T>(executionId: string, fn: () => T): T {
|
|
81
|
+
return executionContext.run(executionId, fn);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Configures whether to pause execution for client services
|
|
86
|
+
* @param pause - If true, throws PauseExecutionError instead of calling callback
|
|
87
|
+
*/
|
|
88
|
+
export function setPauseForClient(pause: boolean): void {
|
|
89
|
+
getCurrentState().shouldPauseForClient = pause;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Checks if should pause for client
|
|
94
|
+
*/
|
|
95
|
+
export function shouldPauseForClient(): boolean {
|
|
96
|
+
return getCurrentState().shouldPauseForClient;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Sets up replay mode for resumption
|
|
101
|
+
* @param results - Map of sequence number to result for replaying callbacks
|
|
102
|
+
*/
|
|
103
|
+
export function setReplayMode(results: Map<number, unknown> | undefined): void {
|
|
104
|
+
const state = getCurrentState();
|
|
105
|
+
state.replayResults = results;
|
|
106
|
+
state.callSequenceNumber = 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Gets current call sequence number
|
|
111
|
+
*/
|
|
112
|
+
export function getCallSequenceNumber(): number {
|
|
113
|
+
return getCurrentState().callSequenceNumber;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Increments and returns the next sequence number
|
|
118
|
+
*/
|
|
119
|
+
export function nextSequenceNumber(): number {
|
|
120
|
+
const state = getCurrentState();
|
|
121
|
+
return state.callSequenceNumber++;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Check if we have a cached result for the current sequence
|
|
126
|
+
*/
|
|
127
|
+
export function getCachedResult(sequenceNumber: number): unknown | undefined {
|
|
128
|
+
const state = getCurrentState();
|
|
129
|
+
if (state.replayResults && state.replayResults.has(sequenceNumber)) {
|
|
130
|
+
const result = state.replayResults.get(sequenceNumber);
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Check if we're in replay mode
|
|
138
|
+
*/
|
|
139
|
+
export function isReplayMode(): boolean {
|
|
140
|
+
return getCurrentState().replayResults !== undefined;
|
|
141
|
+
}
|
package/src/llm/types.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface LLMCallOptions {
|
|
2
|
+
prompt: string;
|
|
3
|
+
context?: Record<string, unknown>;
|
|
4
|
+
model?: string;
|
|
5
|
+
maxTokens?: number;
|
|
6
|
+
temperature?: number;
|
|
7
|
+
systemPrompt?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface LLMExtractOptions {
|
|
11
|
+
prompt: string;
|
|
12
|
+
context?: Record<string, unknown>;
|
|
13
|
+
schema: unknown;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface LLMClassifyOptions {
|
|
17
|
+
text: string;
|
|
18
|
+
categories: string[];
|
|
19
|
+
context?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Client callback handler for LLM operations
|
|
24
|
+
* Set when client provides their own LLM implementation
|
|
25
|
+
*/
|
|
26
|
+
export type ClientLLMCallback = (
|
|
27
|
+
operation: string,
|
|
28
|
+
payload: Record<string, unknown>
|
|
29
|
+
) => Promise<unknown>;
|
package/src/log/index.ts
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import pino from 'pino';
|
|
2
|
+
import type { LogLevel, LoggerConfig, Logger } from './types.js';
|
|
3
|
+
|
|
4
|
+
export type { LogLevel, LoggerConfig, Logger } from './types.js';
|
|
5
|
+
|
|
6
|
+
let logger: pino.Logger | null = null;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Initializes the logger with configuration
|
|
10
|
+
*/
|
|
11
|
+
export function initializeLogger(config?: LoggerConfig): void {
|
|
12
|
+
const options: pino.LoggerOptions = {
|
|
13
|
+
level: config?.level ?? 'info',
|
|
14
|
+
timestamp: pino.stdTimeFunctions.isoTime,
|
|
15
|
+
formatters: {
|
|
16
|
+
level: (label) => {
|
|
17
|
+
return { level: label };
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
redact: {
|
|
21
|
+
paths: config?.redact ?? ['apiKey', 'password', '*.apiKey', '*.password', 'authorization'],
|
|
22
|
+
censor: '[REDACTED]',
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
if (config?.pretty) {
|
|
27
|
+
logger = pino({
|
|
28
|
+
...options,
|
|
29
|
+
transport: {
|
|
30
|
+
target: 'pino-pretty',
|
|
31
|
+
options: {
|
|
32
|
+
colorize: true,
|
|
33
|
+
translateTime: 'SYS:standard',
|
|
34
|
+
ignore: 'pid,hostname',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
} else if (config?.destination && config.destination !== 'stdout') {
|
|
39
|
+
logger = pino(options, pino.destination(config.destination));
|
|
40
|
+
} else {
|
|
41
|
+
logger = pino(options);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Gets or initializes the logger
|
|
47
|
+
*/
|
|
48
|
+
function getLogger(): pino.Logger {
|
|
49
|
+
if (!logger) {
|
|
50
|
+
initializeLogger({ level: 'info', pretty: false });
|
|
51
|
+
}
|
|
52
|
+
return logger!;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const log: Logger = {
|
|
56
|
+
/**
|
|
57
|
+
* Logs an informational message
|
|
58
|
+
*/
|
|
59
|
+
info(message: string, data?: unknown): void {
|
|
60
|
+
const l = getLogger();
|
|
61
|
+
if (data) {
|
|
62
|
+
l.info(data, message);
|
|
63
|
+
} else {
|
|
64
|
+
l.info(message);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Logs a warning message
|
|
70
|
+
*/
|
|
71
|
+
warn(message: string, data?: unknown): void {
|
|
72
|
+
const l = getLogger();
|
|
73
|
+
if (data) {
|
|
74
|
+
l.warn(data, message);
|
|
75
|
+
} else {
|
|
76
|
+
l.warn(message);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Logs an error message
|
|
82
|
+
*/
|
|
83
|
+
error(message: string, data?: unknown): void {
|
|
84
|
+
const l = getLogger();
|
|
85
|
+
if (data) {
|
|
86
|
+
l.error(data, message);
|
|
87
|
+
} else {
|
|
88
|
+
l.error(message);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Logs a debug message
|
|
94
|
+
*/
|
|
95
|
+
debug(message: string, data?: unknown): void {
|
|
96
|
+
const l = getLogger();
|
|
97
|
+
if (data) {
|
|
98
|
+
l.debug(data, message);
|
|
99
|
+
} else {
|
|
100
|
+
l.debug(message);
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Logs a fatal error message
|
|
106
|
+
*/
|
|
107
|
+
fatal(message: string, data?: unknown): void {
|
|
108
|
+
const l = getLogger();
|
|
109
|
+
if (data) {
|
|
110
|
+
l.fatal(data, message);
|
|
111
|
+
} else {
|
|
112
|
+
l.fatal(message);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Creates a child logger with additional context
|
|
118
|
+
*/
|
|
119
|
+
child(bindings: Record<string, unknown>): typeof log {
|
|
120
|
+
const childLogger = getLogger().child(bindings);
|
|
121
|
+
return {
|
|
122
|
+
info: (message: string, data?: unknown) => {
|
|
123
|
+
if (data) {
|
|
124
|
+
childLogger.info(data, message);
|
|
125
|
+
} else {
|
|
126
|
+
childLogger.info(message);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
warn: (message: string, data?: unknown) => {
|
|
130
|
+
if (data) {
|
|
131
|
+
childLogger.warn(data, message);
|
|
132
|
+
} else {
|
|
133
|
+
childLogger.warn(message);
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
error: (message: string, data?: unknown) => {
|
|
137
|
+
if (data) {
|
|
138
|
+
childLogger.error(data, message);
|
|
139
|
+
} else {
|
|
140
|
+
childLogger.error(message);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
debug: (message: string, data?: unknown) => {
|
|
144
|
+
if (data) {
|
|
145
|
+
childLogger.debug(data, message);
|
|
146
|
+
} else {
|
|
147
|
+
childLogger.debug(message);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
fatal: (message: string, data?: unknown) => {
|
|
151
|
+
if (data) {
|
|
152
|
+
childLogger.fatal(data, message);
|
|
153
|
+
} else {
|
|
154
|
+
childLogger.fatal(message);
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
child: log.child,
|
|
158
|
+
};
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Shuts down the logger (for cleanup in tests)
|
|
164
|
+
*/
|
|
165
|
+
export function shutdownLogger(): void {
|
|
166
|
+
logger = null;
|
|
167
|
+
}
|
package/src/log/types.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log API Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
6
|
+
|
|
7
|
+
export interface LoggerConfig {
|
|
8
|
+
level: LogLevel;
|
|
9
|
+
pretty?: boolean;
|
|
10
|
+
destination?: string;
|
|
11
|
+
redact?: string[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface Logger {
|
|
15
|
+
info(message: string, data?: unknown): void;
|
|
16
|
+
warn(message: string, data?: unknown): void;
|
|
17
|
+
error(message: string, data?: unknown): void;
|
|
18
|
+
debug(message: string, data?: unknown): void;
|
|
19
|
+
fatal(message: string, data?: unknown): void;
|
|
20
|
+
child(bindings: Record<string, unknown>): Logger;
|
|
21
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decorator-based metadata system for runtime APIs
|
|
3
|
+
*
|
|
4
|
+
* These decorators are MARKERS ONLY - they don't extract types at runtime.
|
|
5
|
+
* All type extraction happens at BUILD TIME using ts-morph.
|
|
6
|
+
*
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Class decorator to mark a runtime API
|
|
10
|
+
*
|
|
11
|
+
* This is just a marker - ts-morph extracts all metadata at build time
|
|
12
|
+
*/
|
|
13
|
+
export function RuntimeAPI(name: string, description: string) {
|
|
14
|
+
return function <T extends { new (...args: any[]): {} }>(constructor: T) {
|
|
15
|
+
(constructor as any).API_NAME = name;
|
|
16
|
+
(constructor as any).API_DESCRIPTION = description;
|
|
17
|
+
|
|
18
|
+
return constructor;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Method decorator to mark a runtime method
|
|
24
|
+
*
|
|
25
|
+
* This is just a marker - ts-morph extracts types/params at build time
|
|
26
|
+
* Only the description and optional param descriptions are stored
|
|
27
|
+
*/
|
|
28
|
+
export function RuntimeMethod(
|
|
29
|
+
description: string,
|
|
30
|
+
paramDescriptions?: Record<string, { description?: string; optional?: boolean; type?: string }>
|
|
31
|
+
) {
|
|
32
|
+
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
|
33
|
+
if (!target.constructor.__methods) {
|
|
34
|
+
target.constructor.__methods = {};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
target.constructor.__methods[propertyKey] = {
|
|
38
|
+
description,
|
|
39
|
+
paramDescriptions: paramDescriptions || {},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return descriptor;
|
|
43
|
+
};
|
|
44
|
+
}
|