@jayjiang/byoao 0.2.3 → 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/dist/__tests__/plugin-config.test.js +130 -0
- package/dist/__tests__/plugin-config.test.js.map +1 -0
- package/dist/cli/cli-program.js +60 -10
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/installer.js +39 -30
- package/dist/cli/installer.js.map +1 -1
- package/dist/cli/ui.js +23 -0
- package/dist/cli/ui.js.map +1 -1
- package/dist/hooks/__tests__/idle-suggestions.test.js +15 -0
- package/dist/hooks/__tests__/idle-suggestions.test.js.map +1 -0
- package/dist/plugin-config.js +9 -0
- package/dist/plugin-config.js.map +1 -1
- package/dist/tools/init-vault.js +38 -0
- package/dist/tools/init-vault.js.map +1 -1
- package/dist/vault/__tests__/create.test.js +125 -0
- package/dist/vault/__tests__/create.test.js.map +1 -0
- package/dist/vault/__tests__/doctor.test.js +88 -0
- package/dist/vault/__tests__/doctor.test.js.map +1 -0
- package/dist/vault/__tests__/glossary.test.js +57 -0
- package/dist/vault/__tests__/glossary.test.js.map +1 -0
- package/dist/vault/__tests__/mcp.test.js +88 -0
- package/dist/vault/__tests__/mcp.test.js.map +1 -0
- package/dist/vault/__tests__/member.test.js +87 -0
- package/dist/vault/__tests__/member.test.js.map +1 -0
- package/dist/vault/__tests__/obsidian-plugins.test.js +366 -0
- package/dist/vault/__tests__/obsidian-plugins.test.js.map +1 -0
- package/dist/vault/__tests__/status.test.js +134 -0
- package/dist/vault/__tests__/status.test.js.map +1 -0
- package/dist/vault/__tests__/template.test.js +33 -0
- package/dist/vault/__tests__/template.test.js.map +1 -0
- package/dist/vault/create.js +121 -18
- package/dist/vault/create.js.map +1 -1
- package/dist/vault/mcp.js +54 -0
- package/dist/vault/mcp.js.map +1 -0
- package/dist/vault/obsidian-plugins.js +209 -0
- package/dist/vault/obsidian-plugins.js.map +1 -0
- package/package.json +7 -2
- package/src/assets/presets/pm-tpm/preset.json +25 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-vault.js","sourceRoot":"","sources":["../../src/tools/init-vault.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"init-vault.js","sourceRoot":"","sources":["../../src/tools/init-vault.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { createVault } from "../create.js";
|
|
6
|
+
// Mock mcp.ts so we don't touch real OpenCode config
|
|
7
|
+
vi.mock("../mcp.js", () => ({
|
|
8
|
+
configureMcp: vi.fn().mockResolvedValue(null),
|
|
9
|
+
}));
|
|
10
|
+
vi.mock("../obsidian-plugins.js", () => ({
|
|
11
|
+
configureObsidianPlugins: vi.fn().mockResolvedValue(null),
|
|
12
|
+
}));
|
|
13
|
+
let tmpDir;
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "byoao-create-"));
|
|
16
|
+
});
|
|
17
|
+
afterEach(async () => {
|
|
18
|
+
await fs.remove(tmpDir);
|
|
19
|
+
});
|
|
20
|
+
function makeConfig(overrides = {}) {
|
|
21
|
+
return {
|
|
22
|
+
teamName: "TestTeam",
|
|
23
|
+
vaultPath: path.join(tmpDir, "vault"),
|
|
24
|
+
members: [],
|
|
25
|
+
projects: [],
|
|
26
|
+
glossaryEntries: [],
|
|
27
|
+
jiraHost: "",
|
|
28
|
+
jiraProject: "",
|
|
29
|
+
preset: "pm-tpm",
|
|
30
|
+
...overrides,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
describe("createVault", () => {
|
|
34
|
+
it("creates expected directory structure", async () => {
|
|
35
|
+
const result = await createVault(makeConfig());
|
|
36
|
+
expect(result.directories).toContain("Inbox");
|
|
37
|
+
expect(result.directories).toContain("Knowledge");
|
|
38
|
+
expect(result.directories).toContain("People");
|
|
39
|
+
expect(result.directories).toContain("Projects");
|
|
40
|
+
expect(result.directories).toContain("Sprints");
|
|
41
|
+
for (const dir of result.directories) {
|
|
42
|
+
expect(await fs.pathExists(path.join(result.vaultPath, dir))).toBe(true);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
it("generates AGENT.md and CLAUDE.md", async () => {
|
|
46
|
+
const result = await createVault(makeConfig());
|
|
47
|
+
const vp = result.vaultPath;
|
|
48
|
+
expect(await fs.pathExists(path.join(vp, "AGENT.md"))).toBe(true);
|
|
49
|
+
expect(await fs.pathExists(path.join(vp, "CLAUDE.md"))).toBe(true);
|
|
50
|
+
const agentContent = await fs.readFile(path.join(vp, "AGENT.md"), "utf-8");
|
|
51
|
+
expect(agentContent).toContain("TestTeam");
|
|
52
|
+
});
|
|
53
|
+
it("generates Start Here.md and Glossary.md", async () => {
|
|
54
|
+
const result = await createVault(makeConfig());
|
|
55
|
+
const vp = result.vaultPath;
|
|
56
|
+
expect(await fs.pathExists(path.join(vp, "Start Here.md"))).toBe(true);
|
|
57
|
+
expect(await fs.pathExists(path.join(vp, "Knowledge/Glossary.md"))).toBe(true);
|
|
58
|
+
const startHere = await fs.readFile(path.join(vp, "Start Here.md"), "utf-8");
|
|
59
|
+
expect(startHere).toContain("TestTeam");
|
|
60
|
+
});
|
|
61
|
+
it("creates people notes from members config", async () => {
|
|
62
|
+
const config = makeConfig({
|
|
63
|
+
members: [
|
|
64
|
+
{ name: "Alice", role: "Engineer" },
|
|
65
|
+
{ name: "Bob", role: "PM" },
|
|
66
|
+
],
|
|
67
|
+
});
|
|
68
|
+
const result = await createVault(config);
|
|
69
|
+
const vp = result.vaultPath;
|
|
70
|
+
const alice = await fs.readFile(path.join(vp, "People/Alice.md"), "utf-8");
|
|
71
|
+
expect(alice).toContain('type: person');
|
|
72
|
+
expect(alice).toContain("Engineer");
|
|
73
|
+
expect(await fs.pathExists(path.join(vp, "People/Bob.md"))).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
it("creates project notes from projects config", async () => {
|
|
76
|
+
const config = makeConfig({
|
|
77
|
+
projects: [{ name: "Widget", description: "Build a widget" }],
|
|
78
|
+
});
|
|
79
|
+
const result = await createVault(config);
|
|
80
|
+
const vp = result.vaultPath;
|
|
81
|
+
const widget = await fs.readFile(path.join(vp, "Projects/Widget.md"), "utf-8");
|
|
82
|
+
expect(widget).toContain("type: feature");
|
|
83
|
+
expect(widget).toContain("Build a widget");
|
|
84
|
+
});
|
|
85
|
+
it("returns correct filesCreated count", async () => {
|
|
86
|
+
const config = makeConfig({
|
|
87
|
+
members: [{ name: "Alice", role: "Eng" }],
|
|
88
|
+
projects: [{ name: "P1", description: "desc" }],
|
|
89
|
+
});
|
|
90
|
+
const result = await createVault(config);
|
|
91
|
+
// At minimum: obsidian configs + templates + glossary + start here + agent + claude + 1 person + 1 project + team index
|
|
92
|
+
expect(result.filesCreated).toBeGreaterThanOrEqual(9);
|
|
93
|
+
});
|
|
94
|
+
it("tracks wikilinks created for members and projects", async () => {
|
|
95
|
+
const config = makeConfig({
|
|
96
|
+
members: [{ name: "Alice", role: "Eng" }],
|
|
97
|
+
projects: [{ name: "P1", description: "d" }],
|
|
98
|
+
});
|
|
99
|
+
const result = await createVault(config);
|
|
100
|
+
// members wikilinks in AGENT.md + team index, projects in AGENT.md + team index
|
|
101
|
+
expect(result.wikilinksCreated).toBeGreaterThanOrEqual(4);
|
|
102
|
+
});
|
|
103
|
+
it("populates wikilinks in team index", async () => {
|
|
104
|
+
const config = makeConfig({
|
|
105
|
+
members: [
|
|
106
|
+
{ name: "Alice", role: "Eng" },
|
|
107
|
+
{ name: "Bob", role: "PM" },
|
|
108
|
+
],
|
|
109
|
+
});
|
|
110
|
+
const result = await createVault(config);
|
|
111
|
+
const teamIndex = await fs.readFile(path.join(result.vaultPath, "People/TestTeam Team.md"), "utf-8");
|
|
112
|
+
expect(teamIndex).toContain("[[Alice]]");
|
|
113
|
+
expect(teamIndex).toContain("[[Bob]]");
|
|
114
|
+
});
|
|
115
|
+
it("includes glossary entries when provided", async () => {
|
|
116
|
+
const config = makeConfig({
|
|
117
|
+
glossaryEntries: [{ term: "API", definition: "Application interface" }],
|
|
118
|
+
});
|
|
119
|
+
const result = await createVault(config);
|
|
120
|
+
const glossary = await fs.readFile(path.join(result.vaultPath, "Knowledge/Glossary.md"), "utf-8");
|
|
121
|
+
expect(glossary).toContain("**API**");
|
|
122
|
+
expect(glossary).toContain("Application interface");
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
//# sourceMappingURL=create.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.test.js","sourceRoot":"","sources":["../../../src/vault/__tests__/create.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { getVaultDiagnosis } from "../doctor.js";
|
|
6
|
+
let tmpDir;
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "byoao-doctor-"));
|
|
9
|
+
});
|
|
10
|
+
afterEach(async () => {
|
|
11
|
+
await fs.remove(tmpDir);
|
|
12
|
+
});
|
|
13
|
+
function writeNote(name, content) {
|
|
14
|
+
return fs.writeFile(path.join(tmpDir, name), content);
|
|
15
|
+
}
|
|
16
|
+
function noteWithFrontmatter(fields, body = "") {
|
|
17
|
+
const yaml = Object.entries(fields)
|
|
18
|
+
.map(([k, v]) => {
|
|
19
|
+
if (Array.isArray(v))
|
|
20
|
+
return `${k}: [${v.join(", ")}]`;
|
|
21
|
+
return `${k}: ${v}`;
|
|
22
|
+
})
|
|
23
|
+
.join("\n");
|
|
24
|
+
return `---\n${yaml}\n---\n\n${body}`;
|
|
25
|
+
}
|
|
26
|
+
describe("getVaultDiagnosis", () => {
|
|
27
|
+
it("reports zero issues for a clean vault", async () => {
|
|
28
|
+
await writeNote("note.md", noteWithFrontmatter({ type: "reference", tags: ["test"] }, "See [[other]]\n"));
|
|
29
|
+
await writeNote("other.md", noteWithFrontmatter({ type: "reference", tags: ["test"] }, "Back to [[note]]\n"));
|
|
30
|
+
const report = await getVaultDiagnosis(tmpDir);
|
|
31
|
+
expect(report.issues).toHaveLength(0);
|
|
32
|
+
expect(report.summary.totalNotes).toBe(2);
|
|
33
|
+
expect(report.summary.healthyNotes).toBe(2);
|
|
34
|
+
});
|
|
35
|
+
it("reports missing frontmatter", async () => {
|
|
36
|
+
await writeNote("bare.md", "# No frontmatter\n\nJust text.");
|
|
37
|
+
const report = await getVaultDiagnosis(tmpDir);
|
|
38
|
+
const fmIssues = report.issues.filter((i) => i.category === "frontmatter");
|
|
39
|
+
expect(fmIssues.length).toBeGreaterThanOrEqual(1);
|
|
40
|
+
expect(fmIssues[0].message).toContain("Missing frontmatter");
|
|
41
|
+
});
|
|
42
|
+
it("reports missing type field", async () => {
|
|
43
|
+
await writeNote("no-type.md", noteWithFrontmatter({ tags: ["test"] }, "Content"));
|
|
44
|
+
const report = await getVaultDiagnosis(tmpDir);
|
|
45
|
+
const typeIssue = report.issues.find((i) => i.message.includes("Missing `type`"));
|
|
46
|
+
expect(typeIssue).toBeDefined();
|
|
47
|
+
expect(typeIssue.severity).toBe("warning");
|
|
48
|
+
});
|
|
49
|
+
it("reports missing tags field", async () => {
|
|
50
|
+
await writeNote("no-tags.md", noteWithFrontmatter({ type: "reference" }, "Content"));
|
|
51
|
+
const report = await getVaultDiagnosis(tmpDir);
|
|
52
|
+
const tagsIssue = report.issues.find((i) => i.message.includes("Missing `tags`"));
|
|
53
|
+
expect(tagsIssue).toBeDefined();
|
|
54
|
+
expect(tagsIssue.severity).toBe("info");
|
|
55
|
+
});
|
|
56
|
+
it("reports orphan notes", async () => {
|
|
57
|
+
await writeNote("orphan.md", noteWithFrontmatter({ type: "reference", tags: ["test"] }, "No links."));
|
|
58
|
+
const report = await getVaultDiagnosis(tmpDir);
|
|
59
|
+
const orphanIssues = report.issues.filter((i) => i.category === "orphan");
|
|
60
|
+
expect(orphanIssues).toHaveLength(1);
|
|
61
|
+
expect(orphanIssues[0].file).toBe("orphan.md");
|
|
62
|
+
});
|
|
63
|
+
it("reports broken wikilinks", async () => {
|
|
64
|
+
await writeNote("source.md", noteWithFrontmatter({ type: "reference", tags: ["test"] }, "Links to [[nonexistent]]"));
|
|
65
|
+
const report = await getVaultDiagnosis(tmpDir);
|
|
66
|
+
const brokenLinks = report.issues.filter((i) => i.category === "broken-link");
|
|
67
|
+
expect(brokenLinks).toHaveLength(1);
|
|
68
|
+
expect(brokenLinks[0].message).toContain("[[nonexistent]]");
|
|
69
|
+
});
|
|
70
|
+
it("reports AGENT.md drift", async () => {
|
|
71
|
+
await writeNote("AGENT.md", "Team: [[Alice]] and [[Bob]]");
|
|
72
|
+
await fs.ensureDir(path.join(tmpDir, "People"));
|
|
73
|
+
await writeNote("People/Alice.md", noteWithFrontmatter({ type: "person", tags: ["person"] }));
|
|
74
|
+
// Bob doesn't exist
|
|
75
|
+
const report = await getVaultDiagnosis(tmpDir);
|
|
76
|
+
const driftIssues = report.issues.filter((i) => i.category === "agent-drift");
|
|
77
|
+
expect(driftIssues).toHaveLength(1);
|
|
78
|
+
expect(driftIssues[0].message).toContain("[[Bob]]");
|
|
79
|
+
});
|
|
80
|
+
it("skips template files", async () => {
|
|
81
|
+
await fs.ensureDir(path.join(tmpDir, "Knowledge/templates"));
|
|
82
|
+
await fs.writeFile(path.join(tmpDir, "Knowledge/templates/Template.md"), "# No frontmatter template");
|
|
83
|
+
const report = await getVaultDiagnosis(tmpDir);
|
|
84
|
+
const templateIssues = report.issues.filter((i) => i.file?.startsWith("Knowledge/templates/"));
|
|
85
|
+
expect(templateIssues).toHaveLength(0);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=doctor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.test.js","sourceRoot":"","sources":["../../../src/vault/__tests__/doctor.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { addGlossaryTerm } from "../glossary.js";
|
|
6
|
+
let tmpDir;
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "byoao-glossary-"));
|
|
9
|
+
await fs.ensureDir(path.join(tmpDir, "Knowledge"));
|
|
10
|
+
});
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
await fs.remove(tmpDir);
|
|
13
|
+
});
|
|
14
|
+
const GLOSSARY_TEMPLATE = `---
|
|
15
|
+
title: "Test Glossary"
|
|
16
|
+
type: reference
|
|
17
|
+
tags: [glossary]
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Test Glossary
|
|
21
|
+
|
|
22
|
+
## Core Terms
|
|
23
|
+
|
|
24
|
+
| Term | Definition |
|
|
25
|
+
|------|-----------|
|
|
26
|
+
| **API** | Application programming interface |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## How to Add a New Term
|
|
31
|
+
|
|
32
|
+
Just add it.
|
|
33
|
+
`;
|
|
34
|
+
describe("addGlossaryTerm", () => {
|
|
35
|
+
it("appends term to existing Core Terms table", async () => {
|
|
36
|
+
await fs.writeFile(path.join(tmpDir, "Knowledge/Glossary.md"), GLOSSARY_TEMPLATE);
|
|
37
|
+
const result = await addGlossaryTerm({
|
|
38
|
+
vaultPath: tmpDir,
|
|
39
|
+
term: "SDK",
|
|
40
|
+
definition: "Software development kit",
|
|
41
|
+
});
|
|
42
|
+
expect(result.termAdded).toBe("SDK");
|
|
43
|
+
const content = await fs.readFile(path.join(tmpDir, "Knowledge/Glossary.md"), "utf-8");
|
|
44
|
+
expect(content).toContain("**SDK**");
|
|
45
|
+
expect(content).toContain("Software development kit");
|
|
46
|
+
// Original term still present
|
|
47
|
+
expect(content).toContain("**API**");
|
|
48
|
+
});
|
|
49
|
+
it("throws when Glossary.md does not exist", async () => {
|
|
50
|
+
await expect(addGlossaryTerm({
|
|
51
|
+
vaultPath: tmpDir,
|
|
52
|
+
term: "Test",
|
|
53
|
+
definition: "A test",
|
|
54
|
+
})).rejects.toThrow("Glossary not found");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=glossary.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary.test.js","sourceRoot":"","sources":["../../../src/vault/__tests__/glossary.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,IAAI,MAAc,CAAC;AAEnB,UAAU,CAAC,KAAK,IAAI,EAAE;IACpB,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACrE,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;CAmBzB,CAAC;AAEF,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAC1C,iBAAiB,CAClB,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC;YACnC,SAAS,EAAE,MAAM;YACjB,IAAI,EAAE,KAAK;YACX,UAAU,EAAE,0BAA0B;SACvC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAErC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAC1C,OAAO,CACR,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QACtD,8BAA8B;QAC9B,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,MAAM,CACV,eAAe,CAAC;YACd,SAAS,EAAE,MAAM;YACjB,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,QAAQ;SACrB,CAAC,CACH,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
let tmpDir;
|
|
6
|
+
let configPath;
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "byoao-mcp-"));
|
|
9
|
+
configPath = path.join(tmpDir, ".config/opencode/opencode.json");
|
|
10
|
+
await fs.ensureDir(path.dirname(configPath));
|
|
11
|
+
// Mock os.homedir() to point at our temp dir
|
|
12
|
+
vi.spyOn(os, "homedir").mockReturnValue(tmpDir);
|
|
13
|
+
});
|
|
14
|
+
afterEach(async () => {
|
|
15
|
+
vi.restoreAllMocks();
|
|
16
|
+
// Re-import to clear module cache with mocked homedir
|
|
17
|
+
vi.resetModules();
|
|
18
|
+
await fs.remove(tmpDir);
|
|
19
|
+
});
|
|
20
|
+
async function loadConfigureMcp() {
|
|
21
|
+
const mod = await import("../mcp.js");
|
|
22
|
+
return mod.configureMcp;
|
|
23
|
+
}
|
|
24
|
+
function makePreset(mcpServers = {}) {
|
|
25
|
+
return {
|
|
26
|
+
name: "test",
|
|
27
|
+
displayName: "Test",
|
|
28
|
+
description: "test preset",
|
|
29
|
+
directories: [],
|
|
30
|
+
agentDescription: "test",
|
|
31
|
+
frontmatterExtras: {},
|
|
32
|
+
templates: [],
|
|
33
|
+
mcpServers,
|
|
34
|
+
obsidianPlugins: {},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
describe("configureMcp", () => {
|
|
38
|
+
it("returns null when preset has no mcpServers", async () => {
|
|
39
|
+
const configureMcp = await loadConfigureMcp();
|
|
40
|
+
const result = await configureMcp(makePreset());
|
|
41
|
+
expect(result).toBeNull();
|
|
42
|
+
});
|
|
43
|
+
it("adds servers to empty config", async () => {
|
|
44
|
+
const configureMcp = await loadConfigureMcp();
|
|
45
|
+
const preset = makePreset({
|
|
46
|
+
atlassian: { type: "remote", url: "https://mcp.atlassian.com/v1/sse" },
|
|
47
|
+
});
|
|
48
|
+
const result = await configureMcp(preset);
|
|
49
|
+
expect(result).not.toBeNull();
|
|
50
|
+
expect(result.serversAdded).toContain("atlassian");
|
|
51
|
+
expect(result.serversSkipped).toHaveLength(0);
|
|
52
|
+
const written = await fs.readJson(configPath);
|
|
53
|
+
expect(written.mcp.atlassian.url).toBe("https://mcp.atlassian.com/v1/sse");
|
|
54
|
+
});
|
|
55
|
+
it("skips servers that already exist (idempotent)", async () => {
|
|
56
|
+
// Pre-populate config
|
|
57
|
+
await fs.writeJson(configPath, {
|
|
58
|
+
mcp: {
|
|
59
|
+
atlassian: { type: "remote", url: "https://existing.example.com" },
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
const configureMcp = await loadConfigureMcp();
|
|
63
|
+
const preset = makePreset({
|
|
64
|
+
atlassian: { type: "remote", url: "https://mcp.atlassian.com/v1/sse" },
|
|
65
|
+
});
|
|
66
|
+
const result = await configureMcp(preset);
|
|
67
|
+
expect(result.serversSkipped).toContain("atlassian");
|
|
68
|
+
expect(result.serversAdded).toHaveLength(0);
|
|
69
|
+
// Original URL preserved
|
|
70
|
+
const written = await fs.readJson(configPath);
|
|
71
|
+
expect(written.mcp.atlassian.url).toBe("https://existing.example.com");
|
|
72
|
+
});
|
|
73
|
+
it("preserves other config fields when writing", async () => {
|
|
74
|
+
await fs.writeJson(configPath, {
|
|
75
|
+
theme: "dark",
|
|
76
|
+
mcp: {},
|
|
77
|
+
});
|
|
78
|
+
const configureMcp = await loadConfigureMcp();
|
|
79
|
+
const preset = makePreset({
|
|
80
|
+
linear: { type: "remote", url: "https://mcp.linear.app" },
|
|
81
|
+
});
|
|
82
|
+
await configureMcp(preset);
|
|
83
|
+
const written = await fs.readJson(configPath);
|
|
84
|
+
expect(written.theme).toBe("dark");
|
|
85
|
+
expect(written.mcp.linear).toBeDefined();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=mcp.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.test.js","sourceRoot":"","sources":["../../../src/vault/__tests__/mcp.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { addMember } from "../member.js";
|
|
6
|
+
let tmpDir;
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "byoao-member-"));
|
|
9
|
+
await fs.ensureDir(path.join(tmpDir, "People"));
|
|
10
|
+
});
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
await fs.remove(tmpDir);
|
|
13
|
+
});
|
|
14
|
+
describe("addMember", () => {
|
|
15
|
+
it("creates person note with correct frontmatter", async () => {
|
|
16
|
+
const result = await addMember({
|
|
17
|
+
vaultPath: tmpDir,
|
|
18
|
+
name: "Alice",
|
|
19
|
+
role: "Engineer",
|
|
20
|
+
team: "Platform",
|
|
21
|
+
});
|
|
22
|
+
expect(result.filePath).toContain("People/Alice.md");
|
|
23
|
+
const content = await fs.readFile(path.join(tmpDir, "People/Alice.md"), "utf-8");
|
|
24
|
+
expect(content).toContain("type: person");
|
|
25
|
+
expect(content).toContain('team: "Platform"');
|
|
26
|
+
expect(content).toContain('role: "Engineer"');
|
|
27
|
+
expect(content).toContain("status: active");
|
|
28
|
+
});
|
|
29
|
+
it("updates team index table", async () => {
|
|
30
|
+
// Create a team index file
|
|
31
|
+
const teamIndexContent = `---
|
|
32
|
+
title: "Platform Team"
|
|
33
|
+
type: reference
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
# Platform Team
|
|
37
|
+
|
|
38
|
+
## Members
|
|
39
|
+
|
|
40
|
+
| Name | Role |
|
|
41
|
+
|------|------|
|
|
42
|
+
|
|
43
|
+
## Active Projects
|
|
44
|
+
`;
|
|
45
|
+
await fs.writeFile(path.join(tmpDir, "People/Platform Team.md"), teamIndexContent);
|
|
46
|
+
await addMember({
|
|
47
|
+
vaultPath: tmpDir,
|
|
48
|
+
name: "Bob",
|
|
49
|
+
role: "PM",
|
|
50
|
+
team: "Platform",
|
|
51
|
+
});
|
|
52
|
+
const updated = await fs.readFile(path.join(tmpDir, "People/Platform Team.md"), "utf-8");
|
|
53
|
+
expect(updated).toContain("[[Bob]]");
|
|
54
|
+
expect(updated).toContain("PM");
|
|
55
|
+
});
|
|
56
|
+
it("updates AGENT.md and CLAUDE.md wikilinks", async () => {
|
|
57
|
+
// Create AGENT.md and CLAUDE.md with placeholder
|
|
58
|
+
const agentContent = `# Agent
|
|
59
|
+
|
|
60
|
+
## Team
|
|
61
|
+
|
|
62
|
+
(No members added yet — create notes in People/)
|
|
63
|
+
`;
|
|
64
|
+
await fs.writeFile(path.join(tmpDir, "AGENT.md"), agentContent);
|
|
65
|
+
await fs.writeFile(path.join(tmpDir, "CLAUDE.md"), agentContent);
|
|
66
|
+
const result = await addMember({
|
|
67
|
+
vaultPath: tmpDir,
|
|
68
|
+
name: "Carol",
|
|
69
|
+
role: "Designer",
|
|
70
|
+
team: "Platform",
|
|
71
|
+
});
|
|
72
|
+
expect(result.wikilinksAdded).toBeGreaterThanOrEqual(2);
|
|
73
|
+
const agent = await fs.readFile(path.join(tmpDir, "AGENT.md"), "utf-8");
|
|
74
|
+
expect(agent).toContain("[[Carol]]");
|
|
75
|
+
expect(agent).not.toContain("No members added yet");
|
|
76
|
+
});
|
|
77
|
+
it("throws when person already exists", async () => {
|
|
78
|
+
await fs.writeFile(path.join(tmpDir, "People/Alice.md"), "# Alice");
|
|
79
|
+
await expect(addMember({
|
|
80
|
+
vaultPath: tmpDir,
|
|
81
|
+
name: "Alice",
|
|
82
|
+
role: "Eng",
|
|
83
|
+
team: "T",
|
|
84
|
+
})).rejects.toThrow("already exists");
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=member.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"member.test.js","sourceRoot":"","sources":["../../../src/vault/__tests__/member.test.ts"],"names":[],"mappings":"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"}
|