agentopology 0.2.4 → 0.3.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 +92 -10
- package/dist/bindings/__tests__/bindings.test.js +2 -2
- package/dist/bindings/__tests__/claude-code-hybrid.test.d.ts +2 -0
- package/dist/bindings/__tests__/claude-code-hybrid.test.d.ts.map +1 -0
- package/dist/bindings/__tests__/claude-code-hybrid.test.js +152 -0
- package/dist/bindings/__tests__/claude-code-hybrid.test.js.map +1 -0
- package/dist/bindings/__tests__/claude-workflow.test.d.ts +2 -0
- package/dist/bindings/__tests__/claude-workflow.test.d.ts.map +1 -0
- package/dist/bindings/__tests__/claude-workflow.test.js +204 -0
- package/dist/bindings/__tests__/claude-workflow.test.js.map +1 -0
- package/dist/bindings/__tests__/hybrid-e2e.test.d.ts +15 -0
- package/dist/bindings/__tests__/hybrid-e2e.test.d.ts.map +1 -0
- package/dist/bindings/__tests__/hybrid-e2e.test.js +94 -0
- package/dist/bindings/__tests__/hybrid-e2e.test.js.map +1 -0
- package/dist/bindings/claude-code.d.ts.map +1 -1
- package/dist/bindings/claude-code.js +407 -3
- package/dist/bindings/claude-code.js.map +1 -1
- package/dist/bindings/claude-workflow.d.ts +28 -0
- package/dist/bindings/claude-workflow.d.ts.map +1 -0
- package/dist/bindings/claude-workflow.js +684 -0
- package/dist/bindings/claude-workflow.js.map +1 -0
- package/dist/bindings/index.d.ts +1 -0
- package/dist/bindings/index.d.ts.map +1 -1
- package/dist/bindings/index.js +3 -0
- package/dist/bindings/index.js.map +1 -1
- package/dist/bindings/lib/seam.d.ts +35 -0
- package/dist/bindings/lib/seam.d.ts.map +1 -0
- package/dist/bindings/lib/seam.js +42 -0
- package/dist/bindings/lib/seam.js.map +1 -0
- package/dist/cli/index.js +195 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/parser/__tests__/parser.test.js +170 -0
- package/dist/parser/__tests__/parser.test.js.map +1 -1
- package/dist/parser/ast.d.ts +39 -0
- package/dist/parser/ast.d.ts.map +1 -1
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +58 -2
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/validator.d.ts.map +1 -1
- package/dist/parser/validator.js +66 -3
- package/dist/parser/validator.js.map +1 -1
- package/dist/visualizer/__tests__/brain.test.d.ts +2 -0
- package/dist/visualizer/__tests__/brain.test.d.ts.map +1 -0
- package/dist/visualizer/__tests__/brain.test.js +138 -0
- package/dist/visualizer/__tests__/brain.test.js.map +1 -0
- package/dist/visualizer/__tests__/topology-brain-link.test.d.ts +2 -0
- package/dist/visualizer/__tests__/topology-brain-link.test.d.ts.map +1 -0
- package/dist/visualizer/__tests__/topology-brain-link.test.js +41 -0
- package/dist/visualizer/__tests__/topology-brain-link.test.js.map +1 -0
- package/dist/visualizer/brain.d.ts +97 -0
- package/dist/visualizer/brain.d.ts.map +1 -0
- package/dist/visualizer/brain.js +473 -0
- package/dist/visualizer/brain.js.map +1 -0
- package/dist/visualizer/index.d.ts +19 -1
- package/dist/visualizer/index.d.ts.map +1 -1
- package/dist/visualizer/index.js +26 -11
- package/dist/visualizer/index.js.map +1 -1
- package/examples/company-brain-team.at +241 -0
- package/examples/company-brain.at +104 -0
- package/examples/logos/gmail.svg +1 -0
- package/examples/logos/slack.svg +1 -0
- package/examples/matchmat-ship.at +249 -0
- package/package.json +1 -1
- package/spec/grammar.md +42 -3
|
@@ -7059,4 +7059,174 @@ describe("Auth block in providers (F42)", () => {
|
|
|
7059
7059
|
});
|
|
7060
7060
|
});
|
|
7061
7061
|
});
|
|
7062
|
+
describe("Company brain — pattern, brain store type, custody primitive", () => {
|
|
7063
|
+
const brainSrc = `topology cb : [brain] {
|
|
7064
|
+
meta { version: "1.0.0" description: "x" }
|
|
7065
|
+
memory {
|
|
7066
|
+
store brain {
|
|
7067
|
+
type: brain
|
|
7068
|
+
description: "the company brain"
|
|
7069
|
+
path: "brain/"
|
|
7070
|
+
format: obsidian
|
|
7071
|
+
}
|
|
7072
|
+
}
|
|
7073
|
+
agent librarian {
|
|
7074
|
+
model: sonnet
|
|
7075
|
+
description: "keeps the brain"
|
|
7076
|
+
tools: [Read, Write, Grep]
|
|
7077
|
+
custodian-of: [brain] {
|
|
7078
|
+
does: [link, tag, index, dedupe]
|
|
7079
|
+
}
|
|
7080
|
+
}
|
|
7081
|
+
agent researcher {
|
|
7082
|
+
model: sonnet
|
|
7083
|
+
description: "reads the brain"
|
|
7084
|
+
tools: [Read, Grep]
|
|
7085
|
+
memory: [brain]
|
|
7086
|
+
}
|
|
7087
|
+
action intake {
|
|
7088
|
+
kind: inline
|
|
7089
|
+
description: "in"
|
|
7090
|
+
}
|
|
7091
|
+
flow {
|
|
7092
|
+
intake -> librarian
|
|
7093
|
+
librarian -> researcher
|
|
7094
|
+
}
|
|
7095
|
+
}`;
|
|
7096
|
+
it("parses a brain-type store with files backend default and format", () => {
|
|
7097
|
+
const ast = parse(brainSrc);
|
|
7098
|
+
const store = (ast.stores ?? []).find((s) => s.id === "brain");
|
|
7099
|
+
expect(store).toBeDefined();
|
|
7100
|
+
expect(store.type).toBe("brain");
|
|
7101
|
+
expect(store.backend).toBe("files"); // file-native default, not lancedb
|
|
7102
|
+
expect(store.format).toBe("obsidian");
|
|
7103
|
+
expect(store.path).toBe("brain/");
|
|
7104
|
+
});
|
|
7105
|
+
it("parses custodian-of and the optional does verbs on an agent", () => {
|
|
7106
|
+
const ast = parse(brainSrc);
|
|
7107
|
+
const librarian = ast.nodes.find((n) => n.id === "librarian");
|
|
7108
|
+
expect(librarian.custodianOf).toEqual(["brain"]);
|
|
7109
|
+
expect(librarian.custodianDoes).toEqual(["link", "tag", "index", "dedupe"]);
|
|
7110
|
+
});
|
|
7111
|
+
it("custody is optional — bare custodian-of with no verbs parses", () => {
|
|
7112
|
+
const src = brainSrc.replace("custodian-of: [brain] {\n does: [link, tag, index, dedupe]\n }", "custodian-of: [brain]");
|
|
7113
|
+
const ast = parse(src);
|
|
7114
|
+
const librarian = ast.nodes.find((n) => n.id === "librarian");
|
|
7115
|
+
expect(librarian.custodianOf).toEqual(["brain"]);
|
|
7116
|
+
expect(librarian.custodianDoes).toBeUndefined();
|
|
7117
|
+
});
|
|
7118
|
+
it("the brain pattern tag is recognized (no V2 reserved-keyword error)", () => {
|
|
7119
|
+
const ast = parse(brainSrc);
|
|
7120
|
+
expect(ast.topology.patterns).toContain("brain");
|
|
7121
|
+
const results = validate(ast);
|
|
7122
|
+
expect(results.filter((r) => r.level === "error")).toHaveLength(0);
|
|
7123
|
+
});
|
|
7124
|
+
it("V81: a brain store needs no DB backend (exempt from backend enum)", () => {
|
|
7125
|
+
const ast = parse(brainSrc);
|
|
7126
|
+
const results = validate(ast);
|
|
7127
|
+
expect(results.filter((r) => r.rule === "V81")).toHaveLength(0);
|
|
7128
|
+
});
|
|
7129
|
+
it("V88: custodian-of referencing an undeclared store is an error", () => {
|
|
7130
|
+
const ast = minimalASTForWave6({
|
|
7131
|
+
nodes: [
|
|
7132
|
+
{ id: "orchestrator", type: "orchestrator", label: "O", model: "opus", handles: ["intake"] },
|
|
7133
|
+
{ id: "intake", type: "action", label: "Intake" },
|
|
7134
|
+
{ id: "keeper", type: "agent", label: "Keeper", model: "sonnet", custodianOf: ["ghost-store"] },
|
|
7135
|
+
],
|
|
7136
|
+
edges: [{ from: "intake", to: "keeper", condition: null, maxIterations: null }],
|
|
7137
|
+
stores: [{ id: "brain", type: "brain", backend: "files" }],
|
|
7138
|
+
retrievals: [],
|
|
7139
|
+
});
|
|
7140
|
+
const v88 = validate(ast).filter((r) => r.rule === "V88" && r.level === "error");
|
|
7141
|
+
expect(v88).toHaveLength(1);
|
|
7142
|
+
expect(v88[0].message).toContain("ghost-store");
|
|
7143
|
+
});
|
|
7144
|
+
it("V88: custody over a declared brain store is clean", () => {
|
|
7145
|
+
const ast = minimalASTForWave6({
|
|
7146
|
+
nodes: [
|
|
7147
|
+
{ id: "orchestrator", type: "orchestrator", label: "O", model: "opus", handles: ["intake"] },
|
|
7148
|
+
{ id: "intake", type: "action", label: "Intake" },
|
|
7149
|
+
{ id: "keeper", type: "agent", label: "Keeper", model: "sonnet", custodianOf: ["brain"] },
|
|
7150
|
+
],
|
|
7151
|
+
edges: [{ from: "intake", to: "keeper", condition: null, maxIterations: null }],
|
|
7152
|
+
stores: [{ id: "brain", type: "brain", backend: "files" }],
|
|
7153
|
+
retrievals: [],
|
|
7154
|
+
});
|
|
7155
|
+
const v88 = validate(ast).filter((r) => r.rule === "V88");
|
|
7156
|
+
expect(v88).toHaveLength(0);
|
|
7157
|
+
});
|
|
7158
|
+
it("V88: custody over a non-brain store is a warning, not an error", () => {
|
|
7159
|
+
const ast = minimalASTForWave6({
|
|
7160
|
+
nodes: [
|
|
7161
|
+
{ id: "orchestrator", type: "orchestrator", label: "O", model: "opus", handles: ["intake"] },
|
|
7162
|
+
{ id: "intake", type: "action", label: "Intake" },
|
|
7163
|
+
{ id: "keeper", type: "agent", label: "Keeper", model: "sonnet", custodianOf: ["kg"] },
|
|
7164
|
+
],
|
|
7165
|
+
edges: [{ from: "intake", to: "keeper", condition: null, maxIterations: null }],
|
|
7166
|
+
stores: [{ id: "kg", type: "graph", backend: "kuzu" }],
|
|
7167
|
+
retrievals: [],
|
|
7168
|
+
});
|
|
7169
|
+
const v88 = validate(ast).filter((r) => r.rule === "V88");
|
|
7170
|
+
expect(v88).toHaveLength(1);
|
|
7171
|
+
expect(v88[0].level).toBe("warning");
|
|
7172
|
+
});
|
|
7173
|
+
it("parses a brain store's presentation-only `sources` block", () => {
|
|
7174
|
+
const src = `topology cb : [brain] {
|
|
7175
|
+
meta { version: "1.0.0" description: "x" }
|
|
7176
|
+
memory {
|
|
7177
|
+
store brain {
|
|
7178
|
+
type: brain
|
|
7179
|
+
path: "brain/"
|
|
7180
|
+
sources {
|
|
7181
|
+
gmail {
|
|
7182
|
+
color: "#EA4335"
|
|
7183
|
+
icon: "./logos/gmail.svg"
|
|
7184
|
+
}
|
|
7185
|
+
slack {
|
|
7186
|
+
color: "#4A154B"
|
|
7187
|
+
}
|
|
7188
|
+
}
|
|
7189
|
+
}
|
|
7190
|
+
}
|
|
7191
|
+
agent lib { model: sonnet description: "k" tools: [Read, Write] custodian-of: [brain] }
|
|
7192
|
+
action intake {
|
|
7193
|
+
kind: inline
|
|
7194
|
+
description: "in"
|
|
7195
|
+
}
|
|
7196
|
+
flow { intake -> lib }
|
|
7197
|
+
}`;
|
|
7198
|
+
const ast = parse(src);
|
|
7199
|
+
const store = (ast.stores ?? []).find((s) => s.id === "brain");
|
|
7200
|
+
expect(store?.sources).toEqual({
|
|
7201
|
+
gmail: { color: "#EA4335", icon: "./logos/gmail.svg" },
|
|
7202
|
+
slack: { color: "#4A154B" },
|
|
7203
|
+
});
|
|
7204
|
+
// It is presentation-only — purely data on the AST, no validation error.
|
|
7205
|
+
expect(validate(ast).filter((r) => r.level === "error")).toHaveLength(0);
|
|
7206
|
+
});
|
|
7207
|
+
it("round-trips the company-brain.at example with no validation errors", () => {
|
|
7208
|
+
const src = readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), "../../../examples/company-brain.at"), "utf8");
|
|
7209
|
+
const ast = parse(src);
|
|
7210
|
+
const errors = validate(ast).filter((r) => r.level === "error");
|
|
7211
|
+
expect(errors).toHaveLength(0);
|
|
7212
|
+
});
|
|
7213
|
+
it("round-trips the team-of-N company-brain-team.at example cleanly", () => {
|
|
7214
|
+
const src = readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), "../../../examples/company-brain-team.at"), "utf8");
|
|
7215
|
+
const ast = parse(src);
|
|
7216
|
+
const errors = validate(ast).filter((r) => r.level === "error");
|
|
7217
|
+
expect(errors).toHaveLength(0);
|
|
7218
|
+
});
|
|
7219
|
+
it("team example: two distinct custodians of the same brain, with different verbs", () => {
|
|
7220
|
+
const src = readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), "../../../examples/company-brain-team.at"), "utf8");
|
|
7221
|
+
const ast = parse(src);
|
|
7222
|
+
const librarian = ast.nodes.find((n) => n.id === "librarian");
|
|
7223
|
+
const auditor = ast.nodes.find((n) => n.id === "auditor");
|
|
7224
|
+
// Both own the same brain store — custody is not exclusive.
|
|
7225
|
+
expect(librarian.custodianOf).toEqual(["brain"]);
|
|
7226
|
+
expect(auditor.custodianOf).toEqual(["brain"]);
|
|
7227
|
+
// But they perform different maintenance verbs (different roles, same layer).
|
|
7228
|
+
expect(librarian.custodianDoes).toEqual(["link", "tag", "index", "dedupe"]);
|
|
7229
|
+
expect(auditor.custodianDoes).toEqual(["heal", "dedupe", "index"]);
|
|
7230
|
+
});
|
|
7231
|
+
});
|
|
7062
7232
|
//# sourceMappingURL=parser.test.js.map
|