@denispro2006/duke-ai-kernel 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 +81 -0
- package/config/prompts/default.txt +1 -0
- package/config/routing.json +24 -0
- package/dist/api/routes.d.ts +3 -0
- package/dist/api/routes.d.ts.map +1 -0
- package/dist/api/routes.js +114 -0
- package/dist/api/routes.js.map +1 -0
- package/dist/app.d.ts +7 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +21 -0
- package/dist/app.js.map +1 -0
- package/dist/config/index.d.ts +50 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +86 -0
- package/dist/config/index.js.map +1 -0
- package/dist/context/context-manager.d.ts +30 -0
- package/dist/context/context-manager.d.ts.map +1 -0
- package/dist/context/context-manager.js +77 -0
- package/dist/context/context-manager.js.map +1 -0
- package/dist/controllers/ai.controller.d.ts +3 -0
- package/dist/controllers/ai.controller.d.ts.map +1 -0
- package/dist/controllers/ai.controller.js +20 -0
- package/dist/controllers/ai.controller.js.map +1 -0
- package/dist/controllers/message.controller.d.ts +4 -0
- package/dist/controllers/message.controller.d.ts.map +1 -0
- package/dist/controllers/message.controller.js +28 -0
- package/dist/controllers/message.controller.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/index.d.ts +17 -0
- package/dist/kernel/index.d.ts.map +1 -0
- package/dist/kernel/index.js +134 -0
- package/dist/kernel/index.js.map +1 -0
- package/dist/lib/logger.d.ts +3 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +15 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/middleware/auth.middleware.d.ts +3 -0
- package/dist/middleware/auth.middleware.d.ts.map +1 -0
- package/dist/middleware/auth.middleware.js +24 -0
- package/dist/middleware/auth.middleware.js.map +1 -0
- package/dist/middleware/error.middleware.d.ts +6 -0
- package/dist/middleware/error.middleware.d.ts.map +1 -0
- package/dist/middleware/error.middleware.js +16 -0
- package/dist/middleware/error.middleware.js.map +1 -0
- package/dist/models/Message.d.ts +10 -0
- package/dist/models/Message.d.ts.map +1 -0
- package/dist/models/Message.js +3 -0
- package/dist/models/Message.js.map +1 -0
- package/dist/models/User.d.ts +7 -0
- package/dist/models/User.d.ts.map +1 -0
- package/dist/models/User.js +3 -0
- package/dist/models/User.js.map +1 -0
- package/dist/plugins/index.d.ts +10 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +74 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/providers/anthropic.d.ts +3 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +65 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +38 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama.d.ts +3 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +77 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai.d.ts +3 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +63 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/router/index.d.ts +13 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +70 -0
- package/dist/router/index.js.map +1 -0
- package/dist/routes/ai.routes.d.ts +3 -0
- package/dist/routes/ai.routes.d.ts.map +1 -0
- package/dist/routes/ai.routes.js +9 -0
- package/dist/routes/ai.routes.js.map +1 -0
- package/dist/routes/index.d.ts +2 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +6 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/services/ai.service.d.ts +4 -0
- package/dist/services/ai.service.d.ts.map +1 -0
- package/dist/services/ai.service.js +28 -0
- package/dist/services/ai.service.js.map +1 -0
- package/dist/services/db.service.d.ts +3 -0
- package/dist/services/db.service.d.ts.map +1 -0
- package/dist/services/db.service.js +60 -0
- package/dist/services/db.service.js.map +1 -0
- package/dist/services/kernel.service.d.ts +4 -0
- package/dist/services/kernel.service.d.ts.map +1 -0
- package/dist/services/kernel.service.js +14 -0
- package/dist/services/kernel.service.js.map +1 -0
- package/dist/types.d.ts +72 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/helpers.d.ts +6 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +24 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +6 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/workers/aiWorker.d.ts +6 -0
- package/dist/workers/aiWorker.d.ts.map +1 -0
- package/dist/workers/aiWorker.js +42 -0
- package/dist/workers/aiWorker.js.map +1 -0
- package/dist/ws/gateway.d.ts +3 -0
- package/dist/ws/gateway.d.ts.map +1 -0
- package/dist/ws/gateway.js +110 -0
- package/dist/ws/gateway.js.map +1 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# duke-ai-kernel
|
|
2
|
+
|
|
3
|
+
AI kernel for the [duke-messenger](https://github.com/duke-messenger) platform. Handles LLM routing, context management, and real-time messaging via WebSocket.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# 1. Clone and install
|
|
9
|
+
git clone https://github.com/duke-messenger/duke-ai-kernel
|
|
10
|
+
cd duke-ai-kernel
|
|
11
|
+
npm install
|
|
12
|
+
|
|
13
|
+
# 2. Configure environment
|
|
14
|
+
cp .env.example .env
|
|
15
|
+
# Edit .env with your API keys
|
|
16
|
+
|
|
17
|
+
# 3. Start the kernel
|
|
18
|
+
npm run dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The kernel starts on `http://localhost:3000` by default.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- **Unified LLM routing** — route requests to OpenAI, Anthropic, or local Ollama models
|
|
26
|
+
- **Context management** — per-conversation history with configurable token-budget trimming
|
|
27
|
+
- **Real-time streaming** — stream responses to clients over WebSocket
|
|
28
|
+
- **Plugin pipeline** — extend with custom pre/post processors
|
|
29
|
+
- **Worker concurrency** — bounded async workers prevent rate-limit saturation
|
|
30
|
+
|
|
31
|
+
## Stack
|
|
32
|
+
|
|
33
|
+
| Layer | Technology |
|
|
34
|
+
|-------|-----------|
|
|
35
|
+
| Runtime | Node.js 20+ |
|
|
36
|
+
| Framework | Express 5 |
|
|
37
|
+
| WebSocket | ws |
|
|
38
|
+
| Language | TypeScript |
|
|
39
|
+
| Testing | Vitest |
|
|
40
|
+
|
|
41
|
+
## Scripts
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm run dev # Start with hot reload
|
|
45
|
+
npm run build # Compile TypeScript
|
|
46
|
+
npm start # Run compiled output
|
|
47
|
+
npm run lint # Check code style
|
|
48
|
+
npm run typecheck # Type-check without building
|
|
49
|
+
npm test # Run all tests
|
|
50
|
+
npm run test:coverage # Run tests with coverage report
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Environment Variables
|
|
54
|
+
|
|
55
|
+
Copy `.env.example` to `.env`. At minimum you need:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
OPENAI_API_KEY=sk-...
|
|
59
|
+
AUTH_SECRET=your-secret-here
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
See [Environment Variables](docs/api.md) for the full reference.
|
|
63
|
+
|
|
64
|
+
## Docker
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Start kernel + Redis
|
|
68
|
+
docker compose up -d
|
|
69
|
+
|
|
70
|
+
# Verify
|
|
71
|
+
curl http://localhost:3000/api/v1/healthz
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Documentation
|
|
75
|
+
|
|
76
|
+
- [API Reference](docs/api.md)
|
|
77
|
+
- [Architecture & Data Flow](docs/api.md)
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
MIT © duke-messenger contributors
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
You are a helpful assistant.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"rules": [
|
|
3
|
+
{
|
|
4
|
+
"if": { "tag": "reasoning" },
|
|
5
|
+
"use": "openai",
|
|
6
|
+
"model": "o1-mini"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"if": { "tag": "local" },
|
|
10
|
+
"use": "ollama",
|
|
11
|
+
"model": "llama3"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"if": { "tier": "low-cost" },
|
|
15
|
+
"use": "openai",
|
|
16
|
+
"model": "gpt-4o-mini"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"default": true,
|
|
20
|
+
"use": "openai",
|
|
21
|
+
"model": "gpt-4o-mini"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,SAAS,4CAAW,CAAA;AAoH1B,OAAO,EAAE,SAAS,EAAE,CAAA"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.apiRouter = void 0;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const kernel_1 = require("../kernel");
|
|
7
|
+
const context_manager_1 = require("../context/context-manager");
|
|
8
|
+
const router_1 = require("../router");
|
|
9
|
+
const helpers_1 = require("../utils/helpers");
|
|
10
|
+
const logger_1 = require("../lib/logger");
|
|
11
|
+
const config_1 = require("../config");
|
|
12
|
+
const apiRouter = (0, express_1.Router)();
|
|
13
|
+
exports.apiRouter = apiRouter;
|
|
14
|
+
const MessageSchema = zod_1.z.object({
|
|
15
|
+
role: zod_1.z.enum(['user', 'assistant', 'system']),
|
|
16
|
+
content: zod_1.z.string(),
|
|
17
|
+
});
|
|
18
|
+
const CompleteSchema = zod_1.z.object({
|
|
19
|
+
model: zod_1.z.string().optional(),
|
|
20
|
+
conversationId: zod_1.z.string().optional(),
|
|
21
|
+
messages: zod_1.z.array(MessageSchema).min(1),
|
|
22
|
+
options: zod_1.z
|
|
23
|
+
.object({
|
|
24
|
+
temperature: zod_1.z.number().min(0).max(2).optional(),
|
|
25
|
+
maxTokens: zod_1.z.number().int().positive().optional(),
|
|
26
|
+
tag: zod_1.z.string().optional(),
|
|
27
|
+
tier: zod_1.z.string().optional(),
|
|
28
|
+
})
|
|
29
|
+
.optional(),
|
|
30
|
+
});
|
|
31
|
+
const ConversationCreateSchema = zod_1.z.object({
|
|
32
|
+
systemPrompt: zod_1.z.string().optional(),
|
|
33
|
+
maxContextTokens: zod_1.z.number().int().positive().optional(),
|
|
34
|
+
metadata: zod_1.z.record(zod_1.z.unknown()).optional(),
|
|
35
|
+
});
|
|
36
|
+
apiRouter.get('/healthz', (_req, res) => {
|
|
37
|
+
res.json({
|
|
38
|
+
status: 'ok',
|
|
39
|
+
uptime: Math.floor(process.uptime()),
|
|
40
|
+
version: '1.0.0',
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
apiRouter.post('/complete', async (req, res) => {
|
|
44
|
+
const parsed = CompleteSchema.safeParse(req.body);
|
|
45
|
+
if (!parsed.success) {
|
|
46
|
+
res.status(400).json({ error: 'VALIDATION_ERROR', message: parsed.error.message });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const { model, conversationId, messages, options } = parsed.data;
|
|
50
|
+
const convId = conversationId ?? (0, helpers_1.generateId)('conv');
|
|
51
|
+
try {
|
|
52
|
+
const response = await kernel_1.kernel.process({
|
|
53
|
+
id: (0, helpers_1.generateId)('req'),
|
|
54
|
+
conversationId: convId,
|
|
55
|
+
messages,
|
|
56
|
+
model: model ?? config_1.config.providers.defaultModel,
|
|
57
|
+
options,
|
|
58
|
+
});
|
|
59
|
+
res.json({
|
|
60
|
+
id: response.id,
|
|
61
|
+
conversationId: convId,
|
|
62
|
+
message: response.message,
|
|
63
|
+
usage: response.usage,
|
|
64
|
+
model: response.model,
|
|
65
|
+
finishReason: response.finishReason,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
logger_1.logger.error({ err, conversationId: convId }, 'Completion failed');
|
|
70
|
+
res.status(502).json({ error: 'PROVIDER_ERROR', message: err.message });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
apiRouter.get('/conversations/:id', async (req, res) => {
|
|
74
|
+
const id = req.params['id'];
|
|
75
|
+
const entry = await context_manager_1.contextManager.getEntry(id);
|
|
76
|
+
if (!entry) {
|
|
77
|
+
res.status(404).json({ error: 'NOT_FOUND', message: `Conversation ${id} does not exist.` });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const tokenCount = context_manager_1.contextManager.estimateTokens(entry.messages);
|
|
81
|
+
res.json({
|
|
82
|
+
conversationId: id,
|
|
83
|
+
messages: entry.messages,
|
|
84
|
+
createdAt: entry.createdAt,
|
|
85
|
+
updatedAt: entry.updatedAt,
|
|
86
|
+
tokenCount,
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
apiRouter.delete('/conversations/:id', async (req, res) => {
|
|
90
|
+
const id = req.params['id'];
|
|
91
|
+
await context_manager_1.contextManager.clear(id);
|
|
92
|
+
res.status(204).send();
|
|
93
|
+
});
|
|
94
|
+
apiRouter.post('/conversations', async (req, res) => {
|
|
95
|
+
const parsed = ConversationCreateSchema.safeParse(req.body);
|
|
96
|
+
if (!parsed.success) {
|
|
97
|
+
res.status(400).json({ error: 'VALIDATION_ERROR', message: parsed.error.message });
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const conversationId = (0, helpers_1.generateId)('conv');
|
|
101
|
+
await context_manager_1.contextManager.create(conversationId, {
|
|
102
|
+
systemPrompt: parsed.data.systemPrompt,
|
|
103
|
+
maxContextTokens: parsed.data.maxContextTokens,
|
|
104
|
+
});
|
|
105
|
+
res.status(201).json({
|
|
106
|
+
conversationId,
|
|
107
|
+
createdAt: new Date(),
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
apiRouter.get('/models', (_req, res) => {
|
|
111
|
+
const models = router_1.router.getAvailableModels();
|
|
112
|
+
res.json({ models });
|
|
113
|
+
});
|
|
114
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"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"}
|
package/dist/app.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAO1C,KAAK,UAAU,GAAG;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,CAAA;AAED,wBAAgB,QAAQ,CAAC,QAAQ,GAAE,UAAe,GAAG,OAAO,CAW3D"}
|
package/dist/app.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildApp = buildApp;
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const pino_http_1 = __importDefault(require("pino-http"));
|
|
9
|
+
const routes_1 = require("./api/routes");
|
|
10
|
+
const auth_middleware_1 = require("./middleware/auth.middleware");
|
|
11
|
+
const error_middleware_1 = require("./middleware/error.middleware");
|
|
12
|
+
const logger_1 = require("./lib/logger");
|
|
13
|
+
function buildApp(_options = {}) {
|
|
14
|
+
const app = (0, express_1.default)();
|
|
15
|
+
app.use(express_1.default.json());
|
|
16
|
+
app.use((0, pino_http_1.default)({ logger: logger_1.logger }));
|
|
17
|
+
app.use('/api/v1', auth_middleware_1.authMiddleware, routes_1.apiRouter);
|
|
18
|
+
app.use(error_middleware_1.errorMiddleware);
|
|
19
|
+
return app;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":";;;;;AAWA,4BAWC;AAtBD,sDAA0C;AAC1C,0DAAgC;AAChC,yCAAwC;AACxC,kEAA6D;AAC7D,oEAA+D;AAC/D,yCAAqC;AAMrC,SAAgB,QAAQ,CAAC,WAAuB,EAAE;IAChD,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAA;IAErB,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACvB,GAAG,CAAC,GAAG,CAAC,IAAA,mBAAQ,EAAC,EAAE,MAAM,EAAN,eAAM,EAAE,CAAC,CAAC,CAAA;IAE7B,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,gCAAc,EAAE,kBAAS,CAAC,CAAA;IAE7C,GAAG,CAAC,GAAG,CAAC,kCAA8C,CAAC,CAAA;IAEvD,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
export declare const config: {
|
|
3
|
+
readonly port: number;
|
|
4
|
+
readonly nodeEnv: string;
|
|
5
|
+
readonly logLevel: string;
|
|
6
|
+
readonly auth: {
|
|
7
|
+
readonly secret: string;
|
|
8
|
+
readonly tokenTtl: number;
|
|
9
|
+
readonly bypass: boolean;
|
|
10
|
+
};
|
|
11
|
+
readonly providers: {
|
|
12
|
+
readonly openai: {
|
|
13
|
+
readonly apiKey: string | undefined;
|
|
14
|
+
readonly baseUrl: string | undefined;
|
|
15
|
+
};
|
|
16
|
+
readonly anthropic: {
|
|
17
|
+
readonly apiKey: string | undefined;
|
|
18
|
+
};
|
|
19
|
+
readonly ollama: {
|
|
20
|
+
readonly baseUrl: string;
|
|
21
|
+
};
|
|
22
|
+
readonly defaultModel: string;
|
|
23
|
+
};
|
|
24
|
+
readonly worker: {
|
|
25
|
+
readonly concurrency: number;
|
|
26
|
+
readonly retryLimit: number;
|
|
27
|
+
readonly retryDelayMs: number;
|
|
28
|
+
readonly timeoutMs: number;
|
|
29
|
+
};
|
|
30
|
+
readonly context: {
|
|
31
|
+
readonly store: "memory" | "redis";
|
|
32
|
+
readonly redisUrl: string;
|
|
33
|
+
readonly maxTokens: number;
|
|
34
|
+
readonly ttl: number;
|
|
35
|
+
};
|
|
36
|
+
readonly rateLimit: {
|
|
37
|
+
readonly enabled: boolean;
|
|
38
|
+
readonly rpm: number;
|
|
39
|
+
readonly store: "memory" | "redis";
|
|
40
|
+
};
|
|
41
|
+
readonly db: {
|
|
42
|
+
readonly enabled: boolean;
|
|
43
|
+
readonly url: string | undefined;
|
|
44
|
+
};
|
|
45
|
+
readonly systemPrompt: {
|
|
46
|
+
readonly text: string;
|
|
47
|
+
readonly file: string | undefined;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AAqCtB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAiCkC,QAAQ,GAAG,OAAO;;;;;;;;wBASf,QAAQ,GAAG,OAAO;;;;;;;;;;CAYhE,CAAA"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.config = void 0;
|
|
4
|
+
require("dotenv/config");
|
|
5
|
+
function requireEnv(name) {
|
|
6
|
+
const val = process.env[name];
|
|
7
|
+
if (!val)
|
|
8
|
+
throw new Error(`Missing required env var: ${name}`);
|
|
9
|
+
return val;
|
|
10
|
+
}
|
|
11
|
+
function optionalEnv(name, fallback) {
|
|
12
|
+
return process.env[name] ?? fallback;
|
|
13
|
+
}
|
|
14
|
+
function optionalBool(name, fallback) {
|
|
15
|
+
const val = process.env[name];
|
|
16
|
+
if (val === undefined)
|
|
17
|
+
return fallback;
|
|
18
|
+
return val === 'true';
|
|
19
|
+
}
|
|
20
|
+
function optionalInt(name, fallback) {
|
|
21
|
+
const val = process.env[name];
|
|
22
|
+
if (val === undefined)
|
|
23
|
+
return fallback;
|
|
24
|
+
const parsed = parseInt(val, 10);
|
|
25
|
+
if (isNaN(parsed))
|
|
26
|
+
throw new Error(`Env var ${name} must be an integer, got: ${val}`);
|
|
27
|
+
return parsed;
|
|
28
|
+
}
|
|
29
|
+
if (!optionalBool('AUTH_BYPASS', false)) {
|
|
30
|
+
requireEnv('AUTH_SECRET');
|
|
31
|
+
}
|
|
32
|
+
const hasOpenAI = !!process.env['OPENAI_API_KEY'];
|
|
33
|
+
const hasAnthropic = !!process.env['ANTHROPIC_API_KEY'];
|
|
34
|
+
const hasOllama = !!process.env['OLLAMA_BASE_URL'];
|
|
35
|
+
if (!hasOpenAI && !hasAnthropic && !hasOllama) {
|
|
36
|
+
throw new Error('At least one LLM provider key must be configured (OPENAI_API_KEY, ANTHROPIC_API_KEY, or OLLAMA_BASE_URL)');
|
|
37
|
+
}
|
|
38
|
+
exports.config = {
|
|
39
|
+
port: optionalInt('PORT', 3000),
|
|
40
|
+
nodeEnv: optionalEnv('NODE_ENV', 'development'),
|
|
41
|
+
logLevel: optionalEnv('LOG_LEVEL', 'info'),
|
|
42
|
+
auth: {
|
|
43
|
+
secret: process.env['AUTH_SECRET'] ?? '',
|
|
44
|
+
tokenTtl: optionalInt('AUTH_TOKEN_TTL', 86400),
|
|
45
|
+
bypass: optionalBool('AUTH_BYPASS', false),
|
|
46
|
+
},
|
|
47
|
+
providers: {
|
|
48
|
+
openai: {
|
|
49
|
+
apiKey: process.env['OPENAI_API_KEY'],
|
|
50
|
+
baseUrl: process.env['OPENAI_BASE_URL'],
|
|
51
|
+
},
|
|
52
|
+
anthropic: {
|
|
53
|
+
apiKey: process.env['ANTHROPIC_API_KEY'],
|
|
54
|
+
},
|
|
55
|
+
ollama: {
|
|
56
|
+
baseUrl: optionalEnv('OLLAMA_BASE_URL', 'http://localhost:11434'),
|
|
57
|
+
},
|
|
58
|
+
defaultModel: optionalEnv('DEFAULT_MODEL', 'gpt-4o-mini'),
|
|
59
|
+
},
|
|
60
|
+
worker: {
|
|
61
|
+
concurrency: optionalInt('WORKER_CONCURRENCY', 5),
|
|
62
|
+
retryLimit: optionalInt('WORKER_RETRY_LIMIT', 3),
|
|
63
|
+
retryDelayMs: optionalInt('WORKER_RETRY_DELAY_MS', 1000),
|
|
64
|
+
timeoutMs: optionalInt('WORKER_TIMEOUT_MS', 60000),
|
|
65
|
+
},
|
|
66
|
+
context: {
|
|
67
|
+
store: optionalEnv('CONTEXT_STORE', 'memory'),
|
|
68
|
+
redisUrl: optionalEnv('REDIS_URL', 'redis://localhost:6379'),
|
|
69
|
+
maxTokens: optionalInt('CONTEXT_MAX_TOKENS', 4096),
|
|
70
|
+
ttl: optionalInt('CONTEXT_TTL', 3600),
|
|
71
|
+
},
|
|
72
|
+
rateLimit: {
|
|
73
|
+
enabled: optionalBool('RATE_LIMIT_ENABLED', true),
|
|
74
|
+
rpm: optionalInt('RATE_LIMIT_RPM', 60),
|
|
75
|
+
store: optionalEnv('RATE_LIMIT_STORE', 'memory'),
|
|
76
|
+
},
|
|
77
|
+
db: {
|
|
78
|
+
enabled: optionalBool('ENABLE_DB_PERSISTENCE', false),
|
|
79
|
+
url: process.env['DATABASE_URL'],
|
|
80
|
+
},
|
|
81
|
+
systemPrompt: {
|
|
82
|
+
text: optionalEnv('SYSTEM_PROMPT', 'You are a helpful assistant.'),
|
|
83
|
+
file: process.env['SYSTEM_PROMPT_FILE'],
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Message } from '../types';
|
|
2
|
+
type ContextEntry = {
|
|
3
|
+
messages: Message[];
|
|
4
|
+
createdAt: Date;
|
|
5
|
+
updatedAt: Date;
|
|
6
|
+
maxTokens?: number;
|
|
7
|
+
systemPrompt?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare class ContextManager {
|
|
10
|
+
private store;
|
|
11
|
+
get(conversationId: string): Promise<Message[]>;
|
|
12
|
+
getEntry(conversationId: string): Promise<ContextEntry | undefined>;
|
|
13
|
+
create(conversationId: string, options?: {
|
|
14
|
+
systemPrompt?: string;
|
|
15
|
+
maxContextTokens?: number;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
append(conversationId: string, messages: Message[]): Promise<void>;
|
|
18
|
+
clear(conversationId: string): Promise<void>;
|
|
19
|
+
trim(messages: Message[], maxTokens: number): Promise<Message[]>;
|
|
20
|
+
getForRequest(conversationId: string): Promise<{
|
|
21
|
+
messages: Message[];
|
|
22
|
+
systemPrompt?: string;
|
|
23
|
+
}>;
|
|
24
|
+
has(conversationId: string): boolean;
|
|
25
|
+
estimateTokens(messages: Message[]): number;
|
|
26
|
+
getAll(): Map<string, ContextEntry>;
|
|
27
|
+
}
|
|
28
|
+
export declare const contextManager: ContextManager;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=context-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-manager.d.ts","sourceRoot":"","sources":["../../src/context/context-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAIlC,KAAK,YAAY,GAAG;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAuC;IAE9C,GAAG,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAK/C,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;IAInE,MAAM,CACV,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,GAC7D,OAAO,CAAC,IAAI,CAAC;IAYV,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWlE,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5C,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAwBhE,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAOpG,GAAG,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO;IAIpC,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM;IAM3C,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC;CAGpC;AAED,eAAO,MAAM,cAAc,gBAAuB,CAAA"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.contextManager = exports.ContextManager = void 0;
|
|
4
|
+
const logger_1 = require("../lib/logger");
|
|
5
|
+
const config_1 = require("../config");
|
|
6
|
+
class ContextManager {
|
|
7
|
+
store = new Map();
|
|
8
|
+
async get(conversationId) {
|
|
9
|
+
const entry = this.store.get(conversationId);
|
|
10
|
+
return entry ? [...entry.messages] : [];
|
|
11
|
+
}
|
|
12
|
+
async getEntry(conversationId) {
|
|
13
|
+
return this.store.get(conversationId);
|
|
14
|
+
}
|
|
15
|
+
async create(conversationId, options) {
|
|
16
|
+
const now = new Date();
|
|
17
|
+
this.store.set(conversationId, {
|
|
18
|
+
messages: [],
|
|
19
|
+
createdAt: now,
|
|
20
|
+
updatedAt: now,
|
|
21
|
+
maxTokens: options?.maxContextTokens,
|
|
22
|
+
systemPrompt: options?.systemPrompt,
|
|
23
|
+
});
|
|
24
|
+
logger_1.logger.debug({ conversationId }, 'Context created');
|
|
25
|
+
}
|
|
26
|
+
async append(conversationId, messages) {
|
|
27
|
+
let entry = this.store.get(conversationId);
|
|
28
|
+
if (!entry) {
|
|
29
|
+
await this.create(conversationId);
|
|
30
|
+
entry = this.store.get(conversationId);
|
|
31
|
+
}
|
|
32
|
+
entry.messages.push(...messages);
|
|
33
|
+
entry.updatedAt = new Date();
|
|
34
|
+
logger_1.logger.debug({ conversationId, added: messages.length }, 'Context appended');
|
|
35
|
+
}
|
|
36
|
+
async clear(conversationId) {
|
|
37
|
+
this.store.delete(conversationId);
|
|
38
|
+
logger_1.logger.debug({ conversationId }, 'Context cleared');
|
|
39
|
+
}
|
|
40
|
+
async trim(messages, maxTokens) {
|
|
41
|
+
const pinned = messages.filter((m) => m.metadata?.['pinned'] === true);
|
|
42
|
+
const unpinned = messages.filter((m) => m.metadata?.['pinned'] !== true);
|
|
43
|
+
let tokenCount = this.estimateTokens(pinned);
|
|
44
|
+
const kept = [];
|
|
45
|
+
for (let i = unpinned.length - 1; i >= 0; i--) {
|
|
46
|
+
const msg = unpinned[i];
|
|
47
|
+
const msgTokens = this.estimateTokens([msg]);
|
|
48
|
+
if (tokenCount + msgTokens <= maxTokens) {
|
|
49
|
+
kept.unshift(msg);
|
|
50
|
+
tokenCount += msgTokens;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const result = [...pinned, ...kept];
|
|
54
|
+
logger_1.logger.debug({ original: messages.length, trimmed: result.length, tokens: tokenCount }, 'Context trimmed');
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
async getForRequest(conversationId) {
|
|
58
|
+
const entry = this.store.get(conversationId);
|
|
59
|
+
const maxTokens = entry?.maxTokens ?? config_1.config.context.maxTokens;
|
|
60
|
+
const messages = entry ? await this.trim(entry.messages, maxTokens) : [];
|
|
61
|
+
return { messages, systemPrompt: entry?.systemPrompt };
|
|
62
|
+
}
|
|
63
|
+
has(conversationId) {
|
|
64
|
+
return this.store.has(conversationId);
|
|
65
|
+
}
|
|
66
|
+
estimateTokens(messages) {
|
|
67
|
+
return messages.reduce((sum, m) => {
|
|
68
|
+
return sum + Math.ceil(m.content.length / 4) + 4;
|
|
69
|
+
}, 0);
|
|
70
|
+
}
|
|
71
|
+
getAll() {
|
|
72
|
+
return this.store;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.ContextManager = ContextManager;
|
|
76
|
+
exports.contextManager = new ContextManager();
|
|
77
|
+
//# sourceMappingURL=context-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/context/context-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/ai.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAK3C,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB/E"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleComplete = handleComplete;
|
|
4
|
+
const ai_service_1 = require("../services/ai.service");
|
|
5
|
+
const helpers_1 = require("../utils/helpers");
|
|
6
|
+
const logger_1 = require("../lib/logger");
|
|
7
|
+
async function handleComplete(req, res) {
|
|
8
|
+
const { conversationId, messages, model, options } = req.body;
|
|
9
|
+
const convId = conversationId ?? (0, helpers_1.generateId)('conv');
|
|
10
|
+
const userMessage = messages.find((m) => m.role === 'user')?.content ?? '';
|
|
11
|
+
try {
|
|
12
|
+
const response = await (0, ai_service_1.complete)(convId, userMessage, model, options);
|
|
13
|
+
res.json(response);
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
logger_1.logger.error({ err }, 'Controller: completion failed');
|
|
17
|
+
res.status(502).json({ error: 'PROVIDER_ERROR', message: err.message });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=ai.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.controller.js","sourceRoot":"","sources":["../../src/controllers/ai.controller.ts"],"names":[],"mappings":";;AAKA,wCAkBC;AAtBD,uDAAiD;AACjD,8CAA6C;AAC7C,0CAAsC;AAE/B,KAAK,UAAU,cAAc,CAAC,GAAY,EAAE,GAAa;IAC9D,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,IAKxD,CAAA;IAED,MAAM,MAAM,GAAG,cAAc,IAAI,IAAA,oBAAU,EAAC,MAAM,CAAC,CAAA;IACnD,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,OAAO,IAAI,EAAE,CAAA;IAE1E,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAQ,EAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,OAA8C,CAAC,CAAA;QAC3G,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,+BAA+B,CAAC,CAAA;QACtD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;IACpF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/message.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAI3C,wBAAsB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBhF;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAKnF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getConversation = getConversation;
|
|
4
|
+
exports.deleteConversation = deleteConversation;
|
|
5
|
+
const context_manager_1 = require("../context/context-manager");
|
|
6
|
+
const logger_1 = require("../lib/logger");
|
|
7
|
+
async function getConversation(req, res) {
|
|
8
|
+
const id = req.params['id'];
|
|
9
|
+
const entry = await context_manager_1.contextManager.getEntry(id);
|
|
10
|
+
if (!entry) {
|
|
11
|
+
res.status(404).json({ error: 'NOT_FOUND', message: `Conversation ${id} does not exist.` });
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
res.json({
|
|
15
|
+
conversationId: id,
|
|
16
|
+
messages: entry.messages,
|
|
17
|
+
createdAt: entry.createdAt,
|
|
18
|
+
updatedAt: entry.updatedAt,
|
|
19
|
+
tokenCount: context_manager_1.contextManager.estimateTokens(entry.messages),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async function deleteConversation(req, res) {
|
|
23
|
+
const id = req.params['id'];
|
|
24
|
+
await context_manager_1.contextManager.clear(id);
|
|
25
|
+
logger_1.logger.debug({ conversationId: id }, 'Conversation deleted');
|
|
26
|
+
res.status(204).send();
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=message.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.controller.js","sourceRoot":"","sources":["../../src/controllers/message.controller.ts"],"names":[],"mappings":";;AAIA,0CAgBC;AAED,gDAKC;AA1BD,gEAA2D;AAC3D,0CAAsC;AAE/B,KAAK,UAAU,eAAe,CAAC,GAAY,EAAE,GAAa;IAC/D,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAW,CAAA;IACrC,MAAM,KAAK,GAAG,MAAM,gCAAc,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAE/C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,CAAC,CAAA;QAC3F,OAAM;IACR,CAAC;IAED,GAAG,CAAC,IAAI,CAAC;QACP,cAAc,EAAE,EAAE;QAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,UAAU,EAAE,gCAAc,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC;KAC1D,CAAC,CAAA;AACJ,CAAC;AAEM,KAAK,UAAU,kBAAkB,CAAC,GAAY,EAAE,GAAa;IAClE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAW,CAAA;IACrC,MAAM,gCAAc,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IAC9B,eAAM,CAAC,KAAK,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,EAAE,sBAAsB,CAAC,CAAA;IAC5D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;AACxB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA"}
|