codsh-cli 0.2.0 → 0.4.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/README.md +5 -73
- package/bin/codsh.mjs +105 -43
- package/package.json +9 -127
- package/README.zh.md +0 -76
- package/agent-presets/code-cli/agent.cordis.yml +0 -322
- package/agent-presets/code-cli/preset.yml +0 -3
- package/cordis.patch.yml +0 -165
- package/lib/index.js +0 -4911
- package/lib/invariant.js +0 -23
- package/lib/startup.js +0 -64
- package/lib/types/approval.d.ts +0 -57
- package/lib/types/banner.d.ts +0 -30
- package/lib/types/completion.d.ts +0 -45
- package/lib/types/console.d.ts +0 -240
- package/lib/types/custom-commands.d.ts +0 -54
- package/lib/types/editor.d.ts +0 -186
- package/lib/types/index.d.ts +0 -48
- package/lib/types/inputbox.d.ts +0 -45
- package/lib/types/invariant.d.ts +0 -15
- package/lib/types/keys.d.ts +0 -123
- package/lib/types/markdown.d.ts +0 -73
- package/lib/types/preset-install.d.ts +0 -34
- package/lib/types/prompt.d.ts +0 -150
- package/lib/types/questions.d.ts +0 -65
- package/lib/types/screen.d.ts +0 -204
- package/lib/types/selector.d.ts +0 -98
- package/lib/types/spinner.d.ts +0 -63
- package/lib/types/startup.d.ts +0 -31
- package/lib/types/status.d.ts +0 -94
- package/lib/types/streaming.d.ts +0 -68
- package/lib/types/theme.d.ts +0 -75
- package/lib/types/transcript.d.ts +0 -129
- package/lib/types/wrap.d.ts +0 -27
package/README.md
CHANGED
|
@@ -1,77 +1,9 @@
|
|
|
1
|
-
# codsh
|
|
1
|
+
# codsh-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The `codsh` command: a **zero-dependency launcher** for [codsh](https://github.com/Blackman99/codsh), a Claude Code-style coding agent for the terminal composed on the DeepSeek Harness (dsh).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This package bundles nothing. It finds the dsh you already have (`DSH_BIN`, a resolvable `@deepseek-ai/dsh`, or `dsh` on PATH), registers the [`codsh-bundle`](https://www.npmjs.com/package/codsh-bundle) runtime into a dsh `code` profile on first run, and boots `dsh --profile code`. No dsh yet? `npm install -g @deepseek-ai/dsh` first.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Set `DSH_BIN=/path/to/dsh` to pin a specific dsh; set `CODSH_BUNDLE_SPEC` to register a bundle other than the launcher's paired `codsh-bundle@^<version>` (development installs use a `file:` tarball here, which the launcher never overwrites).
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
npm install -g codsh-cli
|
|
13
|
-
codsh
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
The first run registers this package into a dsh `code` profile under `$DSH_HOME` (default `~/.dsh`) and installs the packaged `code-cli` agent preset; every later run boots straight into the prompt. The model key is read from `DEEPSEEK_API_KEY` (environment or `.env`).
|
|
17
|
-
|
|
18
|
-
`codsh` is exactly `dsh --profile code` — the wrapper only performs the one-time profile registration. Flags after `codsh` reach the app: `codsh --resume <session-id>`, `codsh --continue`, `codsh -p "one-shot task"`.
|
|
19
|
-
|
|
20
|
-
## What you get
|
|
21
|
-
|
|
22
|
-
- **A session that is its own space**: codsh takes the alternate screen, so your shell's scrollback is untouched and waiting when you leave. The transcript scrolls in a buffer the session owns — mouse wheel, PgUp/PgDn, Shift+↑/↓ — under an input box that never moves from the bottom; scrolled back, the viewport says how far and new output keeps accumulating without yanking you to it. Every frame paints as one synchronized update, and quitting drops a two-line summary (session id, spend, the `--resume` command) into your shell.
|
|
23
|
-
- **Select to copy**: drag with the mouse and the selection is on your clipboard the moment you release — highlighted in place, sent through OSC 52 and the platform clipboard both (`CODSH_CLIPBOARD=osc52|system|off` narrows it). Long finished blocks — thinking, tool output, and answers past a screenful — collapse to their head lines once you move on; Ctrl-O swaps every one of them between summary and full form.
|
|
24
|
-
- **An input box that owns the keyboard**: multi-line editing (Alt-Enter), history across sessions, and completion for commands, arguments, and `@`-mentioned files (fuzzy, workspace-wide), opened as you type.
|
|
25
|
-
- **Streaming rendering**: Markdown with code highlighting and table layout, reasoning models' thinking dim under `✻ thinking`, tool calls as presenter-driven cards with diffs, and Ctrl-O to reprint the last clipped output in full.
|
|
26
|
-
- **Decisions as selections**: approvals, questions, `/model`, and `/resume` are arrow-key widgets; plan mode toggles on Shift-Tab and tints the box frame.
|
|
27
|
-
- **Session flow**: `/clear` starts fresh in place, `/resume` picks from recorded sessions with titles and ages, Escape twice recalls your previous message for editing, and `!cmd` runs in your shell with the outcome injected as model-visible context — no turn spent.
|
|
28
|
-
- **Canned prompts**: `/init` drafts an `AGENTS.md`; your own Markdown files under `$DSH_HOME/commands/` or `<workspace>/.dsh/commands/` become slash commands with `$ARGUMENTS` templating.
|
|
29
|
-
- Status line (model, preset, permissions, tokens, context left, branch), terminal-title updates, a bell when a decision waits, and a `--print` mode for scripts.
|
|
30
|
-
|
|
31
|
-
Off a TTY (pipes, scripts) the same surface degrades to a line reader: selections become typed answers, lists replace widgets, and nothing draws.
|
|
32
|
-
|
|
33
|
-
## Development
|
|
34
|
-
|
|
35
|
-
```sh
|
|
36
|
-
pnpm install
|
|
37
|
-
pnpm run dev # build → sync into .dev-home → boot; seconds per iteration
|
|
38
|
-
MOCK=markdown pnpm run dev # keyless, against the e2e mock model
|
|
39
|
-
pnpm run build # tsdown runtime bundles + tsc declarations into lib/
|
|
40
|
-
pnpm run typecheck
|
|
41
|
-
pnpm test # unit suites (pure modules: editor, markdown, transcript, …)
|
|
42
|
-
pnpm run test:e2e # packs this repo, registers it into a dsh profile, and
|
|
43
|
-
# drives the INSTALLED dsh binary through pipes and a real PTY
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
`pnpm run dev` keeps a repo-local dsh home in `.dev-home`: the first run does a real profile install of the packed tree, and every later run just copies the fresh `lib/` over the profile's unpacked package — so edits reach the running surface in seconds. `MOCK=<write|bash|slow|markdown|reasoning|echo|tall>` swaps in the keyless e2e model for UI work without a key, arguments pass through (`pnpm run dev -- --resume <id>`), and `INSPECT=1` opens the Node inspector on the app process (`chrome://inspect` or a VS Code attach). Off-TTY logic is easiest to step through piped — `printf 'task\n/exit\n' | MOCK=echo pnpm run dev` — where raw mode and the repaint region are out of the picture; keep `console.*` out of debug prints on a TTY (they tear the managed region) and log to a file instead.
|
|
47
|
-
|
|
48
|
-
The e2e suites test the release artifact: `npm pack` output installed into a real profile, booted by the dsh launcher from npm, with a keyless mock model. What passes there is what a user installs.
|
|
49
|
-
|
|
50
|
-
### Debugging against dsh sources
|
|
51
|
-
|
|
52
|
-
Day to day, dsh is an ordinary npm dependency. To step into harness code, clone [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) beside this repo, build it (`pnpm install && pnpm run build`), then point the packages you are debugging at the checkout:
|
|
53
|
-
|
|
54
|
-
```jsonc
|
|
55
|
-
// package.json — remove again when done; keep npm as the default
|
|
56
|
-
"pnpm": {
|
|
57
|
-
"overrides": {
|
|
58
|
-
"@deepseek-ai/dsh-agent-loop": "link:../deepseek-harness/packages/core/agent-loop"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
and re-run `pnpm install`. Changes you want upstream go to the harness repo as ordinary PRs; this repository never forks it.
|
|
64
|
-
|
|
65
|
-
### Keeping up with dsh releases
|
|
66
|
-
|
|
67
|
-
codsh consumes the harness as published `@deepseek-ai/dsh-*` packages, so "syncing with dsh" means tracking harness **releases**, not merging source. Three layers keep it automatic:
|
|
68
|
-
|
|
69
|
-
1. **Detect** — [Renovate](renovate.json) watches `@deepseek-ai/dsh-*` (plus co-released cordis packages) and opens dependency PRs; a nightly [sync workflow](.github/workflows/sync-dsh.yml) does the same without third-party services.
|
|
70
|
-
2. **Bump** — `pnpm run sync:dsh` rewrites every `@deepseek-ai/dsh-*` range to the latest published release, refreshes the lockfile, writes a changeset, and exits `1` from `--check` when newer versions exist (that is what the nightly job keys on).
|
|
71
|
-
3. **Prove** — the same command re-verifies `cordis.patch.yml`: every plugin id it disables or configures must still be declared by an installed dsh bundle, and every package it inserts must resolve. Then it runs typecheck/build/unit (add `--e2e` to boot the real patched bundle), and CI repeats all of that on the resulting PR.
|
|
72
|
-
|
|
73
|
-
Because every dsh package is a prerelease (`0.1.0-rc.N`), plain semver ranges do **not** float across releases — the sync command is the source of truth, not `pnpm update`.
|
|
74
|
-
|
|
75
|
-
## License
|
|
76
|
-
|
|
77
|
-
MIT
|
|
9
|
+
Full documentation: [github.com/Blackman99/codsh](https://github.com/Blackman99/codsh)
|
package/bin/codsh.mjs
CHANGED
|
@@ -1,61 +1,123 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* The `codsh` command:
|
|
4
|
-
*
|
|
3
|
+
* The `codsh` command: a zero-dependency launcher over the dsh you already
|
|
4
|
+
* have.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `
|
|
6
|
+
* This package deliberately bundles NOTHING — the ~300MB dsh runtime lives
|
|
7
|
+
* once on a machine, not once per tool. The wrapper finds a dsh (`DSH_BIN`,
|
|
8
|
+
* then a resolvable `@deepseek-ai/dsh` install, then `dsh` on PATH), registers
|
|
9
|
+
* the `codsh-bundle` runtime into the `code` profile on first run, and boots
|
|
10
|
+
* `dsh --profile code` with the arguments passed through.
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
import { spawnSync } from 'node:child_process'
|
|
13
|
-
import { existsSync,
|
|
14
|
-
import { homedir
|
|
14
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
15
|
+
import { homedir } from 'node:os'
|
|
15
16
|
import { dirname, join } from 'node:path'
|
|
16
|
-
import { fileURLToPath } from 'node:url'
|
|
17
17
|
import { createRequire } from 'node:module'
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
const requireFromHere = createRequire(import.meta.url)
|
|
20
|
+
const own = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
|
|
21
|
+
|
|
22
|
+
/** The bundle package this launcher pairs with, lockstep-versioned. */
|
|
23
|
+
const BUNDLE = 'codsh-bundle'
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Locate a dsh launcher without carrying one.
|
|
27
|
+
* @returns how to spawn it, or undefined when the machine has none.
|
|
28
|
+
*/
|
|
29
|
+
function findDsh() {
|
|
30
|
+
const pinned = process.env.DSH_BIN
|
|
31
|
+
if (pinned !== undefined && pinned !== '') {
|
|
32
|
+
// A JS entry runs through this Node; anything else is an executable.
|
|
33
|
+
return /\.[cm]?js$/.test(pinned)
|
|
34
|
+
? { command: process.execPath, prefix: [pinned] }
|
|
35
|
+
: { command: pinned, prefix: [] }
|
|
36
|
+
}
|
|
30
37
|
try {
|
|
31
|
-
const
|
|
32
|
-
|
|
38
|
+
const manifest = requireFromHere.resolve('@deepseek-ai/dsh/package.json')
|
|
39
|
+
const bin = JSON.parse(readFileSync(manifest, 'utf8')).bin
|
|
40
|
+
const entry = join(dirname(manifest), typeof bin === 'string' ? bin : bin.dsh)
|
|
41
|
+
return { command: process.execPath, prefix: [entry] }
|
|
33
42
|
} catch {
|
|
34
|
-
|
|
43
|
+
// Not installed beside this package; the PATH is next.
|
|
35
44
|
}
|
|
45
|
+
const probe = spawnSync('dsh', ['--version'], { stdio: 'ignore', shell: process.platform === 'win32' })
|
|
46
|
+
if (probe.error === undefined && probe.status !== null) return { command: 'dsh', prefix: [] }
|
|
47
|
+
return undefined
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const dsh = findDsh()
|
|
51
|
+
if (dsh === undefined) {
|
|
52
|
+
console.error(`codsh: no dsh runtime found. codsh launches the dsh you already have —
|
|
53
|
+
the runtime is not bundled, so a machine never carries a second copy.
|
|
54
|
+
|
|
55
|
+
install one: npm install -g @deepseek-ai/dsh
|
|
56
|
+
or point at one: DSH_BIN=/path/to/dsh codsh`)
|
|
57
|
+
process.exit(1)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Run the found dsh with arguments, inheriting the terminal. */
|
|
61
|
+
function run(args) {
|
|
62
|
+
const result = spawnSync(dsh.command, [...dsh.prefix, ...args], { stdio: 'inherit' })
|
|
63
|
+
return result.status ?? 1
|
|
36
64
|
}
|
|
37
65
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
66
|
+
/** `a > b` for plain x.y.z versions, which is all this pair publishes. */
|
|
67
|
+
function newer(a, b) {
|
|
68
|
+
const pa = String(a).split('.').map(Number)
|
|
69
|
+
const pb = String(b).split('.').map(Number)
|
|
70
|
+
for (let index = 0; index < 3; index += 1) {
|
|
71
|
+
if ((pa[index] ?? 0) !== (pb[index] ?? 0)) return (pa[index] ?? 0) > (pb[index] ?? 0)
|
|
72
|
+
}
|
|
73
|
+
return false
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const home = process.env.DSH_HOME ?? join(homedir(), '.dsh')
|
|
77
|
+
const manifestPath = join(home, 'profiles', 'code', 'package.json')
|
|
78
|
+
|
|
79
|
+
/** What the code profile currently carries, or undefined before first run. */
|
|
80
|
+
function profile() {
|
|
81
|
+
if (!existsSync(manifestPath)) return undefined
|
|
82
|
+
try {
|
|
83
|
+
return JSON.parse(readFileSync(manifestPath, 'utf8'))
|
|
84
|
+
} catch {
|
|
85
|
+
return undefined
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Decide whether — and what — to register into the profile this run.
|
|
91
|
+
* @returns the spec to `dsh plugin add`, or undefined when nothing is due.
|
|
92
|
+
*/
|
|
93
|
+
function registration() {
|
|
94
|
+
const spec = process.env.CODSH_BUNDLE_SPEC ?? `${BUNDLE}@^${own.version}`
|
|
95
|
+
const manifest = profile()
|
|
96
|
+
const dependencies = manifest?.dependencies ?? {}
|
|
97
|
+
// The pre-split layout carried the whole runtime under this launcher's own
|
|
98
|
+
// name; migrate it out so both bundles don't fight over the terminal.
|
|
99
|
+
if (manifest !== undefined && 'codsh-cli' in dependencies) {
|
|
100
|
+
console.error('codsh: migrating the profile to the split codsh-bundle runtime')
|
|
101
|
+
delete manifest.dependencies['codsh-cli']
|
|
102
|
+
const bundles = manifest?.dsh?.profile?.bundles
|
|
103
|
+
if (Array.isArray(bundles)) {
|
|
104
|
+
manifest.dsh.profile.bundles = bundles.filter(name => name !== 'codsh-cli')
|
|
52
105
|
}
|
|
53
|
-
|
|
106
|
+
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`)
|
|
107
|
+
return spec
|
|
54
108
|
}
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
57
|
-
|
|
109
|
+
const current = dependencies[BUNDLE]
|
|
110
|
+
if (current === undefined) return spec
|
|
111
|
+
// A file:/link: registration is a development pin; never clobber it.
|
|
112
|
+
if (!current.startsWith('^')) return undefined
|
|
113
|
+
return newer(own.version, current.slice(1)) ? spec : undefined
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const spec = registration()
|
|
117
|
+
if (spec !== undefined) {
|
|
118
|
+
console.error(`codsh: registering ${spec} into the dsh code profile`)
|
|
119
|
+
const status = run(['plugin', '--profile', 'code', 'add', spec])
|
|
120
|
+
if (status !== 0) process.exit(status)
|
|
58
121
|
}
|
|
59
122
|
|
|
60
|
-
|
|
61
|
-
process.exit(run.status ?? 0)
|
|
123
|
+
process.exit(run(['--profile', 'code', ...process.argv.slice(2)]))
|
package/package.json
CHANGED
|
@@ -1,132 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codsh-cli",
|
|
3
|
-
"description": "A Claude Code-style coding agent for the terminal, composed on the DeepSeek Harness (dsh)
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "A Claude Code-style coding agent for the terminal, composed on the DeepSeek Harness (dsh). This is the zero-dependency launcher: it finds your dsh, registers the codsh-bundle runtime into a profile, and boots it.",
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
8
8
|
"codsh": "./bin/codsh.mjs"
|
|
9
9
|
},
|
|
10
|
-
"main": "lib/index.js",
|
|
11
|
-
"types": "lib/types/index.d.ts",
|
|
12
|
-
"exports": {
|
|
13
|
-
".": {
|
|
14
|
-
"types": "./lib/types/index.d.ts",
|
|
15
|
-
"default": "./lib/index.js"
|
|
16
|
-
},
|
|
17
|
-
"./startup": {
|
|
18
|
-
"types": "./lib/types/startup.d.ts",
|
|
19
|
-
"default": "./lib/startup.js"
|
|
20
|
-
},
|
|
21
|
-
"./invariant": {
|
|
22
|
-
"types": "./lib/types/invariant.d.ts",
|
|
23
|
-
"default": "./lib/invariant.js"
|
|
24
|
-
},
|
|
25
|
-
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
26
|
-
"./package.json": "./package.json",
|
|
27
|
-
"./agent-presets/*": "./agent-presets/*"
|
|
28
|
-
},
|
|
29
10
|
"files": [
|
|
30
|
-
"lib/index.js",
|
|
31
|
-
"lib/invariant.js",
|
|
32
|
-
"lib/startup.js",
|
|
33
11
|
"bin",
|
|
34
|
-
"
|
|
35
|
-
"agent-presets",
|
|
36
|
-
"lib/types/**/*.d.ts"
|
|
12
|
+
"README.md"
|
|
37
13
|
],
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"patch": "./cordis.patch.yml"
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
"dependencies": {
|
|
44
|
-
"@deepseek-ai/dsh": "^0.1.0-rc.7",
|
|
45
|
-
"@deepseek-ai/dsh-agent-instructions": "^0.1.0-rc.7",
|
|
46
|
-
"@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.7",
|
|
47
|
-
"@deepseek-ai/dsh-cmdline": "^0.1.0-rc.7",
|
|
48
|
-
"@deepseek-ai/dsh-code-runtime-worker-thread": "^0.1.0-rc.7",
|
|
49
|
-
"@deepseek-ai/dsh-command-compact": "^0.1.0-rc.7",
|
|
50
|
-
"@deepseek-ai/dsh-compaction-basic": "^0.1.0-rc.7",
|
|
51
|
-
"@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.0-rc.7",
|
|
52
|
-
"@deepseek-ai/dsh-lsp": "^0.1.0-rc.7",
|
|
53
|
-
"@deepseek-ai/dsh-lsp-stdio": "^0.1.0-rc.7",
|
|
54
|
-
"@deepseek-ai/dsh-persona": "^0.1.0-rc.7",
|
|
55
|
-
"@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.7",
|
|
56
|
-
"@deepseek-ai/dsh-skill-filesystem": "^0.1.0-rc.7",
|
|
57
|
-
"@deepseek-ai/dsh-terminal": "^0.1.0-rc.7",
|
|
58
|
-
"@deepseek-ai/dsh-terminal-bash": "^0.1.0-rc.7",
|
|
59
|
-
"@deepseek-ai/dsh-tool-ask-user": "^0.1.0-rc.7",
|
|
60
|
-
"@deepseek-ai/dsh-tool-bash": "^0.1.0-rc.7",
|
|
61
|
-
"@deepseek-ai/dsh-tool-fs": "^0.1.0-rc.7",
|
|
62
|
-
"@deepseek-ai/dsh-tool-fs-search": "^0.1.0-rc.7",
|
|
63
|
-
"@deepseek-ai/dsh-tool-goal": "^0.1.0-rc.7",
|
|
64
|
-
"@deepseek-ai/dsh-tool-jobs": "^0.1.0-rc.7",
|
|
65
|
-
"@deepseek-ai/dsh-tool-lsp": "^0.1.0-rc.7",
|
|
66
|
-
"@deepseek-ai/dsh-tool-pwsh": "^0.1.0-rc.7",
|
|
67
|
-
"@deepseek-ai/dsh-tool-ralph": "^0.1.0-rc.7",
|
|
68
|
-
"@deepseek-ai/dsh-tool-skill": "^0.1.0-rc.7",
|
|
69
|
-
"@deepseek-ai/dsh-tool-subagent": "^0.1.0-rc.7",
|
|
70
|
-
"@deepseek-ai/dsh-tool-subagent-control": "^0.1.0-rc.7",
|
|
71
|
-
"@deepseek-ai/dsh-tool-terminal": "^0.1.0-rc.7",
|
|
72
|
-
"@deepseek-ai/dsh-tool-todo": "^0.1.0-rc.7",
|
|
73
|
-
"@deepseek-ai/dsh-tool-web": "^0.1.0-rc.7",
|
|
74
|
-
"@deepseek-ai/dsh-tool-workflow": "^0.1.0-rc.7",
|
|
75
|
-
"@deepseek-ai/dsh-workflow-worker-thread": "^0.1.0-rc.7",
|
|
76
|
-
"@deepseek-ai/schemastery": "^3.18.1",
|
|
77
|
-
"commander": "^15.0.0",
|
|
78
|
-
"diff": "^9.0.0",
|
|
79
|
-
"string-width": "^8.2.2"
|
|
80
|
-
},
|
|
81
|
-
"peerDependencies": {
|
|
82
|
-
"@deepseek-ai/cordis": "^4.0.1",
|
|
83
|
-
"@deepseek-ai/cordis-plugin-loader": "^1.0.2",
|
|
84
|
-
"@deepseek-ai/dsh-agent": "^0.1.0-rc.7",
|
|
85
|
-
"@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.7",
|
|
86
|
-
"@deepseek-ai/dsh-commands": "^0.1.0-rc.7",
|
|
87
|
-
"@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7",
|
|
88
|
-
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.7",
|
|
89
|
-
"@deepseek-ai/dsh-llm": "^0.1.0-rc.7",
|
|
90
|
-
"@deepseek-ai/dsh-permission-presets": "^0.1.0-rc.7",
|
|
91
|
-
"@deepseek-ai/dsh-session": "^0.1.0-rc.7",
|
|
92
|
-
"@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7",
|
|
93
|
-
"@deepseek-ai/dsh-session-query": "^0.1.0-rc.7",
|
|
94
|
-
"@deepseek-ai/dsh-token-meter": "^0.1.0-rc.7",
|
|
95
|
-
"@deepseek-ai/dsh-tools": "^0.1.0-rc.7",
|
|
96
|
-
"@deepseek-ai/dsh-user-approval": "^0.1.0-rc.7",
|
|
97
|
-
"@deepseek-ai/dsh-user-questions": "^0.1.0-rc.7"
|
|
98
|
-
},
|
|
99
|
-
"devDependencies": {
|
|
100
|
-
"@changesets/cli": "^3.0.0",
|
|
101
|
-
"@deepseek-ai/cordis": "^4.0.1",
|
|
102
|
-
"@deepseek-ai/cordis-plugin-loader": "^1.0.2",
|
|
103
|
-
"@deepseek-ai/dsh-agent": "^0.1.0-rc.7",
|
|
104
|
-
"@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.7",
|
|
105
|
-
"@deepseek-ai/dsh-commands": "^0.1.0-rc.7",
|
|
106
|
-
"@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7",
|
|
107
|
-
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.7",
|
|
108
|
-
"@deepseek-ai/dsh-llm": "^0.1.0-rc.7",
|
|
109
|
-
"@deepseek-ai/dsh-permission-presets": "^0.1.0-rc.7",
|
|
110
|
-
"@deepseek-ai/dsh-session": "^0.1.0-rc.7",
|
|
111
|
-
"@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7",
|
|
112
|
-
"@deepseek-ai/dsh-session-query": "^0.1.0-rc.7",
|
|
113
|
-
"@deepseek-ai/dsh-token-meter": "^0.1.0-rc.7",
|
|
114
|
-
"@deepseek-ai/dsh-tools": "^0.1.0-rc.7",
|
|
115
|
-
"@deepseek-ai/dsh-user-approval": "^0.1.0-rc.7",
|
|
116
|
-
"@deepseek-ai/dsh-user-questions": "^0.1.0-rc.7",
|
|
117
|
-
"@types/node": "^24.0.0",
|
|
118
|
-
"execa": "^9.0.0",
|
|
119
|
-
"tsdown": "^0.15.0",
|
|
120
|
-
"tsx": "^4.20.0",
|
|
121
|
-
"typescript": "^5.9.0",
|
|
122
|
-
"vitest": "^4.0.0"
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=22.19"
|
|
123
16
|
},
|
|
124
17
|
"repository": {
|
|
125
18
|
"type": "git",
|
|
126
|
-
"url": "git+https://github.com/Blackman99/codsh.git"
|
|
19
|
+
"url": "git+https://github.com/Blackman99/codsh.git",
|
|
20
|
+
"directory": "packages/cli"
|
|
127
21
|
},
|
|
128
|
-
"homepage": "https://github.com/Blackman99/codsh#readme",
|
|
129
|
-
"bugs": "https://github.com/Blackman99/codsh/issues",
|
|
130
22
|
"keywords": [
|
|
131
23
|
"cli",
|
|
132
24
|
"coding-agent",
|
|
@@ -136,16 +28,6 @@
|
|
|
136
28
|
"ai",
|
|
137
29
|
"agent"
|
|
138
30
|
],
|
|
139
|
-
"
|
|
140
|
-
|
|
141
|
-
},
|
|
142
|
-
"scripts": {
|
|
143
|
-
"build": "tsdown && tsc -p tsconfig.build.json",
|
|
144
|
-
"typecheck": "tsc --noEmit",
|
|
145
|
-
"test": "vitest run",
|
|
146
|
-
"test:e2e": "pnpm run build && vitest run --config vitest.e2e.config.ts",
|
|
147
|
-
"dev": "node scripts/dev.mjs",
|
|
148
|
-
"sync:dsh": "node scripts/sync-dsh.mjs",
|
|
149
|
-
"release": "pnpm run build && changeset publish"
|
|
150
|
-
}
|
|
31
|
+
"homepage": "https://github.com/Blackman99/codsh#readme",
|
|
32
|
+
"bugs": "https://github.com/Blackman99/codsh/issues"
|
|
151
33
|
}
|
package/README.zh.md
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# codsh
|
|
2
|
-
|
|
3
|
-
> npm 包名:[`codsh-cli`](https://www.npmjs.com/package/codsh-cli) · 命令:`codsh`
|
|
4
|
-
|
|
5
|
-
[English](README.md) | 中文
|
|
6
|
-
|
|
7
|
-
一款汲取了当今主流 agent CLI 交互体验精髓的终端编码 agent,组合在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)插件运行时之上。codsh 是一个 dsh *bundle*:它携带交互式 TTY 界面与编码 agent preset,其下的一切——agent 循环、工具、会话、沙箱、模型适配器——都是 npm 上已发布的 dsh 包。
|
|
8
|
-
|
|
9
|
-
## 安装
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
npm install -g codsh-cli
|
|
13
|
-
codsh
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
首次运行会把本包注册进 `$DSH_HOME`(默认 `~/.dsh`)下的 dsh `code` profile 并安装自带的 `code-cli` agent preset;之后每次运行直接进入提示符。模型密钥从 `DEEPSEEK_API_KEY` 读取(环境变量或 `.env`)。
|
|
17
|
-
|
|
18
|
-
`codsh` 严格等价于 `dsh --profile code`——包装器只做一次性的 profile 注册。`codsh` 之后的参数直达应用:`codsh --resume <会话 id>`、`codsh --continue`、`codsh -p "一次性任务"`。
|
|
19
|
-
|
|
20
|
-
## 你会得到什么
|
|
21
|
-
|
|
22
|
-
- **会话是自己的空间**:codsh 进入备用屏幕,你的 shell 滚回历史原封不动、退出即恢复。transcript 在会话自有的缓冲里滚动——鼠标滚轮、PgUp/PgDn、Shift+↑/↓——输入框钉在底部从不移动;向上翻阅时视口会标注离尾部多远,新输出继续累积而不把你拽回去。每一帧以同步更新原子绘制;退出时向 shell 留下两行摘要(会话 id、用量、`--resume` 命令)。
|
|
23
|
-
- **接管键盘的输入框**:多行编辑(Alt-Enter)、跨会话历史,命令、参数与 `@` 文件提及(全工作区模糊搜索)的补全随输入自动打开。
|
|
24
|
-
- **流式渲染**:Markdown 带代码高亮与表格排版,推理模型的思考在 `✻ thinking` 下暗色显示,工具调用按 presenter 驱动的卡片渲染(含 diff),Ctrl-O 完整重印最近被截断的输出。
|
|
25
|
-
- **决定用选择**:审批、提问、`/model` 与 `/resume` 都是方向键组件;Shift-Tab 切换 plan 模式并为框着色。
|
|
26
|
-
- **会话流**:`/clear` 原地开新会话,`/resume` 从带标题和时间的会话列表里选,连按两次 Escape 召回上一条消息编辑,`!cmd` 在你自己的 shell 里运行并把结果注入为模型可见上下文——不花回合。
|
|
27
|
-
- **固定 prompt**:`/init` 起草 `AGENTS.md`;`$DSH_HOME/commands/` 或 `<工作区>/.dsh/commands/` 下的 Markdown 文件即成为斜杠命令,支持 `$ARGUMENTS` 模板。
|
|
28
|
-
- 状态行(模型、preset、权限、token、剩余上下文、分支)、终端标题跟随、有决定等待时的铃声,以及面向脚本的 `--print` 模式。
|
|
29
|
-
|
|
30
|
-
非 TTY 环境(管道、脚本)下同一界面降级为行读取器:选择变为键入回答、组件变为列表、不绘制任何东西。
|
|
31
|
-
|
|
32
|
-
## 开发
|
|
33
|
-
|
|
34
|
-
```sh
|
|
35
|
-
pnpm install
|
|
36
|
-
pnpm run dev # build → 同步进 .dev-home → 启动;秒级迭代
|
|
37
|
-
MOCK=markdown pnpm run dev # 无 key,对着 e2e mock 模型
|
|
38
|
-
pnpm run build # tsdown 运行时 bundle + tsc 声明文件,输出到 lib/
|
|
39
|
-
pnpm run typecheck
|
|
40
|
-
pnpm test # 单测(纯函数模块:editor、markdown、transcript……)
|
|
41
|
-
pnpm run test:e2e # 打包本仓库、注册进 dsh profile,然后经管道与真实 PTY
|
|
42
|
-
# 驱动 npm 安装的 dsh 可执行文件
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
`pnpm run dev` 在 `.dev-home` 维护一个仓库本地的 dsh home:首次运行对打包后的工作树做一次真实 profile 安装,之后每次只把新构建的 `lib/` 覆盖到 profile 里解包的本包上——改动秒级到达运行中的界面。`MOCK=<write|bash|slow|markdown|reasoning|echo|tall>` 换上 keyless e2e 模型、无 key 调 UI;参数透传(`pnpm run dev -- --resume <id>`);`INSPECT=1` 在应用进程上打开 Node inspector(`chrome://inspect` 或 VS Code attach)。逻辑问题优先用管道形态单步——`printf 'task\n/exit\n' | MOCK=echo pnpm run dev`——那里没有 raw mode 和重绘区域的干扰;在 TTY 上调试不要用 `console.*` 打点(会撕裂受管理区域),改写文件日志。
|
|
46
|
-
|
|
47
|
-
e2e 测试的是发布产物:`npm pack` 的输出装进真实 profile,由 npm 上的 dsh launcher 启动,配 keyless mock 模型。那里通过的就是用户装到的。
|
|
48
|
-
|
|
49
|
-
### 对着 dsh 源码调试
|
|
50
|
-
|
|
51
|
-
日常里 dsh 是普通的 npm 依赖。需要单步进 harness 代码时,把 [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) clone 到本仓库旁边并构建(`pnpm install && pnpm run build`),然后把要调试的包指向 checkout:
|
|
52
|
-
|
|
53
|
-
```jsonc
|
|
54
|
-
// package.json —— 调完删掉;npm 始终是默认
|
|
55
|
-
"pnpm": {
|
|
56
|
-
"overrides": {
|
|
57
|
-
"@deepseek-ai/dsh-agent-loop": "link:../deepseek-harness/packages/core/agent-loop"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
再执行 `pnpm install`。想进上游的改动以普通 PR 提交到 harness 仓库;本仓库绝不 fork 它。
|
|
63
|
-
|
|
64
|
-
### 跟随 dsh 发布版本
|
|
65
|
-
|
|
66
|
-
codsh 消费的是已发布的 `@deepseek-ai/dsh-*` npm 包,所以"与 dsh 同步"跟踪的是 harness 的**发布**,不是合并源码。三层机制让这件事全自动:
|
|
67
|
-
|
|
68
|
-
1. **发现**——[Renovate](renovate.json) 盯着 `@deepseek-ai/dsh-*`(及同步发布的 cordis 包)自动开依赖 PR;[夜间 sync 工作流](.github/workflows/sync-dsh.yml) 不依赖第三方服务也能做同样的事。
|
|
69
|
-
2. **升级**——`pnpm run sync:dsh` 把所有 `@deepseek-ai/dsh-*` 范围改写到最新发布版、刷新锁文件、写 changeset;`--check` 模式在存在新版本时以退出码 1 报告(夜间任务就靠它判断)。
|
|
70
|
-
3. **验证**——同一命令重新核对 `cordis.patch.yml`:每个被禁用/配置的插件 id 必须仍被已安装的 dsh bundle 声明,每个 insert 的包必须可解析;然后跑 typecheck/build/单测(加 `--e2e` 会真正启动打补丁后的 bundle),CI 在生成的 PR 上再全部跑一遍。
|
|
71
|
-
|
|
72
|
-
因为所有 dsh 包都是预发布版本(`0.1.0-rc.N`),普通 semver 范围**不会**跨版本浮动——同步命令才是事实来源,`pnpm update` 不是。
|
|
73
|
-
|
|
74
|
-
## 许可
|
|
75
|
-
|
|
76
|
-
MIT
|