skillwiki 0.8.5-beta.1 → 0.8.5-beta.2
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.js +185 -66
- package/package.json +1 -1
- package/skills/.claude-plugin/plugin.json +1 -1
- package/skills/.codex-plugin/plugin.json +1 -1
- package/skills/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4011,7 +4011,7 @@ async function runConfigPath(input) {
|
|
|
4011
4011
|
}
|
|
4012
4012
|
|
|
4013
4013
|
// src/commands/doctor.ts
|
|
4014
|
-
import { existsSync as
|
|
4014
|
+
import { existsSync as existsSync10, lstatSync, readlinkSync, readdirSync as readdirSync2, statSync as statSync3, readFileSync as readFileSync7 } from "fs";
|
|
4015
4015
|
import { join as join27, resolve as resolve5 } from "path";
|
|
4016
4016
|
import { execSync as execSync2 } from "child_process";
|
|
4017
4017
|
import { platform as platform2 } from "os";
|
|
@@ -4078,9 +4078,10 @@ function triggerAutoUpdate(home, currentVersion) {
|
|
|
4078
4078
|
}
|
|
4079
4079
|
|
|
4080
4080
|
// src/utils/plugin-registry.ts
|
|
4081
|
-
import { readFileSync as readFileSync5 } from "fs";
|
|
4081
|
+
import { existsSync as existsSync8, readdirSync, readFileSync as readFileSync5 } from "fs";
|
|
4082
4082
|
import { join as join25 } from "path";
|
|
4083
4083
|
var REGISTRY_PATH = join25(".claude", "plugins", "installed_plugins.json");
|
|
4084
|
+
var CODEX_CONFIG_PATH = join25(".codex", "config.toml");
|
|
4084
4085
|
var PLUGIN_KEY = "skillwiki@llm-wiki";
|
|
4085
4086
|
function readInstalledPlugins(home) {
|
|
4086
4087
|
try {
|
|
@@ -4097,6 +4098,102 @@ function findPlugin(home, key = PLUGIN_KEY) {
|
|
|
4097
4098
|
if (!entries || entries.length === 0) return null;
|
|
4098
4099
|
return entries[0];
|
|
4099
4100
|
}
|
|
4101
|
+
function findPluginInstallations(home, key = PLUGIN_KEY) {
|
|
4102
|
+
const parsed = parsePluginKey(key);
|
|
4103
|
+
if (!parsed) return [];
|
|
4104
|
+
const installs = [];
|
|
4105
|
+
const claudePlugin = findPlugin(home, key);
|
|
4106
|
+
if (claudePlugin) {
|
|
4107
|
+
installs.push({
|
|
4108
|
+
channel: "claude",
|
|
4109
|
+
label: "Claude",
|
|
4110
|
+
key,
|
|
4111
|
+
pluginName: parsed.pluginName,
|
|
4112
|
+
marketplace: parsed.marketplace,
|
|
4113
|
+
installPath: claudePlugin.installPath,
|
|
4114
|
+
version: claudePlugin.version
|
|
4115
|
+
});
|
|
4116
|
+
}
|
|
4117
|
+
const codexPlugin = findCodexPlugin(home, key, parsed.pluginName, parsed.marketplace);
|
|
4118
|
+
if (codexPlugin) installs.push(codexPlugin);
|
|
4119
|
+
return installs;
|
|
4120
|
+
}
|
|
4121
|
+
function findCodexPlugin(home, key, pluginName, marketplace) {
|
|
4122
|
+
const config = readCodexPluginConfig(home, key, marketplace);
|
|
4123
|
+
if (!config?.enabled) return null;
|
|
4124
|
+
const cacheRoot = join25(home, ".codex", "plugins", "cache", marketplace, pluginName);
|
|
4125
|
+
if (!existsSync8(cacheRoot)) return null;
|
|
4126
|
+
let versions;
|
|
4127
|
+
try {
|
|
4128
|
+
versions = readdirSync(cacheRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
4129
|
+
} catch {
|
|
4130
|
+
return null;
|
|
4131
|
+
}
|
|
4132
|
+
if (versions.length === 0) return null;
|
|
4133
|
+
const version = versions.reduce((latest, candidate) => semverGt(candidate, latest) ? candidate : latest);
|
|
4134
|
+
return {
|
|
4135
|
+
channel: "codex",
|
|
4136
|
+
label: "Codex",
|
|
4137
|
+
key,
|
|
4138
|
+
pluginName,
|
|
4139
|
+
marketplace,
|
|
4140
|
+
installPath: join25(cacheRoot, version),
|
|
4141
|
+
version,
|
|
4142
|
+
sourceType: config.sourceType,
|
|
4143
|
+
source: config.source
|
|
4144
|
+
};
|
|
4145
|
+
}
|
|
4146
|
+
function parsePluginKey(key) {
|
|
4147
|
+
const at = key.lastIndexOf("@");
|
|
4148
|
+
if (at <= 0 || at === key.length - 1) return null;
|
|
4149
|
+
return {
|
|
4150
|
+
pluginName: key.slice(0, at),
|
|
4151
|
+
marketplace: key.slice(at + 1)
|
|
4152
|
+
};
|
|
4153
|
+
}
|
|
4154
|
+
function readCodexPluginConfig(home, key, marketplace) {
|
|
4155
|
+
let raw;
|
|
4156
|
+
try {
|
|
4157
|
+
raw = readFileSync5(join25(home, CODEX_CONFIG_PATH), "utf8");
|
|
4158
|
+
} catch {
|
|
4159
|
+
return null;
|
|
4160
|
+
}
|
|
4161
|
+
const pluginSections = /* @__PURE__ */ new Set([`plugins."${key}"`, `plugins.${key}`]);
|
|
4162
|
+
const marketplaceSections = /* @__PURE__ */ new Set([`marketplaces.${marketplace}`, `marketplaces."${marketplace}"`]);
|
|
4163
|
+
let section = "";
|
|
4164
|
+
let sawPlugin = false;
|
|
4165
|
+
const config = { enabled: false };
|
|
4166
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
4167
|
+
const trimmed = line.trim();
|
|
4168
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
4169
|
+
const sectionMatch = trimmed.match(/^\[([^\]]+)\]$/);
|
|
4170
|
+
if (sectionMatch) {
|
|
4171
|
+
section = sectionMatch[1];
|
|
4172
|
+
continue;
|
|
4173
|
+
}
|
|
4174
|
+
const kv = trimmed.match(/^([A-Za-z0-9_.-]+)\s*=\s*(.+)$/);
|
|
4175
|
+
if (!kv) continue;
|
|
4176
|
+
const name = kv[1];
|
|
4177
|
+
const value = parseTomlScalar(kv[2]);
|
|
4178
|
+
if (pluginSections.has(section) && name === "enabled") {
|
|
4179
|
+
sawPlugin = true;
|
|
4180
|
+
config.enabled = value === true;
|
|
4181
|
+
} else if (marketplaceSections.has(section) && name === "source_type" && typeof value === "string") {
|
|
4182
|
+
config.sourceType = value;
|
|
4183
|
+
} else if (marketplaceSections.has(section) && name === "source" && typeof value === "string") {
|
|
4184
|
+
config.source = value;
|
|
4185
|
+
}
|
|
4186
|
+
}
|
|
4187
|
+
return sawPlugin ? config : null;
|
|
4188
|
+
}
|
|
4189
|
+
function parseTomlScalar(rawValue) {
|
|
4190
|
+
const value = rawValue.replace(/\s+#.*$/, "").trim();
|
|
4191
|
+
if (value === "true") return true;
|
|
4192
|
+
if (value === "false") return false;
|
|
4193
|
+
const quoted = value.match(/^"((?:\\"|[^"])*)"$/);
|
|
4194
|
+
if (quoted) return quoted[1].replace(/\\"/g, '"');
|
|
4195
|
+
return value;
|
|
4196
|
+
}
|
|
4100
4197
|
|
|
4101
4198
|
// src/utils/s3-mount-health.ts
|
|
4102
4199
|
import { execSync } from "child_process";
|
|
@@ -4361,12 +4458,12 @@ function detectCliChannels(argv, home) {
|
|
|
4361
4458
|
const plugin = findPlugin(home);
|
|
4362
4459
|
if (plugin) {
|
|
4363
4460
|
const pluginBin = join27(plugin.installPath, "bin", "skillwiki");
|
|
4364
|
-
if (
|
|
4461
|
+
if (existsSync10(pluginBin)) {
|
|
4365
4462
|
channels.push({ name: "plugin", path: pluginBin, isDevLink: false });
|
|
4366
4463
|
}
|
|
4367
4464
|
}
|
|
4368
4465
|
const installBin = join27(home, ".claude", "skills", "bin", "skillwiki");
|
|
4369
|
-
if (
|
|
4466
|
+
if (existsSync10(installBin)) {
|
|
4370
4467
|
channels.push({ name: "install", path: installBin, isDevLink: false });
|
|
4371
4468
|
}
|
|
4372
4469
|
return channels;
|
|
@@ -4418,7 +4515,7 @@ function checkCliChannels(argv, home) {
|
|
|
4418
4515
|
}
|
|
4419
4516
|
async function checkConfigFile(home) {
|
|
4420
4517
|
const cfgPath = configPath(home);
|
|
4421
|
-
if (!
|
|
4518
|
+
if (!existsSync10(cfgPath)) {
|
|
4422
4519
|
return check("warn", "config_file", "Config file exists", `${cfgPath} not found`);
|
|
4423
4520
|
}
|
|
4424
4521
|
try {
|
|
@@ -4433,7 +4530,7 @@ function checkWikiPathExists(resolvedPath) {
|
|
|
4433
4530
|
if (resolvedPath === void 0) {
|
|
4434
4531
|
return check("error", "wiki_path_exists", "Vault directory exists", "Cannot check \u2014 WIKI_PATH not resolved");
|
|
4435
4532
|
}
|
|
4436
|
-
if (
|
|
4533
|
+
if (existsSync10(resolvedPath) && statSync3(resolvedPath).isDirectory()) {
|
|
4437
4534
|
return check("pass", "wiki_path_exists", "Vault directory exists", resolvedPath);
|
|
4438
4535
|
}
|
|
4439
4536
|
return check("error", "wiki_path_exists", "Vault directory exists", `${resolvedPath} does not exist or is not a directory`);
|
|
@@ -4442,13 +4539,13 @@ function checkVaultStructure(resolvedPath) {
|
|
|
4442
4539
|
if (resolvedPath === void 0) {
|
|
4443
4540
|
return check("error", "vault_structure", "Vault structure valid", "Cannot check \u2014 WIKI_PATH not resolved");
|
|
4444
4541
|
}
|
|
4445
|
-
if (!
|
|
4542
|
+
if (!existsSync10(resolvedPath)) {
|
|
4446
4543
|
return check("error", "vault_structure", "Vault structure valid", "Cannot check \u2014 vault directory does not exist");
|
|
4447
4544
|
}
|
|
4448
4545
|
const missing = [];
|
|
4449
|
-
if (!
|
|
4546
|
+
if (!existsSync10(join27(resolvedPath, "SCHEMA.md"))) missing.push("SCHEMA.md");
|
|
4450
4547
|
for (const dir of ["raw", "entities", "concepts", "meta"]) {
|
|
4451
|
-
if (!
|
|
4548
|
+
if (!existsSync10(join27(resolvedPath, dir))) missing.push(dir + "/");
|
|
4452
4549
|
}
|
|
4453
4550
|
if (missing.length === 0) {
|
|
4454
4551
|
return check("pass", "vault_structure", "Vault structure valid", "All required files and directories present");
|
|
@@ -4457,7 +4554,7 @@ function checkVaultStructure(resolvedPath) {
|
|
|
4457
4554
|
}
|
|
4458
4555
|
function checkSkillsInstalled(home, cwd) {
|
|
4459
4556
|
const srcDir = cwd ? join27(cwd, "packages", "skills") : void 0;
|
|
4460
|
-
if (srcDir &&
|
|
4557
|
+
if (srcDir && existsSync10(srcDir)) {
|
|
4461
4558
|
const found = findInstalledSkillMd(srcDir);
|
|
4462
4559
|
if (found.length > 0) {
|
|
4463
4560
|
return check("pass", "skills_installed", "Skills installed", `${found.length} SKILL.md file(s) found (source)`);
|
|
@@ -4471,7 +4568,7 @@ function checkSkillsInstalled(home, cwd) {
|
|
|
4471
4568
|
}
|
|
4472
4569
|
}
|
|
4473
4570
|
const skillsDir = join27(home, ".claude", "skills");
|
|
4474
|
-
if (
|
|
4571
|
+
if (existsSync10(skillsDir)) {
|
|
4475
4572
|
const found = findInstalledSkillMd(skillsDir);
|
|
4476
4573
|
if (found.length > 0) {
|
|
4477
4574
|
return check("pass", "skills_installed", "Skills installed", `${found.length} SKILL.md file(s) found (CLI install)`);
|
|
@@ -4523,22 +4620,44 @@ function checkNpmUpdate(home, currentVersion) {
|
|
|
4523
4620
|
return check("pass", "npm_update", "npm CLI version", `v${currentVersion} (latest: v${latest})`);
|
|
4524
4621
|
}
|
|
4525
4622
|
function checkPluginVersionDrift(home, currentVersion) {
|
|
4526
|
-
const
|
|
4527
|
-
if (
|
|
4623
|
+
const plugins = findPluginInstallations(home);
|
|
4624
|
+
if (plugins.length === 0) {
|
|
4528
4625
|
return check("pass", "plugin_version_drift", "Plugin/CLI version", "Plugin not installed \u2014 CLI only");
|
|
4529
4626
|
}
|
|
4530
|
-
const
|
|
4531
|
-
if (
|
|
4532
|
-
|
|
4627
|
+
const drifted = plugins.filter((plugin) => plugin.version !== currentVersion);
|
|
4628
|
+
if (drifted.length === 0) {
|
|
4629
|
+
if (plugins.length === 1 && plugins[0].channel === "claude") {
|
|
4630
|
+
return check("pass", "plugin_version_drift", "Plugin/CLI version", `Both at v${currentVersion}`);
|
|
4631
|
+
}
|
|
4632
|
+
if (plugins.length === 1) {
|
|
4633
|
+
return check("pass", "plugin_version_drift", "Plugin/CLI version", `${plugins[0].label} plugin and CLI both at v${currentVersion}`);
|
|
4634
|
+
}
|
|
4635
|
+
const labels = plugins.map((plugin) => `${plugin.label} plugin`).join(", ");
|
|
4636
|
+
return check("pass", "plugin_version_drift", "Plugin/CLI version", `${labels}, and CLI all at v${currentVersion}`);
|
|
4533
4637
|
}
|
|
4534
|
-
const
|
|
4638
|
+
const details = drifted.map((plugin) => {
|
|
4639
|
+
const updateCmd = pluginUpdateCommand(plugin, currentVersion);
|
|
4640
|
+
return `${plugin.label} plugin v${plugin.version} \u2260 CLI v${currentVersion} \u2014 run \`${updateCmd}\``;
|
|
4641
|
+
});
|
|
4535
4642
|
return check(
|
|
4536
4643
|
"warn",
|
|
4537
4644
|
"plugin_version_drift",
|
|
4538
4645
|
"Plugin/CLI version",
|
|
4539
|
-
|
|
4646
|
+
details.join("; ")
|
|
4540
4647
|
);
|
|
4541
4648
|
}
|
|
4649
|
+
function pluginUpdateCommand(plugin, currentVersion) {
|
|
4650
|
+
if (semverGt(plugin.version, currentVersion)) {
|
|
4651
|
+
return "npm install -g skillwiki@latest";
|
|
4652
|
+
}
|
|
4653
|
+
if (plugin.channel === "claude") {
|
|
4654
|
+
return "claude plugin update skillwiki@llm-wiki";
|
|
4655
|
+
}
|
|
4656
|
+
if (plugin.sourceType === "git") {
|
|
4657
|
+
return "codex plugin marketplace upgrade llm-wiki && codex plugin remove skillwiki@llm-wiki && codex plugin add skillwiki@llm-wiki";
|
|
4658
|
+
}
|
|
4659
|
+
return "codex plugin remove skillwiki@llm-wiki && codex plugin add skillwiki@llm-wiki";
|
|
4660
|
+
}
|
|
4542
4661
|
async function checkProfiles(home) {
|
|
4543
4662
|
const map = await parseDotenvFile(configPath(home));
|
|
4544
4663
|
const profiles = [];
|
|
@@ -4562,7 +4681,7 @@ async function checkProfiles(home) {
|
|
|
4562
4681
|
async function checkProjectLocalOverride(cwd) {
|
|
4563
4682
|
const dir = cwd ?? process.cwd();
|
|
4564
4683
|
const envPath = join27(dir, ".skillwiki", ".env");
|
|
4565
|
-
if (
|
|
4684
|
+
if (existsSync10(envPath)) {
|
|
4566
4685
|
return check("pass", "project_local", "Project-local config", `Found: ${envPath}`);
|
|
4567
4686
|
}
|
|
4568
4687
|
return check("pass", "project_local", "Project-local config", "None");
|
|
@@ -4571,7 +4690,7 @@ function checkVaultGitRemote(resolvedPath) {
|
|
|
4571
4690
|
if (resolvedPath === void 0) {
|
|
4572
4691
|
return check("error", "vault_git_remote", "Vault git remote", "Cannot check \u2014 WIKI_PATH not resolved");
|
|
4573
4692
|
}
|
|
4574
|
-
if (!
|
|
4693
|
+
if (!existsSync10(join27(resolvedPath, ".git"))) {
|
|
4575
4694
|
return check("warn", "vault_git_remote", "Vault git remote", "Vault is not a git repository \u2014 sync features unavailable");
|
|
4576
4695
|
}
|
|
4577
4696
|
try {
|
|
@@ -4594,9 +4713,9 @@ function checkObsidianTemplates(resolvedPath) {
|
|
|
4594
4713
|
return check("error", "obsidian_templates", "Obsidian templates", "Cannot check \u2014 WIKI_PATH not resolved");
|
|
4595
4714
|
}
|
|
4596
4715
|
const missing = [];
|
|
4597
|
-
if (!
|
|
4598
|
-
if (!
|
|
4599
|
-
if (!
|
|
4716
|
+
if (!existsSync10(join27(resolvedPath, "_Templates"))) missing.push("_Templates/");
|
|
4717
|
+
if (!existsSync10(join27(resolvedPath, ".obsidian", "templates.json"))) missing.push(".obsidian/templates.json");
|
|
4718
|
+
if (!existsSync10(join27(resolvedPath, ".obsidian", "app.json"))) missing.push(".obsidian/app.json");
|
|
4600
4719
|
if (missing.length === 0) {
|
|
4601
4720
|
return check("pass", "obsidian_templates", "Obsidian templates", "Template folder and config present");
|
|
4602
4721
|
}
|
|
@@ -4607,14 +4726,14 @@ function checkDotStoreClean(resolvedPath) {
|
|
|
4607
4726
|
return check("error", "dsstore_clean", "No .DS_Store in raw/", "Cannot check \u2014 WIKI_PATH not resolved");
|
|
4608
4727
|
}
|
|
4609
4728
|
const rawDir = join27(resolvedPath, "raw");
|
|
4610
|
-
if (!
|
|
4729
|
+
if (!existsSync10(rawDir)) {
|
|
4611
4730
|
return check("pass", "dsstore_clean", "No .DS_Store in raw/", "raw/ directory not found \u2014 check skipped");
|
|
4612
4731
|
}
|
|
4613
4732
|
const found = [];
|
|
4614
4733
|
(function walk2(dir, rel) {
|
|
4615
4734
|
let entries;
|
|
4616
4735
|
try {
|
|
4617
|
-
entries =
|
|
4736
|
+
entries = readdirSync2(dir, { withFileTypes: true });
|
|
4618
4737
|
} catch {
|
|
4619
4738
|
return;
|
|
4620
4739
|
}
|
|
@@ -4635,7 +4754,7 @@ function checkSyncLastPush(resolvedPath) {
|
|
|
4635
4754
|
if (resolvedPath === void 0) {
|
|
4636
4755
|
return check("error", "sync_last_push", "Vault sync recency", "Cannot check \u2014 WIKI_PATH not resolved");
|
|
4637
4756
|
}
|
|
4638
|
-
if (!
|
|
4757
|
+
if (!existsSync10(join27(resolvedPath, ".git"))) {
|
|
4639
4758
|
return check("pass", "sync_last_push", "Vault sync recency", "No git repo \u2014 sync check skipped");
|
|
4640
4759
|
}
|
|
4641
4760
|
let timestamp;
|
|
@@ -4683,7 +4802,7 @@ function checkVaultGitDirty(resolvedPath) {
|
|
|
4683
4802
|
if (resolvedPath === void 0) {
|
|
4684
4803
|
return check("pass", "vault_git_dirty", "Vault git dirty state", "No vault path \u2014 check skipped");
|
|
4685
4804
|
}
|
|
4686
|
-
if (!
|
|
4805
|
+
if (!existsSync10(join27(resolvedPath, ".git"))) {
|
|
4687
4806
|
return check("pass", "vault_git_dirty", "Vault git dirty state", "No git repo \u2014 check skipped");
|
|
4688
4807
|
}
|
|
4689
4808
|
try {
|
|
@@ -4724,7 +4843,7 @@ function checkVaultGitComparison(resolvedPath, id, label, range, nonZeroSuffix,
|
|
|
4724
4843
|
if (resolvedPath === void 0) {
|
|
4725
4844
|
return check("pass", id, label, "No vault path \u2014 check skipped");
|
|
4726
4845
|
}
|
|
4727
|
-
if (!
|
|
4846
|
+
if (!existsSync10(join27(resolvedPath, ".git"))) {
|
|
4728
4847
|
return check("pass", id, label, "No git repo \u2014 check skipped");
|
|
4729
4848
|
}
|
|
4730
4849
|
if (!hasOriginMain(resolvedPath)) {
|
|
@@ -4762,7 +4881,7 @@ function isRecentLogLine(line, nowMs) {
|
|
|
4762
4881
|
return nowMs - ts <= 24 * 60 * 60 * 1e3;
|
|
4763
4882
|
}
|
|
4764
4883
|
function checkVaultGitPullFailures(home) {
|
|
4765
|
-
const path = pullLogPaths(home).find((p) =>
|
|
4884
|
+
const path = pullLogPaths(home).find((p) => existsSync10(p));
|
|
4766
4885
|
if (!path) {
|
|
4767
4886
|
return check("pass", "vault_git_pull_failures", "Vault pull failures", "No wiki-pull.log found \u2014 check skipped");
|
|
4768
4887
|
}
|
|
@@ -4791,7 +4910,7 @@ function checkS3MountPerf(resolvedPath) {
|
|
|
4791
4910
|
}
|
|
4792
4911
|
const mountPoint = fuse.mountPoint;
|
|
4793
4912
|
const conceptsDir = join27(resolvedPath, "concepts");
|
|
4794
|
-
if (!
|
|
4913
|
+
if (!existsSync10(conceptsDir)) {
|
|
4795
4914
|
return check("pass", "s3_mount_perf", "S3 mount performance", `S3 FUSE mount (${mountPoint}), no concepts/ to benchmark`);
|
|
4796
4915
|
}
|
|
4797
4916
|
const start = Date.now();
|
|
@@ -4974,7 +5093,7 @@ function checkWriteTest(resolvedPath) {
|
|
|
4974
5093
|
return check("pass", "s3_write_test", "S3 write test", "local disk \u2014 check skipped");
|
|
4975
5094
|
}
|
|
4976
5095
|
const conceptsDir = join27(resolvedPath, "concepts");
|
|
4977
|
-
if (!
|
|
5096
|
+
if (!existsSync10(conceptsDir)) {
|
|
4978
5097
|
return check("pass", "s3_write_test", "S3 write test", "no concepts/ dir to test \u2014 check skipped");
|
|
4979
5098
|
}
|
|
4980
5099
|
const result = writeTest(conceptsDir);
|
|
@@ -5099,7 +5218,7 @@ function vaultSyncChecks(input) {
|
|
|
5099
5218
|
const filterPath = input.filterPath ?? join27(home, ".config", "rclone", "wiki-push-filters.txt");
|
|
5100
5219
|
const snapshotPath = input.snapshotScriptPath ?? "/root/.hermes/scripts/wiki-snapshot-v3.sh";
|
|
5101
5220
|
const pushScriptPath = join27(shareDir, "wiki-push.sh");
|
|
5102
|
-
const c1 =
|
|
5221
|
+
const c1 = existsSync10(pushScriptPath) ? check("pass", "vault_sync_installed", "Vault sync installed", `Found: ${pushScriptPath}`) : check("error", "vault_sync_installed", "Vault sync installed", `Script not found at ${pushScriptPath} \u2014 run vault-sync-install`);
|
|
5103
5222
|
let c2;
|
|
5104
5223
|
try {
|
|
5105
5224
|
if (isMac) {
|
|
@@ -5209,7 +5328,7 @@ function vaultSyncChecks(input) {
|
|
|
5209
5328
|
}
|
|
5210
5329
|
}
|
|
5211
5330
|
} catch {
|
|
5212
|
-
c3 =
|
|
5331
|
+
c3 = existsSync10(logDir) ? check(
|
|
5213
5332
|
"warn",
|
|
5214
5333
|
"vault_sync_last_push_age",
|
|
5215
5334
|
"Vault sync last push recency",
|
|
@@ -5268,7 +5387,7 @@ function vaultSyncChecks(input) {
|
|
|
5268
5387
|
}
|
|
5269
5388
|
let c4;
|
|
5270
5389
|
try {
|
|
5271
|
-
if (!
|
|
5390
|
+
if (!existsSync10(filterPath)) {
|
|
5272
5391
|
c4 = check(
|
|
5273
5392
|
"error",
|
|
5274
5393
|
"vault_sync_filter_present",
|
|
@@ -5317,7 +5436,7 @@ function vaultSyncChecks(input) {
|
|
|
5317
5436
|
);
|
|
5318
5437
|
} else {
|
|
5319
5438
|
try {
|
|
5320
|
-
if (!
|
|
5439
|
+
if (!existsSync10(snapshotPath)) {
|
|
5321
5440
|
c5 = check(
|
|
5322
5441
|
"error",
|
|
5323
5442
|
"vault_sync_snapshot_guard",
|
|
@@ -5357,7 +5476,7 @@ function findSkillMd(dir) {
|
|
|
5357
5476
|
const results = [];
|
|
5358
5477
|
let entries;
|
|
5359
5478
|
try {
|
|
5360
|
-
entries =
|
|
5479
|
+
entries = readdirSync2(dir, { withFileTypes: true });
|
|
5361
5480
|
} catch {
|
|
5362
5481
|
return results;
|
|
5363
5482
|
}
|
|
@@ -5378,12 +5497,12 @@ function findSkillNames(dir) {
|
|
|
5378
5497
|
const results = [];
|
|
5379
5498
|
let entries;
|
|
5380
5499
|
try {
|
|
5381
|
-
entries =
|
|
5500
|
+
entries = readdirSync2(dir, { withFileTypes: true });
|
|
5382
5501
|
} catch {
|
|
5383
5502
|
return results;
|
|
5384
5503
|
}
|
|
5385
5504
|
for (const entry of entries) {
|
|
5386
|
-
if (entry.isDirectory() &&
|
|
5505
|
+
if (entry.isDirectory() && existsSync10(join27(dir, entry.name, "SKILL.md"))) {
|
|
5387
5506
|
results.push(entry.name);
|
|
5388
5507
|
}
|
|
5389
5508
|
}
|
|
@@ -6128,7 +6247,7 @@ async function runUpdate(input) {
|
|
|
6128
6247
|
|
|
6129
6248
|
// src/commands/self-update.ts
|
|
6130
6249
|
import { execSync as execSync4 } from "child_process";
|
|
6131
|
-
import { existsSync as
|
|
6250
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
|
|
6132
6251
|
import { join as join30 } from "path";
|
|
6133
6252
|
var DEFAULT_SOURCE_ROOT_SUFFIX = "/Desktop/code/llm-wiki";
|
|
6134
6253
|
async function runSelfUpdate(input) {
|
|
@@ -6137,7 +6256,7 @@ async function runSelfUpdate(input) {
|
|
|
6137
6256
|
).version;
|
|
6138
6257
|
const sourceRoot = input.sourceRoot ?? `${input.home}${DEFAULT_SOURCE_ROOT_SUFFIX}`;
|
|
6139
6258
|
const localPkgPath = join30(sourceRoot, "packages", "cli", "package.json");
|
|
6140
|
-
const hasLocalSource =
|
|
6259
|
+
const hasLocalSource = existsSync11(localPkgPath);
|
|
6141
6260
|
if (input.check) {
|
|
6142
6261
|
let availableVersion = null;
|
|
6143
6262
|
let source;
|
|
@@ -6445,7 +6564,7 @@ ${entries.map((e) => ` ${e.type}: [[${e.page.replace(/\.md$/, "")}]] \u2014 ${e
|
|
|
6445
6564
|
// src/commands/compound.ts
|
|
6446
6565
|
import { writeFile as writeFile12, mkdir as mkdir11, readdir as readdir7, unlink as unlink4 } from "fs/promises";
|
|
6447
6566
|
import { join as join33 } from "path";
|
|
6448
|
-
import { existsSync as
|
|
6567
|
+
import { existsSync as existsSync12 } from "fs";
|
|
6449
6568
|
import { readFile as readFile23 } from "fs/promises";
|
|
6450
6569
|
var RETRO_HEADING_RE = /^## \[(\d{4}-\d{2}-\d{2})(?:\s+[^\]]+)?\] retro \| loop cycle(?: (\d+))?: (.+)$/;
|
|
6451
6570
|
var FIELD_RE = {
|
|
@@ -6563,7 +6682,7 @@ async function runCompound(input) {
|
|
|
6563
6682
|
}
|
|
6564
6683
|
const slug = slugify(entry.cycleName);
|
|
6565
6684
|
const compoundPath = join33(compoundDir, `${slug}.md`);
|
|
6566
|
-
if (
|
|
6685
|
+
if (existsSync12(compoundPath)) {
|
|
6567
6686
|
skipped.push(entry.date);
|
|
6568
6687
|
continue;
|
|
6569
6688
|
}
|
|
@@ -6601,7 +6720,7 @@ async function runCompound(input) {
|
|
|
6601
6720
|
].join("\n");
|
|
6602
6721
|
const content = frontmatter + "\n" + body;
|
|
6603
6722
|
if (!input.dryRun) {
|
|
6604
|
-
if (!
|
|
6723
|
+
if (!existsSync12(compoundDir)) {
|
|
6605
6724
|
await mkdir11(compoundDir, { recursive: true });
|
|
6606
6725
|
}
|
|
6607
6726
|
await writeFile12(compoundPath, content, "utf8");
|
|
@@ -6624,7 +6743,7 @@ async function runCompound(input) {
|
|
|
6624
6743
|
}
|
|
6625
6744
|
async function runCompoundDelete(input) {
|
|
6626
6745
|
const projectDir = join33(input.vault, "projects", input.project);
|
|
6627
|
-
if (!
|
|
6746
|
+
if (!existsSync12(projectDir)) {
|
|
6628
6747
|
return {
|
|
6629
6748
|
exitCode: ExitCode.PROJECT_NOT_FOUND,
|
|
6630
6749
|
result: err("PROJECT_NOT_FOUND", { slug: input.project, path: projectDir })
|
|
@@ -6632,7 +6751,7 @@ async function runCompoundDelete(input) {
|
|
|
6632
6751
|
}
|
|
6633
6752
|
const entryName = input.entry.replace(/\.md$/, "");
|
|
6634
6753
|
const compoundPath = join33(projectDir, "compound", `${entryName}.md`);
|
|
6635
|
-
if (!
|
|
6754
|
+
if (!existsSync12(compoundPath)) {
|
|
6636
6755
|
return {
|
|
6637
6756
|
exitCode: ExitCode.FILE_NOT_FOUND,
|
|
6638
6757
|
result: err("FILE_NOT_FOUND", { path: compoundPath })
|
|
@@ -6666,7 +6785,7 @@ knowledge.md regenerated`
|
|
|
6666
6785
|
}
|
|
6667
6786
|
async function runCompoundList(input) {
|
|
6668
6787
|
const compoundDir = join33(input.vault, "projects", input.project, "compound");
|
|
6669
|
-
if (!
|
|
6788
|
+
if (!existsSync12(compoundDir)) {
|
|
6670
6789
|
return {
|
|
6671
6790
|
exitCode: ExitCode.OK,
|
|
6672
6791
|
result: ok({
|
|
@@ -6729,7 +6848,7 @@ no compound entries found`;
|
|
|
6729
6848
|
|
|
6730
6849
|
// src/commands/observe.ts
|
|
6731
6850
|
import { mkdir as mkdir12, writeFile as writeFile13 } from "fs/promises";
|
|
6732
|
-
import { existsSync as
|
|
6851
|
+
import { existsSync as existsSync13, statSync as statSync4 } from "fs";
|
|
6733
6852
|
import { join as join34 } from "path";
|
|
6734
6853
|
import { createHash as createHash4 } from "crypto";
|
|
6735
6854
|
var ALLOWED_KINDS = /* @__PURE__ */ new Set(["note", "bug", "task", "idea", "session-log"]);
|
|
@@ -6753,7 +6872,7 @@ async function runObserve(input) {
|
|
|
6753
6872
|
result: err("SCHEME_REJECTED", { message: "Text must not be empty" })
|
|
6754
6873
|
};
|
|
6755
6874
|
}
|
|
6756
|
-
if (!
|
|
6875
|
+
if (!existsSync13(input.vault) || !statSync4(input.vault).isDirectory()) {
|
|
6757
6876
|
return {
|
|
6758
6877
|
exitCode: ExitCode.VAULT_PATH_INVALID,
|
|
6759
6878
|
result: err("VAULT_PATH_INVALID", { path: input.vault })
|
|
@@ -7257,11 +7376,11 @@ ${body}`;
|
|
|
7257
7376
|
}
|
|
7258
7377
|
|
|
7259
7378
|
// src/commands/sync.ts
|
|
7260
|
-
import { existsSync as
|
|
7379
|
+
import { existsSync as existsSync15 } from "fs";
|
|
7261
7380
|
import { join as join37 } from "path";
|
|
7262
7381
|
|
|
7263
7382
|
// src/utils/sync-lock.ts
|
|
7264
|
-
import { existsSync as
|
|
7383
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync4, readFileSync as readFileSync10, renameSync, unlinkSync as unlinkSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
7265
7384
|
import { join as join36 } from "path";
|
|
7266
7385
|
import { createHash as createHash6 } from "crypto";
|
|
7267
7386
|
function getSessionId() {
|
|
@@ -7274,7 +7393,7 @@ function lockPath(vault) {
|
|
|
7274
7393
|
}
|
|
7275
7394
|
function readLock(vault) {
|
|
7276
7395
|
const path = lockPath(vault);
|
|
7277
|
-
if (!
|
|
7396
|
+
if (!existsSync14(path)) return null;
|
|
7278
7397
|
try {
|
|
7279
7398
|
const raw = readFileSync10(path, "utf8");
|
|
7280
7399
|
return JSON.parse(raw);
|
|
@@ -7290,7 +7409,7 @@ function isStale(lock, now) {
|
|
|
7290
7409
|
function acquireLock(vault, opts = {}) {
|
|
7291
7410
|
const path = lockPath(vault);
|
|
7292
7411
|
const dir = join36(vault, ".skillwiki");
|
|
7293
|
-
if (!
|
|
7412
|
+
if (!existsSync14(dir)) {
|
|
7294
7413
|
mkdirSync4(dir, { recursive: true });
|
|
7295
7414
|
}
|
|
7296
7415
|
const sessionId = opts.sessionId ?? getSessionId();
|
|
@@ -7335,7 +7454,7 @@ function writeLockedFile(path, lock) {
|
|
|
7335
7454
|
}
|
|
7336
7455
|
function releaseLock(vault, opts = {}) {
|
|
7337
7456
|
const path = lockPath(vault);
|
|
7338
|
-
if (!
|
|
7457
|
+
if (!existsSync14(path)) {
|
|
7339
7458
|
return { released: false };
|
|
7340
7459
|
}
|
|
7341
7460
|
const sessionId = opts.sessionId ?? getSessionId();
|
|
@@ -7364,7 +7483,7 @@ function releaseLock(vault, opts = {}) {
|
|
|
7364
7483
|
function runSyncStatus(input) {
|
|
7365
7484
|
const vault = input.vault;
|
|
7366
7485
|
const includeStashes = input.includeStashes ?? false;
|
|
7367
|
-
if (!
|
|
7486
|
+
if (!existsSync15(join37(vault, ".git"))) {
|
|
7368
7487
|
return {
|
|
7369
7488
|
exitCode: ExitCode.VAULT_PATH_INVALID,
|
|
7370
7489
|
result: ok({
|
|
@@ -7442,7 +7561,7 @@ function runSyncStatus(input) {
|
|
|
7442
7561
|
}
|
|
7443
7562
|
async function runSyncPush(input) {
|
|
7444
7563
|
const vault = input.vault;
|
|
7445
|
-
if (!
|
|
7564
|
+
if (!existsSync15(join37(vault, ".git"))) {
|
|
7446
7565
|
return {
|
|
7447
7566
|
exitCode: ExitCode.VAULT_PATH_INVALID,
|
|
7448
7567
|
result: err("NOT_A_GIT_REPO", { path: vault })
|
|
@@ -7565,7 +7684,7 @@ function enableGitLongPathsOnWindows(vault) {
|
|
|
7565
7684
|
}
|
|
7566
7685
|
async function runSyncPull(input) {
|
|
7567
7686
|
const vault = input.vault;
|
|
7568
|
-
if (!
|
|
7687
|
+
if (!existsSync15(join37(vault, ".git"))) {
|
|
7569
7688
|
return {
|
|
7570
7689
|
exitCode: ExitCode.VAULT_PATH_INVALID,
|
|
7571
7690
|
result: err("NOT_A_GIT_REPO", { path: vault })
|
|
@@ -7737,7 +7856,7 @@ function runSyncPeers(input) {
|
|
|
7737
7856
|
}
|
|
7738
7857
|
function runSyncLock(input) {
|
|
7739
7858
|
const vault = input.vault;
|
|
7740
|
-
if (!
|
|
7859
|
+
if (!existsSync15(vault)) {
|
|
7741
7860
|
return {
|
|
7742
7861
|
exitCode: ExitCode.VAULT_PATH_INVALID,
|
|
7743
7862
|
result: err("VAULT_PATH_INVALID", { path: vault })
|
|
@@ -7772,7 +7891,7 @@ function runSyncLock(input) {
|
|
|
7772
7891
|
}
|
|
7773
7892
|
function runSyncUnlock(input) {
|
|
7774
7893
|
const vault = input.vault;
|
|
7775
|
-
if (!
|
|
7894
|
+
if (!existsSync15(vault)) {
|
|
7776
7895
|
return {
|
|
7777
7896
|
exitCode: ExitCode.VAULT_PATH_INVALID,
|
|
7778
7897
|
result: err("VAULT_PATH_INVALID", { path: vault })
|
|
@@ -7805,7 +7924,7 @@ function runSyncUnlock(input) {
|
|
|
7805
7924
|
}
|
|
7806
7925
|
|
|
7807
7926
|
// src/commands/backup.ts
|
|
7808
|
-
import { statSync as statSync5, readdirSync as
|
|
7927
|
+
import { statSync as statSync5, readdirSync as readdirSync3, readFileSync as readFileSync11, mkdirSync as mkdirSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
7809
7928
|
import { join as join38, relative as relative3, dirname as dirname12 } from "path";
|
|
7810
7929
|
import { PutObjectCommand, HeadObjectCommand, ListObjectsV2Command, GetObjectCommand, DeleteObjectsCommand } from "@aws-sdk/client-s3";
|
|
7811
7930
|
|
|
@@ -7828,7 +7947,7 @@ function createS3Client(config) {
|
|
|
7828
7947
|
// src/commands/backup.ts
|
|
7829
7948
|
var SKIP_DIRS2 = /* @__PURE__ */ new Set([".git", ".obsidian", "_archive", "node_modules", ".skillwiki"]);
|
|
7830
7949
|
function* walkMarkdown(dir, base) {
|
|
7831
|
-
for (const entry of
|
|
7950
|
+
for (const entry of readdirSync3(dir, { withFileTypes: true })) {
|
|
7832
7951
|
if (SKIP_DIRS2.has(entry.name)) continue;
|
|
7833
7952
|
const full = join38(dir, entry.name);
|
|
7834
7953
|
if (entry.isDirectory()) {
|
|
@@ -7975,11 +8094,11 @@ async function runBackupRestore(input) {
|
|
|
7975
8094
|
}
|
|
7976
8095
|
|
|
7977
8096
|
// src/commands/status.ts
|
|
7978
|
-
import { existsSync as
|
|
8097
|
+
import { existsSync as existsSync16, statSync as statSync6 } from "fs";
|
|
7979
8098
|
import { readFile as readFile25 } from "fs/promises";
|
|
7980
8099
|
import { join as join39 } from "path";
|
|
7981
8100
|
async function runStatus(input) {
|
|
7982
|
-
if (!
|
|
8101
|
+
if (!existsSync16(input.vault)) {
|
|
7983
8102
|
return { exitCode: ExitCode.VAULT_PATH_INVALID, result: err("VAULT_PATH_INVALID", { vault: input.vault }) };
|
|
7984
8103
|
}
|
|
7985
8104
|
const scan = await scanVault(input.vault);
|
|
@@ -8180,7 +8299,7 @@ async function runSeed(input) {
|
|
|
8180
8299
|
|
|
8181
8300
|
// src/commands/canvas.ts
|
|
8182
8301
|
import { readFile as readFile26, writeFile as writeFile16 } from "fs/promises";
|
|
8183
|
-
import { existsSync as
|
|
8302
|
+
import { existsSync as existsSync17 } from "fs";
|
|
8184
8303
|
import { join as join41 } from "path";
|
|
8185
8304
|
var NODE_WIDTH = 240;
|
|
8186
8305
|
var NODE_HEIGHT = 60;
|
|
@@ -8260,7 +8379,7 @@ function buildCanvasEdges(adjacency) {
|
|
|
8260
8379
|
}
|
|
8261
8380
|
async function runCanvasGenerate(input) {
|
|
8262
8381
|
const graphPath = input.graphPath ?? join41(input.vault, ".skillwiki", "graph.json");
|
|
8263
|
-
if (!
|
|
8382
|
+
if (!existsSync17(graphPath)) {
|
|
8264
8383
|
return {
|
|
8265
8384
|
exitCode: ExitCode.FILE_NOT_FOUND,
|
|
8266
8385
|
result: err("FILE_NOT_FOUND", {
|
|
@@ -8463,14 +8582,14 @@ async function loadOrBuildGraph(vault) {
|
|
|
8463
8582
|
}
|
|
8464
8583
|
|
|
8465
8584
|
// src/utils/auto-commit.ts
|
|
8466
|
-
import { existsSync as
|
|
8585
|
+
import { existsSync as existsSync18 } from "fs";
|
|
8467
8586
|
import { join as join43 } from "path";
|
|
8468
8587
|
async function postCommit(vault, exitCode) {
|
|
8469
8588
|
if (exitCode !== 0) return;
|
|
8470
8589
|
const home = process.env.HOME ?? "";
|
|
8471
8590
|
const dotenv = await parseDotenvFile(configPath(home));
|
|
8472
8591
|
if (dotenv["AUTO_COMMIT"] === "false") return;
|
|
8473
|
-
if (!
|
|
8592
|
+
if (!existsSync18(join43(vault, ".git"))) return;
|
|
8474
8593
|
const lastOps = readLastOp(vault);
|
|
8475
8594
|
if (lastOps.length === 0) return;
|
|
8476
8595
|
const porcelain = git(vault, ["status", "--porcelain"]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.8.5-beta.
|
|
3
|
+
"version": "0.8.5-beta.2",
|
|
4
4
|
"skills": "./",
|
|
5
5
|
"description": "Project-aware Karpathy-style knowledge base for Claude Code: 18 prompt-only skills (wiki-*, proj-*, using-skillwiki) backed by the deterministic `skillwiki` CLI.",
|
|
6
6
|
"author": {
|