dsh-plugin-wiki-tools 0.14.1 → 0.14.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/README.md +11 -0
- package/lib/vault.js +27 -12
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
# dsh-plugin-wiki-tools
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-plugin-wiki-tools)
|
|
4
|
+
[](https://www.npmjs.com/package/dsh-plugin-wiki-tools)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin)
|
|
7
|
+
|
|
3
8
|
English | [中文](#中文)
|
|
4
9
|
|
|
5
10
|
Native [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) tools for an Obsidian wiki vault: `wiki_query`, `wiki_write`, and `wiki_lint` implement the mechanical core of the wiki skill suite — path routing, frontmatter completion, index/log bookkeeping, source delta tracking, and health checks — so the model spends its turns on synthesis instead of filesystem chores.
|
|
6
11
|
|
|
12
|
+
```sh
|
|
13
|
+
dsh plugin --profile web add dsh-plugin-wiki-tools
|
|
14
|
+
```
|
|
15
|
+
|
|
7
16
|
Pair with **[dsh-plugin-wiki-skills](https://github.com/Lion-1209/dsh-plugin-wiki-skills)** for the prompt-level skills (`wiki`, `wiki-ingest`, `wiki-query`, `wiki-lint`, `save`).
|
|
8
17
|
|
|
18
|
+
*If this toolchain saves you time maintaining a wiki vault, a ⭐ helps other dsh users find it. 如果这个工具帮到了你,欢迎点个 Star。*
|
|
19
|
+
|
|
9
20
|
## Attribution
|
|
10
21
|
|
|
11
22
|
The vault layout and operation contracts follow the LLM Wiki pattern (Andrej Karpathy) as embodied by [claude-obsidian](https://github.com/AgriciDaniel/claude-obsidian) (MIT, © 2026 AgriciDaniel). This package is an independent plain-ESM implementation of the mechanical core; it contains no code or skill text from claude-obsidian.
|
package/lib/vault.js
CHANGED
|
@@ -214,17 +214,21 @@ export class Vault {
|
|
|
214
214
|
/**
|
|
215
215
|
* Run one mutation under a cross-process advisory lock (the wiki-lock
|
|
216
216
|
* contract): writers in other processes or sessions serialize on the same
|
|
217
|
-
* lock file under `.vault-meta/locks/`.
|
|
218
|
-
* 2s and then
|
|
219
|
-
*
|
|
217
|
+
* lock file under `.vault-meta/locks/`. Default semantics retry once after
|
|
218
|
+
* 2s and then report; pass `{ waitMs }` for patient polling (used by
|
|
219
|
+
* internal bookkeeping, where failing the write after the page file is
|
|
220
|
+
* already on disk would be worse than waiting). A lock older than
|
|
221
|
+
* lockStaleSeconds is treated as crashed and broken either way.
|
|
220
222
|
* @param {string} key - lock key; vault-relative page path, or `__vault__`
|
|
221
223
|
* for vault-wide mutations (rename, archive) and `__manifest__` for the
|
|
222
224
|
* ingest manifest.
|
|
223
225
|
* @param {() => Promise<T>} operation - the mutation to guard.
|
|
226
|
+
* @param {{ waitMs?: number }} [options] - poll until waitMs elapsed
|
|
227
|
+
* instead of the legacy retry-once.
|
|
224
228
|
* @returns {Promise<T>}
|
|
225
229
|
* @template T
|
|
226
230
|
*/
|
|
227
|
-
async withFileLock(key, operation) {
|
|
231
|
+
async withFileLock(key, operation, { waitMs = 0 } = {}) {
|
|
228
232
|
const locksDir = join(this.root, '.vault-meta', 'locks')
|
|
229
233
|
await mkdir(locksDir, { recursive: true })
|
|
230
234
|
const lockPath = join(locksDir, `${createHash('sha1').update(key).digest('hex')}.lock`)
|
|
@@ -244,11 +248,14 @@ export class Vault {
|
|
|
244
248
|
return false
|
|
245
249
|
}
|
|
246
250
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
251
|
+
const deadline = Date.now() + waitMs
|
|
252
|
+
let attempt = 0
|
|
253
|
+
while (!(await acquire())) {
|
|
254
|
+
attempt += 1
|
|
255
|
+
if (Date.now() >= deadline && !(waitMs === 0 && attempt < 2)) {
|
|
250
256
|
throw new Error(`wiki-tools: ${key} is locked by another writer; skipped (retry once it releases)`)
|
|
251
257
|
}
|
|
258
|
+
await new Promise((resolve) => setTimeout(resolve, waitMs > 0 ? 200 : 2000))
|
|
252
259
|
}
|
|
253
260
|
try {
|
|
254
261
|
return await operation()
|
|
@@ -357,11 +364,19 @@ export class Vault {
|
|
|
357
364
|
await mkdir(join(path, '..'), { recursive: true })
|
|
358
365
|
await writeFile(path, file, 'utf8')
|
|
359
366
|
this.invalidateCollectCache()
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
367
|
+
// Index and log are shared state across every writer in the vault: the
|
|
368
|
+
// per-page lock covers this page's file, but two concurrent writes to
|
|
369
|
+
// DIFFERENT pages would otherwise read-modify-write index.md and log.md
|
|
370
|
+
// against each other (entries visibly lost). Serialize the bookkeeping
|
|
371
|
+
// under the vault-wide lock; lock ordering is page → __vault__, and no
|
|
372
|
+
// other path acquires a page lock while holding __vault__, so no cycle.
|
|
373
|
+
await this.withFileLock('__vault__', async () => {
|
|
374
|
+
await this.updateIndex(type, cleanTitle, summary ?? firstContentLine(content))
|
|
375
|
+
await this.updateFolderIndex(type, cleanTitle, summary ?? firstContentLine(content))
|
|
376
|
+
await this.prependLog(`## [${date}] ${existing === undefined ? 'create' : 'update'} | ${cleanTitle}`, [
|
|
377
|
+
`- ${existing === undefined ? 'Created' : 'Updated'}: [[${cleanTitle}]]`,
|
|
378
|
+
])
|
|
379
|
+
}, { waitMs: this.lockStaleMs * 1000 })
|
|
365
380
|
this.gitCommit(`wiki: ${existing === undefined ? 'create' : 'update'} ${cleanTitle}`)
|
|
366
381
|
if (sourcePath !== undefined) {
|
|
367
382
|
await this.trackSource({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-wiki-tools",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.2",
|
|
4
4
|
"description": "Native DeepSeek Harness tools for an Obsidian wiki vault: wiki_query, wiki_write, and wiki_lint implement the mechanical core (path routing, delta tracking, index/log bookkeeping, health checks) of the wiki skill suite.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"./lib/search.js": "./lib/search.js",
|
|
12
12
|
"./lib/lint.js": "./lib/lint.js",
|
|
13
13
|
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
14
|
-
"./package.json": "./package.json"
|
|
14
|
+
"./package.json": "./package.json",
|
|
15
|
+
"./lib/scaffold.js": "./lib/scaffold.js"
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
17
18
|
"index.js",
|