dsh-code-index 0.7.0 → 0.9.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/CHANGELOG.md +36 -0
- package/README.md +95 -52
- package/README.zh.md +97 -34
- package/dist/client.js +74 -19
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +634 -0
- package/dist/index.js +799 -253
- package/dist/index.js.map +1 -1
- package/package.json +8 -5
- package/scripts/context-pack-demo.mjs +49 -0
- package/scripts/release-smoke.mjs +10 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-code-index",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.9.0",
|
|
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",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
53
|
-
"@deepseek-ai/dsh-tools": "
|
|
53
|
+
"@deepseek-ai/dsh-tools": "0.2.0-rc.2"
|
|
54
54
|
},
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
56
|
"@deepseek-ai/cordis": {
|
|
@@ -58,7 +58,8 @@
|
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@deepseek-ai/
|
|
61
|
+
"@deepseek-ai/cordis": "4.0.4",
|
|
62
|
+
"@deepseek-ai/dsh-tools": "0.2.0-rc.2",
|
|
62
63
|
"@types/node": "^26.2.0",
|
|
63
64
|
"@types/react": "^18.3.31",
|
|
64
65
|
"react": "^18.3.1",
|
|
@@ -79,7 +80,9 @@
|
|
|
79
80
|
"url": "https://github.com/lemonxiny55/dsh-code-index/issues"
|
|
80
81
|
},
|
|
81
82
|
"dependencies": {
|
|
82
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
83
|
+
"@deepseek-ai/schemastery": "^3.18.4",
|
|
84
|
+
"chokidar": "4.0.3",
|
|
85
|
+
"ignore": "7.0.5",
|
|
83
86
|
"tree-sitter-wasms": "^0.1.13",
|
|
84
87
|
"web-tree-sitter": "^0.25.10"
|
|
85
88
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Record actual local tool calls; no model, fake card, or invented output.
|
|
2
|
+
import { execFileSync } from 'node:child_process'
|
|
3
|
+
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import os from 'node:os'
|
|
6
|
+
import { tools } from '../dist/index.js'
|
|
7
|
+
|
|
8
|
+
const root = await mkdtemp(path.join(os.tmpdir(), 'cix-demo-'))
|
|
9
|
+
const git = (...args) => execFileSync('git', ['-C', root, ...args], { stdio: 'ignore' })
|
|
10
|
+
const frames = []
|
|
11
|
+
const started = Date.now()
|
|
12
|
+
const record = text => frames.push([(Date.now() - started) / 1000, 'o', text.replace(/\n/g, '\r\n')])
|
|
13
|
+
const waitUntil = async seconds => new Promise(resolve => setTimeout(resolve, Math.max(0, seconds * 1000 - (Date.now() - started))))
|
|
14
|
+
try {
|
|
15
|
+
await mkdir(path.join(root, 'src')); await mkdir(path.join(root, 'tests'))
|
|
16
|
+
await writeFile(path.join(root, 'src/config.ts'), 'export function loadConfig(input: string) {\n return input.trim()\n}\nexport function removed() { return 0 }\n')
|
|
17
|
+
await writeFile(path.join(root, 'src/startup.ts'), "import { loadConfig } from './config'\nexport function startup() { return loadConfig(' input ') }\n")
|
|
18
|
+
await writeFile(path.join(root, 'tests/config.spec.ts'), "import { loadConfig } from '../src/config'\ntest('whitespace', () => loadConfig(' input '))\n")
|
|
19
|
+
git('init', '-q'); git('config', 'user.email', 'demo@example.invalid'); git('config', 'user.name', 'Context Pack demo')
|
|
20
|
+
git('add', '.'); git('commit', '-qm', 'demo baseline')
|
|
21
|
+
const tool = tools.find(tool => tool.name === 'code_context')
|
|
22
|
+
record('dsh-code-index v0.9.0 — actual local tool calls\nClean Git repository: loadConfig, startup, related test\n')
|
|
23
|
+
await waitUntil(3)
|
|
24
|
+
record('\n> code_context({ task: "Explain loadConfig", budgetChars: 5000 })\n')
|
|
25
|
+
const first = await tool.execute({ task: 'Explain loadConfig', repoRoot: root }, {})
|
|
26
|
+
record(first + '\n')
|
|
27
|
+
await waitUntil(13)
|
|
28
|
+
record('\x1b[2J\x1b[HExternal edit: modify loadConfig, remove removed, add betaCaller\n')
|
|
29
|
+
await writeFile(path.join(root, 'src/config.ts'), "export function loadConfig(input: string) {\n return input.toUpperCase()\n}\nexport function betaCaller() { return loadConfig('beta') }\n")
|
|
30
|
+
record('\n> code_context({ task: "Review current changes", outputFormat: "pack" })\n')
|
|
31
|
+
const pack = await tool.execute({ task: 'Review current changes', repoRoot: root, outputFormat: 'pack' }, {})
|
|
32
|
+
record(tool.output.render({}, pack).map(block => block.text ?? '').join('\n') + '\n')
|
|
33
|
+
await waitUntil(23)
|
|
34
|
+
record('\x1b[2J\x1b[H> code_context({ task: "Explain loadConfig", budgetChars: 500 })\n')
|
|
35
|
+
const bounded = await tool.execute({ task: 'Explain loadConfig', repoRoot: root, budgetChars: 500 }, {})
|
|
36
|
+
record(bounded + '\n\nActual text length: ' + bounded.length + ' / 500\n')
|
|
37
|
+
await waitUntil(30)
|
|
38
|
+
record('\nDemo complete. No publishing, model calls, or external API key.\n')
|
|
39
|
+
await mkdir(new URL('../assets/', import.meta.url), { recursive: true })
|
|
40
|
+
await writeFile(new URL('../assets/context-pack-demo.cast', import.meta.url),
|
|
41
|
+
[JSON.stringify({ version: 2, width: 110, height: 36, timestamp: Math.floor(started / 1000), title: 'Edit-ready Context Packs — real local calls' }), ...frames.map(frame => JSON.stringify(frame))].join('\n') + '\n')
|
|
42
|
+
const replay = { duration: frames.at(-1)[0], frames }
|
|
43
|
+
const html = `<!doctype html><html lang="en"><meta charset="utf-8"><title>Context Pack · 30-second local demo</title>
|
|
44
|
+
<style>body{background:#10151e;color:#e2e8f0;font:15px system-ui;max-width:1000px;margin:30px auto;padding:0 20px}button{padding:8px 16px;margin-right:12px}pre{background:#19212d;padding:20px;white-space:pre-wrap;overflow:auto;height:65vh;font:13px/1.5 monospace}small{color:#a8b3c5}</style>
|
|
45
|
+
<h1>Edit-ready Context Packs</h1><p>Recorded real local calls · no DSH Web Card · no model/API request</p><button id="play">Replay 30 seconds</button><span id="time"></span><pre id="terminal"></pre><small>Reproduce with node scripts/context-pack-demo.mjs after building. Output is recorded, not live.</small>
|
|
46
|
+
<script>const recording=${JSON.stringify(replay).replace(/</g, '\\u003c')};let timer;function run(){clearInterval(timer);let start=performance.now(),next=0;terminal.textContent='';timer=setInterval(()=>{let elapsed=(performance.now()-start)/1000;while(next<recording.frames.length&&recording.frames[next][0]<=elapsed){let text=recording.frames[next++][2];if(text.includes('\\x1b[2J\\x1b[H')){terminal.textContent='';text=text.replace('\\x1b[2J\\x1b[H','')}terminal.textContent+=text;terminal.scrollTop=terminal.scrollHeight}time.textContent=Math.min(30,elapsed).toFixed(1)+' / 30 s';if(next===recording.frames.length)clearInterval(timer)},100)}play.onclick=run;run();</script></html>`
|
|
47
|
+
await writeFile(new URL('../assets/context-pack-demo.html', import.meta.url), html)
|
|
48
|
+
console.log(`Recorded ${replay.duration.toFixed(1)}s demo; text ${bounded.length}/500; pack ${JSON.stringify(pack).length}/5000.`)
|
|
49
|
+
} finally { await rm(root, { recursive: true, force: true }) }
|
|
@@ -75,6 +75,7 @@ const expectedFiles = [
|
|
|
75
75
|
'LICENSE',
|
|
76
76
|
'cordis.patch.yml',
|
|
77
77
|
'dist/index.js',
|
|
78
|
+
'dist/index.d.ts',
|
|
78
79
|
'dist/client.js',
|
|
79
80
|
'scripts/fix-wsl-links.mjs',
|
|
80
81
|
'scripts/release-smoke.mjs',
|
|
@@ -94,6 +95,8 @@ try {
|
|
|
94
95
|
assert.equal(installedPackage.exports['.'].default, './dist/index.js')
|
|
95
96
|
assert.match(installedPackage.engines.node, />=22/)
|
|
96
97
|
assert.equal(installedPackage.license, 'MIT')
|
|
98
|
+
const installedTools = JSON.parse(readFileSync(path.join(smokeDir, 'node_modules', '@deepseek-ai', 'dsh-tools', 'package.json'), 'utf8'))
|
|
99
|
+
assert.equal(installedTools.version, '0.2.0-rc.2', 'fresh consumers must resolve the verified matching RC')
|
|
97
100
|
|
|
98
101
|
const plugin = await import(
|
|
99
102
|
pathToFileURL(path.join(smokeDir, 'node_modules', packageJson.name, 'dist', 'index.js')).href,
|
|
@@ -146,6 +149,13 @@ try {
|
|
|
146
149
|
}),
|
|
147
150
|
/Task context|Primary symbols:/,
|
|
148
151
|
)
|
|
152
|
+
const contextPack = await invoke('code_context', {
|
|
153
|
+
task: 'Explain buildIndex', repoRoot: root, budgetChars: 5000, outputFormat: 'pack',
|
|
154
|
+
})
|
|
155
|
+
assert.equal(contextPack.version, 1)
|
|
156
|
+
assert.ok(contextPack.items.some(item => item.kind === 'primary' && item.name === 'buildIndex'))
|
|
157
|
+
assert.ok(contextPack.items.some(item => item.code !== undefined))
|
|
158
|
+
assert.ok(JSON.stringify(contextPack).length <= 5000)
|
|
149
159
|
assert.match(await invoke('code_health', { repoRoot: root }), /repo health/)
|
|
150
160
|
|
|
151
161
|
for (const dispose of disposers.reverse()) dispose()
|