@link-assistant/hive-mind 1.13.0 → 1.14.1

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 CHANGED
@@ -1,5 +1,32 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 1.14.1
4
+
5
+ ### Patch Changes
6
+
7
+ - b139b00: fix: detect agent tool errors during streaming for reliable failure detection (Issue #1201)
8
+
9
+ Previously, agent tool errors (`"type": "error"`) could be missed when the post-hoc
10
+ detection function failed to parse NDJSON lines that were concatenated without newline
11
+ delimiters. Now errors are detected inline during stream processing, ensuring
12
+ `"type": "error"` events always trigger a failure exit regardless of output buffering.
13
+
14
+ ## 1.14.0
15
+
16
+ ### Minor Changes
17
+
18
+ - 3a48254: Add configurable experiments/examples folder paths with ability to disable
19
+
20
+ New CLI options for both `solve` and `hive` commands:
21
+ - `--prompt-experiments-folder <path>`: Path to experiments folder used in system prompt. Set to empty string to disable experiments folder prompt. Default: `./experiments`
22
+ - `--prompt-examples-folder <path>`: Path to examples folder used in system prompt. Set to empty string to disable examples folder prompt. Default: `./examples`
23
+
24
+ Features:
25
+ - Backwards compatible: defaults to `./experiments` and `./examples` as before
26
+ - Custom paths: Specify custom folder paths for experiments and examples
27
+ - Disable functionality: Set to empty string (`''`) to disable the experiments/examples prompt section entirely
28
+ - Works with all AI tools: claude, opencode, codex, and agent
29
+
3
30
  ## 1.13.0
4
31
 
5
32
  ### Minor Changes
package/README.md CHANGED
@@ -106,7 +106,40 @@ bun install -g @link-assistant/hive-mind
106
106
  npm install -g @link-assistant/hive-mind
107
107
  ```
108
108
 
109
- ### Docker Installation
109
+ ### Installing Docker
110
+
111
+ If you don't have Docker installed yet, follow these steps to install Docker Engine on Ubuntu:
112
+
113
+ ```bash
114
+ # Install prerequisites
115
+ sudo apt update
116
+ sudo apt install ca-certificates curl
117
+
118
+ # Add Docker's official GPG key
119
+ sudo install -m 0755 -d /etc/apt/keyrings
120
+ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
121
+ sudo chmod a+r /etc/apt/keyrings/docker.asc
122
+
123
+ # Add Docker repository
124
+ sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
125
+ Types: deb
126
+ URIs: https://download.docker.com/linux/ubuntu
127
+ Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
128
+ Components: stable
129
+ Signed-By: /etc/apt/keyrings/docker.asc
130
+ EOF
131
+
132
+ # Install Docker
133
+ sudo apt update
134
+ sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
135
+
136
+ # Verify installation
137
+ sudo docker run hello-world
138
+ ```
139
+
140
+ **For other operating systems** or detailed instructions, see the [official Docker documentation](https://docs.docker.com/engine/install/).
141
+
142
+ ### Using Docker
110
143
 
111
144
  Run the Hive Mind using Docker for safer local installation - no manual setup required:
112
145
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "1.13.0",
3
+ "version": "1.14.1",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
package/src/agent.lib.mjs CHANGED
@@ -418,6 +418,10 @@ export const executeAgentCommand = async params => {
418
418
  let limitResetTime = null;
419
419
  let lastMessage = '';
420
420
  let fullOutput = ''; // Collect all output for pricing calculation and error detection
421
+ // Issue #1201: Track error events detected during streaming for reliable error detection
422
+ // Post-hoc detection on fullOutput can miss errors if NDJSON lines get concatenated without newlines
423
+ let streamingErrorDetected = false;
424
+ let streamingErrorMessage = null;
421
425
 
422
426
  for await (const chunk of execCommand.stream()) {
423
427
  if (chunk.type === 'stdout') {
@@ -437,6 +441,12 @@ export const executeAgentCommand = async params => {
437
441
  sessionId = data.sessionID;
438
442
  await log(`📌 Session ID: ${sessionId}`);
439
443
  }
444
+ // Issue #1201: Detect error events during streaming for reliable detection
445
+ if (data.type === 'error' || data.type === 'step_error') {
446
+ streamingErrorDetected = true;
447
+ streamingErrorMessage = data.message || data.error || line.substring(0, 100);
448
+ await log(`⚠️ Error event detected in stream: ${streamingErrorMessage}`, { level: 'warning' });
449
+ }
440
450
  } catch {
441
451
  // Not JSON - log as plain text
442
452
  await log(line);
@@ -463,6 +473,12 @@ export const executeAgentCommand = async params => {
463
473
  sessionId = stderrData.sessionID;
464
474
  await log(`📌 Session ID: ${sessionId}`);
465
475
  }
476
+ // Issue #1201: Detect error events during streaming (stderr) for reliable detection
477
+ if (stderrData.type === 'error' || stderrData.type === 'step_error') {
478
+ streamingErrorDetected = true;
479
+ streamingErrorMessage = stderrData.message || stderrData.error || stderrLine.substring(0, 100);
480
+ await log(`⚠️ Error event detected in stream: ${streamingErrorMessage}`, { level: 'warning' });
481
+ }
466
482
  } catch {
467
483
  // Not JSON - log as plain text
468
484
  await log(stderrLine);
@@ -496,7 +512,7 @@ export const executeAgentCommand = async params => {
496
512
 
497
513
  // Check for explicit error message types from agent
498
514
  if (msg.type === 'error' || msg.type === 'step_error') {
499
- return { detected: true, type: 'AgentError', match: msg.message || line.substring(0, 100) };
515
+ return { detected: true, type: 'AgentError', match: msg.message || msg.error || line.substring(0, 100) };
500
516
  }
501
517
  } catch {
502
518
  // Not JSON - ignore for error detection
@@ -510,6 +526,15 @@ export const executeAgentCommand = async params => {
510
526
  // Only check for JSON error messages, not pattern matching in output
511
527
  const outputError = detectAgentErrors(fullOutput);
512
528
 
529
+ // Issue #1201: Use streaming detection as primary, post-hoc as fallback
530
+ // Streaming detection is more reliable because it parses each JSON line as it arrives,
531
+ // avoiding issues where NDJSON lines get concatenated without newline delimiters in fullOutput
532
+ if (!outputError.detected && streamingErrorDetected) {
533
+ outputError.detected = true;
534
+ outputError.type = 'AgentError';
535
+ outputError.match = streamingErrorMessage;
536
+ }
537
+
513
538
  if (exitCode !== 0 || outputError.detected) {
514
539
  // Build JSON error structure for consistent error reporting
515
540
  const errorInfo = {
@@ -545,7 +570,7 @@ export const executeAgentCommand = async params => {
545
570
  await log(line, { level: 'warning' });
546
571
  }
547
572
  } else if (outputError.detected) {
548
- // Explicit JSON error message from agent
573
+ // Explicit JSON error message from agent (Issue #1201: includes streaming-detected errors)
549
574
  errorInfo.message = `Agent reported error: ${outputError.match}`;
550
575
  await log(`\n\n❌ ${errorInfo.message}`, { level: 'error' });
551
576
  } else {
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { getArchitectureCareSubPrompt } from './architecture-care.prompts.lib.mjs';
7
+ import { getExperimentsExamplesSubPrompt } from './experiments-examples.prompts.lib.mjs';
7
8
 
8
9
  /**
9
10
  * Build the user prompt for Agent
@@ -137,9 +138,7 @@ ${workspaceInstructions}General guidelines.
137
138
  - When CI is failing, make sure you download the logs locally and carefully investigate them.
138
139
  - When a code or log file has more than 1500 lines, read it in chunks of 1500 lines.
139
140
  - When facing a complex problem, do as much tracing as possible and turn on all verbose modes.
140
- - When you create debug, test, or example/experiment scripts for fixing, always keep them in an examples and/or experiments folders so you can reuse them later.
141
- - When testing your assumptions, use the experiment scripts, and add it to experiments folder.
142
- - When your experiments can show real world use case of the software, add it to examples folder.
141
+ ${getExperimentsExamplesSubPrompt(argv)}
143
142
  - When you face something extremely hard, use divide and conquer — it always helps.
144
143
 
145
144
  Initial research.
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { getArchitectureCareSubPrompt } from './architecture-care.prompts.lib.mjs';
7
+ import { getExperimentsExamplesSubPrompt } from './experiments-examples.prompts.lib.mjs';
7
8
 
8
9
  /**
9
10
  * Build the user prompt for Claude
@@ -163,9 +164,7 @@ ${workspaceInstructions}General guidelines.
163
164
  Note: If user says "failing" but tools show "passing", this might indicate stale data - consider downloading fresh logs and checking timestamps to resolve the discrepancy.
164
165
  - When a code or log file has more than 1500 lines, read it in chunks of 1500 lines.
165
166
  - When facing a complex problem, do as much tracing as possible and turn on all verbose modes.
166
- - When you create debug, test, or example/experiment scripts for fixing, always keep them in an examples and/or experiments folders so you can reuse them later.
167
- - When testing your assumptions, use the experiment scripts, and add it to experiments folder.
168
- - When your experiments can show real world use case of the software, add it to examples folder.
167
+ ${getExperimentsExamplesSubPrompt(argv)}
169
168
  - When you face something extremely hard, use divide and conquer — it always helps.
170
169
 
171
170
  Initial research.
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { getArchitectureCareSubPrompt } from './architecture-care.prompts.lib.mjs';
7
+ import { getExperimentsExamplesSubPrompt } from './experiments-examples.prompts.lib.mjs';
7
8
 
8
9
  /**
9
10
  * Build the user prompt for Codex
@@ -144,9 +145,7 @@ ${workspaceInstructions}General guidelines.
144
145
  Note: If user says "failing" but tools show "passing", this might indicate stale data - consider downloading fresh logs and checking timestamps to resolve the discrepancy.
145
146
  - When a code or log file has more than 1500 lines, read it in chunks of 1500 lines.
146
147
  - When facing a complex problem, do as much tracing as possible and turn on all verbose modes.
147
- - When you create debug, test, or example/experiment scripts for fixing, always keep them in an examples and/or experiments folders so you can reuse them later.
148
- - When testing your assumptions, use the experiment scripts, and add it to experiments folder.
149
- - When your experiments can show real world use case of the software, add it to examples folder.
148
+ ${getExperimentsExamplesSubPrompt(argv)}
150
149
  - When you face something extremely hard, use divide and conquer — it always helps.
151
150
 
152
151
  Initial research.
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Experiments and examples folder prompts module
3
+ * Handles building configurable prompts for experiments/examples folders
4
+ *
5
+ * @see https://github.com/link-assistant/hive-mind/issues/1199
6
+ */
7
+
8
+ /**
9
+ * Build the experiments/examples sub-prompt based on configuration
10
+ * @param {Object} argv - Command line arguments
11
+ * @param {string} argv.promptExperimentsFolder - Path to experiments folder (empty string to disable)
12
+ * @param {string} argv.promptExamplesFolder - Path to examples folder (empty string to disable)
13
+ * @returns {string} The formatted sub-prompt for experiments/examples folders
14
+ */
15
+ export const getExperimentsExamplesSubPrompt = argv => {
16
+ const experimentsFolder = argv?.promptExperimentsFolder ?? './experiments';
17
+ const examplesFolder = argv?.promptExamplesFolder ?? './examples';
18
+
19
+ // If both are disabled, return empty string
20
+ if (!experimentsFolder && !examplesFolder) {
21
+ return '';
22
+ }
23
+
24
+ const lines = [];
25
+
26
+ // Both folders are enabled (with their respective paths)
27
+ if (experimentsFolder && examplesFolder) {
28
+ lines.push(` - When you create debug, test, or example/experiment scripts for fixing, always keep them in an ${examplesFolder} and/or ${experimentsFolder} folders so you can reuse them later.`);
29
+ lines.push(` - When testing your assumptions, use the experiment scripts, and add it to ${experimentsFolder} folder.`);
30
+ lines.push(` - When your experiments can show real world use case of the software, add it to ${examplesFolder} folder.`);
31
+ }
32
+ // Only experiments folder is enabled
33
+ else if (experimentsFolder) {
34
+ lines.push(` - When you create debug or test scripts for fixing, always keep them in ${experimentsFolder} folder so you can reuse them later.`);
35
+ lines.push(` - When testing your assumptions, use the experiment scripts, and add it to ${experimentsFolder} folder.`);
36
+ }
37
+ // Only examples folder is enabled
38
+ else if (examplesFolder) {
39
+ lines.push(` - When you create example scripts that show real world use cases, keep them in ${examplesFolder} folder.`);
40
+ lines.push(` - When your experiments can show real world use case of the software, add it to ${examplesFolder} folder.`);
41
+ }
42
+
43
+ return lines.join('\n');
44
+ };
45
+
46
+ export default {
47
+ getExperimentsExamplesSubPrompt,
48
+ };
@@ -301,6 +301,16 @@ export const createYargsConfig = yargsInstance => {
301
301
  description: 'Include prompt to check related/sibling pull requests when studying related work. Enabled by default, use --no-prompt-check-sibling-pull-requests to disable.',
302
302
  default: true,
303
303
  })
304
+ .option('prompt-experiments-folder', {
305
+ type: 'string',
306
+ description: 'Path to experiments folder used in system prompt. Set to empty string to disable experiments folder prompt. Default: ./experiments',
307
+ default: './experiments',
308
+ })
309
+ .option('prompt-examples-folder', {
310
+ type: 'string',
311
+ description: 'Path to examples folder used in system prompt. Set to empty string to disable examples folder prompt. Default: ./examples',
312
+ default: './examples',
313
+ })
304
314
  .option('prompt-architecture-care', {
305
315
  type: 'boolean',
306
316
  description: '[EXPERIMENTAL] Include guidance for managing REQUIREMENTS.md and ARCHITECTURE.md files. When enabled, agents will update these documentation files when changes affect requirements or architecture.',
package/src/hive.mjs CHANGED
@@ -770,6 +770,8 @@ if (isDirectExecution) {
770
770
  if (argv.promptIssueReporting) args.push('--prompt-issue-reporting');
771
771
  if (argv.promptCaseStudies) args.push('--prompt-case-studies');
772
772
  if (argv.promptPlaywrightMcp !== undefined) args.push(argv.promptPlaywrightMcp ? '--prompt-playwright-mcp' : '--no-prompt-playwright-mcp');
773
+ if (argv.promptExperimentsFolder !== undefined) args.push('--prompt-experiments-folder', argv.promptExperimentsFolder);
774
+ if (argv.promptExamplesFolder !== undefined) args.push('--prompt-examples-folder', argv.promptExamplesFolder);
773
775
  if (argv.executeToolWithBun) args.push('--execute-tool-with-bun');
774
776
  if (argv.autoMerge) args.push('--auto-merge');
775
777
  if (argv.autoRestartUntilMergable) args.push('--auto-restart-until-mergable');
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { getArchitectureCareSubPrompt } from './architecture-care.prompts.lib.mjs';
7
+ import { getExperimentsExamplesSubPrompt } from './experiments-examples.prompts.lib.mjs';
7
8
 
8
9
  /**
9
10
  * Build the user prompt for OpenCode
@@ -139,9 +140,7 @@ General guidelines.
139
140
  - When CI is failing, make sure you download the logs locally and carefully investigate them.
140
141
  - When a code or log file has more than 1500 lines, read it in chunks of 1500 lines.
141
142
  - When facing a complex problem, do as much tracing as possible and turn on all verbose modes.
142
- - When you create debug, test, or example/experiment scripts for fixing, always keep them in an examples and/or experiments folders so you can reuse them later.
143
- - When testing your assumptions, use the experiment scripts, and add it to experiments folder.
144
- - When your experiments can show real world use case of the software, add it to examples folder.
143
+ ${getExperimentsExamplesSubPrompt(argv)}
145
144
  - When you face something extremely hard, use divide and conquer — it always helps.
146
145
  ${workspaceInstructions}
147
146
  Initial research.
@@ -358,6 +358,16 @@ export const createYargsConfig = yargsInstance => {
358
358
  description: 'Include prompt to check related/sibling pull requests when studying related work. Enabled by default, use --no-prompt-check-sibling-pull-requests to disable.',
359
359
  default: true,
360
360
  })
361
+ .option('prompt-experiments-folder', {
362
+ type: 'string',
363
+ description: 'Path to experiments folder used in system prompt. Set to empty string to disable experiments folder prompt. Default: ./experiments',
364
+ default: './experiments',
365
+ })
366
+ .option('prompt-examples-folder', {
367
+ type: 'string',
368
+ description: 'Path to examples folder used in system prompt. Set to empty string to disable examples folder prompt. Default: ./examples',
369
+ default: './examples',
370
+ })
361
371
  .option('playwright-mcp-auto-cleanup', {
362
372
  type: 'boolean',
363
373
  description: 'Automatically remove .playwright-mcp/ folder before checking for uncommitted changes. This prevents browser automation artifacts from triggering auto-restart. Use --no-playwright-mcp-auto-cleanup to keep the folder for debugging.',