@hncode/hncode 0.5.1 → 0.5.4

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.
Files changed (60) hide show
  1. package/bin/install.cjs +24 -44
  2. package/bin/preinstall.cjs +0 -14
  3. package/package.json +2 -2
  4. package/src/agent-task.js +12 -1
  5. package/src/agent.js +279 -48
  6. package/src/cache.js +175 -130
  7. package/src/cell-buffer.js +5 -0
  8. package/src/clipboard.js +111 -8
  9. package/src/context-bar.js +46 -5
  10. package/src/doctor.js +7 -2
  11. package/src/git.js +35 -4
  12. package/src/index.js +29 -5
  13. package/src/keybindings.js +25 -3
  14. package/src/llm.js +60 -6
  15. package/src/mcp.js +419 -384
  16. package/src/permissions.js +29 -7
  17. package/src/plugin.js +95 -10
  18. package/src/registry-browser.js +21 -6
  19. package/src/remote.js +307 -289
  20. package/src/session-core.js +203 -0
  21. package/src/session-host.js +213 -0
  22. package/src/session-view.js +110 -0
  23. package/src/settings-schema.js +12 -9
  24. package/src/shell-safety.js +610 -473
  25. package/src/swarm-progress.js +348 -293
  26. package/src/tasks-browser.js +4 -1
  27. package/src/team/constants.js +20 -0
  28. package/src/team/context.js +89 -0
  29. package/src/team/mailbox.js +216 -0
  30. package/src/team/permission.js +121 -0
  31. package/src/team/protocol.js +167 -0
  32. package/src/team/runner.js +462 -0
  33. package/src/team/spawn.js +305 -0
  34. package/src/team/store.js +172 -0
  35. package/src/team/tasks.js +177 -0
  36. package/src/team/team.js +346 -0
  37. package/src/team-panel.js +624 -0
  38. package/src/term-caps.js +457 -410
  39. package/src/term.js +162 -19
  40. package/src/tool-result.js +70 -7
  41. package/src/tools/agent-swarm.js +114 -11
  42. package/src/tools/agent.js +464 -386
  43. package/src/tools/bash.js +53 -14
  44. package/src/tools/diagnostics.js +13 -0
  45. package/src/tools/edit.js +428 -50
  46. package/src/tools/git.js +15 -3
  47. package/src/tools/glob.js +5 -3
  48. package/src/tools/grep.js +19 -5
  49. package/src/tools/ignore.js +17 -3
  50. package/src/tools/index.js +19 -3
  51. package/src/tools/read.js +2 -1
  52. package/src/tools/shell.js +145 -134
  53. package/src/tools/tasks.js +214 -141
  54. package/src/tools/team.js +411 -0
  55. package/src/tools/utils.js +12 -3
  56. package/src/tools/web-search.js +53 -40
  57. package/src/tui.js +7496 -5366
  58. package/src/update.js +320 -115
  59. package/src/web-daemon.js +27 -4
  60. package/src/web-live.js +250 -0
package/bin/install.cjs CHANGED
@@ -30,35 +30,27 @@ for (const dir of dirs) {
30
30
 
31
31
  // Check if config file exists
32
32
  if (!fs.existsSync(configFile)) {
33
- const defaultConfig = `# hncode Configuration
34
- # Generated by hncode install script
33
+ const defaultConfig = `# hncode configuration
34
+ #
35
+ # Nothing here is required: every value has a default, and the same keys can be set with
36
+ # HNCODE_* environment variables or from /settings once hncode is running.
37
+ #
38
+ # Model and provider are deliberately left out. Naming one here starts hncode on a model
39
+ # you may have no key for, and the first turn fails against that provider instead of
40
+ # asking you to choose. Set up a provider with /provider, then pick a model with /model.
35
41
 
36
- # Default model (change this to your preferred model)
37
- default_model = "gpt-4o-mini"
38
-
39
- # Optional: Add providers directly here
40
- # Uncomment and configure as needed:
41
- #
42
42
  # [providers.openai]
43
43
  # base_url = "https://api.openai.com/v1"
44
- # api_key = "your-api-key-here"
44
+ # api_key = "sk-..." # or set HNCODE_API_KEY
45
45
  # protocol = "openai"
46
-
47
- # Or use environment variables:
48
- # HNCODE_API_KEY="your-key"
49
- # HNCODE_PROVIDER="openai"
50
- # HNCODE_MODEL="gpt-4o-mini"
51
-
52
46
  `;
53
47
 
54
48
  fs.writeFileSync(configFile, defaultConfig);
55
49
  console.log(`\n✅ Created default configuration at: ${configFile}`);
56
50
  console.log('\n💡 Next steps:');
57
- console.log(' 1. Edit ~/.hncode/config.toml with your API key');
58
- console.log(' 2. Or set environment variables:');
59
- console.log(' export HNCODE_API_KEY="your-key"');
60
- console.log(' export HNCODE_PROVIDER="openai"');
61
- console.log(' 3. Run "hncode" to start!');
51
+ console.log(' 1. Start hncode and run /provider to add an API key');
52
+ console.log(' 2. Then /model to pick one');
53
+ console.log(' Both write to the config above, so there is nothing to edit by hand.');
62
54
  } else {
63
55
  console.log(`\nℹ️ Configuration already exists at: ${configFile}`);
64
56
  console.log(' Run "hncode init" to regenerate or edit manually.');
@@ -66,30 +58,18 @@ default_model = "gpt-4o-mini"
66
58
 
67
59
  console.log('\n✨ hncode is ready to use!');
68
60
 
69
- // Try to refresh environment automatically
70
- try {
71
- const platform = os.platform();
72
-
73
- if (platform === 'win32') {
74
- // Windows: Use PowerShell to refresh environment
75
- const { execSync } = require('child_process');
76
- try {
77
- execSync('$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User");', { stdio: 'pipe' });
78
- console.log('✓ Environment refreshed automatically (PowerShell)');
79
- } catch (e) {
80
- console.log('ℹ️ To refresh environment in PowerShell:');
81
- console.log(' . "$env:LOCALAPPDATA\\npm\\npm.cmd"');
82
- console.log(' Or simply close and reopen your terminal');
83
- }
84
- } else {
85
- // Unix-like systems
86
- console.log('ℹ️ Please run one of these to refresh environment:');
87
- console.log(' source ~/.zshrc # For Zsh');
88
- console.log(' source ~/.bashrc # For Bash');
89
- console.log(' Or simply close and reopen your terminal');
90
- }
91
- } catch (err) {
92
- console.log('ℹ️ Note: You may need to restart your terminal');
61
+ // Tell the user how to pick up the new command.
62
+ //
63
+ // This used to run PowerShell to prepend the npm global path, and print "Environment
64
+ // refreshed automatically". That cannot work: `execSync` starts a CHILD shell, so the
65
+ // `$env:Path` it sets dies with that process. The claim is gone; the note below is true.
66
+ if (os.platform() === 'win32') {
67
+ console.log('ℹ️ If "hncode" is not found, open a new terminal (the PATH is updated at');
68
+ console.log(' login), or run this in the current one:');
69
+ console.log(' $env:Path = [System.Environment]::GetEnvironmentVariable("Path","User") + ";" + $env:Path');
70
+ } else {
71
+ console.log('ℹ️ If "hncode" is not found, open a new terminal, or re-read your shell');
72
+ console.log(' configuration: source ~/.zshrc (or ~/.bashrc)');
93
73
  }
94
74
 
95
75
  console.log('');
@@ -25,18 +25,4 @@ if (major < 20) {
25
25
  const platform = os.platform();
26
26
  console.log(`✓ Platform: ${platform}`);
27
27
 
28
- // Check if already installed globally
29
- try {
30
- const { execSync } = require('child_process');
31
- const npm = execSync('npm list -g hncode 2>&1').toString();
32
- if (npm.includes('hncode')) {
33
- console.log('ℹ️ hncode is already installed globally');
34
- console.log(' Run "npm uninstall -g hncode" to reinstall.\n');
35
- } else {
36
- console.log('✓ Not installed globally yet\n');
37
- }
38
- } catch (e) {
39
- console.log('✓ Not installed globally yet\n');
40
- }
41
-
42
28
  console.log('✅ Environment check passed!\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hncode/hncode",
3
- "version": "0.5.1",
3
+ "version": "0.5.4",
4
4
  "description": "hncode — A cyan-blue TUI AI coding agent with zero runtime dependencies.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -20,7 +20,7 @@
20
20
  "install": "node bin/install.cjs",
21
21
  "i18n": "node tools/sync-i18n.mjs",
22
22
  "i18n:check": "node tools/sync-i18n.mjs --check",
23
- "test": "node --test"
23
+ "test": "node --test \"test/**/*.test.mjs\""
24
24
  },
25
25
  "engines": {
26
26
  "node": ">=20"
package/src/agent-task.js CHANGED
@@ -76,7 +76,10 @@ function store(ctx) {
76
76
  */
77
77
  export function createTask(ctx, kind, options = {}) {
78
78
  const tasks = store(ctx);
79
- const prefix = kind === 'process' ? 'bash' : kind === 'agent' ? 'agent' : 'question';
79
+ // A teammate is its own kind rather than falling through to 'question': the id prefix is
80
+ // what a reader of a task list uses to tell at a glance what kind of work it is.
81
+ const PREFIX = { process: 'bash', agent: 'agent', teammate: 'mate' };
82
+ const prefix = PREFIX[kind] || 'question';
80
83
  const task = {
81
84
  taskId: newTaskId(prefix),
82
85
  kind,
@@ -101,10 +104,18 @@ export function createTask(ctx, kind, options = {}) {
101
104
  task.subagentType = options.subagentType;
102
105
  task.model = options.model;
103
106
  task.thinkingEffort = options.thinkingEffort;
107
+ } else if (kind === 'teammate') {
108
+ task.teamName = options.teamName;
109
+ task.memberName = options.memberName;
110
+ task.agentId = options.agentId;
104
111
  } else if (kind === 'question') {
105
112
  task.questionCount = options.questionCount || 0;
106
113
  task.toolCallId = options.toolCallId;
107
114
  }
115
+ // WHICH TASK THIS ONE BELONGS TO. A swarm's subagents are tasks of their own so /tasks can show
116
+ // what each is doing, and this is what groups them under the swarm that launched them. Absent
117
+ // for a top-level task, which is the common case.
118
+ if (options.parentTaskId) task.parentTaskId = String(options.parentTaskId);
108
119
  // Every task exposes its buffered output through `output`. The chunks are
109
120
  // stored raw and decoded lazily:
110
121
  // * a process appends Buffer chunks -> decode as UTF-8