@streetjs/ai 1.0.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/README.md +107 -0
- package/dist/index.d.ts +183 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +227 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/hassanmubiru/StreetJS/main/docs/assets/images/logo-512.png" alt="StreetJS logo" width="100" height="100">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# @streetjs/ai
|
|
6
|
+
|
|
7
|
+
Official StreetJS Framework AI module: a **provider-agnostic** surface for LLM
|
|
8
|
+
chat, embeddings, retrieval-augmented generation (RAG), and tool calling.
|
|
9
|
+
|
|
10
|
+
- One `AiProvider` contract; swap implementations freely
|
|
11
|
+
- Adapters: `OpenAiProvider`, `AnthropicProvider`, `OllamaProvider`
|
|
12
|
+
- `FakeAiProvider` — deterministic, network-free; default for tests/offline dev
|
|
13
|
+
- `RagPipeline` — embed → store → retrieve → answer (with `InMemoryVectorStore`)
|
|
14
|
+
- `ChatSession` — a tool-calling loop (model requests tools, you run handlers)
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @streetjs/ai
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Chat
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { OpenAiProvider } from '@streetjs/ai';
|
|
26
|
+
|
|
27
|
+
const ai = new OpenAiProvider({ apiKey: process.env.OPENAI_API_KEY });
|
|
28
|
+
const res = await ai.chat({ messages: [{ role: 'user', content: 'Hello!' }] });
|
|
29
|
+
console.log(res.message.content, res.usage);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Swap providers without touching call sites:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { AnthropicProvider, OllamaProvider } from '@streetjs/ai';
|
|
36
|
+
const claude = new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY });
|
|
37
|
+
const local = new OllamaProvider({ baseUrl: 'http://127.0.0.1:11434' });
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Embeddings + RAG
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { RagPipeline, OpenAiProvider } from '@streetjs/ai';
|
|
44
|
+
|
|
45
|
+
const rag = new RagPipeline({ provider: new OpenAiProvider({ apiKey }), topK: 4 });
|
|
46
|
+
await rag.index([
|
|
47
|
+
{ id: 'd1', text: 'The Eiffel Tower is in Paris.' },
|
|
48
|
+
{ id: 'd2', text: 'Mount Everest is the tallest mountain.' },
|
|
49
|
+
]);
|
|
50
|
+
const { answer, context } = await rag.answer('Where is the Eiffel Tower?');
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Tool calling
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { ChatSession, OpenAiProvider } from '@streetjs/ai';
|
|
57
|
+
|
|
58
|
+
const session = new ChatSession({
|
|
59
|
+
provider: new OpenAiProvider({ apiKey }),
|
|
60
|
+
system: 'You can do arithmetic.',
|
|
61
|
+
tools: [{
|
|
62
|
+
name: 'add',
|
|
63
|
+
description: 'Add two numbers',
|
|
64
|
+
parameters: { type: 'object', properties: { a: { type: 'number' }, b: { type: 'number' } } },
|
|
65
|
+
handler: ({ a, b }) => Number(a) + Number(b),
|
|
66
|
+
}],
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const { message, toolCallsExecuted } = await session.send('what is 2 + 3?');
|
|
70
|
+
// session runs the tool, feeds the result back, and returns the final answer
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Testing without network
|
|
74
|
+
|
|
75
|
+
`FakeAiProvider` is deterministic and offline. Its embeddings are hashed
|
|
76
|
+
bag-of-words vectors, so lexically similar text scores higher — enough to
|
|
77
|
+
exercise RAG end-to-end in tests. The HTTP adapters accept an injectable
|
|
78
|
+
`fetch`, so request/response handling is unit-tested without real API calls.
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { FakeAiProvider, RagPipeline } from '@streetjs/ai';
|
|
82
|
+
const rag = new RagPipeline({ provider: new FakeAiProvider() });
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API
|
|
86
|
+
|
|
87
|
+
- Providers: `OpenAiProvider`, `AnthropicProvider`, `OllamaProvider`, `FakeAiProvider`
|
|
88
|
+
- `RagPipeline` (`index`, `retrieve`, `answer`), `InMemoryVectorStore`, `cosineSimilarity`, `hashEmbedding`
|
|
89
|
+
- `ChatSession` (`send`, `messages`)
|
|
90
|
+
- Types: `AiProvider`, `ChatRequest/Response`, `ChatMessage`, `ToolCall`, `ToolDefinition`, `EmbedRequest/Response`
|
|
91
|
+
|
|
92
|
+
## Notes
|
|
93
|
+
|
|
94
|
+
- `AnthropicProvider` does not support embeddings (use OpenAI or Ollama).
|
|
95
|
+
- Tool-call wiring is implemented for the OpenAI adapter; Anthropic/Ollama
|
|
96
|
+
adapters cover chat + (Ollama) embeddings. Function-calling for those is a
|
|
97
|
+
tracked follow-up.
|
|
98
|
+
|
|
99
|
+
## Testing
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm run test -w packages/ai # unit + property tests, fully offline
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
export type Role = 'system' | 'user' | 'assistant' | 'tool';
|
|
2
|
+
/** A request from the model to invoke a tool. */
|
|
3
|
+
export interface ToolCall {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
/** Parsed arguments object the tool was called with. */
|
|
7
|
+
arguments: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
/** A chat message. `toolCalls` is set on assistant turns that request tools; */
|
|
10
|
+
/** `toolCallId` links a `tool` message back to the call it answers. */
|
|
11
|
+
export interface ChatMessage {
|
|
12
|
+
role: Role;
|
|
13
|
+
content: string;
|
|
14
|
+
toolCalls?: ToolCall[];
|
|
15
|
+
toolCallId?: string;
|
|
16
|
+
}
|
|
17
|
+
/** A callable tool exposed to the model. */
|
|
18
|
+
export interface ToolDefinition {
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
/** JSON-schema-ish parameter description (passed through to the provider). */
|
|
22
|
+
parameters: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
export interface TokenUsage {
|
|
25
|
+
promptTokens: number;
|
|
26
|
+
completionTokens: number;
|
|
27
|
+
}
|
|
28
|
+
export interface ChatRequest {
|
|
29
|
+
messages: ChatMessage[];
|
|
30
|
+
tools?: ToolDefinition[];
|
|
31
|
+
model?: string;
|
|
32
|
+
temperature?: number;
|
|
33
|
+
maxTokens?: number;
|
|
34
|
+
}
|
|
35
|
+
export interface ChatResponse {
|
|
36
|
+
message: ChatMessage;
|
|
37
|
+
finishReason: 'stop' | 'tool_calls' | 'length';
|
|
38
|
+
usage?: TokenUsage;
|
|
39
|
+
}
|
|
40
|
+
export interface EmbedRequest {
|
|
41
|
+
input: string[];
|
|
42
|
+
model?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface EmbedResponse {
|
|
45
|
+
/** One embedding vector per input, in order. */
|
|
46
|
+
embeddings: number[][];
|
|
47
|
+
usage?: TokenUsage;
|
|
48
|
+
}
|
|
49
|
+
/** The common provider contract. */
|
|
50
|
+
export interface AiProvider {
|
|
51
|
+
readonly name: string;
|
|
52
|
+
chat(request: ChatRequest): Promise<ChatResponse>;
|
|
53
|
+
embed(request: EmbedRequest): Promise<EmbedResponse>;
|
|
54
|
+
}
|
|
55
|
+
/** Cosine similarity of two equal-length vectors. Returns 0 for zero vectors. */
|
|
56
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
57
|
+
/**
|
|
58
|
+
* Deterministic hashed bag-of-words embedding: lexical overlap → higher cosine
|
|
59
|
+
* similarity. Not semantic, but reproducible and good enough to exercise RAG.
|
|
60
|
+
*/
|
|
61
|
+
export declare function hashEmbedding(text: string, dim?: number): number[];
|
|
62
|
+
export interface FakeAiProviderOptions {
|
|
63
|
+
/**
|
|
64
|
+
* Optional scripted chat behaviour. Given the request, return the assistant
|
|
65
|
+
* message and finish reason. Defaults to echoing a summary of the last user
|
|
66
|
+
* message. Use this to script tool-calls in tests.
|
|
67
|
+
*/
|
|
68
|
+
chatScript?: (request: ChatRequest) => ChatResponse;
|
|
69
|
+
/** Embedding dimensionality. Default 64. */
|
|
70
|
+
dim?: number;
|
|
71
|
+
}
|
|
72
|
+
/** Deterministic, network-free provider for tests, examples, and offline dev. */
|
|
73
|
+
export declare class FakeAiProvider implements AiProvider {
|
|
74
|
+
readonly name = "fake";
|
|
75
|
+
private readonly dim;
|
|
76
|
+
private readonly chatScript;
|
|
77
|
+
constructor(options?: FakeAiProviderOptions);
|
|
78
|
+
chat(request: ChatRequest): Promise<ChatResponse>;
|
|
79
|
+
embed(request: EmbedRequest): Promise<EmbedResponse>;
|
|
80
|
+
}
|
|
81
|
+
export interface VectorRecord {
|
|
82
|
+
id: string;
|
|
83
|
+
text: string;
|
|
84
|
+
embedding: number[];
|
|
85
|
+
metadata?: Record<string, unknown>;
|
|
86
|
+
}
|
|
87
|
+
export interface ScoredRecord {
|
|
88
|
+
record: VectorRecord;
|
|
89
|
+
score: number;
|
|
90
|
+
}
|
|
91
|
+
/** Pluggable vector store. */
|
|
92
|
+
export interface VectorStore {
|
|
93
|
+
upsert(record: VectorRecord): Promise<void>;
|
|
94
|
+
remove(id: string): Promise<boolean>;
|
|
95
|
+
/** Top-`k` records by cosine similarity to `embedding`, score-desc. */
|
|
96
|
+
query(embedding: number[], k: number): Promise<ScoredRecord[]>;
|
|
97
|
+
size(): Promise<number>;
|
|
98
|
+
}
|
|
99
|
+
/** In-process vector store using exact cosine similarity. */
|
|
100
|
+
export declare class InMemoryVectorStore implements VectorStore {
|
|
101
|
+
private readonly records;
|
|
102
|
+
upsert(record: VectorRecord): Promise<void>;
|
|
103
|
+
remove(id: string): Promise<boolean>;
|
|
104
|
+
query(embedding: number[], k: number): Promise<ScoredRecord[]>;
|
|
105
|
+
size(): Promise<number>;
|
|
106
|
+
}
|
|
107
|
+
/** A document to index into a {@link RagPipeline}. */
|
|
108
|
+
export interface RagDocument {
|
|
109
|
+
id: string;
|
|
110
|
+
text: string;
|
|
111
|
+
metadata?: Record<string, unknown>;
|
|
112
|
+
}
|
|
113
|
+
export interface RagAnswer {
|
|
114
|
+
answer: string;
|
|
115
|
+
/** The records used as context, most relevant first. */
|
|
116
|
+
context: ScoredRecord[];
|
|
117
|
+
usage?: TokenUsage;
|
|
118
|
+
}
|
|
119
|
+
export interface RagPipelineOptions {
|
|
120
|
+
provider: AiProvider;
|
|
121
|
+
store?: VectorStore;
|
|
122
|
+
/** Records to retrieve per query. Default 4. */
|
|
123
|
+
topK?: number;
|
|
124
|
+
/** Embedding model passed to the provider. */
|
|
125
|
+
embedModel?: string;
|
|
126
|
+
/** Chat model passed to the provider. */
|
|
127
|
+
chatModel?: string;
|
|
128
|
+
}
|
|
129
|
+
/** Retrieval-augmented generation: embed → store → retrieve → answer. */
|
|
130
|
+
export declare class RagPipeline {
|
|
131
|
+
private readonly provider;
|
|
132
|
+
private readonly store;
|
|
133
|
+
private readonly topK;
|
|
134
|
+
private readonly embedModel;
|
|
135
|
+
private readonly chatModel;
|
|
136
|
+
constructor(options: RagPipelineOptions);
|
|
137
|
+
/** Embed and store documents for later retrieval. */
|
|
138
|
+
index(docs: RagDocument[]): Promise<void>;
|
|
139
|
+
/** Retrieve the most relevant records for `query`. */
|
|
140
|
+
retrieve(query: string, k?: number): Promise<ScoredRecord[]>;
|
|
141
|
+
/**
|
|
142
|
+
* Answer `query` grounded in retrieved context. Builds a system prompt from
|
|
143
|
+
* the top-`k` records and asks the chat model. With {@link FakeAiProvider}
|
|
144
|
+
* this is deterministic.
|
|
145
|
+
*/
|
|
146
|
+
answer(query: string, k?: number): Promise<RagAnswer>;
|
|
147
|
+
}
|
|
148
|
+
/** A tool the model may call, paired with its executor. */
|
|
149
|
+
export interface RegisteredTool extends ToolDefinition {
|
|
150
|
+
handler: (args: Record<string, unknown>) => Promise<unknown> | unknown;
|
|
151
|
+
}
|
|
152
|
+
export interface ChatSessionOptions {
|
|
153
|
+
provider: AiProvider;
|
|
154
|
+
tools?: RegisteredTool[];
|
|
155
|
+
system?: string;
|
|
156
|
+
model?: string;
|
|
157
|
+
/** Max provider round-trips before giving up on a tool loop. Default 5. */
|
|
158
|
+
maxIterations?: number;
|
|
159
|
+
}
|
|
160
|
+
export interface SendResult {
|
|
161
|
+
message: ChatMessage;
|
|
162
|
+
/** Number of tool calls executed while producing this answer. */
|
|
163
|
+
toolCallsExecuted: number;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* A stateful chat session that drives the tool-calling loop: when the model
|
|
167
|
+
* returns `tool_calls`, the session runs the matching handlers, appends the
|
|
168
|
+
* results as `tool` messages, and re-queries until the model produces a final
|
|
169
|
+
* answer (or `maxIterations` is reached).
|
|
170
|
+
*/
|
|
171
|
+
export declare class ChatSession {
|
|
172
|
+
private readonly provider;
|
|
173
|
+
private readonly tools;
|
|
174
|
+
private readonly toolDefs;
|
|
175
|
+
private readonly model;
|
|
176
|
+
private readonly maxIterations;
|
|
177
|
+
readonly messages: ChatMessage[];
|
|
178
|
+
constructor(options: ChatSessionOptions);
|
|
179
|
+
/** Send a user message and resolve to the final assistant message. */
|
|
180
|
+
send(userMessage: string): Promise<SendResult>;
|
|
181
|
+
}
|
|
182
|
+
export * from './providers.js';
|
|
183
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// packages/ai/src/index.ts
|
|
2
|
+
// Official Street Framework AI module: @streetjs/ai.
|
|
3
|
+
//
|
|
4
|
+
// A provider-agnostic surface for LLM chat, embeddings, retrieval-augmented
|
|
5
|
+
// generation (RAG), and tool calling.
|
|
6
|
+
//
|
|
7
|
+
// * AiProvider — the common contract (chat + embed).
|
|
8
|
+
// * FakeAiProvider — deterministic, dependency-free; default for tests,
|
|
9
|
+
// examples, and offline development. Its embeddings
|
|
10
|
+
// are hashed bag-of-words vectors, so lexical overlap
|
|
11
|
+
// yields higher cosine similarity (RAG is meaningful
|
|
12
|
+
// and reproducible without network access).
|
|
13
|
+
// * OpenAiProvider / AnthropicProvider / OllamaProvider — real HTTP adapters
|
|
14
|
+
// with an injectable `fetch`, so request shaping and
|
|
15
|
+
// response parsing are unit-testable without network.
|
|
16
|
+
// * VectorStore / InMemoryVectorStore + cosineSimilarity — vector search.
|
|
17
|
+
// * RagPipeline — embed → store → retrieve → answer.
|
|
18
|
+
// * ChatSession — a tool-calling loop (model requests tools, we run
|
|
19
|
+
// registered handlers, feed results back, repeat).
|
|
20
|
+
// ── Vector math ───────────────────────────────────────────────────────────────
|
|
21
|
+
/** Cosine similarity of two equal-length vectors. Returns 0 for zero vectors. */
|
|
22
|
+
export function cosineSimilarity(a, b) {
|
|
23
|
+
if (a.length !== b.length) {
|
|
24
|
+
throw new Error(`cosineSimilarity: dimension mismatch (${a.length} vs ${b.length})`);
|
|
25
|
+
}
|
|
26
|
+
let dot = 0;
|
|
27
|
+
let na = 0;
|
|
28
|
+
let nb = 0;
|
|
29
|
+
for (let i = 0; i < a.length; i++) {
|
|
30
|
+
dot += a[i] * b[i];
|
|
31
|
+
na += a[i] * a[i];
|
|
32
|
+
nb += b[i] * b[i];
|
|
33
|
+
}
|
|
34
|
+
if (na === 0 || nb === 0)
|
|
35
|
+
return 0;
|
|
36
|
+
return dot / (Math.sqrt(na) * Math.sqrt(nb));
|
|
37
|
+
}
|
|
38
|
+
// ── Deterministic fake provider ─────────────────────────────────────────────────
|
|
39
|
+
const FAKE_DIM = 64;
|
|
40
|
+
/** Lowercase alphanumeric tokens. */
|
|
41
|
+
function tokenize(text) {
|
|
42
|
+
return text.toLowerCase().match(/[a-z0-9]+/g) ?? [];
|
|
43
|
+
}
|
|
44
|
+
/** Stable 32-bit FNV-1a hash. */
|
|
45
|
+
function fnv1a(s) {
|
|
46
|
+
let h = 0x811c9dc5;
|
|
47
|
+
for (let i = 0; i < s.length; i++) {
|
|
48
|
+
h ^= s.charCodeAt(i);
|
|
49
|
+
h = Math.imul(h, 0x01000193);
|
|
50
|
+
}
|
|
51
|
+
return h >>> 0;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Deterministic hashed bag-of-words embedding: lexical overlap → higher cosine
|
|
55
|
+
* similarity. Not semantic, but reproducible and good enough to exercise RAG.
|
|
56
|
+
*/
|
|
57
|
+
export function hashEmbedding(text, dim = FAKE_DIM) {
|
|
58
|
+
const v = new Array(dim).fill(0);
|
|
59
|
+
for (const tok of tokenize(text)) {
|
|
60
|
+
v[fnv1a(tok) % dim] += 1;
|
|
61
|
+
}
|
|
62
|
+
return v;
|
|
63
|
+
}
|
|
64
|
+
/** Deterministic, network-free provider for tests, examples, and offline dev. */
|
|
65
|
+
export class FakeAiProvider {
|
|
66
|
+
name = 'fake';
|
|
67
|
+
dim;
|
|
68
|
+
chatScript;
|
|
69
|
+
constructor(options = {}) {
|
|
70
|
+
this.dim = options.dim ?? FAKE_DIM;
|
|
71
|
+
this.chatScript = options.chatScript;
|
|
72
|
+
}
|
|
73
|
+
async chat(request) {
|
|
74
|
+
if (this.chatScript)
|
|
75
|
+
return this.chatScript(request);
|
|
76
|
+
const lastUser = [...request.messages].reverse().find((m) => m.role === 'user');
|
|
77
|
+
const content = lastUser ? `echo: ${lastUser.content}` : 'echo: (no user message)';
|
|
78
|
+
return {
|
|
79
|
+
message: { role: 'assistant', content },
|
|
80
|
+
finishReason: 'stop',
|
|
81
|
+
usage: { promptTokens: countTokens(request.messages), completionTokens: tokenize(content).length },
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async embed(request) {
|
|
85
|
+
return {
|
|
86
|
+
embeddings: request.input.map((t) => hashEmbedding(t, this.dim)),
|
|
87
|
+
usage: { promptTokens: request.input.reduce((n, t) => n + tokenize(t).length, 0), completionTokens: 0 },
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function countTokens(messages) {
|
|
92
|
+
return messages.reduce((n, m) => n + tokenize(m.content).length, 0);
|
|
93
|
+
}
|
|
94
|
+
/** In-process vector store using exact cosine similarity. */
|
|
95
|
+
export class InMemoryVectorStore {
|
|
96
|
+
records = new Map();
|
|
97
|
+
async upsert(record) {
|
|
98
|
+
this.records.set(record.id, record);
|
|
99
|
+
}
|
|
100
|
+
async remove(id) {
|
|
101
|
+
return this.records.delete(id);
|
|
102
|
+
}
|
|
103
|
+
async query(embedding, k) {
|
|
104
|
+
const scored = [];
|
|
105
|
+
for (const record of this.records.values()) {
|
|
106
|
+
scored.push({ record, score: cosineSimilarity(embedding, record.embedding) });
|
|
107
|
+
}
|
|
108
|
+
scored.sort((a, b) => b.score - a.score || (a.record.id < b.record.id ? -1 : 1));
|
|
109
|
+
return scored.slice(0, Math.max(0, k));
|
|
110
|
+
}
|
|
111
|
+
async size() {
|
|
112
|
+
return this.records.size;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** Retrieval-augmented generation: embed → store → retrieve → answer. */
|
|
116
|
+
export class RagPipeline {
|
|
117
|
+
provider;
|
|
118
|
+
store;
|
|
119
|
+
topK;
|
|
120
|
+
embedModel;
|
|
121
|
+
chatModel;
|
|
122
|
+
constructor(options) {
|
|
123
|
+
if (!options?.provider)
|
|
124
|
+
throw new Error('RagPipeline: a provider is required');
|
|
125
|
+
this.provider = options.provider;
|
|
126
|
+
this.store = options.store ?? new InMemoryVectorStore();
|
|
127
|
+
this.topK = options.topK ?? 4;
|
|
128
|
+
this.embedModel = options.embedModel;
|
|
129
|
+
this.chatModel = options.chatModel;
|
|
130
|
+
}
|
|
131
|
+
/** Embed and store documents for later retrieval. */
|
|
132
|
+
async index(docs) {
|
|
133
|
+
if (docs.length === 0)
|
|
134
|
+
return;
|
|
135
|
+
const { embeddings } = await this.provider.embed({ input: docs.map((d) => d.text), model: this.embedModel });
|
|
136
|
+
await Promise.all(docs.map((d, i) => this.store.upsert({ id: d.id, text: d.text, embedding: embeddings[i], metadata: d.metadata })));
|
|
137
|
+
}
|
|
138
|
+
/** Retrieve the most relevant records for `query`. */
|
|
139
|
+
async retrieve(query, k = this.topK) {
|
|
140
|
+
const { embeddings } = await this.provider.embed({ input: [query], model: this.embedModel });
|
|
141
|
+
return this.store.query(embeddings[0], k);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Answer `query` grounded in retrieved context. Builds a system prompt from
|
|
145
|
+
* the top-`k` records and asks the chat model. With {@link FakeAiProvider}
|
|
146
|
+
* this is deterministic.
|
|
147
|
+
*/
|
|
148
|
+
async answer(query, k = this.topK) {
|
|
149
|
+
const context = await this.retrieve(query, k);
|
|
150
|
+
const contextBlock = context.map((c, i) => `[${i + 1}] ${c.record.text}`).join('\n');
|
|
151
|
+
const messages = [
|
|
152
|
+
{
|
|
153
|
+
role: 'system',
|
|
154
|
+
content: 'Answer the question using only the provided context. ' +
|
|
155
|
+
'If the context is insufficient, say so.\n\nContext:\n' + contextBlock,
|
|
156
|
+
},
|
|
157
|
+
{ role: 'user', content: query },
|
|
158
|
+
];
|
|
159
|
+
const res = await this.provider.chat({ messages, model: this.chatModel });
|
|
160
|
+
return { answer: res.message.content, context, usage: res.usage };
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* A stateful chat session that drives the tool-calling loop: when the model
|
|
165
|
+
* returns `tool_calls`, the session runs the matching handlers, appends the
|
|
166
|
+
* results as `tool` messages, and re-queries until the model produces a final
|
|
167
|
+
* answer (or `maxIterations` is reached).
|
|
168
|
+
*/
|
|
169
|
+
export class ChatSession {
|
|
170
|
+
provider;
|
|
171
|
+
tools;
|
|
172
|
+
toolDefs;
|
|
173
|
+
model;
|
|
174
|
+
maxIterations;
|
|
175
|
+
messages = [];
|
|
176
|
+
constructor(options) {
|
|
177
|
+
if (!options?.provider)
|
|
178
|
+
throw new Error('ChatSession: a provider is required');
|
|
179
|
+
this.provider = options.provider;
|
|
180
|
+
this.tools = new Map((options.tools ?? []).map((t) => [t.name, t]));
|
|
181
|
+
this.toolDefs = (options.tools ?? []).map(({ name, description, parameters }) => ({ name, description, parameters }));
|
|
182
|
+
this.model = options.model;
|
|
183
|
+
this.maxIterations = options.maxIterations ?? 5;
|
|
184
|
+
if (options.system)
|
|
185
|
+
this.messages.push({ role: 'system', content: options.system });
|
|
186
|
+
}
|
|
187
|
+
/** Send a user message and resolve to the final assistant message. */
|
|
188
|
+
async send(userMessage) {
|
|
189
|
+
this.messages.push({ role: 'user', content: userMessage });
|
|
190
|
+
let toolCallsExecuted = 0;
|
|
191
|
+
for (let i = 0; i < this.maxIterations; i++) {
|
|
192
|
+
const res = await this.provider.chat({
|
|
193
|
+
messages: this.messages,
|
|
194
|
+
tools: this.toolDefs.length > 0 ? this.toolDefs : undefined,
|
|
195
|
+
model: this.model,
|
|
196
|
+
});
|
|
197
|
+
this.messages.push(res.message);
|
|
198
|
+
if (res.finishReason !== 'tool_calls' || !res.message.toolCalls?.length) {
|
|
199
|
+
return { message: res.message, toolCallsExecuted };
|
|
200
|
+
}
|
|
201
|
+
// Execute each requested tool and append its result.
|
|
202
|
+
for (const call of res.message.toolCalls) {
|
|
203
|
+
toolCallsExecuted++;
|
|
204
|
+
const tool = this.tools.get(call.name);
|
|
205
|
+
let content;
|
|
206
|
+
try {
|
|
207
|
+
if (!tool)
|
|
208
|
+
throw new Error(`unknown tool "${call.name}"`);
|
|
209
|
+
const result = await tool.handler(call.arguments);
|
|
210
|
+
content = typeof result === 'string' ? result : JSON.stringify(result);
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
content = JSON.stringify({ error: err.message });
|
|
214
|
+
}
|
|
215
|
+
this.messages.push({ role: 'tool', content, toolCallId: call.id });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Loop budget exhausted: return the last assistant message we have.
|
|
219
|
+
const lastAssistant = [...this.messages].reverse().find((m) => m.role === 'assistant');
|
|
220
|
+
return {
|
|
221
|
+
message: lastAssistant ?? { role: 'assistant', content: '' },
|
|
222
|
+
toolCallsExecuted,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
export * from './providers.js';
|
|
227
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,qDAAqD;AACrD,EAAE;AACF,4EAA4E;AAC5E,sCAAsC;AACtC,EAAE;AACF,gEAAgE;AAChE,+EAA+E;AAC/E,+EAA+E;AAC/E,iFAAiF;AACjF,gFAAgF;AAChF,uEAAuE;AACvE,+EAA+E;AAC/E,gFAAgF;AAChF,iFAAiF;AACjF,4EAA4E;AAC5E,+DAA+D;AAC/D,8EAA8E;AAC9E,8EAA8E;AAoE9E,iFAAiF;AAEjF,iFAAiF;AACjF,MAAM,UAAU,gBAAgB,CAAC,CAAW,EAAE,CAAW;IACvD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACvF,CAAC;IACD,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;QACrB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;QACpB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;IACtB,CAAC;IACD,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACnC,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,mFAAmF;AAEnF,MAAM,QAAQ,GAAG,EAAE,CAAC;AAEpB,qCAAqC;AACrC,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;AACtD,CAAC;AAED,iCAAiC;AACjC,SAAS,KAAK,CAAC,CAAS;IACtB,IAAI,CAAC,GAAG,UAAU,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,GAAG,GAAG,QAAQ;IACxD,MAAM,CAAC,GAAG,IAAI,KAAK,CAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,CAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAaD,iFAAiF;AACjF,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,MAAM,CAAC;IACN,GAAG,CAAS;IACZ,UAAU,CAAuD;IAElF,YAAY,UAAiC,EAAE;QAC7C,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,QAAQ,CAAC;QACnC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAoB;QAC7B,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAChF,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,yBAAyB,CAAC;QACnF,OAAO;YACL,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE;YACvC,YAAY,EAAE,MAAM;YACpB,KAAK,EAAE,EAAE,YAAY,EAAE,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,gBAAgB,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE;SACnG,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAqB;QAC/B,OAAO;YACL,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YAChE,KAAK,EAAE,EAAE,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE;SACxG,CAAC;IACJ,CAAC;CACF;AAED,SAAS,WAAW,CAAC,QAAuB;IAC1C,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACtE,CAAC;AAyBD,6DAA6D;AAC7D,MAAM,OAAO,mBAAmB;IACb,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE3D,KAAK,CAAC,MAAM,CAAC,MAAoB;QAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,SAAmB,EAAE,CAAS;QACxC,MAAM,MAAM,GAAmB,EAAE,CAAC;QAClC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjF,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF;AA2BD,yEAAyE;AACzE,MAAM,OAAO,WAAW;IACL,QAAQ,CAAa;IACrB,KAAK,CAAc;IACnB,IAAI,CAAS;IACb,UAAU,CAAqB;IAC/B,SAAS,CAAqB;IAE/C,YAAY,OAA2B;QACrC,IAAI,CAAC,OAAO,EAAE,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC/E,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,mBAAmB,EAAE,CAAC;QACxD,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IACrC,CAAC;IAED,qDAAqD;IACrD,KAAK,CAAC,KAAK,CAAC,IAAmB;QAC7B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC9B,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QAC7G,MAAM,OAAO,CAAC,GAAG,CACf,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAChB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAC/F,CACF,CAAC;IACJ,CAAC;IAED,sDAAsD;IACtD,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI;QACzC,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QAC7F,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI;QACvC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC9C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrF,MAAM,QAAQ,GAAkB;YAC9B;gBACE,IAAI,EAAE,QAAQ;gBACd,OAAO,EACL,uDAAuD;oBACvD,uDAAuD,GAAG,YAAY;aACzE;YACD,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE;SACjC,CAAC;QACF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1E,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;IACpE,CAAC;CACF;AAwBD;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IACL,QAAQ,CAAa;IACrB,KAAK,CAA8B;IACnC,QAAQ,CAAmB;IAC3B,KAAK,CAAqB;IAC1B,aAAa,CAAS;IAC9B,QAAQ,GAAkB,EAAE,CAAC;IAEtC,YAAY,OAA2B;QACrC,IAAI,CAAC,OAAO,EAAE,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC/E,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,IAAI,CAAC,QAAQ,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;QACtH,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;QAChD,IAAI,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,sEAAsE;IACtE,KAAK,CAAC,IAAI,CAAC,WAAmB;QAC5B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QAC3D,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAE1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;gBAC3D,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAEhC,IAAI,GAAG,CAAC,YAAY,KAAK,YAAY,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;gBACxE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,iBAAiB,EAAE,CAAC;YACrD,CAAC;YAED,qDAAqD;YACrD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBACzC,iBAAiB,EAAE,CAAC;gBACpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvC,IAAI,OAAe,CAAC;gBACpB,IAAI,CAAC;oBACH,IAAI,CAAC,IAAI;wBAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;oBAC1D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBAClD,OAAO,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBACzE,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC9D,CAAC;gBACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QAED,oEAAoE;QACpE,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;QACvF,OAAO;YACL,OAAO,EAAE,aAAa,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE;YAC5D,iBAAiB;SAClB,CAAC;IACJ,CAAC;CACF;AAED,cAAc,gBAAgB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@streetjs/ai",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official Street Framework AI module: provider-agnostic chat, embeddings, RAG, and tool-calling with OpenAI/Anthropic/Ollama adapters and a deterministic in-memory provider for tests.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/index.js",
|
|
16
|
+
"dist/index.js.map",
|
|
17
|
+
"dist/index.d.ts",
|
|
18
|
+
"dist/index.d.ts.map",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"lint": "tsc --noEmit",
|
|
24
|
+
"test": "tsc && node --test dist/tests/*.test.js",
|
|
25
|
+
"example": "npm run build && node examples/index.mjs",
|
|
26
|
+
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
27
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"street",
|
|
31
|
+
"streetjs",
|
|
32
|
+
"street-framework",
|
|
33
|
+
"ai",
|
|
34
|
+
"llm",
|
|
35
|
+
"embeddings",
|
|
36
|
+
"rag",
|
|
37
|
+
"tool-calling",
|
|
38
|
+
"openai",
|
|
39
|
+
"anthropic",
|
|
40
|
+
"ollama"
|
|
41
|
+
],
|
|
42
|
+
"author": "street contributors",
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"homepage": "https://hassanmubiru.github.io/StreetJS/",
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/hassanmubiru/StreetJS.git"
|
|
48
|
+
},
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/hassanmubiru/StreetJS/issues"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^25.9.2",
|
|
54
|
+
"fast-check": "^4.8.0",
|
|
55
|
+
"typescript": "^6.0.3"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"typescript": ">=5.0.0"
|
|
59
|
+
},
|
|
60
|
+
"engines": {
|
|
61
|
+
"node": ">=22.0.0"
|
|
62
|
+
},
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
}
|
|
66
|
+
}
|