dsh-plugin-wiki-tools 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -76,9 +76,7 @@ export function createTools(vault, options = {}) {
76
76
  },
77
77
  render: (_args, value) => [{
78
78
  type: 'text',
79
- text: typeof value === 'object' && value !== null && 'results' in value
80
- ? `wiki_query: ${value.results.length} of ${value.totalMatches} matching pages`
81
- : 'wiki_query: returned hot cache and master index',
79
+ text: renderQueryResult(value),
82
80
  }],
83
81
  },
84
82
  async execute(args) {
@@ -181,9 +179,7 @@ export function createTools(vault, options = {}) {
181
179
  },
182
180
  render: (_args, value) => [{
183
181
  type: 'text',
184
- text: typeof value === 'object' && value !== null && 'summary' in value
185
- ? `wiki_lint: ${value.summary.issues} issues across ${value.summary.pagesScanned} pages; report at ${value.reportPath ?? '(not written)'}`
186
- : 'wiki_lint: failed',
182
+ text: renderLintResult(value),
187
183
  }],
188
184
  },
189
185
  async execute() {
@@ -195,6 +191,68 @@ export function createTools(vault, options = {}) {
195
191
  return [wikiQuery, wikiWrite, wikiLint]
196
192
  }
197
193
 
194
+ /**
195
+ * Render a wiki_query result as the model-facing text. The render output is the
196
+ * ONLY content the model sees, so it carries the full payload — hot cache and
197
+ * index verbatim in quick mode, every result with path, snippets, and link
198
+ * context in standard mode — not a summary line.
199
+ * @param {unknown} value - the execute return value.
200
+ * @returns {string} the model-facing result text.
201
+ */
202
+ function renderQueryResult(value) {
203
+ if (typeof value !== 'object' || value === null) return 'wiki_query: no result'
204
+ const result = value
205
+ if (result.mode === 'quick') {
206
+ const parts = []
207
+ if (typeof result.hot === 'string' && result.hot.length > 0) {
208
+ parts.push(`--- wiki/hot.md (recent context cache) ---\n${capText(result.hot, 6000)}`)
209
+ }
210
+ if (typeof result.index === 'string' && result.index.length > 0) {
211
+ parts.push(`--- wiki/index.md (master catalog) ---\n${capText(result.index, 8000)}`)
212
+ }
213
+ if (parts.length === 0) return 'wiki_query (quick): the vault has no hot.md or index.md yet'
214
+ return `wiki_query (quick): hot cache and master index follow. Read these before any page.\n\n${parts.join('\n\n')}`
215
+ }
216
+ if (!Array.isArray(result.results)) return 'wiki_query: no result'
217
+ const lines = [`wiki_query: ${result.results.length} of ${result.totalMatches} matching pages. Open a page with the fs read tool for full content.`]
218
+ for (const hit of result.results) {
219
+ lines.push(`\n### ${hit.name}`)
220
+ lines.push(`path: ${hit.path} · score ${hit.score} · inbound ${hit.inbound.length}${hit.inbound.length > 0 ? ` (${hit.inbound.slice(0, 5).join(', ')})` : ''} · outbound ${hit.outbound}`)
221
+ for (const snippet of hit.snippets) lines.push(`> ${snippet}`)
222
+ }
223
+ return capText(lines.join('\n'), 12000)
224
+ }
225
+
226
+ /**
227
+ * Render a wiki_lint result: every issue with page, severity, and suggestion.
228
+ * @param {unknown} value - the execute return value.
229
+ * @returns {string} the model-facing result text.
230
+ */
231
+ function renderLintResult(value) {
232
+ if (typeof value !== 'object' || value === null || !('summary' in value)) return 'wiki_lint: failed'
233
+ const result = value
234
+ const lines = [
235
+ `wiki_lint: ${result.summary.issues} issues across ${result.summary.pagesScanned} pages.`,
236
+ `checks: ${Object.entries(result.summary.byCheck ?? {}).map(([check, count]) => `${check}×${count}`).join(', ') || 'none'}`,
237
+ `full report: ${typeof result.reportPath === 'string' ? result.reportPath : '(not written)'}`,
238
+ ]
239
+ for (const issue of (result.issues ?? []).slice(0, 60)) {
240
+ lines.push(`- [${issue.severity}] ${issue.check} · ${issue.page}: ${issue.detail} → ${issue.suggestion}`)
241
+ }
242
+ if ((result.issues ?? []).length > 60) lines.push(`… and ${result.issues.length - 60} more (see the report file)`)
243
+ return lines.join('\n')
244
+ }
245
+
246
+ /**
247
+ * Cap one text block, marking the cut.
248
+ * @param {string} text - full text.
249
+ * @param {number} max - maximum characters kept.
250
+ * @returns {string} the capped text.
251
+ */
252
+ function capText(text, max) {
253
+ return text.length <= max ? text : `${text.slice(0, max)}\n… (truncated at ${max} characters)`
254
+ }
255
+
198
256
  /**
199
257
  * Validate the deployment config and register the three wiki tools.
200
258
  * @param {import('@deepseek-ai/cordis').Context} ctx - registrant context carrying the tool registry.
package/lib/search.js CHANGED
@@ -45,7 +45,8 @@ export async function searchVault(root, { query, limit = 10 }) {
45
45
  !META_FILENAMES.has(page.name.toLowerCase()) && !page.name.startsWith('_'))
46
46
  const inbound = new Map(pages.map(page => [page.name, []]))
47
47
  for (const page of searchable) {
48
- for (const target of page.links) {
48
+ // One inbound record per source page, however many times it links.
49
+ for (const target of new Set(page.links)) {
49
50
  inbound.get(target)?.push(page.name)
50
51
  }
51
52
  }
@@ -68,7 +69,7 @@ export async function searchVault(root, { query, limit = 10 }) {
68
69
  score,
69
70
  snippets: matchLines(page.content, needle).slice(0, 2),
70
71
  inbound: inbound.get(page.name) ?? [],
71
- outbound: page.links.length,
72
+ outbound: new Set(page.links).size,
72
73
  })
73
74
  }
74
75
  results.sort((left, right) => right.score - left.score || left.name.localeCompare(right.name))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-wiki-tools",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
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",