@hncode/hncode 0.4.2 → 0.5.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 +1 -15
- package/README_CN.md +1 -15
- package/bin/hncode +22 -9
- package/package.json +3 -2
- package/src/agent.js +145 -33
- package/src/bootstrap.js +56 -0
- package/src/btw-panel.js +224 -0
- package/src/cache.js +3 -2
- package/src/cell-buffer.js +173 -0
- package/src/ci.js +4 -1
- package/src/clipboard.js +202 -43
- package/src/colors.js +175 -30
- package/src/config.js +376 -34
- package/src/context-bar.js +237 -0
- package/src/doctor.js +320 -0
- package/src/experiments.js +122 -0
- package/src/file-history.js +112 -0
- package/src/file-tree.js +255 -0
- package/src/flush-tick.js +56 -0
- package/src/fork.js +44 -0
- package/src/fx.js +148 -0
- package/src/index.js +123 -11
- package/src/keybindings.js +229 -0
- package/src/llm.js +355 -34
- package/src/lsp.js +401 -0
- package/src/notebook.js +232 -0
- package/src/output-styles.js +183 -0
- package/src/patch.js +248 -0
- package/src/permissions.js +130 -1
- package/src/plan.js +3 -2
- package/src/plugin.js +611 -58
- package/src/prompt-presets.js +1 -1
- package/src/registry-browser.js +31 -13
- package/src/remote.js +20 -2
- package/src/rollout.js +151 -0
- package/src/row-cache.js +143 -0
- package/src/schedule.js +294 -0
- package/src/session-approvals.js +86 -0
- package/src/session.js +178 -8
- package/src/shell-safety.js +473 -0
- package/src/side-thread.js +240 -0
- package/src/skills.js +27 -0
- package/src/stream-buffer.js +350 -0
- package/src/subagent-control.js +160 -0
- package/src/teleport.js +260 -0
- package/src/term-caps.js +411 -0
- package/src/term.js +283 -8
- package/src/tools/agent-control.js +98 -0
- package/src/tools/agent-swarm.js +11 -2
- package/src/tools/agent.js +35 -1
- package/src/tools/diagnostics.js +175 -0
- package/src/tools/edit.js +25 -10
- package/src/tools/grep.js +62 -20
- package/src/tools/ignore.js +38 -14
- package/src/tools/index.js +10 -0
- package/src/tools/notebook.js +113 -0
- package/src/tools/read-media-file.js +10 -3
- package/src/tools/shell.js +34 -6
- package/src/tui.js +5219 -792
- package/src/web-public/app.js +7 -0
package/src/tools/shell.js
CHANGED
|
@@ -15,10 +15,26 @@
|
|
|
15
15
|
// on which one was found.
|
|
16
16
|
|
|
17
17
|
import cp from 'node:child_process';
|
|
18
|
+
import fs from 'node:fs';
|
|
18
19
|
|
|
19
20
|
// The two PowerShell families, by the name they are invoked as.
|
|
20
21
|
export const SHELL_CANDIDATES = ['pwsh', 'powershell'];
|
|
21
22
|
|
|
23
|
+
// Last-resort Windows fallback. A Windows box always has cmd.exe (%COMSPEC%),
|
|
24
|
+
// so when neither PowerShell exists the Bash tool must still run SOMETHING
|
|
25
|
+
// rather than failing outright. `cmd` is not a PowerShell, so the syntax
|
|
26
|
+
// guidance and the spawn args differ (see cmdSpawnArgs).
|
|
27
|
+
export function findCmdExe() {
|
|
28
|
+
const fromEnv = process.env.COMSPEC || process.env.ComSpec;
|
|
29
|
+
if (fromEnv) {
|
|
30
|
+
try { if (fs.existsSync(fromEnv)) return fromEnv; } catch { /* fall through to the PATH probe */ }
|
|
31
|
+
}
|
|
32
|
+
if (process.platform === 'win32') {
|
|
33
|
+
return whichSync('cmd') || whichSync('cmd.exe') || 'cmd.exe';
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
22
38
|
/**
|
|
23
39
|
* Resolve an executable name through PATH without spawning it.
|
|
24
40
|
*
|
|
@@ -42,13 +58,15 @@ function whichSync(name) {
|
|
|
42
58
|
}
|
|
43
59
|
|
|
44
60
|
/**
|
|
45
|
-
* Find a usable
|
|
46
|
-
* Returns { path, name, edition } or null
|
|
61
|
+
* Find a usable shell: pwsh, then the built-in powershell, then (on Windows)
|
|
62
|
+
* cmd.exe as a last resort. Returns { path, name, edition } or null.
|
|
47
63
|
*
|
|
48
64
|
* `edition` drives syntax guidance — see the header. It is inferred from the NAME
|
|
49
65
|
* rather than by running the binary (a spawn per probe is not worth it, and
|
|
50
66
|
* PowerShell 6, also named `pwsh`, is EOL and not a realistic target, so `pwsh`
|
|
51
|
-
* safely implies 7+).
|
|
67
|
+
* safely implies 7+). `edition: 'cmd'` means neither PowerShell exists and the
|
|
68
|
+
* Bash tool is running through cmd.exe: it still works, but the command syntax is
|
|
69
|
+
* cmd's, not PowerShell's.
|
|
52
70
|
*/
|
|
53
71
|
export function detectShell() {
|
|
54
72
|
for (const name of SHELL_CANDIDATES) {
|
|
@@ -57,6 +75,9 @@ export function detectShell() {
|
|
|
57
75
|
return { path, name, edition: name === 'pwsh' ? 'core' : 'desktop' };
|
|
58
76
|
}
|
|
59
77
|
}
|
|
78
|
+
// No PowerShell at all: on Windows, guarantee cmd.exe so the tool is not dead.
|
|
79
|
+
const cmd = findCmdExe();
|
|
80
|
+
if (cmd) return { path: cmd, name: 'cmd', edition: 'cmd' };
|
|
60
81
|
return null;
|
|
61
82
|
}
|
|
62
83
|
|
|
@@ -91,16 +112,23 @@ export function resetShellCache() {
|
|
|
91
112
|
* on every single tool call, and `-NonInteractive` stops a command that prompts
|
|
92
113
|
* from hanging the tool forever with no way to answer.
|
|
93
114
|
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
115
|
+
* When neither PowerShell exists, `edition === 'cmd'` selects cmd.exe args instead
|
|
116
|
+
* (see detectShell). Throws a message naming the fix only when no shell at all
|
|
117
|
+
* was found, instead of letting the caller hit a bare ENOENT.
|
|
96
118
|
*/
|
|
97
119
|
export function shellSpawnArgs(command) {
|
|
98
120
|
const shell = getShell();
|
|
99
121
|
if (!shell) {
|
|
100
122
|
throw new Error(
|
|
101
|
-
'No
|
|
123
|
+
'No shell found (tried pwsh, powershell, and cmd.exe). '
|
|
102
124
|
+ 'Install PowerShell 7+ or add it to PATH, then retry.',
|
|
103
125
|
);
|
|
104
126
|
}
|
|
127
|
+
if (shell.edition === 'cmd') {
|
|
128
|
+
// cmd.exe: `/d` skips AutoRun commands, `/s` makes `/c` quoting behave
|
|
129
|
+
// predictably. The command is passed as ONE argv element, so Node does the
|
|
130
|
+
// quoting and we do not wrap it ourselves.
|
|
131
|
+
return { bin: shell.path, args: ['/d', '/s', '/c', command], shell };
|
|
132
|
+
}
|
|
105
133
|
return { bin: shell.path, args: ['-NoProfile', '-NonInteractive', '-Command', command], shell };
|
|
106
134
|
}
|