skillwiki 0.10.109 → 0.10.110
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/{chunk-JCDAEZVD.js → chunk-5MV5SSRM.js} +1 -1
- package/dist/{chunk-LDEZQXH6.js → chunk-6X6PPQNI.js} +424 -100
- package/dist/{chunk-DTTKCCQ4.js → chunk-KX5Y3GSX.js} +2 -2
- package/dist/{chunk-QU2IXZRN.js → chunk-NA3TZ4JN.js} +2 -2
- package/dist/{chunk-FYAKMULW.js → chunk-QU2CKXM4.js} +5 -4
- package/dist/{chunk-GJC2CI3W.js → chunk-R2DJ7IJ5.js} +103 -0
- package/dist/{chunk-HMHMCPCE.js → chunk-WPJHDRTP.js} +1 -1
- package/dist/cli.js +57 -12
- package/dist/{index-projection-ESBJOBS7.js → index-projection-6XGESSHV.js} +3 -3
- package/dist/{managed-write-preflight-MAIGWFQJ.js → managed-write-preflight-JPOBVVSU.js} +4 -4
- package/dist/skillwiki-mcp.js +7 -7
- package/dist/sources-CLOF5VAT.js +9 -0
- package/package.json +1 -1
- package/skills/.claude-plugin/plugin.json +1 -1
- package/skills/.codex-plugin/plugin.json +1 -1
- package/skills/.cursor-plugin/plugin.json +1 -1
- package/skills/package.json +1 -1
- package/skills/skills/using-skillwiki/SKILL.md +1 -1
- package/skills/skills/wiki-init/SKILL.md +12 -11
- package/skills/using-skillwiki/SKILL.md +1 -1
- package/skills/wiki-init/SKILL.md +12 -11
- package/templates/launchd/com.karlchow.skillwiki-clip-outbox.plist +22 -0
- package/templates/web-clipper/llm-wiki-clippings.json +1 -1
- package/templates/web-clipper/readme.txt +13 -13
- package/dist/sources-QTQSZMST.js +0 -9
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
ROOT_INDEX_SECTION_ORDER,
|
|
4
4
|
atomicWriteText,
|
|
5
5
|
buildRootIndexUniverse
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WPJHDRTP.js";
|
|
7
7
|
import {
|
|
8
8
|
err,
|
|
9
9
|
ok
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-R2DJ7IJ5.js";
|
|
11
11
|
|
|
12
12
|
// src/utils/index-projection.ts
|
|
13
13
|
import { readFile } from "fs/promises";
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
readLogEvents,
|
|
9
9
|
resolveExistingRegularFileInsideVault,
|
|
10
10
|
writeLogEvent
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-5MV5SSRM.js";
|
|
12
12
|
import {
|
|
13
13
|
ExitCode,
|
|
14
14
|
RawSourceSchema,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
scanSensitiveContent,
|
|
20
20
|
scanVault,
|
|
21
21
|
splitFrontmatter
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-R2DJ7IJ5.js";
|
|
23
23
|
|
|
24
24
|
// src/commands/sources.ts
|
|
25
25
|
import { readFile as readFile4 } from "fs/promises";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
atomicWriteText,
|
|
4
4
|
buildRootIndexUniverse
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-WPJHDRTP.js";
|
|
6
6
|
import {
|
|
7
7
|
authorizeRawOperation,
|
|
8
8
|
buildSourceReferenceIndex,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
resolveExistingRegularFileInsideVault,
|
|
23
23
|
stripFencedBlocks,
|
|
24
24
|
writeLogEvent
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-5MV5SSRM.js";
|
|
26
26
|
import {
|
|
27
27
|
ExitCode,
|
|
28
28
|
FleetManifestSchema,
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
extractFrontmatter,
|
|
31
31
|
filterGitIgnoredRelativePaths,
|
|
32
32
|
getErrorMessage,
|
|
33
|
+
isClipOutboxKey,
|
|
33
34
|
isVaultSyncKey,
|
|
34
35
|
mapWithConcurrency,
|
|
35
36
|
ok,
|
|
@@ -41,7 +42,7 @@ import {
|
|
|
41
42
|
scanVault,
|
|
42
43
|
splitFrontmatter,
|
|
43
44
|
vaultIoConcurrency
|
|
44
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-R2DJ7IJ5.js";
|
|
45
46
|
|
|
46
47
|
// src/utils/home.ts
|
|
47
48
|
import { homedir } from "os";
|
|
@@ -104,7 +105,7 @@ function parseDotenvText(text) {
|
|
|
104
105
|
if (eq <= 0) continue;
|
|
105
106
|
const key = line.slice(0, eq).trim();
|
|
106
107
|
const value = line.slice(eq + 1).trim();
|
|
107
|
-
if (!_whitelist.has(key) && !isValidWikiProfileKey(key) && !isVaultSyncKey(key)) continue;
|
|
108
|
+
if (!_whitelist.has(key) && !isValidWikiProfileKey(key) && !isVaultSyncKey(key) && !isClipOutboxKey(key)) continue;
|
|
108
109
|
if (value.length === 0) continue;
|
|
109
110
|
out[key] = value;
|
|
110
111
|
}
|
|
@@ -419,6 +419,106 @@ function parseVaultSyncKeyValue(key, value) {
|
|
|
419
419
|
const first = parsed.error.issues[0];
|
|
420
420
|
return { ok: false, message: first?.message ?? "invalid value" };
|
|
421
421
|
}
|
|
422
|
+
var clipBool = z.enum(["true", "false"]);
|
|
423
|
+
var clipIntString = (min, max) => z.string().regex(/^[0-9]+$/, "must be a decimal integer").refine((s) => {
|
|
424
|
+
const n = Number(s);
|
|
425
|
+
return Number.isInteger(n) && n >= min && n <= max;
|
|
426
|
+
}, { message: `must be an integer ${min}\u2013${max}` });
|
|
427
|
+
var clipHttpsUrl = z.string().min(1).refine((s) => {
|
|
428
|
+
try {
|
|
429
|
+
const u = new URL(s);
|
|
430
|
+
return u.protocol === "https:" && u.username === "" && u.password === "";
|
|
431
|
+
} catch {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
}, { message: "must be an https URL without userinfo" });
|
|
435
|
+
var clipCredentialRef = z.string().min(1).max(128).regex(
|
|
436
|
+
/^[a-zA-Z0-9_.-]+$/,
|
|
437
|
+
"must be a credential reference name, never a secret value"
|
|
438
|
+
);
|
|
439
|
+
var CLIP_IMAGE_TYPES = ["png", "jpeg", "gif", "webp"];
|
|
440
|
+
var CLIP_ALLOWED_PREFIXES = "raw/articles,raw/assets";
|
|
441
|
+
var CLIP_OUTBOX_DEFAULTS = {
|
|
442
|
+
enabled: "false",
|
|
443
|
+
vault_id: "central",
|
|
444
|
+
allowed_prefixes: CLIP_ALLOWED_PREFIXES,
|
|
445
|
+
destination: "seaweed-wiki:cloud/wiki",
|
|
446
|
+
mode: "event-watch",
|
|
447
|
+
poll_fallback_enabled: "true",
|
|
448
|
+
reconcile_seconds: "3600",
|
|
449
|
+
debounce_ms: "500",
|
|
450
|
+
stable_hash_ms: "500",
|
|
451
|
+
max_article_bytes: "2097152",
|
|
452
|
+
max_images: "64",
|
|
453
|
+
max_image_bytes: "20971520",
|
|
454
|
+
max_bundle_bytes: "104857600",
|
|
455
|
+
max_pixels: "40000000",
|
|
456
|
+
download_concurrency: "4",
|
|
457
|
+
image_types: CLIP_IMAGE_TYPES.join(","),
|
|
458
|
+
max_redirects: "5",
|
|
459
|
+
request_timeout_ms: "30000",
|
|
460
|
+
localize_timeout_ms: "120000",
|
|
461
|
+
watcher_label: "com.karlchow.skillwiki-clip-outbox"
|
|
462
|
+
};
|
|
463
|
+
var ClipOutboxConfigSchema = z.object({
|
|
464
|
+
"clip_outbox.enabled": clipBool,
|
|
465
|
+
"clip_outbox.root": absolutePath,
|
|
466
|
+
"clip_outbox.state_root": absolutePath,
|
|
467
|
+
"clip_outbox.mirror_root": absolutePath,
|
|
468
|
+
"clip_outbox.d8_note_root": absolutePath,
|
|
469
|
+
"clip_outbox.d8_note_absent": clipBool,
|
|
470
|
+
"clip_outbox.vault_id": z.literal("central"),
|
|
471
|
+
"clip_outbox.allowed_prefixes": z.string().refine((s) => {
|
|
472
|
+
const parts = s.split(",").map((p) => p.trim()).filter(Boolean).sort();
|
|
473
|
+
return parts.join(",") === "raw/articles,raw/assets";
|
|
474
|
+
}, { message: "must be exactly raw/articles,raw/assets" }),
|
|
475
|
+
"clip_outbox.destination": z.literal("seaweed-wiki:cloud/wiki"),
|
|
476
|
+
"clip_outbox.mode": z.literal("event-watch"),
|
|
477
|
+
"clip_outbox.poll_fallback_enabled": clipBool,
|
|
478
|
+
"clip_outbox.reconcile_seconds": clipIntString(1, 86400),
|
|
479
|
+
"clip_outbox.debounce_ms": clipIntString(100, 5e3),
|
|
480
|
+
"clip_outbox.stable_hash_ms": clipIntString(100, 5e3),
|
|
481
|
+
"clip_outbox.max_article_bytes": clipIntString(1, 2097152),
|
|
482
|
+
"clip_outbox.max_images": clipIntString(0, 64),
|
|
483
|
+
"clip_outbox.max_image_bytes": clipIntString(1, 20971520),
|
|
484
|
+
"clip_outbox.max_bundle_bytes": clipIntString(1, 104857600),
|
|
485
|
+
"clip_outbox.max_pixels": clipIntString(1, 4e7),
|
|
486
|
+
"clip_outbox.download_concurrency": clipIntString(1, 4),
|
|
487
|
+
"clip_outbox.image_types": z.string().refine((s) => {
|
|
488
|
+
const parts = s.split(",").map((p) => p.trim()).filter(Boolean);
|
|
489
|
+
if (parts.length === 0) return false;
|
|
490
|
+
const allowed = new Set(CLIP_IMAGE_TYPES);
|
|
491
|
+
const seen = /* @__PURE__ */ new Set();
|
|
492
|
+
for (const p of parts) {
|
|
493
|
+
if (!allowed.has(p) || seen.has(p)) return false;
|
|
494
|
+
seen.add(p);
|
|
495
|
+
}
|
|
496
|
+
return true;
|
|
497
|
+
}, { message: "must be a unique subset of png,jpeg,gif,webp" }),
|
|
498
|
+
"clip_outbox.max_redirects": clipIntString(0, 5),
|
|
499
|
+
"clip_outbox.request_timeout_ms": clipIntString(1, 3e4),
|
|
500
|
+
"clip_outbox.localize_timeout_ms": clipIntString(1, 12e4),
|
|
501
|
+
"clip_outbox.ready_url": clipHttpsUrl,
|
|
502
|
+
"clip_outbox.s3_credential_ref": clipCredentialRef,
|
|
503
|
+
"clip_outbox.ready_credential_ref": clipCredentialRef,
|
|
504
|
+
"clip_outbox.watcher_label": z.literal("com.karlchow.skillwiki-clip-outbox")
|
|
505
|
+
}).strict();
|
|
506
|
+
var CLIP_OUTBOX_KEYS = Object.keys(ClipOutboxConfigSchema.shape);
|
|
507
|
+
function isClipOutboxKey(key) {
|
|
508
|
+
return CLIP_OUTBOX_KEYS.includes(key);
|
|
509
|
+
}
|
|
510
|
+
function parseClipOutboxKeyValue(key, value) {
|
|
511
|
+
if (!isClipOutboxKey(key)) {
|
|
512
|
+
return { ok: false, message: `unknown clip_outbox key: ${key}` };
|
|
513
|
+
}
|
|
514
|
+
const fieldSchema = ClipOutboxConfigSchema.shape[key];
|
|
515
|
+
const parsed = fieldSchema.safeParse(value);
|
|
516
|
+
if (parsed.success) {
|
|
517
|
+
return { ok: true };
|
|
518
|
+
}
|
|
519
|
+
const first = parsed.error.issues[0];
|
|
520
|
+
return { ok: false, message: first?.message ?? "invalid value" };
|
|
521
|
+
}
|
|
422
522
|
function detectSchema(fm) {
|
|
423
523
|
const COMPOUND_TYPES = /* @__PURE__ */ new Set(["lesson", "pattern", "antipattern", "gotcha"]);
|
|
424
524
|
if (typeof fm.type === "string" && COMPOUND_TYPES.has(fm.type) && "project" in fm) return { schema: "compound" };
|
|
@@ -834,6 +934,9 @@ export {
|
|
|
834
934
|
FleetManifestSchema,
|
|
835
935
|
isVaultSyncKey,
|
|
836
936
|
parseVaultSyncKeyValue,
|
|
937
|
+
CLIP_OUTBOX_DEFAULTS,
|
|
938
|
+
isClipOutboxKey,
|
|
939
|
+
parseClipOutboxKeyValue,
|
|
837
940
|
detectSchema,
|
|
838
941
|
isBlockedHost,
|
|
839
942
|
getErrorMessage,
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
CAPTURE_HYGIENE_CONTRACT,
|
|
4
|
+
CLIP_NOT_CONFIGURED,
|
|
4
5
|
DEFAULT_CAPTURE_BUDGET,
|
|
5
6
|
DEFAULT_DIRTY_VOLUME_THRESHOLD,
|
|
6
7
|
DEFAULT_MCP_URL,
|
|
@@ -21,6 +22,7 @@ import {
|
|
|
21
22
|
guardProtectedVaultWrite,
|
|
22
23
|
isEventLedgerPath,
|
|
23
24
|
isFailedRunStatus,
|
|
25
|
+
loadClipOutboxConfig,
|
|
24
26
|
mcpAuthFromEnv,
|
|
25
27
|
measureDirtyVolume,
|
|
26
28
|
memoryAuthorityTiersRank,
|
|
@@ -65,7 +67,7 @@ import {
|
|
|
65
67
|
upsertIndexEntry,
|
|
66
68
|
vectorIndexStatus,
|
|
67
69
|
withMcpClient
|
|
68
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-6X6PPQNI.js";
|
|
69
71
|
import {
|
|
70
72
|
normalizeDistTag,
|
|
71
73
|
readCache,
|
|
@@ -78,7 +80,7 @@ import {
|
|
|
78
80
|
UNMANAGED_START,
|
|
79
81
|
renderRootIndex,
|
|
80
82
|
writeRootIndexProjection
|
|
81
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-KX5Y3GSX.js";
|
|
82
84
|
import {
|
|
83
85
|
FLEET_REL_PATH,
|
|
84
86
|
REDACTED_MALFORMED_REFERENCE,
|
|
@@ -171,12 +173,12 @@ import {
|
|
|
171
173
|
supersedeStaleReviewRequiredJournals,
|
|
172
174
|
taxonomyCommentForPage,
|
|
173
175
|
writeDotenv
|
|
174
|
-
} from "./chunk-
|
|
176
|
+
} from "./chunk-QU2CKXM4.js";
|
|
175
177
|
import {
|
|
176
178
|
assertTargetInsideVault,
|
|
177
179
|
atomicWriteText,
|
|
178
180
|
prepareTypedPage
|
|
179
|
-
} from "./chunk-
|
|
181
|
+
} from "./chunk-WPJHDRTP.js";
|
|
180
182
|
import {
|
|
181
183
|
applySourceDisposition,
|
|
182
184
|
decodeSourceActionApproval,
|
|
@@ -184,7 +186,7 @@ import {
|
|
|
184
186
|
inventorySources,
|
|
185
187
|
planSourceDisposition,
|
|
186
188
|
runSourcesPending
|
|
187
|
-
} from "./chunk-
|
|
189
|
+
} from "./chunk-NA3TZ4JN.js";
|
|
188
190
|
import {
|
|
189
191
|
authorizeRawOperation,
|
|
190
192
|
buildSourceReferenceIndex,
|
|
@@ -201,7 +203,7 @@ import {
|
|
|
201
203
|
resolveExistingRegularFileInsideVault,
|
|
202
204
|
validateLogEvent,
|
|
203
205
|
writeLogEvent
|
|
204
|
-
} from "./chunk-
|
|
206
|
+
} from "./chunk-5MV5SSRM.js";
|
|
205
207
|
import {
|
|
206
208
|
ExitCode,
|
|
207
209
|
MetaSchema,
|
|
@@ -222,7 +224,7 @@ import {
|
|
|
222
224
|
scanVault,
|
|
223
225
|
splitFrontmatter,
|
|
224
226
|
vaultIoConcurrency
|
|
225
|
-
} from "./chunk-
|
|
227
|
+
} from "./chunk-R2DJ7IJ5.js";
|
|
226
228
|
|
|
227
229
|
// src/cli.ts
|
|
228
230
|
import { join as join45 } from "path";
|
|
@@ -1288,7 +1290,7 @@ gitignore: ${gi.written ? "merged" : "unchanged"} (write-gitignore only)`,
|
|
|
1288
1290
|
skipEnv ? "env: skipped" : `env: ${envWritten}`,
|
|
1289
1291
|
input.noGitignore ? "gitignore: skipped" : `gitignore: ${gitignoreWritten ? "written" : "unchanged"}`,
|
|
1290
1292
|
`web clipper template: ${WEB_CLIPPER_TEMPLATE_REL}`,
|
|
1291
|
-
"web clipper import:
|
|
1293
|
+
"web clipper import: create ~/Obsidian/clip-outbox (not ~/wiki), import the JSON in each browser profile, select that outbox vault, keep Add to Obsidian"
|
|
1292
1294
|
].join("\n");
|
|
1293
1295
|
if (created.length > 0) {
|
|
1294
1296
|
appendLastOp(target, {
|
|
@@ -3587,6 +3589,30 @@ async function runHealth(input) {
|
|
|
3587
3589
|
return { exitCode, result: ok(report) };
|
|
3588
3590
|
}
|
|
3589
3591
|
|
|
3592
|
+
// src/commands/clip-outbox.ts
|
|
3593
|
+
async function runClipOutboxStatus(home) {
|
|
3594
|
+
const resolved = await loadClipOutboxConfig(home);
|
|
3595
|
+
if (!resolved.ok) {
|
|
3596
|
+
return {
|
|
3597
|
+
exitCode: ExitCode.INVALID_CONFIG_VALUE,
|
|
3598
|
+
result: err("INVALID_CONFIG_VALUE", { message: resolved.message })
|
|
3599
|
+
};
|
|
3600
|
+
}
|
|
3601
|
+
if (!resolved.enabled) {
|
|
3602
|
+
return {
|
|
3603
|
+
exitCode: ExitCode.OK,
|
|
3604
|
+
result: ok({ enabled: false, humanHint: CLIP_NOT_CONFIGURED })
|
|
3605
|
+
};
|
|
3606
|
+
}
|
|
3607
|
+
return {
|
|
3608
|
+
exitCode: ExitCode.OK,
|
|
3609
|
+
result: ok({
|
|
3610
|
+
enabled: true,
|
|
3611
|
+
humanHint: `clip-outbox enabled root=${resolved.config.root} mode=${resolved.config.mode}`
|
|
3612
|
+
})
|
|
3613
|
+
};
|
|
3614
|
+
}
|
|
3615
|
+
|
|
3590
3616
|
// src/commands/connect.ts
|
|
3591
3617
|
import { chmod, mkdir as mkdir5, readFile as readFile6, stat as stat3 } from "fs/promises";
|
|
3592
3618
|
import { join as join18 } from "path";
|
|
@@ -4107,7 +4133,7 @@ ${fmRewritten}
|
|
|
4107
4133
|
}
|
|
4108
4134
|
let indexUpdated = false;
|
|
4109
4135
|
if (!isRaw) {
|
|
4110
|
-
const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-
|
|
4136
|
+
const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-6XGESSHV.js");
|
|
4111
4137
|
const before = await readFile8(join20(input.vault, "index.md"), "utf8").catch(() => "");
|
|
4112
4138
|
const fullTarget = relPath.replace(/\.md$/, "");
|
|
4113
4139
|
const bare = fullTarget.split("/").pop() ?? fullTarget;
|
|
@@ -4230,7 +4256,7 @@ async function runRemove(input) {
|
|
|
4230
4256
|
if (relPath.endsWith(".md") && !relPath.startsWith("raw/")) {
|
|
4231
4257
|
const { readFile: readFile24 } = await import("fs/promises");
|
|
4232
4258
|
const { join: pathJoin } = await import("path");
|
|
4233
|
-
const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-
|
|
4259
|
+
const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-6XGESSHV.js");
|
|
4234
4260
|
const before = await readFile24(pathJoin(input.vault, "index.md"), "utf8").catch(() => "");
|
|
4235
4261
|
const fullTarget = relPath.replace(/\.md$/, "");
|
|
4236
4262
|
const bare = fullTarget.split("/").pop() ?? fullTarget;
|
|
@@ -9761,11 +9787,20 @@ async function measureAuthoritativeLiveDrift(liveVault, projection) {
|
|
|
9761
9787
|
|
|
9762
9788
|
// src/copy-status/copy-status.ts
|
|
9763
9789
|
function liveRecord(p) {
|
|
9790
|
+
if (p.writable === false) {
|
|
9791
|
+
return {
|
|
9792
|
+
state: "blocked",
|
|
9793
|
+
reachable: p.reachable,
|
|
9794
|
+
writable: false,
|
|
9795
|
+
blocked_reason: "s3_write_probe_failed",
|
|
9796
|
+
detail: p.detail ?? "S3 write probe failed"
|
|
9797
|
+
};
|
|
9798
|
+
}
|
|
9764
9799
|
if (p.unknown || p.reachable === void 0) {
|
|
9765
9800
|
return { state: "unknown", reachable: p.reachable, detail: p.detail ?? "S3/MCP unmeasured" };
|
|
9766
9801
|
}
|
|
9767
9802
|
if (p.reachable) {
|
|
9768
|
-
return { state: "ok", reachable: true, detail: p.detail ?? "S3 reachable" };
|
|
9803
|
+
return { state: "ok", reachable: true, ...p.writable === true ? { writable: true } : {}, detail: p.detail ?? "S3 reachable" };
|
|
9769
9804
|
}
|
|
9770
9805
|
return { state: "unknown", reachable: false, detail: p.detail ?? "S3 unreachable" };
|
|
9771
9806
|
}
|
|
@@ -9937,6 +9972,14 @@ function defaultCopyStatusDeps(input) {
|
|
|
9937
9972
|
};
|
|
9938
9973
|
return {
|
|
9939
9974
|
probeLive() {
|
|
9975
|
+
if (input.s3Writable === false) {
|
|
9976
|
+
return {
|
|
9977
|
+
reachable: input.s3Ok,
|
|
9978
|
+
writable: false,
|
|
9979
|
+
detail: `MCP S3 write probe failed${input.s3WritableError ? ` (${input.s3WritableError})` : ""}`
|
|
9980
|
+
};
|
|
9981
|
+
}
|
|
9982
|
+
if (input.s3Ok === true && input.s3Writable === true) return { reachable: true, writable: true, detail: "MCP S3 readable and writable" };
|
|
9940
9983
|
if (input.s3Ok === true) return { reachable: true, detail: "MCP S3 ok" };
|
|
9941
9984
|
if (input.s3Ok === false) return { reachable: false, detail: "MCP S3 not ok" };
|
|
9942
9985
|
const remote = resolveWikiS3Remote({ home: input.home });
|
|
@@ -11212,7 +11255,7 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
|
|
|
11212
11255
|
if (dirty) {
|
|
11213
11256
|
return emit(dirty, void 0, { postCommit: false });
|
|
11214
11257
|
}
|
|
11215
|
-
const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-
|
|
11258
|
+
const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-JPOBVVSU.js");
|
|
11216
11259
|
const run = await runManagedWriteTransaction2({
|
|
11217
11260
|
vault,
|
|
11218
11261
|
command,
|
|
@@ -11856,6 +11899,8 @@ program.command("doctor").description("diagnose skillwiki setup issues").option(
|
|
|
11856
11899
|
checkMcp: !!opts.checkMcp,
|
|
11857
11900
|
env: process.env
|
|
11858
11901
|
})));
|
|
11902
|
+
var clipOutboxCmd = program.command("clip-outbox").description("dedicated file-level web-clip outbox");
|
|
11903
|
+
clipOutboxCmd.command("status").description("show whether the clip-outbox channel is configured").action(async () => emit(await runClipOutboxStatus(resolveSkillwikiHome())));
|
|
11859
11904
|
program.command("connect").description(CONNECT_DESCRIPTION).option("--from-file <path>", "chat-attached env file (not Drive / \u4E91\u76D8)").option("--from-stdin", "read env file from stdin (no echo)").option("--dry-run", "validate without writing ~/.skillwiki/.env").option("--force", "overwrite a different existing token").action(async (opts) => emit(await runConnect({
|
|
11860
11905
|
home: resolveSkillwikiHome(),
|
|
11861
11906
|
fromFile: opts.fromFile,
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
UNMANAGED_START,
|
|
5
5
|
renderRootIndex,
|
|
6
6
|
writeRootIndexProjection
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-KX5Y3GSX.js";
|
|
8
|
+
import "./chunk-WPJHDRTP.js";
|
|
9
|
+
import "./chunk-R2DJ7IJ5.js";
|
|
10
10
|
export {
|
|
11
11
|
UNMANAGED_END,
|
|
12
12
|
UNMANAGED_START,
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
runManagedWritePeerGate,
|
|
7
7
|
runManagedWritePreflight,
|
|
8
8
|
runManagedWriteTransaction
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-QU2CKXM4.js";
|
|
10
|
+
import "./chunk-WPJHDRTP.js";
|
|
11
|
+
import "./chunk-5MV5SSRM.js";
|
|
12
|
+
import "./chunk-R2DJ7IJ5.js";
|
|
13
13
|
export {
|
|
14
14
|
DEFAULT_MANAGED_WRITE_WAIT_MS,
|
|
15
15
|
MANAGED_WRITE_POLL_INTERVAL_MS,
|
package/dist/skillwiki-mcp.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runSkillwikiMcpStdio
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6X6PPQNI.js";
|
|
5
5
|
import "./chunk-7I2TPIV5.js";
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-KX5Y3GSX.js";
|
|
7
|
+
import "./chunk-QU2CKXM4.js";
|
|
8
|
+
import "./chunk-WPJHDRTP.js";
|
|
9
|
+
import "./chunk-NA3TZ4JN.js";
|
|
10
|
+
import "./chunk-5MV5SSRM.js";
|
|
11
|
+
import "./chunk-R2DJ7IJ5.js";
|
|
12
12
|
|
|
13
13
|
// src/mcp-entry.ts
|
|
14
14
|
runSkillwikiMcpStdio().catch((error) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.110",
|
|
4
4
|
"skills": "./",
|
|
5
5
|
"description": "Project-aware Karpathy-style knowledge base for Claude Code: 22 prompt-only skills (wiki-*, proj-*, using-skillwiki, skillwiki-mcp, skillwiki-connect) backed by the deterministic `skillwiki` CLI.",
|
|
6
6
|
"author": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.110",
|
|
4
4
|
"description": "Project-aware Karpathy-style knowledge base: 22 prompt-only skills (wiki-*, proj-*, using-skillwiki, skillwiki-mcp, skillwiki-connect) backed by HTTP MCP wiki_capture.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "karlorz"
|
package/skills/package.json
CHANGED
|
@@ -183,7 +183,7 @@ If the vault has `.WIKI_GIT_FROZEN`:
|
|
|
183
183
|
## Skill Map
|
|
184
184
|
| Skill | When to Invoke |
|
|
185
185
|
|-------|----------------|
|
|
186
|
-
| `wiki-init` | Bootstrap a vault and install `_Templates/web-clipper/llm-wiki-clippings.json` plus import guidance |
|
|
186
|
+
| `wiki-init` | Bootstrap a vault and install `_Templates/web-clipper/llm-wiki-clippings.json` plus import guidance. File-level clips use a dedicated `~/Obsidian/clip-outbox` vault, not `~/wiki`; `skillwiki doctor` reports clip-channel rows; `wiki_capture` is not clip ingress. |
|
|
187
187
|
| `wiki-ingest` | Convert URLs, files, or pasted text into typed-knowledge pages |
|
|
188
188
|
| `wiki-query` | Search typed knowledge by default; work-queue / doctor / MCP diagnose questions use `wiki_context` or `--scope work` / `--scope all`; explicitly requested fresh/raw evidence uses the separate pending channel |
|
|
189
189
|
| `wiki-lint` | Vault health and lint checks; use `health` for whole-system reports and `lint --summary` for bounded lint buckets |
|
|
@@ -29,17 +29,18 @@ None for the first run.
|
|
|
29
29
|
`skillwiki init --target <dir> --domain existing --write-gitignore`.
|
|
30
30
|
6. Report the installed Web Clipper assets at
|
|
31
31
|
`_Templates/web-clipper/llm-wiki-clippings.json` and
|
|
32
|
-
`_Templates/web-clipper/readme.txt`.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
embeds
|
|
32
|
+
`_Templates/web-clipper/readme.txt`. For the file-level clip channel, create
|
|
33
|
+
or select the dedicated Obsidian vault `~/Obsidian/clip-outbox` (never
|
|
34
|
+
`~/wiki`), with `raw/articles` and `raw/assets`, attachment folder
|
|
35
|
+
`raw/assets`. Tell the user to open Obsidian Web Clipper Settings, import the
|
|
36
|
+
JSON, select that outbox vault, keep **Add to Obsidian**, and repeat the
|
|
37
|
+
import for every browser profile. Re-init preserves existing customized
|
|
38
|
+
copies, including short files. A new package version never silently updates
|
|
39
|
+
browser extension storage.
|
|
40
|
+
7. Explain that the generic template preserves `{{content}}`. The clip-outbox
|
|
41
|
+
worker localizes required v1 HTTPS images before freeze, writes
|
|
42
|
+
`![[raw/assets/...]]` embeds, and uploads `raw/assets/<capture-id>/note.md`.
|
|
43
|
+
`wiki_capture` is not clip ingress. Never use `.txt` as the only index.
|
|
43
44
|
8. **Suggest first sources.** Propose 3–5 initial sources (URLs, papers, articles) appropriate to the domain. Prompt the user to provide the first one to ingest, then hand off to wiki-ingest.
|
|
44
45
|
|
|
45
46
|
## Stop conditions
|
|
@@ -183,7 +183,7 @@ If the vault has `.WIKI_GIT_FROZEN`:
|
|
|
183
183
|
## Skill Map
|
|
184
184
|
| Skill | When to Invoke |
|
|
185
185
|
|-------|----------------|
|
|
186
|
-
| `wiki-init` | Bootstrap a vault and install `_Templates/web-clipper/llm-wiki-clippings.json` plus import guidance |
|
|
186
|
+
| `wiki-init` | Bootstrap a vault and install `_Templates/web-clipper/llm-wiki-clippings.json` plus import guidance. File-level clips use a dedicated `~/Obsidian/clip-outbox` vault, not `~/wiki`; `skillwiki doctor` reports clip-channel rows; `wiki_capture` is not clip ingress. |
|
|
187
187
|
| `wiki-ingest` | Convert URLs, files, or pasted text into typed-knowledge pages |
|
|
188
188
|
| `wiki-query` | Search typed knowledge by default; work-queue / doctor / MCP diagnose questions use `wiki_context` or `--scope work` / `--scope all`; explicitly requested fresh/raw evidence uses the separate pending channel |
|
|
189
189
|
| `wiki-lint` | Vault health and lint checks; use `health` for whole-system reports and `lint --summary` for bounded lint buckets |
|
|
@@ -29,17 +29,18 @@ None for the first run.
|
|
|
29
29
|
`skillwiki init --target <dir> --domain existing --write-gitignore`.
|
|
30
30
|
6. Report the installed Web Clipper assets at
|
|
31
31
|
`_Templates/web-clipper/llm-wiki-clippings.json` and
|
|
32
|
-
`_Templates/web-clipper/readme.txt`.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
embeds
|
|
32
|
+
`_Templates/web-clipper/readme.txt`. For the file-level clip channel, create
|
|
33
|
+
or select the dedicated Obsidian vault `~/Obsidian/clip-outbox` (never
|
|
34
|
+
`~/wiki`), with `raw/articles` and `raw/assets`, attachment folder
|
|
35
|
+
`raw/assets`. Tell the user to open Obsidian Web Clipper Settings, import the
|
|
36
|
+
JSON, select that outbox vault, keep **Add to Obsidian**, and repeat the
|
|
37
|
+
import for every browser profile. Re-init preserves existing customized
|
|
38
|
+
copies, including short files. A new package version never silently updates
|
|
39
|
+
browser extension storage.
|
|
40
|
+
7. Explain that the generic template preserves `{{content}}`. The clip-outbox
|
|
41
|
+
worker localizes required v1 HTTPS images before freeze, writes
|
|
42
|
+
`![[raw/assets/...]]` embeds, and uploads `raw/assets/<capture-id>/note.md`.
|
|
43
|
+
`wiki_capture` is not clip ingress. Never use `.txt` as the only index.
|
|
43
44
|
8. **Suggest first sources.** Propose 3–5 initial sources (URLs, papers, articles) appropriate to the domain. Prompt the user to provide the first one to ingest, then hand off to wiki-ingest.
|
|
44
45
|
|
|
45
46
|
## Stop conditions
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>Label</key>
|
|
6
|
+
<string>com.karlchow.skillwiki-clip-outbox</string>
|
|
7
|
+
<key>ProgramArguments</key>
|
|
8
|
+
<array>
|
|
9
|
+
<string>/usr/local/bin/skillwiki</string>
|
|
10
|
+
<string>clip-outbox</string>
|
|
11
|
+
<string>watch</string>
|
|
12
|
+
</array>
|
|
13
|
+
<key>KeepAlive</key>
|
|
14
|
+
<true/>
|
|
15
|
+
<key>RunAtLoad</key>
|
|
16
|
+
<true/>
|
|
17
|
+
<key>WatchPaths</key>
|
|
18
|
+
<array>
|
|
19
|
+
<string>/Users/REPLACE/Obsidian/clip-outbox/raw/articles</string>
|
|
20
|
+
</array>
|
|
21
|
+
</dict>
|
|
22
|
+
</plist>
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
SkillWiki Obsidian Web Clipper template
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Dedicated clip-outbox (v1):
|
|
4
|
+
1. Create or select an Obsidian vault at ~/Obsidian/clip-outbox (outside ~/wiki).
|
|
5
|
+
2. Create raw/articles and raw/assets in that vault. Set the attachment folder to raw/assets.
|
|
6
|
+
3. Open Obsidian Web Clipper Settings in the browser profile that will capture.
|
|
7
|
+
4. Import llm-wiki-clippings.json.
|
|
8
|
+
5. Select the clip-outbox vault. Keep Add to Obsidian. Do not select ~/wiki.
|
|
9
|
+
6. Confirm the destination path is raw/articles and the behavior is Create.
|
|
10
|
+
7. Repeat the import for every browser profile. Shipping a new JSON does not update extension storage.
|
|
11
|
+
8. Verify with a scratch capture and a repeated same-title save before enabling delivery.
|
|
7
12
|
|
|
8
|
-
The generic template preserves Web Clipper's {{content}} output.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
For attended local asset materialization, an agent may choose any URL-friendly
|
|
13
|
-
path under raw/assets/. Write the asset first, use an explicit vault-qualified
|
|
14
|
-
Obsidian embed such as ![[raw/assets/example/diagram.png]], verify the target and
|
|
15
|
-
preview, and only then finalize the new raw capture. Referenced asset paths are
|
|
16
|
-
stable after capture.
|
|
13
|
+
The generic template preserves Web Clipper's {{content}} output. The clip-outbox
|
|
14
|
+
worker localizes remote HTTPS images, writes explicit ![[raw/assets/...]] embeds,
|
|
15
|
+
and uploads a sibling Markdown index at raw/assets/<capture-id>/note.md. Never use
|
|
16
|
+
.txt as the only index. wiki_capture is not clip or image ingress.
|