@learningnodes/elen 0.1.1
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/client_test_output.txt +17 -0
- package/dist/client.d.ts +16 -0
- package/dist/client.js +80 -0
- package/dist/id.d.ts +3 -0
- package/dist/id.js +20 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +51 -0
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.js +19 -0
- package/dist/storage/interface.d.ts +11 -0
- package/dist/storage/interface.js +2 -0
- package/dist/storage/memory.d.ts +14 -0
- package/dist/storage/memory.js +69 -0
- package/dist/storage/sqlite.d.ts +34 -0
- package/dist/storage/sqlite.js +334 -0
- package/dist/types.d.ts +30 -0
- package/dist/types.js +2 -0
- package/package.json +22 -0
- package/src/client.ts +93 -0
- package/src/id.ts +18 -0
- package/src/index.ts +45 -0
- package/src/shims.d.ts +27 -0
- package/src/storage/index.ts +3 -0
- package/src/storage/interface.ts +12 -0
- package/src/storage/memory.ts +85 -0
- package/src/storage/sqlite.ts +397 -0
- package/src/types.ts +35 -0
- package/test_output.txt +78 -0
- package/tests/client.test.ts +147 -0
- package/tests/integration.test.ts +49 -0
- package/tests/storage.test.ts +100 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { rmSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { Elen } from '../src';
|
|
6
|
+
|
|
7
|
+
describe('Elen integration', () => {
|
|
8
|
+
it('supports batch decision logging and precedent search in memory mode', async () => {
|
|
9
|
+
const elen = new Elen({ agentId: 'agent-int', storage: 'memory' });
|
|
10
|
+
|
|
11
|
+
const first = await elen.logDecision({
|
|
12
|
+
question: 'Which database for sessions?',
|
|
13
|
+
domain: 'infrastructure',
|
|
14
|
+
constraints: ['Must support >1000 writes'],
|
|
15
|
+
evidence: ['pgbench: PostgreSQL 3200 TPS vs SQLite 280 TPS'],
|
|
16
|
+
answer: 'PostgreSQL 16'
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
await elen.logDecision({
|
|
20
|
+
question: 'Which pooler?',
|
|
21
|
+
domain: 'infrastructure',
|
|
22
|
+
constraints: ['Must work with PostgreSQL'],
|
|
23
|
+
evidence: ['PostgreSQL selected per precedent'],
|
|
24
|
+
linkedPrecedents: [first.record_id],
|
|
25
|
+
answer: 'PgBouncer'
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const precedents = await elen.searchPrecedents('high concurrency database selection');
|
|
29
|
+
expect(precedents.length).toBeGreaterThan(0);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('supports sqlite-backed usage', async () => {
|
|
33
|
+
const dbPath = join(tmpdir(), `elen-int-${Date.now()}.db`);
|
|
34
|
+
const elen = new Elen({ agentId: 'agent-sql', storage: 'sqlite', sqlitePath: dbPath });
|
|
35
|
+
|
|
36
|
+
await elen.logDecision({
|
|
37
|
+
question: 'Which cache?',
|
|
38
|
+
domain: 'infrastructure',
|
|
39
|
+
constraints: ['Must be open-source'],
|
|
40
|
+
evidence: ['documentation recommends Redis for this workload'],
|
|
41
|
+
answer: 'Redis'
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const records = await elen.searchRecords({ query: 'redis' });
|
|
45
|
+
expect(records).toHaveLength(1);
|
|
46
|
+
|
|
47
|
+
rmSync(dbPath, { force: true });
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { rmSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import type { DecisionContext, DecisionRecord } from '@learningnodes/elen-core';
|
|
6
|
+
import { InMemoryStorage, SQLiteStorage } from '../src/storage';
|
|
7
|
+
|
|
8
|
+
function fixtures(): { context: DecisionContext; record: DecisionRecord } {
|
|
9
|
+
const decisionId = 'dec-1';
|
|
10
|
+
const context: DecisionContext = {
|
|
11
|
+
decision_id: decisionId,
|
|
12
|
+
agent_id: 'agent-a',
|
|
13
|
+
question: 'Which DB?',
|
|
14
|
+
domain: 'infrastructure',
|
|
15
|
+
status: 'validated',
|
|
16
|
+
constraints: [
|
|
17
|
+
{
|
|
18
|
+
constraint_id: 'con-1',
|
|
19
|
+
decision_id: decisionId,
|
|
20
|
+
type: 'requirement',
|
|
21
|
+
description: 'Must scale',
|
|
22
|
+
locked: false
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
evidence: [
|
|
26
|
+
{
|
|
27
|
+
evidence_id: 'evd-1',
|
|
28
|
+
decision_id: decisionId,
|
|
29
|
+
type: 'benchmark',
|
|
30
|
+
claim: 'Postgres faster',
|
|
31
|
+
proof: 'benchmark 3200 TPS',
|
|
32
|
+
confidence: 0.9
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
checks: [
|
|
36
|
+
{
|
|
37
|
+
check_id: 'chk-1',
|
|
38
|
+
decision_id: decisionId,
|
|
39
|
+
claim: 'Postgres faster',
|
|
40
|
+
result: 'pass',
|
|
41
|
+
evidence_ids: ['evd-1'],
|
|
42
|
+
epistemic_type: 'empirical',
|
|
43
|
+
confidence: 0.9
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
created_at: new Date().toISOString(),
|
|
47
|
+
parent_prompt: 'Build auth system'
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const record: DecisionRecord = {
|
|
51
|
+
record_id: 'rec-1',
|
|
52
|
+
decision_id: decisionId,
|
|
53
|
+
agent_id: 'agent-a',
|
|
54
|
+
question: 'Which DB?',
|
|
55
|
+
answer: 'PostgreSQL',
|
|
56
|
+
constraints_snapshot: context.constraints,
|
|
57
|
+
evidence_snapshot: context.evidence,
|
|
58
|
+
checks_snapshot: context.checks,
|
|
59
|
+
confidence: 0.9,
|
|
60
|
+
validation_type: 'self',
|
|
61
|
+
domain: 'infrastructure',
|
|
62
|
+
tags: ['database'],
|
|
63
|
+
published_at: new Date().toISOString(),
|
|
64
|
+
expires_at: null
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return { context, record };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
describe('Storage adapters', () => {
|
|
71
|
+
it('InMemoryStorage supports CRUD/search/profile', async () => {
|
|
72
|
+
const storage = new InMemoryStorage();
|
|
73
|
+
const { context, record } = fixtures();
|
|
74
|
+
|
|
75
|
+
await storage.saveDecision(context);
|
|
76
|
+
await storage.saveRecord(record);
|
|
77
|
+
|
|
78
|
+
expect(await storage.getRecord('rec-1')).not.toBeNull();
|
|
79
|
+
expect(await storage.searchRecords({ domain: 'infrastructure' })).toHaveLength(1);
|
|
80
|
+
expect(await storage.searchRecords({ parentPrompt: 'auth' })).toHaveLength(1);
|
|
81
|
+
expect((await storage.getCompetencyProfile('agent-a')).strengths).toContain('infrastructure');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('SQLiteStorage supports CRUD/search/profile', async () => {
|
|
85
|
+
const dbPath = join(tmpdir(), `elen-sdk-${Date.now()}.db`);
|
|
86
|
+
const storage = new SQLiteStorage(dbPath);
|
|
87
|
+
const { context, record } = fixtures();
|
|
88
|
+
|
|
89
|
+
await storage.saveDecision(context);
|
|
90
|
+
await storage.saveRecord(record);
|
|
91
|
+
|
|
92
|
+
expect(await storage.getRecord('rec-1')).not.toBeNull();
|
|
93
|
+
expect(await storage.searchRecords({ domain: 'infrastructure' })).toHaveLength(1);
|
|
94
|
+
expect(await storage.searchRecords({ minConfidence: 0.8 })).toHaveLength(1);
|
|
95
|
+
expect(await storage.searchRecords({ parentPrompt: 'auth system' })).toHaveLength(1);
|
|
96
|
+
expect((await storage.getCompetencyProfile('agent-a')).domains).toContain('infrastructure');
|
|
97
|
+
|
|
98
|
+
rmSync(dbPath, { force: true });
|
|
99
|
+
});
|
|
100
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"moduleResolution": "Node",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"outDir": "dist",
|
|
8
|
+
"rootDir": "src",
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"baseUrl": "."
|
|
14
|
+
},
|
|
15
|
+
"include": ["src"]
|
|
16
|
+
}
|