@yesvara/svara 0.1.2 → 0.2.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/CONTRIBUTING.md +1 -1
- package/README.md +187 -19
- package/dist/cli/index.js +35 -37
- package/dist/cli/index.mjs +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +10 -0
- package/dist/index.mjs +10 -0
- package/dist/{new-7K4NIDZO.mjs → new-ULRP6IUQ.mjs} +35 -37
- package/examples/03-rag-knowledge/index.ts +2 -4
- package/package.json +1 -1
- package/src/cli/commands/new.ts +35 -41
- package/src/core/agent.ts +12 -0
- package/svara@1.0.0 +0 -0
- package/test-rag.ts +0 -20
- package/tsx +0 -0
package/CONTRIBUTING.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Contributing to SvaraJS
|
|
2
2
|
|
|
3
|
-
Thanks for your interest in contributing! We welcome all contributions
|
|
3
|
+
Thanks for your interest in contributing! We welcome all contributions such as bug reports, feature requests, documentation improvements, and pull requests.
|
|
4
4
|
|
|
5
5
|
## Code of Conduct
|
|
6
6
|
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
<!-- # @yesvara/svara -->
|
|
5
5
|
|
|
6
|
-
**Build AI agents in
|
|
6
|
+
**Build AI agents in less than 9 lines. Ship to production.**
|
|
7
7
|
|
|
8
8
|
A batteries-included Node.js framework for building agentic AI backends.
|
|
9
9
|
Multi-channel, RAG-ready, and designed for developers who value simplicity.
|
|
@@ -22,18 +22,16 @@ Multi-channel, RAG-ready, and designed for developers who value simplicity.
|
|
|
22
22
|
Most AI frameworks make you think about infrastructure. SvaraJS makes you think about your agent.
|
|
23
23
|
|
|
24
24
|
```ts
|
|
25
|
-
import { SvaraApp, SvaraAgent } from '@yesvara/svara';
|
|
26
|
-
|
|
27
|
-
const app = new SvaraApp();
|
|
25
|
+
import { SvaraApp, SvaraAgent, createTool } from '@yesvara/svara';
|
|
28
26
|
|
|
29
27
|
const agent = new SvaraAgent({
|
|
30
28
|
name: 'Support Bot',
|
|
31
29
|
model: 'gpt-4o-mini', // provider auto-detected
|
|
32
|
-
knowledge: './docs', // PDF, MD, TXT
|
|
30
|
+
knowledge: './docs', // PDF, MD, TXT, just point to a folder
|
|
31
|
+
tools: [tool_1, tool_2, tool_3], // Agent choose the right tool for answer
|
|
33
32
|
});
|
|
34
33
|
|
|
35
|
-
app.route('/chat', agent.handler());
|
|
36
|
-
app.listen(3000);
|
|
34
|
+
const app = new SvaraApp().route('/chat', agent.handler()).listen(3000);
|
|
37
35
|
// Done. Your agent handles 1000 conversations.
|
|
38
36
|
```
|
|
39
37
|
|
|
@@ -44,7 +42,7 @@ That's it. No pipeline setup. No embedding boilerplate. No webhook configuration
|
|
|
44
42
|
|
|
45
43
|
## Features
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
|||
|
|
48
46
|
|---|---|
|
|
49
47
|
| **Zero-config LLM** | Pass a model name, provider is auto-detected |
|
|
50
48
|
| **Instant RAG** | Point to a folder, documents are indexed automatically |
|
|
@@ -359,7 +357,7 @@ agent
|
|
|
359
357
|
verifyToken: process.env.WA_VERIFY_TOKEN,
|
|
360
358
|
});
|
|
361
359
|
|
|
362
|
-
await agent.start();
|
|
360
|
+
await agent.start(); // Start all channels
|
|
363
361
|
```
|
|
364
362
|
|
|
365
363
|
### Events
|
|
@@ -416,12 +414,15 @@ console.log(reply); // "It's currently 14:32 UTC..."
|
|
|
416
414
|
const agent = new SvaraAgent({
|
|
417
415
|
name: 'Support Bot',
|
|
418
416
|
model: 'gpt-4o-mini',
|
|
419
|
-
knowledge: './docs',
|
|
417
|
+
knowledge: './docs', // Auto-loaded on first request
|
|
420
418
|
systemPrompt: 'You are a customer support agent. Answer using the documentation.',
|
|
421
419
|
memory: { window: 20 },
|
|
422
420
|
});
|
|
423
421
|
|
|
424
|
-
|
|
422
|
+
const app = new SvaraApp({ cors: true });
|
|
423
|
+
app.route('/chat', agent.handler());
|
|
424
|
+
app.listen(3000);
|
|
425
|
+
// Knowledge indexes automatically on first request
|
|
425
426
|
```
|
|
426
427
|
|
|
427
428
|
### Multi-channel (Web + Telegram + WhatsApp)
|
|
@@ -462,21 +463,105 @@ app.listen(3000);
|
|
|
462
463
|
|
|
463
464
|
---
|
|
464
465
|
|
|
466
|
+
## Adding Knowledge & Tools at Runtime
|
|
467
|
+
|
|
468
|
+
### Adding knowledge (dynamic indexing)
|
|
469
|
+
|
|
470
|
+
After the agent is created, add more documents **without restarting**:
|
|
471
|
+
|
|
472
|
+
```ts
|
|
473
|
+
const agent = new SvaraAgent({
|
|
474
|
+
name: 'Support Bot',
|
|
475
|
+
model: 'gpt-4o-mini',
|
|
476
|
+
knowledge: './docs', // Initial knowledge
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
// ── Later (no restart needed) ──────────────────────
|
|
480
|
+
// Add a single document
|
|
481
|
+
await agent.addKnowledge('./policies/new-policy-2024.pdf');
|
|
482
|
+
|
|
483
|
+
// Add multiple documents
|
|
484
|
+
await agent.addKnowledge(['./faq.md', './terms.txt', './pricing.pdf']);
|
|
485
|
+
|
|
486
|
+
// Agent immediately has the new knowledge
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
**Real-world example** — admin endpoint to upload documents:
|
|
490
|
+
|
|
491
|
+
```ts
|
|
492
|
+
const app = new SvaraApp({ cors: true });
|
|
493
|
+
app.route('/chat', agent.handler());
|
|
494
|
+
|
|
495
|
+
// Admin: dynamically add knowledge
|
|
496
|
+
app.post('/admin/add-knowledge', async (req, res) => {
|
|
497
|
+
const { path } = req.body;
|
|
498
|
+
try {
|
|
499
|
+
await agent.addKnowledge(path);
|
|
500
|
+
res.json({ status: 'Knowledge added', path });
|
|
501
|
+
} catch (err) {
|
|
502
|
+
res.status(400).json({ error: (err as Error).message });
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
app.listen(3000);
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
### Adding tools (dynamic function calling)
|
|
510
|
+
|
|
511
|
+
Add tools at runtime with `addTool()`:
|
|
512
|
+
|
|
513
|
+
```ts
|
|
514
|
+
import { SvaraAgent, createTool } from '@yesvara/svara';
|
|
515
|
+
|
|
516
|
+
const agent = new SvaraAgent({
|
|
517
|
+
name: 'Assistant',
|
|
518
|
+
model: 'gpt-4o-mini',
|
|
519
|
+
tools: [initialTool], // Start with one tool
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
// ── Later ────────────────────────────────────────
|
|
523
|
+
// Add more tools dynamically
|
|
524
|
+
const newTool = createTool({
|
|
525
|
+
name: 'send_email',
|
|
526
|
+
description: 'Send an email to a user',
|
|
527
|
+
parameters: {
|
|
528
|
+
to: { type: 'string', description: 'Email address', required: true },
|
|
529
|
+
subject: { type: 'string', description: 'Email subject', required: true },
|
|
530
|
+
body: { type: 'string', description: 'Email body', required: true },
|
|
531
|
+
},
|
|
532
|
+
async run({ to, subject, body }) {
|
|
533
|
+
// Call your email service
|
|
534
|
+
return { status: 'sent', to, subject };
|
|
535
|
+
},
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
agent.addTool(newTool);
|
|
539
|
+
|
|
540
|
+
// Agent can now use send_email tool
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
**Chainable tool registration** (multiple tools):
|
|
544
|
+
|
|
545
|
+
```ts
|
|
546
|
+
agent
|
|
547
|
+
.addTool(emailTool)
|
|
548
|
+
.addTool(databaseTool)
|
|
549
|
+
.addTool(slackTool)
|
|
550
|
+
.addTool(webhookTool);
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
---
|
|
554
|
+
|
|
465
555
|
## CLI
|
|
466
556
|
|
|
557
|
+
### Create a new project
|
|
558
|
+
|
|
467
559
|
```bash
|
|
468
|
-
# Scaffold a new project
|
|
469
560
|
svara new my-app
|
|
470
|
-
|
|
471
|
-
# Start dev server with hot-reload
|
|
472
|
-
svara dev
|
|
473
|
-
|
|
474
|
-
# Build for production
|
|
475
|
-
svara build
|
|
476
561
|
```
|
|
477
562
|
|
|
563
|
+
Output:
|
|
478
564
|
```
|
|
479
|
-
$ svara new my-app
|
|
480
565
|
✨ Creating SvaraJS project: my-app
|
|
481
566
|
|
|
482
567
|
✓ package.json
|
|
@@ -494,6 +579,89 @@ $ svara new my-app
|
|
|
494
579
|
npm run dev
|
|
495
580
|
```
|
|
496
581
|
|
|
582
|
+
Options:
|
|
583
|
+
- `--template <name>` — Use a specific template (default: `basic`)
|
|
584
|
+
- `basic` — Simple agent with HTTP endpoint
|
|
585
|
+
- `rag` — RAG-powered agent with document loader
|
|
586
|
+
- `multi-channel` — Web + Telegram + WhatsApp setup
|
|
587
|
+
- `tools` — Agent with tool calling examples
|
|
588
|
+
|
|
589
|
+
### Start development server
|
|
590
|
+
|
|
591
|
+
```bash
|
|
592
|
+
svara dev
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Features:
|
|
596
|
+
- Hot-reload on file changes
|
|
597
|
+
- Auto-restart agent on code updates
|
|
598
|
+
- Debug logging enabled
|
|
599
|
+
- Serves on `http://localhost:3000` (configurable)
|
|
600
|
+
|
|
601
|
+
Options:
|
|
602
|
+
- `--port <number>` — Custom port (default: `3000`)
|
|
603
|
+
- `--watch <glob>` — Watch additional paths (default: `src/**`)
|
|
604
|
+
- `--env <file>` — Load custom .env file
|
|
605
|
+
|
|
606
|
+
### Build for production
|
|
607
|
+
|
|
608
|
+
```bash
|
|
609
|
+
svara build
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
Outputs:
|
|
613
|
+
- `dist/` — Compiled JavaScript
|
|
614
|
+
- `dist/index.js` — Entry point (ready for Node or Docker)
|
|
615
|
+
- Source maps and type declarations included
|
|
616
|
+
|
|
617
|
+
Options:
|
|
618
|
+
- `--minify` — Minify output
|
|
619
|
+
- `--sourcemaps` — Include source maps (default: true)
|
|
620
|
+
- `--outdir <path>` — Custom output directory (default: `dist/`)
|
|
621
|
+
|
|
622
|
+
### Running built projects
|
|
623
|
+
|
|
624
|
+
```bash
|
|
625
|
+
# After building
|
|
626
|
+
node dist/index.js
|
|
627
|
+
|
|
628
|
+
# Or with env file
|
|
629
|
+
NODE_ENV=production OPENAI_API_KEY=sk-... node dist/index.js
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### Database management
|
|
633
|
+
|
|
634
|
+
```bash
|
|
635
|
+
# Initialize database (auto-creates tables)
|
|
636
|
+
svara db init
|
|
637
|
+
|
|
638
|
+
# Show database schema
|
|
639
|
+
svara db schema
|
|
640
|
+
|
|
641
|
+
# Export users and conversation history
|
|
642
|
+
svara db export --format json
|
|
643
|
+
svara db export --format csv --table svara_messages
|
|
644
|
+
|
|
645
|
+
# Query database directly
|
|
646
|
+
svara db query "SELECT COUNT(*) FROM svara_users"
|
|
647
|
+
|
|
648
|
+
# Reset database (⚠️ deletes all data)
|
|
649
|
+
svara db reset
|
|
650
|
+
|
|
651
|
+
# Backup database
|
|
652
|
+
svara db backup --output backup-2026-01-15.db
|
|
653
|
+
|
|
654
|
+
# Restore from backup
|
|
655
|
+
svara db restore --input backup-2026-01-15.db
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
Options:
|
|
659
|
+
- `--db <path>` — Custom database path (default: `./data/svara.db`)
|
|
660
|
+
- `--format <type>` — Export format: `json`, `csv`, `sql` (default: `json`)
|
|
661
|
+
- `--table <name>` — Specific table to export
|
|
662
|
+
- `--output <path>` — Output file path
|
|
663
|
+
- `--force` — Skip confirmation prompts (use with `reset` carefully!)
|
|
664
|
+
|
|
497
665
|
---
|
|
498
666
|
|
|
499
667
|
## Built-in Database
|
package/dist/cli/index.js
CHANGED
|
@@ -97,7 +97,7 @@ function generatePackageJson(name) {
|
|
|
97
97
|
start: "node dist/index.js"
|
|
98
98
|
},
|
|
99
99
|
dependencies: {
|
|
100
|
-
|
|
100
|
+
"@yesvara/svara": "^0.1.3",
|
|
101
101
|
dotenv: "^16.4.5"
|
|
102
102
|
},
|
|
103
103
|
devDependencies: {
|
|
@@ -144,55 +144,53 @@ function generateIndexFile(name, provider, channels) {
|
|
|
144
144
|
anthropic: "claude-opus-4-6",
|
|
145
145
|
ollama: "llama3"
|
|
146
146
|
};
|
|
147
|
-
const channelSetup = channels.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
147
|
+
const channelSetup = channels.includes("web") ? `const app = new SvaraApp({ cors: true });
|
|
148
|
+
app.route('/chat', agent.handler());
|
|
149
|
+
app.listen(3000);` : channels.length > 0 ? `agent
|
|
150
|
+
${channels.map((ch) => {
|
|
151
|
+
if (ch === "telegram") return `.connectChannel('telegram', { token: process.env.TELEGRAM_BOT_TOKEN! })`;
|
|
152
|
+
if (ch === "whatsapp")
|
|
153
|
+
return `.connectChannel('whatsapp', {
|
|
154
|
+
token: process.env.WA_ACCESS_TOKEN!,
|
|
155
|
+
phoneId: process.env.WA_PHONE_ID!,
|
|
156
|
+
verifyToken: process.env.WA_VERIFY_TOKEN!,
|
|
157
|
+
})`;
|
|
157
158
|
return "";
|
|
158
|
-
}).filter(Boolean).join("\n");
|
|
159
|
+
}).filter(Boolean).join("\n ")};
|
|
160
|
+
await agent.start();` : "";
|
|
159
161
|
return `import 'dotenv/config';
|
|
160
|
-
import {
|
|
162
|
+
import { SvaraApp, SvaraAgent, createTool } from '@yesvara/svara';
|
|
161
163
|
|
|
162
164
|
/**
|
|
163
165
|
* ${name} \u2014 powered by SvaraJS
|
|
164
166
|
*/
|
|
165
|
-
const agent = svara({
|
|
166
|
-
llm: {
|
|
167
|
-
provider: '${provider}',
|
|
168
|
-
model: '${modelMap[provider] ?? "gpt-4o"}',
|
|
169
|
-
},
|
|
170
|
-
systemPrompt: \`You are a helpful AI assistant called ${name}.
|
|
171
|
-
Be concise, friendly, and always try your best to help.\`,
|
|
172
|
-
memory: {
|
|
173
|
-
type: 'conversation',
|
|
174
|
-
maxMessages: 20,
|
|
175
|
-
},
|
|
176
|
-
verbose: true,
|
|
177
|
-
});
|
|
178
167
|
|
|
179
|
-
//
|
|
180
|
-
|
|
168
|
+
// Define tools
|
|
169
|
+
const timeTool = createTool({
|
|
170
|
+
name: 'get_time',
|
|
181
171
|
description: 'Get the current date and time',
|
|
182
172
|
parameters: {},
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
173
|
+
async run() {
|
|
174
|
+
return {
|
|
175
|
+
datetime: new Date().toISOString(),
|
|
176
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Create agent
|
|
182
|
+
const agent = new SvaraAgent({
|
|
183
|
+
name: '${name}',
|
|
184
|
+
model: '${modelMap[provider] ?? "gpt-4o"}',
|
|
185
|
+
systemPrompt: 'You are a helpful AI assistant. Be concise and friendly.',
|
|
186
|
+
tools: [timeTool],
|
|
187
|
+
knowledge: './docs', // Add your documents here for RAG
|
|
187
188
|
});
|
|
188
189
|
|
|
189
|
-
//
|
|
190
|
+
// Setup channels
|
|
190
191
|
${channelSetup}
|
|
191
192
|
|
|
192
|
-
|
|
193
|
-
agent.start().then(() => {
|
|
194
|
-
console.log('\u{1F680} ${name} is running!');
|
|
195
|
-
});
|
|
193
|
+
console.log('\u2728 ${name} is running!');
|
|
196
194
|
`;
|
|
197
195
|
}
|
|
198
196
|
function generateGitignore() {
|
package/dist/cli/index.mjs
CHANGED
|
@@ -9,7 +9,7 @@ var pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
|
9
9
|
var program = new Command();
|
|
10
10
|
program.name("svara").description(pkg.description).version(pkg.version, "-v, --version");
|
|
11
11
|
program.command("new <name>").description("Create a new SvaraJS project").option("--provider <provider>", "LLM provider (openai|anthropic|ollama)", "openai").option("--channel <channels...>", "Channels to include", ["web"]).option("--no-install", "Skip npm install").action(async (name, opts) => {
|
|
12
|
-
const { newProject } = await import("../new-
|
|
12
|
+
const { newProject } = await import("../new-ULRP6IUQ.mjs");
|
|
13
13
|
await newProject({
|
|
14
14
|
name,
|
|
15
15
|
provider: opts.provider,
|
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1701,6 +1701,7 @@ var SvaraAgent = class extends import_events.default {
|
|
|
1701
1701
|
// Store VectorRetriever for retrieveChunks access
|
|
1702
1702
|
knowledgePaths = [];
|
|
1703
1703
|
isStarted = false;
|
|
1704
|
+
isKnowledgeInitialized = false;
|
|
1704
1705
|
db;
|
|
1705
1706
|
constructor(config) {
|
|
1706
1707
|
super();
|
|
@@ -1809,6 +1810,15 @@ var SvaraAgent = class extends import_events.default {
|
|
|
1809
1810
|
*/
|
|
1810
1811
|
handler() {
|
|
1811
1812
|
return async (req, res) => {
|
|
1813
|
+
if (this.knowledgePaths.length > 0 && !this.isKnowledgeInitialized) {
|
|
1814
|
+
try {
|
|
1815
|
+
await this.initKnowledge(this.knowledgePaths);
|
|
1816
|
+
this.isKnowledgeInitialized = true;
|
|
1817
|
+
} catch (err) {
|
|
1818
|
+
const error = err;
|
|
1819
|
+
this.log("error", `Failed to initialize knowledge: ${error.message}`);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1812
1822
|
const { message, sessionId, userId } = req.body;
|
|
1813
1823
|
if (!message?.trim()) {
|
|
1814
1824
|
res.status(400).json({
|
package/dist/index.mjs
CHANGED
|
@@ -891,6 +891,7 @@ var SvaraAgent = class extends EventEmitter {
|
|
|
891
891
|
// Store VectorRetriever for retrieveChunks access
|
|
892
892
|
knowledgePaths = [];
|
|
893
893
|
isStarted = false;
|
|
894
|
+
isKnowledgeInitialized = false;
|
|
894
895
|
db;
|
|
895
896
|
constructor(config) {
|
|
896
897
|
super();
|
|
@@ -999,6 +1000,15 @@ var SvaraAgent = class extends EventEmitter {
|
|
|
999
1000
|
*/
|
|
1000
1001
|
handler() {
|
|
1001
1002
|
return async (req, res) => {
|
|
1003
|
+
if (this.knowledgePaths.length > 0 && !this.isKnowledgeInitialized) {
|
|
1004
|
+
try {
|
|
1005
|
+
await this.initKnowledge(this.knowledgePaths);
|
|
1006
|
+
this.isKnowledgeInitialized = true;
|
|
1007
|
+
} catch (err) {
|
|
1008
|
+
const error = err;
|
|
1009
|
+
this.log("error", `Failed to initialize knowledge: ${error.message}`);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1002
1012
|
const { message, sessionId, userId } = req.body;
|
|
1003
1013
|
if (!message?.trim()) {
|
|
1004
1014
|
res.status(400).json({
|
|
@@ -66,7 +66,7 @@ function generatePackageJson(name) {
|
|
|
66
66
|
start: "node dist/index.js"
|
|
67
67
|
},
|
|
68
68
|
dependencies: {
|
|
69
|
-
|
|
69
|
+
"@yesvara/svara": "^0.1.3",
|
|
70
70
|
dotenv: "^16.4.5"
|
|
71
71
|
},
|
|
72
72
|
devDependencies: {
|
|
@@ -113,55 +113,53 @@ function generateIndexFile(name, provider, channels) {
|
|
|
113
113
|
anthropic: "claude-opus-4-6",
|
|
114
114
|
ollama: "llama3"
|
|
115
115
|
};
|
|
116
|
-
const channelSetup = channels.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
116
|
+
const channelSetup = channels.includes("web") ? `const app = new SvaraApp({ cors: true });
|
|
117
|
+
app.route('/chat', agent.handler());
|
|
118
|
+
app.listen(3000);` : channels.length > 0 ? `agent
|
|
119
|
+
${channels.map((ch) => {
|
|
120
|
+
if (ch === "telegram") return `.connectChannel('telegram', { token: process.env.TELEGRAM_BOT_TOKEN! })`;
|
|
121
|
+
if (ch === "whatsapp")
|
|
122
|
+
return `.connectChannel('whatsapp', {
|
|
123
|
+
token: process.env.WA_ACCESS_TOKEN!,
|
|
124
|
+
phoneId: process.env.WA_PHONE_ID!,
|
|
125
|
+
verifyToken: process.env.WA_VERIFY_TOKEN!,
|
|
126
|
+
})`;
|
|
126
127
|
return "";
|
|
127
|
-
}).filter(Boolean).join("\n");
|
|
128
|
+
}).filter(Boolean).join("\n ")};
|
|
129
|
+
await agent.start();` : "";
|
|
128
130
|
return `import 'dotenv/config';
|
|
129
|
-
import {
|
|
131
|
+
import { SvaraApp, SvaraAgent, createTool } from '@yesvara/svara';
|
|
130
132
|
|
|
131
133
|
/**
|
|
132
134
|
* ${name} \u2014 powered by SvaraJS
|
|
133
135
|
*/
|
|
134
|
-
const agent = svara({
|
|
135
|
-
llm: {
|
|
136
|
-
provider: '${provider}',
|
|
137
|
-
model: '${modelMap[provider] ?? "gpt-4o"}',
|
|
138
|
-
},
|
|
139
|
-
systemPrompt: \`You are a helpful AI assistant called ${name}.
|
|
140
|
-
Be concise, friendly, and always try your best to help.\`,
|
|
141
|
-
memory: {
|
|
142
|
-
type: 'conversation',
|
|
143
|
-
maxMessages: 20,
|
|
144
|
-
},
|
|
145
|
-
verbose: true,
|
|
146
|
-
});
|
|
147
136
|
|
|
148
|
-
//
|
|
149
|
-
|
|
137
|
+
// Define tools
|
|
138
|
+
const timeTool = createTool({
|
|
139
|
+
name: 'get_time',
|
|
150
140
|
description: 'Get the current date and time',
|
|
151
141
|
parameters: {},
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
142
|
+
async run() {
|
|
143
|
+
return {
|
|
144
|
+
datetime: new Date().toISOString(),
|
|
145
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
146
|
+
};
|
|
147
|
+
},
|
|
156
148
|
});
|
|
157
149
|
|
|
158
|
-
//
|
|
150
|
+
// Create agent
|
|
151
|
+
const agent = new SvaraAgent({
|
|
152
|
+
name: '${name}',
|
|
153
|
+
model: '${modelMap[provider] ?? "gpt-4o"}',
|
|
154
|
+
systemPrompt: 'You are a helpful AI assistant. Be concise and friendly.',
|
|
155
|
+
tools: [timeTool],
|
|
156
|
+
knowledge: './docs', // Add your documents here for RAG
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Setup channels
|
|
159
160
|
${channelSetup}
|
|
160
161
|
|
|
161
|
-
|
|
162
|
-
agent.start().then(() => {
|
|
163
|
-
console.log('\u{1F680} ${name} is running!');
|
|
164
|
-
});
|
|
162
|
+
console.log('\u2728 ${name} is running!');
|
|
165
163
|
`;
|
|
166
164
|
}
|
|
167
165
|
function generateGitignore() {
|
|
@@ -31,11 +31,9 @@ Always be friendly and professional.`,
|
|
|
31
31
|
memory: { window: 20 },
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
// You can also add knowledge dynamically (hot reload, no restart needed)
|
|
35
|
-
// await agent.addKnowledge('./new-policy-2024.pdf');
|
|
36
|
-
|
|
37
34
|
const app = new SvaraApp({ cors: true });
|
|
38
35
|
app.route('/chat', agent.handler());
|
|
39
36
|
|
|
40
|
-
await agent.start(); // indexes documents
|
|
41
37
|
app.listen(3000);
|
|
38
|
+
console.log('✓ Agent running on http://localhost:3000');
|
|
39
|
+
console.log(' Knowledge base auto-loads on first request');
|
package/package.json
CHANGED
package/src/cli/commands/new.ts
CHANGED
|
@@ -86,7 +86,7 @@ function generatePackageJson(name: string): string {
|
|
|
86
86
|
start: 'node dist/index.js',
|
|
87
87
|
},
|
|
88
88
|
dependencies: {
|
|
89
|
-
|
|
89
|
+
'@yesvara/svara': '^0.1.3',
|
|
90
90
|
dotenv: '^16.4.5',
|
|
91
91
|
},
|
|
92
92
|
devDependencies: {
|
|
@@ -147,59 +147,53 @@ function generateIndexFile(
|
|
|
147
147
|
ollama: 'llama3',
|
|
148
148
|
};
|
|
149
149
|
|
|
150
|
-
const channelSetup = channels
|
|
151
|
-
.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
.filter(Boolean)
|
|
164
|
-
.join('\n');
|
|
150
|
+
const channelSetup = channels.includes('web')
|
|
151
|
+
? `const app = new SvaraApp({ cors: true });\napp.route('/chat', agent.handler());\napp.listen(3000);`
|
|
152
|
+
: channels.length > 0
|
|
153
|
+
? `agent\n ${channels
|
|
154
|
+
.map((ch) => {
|
|
155
|
+
if (ch === 'telegram') return `.connectChannel('telegram', { token: process.env.TELEGRAM_BOT_TOKEN! })`;
|
|
156
|
+
if (ch === 'whatsapp')
|
|
157
|
+
return `.connectChannel('whatsapp', {\n token: process.env.WA_ACCESS_TOKEN!,\n phoneId: process.env.WA_PHONE_ID!,\n verifyToken: process.env.WA_VERIFY_TOKEN!,\n })`;
|
|
158
|
+
return '';
|
|
159
|
+
})
|
|
160
|
+
.filter(Boolean)
|
|
161
|
+
.join('\n ')};\nawait agent.start();`
|
|
162
|
+
: '';
|
|
165
163
|
|
|
166
164
|
return `import 'dotenv/config';
|
|
167
|
-
import {
|
|
165
|
+
import { SvaraApp, SvaraAgent, createTool } from '@yesvara/svara';
|
|
168
166
|
|
|
169
167
|
/**
|
|
170
168
|
* ${name} — powered by SvaraJS
|
|
171
169
|
*/
|
|
172
|
-
const agent = svara({
|
|
173
|
-
llm: {
|
|
174
|
-
provider: '${provider}',
|
|
175
|
-
model: '${modelMap[provider] ?? 'gpt-4o'}',
|
|
176
|
-
},
|
|
177
|
-
systemPrompt: \`You are a helpful AI assistant called ${name}.
|
|
178
|
-
Be concise, friendly, and always try your best to help.\`,
|
|
179
|
-
memory: {
|
|
180
|
-
type: 'conversation',
|
|
181
|
-
maxMessages: 20,
|
|
182
|
-
},
|
|
183
|
-
verbose: true,
|
|
184
|
-
});
|
|
185
170
|
|
|
186
|
-
//
|
|
187
|
-
|
|
171
|
+
// Define tools
|
|
172
|
+
const timeTool = createTool({
|
|
173
|
+
name: 'get_time',
|
|
188
174
|
description: 'Get the current date and time',
|
|
189
175
|
parameters: {},
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
176
|
+
async run() {
|
|
177
|
+
return {
|
|
178
|
+
datetime: new Date().toISOString(),
|
|
179
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
180
|
+
};
|
|
181
|
+
},
|
|
194
182
|
});
|
|
195
183
|
|
|
196
|
-
//
|
|
184
|
+
// Create agent
|
|
185
|
+
const agent = new SvaraAgent({
|
|
186
|
+
name: '${name}',
|
|
187
|
+
model: '${modelMap[provider] ?? 'gpt-4o'}',
|
|
188
|
+
systemPrompt: 'You are a helpful AI assistant. Be concise and friendly.',
|
|
189
|
+
tools: [timeTool],
|
|
190
|
+
knowledge: './docs', // Add your documents here for RAG
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Setup channels
|
|
197
194
|
${channelSetup}
|
|
198
195
|
|
|
199
|
-
|
|
200
|
-
agent.start().then(() => {
|
|
201
|
-
console.log('🚀 ${name} is running!');
|
|
202
|
-
});
|
|
196
|
+
console.log('✨ ${name} is running!');
|
|
203
197
|
`;
|
|
204
198
|
}
|
|
205
199
|
|
package/src/core/agent.ts
CHANGED
|
@@ -173,6 +173,7 @@ export class SvaraAgent extends EventEmitter {
|
|
|
173
173
|
private retriever: any = null; // Store VectorRetriever for retrieveChunks access
|
|
174
174
|
private knowledgePaths: string[] = [];
|
|
175
175
|
private isStarted = false;
|
|
176
|
+
private isKnowledgeInitialized = false;
|
|
176
177
|
private db: SvaraDB;
|
|
177
178
|
|
|
178
179
|
constructor(config: AgentConfig) {
|
|
@@ -303,6 +304,17 @@ export class SvaraAgent extends EventEmitter {
|
|
|
303
304
|
*/
|
|
304
305
|
handler(): RequestHandler {
|
|
305
306
|
return async (req, res) => {
|
|
307
|
+
// Auto-initialize knowledge on first request (lazy loading)
|
|
308
|
+
if (this.knowledgePaths.length > 0 && !this.isKnowledgeInitialized) {
|
|
309
|
+
try {
|
|
310
|
+
await this.initKnowledge(this.knowledgePaths);
|
|
311
|
+
this.isKnowledgeInitialized = true;
|
|
312
|
+
} catch (err) {
|
|
313
|
+
const error = err as Error;
|
|
314
|
+
this.log('error', `Failed to initialize knowledge: ${error.message}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
306
318
|
const { message, sessionId, userId } = req.body as {
|
|
307
319
|
message?: string;
|
|
308
320
|
sessionId?: string;
|
package/svara@1.0.0
DELETED
|
File without changes
|
package/test-rag.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
|
-
import { SvaraApp, SvaraAgent } from './src/index.js';
|
|
3
|
-
|
|
4
|
-
async function main() {
|
|
5
|
-
const app = new SvaraApp({ cors: true });
|
|
6
|
-
|
|
7
|
-
const agent = new SvaraAgent({
|
|
8
|
-
name: 'TestAgent',
|
|
9
|
-
model: 'gpt-4o-mini',
|
|
10
|
-
knowledge: '/Users/920078/Documents/svara/contoh_folder_knowledge/**/*',
|
|
11
|
-
verbose: true,
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
await agent.start();
|
|
15
|
-
app.route('/chat', agent.handler());
|
|
16
|
-
app.listen(3000);
|
|
17
|
-
console.log('✓ Test server on port 3000');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
main().catch(console.error);
|
package/tsx
DELETED
|
File without changes
|