agentopology 0.1.1 → 0.2.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/README.md +8 -6
- package/dist/analyzer/index.d.ts +1 -0
- package/dist/analyzer/index.d.ts.map +1 -1
- package/dist/analyzer/index.js +35 -0
- package/dist/analyzer/index.js.map +1 -1
- package/dist/bindings/__tests__/bindings.test.js +11 -11
- package/dist/bindings/__tests__/bindings.test.js.map +1 -1
- package/dist/bindings/claude-code.d.ts.map +1 -1
- package/dist/bindings/claude-code.js +339 -85
- package/dist/bindings/claude-code.js.map +1 -1
- package/dist/bindings/openclaw.d.ts.map +1 -1
- package/dist/bindings/openclaw.js +367 -5
- package/dist/bindings/openclaw.js.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/docs/__tests__/docs.test.js +2 -1
- package/dist/docs/__tests__/docs.test.js.map +1 -1
- package/dist/docs/content.d.ts.map +1 -1
- package/dist/docs/content.js +730 -4
- package/dist/docs/content.js.map +1 -1
- package/dist/exporters/markdown.d.ts.map +1 -1
- package/dist/exporters/markdown.js +165 -0
- package/dist/exporters/markdown.js.map +1 -1
- package/dist/exporters/mermaid.d.ts.map +1 -1
- package/dist/exporters/mermaid.js +30 -0
- package/dist/exporters/mermaid.js.map +1 -1
- package/dist/import/__tests__/import.test.js +556 -2
- package/dist/import/__tests__/import.test.js.map +1 -1
- package/dist/import/claude-code.d.ts.map +1 -1
- package/dist/import/claude-code.js +2 -0
- package/dist/import/claude-code.js.map +1 -1
- package/dist/import/index.d.ts +1 -0
- package/dist/import/index.d.ts.map +1 -1
- package/dist/import/index.js +7 -1
- package/dist/import/index.js.map +1 -1
- package/dist/import/openclaw.d.ts +70 -0
- package/dist/import/openclaw.d.ts.map +1 -0
- package/dist/import/openclaw.js +1060 -0
- package/dist/import/openclaw.js.map +1 -0
- package/dist/import/serializer.d.ts.map +1 -1
- package/dist/import/serializer.js +171 -4
- package/dist/import/serializer.js.map +1 -1
- package/dist/parser/__tests__/parser.test.js +463 -0
- package/dist/parser/__tests__/parser.test.js.map +1 -1
- package/dist/parser/ast.d.ts +122 -0
- package/dist/parser/ast.d.ts.map +1 -1
- package/dist/parser/index.d.ts +14 -2
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +226 -5
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/validator.d.ts +1 -1
- package/dist/parser/validator.d.ts.map +1 -1
- package/dist/parser/validator.js +214 -1
- package/dist/parser/validator.js.map +1 -1
- package/dist/visualizer/index.d.ts.map +1 -1
- package/dist/visualizer/index.js +104 -16
- package/dist/visualizer/index.js.map +1 -1
- package/examples/memory-system.at +162 -0
- package/examples/script-agent-pipeline.at +65 -0
- package/package.json +2 -1
- package/skill/SKILL.md +7 -7
- package/spec/grammar.md +345 -10
- package/spec/reserved-keywords.md +25 -1
- package/spec/validation.md +171 -2
|
@@ -739,6 +739,8 @@ describe("Validator", () => {
|
|
|
739
739
|
includes: [],
|
|
740
740
|
checkpoint: null,
|
|
741
741
|
artifacts: [],
|
|
742
|
+
stores: [],
|
|
743
|
+
retrievals: [],
|
|
742
744
|
...overrides,
|
|
743
745
|
};
|
|
744
746
|
}
|
|
@@ -2358,6 +2360,8 @@ describe("Error Handling (timeout, on-fail, retry block)", () => {
|
|
|
2358
2360
|
includes: [],
|
|
2359
2361
|
checkpoint: null,
|
|
2360
2362
|
artifacts: [],
|
|
2363
|
+
stores: [],
|
|
2364
|
+
retrievals: [],
|
|
2361
2365
|
...overrides,
|
|
2362
2366
|
};
|
|
2363
2367
|
}
|
|
@@ -3127,6 +3131,8 @@ describe("Wave 2: Validator rules V39-V45", () => {
|
|
|
3127
3131
|
includes: [],
|
|
3128
3132
|
checkpoint: null,
|
|
3129
3133
|
artifacts: [],
|
|
3134
|
+
stores: [],
|
|
3135
|
+
retrievals: [],
|
|
3130
3136
|
...overrides,
|
|
3131
3137
|
};
|
|
3132
3138
|
}
|
|
@@ -3645,6 +3651,8 @@ topology test : [pipeline] {
|
|
|
3645
3651
|
includes: [],
|
|
3646
3652
|
checkpoint: null,
|
|
3647
3653
|
artifacts: [],
|
|
3654
|
+
stores: [],
|
|
3655
|
+
retrievals: [],
|
|
3648
3656
|
...overrides,
|
|
3649
3657
|
};
|
|
3650
3658
|
}
|
|
@@ -3721,6 +3729,8 @@ topology test : [pipeline] {
|
|
|
3721
3729
|
includes: [],
|
|
3722
3730
|
checkpoint: null,
|
|
3723
3731
|
artifacts: [],
|
|
3732
|
+
stores: [],
|
|
3733
|
+
retrievals: [],
|
|
3724
3734
|
...overrides,
|
|
3725
3735
|
};
|
|
3726
3736
|
}
|
|
@@ -4145,6 +4155,8 @@ describe("Wave 3: Validator rules V48-V50 (observability)", () => {
|
|
|
4145
4155
|
includes: [],
|
|
4146
4156
|
checkpoint: null,
|
|
4147
4157
|
artifacts: [],
|
|
4158
|
+
stores: [],
|
|
4159
|
+
retrievals: [],
|
|
4148
4160
|
...overrides,
|
|
4149
4161
|
};
|
|
4150
4162
|
}
|
|
@@ -4606,6 +4618,8 @@ topology simple : [pipeline] {
|
|
|
4606
4618
|
includes: [],
|
|
4607
4619
|
checkpoint: null,
|
|
4608
4620
|
artifacts: [],
|
|
4621
|
+
stores: [],
|
|
4622
|
+
retrievals: [],
|
|
4609
4623
|
...overrides,
|
|
4610
4624
|
};
|
|
4611
4625
|
}
|
|
@@ -4912,6 +4926,8 @@ describe("Circuit Breaker (F26)", () => {
|
|
|
4912
4926
|
includes: [],
|
|
4913
4927
|
checkpoint: null,
|
|
4914
4928
|
artifacts: [],
|
|
4929
|
+
stores: [],
|
|
4930
|
+
retrievals: [],
|
|
4915
4931
|
...overrides,
|
|
4916
4932
|
};
|
|
4917
4933
|
}
|
|
@@ -5323,6 +5339,8 @@ function minimalASTForWave6(overrides = {}) {
|
|
|
5323
5339
|
includes: [],
|
|
5324
5340
|
checkpoint: null,
|
|
5325
5341
|
artifacts: [],
|
|
5342
|
+
stores: [],
|
|
5343
|
+
retrievals: [],
|
|
5326
5344
|
...overrides,
|
|
5327
5345
|
};
|
|
5328
5346
|
}
|
|
@@ -6510,5 +6528,450 @@ describe("Auth block in providers (F42)", () => {
|
|
|
6510
6528
|
const v80 = results.filter((r) => r.rule === "V80");
|
|
6511
6529
|
expect(v80.length).toBe(0);
|
|
6512
6530
|
});
|
|
6531
|
+
// =========================================================================
|
|
6532
|
+
// Store and retrieval blocks (parser tests)
|
|
6533
|
+
// =========================================================================
|
|
6534
|
+
describe("store and retrieval blocks", () => {
|
|
6535
|
+
it("parses a basic store with type, backend, and path", () => {
|
|
6536
|
+
const src = `topology t : [pipeline] {\n meta { version: "1.0.0" }\n orchestrator { model: opus handles: [a] }\n action a { kind: inline }\n flow { a -> a }\n memory {\n store my-store {\n type: semantic\n backend: lancedb\n path: ".memory/"\n }\n }\n}`;
|
|
6537
|
+
const ast = parse(src);
|
|
6538
|
+
expect(ast.stores).toHaveLength(1);
|
|
6539
|
+
expect(ast.stores[0].id).toBe("my-store");
|
|
6540
|
+
expect(ast.stores[0].type).toBe("semantic");
|
|
6541
|
+
expect(ast.stores[0].backend).toBe("lancedb");
|
|
6542
|
+
expect(ast.stores[0].path).toBe(".memory/");
|
|
6543
|
+
});
|
|
6544
|
+
it("parses multiple stores in one memory block", () => {
|
|
6545
|
+
const src = `topology t : [pipeline] {\n meta { version: "1.0.0" }\n orchestrator { model: opus handles: [a] }\n action a { kind: inline }\n flow { a -> a }\n memory {\n store kb {\n type: semantic\n backend: lancedb\n }\n store relations {\n type: graph\n backend: kuzu\n }\n store history {\n type: episodic\n backend: sqlite-vec\n }\n }\n}`;
|
|
6546
|
+
const ast = parse(src);
|
|
6547
|
+
expect(ast.stores).toHaveLength(3);
|
|
6548
|
+
expect(ast.stores[0].id).toBe("kb");
|
|
6549
|
+
expect(ast.stores[0].type).toBe("semantic");
|
|
6550
|
+
expect(ast.stores[0].backend).toBe("lancedb");
|
|
6551
|
+
expect(ast.stores[1].id).toBe("relations");
|
|
6552
|
+
expect(ast.stores[1].type).toBe("graph");
|
|
6553
|
+
expect(ast.stores[1].backend).toBe("kuzu");
|
|
6554
|
+
expect(ast.stores[2].id).toBe("history");
|
|
6555
|
+
expect(ast.stores[2].type).toBe("episodic");
|
|
6556
|
+
expect(ast.stores[2].backend).toBe("sqlite-vec");
|
|
6557
|
+
});
|
|
6558
|
+
it("parses store with all sub-blocks", () => {
|
|
6559
|
+
const src = [
|
|
6560
|
+
"topology t : [pipeline] {",
|
|
6561
|
+
" meta { version: \"1.0.0\" }",
|
|
6562
|
+
" orchestrator { model: opus handles: [a] }",
|
|
6563
|
+
" action a { kind: inline }",
|
|
6564
|
+
" flow { a -> a }",
|
|
6565
|
+
" memory {",
|
|
6566
|
+
" store full-store {",
|
|
6567
|
+
" type: semantic",
|
|
6568
|
+
" backend: lancedb",
|
|
6569
|
+
" path: \".memory/full\"",
|
|
6570
|
+
" scope: agent",
|
|
6571
|
+
" embedding {",
|
|
6572
|
+
" provider: ollama",
|
|
6573
|
+
" model: nomic-embed-text",
|
|
6574
|
+
" dimensions: 1024",
|
|
6575
|
+
" }",
|
|
6576
|
+
" index {",
|
|
6577
|
+
" collection: \"full_collection\"",
|
|
6578
|
+
" metric: cosine",
|
|
6579
|
+
" }",
|
|
6580
|
+
" ingestion {",
|
|
6581
|
+
" chunking: recursive",
|
|
6582
|
+
" chunk-size: 512",
|
|
6583
|
+
" overlap: 50",
|
|
6584
|
+
" }",
|
|
6585
|
+
" search {",
|
|
6586
|
+
" strategy: hybrid",
|
|
6587
|
+
" rerank: true",
|
|
6588
|
+
" top-k: 10",
|
|
6589
|
+
" }",
|
|
6590
|
+
" lifecycle {",
|
|
6591
|
+
" retention: 90d",
|
|
6592
|
+
" decay-half-life: 30d",
|
|
6593
|
+
" consolidation: 0.8",
|
|
6594
|
+
" contradiction: overwrite",
|
|
6595
|
+
" audit-log: true",
|
|
6596
|
+
" }",
|
|
6597
|
+
" backend-config {",
|
|
6598
|
+
" region: \"us-east-1\"",
|
|
6599
|
+
" replicas: 3",
|
|
6600
|
+
" }",
|
|
6601
|
+
" }",
|
|
6602
|
+
" }",
|
|
6603
|
+
"}",
|
|
6604
|
+
].join("\n");
|
|
6605
|
+
const ast = parse(src);
|
|
6606
|
+
expect(ast.stores).toHaveLength(1);
|
|
6607
|
+
const store = ast.stores[0];
|
|
6608
|
+
expect(store.id).toBe("full-store");
|
|
6609
|
+
expect(store.type).toBe("semantic");
|
|
6610
|
+
expect(store.backend).toBe("lancedb");
|
|
6611
|
+
expect(store.path).toBe(".memory/full");
|
|
6612
|
+
expect(store.scope).toBe("agent");
|
|
6613
|
+
// embedding
|
|
6614
|
+
expect(store.embedding).toBeDefined();
|
|
6615
|
+
expect(store.embedding.provider).toBe("ollama");
|
|
6616
|
+
expect(store.embedding.model).toBe("nomic-embed-text");
|
|
6617
|
+
expect(store.embedding.dimensions).toBe(1024);
|
|
6618
|
+
// index
|
|
6619
|
+
expect(store.index).toBeDefined();
|
|
6620
|
+
expect(store.index.collection).toBe("full_collection");
|
|
6621
|
+
expect(store.index.metric).toBe("cosine");
|
|
6622
|
+
// ingestion
|
|
6623
|
+
expect(store.ingestion).toBeDefined();
|
|
6624
|
+
expect(store.ingestion.chunking).toBe("recursive");
|
|
6625
|
+
expect(store.ingestion.chunkSize).toBe(512);
|
|
6626
|
+
expect(store.ingestion.overlap).toBe(50);
|
|
6627
|
+
// search
|
|
6628
|
+
expect(store.search).toBeDefined();
|
|
6629
|
+
expect(store.search.strategy).toBe("hybrid");
|
|
6630
|
+
expect(store.search.rerank).toBe(true);
|
|
6631
|
+
expect(store.search.topK).toBe(10);
|
|
6632
|
+
// lifecycle
|
|
6633
|
+
expect(store.lifecycle).toBeDefined();
|
|
6634
|
+
expect(store.lifecycle.retention).toBe("90d");
|
|
6635
|
+
expect(store.lifecycle.decayHalfLife).toBe("30d");
|
|
6636
|
+
expect(store.lifecycle.consolidation).toBe(0.8);
|
|
6637
|
+
expect(store.lifecycle.contradiction).toBe("overwrite");
|
|
6638
|
+
expect(store.lifecycle.auditLog).toBe(true);
|
|
6639
|
+
// backend-config
|
|
6640
|
+
expect(store.backendConfig).toBeDefined();
|
|
6641
|
+
expect(store.backendConfig["region"]).toBe("us-east-1");
|
|
6642
|
+
expect(store.backendConfig["replicas"]).toBe(3);
|
|
6643
|
+
});
|
|
6644
|
+
it("parses store with connection secret", () => {
|
|
6645
|
+
const src = `topology t : [pipeline] {\n meta { version: "1.0.0" }\n orchestrator { model: opus handles: [a] }\n action a { kind: inline }\n flow { a -> a }\n memory {\n store remote-db {\n type: semantic\n backend: pinecone\n connection: secret "DB_URL"\n }\n }\n}`;
|
|
6646
|
+
const ast = parse(src);
|
|
6647
|
+
expect(ast.stores).toHaveLength(1);
|
|
6648
|
+
expect(ast.stores[0].connection).toBe("DB_URL");
|
|
6649
|
+
});
|
|
6650
|
+
it("parses retrieval block with all fields", () => {
|
|
6651
|
+
const src = [
|
|
6652
|
+
"topology t : [pipeline] {",
|
|
6653
|
+
" meta { version: \"1.0.0\" }",
|
|
6654
|
+
" orchestrator { model: opus handles: [a] }",
|
|
6655
|
+
" action a { kind: inline }",
|
|
6656
|
+
" flow { a -> a }",
|
|
6657
|
+
" memory {",
|
|
6658
|
+
" store kb { type: semantic backend: lancedb }",
|
|
6659
|
+
" store history { type: episodic backend: sqlite-vec }",
|
|
6660
|
+
" retrieval planner {",
|
|
6661
|
+
" sources: [kb, history]",
|
|
6662
|
+
" budget: 4096",
|
|
6663
|
+
" paths: [semantic, graph]",
|
|
6664
|
+
" rerank: true",
|
|
6665
|
+
" diversity: true",
|
|
6666
|
+
" cache-hit-threshold: 0.92",
|
|
6667
|
+
" cache-hit-action: short-circuit",
|
|
6668
|
+
" }",
|
|
6669
|
+
" }",
|
|
6670
|
+
"}",
|
|
6671
|
+
].join("\n");
|
|
6672
|
+
const ast = parse(src);
|
|
6673
|
+
expect(ast.retrievals).toHaveLength(1);
|
|
6674
|
+
const r = ast.retrievals[0];
|
|
6675
|
+
expect(r.id).toBe("planner");
|
|
6676
|
+
expect(r.sources).toEqual(["kb", "history"]);
|
|
6677
|
+
expect(r.budget).toBe(4096);
|
|
6678
|
+
expect(r.paths).toEqual(["semantic", "graph"]);
|
|
6679
|
+
expect(r.rerank).toBe(true);
|
|
6680
|
+
expect(r.diversity).toBe(true);
|
|
6681
|
+
expect(r.cacheHitThreshold).toBe(0.92);
|
|
6682
|
+
expect(r.cacheHitAction).toBe("short-circuit");
|
|
6683
|
+
});
|
|
6684
|
+
it("parses retrieval with scoring sub-block", () => {
|
|
6685
|
+
const src = [
|
|
6686
|
+
"topology t : [pipeline] {",
|
|
6687
|
+
" meta { version: \"1.0.0\" }",
|
|
6688
|
+
" orchestrator { model: opus handles: [a] }",
|
|
6689
|
+
" action a { kind: inline }",
|
|
6690
|
+
" flow { a -> a }",
|
|
6691
|
+
" memory {",
|
|
6692
|
+
" retrieval scored {",
|
|
6693
|
+
" sources: [kb]",
|
|
6694
|
+
" scoring {",
|
|
6695
|
+
" recency-weight: 0.3",
|
|
6696
|
+
" semantic-weight: 0.5",
|
|
6697
|
+
" importance-weight: 0.2",
|
|
6698
|
+
" }",
|
|
6699
|
+
" }",
|
|
6700
|
+
" }",
|
|
6701
|
+
"}",
|
|
6702
|
+
].join("\n");
|
|
6703
|
+
const ast = parse(src);
|
|
6704
|
+
expect(ast.retrievals).toHaveLength(1);
|
|
6705
|
+
const r = ast.retrievals[0];
|
|
6706
|
+
expect(r.scoring).toBeDefined();
|
|
6707
|
+
expect(r.scoring.recencyWeight).toBe(0.3);
|
|
6708
|
+
expect(r.scoring.semanticWeight).toBe(0.5);
|
|
6709
|
+
expect(r.scoring.importanceWeight).toBe(0.2);
|
|
6710
|
+
});
|
|
6711
|
+
it("parses agent with memory and retrieval fields", () => {
|
|
6712
|
+
const src = [
|
|
6713
|
+
"topology t : [pipeline] {",
|
|
6714
|
+
" meta { version: \"1.0.0\" }",
|
|
6715
|
+
" orchestrator { model: opus handles: [intake] }",
|
|
6716
|
+
" action intake { kind: inline }",
|
|
6717
|
+
" agent worker {",
|
|
6718
|
+
" model: sonnet",
|
|
6719
|
+
" memory: [kb, history]",
|
|
6720
|
+
" retrieval: planner",
|
|
6721
|
+
" }",
|
|
6722
|
+
" flow { intake -> worker }",
|
|
6723
|
+
" memory {",
|
|
6724
|
+
" store kb { type: semantic backend: lancedb }",
|
|
6725
|
+
" store history { type: episodic backend: sqlite-vec }",
|
|
6726
|
+
" retrieval planner { sources: [kb, history] }",
|
|
6727
|
+
" }",
|
|
6728
|
+
"}",
|
|
6729
|
+
].join("\n");
|
|
6730
|
+
const ast = parse(src);
|
|
6731
|
+
const agent = ast.nodes.find((n) => n.id === "worker");
|
|
6732
|
+
expect(agent.memory).toEqual(["kb", "history"]);
|
|
6733
|
+
expect(agent.retrieval).toBe("planner");
|
|
6734
|
+
});
|
|
6735
|
+
it("parses empty memory block with no stores", () => {
|
|
6736
|
+
const src = `topology t : [pipeline] {\n meta { version: "1.0.0" }\n orchestrator { model: opus handles: [a] }\n action a { kind: inline }\n flow { a -> a }\n memory {}\n}`;
|
|
6737
|
+
const ast = parse(src);
|
|
6738
|
+
expect(ast.stores).toEqual([]);
|
|
6739
|
+
expect(ast.retrievals).toEqual([]);
|
|
6740
|
+
});
|
|
6741
|
+
it("parses store alongside existing memory sub-blocks (workspace, domains)", () => {
|
|
6742
|
+
const src = [
|
|
6743
|
+
"topology t : [pipeline] {",
|
|
6744
|
+
" meta { version: \"1.0.0\" }",
|
|
6745
|
+
" orchestrator { model: opus handles: [a] }",
|
|
6746
|
+
" action a { kind: inline }",
|
|
6747
|
+
" flow { a -> a }",
|
|
6748
|
+
" memory {",
|
|
6749
|
+
" workspace {",
|
|
6750
|
+
" path: \".state\"",
|
|
6751
|
+
" }",
|
|
6752
|
+
" domains {",
|
|
6753
|
+
" primary: \"engineering\"",
|
|
6754
|
+
" }",
|
|
6755
|
+
" store kb {",
|
|
6756
|
+
" type: semantic",
|
|
6757
|
+
" backend: lancedb",
|
|
6758
|
+
" }",
|
|
6759
|
+
" }",
|
|
6760
|
+
"}",
|
|
6761
|
+
].join("\n");
|
|
6762
|
+
const ast = parse(src);
|
|
6763
|
+
// Old-style memory sub-blocks still populated
|
|
6764
|
+
const ws = ast.memory["workspace"];
|
|
6765
|
+
expect(ws).toBeDefined();
|
|
6766
|
+
expect(ws["path"]).toBe(".state");
|
|
6767
|
+
const domains = ast.memory["domains"];
|
|
6768
|
+
expect(domains).toBeDefined();
|
|
6769
|
+
expect(domains["primary"]).toBe("engineering");
|
|
6770
|
+
// New store also populated
|
|
6771
|
+
expect(ast.stores).toHaveLength(1);
|
|
6772
|
+
expect(ast.stores[0].id).toBe("kb");
|
|
6773
|
+
});
|
|
6774
|
+
it("does not produce V24 warning for store/retrieval inside memory", () => {
|
|
6775
|
+
const src = [
|
|
6776
|
+
"topology t : [pipeline] {",
|
|
6777
|
+
" meta { version: \"1.0.0\" }",
|
|
6778
|
+
" orchestrator { model: opus handles: [a] }",
|
|
6779
|
+
" action a { kind: inline }",
|
|
6780
|
+
" flow { a -> a }",
|
|
6781
|
+
" memory {",
|
|
6782
|
+
" store kb {",
|
|
6783
|
+
" type: semantic",
|
|
6784
|
+
" backend: lancedb",
|
|
6785
|
+
" }",
|
|
6786
|
+
" retrieval planner {",
|
|
6787
|
+
" sources: [kb]",
|
|
6788
|
+
" }",
|
|
6789
|
+
" }",
|
|
6790
|
+
"}",
|
|
6791
|
+
].join("\n");
|
|
6792
|
+
const ast = parse(src);
|
|
6793
|
+
const results = validate(ast);
|
|
6794
|
+
const v24 = results.filter((r) => r.rule === "V24");
|
|
6795
|
+
expect(v24).toHaveLength(0);
|
|
6796
|
+
});
|
|
6797
|
+
});
|
|
6798
|
+
// =========================================================================
|
|
6799
|
+
// V81-V86 memory store validation
|
|
6800
|
+
// =========================================================================
|
|
6801
|
+
describe("V81-V86 memory store validation", () => {
|
|
6802
|
+
it("V81: invalid store backend produces error", () => {
|
|
6803
|
+
const ast = minimalASTForWave6({
|
|
6804
|
+
stores: [
|
|
6805
|
+
{ id: "bad-store", type: "semantic", backend: "invalid-db" },
|
|
6806
|
+
],
|
|
6807
|
+
});
|
|
6808
|
+
const results = validate(ast);
|
|
6809
|
+
const v81 = results.filter((r) => r.rule === "V81");
|
|
6810
|
+
expect(v81.length).toBeGreaterThan(0);
|
|
6811
|
+
expect(v81[0].level).toBe("error");
|
|
6812
|
+
expect(v81[0].message).toContain("invalid-db");
|
|
6813
|
+
});
|
|
6814
|
+
it("V81: valid store backend produces no error", () => {
|
|
6815
|
+
const ast = minimalASTForWave6({
|
|
6816
|
+
stores: [
|
|
6817
|
+
{ id: "good-store", type: "semantic", backend: "lancedb" },
|
|
6818
|
+
],
|
|
6819
|
+
});
|
|
6820
|
+
const results = validate(ast);
|
|
6821
|
+
const v81 = results.filter((r) => r.rule === "V81");
|
|
6822
|
+
expect(v81).toHaveLength(0);
|
|
6823
|
+
});
|
|
6824
|
+
it("V82: semantic store without embedding produces warning", () => {
|
|
6825
|
+
const ast = minimalASTForWave6({
|
|
6826
|
+
stores: [
|
|
6827
|
+
{ id: "kb", type: "semantic", backend: "lancedb" },
|
|
6828
|
+
],
|
|
6829
|
+
});
|
|
6830
|
+
const results = validate(ast);
|
|
6831
|
+
const v82 = results.filter((r) => r.rule === "V82");
|
|
6832
|
+
expect(v82.length).toBeGreaterThan(0);
|
|
6833
|
+
expect(v82[0].level).toBe("warning");
|
|
6834
|
+
expect(v82[0].message).toContain("embedding");
|
|
6835
|
+
});
|
|
6836
|
+
it("V82: semantic store with embedding produces no warning", () => {
|
|
6837
|
+
const ast = minimalASTForWave6({
|
|
6838
|
+
stores: [
|
|
6839
|
+
{ id: "kb", type: "semantic", backend: "lancedb", embedding: { provider: "ollama", model: "nomic", dimensions: 768 } },
|
|
6840
|
+
],
|
|
6841
|
+
});
|
|
6842
|
+
const results = validate(ast);
|
|
6843
|
+
const v82 = results.filter((r) => r.rule === "V82");
|
|
6844
|
+
expect(v82).toHaveLength(0);
|
|
6845
|
+
});
|
|
6846
|
+
it("V83: store without scope produces warning", () => {
|
|
6847
|
+
const ast = minimalASTForWave6({
|
|
6848
|
+
stores: [
|
|
6849
|
+
{ id: "kb", type: "semantic", backend: "lancedb" },
|
|
6850
|
+
],
|
|
6851
|
+
});
|
|
6852
|
+
const results = validate(ast);
|
|
6853
|
+
const v83 = results.filter((r) => r.rule === "V83");
|
|
6854
|
+
expect(v83.length).toBeGreaterThan(0);
|
|
6855
|
+
expect(v83[0].level).toBe("warning");
|
|
6856
|
+
expect(v83[0].message).toContain("scope");
|
|
6857
|
+
});
|
|
6858
|
+
it("V84: retrieval with nonexistent source produces error", () => {
|
|
6859
|
+
const ast = minimalASTForWave6({
|
|
6860
|
+
stores: [
|
|
6861
|
+
{ id: "kb", type: "semantic", backend: "lancedb" },
|
|
6862
|
+
],
|
|
6863
|
+
retrievals: [
|
|
6864
|
+
{ id: "planner", sources: ["kb", "nonexistent"] },
|
|
6865
|
+
],
|
|
6866
|
+
});
|
|
6867
|
+
const results = validate(ast);
|
|
6868
|
+
const v84 = results.filter((r) => r.rule === "V84");
|
|
6869
|
+
expect(v84.length).toBeGreaterThan(0);
|
|
6870
|
+
expect(v84[0].level).toBe("error");
|
|
6871
|
+
expect(v84[0].message).toContain("nonexistent");
|
|
6872
|
+
});
|
|
6873
|
+
it("V84: retrieval with valid sources produces no error", () => {
|
|
6874
|
+
const ast = minimalASTForWave6({
|
|
6875
|
+
stores: [
|
|
6876
|
+
{ id: "kb", type: "semantic", backend: "lancedb" },
|
|
6877
|
+
{ id: "history", type: "episodic", backend: "sqlite-vec" },
|
|
6878
|
+
],
|
|
6879
|
+
retrievals: [
|
|
6880
|
+
{ id: "planner", sources: ["kb", "history"] },
|
|
6881
|
+
],
|
|
6882
|
+
});
|
|
6883
|
+
const results = validate(ast);
|
|
6884
|
+
const v84 = results.filter((r) => r.rule === "V84");
|
|
6885
|
+
expect(v84).toHaveLength(0);
|
|
6886
|
+
});
|
|
6887
|
+
it("V85: remote backend without connection produces error", () => {
|
|
6888
|
+
const ast = minimalASTForWave6({
|
|
6889
|
+
stores: [
|
|
6890
|
+
{ id: "cloud-store", type: "semantic", backend: "pinecone" },
|
|
6891
|
+
],
|
|
6892
|
+
});
|
|
6893
|
+
const results = validate(ast);
|
|
6894
|
+
const v85 = results.filter((r) => r.rule === "V85");
|
|
6895
|
+
expect(v85.length).toBeGreaterThan(0);
|
|
6896
|
+
expect(v85[0].level).toBe("error");
|
|
6897
|
+
expect(v85[0].message).toContain("pinecone");
|
|
6898
|
+
expect(v85[0].message).toContain("connection");
|
|
6899
|
+
});
|
|
6900
|
+
it("V85: local backend without connection produces no error", () => {
|
|
6901
|
+
const ast = minimalASTForWave6({
|
|
6902
|
+
stores: [
|
|
6903
|
+
{ id: "local-store", type: "semantic", backend: "lancedb" },
|
|
6904
|
+
],
|
|
6905
|
+
});
|
|
6906
|
+
const results = validate(ast);
|
|
6907
|
+
const v85 = results.filter((r) => r.rule === "V85");
|
|
6908
|
+
expect(v85).toHaveLength(0);
|
|
6909
|
+
});
|
|
6910
|
+
it("V86: agent memory referencing nonexistent store produces error", () => {
|
|
6911
|
+
const ast = minimalASTForWave6({
|
|
6912
|
+
stores: [
|
|
6913
|
+
{ id: "kb", type: "semantic", backend: "lancedb" },
|
|
6914
|
+
],
|
|
6915
|
+
retrievals: [],
|
|
6916
|
+
nodes: [
|
|
6917
|
+
{ id: "orchestrator", type: "orchestrator", label: "O", model: "opus", handles: ["intake"] },
|
|
6918
|
+
{ id: "intake", type: "action", label: "Intake" },
|
|
6919
|
+
{ id: "worker", type: "agent", label: "Worker", model: "sonnet", memory: ["nonexistent"] },
|
|
6920
|
+
],
|
|
6921
|
+
});
|
|
6922
|
+
const results = validate(ast);
|
|
6923
|
+
const v86 = results.filter((r) => r.rule === "V86");
|
|
6924
|
+
expect(v86.length).toBeGreaterThan(0);
|
|
6925
|
+
expect(v86[0].level).toBe("error");
|
|
6926
|
+
expect(v86[0].message).toContain("nonexistent");
|
|
6927
|
+
});
|
|
6928
|
+
it("V86: agent memory referencing existing store produces no error", () => {
|
|
6929
|
+
const ast = minimalASTForWave6({
|
|
6930
|
+
stores: [
|
|
6931
|
+
{ id: "kb", type: "semantic", backend: "lancedb" },
|
|
6932
|
+
],
|
|
6933
|
+
retrievals: [],
|
|
6934
|
+
nodes: [
|
|
6935
|
+
{ id: "orchestrator", type: "orchestrator", label: "O", model: "opus", handles: ["intake"] },
|
|
6936
|
+
{ id: "intake", type: "action", label: "Intake" },
|
|
6937
|
+
{ id: "worker", type: "agent", label: "Worker", model: "sonnet", memory: ["kb"] },
|
|
6938
|
+
],
|
|
6939
|
+
});
|
|
6940
|
+
const results = validate(ast);
|
|
6941
|
+
const v86 = results.filter((r) => r.rule === "V86");
|
|
6942
|
+
expect(v86).toHaveLength(0);
|
|
6943
|
+
});
|
|
6944
|
+
it("V86: agent retrieval referencing nonexistent strategy produces error", () => {
|
|
6945
|
+
const ast = minimalASTForWave6({
|
|
6946
|
+
stores: [
|
|
6947
|
+
{ id: "kb", type: "semantic", backend: "lancedb" },
|
|
6948
|
+
],
|
|
6949
|
+
retrievals: [
|
|
6950
|
+
{ id: "planner", sources: ["kb"] },
|
|
6951
|
+
],
|
|
6952
|
+
nodes: [
|
|
6953
|
+
{ id: "orchestrator", type: "orchestrator", label: "O", model: "opus", handles: ["intake"] },
|
|
6954
|
+
{ id: "intake", type: "action", label: "Intake" },
|
|
6955
|
+
{ id: "worker", type: "agent", label: "Worker", model: "sonnet", retrieval: "nonexistent" },
|
|
6956
|
+
],
|
|
6957
|
+
});
|
|
6958
|
+
const results = validate(ast);
|
|
6959
|
+
const v86 = results.filter((r) => r.rule === "V86");
|
|
6960
|
+
expect(v86.length).toBeGreaterThan(0);
|
|
6961
|
+
expect(v86[0].level).toBe("error");
|
|
6962
|
+
expect(v86[0].message).toContain("nonexistent");
|
|
6963
|
+
});
|
|
6964
|
+
it("V81: duckdb backend produces no error", () => {
|
|
6965
|
+
const ast = minimalASTForWave6({
|
|
6966
|
+
stores: [
|
|
6967
|
+
{ id: "duck-store", type: "entity", backend: "duckdb" },
|
|
6968
|
+
],
|
|
6969
|
+
retrievals: [],
|
|
6970
|
+
});
|
|
6971
|
+
const results = validate(ast);
|
|
6972
|
+
const v81 = results.filter((r) => r.rule === "V81");
|
|
6973
|
+
expect(v81).toHaveLength(0);
|
|
6974
|
+
});
|
|
6975
|
+
});
|
|
6513
6976
|
});
|
|
6514
6977
|
//# sourceMappingURL=parser.test.js.map
|