@micrantha/react-native-amaryllis 0.1.1 → 0.1.5
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 +43 -8
- package/android/src/main/java/com/micrantha/amaryllis/Amaryllis.kt +83 -8
- package/lib/module/Amaryllis.js +75 -20
- package/lib/module/Amaryllis.js.map +1 -1
- package/lib/module/AmaryllisContext.js +14 -4
- package/lib/module/AmaryllisContext.js.map +1 -1
- package/lib/module/AmaryllisHooks.js +87 -4
- package/lib/module/AmaryllisHooks.js.map +1 -1
- package/lib/module/AmaryllisRx.js +15 -14
- package/lib/module/AmaryllisRx.js.map +1 -1
- package/lib/module/ContextEngine.js +87 -0
- package/lib/module/ContextEngine.js.map +1 -0
- package/lib/module/ContextEngineContext.js +22 -0
- package/lib/module/ContextEngineContext.js.map +1 -0
- package/lib/module/ContextPolicies.js +46 -0
- package/lib/module/ContextPolicies.js.map +1 -0
- package/lib/module/ContextTypes.js +4 -0
- package/lib/module/ContextTypes.js.map +1 -0
- package/lib/module/ContextValidation.js +189 -0
- package/lib/module/ContextValidation.js.map +1 -0
- package/lib/module/Errors.js +46 -0
- package/lib/module/Errors.js.map +1 -0
- package/lib/module/NativeAmaryllis.js.map +1 -1
- package/lib/module/TypeConverters.js +80 -0
- package/lib/module/TypeConverters.js.map +1 -0
- package/lib/module/context.js +8 -0
- package/lib/module/context.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/Amaryllis.d.ts.map +1 -1
- package/lib/typescript/src/AmaryllisContext.d.ts.map +1 -1
- package/lib/typescript/src/AmaryllisHooks.d.ts +8 -1
- package/lib/typescript/src/AmaryllisHooks.d.ts.map +1 -1
- package/lib/typescript/src/AmaryllisRx.d.ts.map +1 -1
- package/lib/typescript/src/ContextEngine.d.ts +19 -0
- package/lib/typescript/src/ContextEngine.d.ts.map +1 -0
- package/lib/typescript/src/ContextEngineContext.d.ts +9 -0
- package/lib/typescript/src/ContextEngineContext.d.ts.map +1 -0
- package/lib/typescript/src/ContextPolicies.d.ts +4 -0
- package/lib/typescript/src/ContextPolicies.d.ts.map +1 -0
- package/lib/typescript/src/ContextTypes.d.ts +92 -0
- package/lib/typescript/src/ContextTypes.d.ts.map +1 -0
- package/lib/typescript/src/ContextValidation.d.ts +9 -0
- package/lib/typescript/src/ContextValidation.d.ts.map +1 -0
- package/lib/typescript/src/Errors.d.ts +22 -0
- package/lib/typescript/src/Errors.d.ts.map +1 -0
- package/lib/typescript/src/NativeAmaryllis.d.ts +24 -4
- package/lib/typescript/src/NativeAmaryllis.d.ts.map +1 -1
- package/lib/typescript/src/TypeConverters.d.ts +43 -0
- package/lib/typescript/src/TypeConverters.d.ts.map +1 -0
- package/lib/typescript/src/Types.d.ts +14 -0
- package/lib/typescript/src/Types.d.ts.map +1 -1
- package/lib/typescript/src/context.d.ts +8 -0
- package/lib/typescript/src/context.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +33 -27
- package/src/Amaryllis.ts +75 -24
- package/src/AmaryllisContext.tsx +19 -4
- package/src/AmaryllisHooks.tsx +106 -5
- package/src/AmaryllisRx.ts +13 -9
- package/src/ContextEngine.ts +133 -0
- package/src/ContextEngineContext.tsx +31 -0
- package/src/ContextPolicies.ts +54 -0
- package/src/ContextTypes.ts +122 -0
- package/src/ContextValidation.ts +279 -0
- package/src/Errors.ts +55 -0
- package/src/NativeAmaryllis.ts +18 -4
- package/src/TypeConverters.ts +87 -0
- package/src/Types.ts +9 -0
- package/src/context.ts +14 -0
- package/src/index.tsx +5 -0
package/src/AmaryllisHooks.tsx
CHANGED
|
@@ -1,7 +1,42 @@
|
|
|
1
1
|
import { useCallback, useMemo, useEffect } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { InferenceProps, LlmRequestParams } from './Types';
|
|
3
3
|
import { useLLMContext } from './AmaryllisContext';
|
|
4
4
|
import { createLLMObservable } from './AmaryllisRx';
|
|
5
|
+
import { useContextEngine } from './ContextEngineContext';
|
|
6
|
+
import type { ContextEngine, ContextQuery } from './ContextTypes';
|
|
7
|
+
|
|
8
|
+
export type ContextInferenceProps = InferenceProps & {
|
|
9
|
+
contextEngine?: ContextEngine;
|
|
10
|
+
query?: ContextQuery;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const useContextAugmentation = (
|
|
14
|
+
contextEngine?: ContextEngine,
|
|
15
|
+
query?: ContextQuery
|
|
16
|
+
) => {
|
|
17
|
+
const engineFromProvider = useContextEngine();
|
|
18
|
+
const engine = contextEngine ?? engineFromProvider;
|
|
19
|
+
|
|
20
|
+
return useCallback(
|
|
21
|
+
async (params: LlmRequestParams): Promise<LlmRequestParams> => {
|
|
22
|
+
if (!engine) {
|
|
23
|
+
return params;
|
|
24
|
+
}
|
|
25
|
+
const resolvedQuery = query ?? engine.deriveQuery(params.prompt, params);
|
|
26
|
+
if (!resolvedQuery) {
|
|
27
|
+
return params;
|
|
28
|
+
}
|
|
29
|
+
const items = await engine.search(resolvedQuery);
|
|
30
|
+
return engine.formatRequest({
|
|
31
|
+
prompt: params.prompt,
|
|
32
|
+
items,
|
|
33
|
+
query: resolvedQuery,
|
|
34
|
+
request: params,
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
[engine, query]
|
|
38
|
+
);
|
|
39
|
+
};
|
|
5
40
|
|
|
6
41
|
export const useInferenceAsync = (props: InferenceProps = {}) => {
|
|
7
42
|
const { controller } = useLLMContext();
|
|
@@ -11,16 +46,23 @@ export const useInferenceAsync = (props: InferenceProps = {}) => {
|
|
|
11
46
|
|
|
12
47
|
const generate = useCallback(
|
|
13
48
|
async (params: LlmRequestParams) => {
|
|
49
|
+
if (!controller) {
|
|
50
|
+
onError?.(new Error('Controller not initialized'));
|
|
51
|
+
return () => {
|
|
52
|
+
onComplete?.();
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
14
56
|
try {
|
|
15
57
|
onGenerate?.();
|
|
16
|
-
await controller
|
|
58
|
+
await controller.generateAsync(params, llm$.callbacks);
|
|
17
59
|
} catch (err) {
|
|
18
60
|
onError?.(
|
|
19
61
|
err instanceof Error ? err : new Error('An unknown error occurred')
|
|
20
62
|
);
|
|
21
63
|
}
|
|
22
64
|
return () => {
|
|
23
|
-
controller
|
|
65
|
+
controller.cancelAsync();
|
|
24
66
|
onComplete?.();
|
|
25
67
|
};
|
|
26
68
|
},
|
|
@@ -56,9 +98,16 @@ export const useInference = (props: InferenceProps = {}) => {
|
|
|
56
98
|
|
|
57
99
|
const generate = useCallback(
|
|
58
100
|
async (params: LlmRequestParams) => {
|
|
101
|
+
if (!controller) {
|
|
102
|
+
onError?.(new Error('Controller not initialized'));
|
|
103
|
+
return () => {
|
|
104
|
+
onComplete?.();
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
59
108
|
try {
|
|
60
109
|
onGenerate?.();
|
|
61
|
-
const response = await controller
|
|
110
|
+
const response = await controller.generate(params);
|
|
62
111
|
onResult?.(response ?? '', true);
|
|
63
112
|
} catch (err) {
|
|
64
113
|
onError?.(
|
|
@@ -67,7 +116,7 @@ export const useInference = (props: InferenceProps = {}) => {
|
|
|
67
116
|
}
|
|
68
117
|
|
|
69
118
|
return () => {
|
|
70
|
-
controller
|
|
119
|
+
controller.cancelAsync();
|
|
71
120
|
onComplete?.();
|
|
72
121
|
};
|
|
73
122
|
},
|
|
@@ -76,3 +125,55 @@ export const useInference = (props: InferenceProps = {}) => {
|
|
|
76
125
|
|
|
77
126
|
return generate;
|
|
78
127
|
};
|
|
128
|
+
|
|
129
|
+
export const useContextInferenceAsync = (props: ContextInferenceProps = {}) => {
|
|
130
|
+
const { contextEngine, query, ...inferenceProps } = props;
|
|
131
|
+
const { onComplete, onError } = inferenceProps;
|
|
132
|
+
const augmentRequest = useContextAugmentation(contextEngine, query);
|
|
133
|
+
const generateBase = useInferenceAsync(inferenceProps);
|
|
134
|
+
|
|
135
|
+
const generate = useCallback(
|
|
136
|
+
async (params: LlmRequestParams) => {
|
|
137
|
+
try {
|
|
138
|
+
const augmented = await augmentRequest(params);
|
|
139
|
+
return await generateBase(augmented);
|
|
140
|
+
} catch (err) {
|
|
141
|
+
onError?.(
|
|
142
|
+
err instanceof Error ? err : new Error('An unknown error occurred')
|
|
143
|
+
);
|
|
144
|
+
return () => {
|
|
145
|
+
onComplete?.();
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
[augmentRequest, generateBase, onComplete, onError]
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
return generate;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export const useContextInference = (props: ContextInferenceProps = {}) => {
|
|
156
|
+
const { contextEngine, query, ...inferenceProps } = props;
|
|
157
|
+
const { onComplete, onError } = inferenceProps;
|
|
158
|
+
const augmentRequest = useContextAugmentation(contextEngine, query);
|
|
159
|
+
const generateBase = useInference(inferenceProps);
|
|
160
|
+
|
|
161
|
+
const generate = useCallback(
|
|
162
|
+
async (params: LlmRequestParams) => {
|
|
163
|
+
try {
|
|
164
|
+
const augmented = await augmentRequest(params);
|
|
165
|
+
return await generateBase(augmented);
|
|
166
|
+
} catch (err) {
|
|
167
|
+
onError?.(
|
|
168
|
+
err instanceof Error ? err : new Error('An unknown error occurred')
|
|
169
|
+
);
|
|
170
|
+
return () => {
|
|
171
|
+
onComplete?.();
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
[augmentRequest, generateBase, onComplete, onError]
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
return generate;
|
|
179
|
+
};
|
package/src/AmaryllisRx.ts
CHANGED
|
@@ -2,21 +2,25 @@ import type { LlmCallbacks, LLMObservableResult, LLMResult } from './Types';
|
|
|
2
2
|
import { Observable, Subscriber } from 'rxjs';
|
|
3
3
|
|
|
4
4
|
export function createLLMObservable(): LLMObservableResult {
|
|
5
|
-
let subscriber: Subscriber<LLMResult
|
|
5
|
+
let subscriber: Subscriber<LLMResult> | null = null;
|
|
6
6
|
|
|
7
7
|
const observable = new Observable<LLMResult>((sub) => {
|
|
8
8
|
subscriber = sub;
|
|
9
|
+
return () => {
|
|
10
|
+
subscriber = null;
|
|
11
|
+
};
|
|
9
12
|
});
|
|
10
13
|
|
|
11
14
|
const callbacks: LlmCallbacks = {
|
|
12
|
-
|
|
13
|
-
subscriber
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
onEvent: (event) => {
|
|
16
|
+
if (!subscriber) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (event.type === 'error') {
|
|
20
|
+
subscriber.error(event.error);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
subscriber.next({ text: event.text, isFinal: event.type === 'final' });
|
|
20
24
|
},
|
|
21
25
|
};
|
|
22
26
|
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ContextEngine as ContextEngineContract,
|
|
3
|
+
ContextEngineOptions,
|
|
4
|
+
ContextFormatParams,
|
|
5
|
+
ContextItem,
|
|
6
|
+
ContextQuery,
|
|
7
|
+
ContextScorer,
|
|
8
|
+
ContextDefaultQueryFactory,
|
|
9
|
+
ContextRequestFormatter,
|
|
10
|
+
} from './ContextTypes';
|
|
11
|
+
import type { LlmRequestParams } from './Types';
|
|
12
|
+
import { defaultContextScorer } from './ContextPolicies';
|
|
13
|
+
import {
|
|
14
|
+
validateContextItems,
|
|
15
|
+
validateContextPolicy,
|
|
16
|
+
validateContextQuery,
|
|
17
|
+
} from './ContextValidation';
|
|
18
|
+
|
|
19
|
+
const formatMetadata = (metadata: ContextItem['metadata']): string | null => {
|
|
20
|
+
if (!metadata) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const entries = Object.entries(metadata);
|
|
24
|
+
if (entries.length === 0) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const pairs = entries.map(([key, value]) => `${key}=${value}`);
|
|
28
|
+
return `meta=${pairs.join(', ')}`;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const formatTags = (tags: ContextItem['tags']): string | null => {
|
|
32
|
+
if (!tags || tags.length === 0) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return `tags=${tags.join(', ')}`;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const formatContextItem = (item: ContextItem): string => {
|
|
39
|
+
const parts = [
|
|
40
|
+
item.text.trim(),
|
|
41
|
+
formatTags(item.tags),
|
|
42
|
+
formatMetadata(item.metadata),
|
|
43
|
+
];
|
|
44
|
+
return parts
|
|
45
|
+
.filter((part): part is string => Boolean(part && part.length > 0))
|
|
46
|
+
.join(' | ');
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const defaultContextFormatter: ContextRequestFormatter = (
|
|
50
|
+
params: ContextFormatParams
|
|
51
|
+
) => {
|
|
52
|
+
if (params.items.length === 0) {
|
|
53
|
+
return params.request;
|
|
54
|
+
}
|
|
55
|
+
const lines = params.items.map((item) => `- ${formatContextItem(item)}`);
|
|
56
|
+
const contextBlock = ['Context:', ...lines].join('\n');
|
|
57
|
+
const augmentedPrompt = [contextBlock, params.prompt]
|
|
58
|
+
.map((entry) => entry.trim())
|
|
59
|
+
.filter((entry) => entry.length > 0)
|
|
60
|
+
.join('\n\n');
|
|
61
|
+
return {
|
|
62
|
+
...params.request,
|
|
63
|
+
prompt: augmentedPrompt,
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export class ContextEngine implements ContextEngineContract {
|
|
68
|
+
private readonly store: ContextEngineOptions['store'];
|
|
69
|
+
private readonly scorer: ContextScorer;
|
|
70
|
+
private policy: ContextEngineOptions['policy'];
|
|
71
|
+
private readonly formatter: ContextRequestFormatter;
|
|
72
|
+
private readonly defaultQueryFactory?: ContextDefaultQueryFactory;
|
|
73
|
+
|
|
74
|
+
constructor(options: ContextEngineOptions) {
|
|
75
|
+
validateContextPolicy(options.policy);
|
|
76
|
+
this.store = options.store;
|
|
77
|
+
this.scorer = options.scorer ?? defaultContextScorer;
|
|
78
|
+
this.policy = options.policy ?? {};
|
|
79
|
+
this.formatter = options.formatter ?? defaultContextFormatter;
|
|
80
|
+
this.defaultQueryFactory = options.defaultQueryFactory;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async add(items: ContextItem[]): Promise<void> {
|
|
84
|
+
validateContextItems(items, this.policy);
|
|
85
|
+
await this.store.put(items);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async search(query: ContextQuery): Promise<ContextItem[]> {
|
|
89
|
+
validateContextQuery(query);
|
|
90
|
+
const results = await this.store.query(query);
|
|
91
|
+
if (results.length <= 1) {
|
|
92
|
+
return results;
|
|
93
|
+
}
|
|
94
|
+
const scored = results.map((item, index) => ({
|
|
95
|
+
item,
|
|
96
|
+
index,
|
|
97
|
+
score: this.scorer.score(item, query),
|
|
98
|
+
}));
|
|
99
|
+
scored.sort((a, b) => {
|
|
100
|
+
if (a.score === b.score) {
|
|
101
|
+
return a.index - b.index;
|
|
102
|
+
}
|
|
103
|
+
return b.score - a.score;
|
|
104
|
+
});
|
|
105
|
+
return scored.map((entry) => entry.item);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
setPolicy(policy: ContextEngineOptions['policy']): void {
|
|
109
|
+
validateContextPolicy(policy);
|
|
110
|
+
this.policy = policy ?? {};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async compact(): Promise<void> {
|
|
114
|
+
await this.store.compact(this.policy ?? {});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
formatRequest(params: ContextFormatParams): LlmRequestParams {
|
|
118
|
+
return this.formatter(params);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
deriveQuery(
|
|
122
|
+
prompt: string,
|
|
123
|
+
request: LlmRequestParams
|
|
124
|
+
): ContextQuery | undefined {
|
|
125
|
+
return this.defaultQueryFactory?.(prompt, request);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export const createContextEngine = (
|
|
130
|
+
options: ContextEngineOptions
|
|
131
|
+
): ContextEngineContract => {
|
|
132
|
+
return new ContextEngine(options);
|
|
133
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import type { ContextEngine } from './ContextTypes';
|
|
4
|
+
|
|
5
|
+
export interface ContextEngineProviderProps {
|
|
6
|
+
engine: ContextEngine;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface ContextEngineContextValue {
|
|
11
|
+
engine: ContextEngine | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const ContextEngineContext = createContext<ContextEngineContextValue>({
|
|
15
|
+
engine: null,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const ContextEngineProvider = ({
|
|
19
|
+
engine,
|
|
20
|
+
children,
|
|
21
|
+
}: ContextEngineProviderProps) => {
|
|
22
|
+
return (
|
|
23
|
+
<ContextEngineContext.Provider value={{ engine }}>
|
|
24
|
+
{children}
|
|
25
|
+
</ContextEngineContext.Provider>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const useContextEngine = (): ContextEngine | null => {
|
|
30
|
+
return useContext(ContextEngineContext).engine;
|
|
31
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ContextItem, ContextQuery, ContextScorer } from './ContextTypes';
|
|
2
|
+
|
|
3
|
+
export const DEFAULT_RECENCY_BIAS = 0.35;
|
|
4
|
+
|
|
5
|
+
const clamp01 = (value: number): number => {
|
|
6
|
+
if (value < 0) {
|
|
7
|
+
return 0;
|
|
8
|
+
}
|
|
9
|
+
if (value > 1) {
|
|
10
|
+
return 1;
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const tokenize = (text: string): string[] => {
|
|
16
|
+
return text
|
|
17
|
+
.toLowerCase()
|
|
18
|
+
.split(/\\s+/)
|
|
19
|
+
.map((token) => token.trim())
|
|
20
|
+
.filter((token) => token.length > 0);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const keywordScore = (item: ContextItem, query: ContextQuery): number => {
|
|
24
|
+
const queryTokens = tokenize(query.text);
|
|
25
|
+
if (queryTokens.length === 0) {
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
const haystack = item.text.toLowerCase();
|
|
29
|
+
let hits = 0;
|
|
30
|
+
for (const token of queryTokens) {
|
|
31
|
+
if (haystack.includes(token)) {
|
|
32
|
+
hits += 1;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return hits / queryTokens.length;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const recencyScore = (item: ContextItem): number => {
|
|
39
|
+
const ageMs = Date.now() - item.createdAt;
|
|
40
|
+
if (!Number.isFinite(ageMs) || ageMs < 0) {
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
const ageHours = ageMs / (1000 * 60 * 60);
|
|
44
|
+
return 1 / (1 + ageHours);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const defaultContextScorer: ContextScorer = {
|
|
48
|
+
score: (item: ContextItem, query: ContextQuery): number => {
|
|
49
|
+
const bias = clamp01(query.recencyBias ?? DEFAULT_RECENCY_BIAS);
|
|
50
|
+
const recency = recencyScore(item);
|
|
51
|
+
const keyword = keywordScore(item, query);
|
|
52
|
+
return bias * recency + (1 - bias) * keyword;
|
|
53
|
+
},
|
|
54
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { LlmRequestParams } from './Types';
|
|
2
|
+
|
|
3
|
+
export type EvictionStrategy = 'lru' | 'recency' | 'size';
|
|
4
|
+
|
|
5
|
+
export interface MediaReference {
|
|
6
|
+
// Absolute path or URI depending on app policy.
|
|
7
|
+
uri: string;
|
|
8
|
+
mimeType?: string;
|
|
9
|
+
sizeBytes?: number;
|
|
10
|
+
width?: number;
|
|
11
|
+
height?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface MediaValidationPolicy {
|
|
15
|
+
// Require absolute URIs (recommended for security).
|
|
16
|
+
requireAbsoluteUri?: boolean;
|
|
17
|
+
// Whitelist of allowed URI schemes (e.g., ['file', 'content']).
|
|
18
|
+
allowedUriSchemes?: string[];
|
|
19
|
+
// Size and dimension limits for referenced media.
|
|
20
|
+
maxMediaBytes?: number;
|
|
21
|
+
maxMediaWidth?: number;
|
|
22
|
+
maxMediaHeight?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ContextItem {
|
|
26
|
+
id: string;
|
|
27
|
+
text: string;
|
|
28
|
+
metadata?: Record<string, string>;
|
|
29
|
+
tags?: string[];
|
|
30
|
+
media?: MediaReference[];
|
|
31
|
+
createdAt: number;
|
|
32
|
+
updatedAt?: number;
|
|
33
|
+
ttlSeconds?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ContextQuery {
|
|
37
|
+
text: string;
|
|
38
|
+
limit?: number;
|
|
39
|
+
filters?: Record<string, string>;
|
|
40
|
+
tags?: string[];
|
|
41
|
+
// 0..1 weighting for recency in scoring.
|
|
42
|
+
recencyBias?: number;
|
|
43
|
+
useSemantic?: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ContextPolicy {
|
|
47
|
+
maxBytes?: number;
|
|
48
|
+
maxItems?: number;
|
|
49
|
+
defaultTtlSeconds?: number;
|
|
50
|
+
evictionStrategy?: EvictionStrategy;
|
|
51
|
+
media?: MediaValidationPolicy;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ContextStoreStats {
|
|
55
|
+
itemCount: number;
|
|
56
|
+
totalBytes?: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ContextStore {
|
|
60
|
+
put(items: ContextItem[]): Promise<void>;
|
|
61
|
+
query(query: ContextQuery): Promise<ContextItem[]>;
|
|
62
|
+
delete(ids: string[]): Promise<void>;
|
|
63
|
+
compact(policy: ContextPolicy): Promise<void>;
|
|
64
|
+
stats(): Promise<ContextStoreStats>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface EmbeddingProvider {
|
|
68
|
+
embed(texts: string[]): Promise<number[][]>;
|
|
69
|
+
dimension?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface ContextEngine {
|
|
73
|
+
add(items: ContextItem[]): Promise<void>;
|
|
74
|
+
search(query: ContextQuery): Promise<ContextItem[]>;
|
|
75
|
+
setPolicy(policy: ContextPolicy): void;
|
|
76
|
+
compact(): Promise<void>;
|
|
77
|
+
formatRequest(params: ContextFormatParams): LlmRequestParams;
|
|
78
|
+
deriveQuery(
|
|
79
|
+
prompt: string,
|
|
80
|
+
request: LlmRequestParams
|
|
81
|
+
): ContextQuery | undefined;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface ContextScorer {
|
|
85
|
+
score(item: ContextItem, query: ContextQuery): number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface ContextEngineOptions {
|
|
89
|
+
store: ContextStore;
|
|
90
|
+
scorer?: ContextScorer;
|
|
91
|
+
policy?: ContextPolicy;
|
|
92
|
+
formatter?: ContextRequestFormatter;
|
|
93
|
+
defaultQueryFactory?: ContextDefaultQueryFactory;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface ContextFormatParams {
|
|
97
|
+
prompt: string;
|
|
98
|
+
items: ContextItem[];
|
|
99
|
+
query?: ContextQuery;
|
|
100
|
+
request: LlmRequestParams;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export type ContextRequestFormatter = (
|
|
104
|
+
params: ContextFormatParams
|
|
105
|
+
) => LlmRequestParams;
|
|
106
|
+
|
|
107
|
+
export type ContextDefaultQueryFactory = (
|
|
108
|
+
prompt: string,
|
|
109
|
+
request: LlmRequestParams
|
|
110
|
+
) => ContextQuery | undefined;
|
|
111
|
+
|
|
112
|
+
export interface ToolDefinition {
|
|
113
|
+
name: string;
|
|
114
|
+
description?: string;
|
|
115
|
+
// JSON schema or similar contract for tool input.
|
|
116
|
+
inputSchema?: Record<string, unknown>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface ToolRegistry {
|
|
120
|
+
register(tool: ToolDefinition): void;
|
|
121
|
+
invoke(name: string, input: unknown): Promise<unknown>;
|
|
122
|
+
}
|