dsh-code-index 0.10.0 → 0.10.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/CHANGELOG.md +16 -3
- package/README.md +19 -11
- package/README.zh.md +19 -11
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/scripts/release-smoke.mjs +84 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-code-index",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "Edit-ready Context Packs for DSH agents: bounded source excerpts, changes, related tests, and inclusion evidence — local-first.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
54
|
-
"@deepseek-ai/dsh-tools": "0.2.0-rc.2"
|
|
54
|
+
"@deepseek-ai/dsh-tools": "0.2.0-rc.2 || 0.2.1-rc.2"
|
|
55
55
|
},
|
|
56
56
|
"peerDependenciesMeta": {
|
|
57
57
|
"@deepseek-ai/cordis": {
|
|
@@ -2,6 +2,7 @@ import assert from 'node:assert/strict'
|
|
|
2
2
|
import { execFileSync } from 'node:child_process'
|
|
3
3
|
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
4
4
|
import os from 'node:os'
|
|
5
|
+
import { createRequire } from 'node:module'
|
|
5
6
|
import path from 'node:path'
|
|
6
7
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
7
8
|
|
|
@@ -65,6 +66,10 @@ function parseJsonArrayOutput(output, command) {
|
|
|
65
66
|
|
|
66
67
|
// A release gate can reuse one immutable candidate across Node versions.
|
|
67
68
|
const suppliedTarball = process.argv[2] ? path.resolve(process.argv[2]) : null
|
|
69
|
+
// Exercise each supported host group against the same immutable candidate.
|
|
70
|
+
const toolsVersion = process.argv[3] ?? '0.2.1-rc.2'
|
|
71
|
+
const supportedToolsVersions = packageJson.peerDependencies['@deepseek-ai/dsh-tools'].split(' || ')
|
|
72
|
+
assert.ok(supportedToolsVersions.includes(toolsVersion), 'smoke requires an explicitly supported DSH tools version')
|
|
68
73
|
const packed = suppliedTarball ? null : parseJsonArrayOutput(run(npm, ['pack', '--ignore-scripts', '--json'], root), 'npm pack')
|
|
69
74
|
if (packed) assert.equal(packed.length, 1, 'npm pack must produce exactly one artifact')
|
|
70
75
|
const tarball = suppliedTarball ?? path.resolve(root, packed[0].filename)
|
|
@@ -92,7 +97,7 @@ for (const file of expectedFiles) assert.ok(listed.has(file), `tarball is missin
|
|
|
92
97
|
const smokeDir = mkdtempSync(path.join(os.tmpdir(), 'dsh-code-index-release-'))
|
|
93
98
|
try {
|
|
94
99
|
run(npm, ['init', '--yes'], smokeDir)
|
|
95
|
-
run(npm, ['install', '--ignore-scripts', '--no-save', tarball], smokeDir)
|
|
100
|
+
run(npm, ['install', '--ignore-scripts', '--no-save', tarball, `@deepseek-ai/dsh-tools@${toolsVersion}`], smokeDir)
|
|
96
101
|
|
|
97
102
|
const installedPackage = JSON.parse(
|
|
98
103
|
readFileSync(path.join(smokeDir, 'node_modules', packageJson.name, 'package.json'), 'utf8'),
|
|
@@ -103,7 +108,7 @@ try {
|
|
|
103
108
|
assert.match(installedPackage.engines.node, />=22/)
|
|
104
109
|
assert.equal(installedPackage.license, 'MIT')
|
|
105
110
|
const installedTools = JSON.parse(readFileSync(path.join(smokeDir, 'node_modules', '@deepseek-ai', 'dsh-tools', 'package.json'), 'utf8'))
|
|
106
|
-
assert.equal(installedTools.version,
|
|
111
|
+
assert.equal(installedTools.version, toolsVersion, 'consumer must use the selected matching RC group')
|
|
107
112
|
|
|
108
113
|
const plugin = await import(
|
|
109
114
|
pathToFileURL(path.join(smokeDir, 'node_modules', packageJson.name, 'dist', 'index.js')).href,
|
|
@@ -214,6 +219,23 @@ try {
|
|
|
214
219
|
writeFileSync(path.join(arkRoot, 'Broken.ets'), '@Component\nstruct Broken { build() {')
|
|
215
220
|
assert.match(await invoke('code_index', { repoRoot: arkRoot }), /index incomplete:/)
|
|
216
221
|
|
|
222
|
+
// Issue #5: exercise actual installed Rust signatures, not source imports.
|
|
223
|
+
const rustRoot = path.join(smokeDir, 'rust-repo')
|
|
224
|
+
mkdirSync(path.join(rustRoot, '.git'), { recursive: true })
|
|
225
|
+
writeFileSync(path.join(rustRoot, 'repro.rs'), [
|
|
226
|
+
'pub struct PublicOne { pub field: u32 }',
|
|
227
|
+
'struct PrivateOne { field: u32 }',
|
|
228
|
+
'pub enum PublicEnum { A }',
|
|
229
|
+
'enum PrivateEnum { A }',
|
|
230
|
+
'pub trait PublicTrait { fn run(&self); }',
|
|
231
|
+
'trait PrivateTrait { fn run(&self); }',
|
|
232
|
+
'pub fn public_function(a: u32) -> u32 { a }',
|
|
233
|
+
'fn private_function(a: u32) -> u32 { a }',
|
|
234
|
+
'pub(crate) struct CrateOnly;',
|
|
235
|
+
'pub(in crate) enum Restricted { A }',
|
|
236
|
+
'fn caller() { let value = PublicOne { field: public_function(1) }; }',
|
|
237
|
+
].join('\n'))
|
|
238
|
+
|
|
217
239
|
for (const dispose of disposers.reverse()) dispose()
|
|
218
240
|
|
|
219
241
|
const compactRegistered = []
|
|
@@ -236,7 +258,66 @@ try {
|
|
|
236
258
|
)
|
|
237
259
|
assert.deepEqual(compactRegistered, ['code_index', 'code_context', 'code_health'])
|
|
238
260
|
for (const dispose of compactDisposers.reverse()) dispose()
|
|
239
|
-
|
|
261
|
+
|
|
262
|
+
// Direct handlers above verify package behavior; this separate check runs
|
|
263
|
+
// through the selected RC's real schema/dispatch/rendering pipeline.
|
|
264
|
+
const consumerRequire = createRequire(path.join(smokeDir, 'package.json'))
|
|
265
|
+
const { Context } = await import(pathToFileURL(consumerRequire.resolve('@deepseek-ai/cordis')).href)
|
|
266
|
+
const { default: ToolRuntime } = await import(pathToFileURL(consumerRequire.resolve('@deepseek-ai/dsh-tools')).href)
|
|
267
|
+
const nativeContext = new Context()
|
|
268
|
+
nativeContext.provide('systemPrompt', { tools: () => () => {}, section: () => () => {} })
|
|
269
|
+
const runtime = new ToolRuntime(nativeContext)
|
|
270
|
+
const nativeDisposers = plugin.tools.map(tool => runtime.register(tool))
|
|
271
|
+
try {
|
|
272
|
+
const nativeInvoke = async (name, args) => {
|
|
273
|
+
const result = await runtime.execute({
|
|
274
|
+
callId: `release:${name}`, name, arguments: args,
|
|
275
|
+
signal: new AbortController().signal,
|
|
276
|
+
})
|
|
277
|
+
assert.equal(result.isError, false, JSON.stringify(result.content))
|
|
278
|
+
return result
|
|
279
|
+
}
|
|
280
|
+
await nativeInvoke('code_index', { action: 'build', repoRoot: arkRoot })
|
|
281
|
+
const search = await nativeInvoke('code_search', { query: 'PackageCard', repoRoot: arkRoot })
|
|
282
|
+
assert.equal(search.value[0]?.file, 'Card.ets')
|
|
283
|
+
assert.ok(search.meta, 'search presentation metadata must survive runtime dispatch')
|
|
284
|
+
for (const outputFormat of ['text', 'pack']) {
|
|
285
|
+
const result = await nativeInvoke('code_context', {
|
|
286
|
+
task: 'Explain PackageCard in Card.ets', repoRoot: arkRoot, outputFormat, budgetChars: 5000,
|
|
287
|
+
})
|
|
288
|
+
assert.match(JSON.stringify(result.content), /@ComponentV2/)
|
|
289
|
+
assert.equal(typeof result.value, outputFormat === 'pack' ? 'object' : 'string')
|
|
290
|
+
if (outputFormat === 'pack') assert.ok(JSON.stringify(result.value).length <= 5000)
|
|
291
|
+
}
|
|
292
|
+
await nativeInvoke('code_index', { action: 'build', repoRoot: rustRoot })
|
|
293
|
+
const rustSymbols = await nativeInvoke('code_symbols', { repoRoot: rustRoot })
|
|
294
|
+
assert.ok(rustSymbols.value.some(symbol => symbol.name === 'CrateOnly' && symbol.signature === 'CrateOnly' && !symbol.exported))
|
|
295
|
+
assert.ok(rustSymbols.value.some(symbol => symbol.name === 'Restricted' && symbol.signature === 'Restricted' && !symbol.exported))
|
|
296
|
+
const rustMap = await nativeInvoke('code_map', { repoRoot: rustRoot })
|
|
297
|
+
for (const name of ['PublicOne', 'PublicEnum', 'PublicTrait']) {
|
|
298
|
+
const search = await nativeInvoke('code_search', { query: name, repoRoot: rustRoot })
|
|
299
|
+
assert.equal(search.value[0]?.name, name)
|
|
300
|
+
assert.equal(search.value[0]?.signature, name)
|
|
301
|
+
assert.match(JSON.stringify(search.content), new RegExp(name))
|
|
302
|
+
assert.match(rustMap.value, new RegExp(name))
|
|
303
|
+
const refs = await nativeInvoke('code_refs', { symbol: name, repoRoot: rustRoot })
|
|
304
|
+
assert.match(refs.value, new RegExp(`${name} — repro.rs:`))
|
|
305
|
+
assert.match(refs.value, /callers \(0\)/) // no invented struct-literal/type-use edges
|
|
306
|
+
}
|
|
307
|
+
const rustFunction = await nativeInvoke('code_refs', { symbol: 'public_function', repoRoot: rustRoot })
|
|
308
|
+
assert.match(rustFunction.value, /callers \(1\)/)
|
|
309
|
+
for (const outputFormat of ['text', 'pack']) {
|
|
310
|
+
const result = await nativeInvoke('code_context', {
|
|
311
|
+
task: 'Explain PublicOne', repoRoot: rustRoot, outputFormat, budgetChars: 5000,
|
|
312
|
+
})
|
|
313
|
+
assert.match(JSON.stringify(result.content), /PublicOne/)
|
|
314
|
+
if (outputFormat === 'pack') assert.ok(result.value.items.some(item => item.name === 'PublicOne' && item.code?.includes('pub struct PublicOne')))
|
|
315
|
+
}
|
|
316
|
+
} finally {
|
|
317
|
+
for (const dispose of nativeDisposers.reverse()) dispose()
|
|
318
|
+
await nativeContext.fiber.dispose()
|
|
319
|
+
}
|
|
320
|
+
console.log(`release smoke passed for ${packageJson.name}@${packageJson.version} with dsh-tools@${toolsVersion}`)
|
|
240
321
|
} finally {
|
|
241
322
|
rmSync(smokeDir, { recursive: true, force: true })
|
|
242
323
|
if (!suppliedTarball) rmSync(tarball, { force: true })
|