@ftarganski/omni-ai 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/dist/chunk-3RZELMF2.js +214 -0
- package/dist/chunk-5WELBZWN.js +70 -0
- package/dist/chunk-6APAA6WD.js +495 -0
- package/dist/chunk-6OPRALDC.js +163 -0
- package/dist/chunk-6YFFZMXY.js +104 -0
- package/dist/chunk-AG6NZIJ3.js +122 -0
- package/dist/chunk-AWMSN7OB.js +451 -0
- package/dist/chunk-JTXDF5KG.js +156 -0
- package/dist/chunk-M4QJF7CV.js +57 -0
- package/dist/chunk-PPTEJ2FH.js +102 -0
- package/dist/chunk-S5MK6LBH.js +136 -0
- package/dist/chunk-TFU437SW.js +107 -0
- package/dist/chunk-Y4EYGADJ.js +216 -0
- package/dist/cli/bin.js +2723 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +42 -0
- package/dist/mcp.d.ts +1 -0
- package/dist/mcp.js +86 -0
- package/dist/memory.d.ts +1 -0
- package/dist/memory.js +320 -0
- package/dist/provider-anthropic.d.ts +1 -0
- package/dist/provider-anthropic.js +120 -0
- package/dist/provider-google.d.ts +1 -0
- package/dist/provider-google.js +141 -0
- package/dist/provider-openai.d.ts +1 -0
- package/dist/provider-openai.js +214 -0
- package/dist/skills/backend.d.ts +1 -0
- package/dist/skills/backend.js +12 -0
- package/dist/skills/code.d.ts +1 -0
- package/dist/skills/code.js +6 -0
- package/dist/skills/frontend.d.ts +1 -0
- package/dist/skills/frontend.js +10 -0
- package/dist/skills/fs.d.ts +1 -0
- package/dist/skills/fs.js +10 -0
- package/dist/skills/git.d.ts +1 -0
- package/dist/skills/git.js +12 -0
- package/dist/skills/http.d.ts +1 -0
- package/dist/skills/http.js +6 -0
- package/dist/skills/index.d.ts +1 -0
- package/dist/skills/index.js +60 -0
- package/dist/skills/multimodal.d.ts +1 -0
- package/dist/skills/multimodal.js +6 -0
- package/dist/skills/qa.d.ts +1 -0
- package/dist/skills/qa.js +8 -0
- package/dist/skills/ux.d.ts +1 -0
- package/dist/skills/ux.js +6 -0
- package/dist/src-6MUVU5ML.js +8 -0
- package/dist/src-ZHTGR7T6.js +8 -0
- package/package.json +136 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export * from '@omni-ai/core';
|
|
2
|
+
import '@omni-ai/skills';
|
|
3
|
+
import '@omni-ai/skills/fs';
|
|
4
|
+
import '@omni-ai/skills/code';
|
|
5
|
+
import '@omni-ai/skills/ux';
|
|
6
|
+
import '@omni-ai/skills/git';
|
|
7
|
+
import '@omni-ai/skills/http';
|
|
8
|
+
import '@omni-ai/skills/multimodal';
|
|
9
|
+
import '@omni-ai/skills/backend';
|
|
10
|
+
import '@omni-ai/skills/frontend';
|
|
11
|
+
import '@omni-ai/skills/qa';
|
|
12
|
+
import '@omni-ai/memory';
|
|
13
|
+
import '@omni-ai/mcp';
|
|
14
|
+
import '@omni-ai/provider-anthropic';
|
|
15
|
+
import '@omni-ai/provider-openai';
|
|
16
|
+
import '@omni-ai/provider-google';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Agent,
|
|
3
|
+
AgentConfigSchema,
|
|
4
|
+
FallbackProvider,
|
|
5
|
+
OmniAiConfigSchema,
|
|
6
|
+
ProviderConfigSchema,
|
|
7
|
+
RetryConfigSchema,
|
|
8
|
+
RetryProvider,
|
|
9
|
+
ScaffoldPathsSchema,
|
|
10
|
+
SkillRegistry,
|
|
11
|
+
buildProvider,
|
|
12
|
+
composeMiddleware,
|
|
13
|
+
contentToString,
|
|
14
|
+
createProvider,
|
|
15
|
+
createRuntime,
|
|
16
|
+
getRegisteredProviders,
|
|
17
|
+
loadAgent,
|
|
18
|
+
loadConfig,
|
|
19
|
+
parallel,
|
|
20
|
+
registerProvider
|
|
21
|
+
} from "./chunk-6APAA6WD.js";
|
|
22
|
+
export {
|
|
23
|
+
Agent,
|
|
24
|
+
AgentConfigSchema,
|
|
25
|
+
FallbackProvider,
|
|
26
|
+
OmniAiConfigSchema,
|
|
27
|
+
ProviderConfigSchema,
|
|
28
|
+
RetryConfigSchema,
|
|
29
|
+
RetryProvider,
|
|
30
|
+
ScaffoldPathsSchema,
|
|
31
|
+
SkillRegistry,
|
|
32
|
+
buildProvider,
|
|
33
|
+
composeMiddleware,
|
|
34
|
+
contentToString,
|
|
35
|
+
createProvider,
|
|
36
|
+
createRuntime,
|
|
37
|
+
getRegisteredProviders,
|
|
38
|
+
loadAgent,
|
|
39
|
+
loadConfig,
|
|
40
|
+
parallel,
|
|
41
|
+
registerProvider
|
|
42
|
+
};
|
package/dist/mcp.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@omni-ai/mcp';
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// ../mcp/src/server.ts
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
var stubProvider = {
|
|
6
|
+
name: "mcp-stub",
|
|
7
|
+
capabilities: {},
|
|
8
|
+
complete: () => {
|
|
9
|
+
throw new Error("Provider not available in MCP server context");
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
function createMcpServer(skills, options) {
|
|
13
|
+
const server = new McpServer({
|
|
14
|
+
name: options?.name ?? "omni-ai",
|
|
15
|
+
version: options?.version ?? "0.1.0"
|
|
16
|
+
});
|
|
17
|
+
const ctx = {
|
|
18
|
+
provider: options?.ctx?.provider ?? stubProvider,
|
|
19
|
+
config: options?.ctx?.config ?? {}
|
|
20
|
+
};
|
|
21
|
+
for (const skill of skills) {
|
|
22
|
+
server.registerTool(
|
|
23
|
+
skill.name,
|
|
24
|
+
{ description: skill.description, inputSchema: z.record(z.unknown()) },
|
|
25
|
+
async (args) => {
|
|
26
|
+
try {
|
|
27
|
+
const result = await skill.execute(args, ctx);
|
|
28
|
+
const text = typeof result === "string" ? result : JSON.stringify(result);
|
|
29
|
+
return { content: [{ type: "text", text }] };
|
|
30
|
+
} catch (err) {
|
|
31
|
+
return {
|
|
32
|
+
content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
33
|
+
isError: true
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return server;
|
|
40
|
+
}
|
|
41
|
+
async function serveMcp(skills, transport, options) {
|
|
42
|
+
const server = createMcpServer(skills, options);
|
|
43
|
+
await server.connect(transport);
|
|
44
|
+
return server;
|
|
45
|
+
}
|
|
46
|
+
async function serveStdioMcp(skills, options) {
|
|
47
|
+
const transport = new StdioServerTransport();
|
|
48
|
+
return serveMcp(skills, transport, options);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ../mcp/src/skill.ts
|
|
52
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
53
|
+
var McpSkill = class {
|
|
54
|
+
name;
|
|
55
|
+
description;
|
|
56
|
+
client;
|
|
57
|
+
constructor(name, description, client) {
|
|
58
|
+
this.name = name;
|
|
59
|
+
this.description = description;
|
|
60
|
+
this.client = client;
|
|
61
|
+
}
|
|
62
|
+
async execute(input, _ctx) {
|
|
63
|
+
const args = typeof input === "object" && input !== null ? input : { input };
|
|
64
|
+
const result = await this.client.callTool({ name: this.name, arguments: args });
|
|
65
|
+
const content = result.content;
|
|
66
|
+
const first = content?.[0];
|
|
67
|
+
if (first?.type === "text") return first.text;
|
|
68
|
+
return JSON.stringify(content);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
async function connectMcpSkills(transport, options) {
|
|
72
|
+
const client = new Client({
|
|
73
|
+
name: options?.name ?? "omni-ai-client",
|
|
74
|
+
version: options?.version ?? "0.1.0"
|
|
75
|
+
});
|
|
76
|
+
await client.connect(transport);
|
|
77
|
+
const { tools } = await client.listTools();
|
|
78
|
+
return tools.map((t) => new McpSkill(t.name, t.description ?? "", client));
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
McpSkill,
|
|
82
|
+
connectMcpSkills,
|
|
83
|
+
createMcpServer,
|
|
84
|
+
serveMcp,
|
|
85
|
+
serveStdioMcp
|
|
86
|
+
};
|
package/dist/memory.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@omni-ai/memory';
|
package/dist/memory.js
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import {
|
|
2
|
+
contentToString
|
|
3
|
+
} from "./chunk-6APAA6WD.js";
|
|
4
|
+
|
|
5
|
+
// ../memory/src/utils.ts
|
|
6
|
+
function estimateTokens(messages) {
|
|
7
|
+
return messages.reduce((sum, m) => sum + Math.ceil(contentToString(m.content).length / 4), 0);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// ../memory/src/compactors/observation-masking.ts
|
|
11
|
+
var TOOL_RESULT_PREFIX = "[Tool ";
|
|
12
|
+
function isToolResult(msg) {
|
|
13
|
+
return msg.role === "user" && contentToString(msg.content).startsWith(TOOL_RESULT_PREFIX);
|
|
14
|
+
}
|
|
15
|
+
var ObservationMaskingCompactor = class {
|
|
16
|
+
threshold;
|
|
17
|
+
lastMessages;
|
|
18
|
+
/**
|
|
19
|
+
* @param threshold Fraction of maxTokens at which to trigger. Default: 0.7
|
|
20
|
+
* @param lastMessages Number of recent messages to keep verbatim. Default: 6
|
|
21
|
+
*/
|
|
22
|
+
constructor(threshold = 0.7, lastMessages = 6) {
|
|
23
|
+
this.threshold = threshold;
|
|
24
|
+
this.lastMessages = lastMessages;
|
|
25
|
+
}
|
|
26
|
+
shouldCompact(messages, maxTokens) {
|
|
27
|
+
return estimateTokens(messages) > maxTokens * this.threshold;
|
|
28
|
+
}
|
|
29
|
+
async compact(messages, _provider) {
|
|
30
|
+
if (messages.length <= this.lastMessages) return messages;
|
|
31
|
+
const cutoff = messages.length - this.lastMessages;
|
|
32
|
+
return messages.map((msg, i) => {
|
|
33
|
+
if (i >= cutoff || !isToolResult(msg)) return msg;
|
|
34
|
+
const str = contentToString(msg.content);
|
|
35
|
+
const tokenCount = Math.ceil(str.length / 4);
|
|
36
|
+
const match = /^\[Tool ([^\]]+) result\]:/.exec(str);
|
|
37
|
+
const toolName = match?.[1] ?? "unknown";
|
|
38
|
+
return {
|
|
39
|
+
role: msg.role,
|
|
40
|
+
content: `[Tool ${toolName} result: masked, ~${tokenCount} tokens]`
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// ../memory/src/compactors/summary.ts
|
|
47
|
+
function formatForSummary(messages) {
|
|
48
|
+
return messages.map((m) => {
|
|
49
|
+
const label = m.role === "assistant" ? "Assistant" : "User/Tool";
|
|
50
|
+
return `[${label}]: ${contentToString(m.content)}`;
|
|
51
|
+
}).join("\n\n");
|
|
52
|
+
}
|
|
53
|
+
var SummaryCompactor = class {
|
|
54
|
+
threshold;
|
|
55
|
+
lastMessages;
|
|
56
|
+
/**
|
|
57
|
+
* @param threshold Fraction of maxTokens at which to trigger. Default: 0.7
|
|
58
|
+
* @param lastMessages Number of recent messages to keep verbatim. Default: 6
|
|
59
|
+
*/
|
|
60
|
+
constructor(threshold = 0.7, lastMessages = 6) {
|
|
61
|
+
this.threshold = threshold;
|
|
62
|
+
this.lastMessages = lastMessages;
|
|
63
|
+
}
|
|
64
|
+
shouldCompact(messages, maxTokens) {
|
|
65
|
+
return estimateTokens(messages) > maxTokens * this.threshold;
|
|
66
|
+
}
|
|
67
|
+
async compact(messages, provider) {
|
|
68
|
+
if (messages.length <= this.lastMessages) return messages;
|
|
69
|
+
const cutoff = messages.length - this.lastMessages;
|
|
70
|
+
const toSummarize = messages.slice(0, cutoff);
|
|
71
|
+
const toKeep = messages.slice(cutoff);
|
|
72
|
+
const summaryResponse = await provider.complete({
|
|
73
|
+
messages: [
|
|
74
|
+
{
|
|
75
|
+
role: "user",
|
|
76
|
+
content: [
|
|
77
|
+
"Summarize the following conversation history concisely.",
|
|
78
|
+
"Preserve: decisions made, key facts found, files read, errors encountered, and current task state.",
|
|
79
|
+
"Omit: raw file contents, full search results, repetitive tool outputs.",
|
|
80
|
+
"Write the summary as a compact factual paragraph or bullet list.",
|
|
81
|
+
"",
|
|
82
|
+
"--- CONVERSATION TO SUMMARIZE ---",
|
|
83
|
+
formatForSummary(toSummarize)
|
|
84
|
+
].join("\n")
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
systemPrompt: "You are a precise conversation summarizer. Be concise and factual.",
|
|
88
|
+
temperature: 0.1
|
|
89
|
+
});
|
|
90
|
+
const summaryMsg = {
|
|
91
|
+
role: "user",
|
|
92
|
+
content: `[Context summary \u2014 ${toSummarize.length} messages compressed]:
|
|
93
|
+
${summaryResponse.content}`
|
|
94
|
+
};
|
|
95
|
+
return [summaryMsg, ...toKeep];
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// ../memory/src/stores/in-memory.ts
|
|
100
|
+
function sessionKey(session) {
|
|
101
|
+
return `${session.resourceId}:${session.threadId}`;
|
|
102
|
+
}
|
|
103
|
+
var InMemoryStore = class {
|
|
104
|
+
messages = /* @__PURE__ */ new Map();
|
|
105
|
+
working = /* @__PURE__ */ new Map();
|
|
106
|
+
async saveMessages(session, messages) {
|
|
107
|
+
const key = sessionKey(session);
|
|
108
|
+
const existing = this.messages.get(key) ?? [];
|
|
109
|
+
this.messages.set(key, [...existing, ...messages]);
|
|
110
|
+
}
|
|
111
|
+
async loadMessages(session, limit) {
|
|
112
|
+
const entries = this.messages.get(sessionKey(session)) ?? [];
|
|
113
|
+
return limit ? entries.slice(-limit) : entries;
|
|
114
|
+
}
|
|
115
|
+
async search(session, query, topK = 5) {
|
|
116
|
+
const entries = this.messages.get(sessionKey(session)) ?? [];
|
|
117
|
+
const q = query.toLowerCase();
|
|
118
|
+
return entries.filter((e) => e.content.toLowerCase().includes(q)).slice(-topK).map((e) => ({ content: e.content, score: 1 }));
|
|
119
|
+
}
|
|
120
|
+
async getWorkingMemory(session) {
|
|
121
|
+
return this.working.get(sessionKey(session)) ?? null;
|
|
122
|
+
}
|
|
123
|
+
async setWorkingMemory(session, content) {
|
|
124
|
+
this.working.set(sessionKey(session), content);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// ../memory/src/vector.ts
|
|
129
|
+
function cosineSimilarity(a, b) {
|
|
130
|
+
let dot = 0;
|
|
131
|
+
let normA = 0;
|
|
132
|
+
let normB = 0;
|
|
133
|
+
for (let i = 0; i < a.length; i++) {
|
|
134
|
+
dot += a[i] * b[i];
|
|
135
|
+
normA += a[i] * a[i];
|
|
136
|
+
normB += b[i] * b[i];
|
|
137
|
+
}
|
|
138
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
139
|
+
return denom === 0 ? 0 : dot / denom;
|
|
140
|
+
}
|
|
141
|
+
var VectorIndex = class {
|
|
142
|
+
entries = [];
|
|
143
|
+
add(id, vector) {
|
|
144
|
+
this.entries.push({ id, vector });
|
|
145
|
+
}
|
|
146
|
+
query(queryVector, topK = 5) {
|
|
147
|
+
return this.entries.map((e) => ({ id: e.id, score: cosineSimilarity(queryVector, e.vector) })).sort((a, b) => b.score - a.score).slice(0, topK);
|
|
148
|
+
}
|
|
149
|
+
remove(id) {
|
|
150
|
+
this.entries = this.entries.filter((e) => e.id !== id);
|
|
151
|
+
}
|
|
152
|
+
clear() {
|
|
153
|
+
this.entries = [];
|
|
154
|
+
}
|
|
155
|
+
get size() {
|
|
156
|
+
return this.entries.length;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// ../memory/src/stores/semantic-memory-store.ts
|
|
161
|
+
var SemanticMemoryStore = class {
|
|
162
|
+
provider;
|
|
163
|
+
inner;
|
|
164
|
+
cache = /* @__PURE__ */ new Map();
|
|
165
|
+
constructor(provider, inner) {
|
|
166
|
+
if (!provider.embed) {
|
|
167
|
+
throw new Error(
|
|
168
|
+
`Provider "${provider.name}" does not support embeddings \u2014 use a provider with capabilities.embedding = true`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
this.provider = provider;
|
|
172
|
+
this.inner = inner ?? new InMemoryStore();
|
|
173
|
+
}
|
|
174
|
+
async saveMessages(session, messages) {
|
|
175
|
+
await this.inner.saveMessages(session, messages);
|
|
176
|
+
const key = sessionKey2(session);
|
|
177
|
+
const cached = this.cache.get(key) ?? [];
|
|
178
|
+
for (const m of messages) {
|
|
179
|
+
try {
|
|
180
|
+
const resp = await this.provider.embed?.({ input: m.content });
|
|
181
|
+
if (resp) cached.push({ content: m.content, vector: resp.embeddings[0] });
|
|
182
|
+
} catch {
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
this.cache.set(key, cached);
|
|
186
|
+
}
|
|
187
|
+
async search(session, query, topK = 5) {
|
|
188
|
+
const key = sessionKey2(session);
|
|
189
|
+
const cached = this.cache.get(key);
|
|
190
|
+
if (!cached || cached.length === 0) {
|
|
191
|
+
return this.inner.search ? this.inner.search(session, query, topK) : [];
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const resp = await this.provider.embed?.({ input: query });
|
|
195
|
+
if (!resp) return this.inner.search?.(session, query, topK) ?? [];
|
|
196
|
+
const queryVector = resp.embeddings[0];
|
|
197
|
+
return cached.map((e) => ({ content: e.content, score: cosineSimilarity(queryVector, e.vector) })).sort((a, b) => b.score - a.score).slice(0, topK);
|
|
198
|
+
} catch {
|
|
199
|
+
return this.inner.search ? this.inner.search(session, query, topK) : [];
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
async loadMessages(session, limit) {
|
|
203
|
+
return this.inner.loadMessages(session, limit);
|
|
204
|
+
}
|
|
205
|
+
async getWorkingMemory(session) {
|
|
206
|
+
return this.inner.getWorkingMemory?.(session) ?? null;
|
|
207
|
+
}
|
|
208
|
+
async setWorkingMemory(session, content) {
|
|
209
|
+
return this.inner.setWorkingMemory?.(session, content);
|
|
210
|
+
}
|
|
211
|
+
async close() {
|
|
212
|
+
return this.inner.close?.();
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
function sessionKey2(session) {
|
|
216
|
+
return `${session.resourceId}:${session.threadId}`;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ../memory/src/stores/sqlite.ts
|
|
220
|
+
import Database from "better-sqlite3";
|
|
221
|
+
var SQLiteMemoryStore = class {
|
|
222
|
+
db;
|
|
223
|
+
defaultLimit;
|
|
224
|
+
constructor(options = {}) {
|
|
225
|
+
const path = options.path ?? "./omni-ai-memory.db";
|
|
226
|
+
this.defaultLimit = options.defaultLimit ?? 100;
|
|
227
|
+
this.db = new Database(path);
|
|
228
|
+
this.db.pragma("journal_mode = WAL");
|
|
229
|
+
this.migrate();
|
|
230
|
+
}
|
|
231
|
+
migrate() {
|
|
232
|
+
this.db.exec(`
|
|
233
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
234
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
235
|
+
resource_id TEXT NOT NULL,
|
|
236
|
+
thread_id TEXT NOT NULL,
|
|
237
|
+
role TEXT NOT NULL,
|
|
238
|
+
content TEXT NOT NULL,
|
|
239
|
+
timestamp INTEGER NOT NULL
|
|
240
|
+
);
|
|
241
|
+
CREATE INDEX IF NOT EXISTS idx_messages_session
|
|
242
|
+
ON messages (resource_id, thread_id, id);
|
|
243
|
+
|
|
244
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(
|
|
245
|
+
content,
|
|
246
|
+
content='messages',
|
|
247
|
+
content_rowid='id'
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
CREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN
|
|
251
|
+
INSERT INTO messages_fts (rowid, content) VALUES (new.id, new.content);
|
|
252
|
+
END;
|
|
253
|
+
|
|
254
|
+
CREATE TABLE IF NOT EXISTS working_memory (
|
|
255
|
+
resource_id TEXT NOT NULL,
|
|
256
|
+
thread_id TEXT NOT NULL,
|
|
257
|
+
content TEXT NOT NULL,
|
|
258
|
+
updated_at INTEGER NOT NULL,
|
|
259
|
+
PRIMARY KEY (resource_id, thread_id)
|
|
260
|
+
);
|
|
261
|
+
`);
|
|
262
|
+
}
|
|
263
|
+
async saveMessages(session, messages) {
|
|
264
|
+
const insert = this.db.prepare(
|
|
265
|
+
`INSERT INTO messages (resource_id, thread_id, role, content, timestamp)
|
|
266
|
+
VALUES (@resourceId, @threadId, @role, @content, @timestamp)`
|
|
267
|
+
);
|
|
268
|
+
const insertMany = this.db.transaction((entries) => {
|
|
269
|
+
for (const e of entries) {
|
|
270
|
+
insert.run({ ...session, role: e.role, content: e.content, timestamp: e.timestamp });
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
insertMany(messages);
|
|
274
|
+
}
|
|
275
|
+
async loadMessages(session, limit) {
|
|
276
|
+
const n = limit ?? this.defaultLimit;
|
|
277
|
+
const rows = this.db.prepare(
|
|
278
|
+
`SELECT role, content, timestamp FROM (
|
|
279
|
+
SELECT role, content, timestamp FROM messages
|
|
280
|
+
WHERE resource_id = ? AND thread_id = ?
|
|
281
|
+
ORDER BY id DESC LIMIT ?
|
|
282
|
+
) ORDER BY timestamp ASC`
|
|
283
|
+
).all(session.resourceId, session.threadId, n);
|
|
284
|
+
return rows;
|
|
285
|
+
}
|
|
286
|
+
async search(session, query, topK = 5) {
|
|
287
|
+
const rows = this.db.prepare(
|
|
288
|
+
`SELECT m.content, rank AS score
|
|
289
|
+
FROM messages_fts fts
|
|
290
|
+
JOIN messages m ON m.id = fts.rowid
|
|
291
|
+
WHERE fts.content MATCH ?
|
|
292
|
+
AND m.resource_id = ? AND m.thread_id = ?
|
|
293
|
+
ORDER BY rank LIMIT ?`
|
|
294
|
+
).all(query, session.resourceId, session.threadId, topK);
|
|
295
|
+
return rows.map((r) => ({ content: r.content, score: r.score }));
|
|
296
|
+
}
|
|
297
|
+
async getWorkingMemory(session) {
|
|
298
|
+
const row = this.db.prepare(`SELECT content FROM working_memory WHERE resource_id = ? AND thread_id = ?`).get(session.resourceId, session.threadId);
|
|
299
|
+
return row?.content ?? null;
|
|
300
|
+
}
|
|
301
|
+
async setWorkingMemory(session, content) {
|
|
302
|
+
this.db.prepare(
|
|
303
|
+
`INSERT INTO working_memory (resource_id, thread_id, content, updated_at)
|
|
304
|
+
VALUES (?, ?, ?, ?)
|
|
305
|
+
ON CONFLICT (resource_id, thread_id) DO UPDATE SET content = excluded.content, updated_at = excluded.updated_at`
|
|
306
|
+
).run(session.resourceId, session.threadId, content, Date.now());
|
|
307
|
+
}
|
|
308
|
+
async close() {
|
|
309
|
+
this.db.close();
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
export {
|
|
313
|
+
InMemoryStore,
|
|
314
|
+
ObservationMaskingCompactor,
|
|
315
|
+
SQLiteMemoryStore,
|
|
316
|
+
SemanticMemoryStore,
|
|
317
|
+
SummaryCompactor,
|
|
318
|
+
VectorIndex,
|
|
319
|
+
cosineSimilarity
|
|
320
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@omni-ai/provider-anthropic';
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
registerProvider
|
|
3
|
+
} from "./chunk-6APAA6WD.js";
|
|
4
|
+
|
|
5
|
+
// ../provider-anthropic/src/provider.ts
|
|
6
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
7
|
+
|
|
8
|
+
// ../provider-anthropic/src/mappers.ts
|
|
9
|
+
function toAnthropicContentPart(part) {
|
|
10
|
+
if (part.type === "text") return { type: "text", text: part.text };
|
|
11
|
+
return {
|
|
12
|
+
type: "image",
|
|
13
|
+
source: { type: "base64", media_type: part.mimeType, data: part.data }
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function toAnthropicMessages(messages) {
|
|
17
|
+
return messages.filter((m) => m.role !== "system").map((m) => ({
|
|
18
|
+
role: m.role,
|
|
19
|
+
content: typeof m.content === "string" ? m.content : m.content.map(toAnthropicContentPart)
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
function toAnthropicTools(tools) {
|
|
23
|
+
return tools.map((t) => ({
|
|
24
|
+
name: t.name,
|
|
25
|
+
description: t.description,
|
|
26
|
+
input_schema: t.parameters
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
function extractSystemPrompt(request) {
|
|
30
|
+
const systemMsg = request.messages.find((m) => m.role === "system");
|
|
31
|
+
const raw = request.systemPrompt ?? systemMsg?.content;
|
|
32
|
+
if (raw === void 0) return void 0;
|
|
33
|
+
return typeof raw === "string" ? raw : raw.map((p) => p.type === "text" ? p.text : "").join("");
|
|
34
|
+
}
|
|
35
|
+
function fromAnthropicResponse(response, providerName) {
|
|
36
|
+
let content = "";
|
|
37
|
+
const toolCalls = [];
|
|
38
|
+
for (const block of response.content) {
|
|
39
|
+
if (block.type === "text") {
|
|
40
|
+
content += block.text;
|
|
41
|
+
} else if (block.type === "tool_use") {
|
|
42
|
+
toolCalls.push({
|
|
43
|
+
id: block.id,
|
|
44
|
+
name: block.name,
|
|
45
|
+
arguments: block.input
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
content,
|
|
51
|
+
toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
52
|
+
usage: {
|
|
53
|
+
inputTokens: response.usage.input_tokens,
|
|
54
|
+
outputTokens: response.usage.output_tokens
|
|
55
|
+
},
|
|
56
|
+
model: response.model,
|
|
57
|
+
provider: providerName
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ../provider-anthropic/src/provider.ts
|
|
62
|
+
var AnthropicProvider = class {
|
|
63
|
+
name;
|
|
64
|
+
capabilities = {
|
|
65
|
+
chat: true,
|
|
66
|
+
embedding: false,
|
|
67
|
+
streaming: true,
|
|
68
|
+
toolUse: true,
|
|
69
|
+
vision: true
|
|
70
|
+
};
|
|
71
|
+
client;
|
|
72
|
+
defaultModel;
|
|
73
|
+
constructor(options) {
|
|
74
|
+
this.name = options.name ?? "anthropic";
|
|
75
|
+
this.defaultModel = options.defaultModel ?? "claude-sonnet-4-6";
|
|
76
|
+
this.client = new Anthropic({ apiKey: options.apiKey });
|
|
77
|
+
}
|
|
78
|
+
async complete(request) {
|
|
79
|
+
const model = request.model ?? this.defaultModel;
|
|
80
|
+
if (request.temperature !== void 0 && request.temperature > 1) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Anthropic models require temperature <= 1.0 (got ${request.temperature}). Update the agent YAML or use an OpenAI provider for higher temperature values.`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
const system = extractSystemPrompt(request);
|
|
86
|
+
const messages = toAnthropicMessages(request.messages);
|
|
87
|
+
const tools = request.tools && request.tools.length > 0 ? toAnthropicTools(request.tools) : void 0;
|
|
88
|
+
const params = {
|
|
89
|
+
model,
|
|
90
|
+
max_tokens: request.maxTokens ?? 8096,
|
|
91
|
+
temperature: request.temperature,
|
|
92
|
+
system,
|
|
93
|
+
messages,
|
|
94
|
+
tools
|
|
95
|
+
};
|
|
96
|
+
if (request.onToken) {
|
|
97
|
+
const stream = this.client.messages.stream(params);
|
|
98
|
+
stream.on("text", request.onToken);
|
|
99
|
+
const finalMessage = await stream.finalMessage();
|
|
100
|
+
return fromAnthropicResponse(finalMessage, this.name);
|
|
101
|
+
}
|
|
102
|
+
const response = await this.client.messages.create(params);
|
|
103
|
+
return fromAnthropicResponse(response, this.name);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// ../provider-anthropic/src/index.ts
|
|
108
|
+
registerProvider("anthropic", (config) => {
|
|
109
|
+
if (!config.apiKey) {
|
|
110
|
+
throw new Error(`Provider "${config.name}" (anthropic) requires ANTHROPIC_API_KEY to be set in the environment.`);
|
|
111
|
+
}
|
|
112
|
+
return new AnthropicProvider({
|
|
113
|
+
apiKey: config.apiKey,
|
|
114
|
+
defaultModel: config.defaultModel,
|
|
115
|
+
name: config.name
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
export {
|
|
119
|
+
AnthropicProvider
|
|
120
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@omni-ai/provider-google';
|