@jayjiang/byoao 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/dist/cli/cli-program.js +241 -0
- package/dist/cli/cli-program.js.map +1 -0
- package/dist/cli/installer.js +226 -0
- package/dist/cli/installer.js.map +1 -0
- package/dist/cli/ui.js +157 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/hooks/idle-suggestions.js +14 -0
- package/dist/hooks/idle-suggestions.js.map +1 -0
- package/dist/hooks/system-transform.js +34 -0
- package/dist/hooks/system-transform.js.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin-config.js +57 -0
- package/dist/plugin-config.js.map +1 -0
- package/dist/tools/add-glossary-term.js +19 -0
- package/dist/tools/add-glossary-term.js.map +1 -0
- package/dist/tools/add-member.js +21 -0
- package/dist/tools/add-member.js.map +1 -0
- package/dist/tools/add-project.js +24 -0
- package/dist/tools/add-project.js.map +1 -0
- package/dist/tools/init-vault.js +82 -0
- package/dist/tools/init-vault.js.map +1 -0
- package/dist/tools/vault-doctor.js +38 -0
- package/dist/tools/vault-doctor.js.map +1 -0
- package/dist/tools/vault-status.js +18 -0
- package/dist/tools/vault-status.js.map +1 -0
- package/dist/vault/create.js +230 -0
- package/dist/vault/create.js.map +1 -0
- package/dist/vault/doctor.js +148 -0
- package/dist/vault/doctor.js.map +1 -0
- package/dist/vault/glossary.js +33 -0
- package/dist/vault/glossary.js.map +1 -0
- package/dist/vault/member.js +67 -0
- package/dist/vault/member.js.map +1 -0
- package/dist/vault/obsidian-check.js +125 -0
- package/dist/vault/obsidian-check.js.map +1 -0
- package/dist/vault/obsidian-cli.js +47 -0
- package/dist/vault/obsidian-cli.js.map +1 -0
- package/dist/vault/opencode-check.js +65 -0
- package/dist/vault/opencode-check.js.map +1 -0
- package/dist/vault/preset.js +48 -0
- package/dist/vault/preset.js.map +1 -0
- package/dist/vault/project.js +68 -0
- package/dist/vault/project.js.map +1 -0
- package/dist/vault/status.js +135 -0
- package/dist/vault/status.js.map +1 -0
- package/dist/vault/template.js +14 -0
- package/dist/vault/template.js.map +1 -0
- package/package.json +58 -0
- package/src/assets/obsidian-skills/defuddle.md +41 -0
- package/src/assets/obsidian-skills/json-canvas.md +244 -0
- package/src/assets/obsidian-skills/obsidian-bases.md +497 -0
- package/src/assets/obsidian-skills/obsidian-cli.md +106 -0
- package/src/assets/obsidian-skills/obsidian-markdown.md +196 -0
- package/src/assets/presets/common/AGENT.md.hbs +29 -0
- package/src/assets/presets/common/Glossary.md.hbs +44 -0
- package/src/assets/presets/common/Start Here.md.hbs +95 -0
- package/src/assets/presets/common/obsidian/core-plugins.json +33 -0
- package/src/assets/presets/common/obsidian/daily-notes.json +5 -0
- package/src/assets/presets/common/obsidian/templates.json +3 -0
- package/src/assets/presets/common/templates/Daily Note.md +19 -0
- package/src/assets/presets/common/templates/Decision Record.md +32 -0
- package/src/assets/presets/common/templates/Investigation.md +34 -0
- package/src/assets/presets/common/templates/Meeting Notes.md +25 -0
- package/src/assets/presets/pm-tpm/agent-section.hbs +15 -0
- package/src/assets/presets/pm-tpm/preset.json +12 -0
- package/src/assets/presets/pm-tpm/templates/Feature Doc.md +45 -0
- package/src/assets/presets/pm-tpm/templates/Sprint Handoff.md +38 -0
- package/src/assets/web-clipper/confluence-page.json +63 -0
- package/src/assets/web-clipper/general-article.json +53 -0
- package/src/assets/web-clipper/jira-issue.json +68 -0
- package/src/assets/web-clipper/meeting-notes.json +53 -0
- package/src/skills/enrich-document.md +52 -0
- package/src/skills/init-knowledge-base.md +85 -0
- package/src/skills/system-explainer.md +58 -0
- package/src/skills/vault-doctor.md +73 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* Check if the `obsidian` CLI is available in PATH.
|
|
4
|
+
*/
|
|
5
|
+
export function isObsidianCliAvailable() {
|
|
6
|
+
try {
|
|
7
|
+
execFileSync("obsidian", ["--version"], { stdio: "pipe" });
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Execute an Obsidian CLI command and return the result.
|
|
16
|
+
* Uses execFileSync (array form) to avoid shell injection.
|
|
17
|
+
* @param args - Command arguments (e.g., ["orphans", "--vault", "MyVault"])
|
|
18
|
+
*/
|
|
19
|
+
export function execObsidianCmd(args) {
|
|
20
|
+
try {
|
|
21
|
+
const output = execFileSync("obsidian", args, {
|
|
22
|
+
stdio: "pipe",
|
|
23
|
+
encoding: "utf-8",
|
|
24
|
+
timeout: 10000,
|
|
25
|
+
});
|
|
26
|
+
return { success: true, output: output.trim() };
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
30
|
+
return { success: false, output: "", error: msg };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Execute an Obsidian CLI command and parse JSON output.
|
|
35
|
+
*/
|
|
36
|
+
export function execObsidianJson(args) {
|
|
37
|
+
const result = execObsidianCmd([...args, "format=json"]);
|
|
38
|
+
if (!result.success)
|
|
39
|
+
return null;
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(result.output);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=obsidian-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obsidian-cli.js","sourceRoot":"","sources":["../../src/vault/obsidian-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQlD;;GAEG;AACH,MAAM,UAAU,sBAAsB;IACpC,IAAI,CAAC;QACH,YAAY,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAc;IAC5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,EAAE,IAAI,EAAE;YAC5C,KAAK,EAAE,MAAM;YACb,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;IAClD,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACpD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAc,IAAc;IAC1D,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAM,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { platform } from "node:os";
|
|
3
|
+
export function checkOpenCode() {
|
|
4
|
+
const installCommands = getInstallCommands();
|
|
5
|
+
try {
|
|
6
|
+
const result = execSync("opencode version", {
|
|
7
|
+
timeout: 5000,
|
|
8
|
+
encoding: "utf-8",
|
|
9
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
10
|
+
}).trim();
|
|
11
|
+
return {
|
|
12
|
+
installed: true,
|
|
13
|
+
version: result || "unknown",
|
|
14
|
+
installCommands,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// Also try just checking if the binary exists
|
|
19
|
+
try {
|
|
20
|
+
execSync("which opencode", {
|
|
21
|
+
timeout: 3000,
|
|
22
|
+
encoding: "utf-8",
|
|
23
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
24
|
+
});
|
|
25
|
+
return { installed: true, version: "unknown", installCommands };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Not installed
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return { installed: false, version: null, installCommands };
|
|
32
|
+
}
|
|
33
|
+
function getInstallCommands() {
|
|
34
|
+
const os = platform();
|
|
35
|
+
const commands = [];
|
|
36
|
+
if (os === "darwin") {
|
|
37
|
+
commands.push({
|
|
38
|
+
label: "Homebrew",
|
|
39
|
+
command: "brew install opencode-ai/tap/opencode",
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
commands.push({
|
|
43
|
+
label: "curl (official installer)",
|
|
44
|
+
command: "curl -fsSL https://opencode.ai/install | bash",
|
|
45
|
+
});
|
|
46
|
+
commands.push({
|
|
47
|
+
label: "npm",
|
|
48
|
+
command: "npm install -g opencode-ai",
|
|
49
|
+
});
|
|
50
|
+
return commands;
|
|
51
|
+
}
|
|
52
|
+
export function formatOpenCodeStatus(status) {
|
|
53
|
+
if (status.installed) {
|
|
54
|
+
return `ā OpenCode is installed (${status.version})`;
|
|
55
|
+
}
|
|
56
|
+
const lines = [
|
|
57
|
+
"ā ļø OpenCode is NOT installed.",
|
|
58
|
+
" Available install methods:",
|
|
59
|
+
];
|
|
60
|
+
for (const cmd of status.installCommands) {
|
|
61
|
+
lines.push(` - ${cmd.label}: ${cmd.command}`);
|
|
62
|
+
}
|
|
63
|
+
return lines.join("\n");
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=opencode-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode-check.js","sourceRoot":"","sources":["../../src/vault/opencode-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQnC,MAAM,UAAU,aAAa;IAC3B,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,kBAAkB,EAAE;YAC1C,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEV,OAAO;YACL,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,MAAM,IAAI,SAAS;YAC5B,eAAe;SAChB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,8CAA8C;QAC9C,IAAI,CAAC;YACH,QAAQ,CAAC,gBAAgB,EAAE;gBACzB,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aAChC,CAAC,CAAC;YACH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;QAClE,CAAC;QAAC,MAAM,CAAC;YACP,gBAAgB;QAClB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AAC9D,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,MAAM,QAAQ,GAAyC,EAAE,CAAC;IAE1D,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;QACpB,QAAQ,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,UAAU;YACjB,OAAO,EAAE,uCAAuC;SACjD,CAAC,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC;QACZ,KAAK,EAAE,2BAA2B;QAClC,OAAO,EAAE,+CAA+C;KACzD,CAAC,CAAC;IAEH,QAAQ,CAAC,IAAI,CAAC;QACZ,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,4BAA4B;KACtC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAsB;IACzD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,OAAO,4BAA4B,MAAM,CAAC,OAAO,GAAG,CAAC;IACvD,CAAC;IAED,MAAM,KAAK,GAAG;QACZ,+BAA+B;QAC/B,+BAA+B;KAChC,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { PresetConfigSchema } from "../plugin-config.js";
|
|
4
|
+
function getPresetsDir() {
|
|
5
|
+
const srcPresets = path.resolve(import.meta.dirname, "..", "assets", "presets");
|
|
6
|
+
const distPresets = path.resolve(import.meta.dirname, "..", "..", "src", "assets", "presets");
|
|
7
|
+
if (fs.existsSync(srcPresets))
|
|
8
|
+
return srcPresets;
|
|
9
|
+
if (fs.existsSync(distPresets))
|
|
10
|
+
return distPresets;
|
|
11
|
+
throw new Error(`Cannot find presets directory. Looked in:\n ${srcPresets}\n ${distPresets}`);
|
|
12
|
+
}
|
|
13
|
+
export function listPresets() {
|
|
14
|
+
const presetsDir = getPresetsDir();
|
|
15
|
+
const entries = fs.readdirSync(presetsDir, { withFileTypes: true });
|
|
16
|
+
const presets = [];
|
|
17
|
+
for (const entry of entries) {
|
|
18
|
+
if (!entry.isDirectory() || entry.name === "common")
|
|
19
|
+
continue;
|
|
20
|
+
const configPath = path.join(presetsDir, entry.name, "preset.json");
|
|
21
|
+
if (!fs.existsSync(configPath))
|
|
22
|
+
continue;
|
|
23
|
+
const raw = fs.readJsonSync(configPath);
|
|
24
|
+
const parsed = PresetConfigSchema.parse(raw);
|
|
25
|
+
presets.push({
|
|
26
|
+
name: parsed.name,
|
|
27
|
+
displayName: parsed.displayName,
|
|
28
|
+
description: parsed.description,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return presets;
|
|
32
|
+
}
|
|
33
|
+
export function loadPreset(name) {
|
|
34
|
+
const presetsDir = getPresetsDir();
|
|
35
|
+
const presetDir = path.join(presetsDir, name);
|
|
36
|
+
const configPath = path.join(presetDir, "preset.json");
|
|
37
|
+
if (!fs.existsSync(configPath)) {
|
|
38
|
+
const available = listPresets().map((p) => p.name);
|
|
39
|
+
throw new Error(`Preset "${name}" not found. Available presets: ${available.join(", ")}`);
|
|
40
|
+
}
|
|
41
|
+
const raw = fs.readJsonSync(configPath);
|
|
42
|
+
const config = PresetConfigSchema.parse(raw);
|
|
43
|
+
return { config, presetsDir };
|
|
44
|
+
}
|
|
45
|
+
export function getCommonDir() {
|
|
46
|
+
return path.join(getPresetsDir(), "common");
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=preset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preset.js","sourceRoot":"","sources":["../../src/vault/preset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAqB,MAAM,qBAAqB,CAAC;AAE5E,SAAS,aAAa;IACpB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChF,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAC5D,CAAC;IACF,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IACjD,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,WAAW,CAAC;IACnD,MAAM,IAAI,KAAK,CACb,gDAAgD,UAAU,OAAO,WAAW,EAAE,CAC/E,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,MAAM,OAAO,GAAiE,EAAE,CAAC;IAEjF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QACpE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,SAAS;QACzC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IAIrC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAEvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,IAAI,KAAK,CACb,WAAW,IAAI,mCAAmC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzE,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { today } from "./template.js";
|
|
4
|
+
export async function addProject(input) {
|
|
5
|
+
const { vaultPath, name, description, team } = input;
|
|
6
|
+
let wikilinksAdded = 0;
|
|
7
|
+
// 1. Create project note
|
|
8
|
+
const projectPath = path.join(vaultPath, `10-Projects/${name}.md`);
|
|
9
|
+
if (await fs.pathExists(projectPath)) {
|
|
10
|
+
throw new Error(`Project note already exists: ${projectPath}`);
|
|
11
|
+
}
|
|
12
|
+
const content = `---
|
|
13
|
+
title: "${name}"
|
|
14
|
+
type: feature
|
|
15
|
+
status: active
|
|
16
|
+
date: ${today()}
|
|
17
|
+
team: "${team}"
|
|
18
|
+
jira: ""
|
|
19
|
+
stakeholders: []
|
|
20
|
+
priority: ""
|
|
21
|
+
tags: [project]
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# ${name}
|
|
25
|
+
|
|
26
|
+
${description}
|
|
27
|
+
`;
|
|
28
|
+
await fs.writeFile(projectPath, content);
|
|
29
|
+
// 2. Update team index if it exists
|
|
30
|
+
const peoplePath = path.join(vaultPath, "40-People");
|
|
31
|
+
if (await fs.pathExists(peoplePath)) {
|
|
32
|
+
const teamFiles = await fs.readdir(peoplePath);
|
|
33
|
+
const teamIndexFile = teamFiles.find((f) => f.endsWith("Team.md"));
|
|
34
|
+
if (teamIndexFile) {
|
|
35
|
+
const teamIndexPath = path.join(peoplePath, teamIndexFile);
|
|
36
|
+
let teamContent = await fs.readFile(teamIndexPath, "utf-8");
|
|
37
|
+
const projectLine = `- [[${name}]] ā ${description}`;
|
|
38
|
+
if (teamContent.includes("(No projects added yet)")) {
|
|
39
|
+
teamContent = teamContent.replace("(No projects added yet)", projectLine);
|
|
40
|
+
}
|
|
41
|
+
else if (teamContent.includes("## Active Projects")) {
|
|
42
|
+
// Append to the projects section
|
|
43
|
+
teamContent = teamContent.replace(/(## Active Projects\n\n)([\s\S]*?)(\n\n|$)/, `$1$2\n${projectLine}$3`);
|
|
44
|
+
}
|
|
45
|
+
wikilinksAdded++;
|
|
46
|
+
await fs.writeFile(teamIndexPath, teamContent);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// 3. Update AGENT.md wikilinks
|
|
50
|
+
for (const agentFile of ["AGENT.md", "CLAUDE.md"]) {
|
|
51
|
+
const agentPath = path.join(vaultPath, agentFile);
|
|
52
|
+
if (await fs.pathExists(agentPath)) {
|
|
53
|
+
let agentContent = await fs.readFile(agentPath, "utf-8");
|
|
54
|
+
const projectLine = `- [[${name}]] ā ${description}`;
|
|
55
|
+
if (agentContent.includes("(No projects added yet")) {
|
|
56
|
+
agentContent = agentContent.replace(/\(No projects added yet[^)]*\)/, projectLine);
|
|
57
|
+
wikilinksAdded++;
|
|
58
|
+
}
|
|
59
|
+
else if (agentContent.includes("## Active Projects")) {
|
|
60
|
+
agentContent = agentContent.replace(/(## Active Projects[^\n]*\n\n)([\s\S]*?)(\n\n|$)/, `$1$2\n${projectLine}$3`);
|
|
61
|
+
wikilinksAdded++;
|
|
62
|
+
}
|
|
63
|
+
await fs.writeFile(agentPath, agentContent);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { filePath: projectPath, wikilinksAdded };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/vault/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
async function countFilesInDir(dirPath, ext = ".md") {
|
|
4
|
+
if (!(await fs.pathExists(dirPath)))
|
|
5
|
+
return 0;
|
|
6
|
+
const files = await fs.readdir(dirPath);
|
|
7
|
+
return files.filter((f) => f.endsWith(ext)).length;
|
|
8
|
+
}
|
|
9
|
+
async function getAllMarkdownFiles(dirPath) {
|
|
10
|
+
const results = [];
|
|
11
|
+
async function walk(dir) {
|
|
12
|
+
if (!(await fs.pathExists(dir)))
|
|
13
|
+
return;
|
|
14
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
const fullPath = path.join(dir, entry.name);
|
|
17
|
+
if (entry.isDirectory()) {
|
|
18
|
+
// Skip .obsidian and hidden dirs
|
|
19
|
+
if (!entry.name.startsWith(".")) {
|
|
20
|
+
await walk(fullPath);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else if (entry.name.endsWith(".md")) {
|
|
24
|
+
results.push(fullPath);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
await walk(dirPath);
|
|
29
|
+
return results;
|
|
30
|
+
}
|
|
31
|
+
function extractWikilinks(content) {
|
|
32
|
+
// Strip code blocks and inline code before extracting wikilinks
|
|
33
|
+
const stripped = content
|
|
34
|
+
.replace(/```[\s\S]*?```/g, "") // fenced code blocks
|
|
35
|
+
.replace(/`[^`]+`/g, ""); // inline code
|
|
36
|
+
const matches = stripped.match(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g);
|
|
37
|
+
if (!matches)
|
|
38
|
+
return [];
|
|
39
|
+
return matches.map((m) => m.replace(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/, "$1"));
|
|
40
|
+
}
|
|
41
|
+
export async function getVaultStatus(vaultPath) {
|
|
42
|
+
const exists = await fs.pathExists(vaultPath);
|
|
43
|
+
if (!exists) {
|
|
44
|
+
return {
|
|
45
|
+
exists: false,
|
|
46
|
+
vaultPath,
|
|
47
|
+
noteCount: 0,
|
|
48
|
+
wikilinkCount: 0,
|
|
49
|
+
brokenLinks: [],
|
|
50
|
+
directories: {},
|
|
51
|
+
hasObsidianConfig: false,
|
|
52
|
+
hasAgentMd: false,
|
|
53
|
+
hasGlossary: false,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const allFiles = await getAllMarkdownFiles(vaultPath);
|
|
57
|
+
const noteNames = new Set(allFiles.map((f) => path.basename(f, ".md")));
|
|
58
|
+
// Count wikilinks and find broken ones
|
|
59
|
+
let wikilinkCount = 0;
|
|
60
|
+
const brokenLinksSet = new Set();
|
|
61
|
+
for (const file of allFiles) {
|
|
62
|
+
const content = await fs.readFile(file, "utf-8");
|
|
63
|
+
const links = extractWikilinks(content);
|
|
64
|
+
wikilinkCount += links.length;
|
|
65
|
+
for (const link of links) {
|
|
66
|
+
if (!noteNames.has(link)) {
|
|
67
|
+
brokenLinksSet.add(link);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Count per directory
|
|
72
|
+
const directories = {};
|
|
73
|
+
const topDirs = [
|
|
74
|
+
"Inbox",
|
|
75
|
+
"Projects",
|
|
76
|
+
"Sprints",
|
|
77
|
+
"Knowledge",
|
|
78
|
+
"People",
|
|
79
|
+
"Systems",
|
|
80
|
+
"Archive",
|
|
81
|
+
"Daily",
|
|
82
|
+
];
|
|
83
|
+
for (const dir of topDirs) {
|
|
84
|
+
const dirPath = path.join(vaultPath, dir);
|
|
85
|
+
if (await fs.pathExists(dirPath)) {
|
|
86
|
+
const files = await getAllMarkdownFiles(dirPath);
|
|
87
|
+
directories[dir] = files.length;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
exists: true,
|
|
92
|
+
vaultPath,
|
|
93
|
+
noteCount: allFiles.length,
|
|
94
|
+
wikilinkCount,
|
|
95
|
+
brokenLinks: Array.from(brokenLinksSet),
|
|
96
|
+
directories,
|
|
97
|
+
hasObsidianConfig: await fs.pathExists(path.join(vaultPath, ".obsidian")),
|
|
98
|
+
hasAgentMd: await fs.pathExists(path.join(vaultPath, "AGENT.md")),
|
|
99
|
+
hasGlossary: await fs.pathExists(path.join(vaultPath, "Knowledge/Glossary.md")),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export function formatVaultStatus(status) {
|
|
103
|
+
if (!status.exists) {
|
|
104
|
+
return `ā Vault not found at: ${status.vaultPath}`;
|
|
105
|
+
}
|
|
106
|
+
const lines = [
|
|
107
|
+
`š Vault: ${status.vaultPath}`,
|
|
108
|
+
`š Notes: ${status.noteCount}`,
|
|
109
|
+
`š Wikilinks: ${status.wikilinkCount}`,
|
|
110
|
+
"",
|
|
111
|
+
"Directory breakdown:",
|
|
112
|
+
];
|
|
113
|
+
for (const [dir, count] of Object.entries(status.directories)) {
|
|
114
|
+
lines.push(` ${dir}: ${count} notes`);
|
|
115
|
+
}
|
|
116
|
+
lines.push("");
|
|
117
|
+
lines.push(`Config: ${status.hasObsidianConfig ? "ā" : "ā"} .obsidian/`);
|
|
118
|
+
lines.push(`Agent: ${status.hasAgentMd ? "ā" : "ā"} AGENT.md`);
|
|
119
|
+
lines.push(`Glossary: ${status.hasGlossary ? "ā" : "ā"} Glossary.md`);
|
|
120
|
+
if (status.brokenLinks.length > 0) {
|
|
121
|
+
lines.push("");
|
|
122
|
+
lines.push(`ā ļø Broken links (${status.brokenLinks.length}):`);
|
|
123
|
+
for (const link of status.brokenLinks.slice(0, 10)) {
|
|
124
|
+
lines.push(` - [[${link}]]`);
|
|
125
|
+
}
|
|
126
|
+
if (status.brokenLinks.length > 10) {
|
|
127
|
+
lines.push(` ... and ${status.brokenLinks.length - 10} more`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
lines.push("\nā No broken links");
|
|
132
|
+
}
|
|
133
|
+
return lines.join("\n");
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/vault/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Handlebars from "handlebars";
|
|
2
|
+
const templateCache = new Map();
|
|
3
|
+
export function renderTemplate(templateStr, data) {
|
|
4
|
+
let compiled = templateCache.get(templateStr);
|
|
5
|
+
if (!compiled) {
|
|
6
|
+
compiled = Handlebars.compile(templateStr, { noEscape: true });
|
|
7
|
+
templateCache.set(templateStr, compiled);
|
|
8
|
+
}
|
|
9
|
+
return compiled(data);
|
|
10
|
+
}
|
|
11
|
+
export function today() {
|
|
12
|
+
return new Date().toISOString().slice(0, 10);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/vault/template.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAsC,CAAC;AAEpE,MAAM,UAAU,cAAc,CAC5B,WAAmB,EACnB,IAA6B;IAE7B,IAAI,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jayjiang/byoao",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Build Your Own AI OS ā Obsidian + AI Agent",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"byoao": "dist/cli/cli-program.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"dev": "node --import tsx src/cli/cli-program.ts",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist/",
|
|
19
|
+
"src/assets/",
|
|
20
|
+
"src/skills/"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"opencode",
|
|
24
|
+
"opencode-plugin",
|
|
25
|
+
"obsidian",
|
|
26
|
+
"knowledge-os",
|
|
27
|
+
"preset",
|
|
28
|
+
"knowledge-management"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"author": "Jay Jiang",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/JayJiangCT/BYOAO.git",
|
|
35
|
+
"directory": "byoao"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/JayJiangCT/BYOAO#readme",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/JayJiangCT/BYOAO/issues"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@opencode-ai/plugin": "^1.2.24",
|
|
43
|
+
"chalk": "^5.0.0",
|
|
44
|
+
"commander": "^12.0.0",
|
|
45
|
+
"fs-extra": "^11.0.0",
|
|
46
|
+
"gray-matter": "^4.0.0",
|
|
47
|
+
"handlebars": "^4.7.0",
|
|
48
|
+
"inquirer": "^9.0.0",
|
|
49
|
+
"zod": "^3.23.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/fs-extra": "^11.0.0",
|
|
53
|
+
"@types/inquirer": "^9.0.0",
|
|
54
|
+
"@types/node": "^20.0.0",
|
|
55
|
+
"tsx": "^4.21.0",
|
|
56
|
+
"typescript": "^5.4.0"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: defuddle
|
|
3
|
+
description: Extract clean markdown content from web pages using Defuddle CLI, removing clutter and navigation to save tokens. Use instead of WebFetch when the user provides a URL to read or analyze, for online documentation, articles, blog posts, or any standard web page.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Defuddle
|
|
7
|
+
|
|
8
|
+
Use Defuddle CLI to extract clean readable content from web pages. Prefer over WebFetch for standard web pages ā it removes navigation, ads, and clutter, reducing token usage.
|
|
9
|
+
|
|
10
|
+
If not installed: `npm install -g defuddle`
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
Always use `--md` for markdown output:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
defuddle parse <url> --md
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Save to file:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
defuddle parse <url> --md -o content.md
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Extract specific metadata:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
defuddle parse <url> -p title
|
|
30
|
+
defuddle parse <url> -p description
|
|
31
|
+
defuddle parse <url> -p domain
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Output formats
|
|
35
|
+
|
|
36
|
+
| Flag | Format |
|
|
37
|
+
|------|--------|
|
|
38
|
+
| `--md` | Markdown (default choice) |
|
|
39
|
+
| `--json` | JSON with both HTML and markdown |
|
|
40
|
+
| (none) | HTML |
|
|
41
|
+
| `-p <name>` | Specific metadata property |
|