mindforge-sdk 11.8.0 → 11.9.5

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 CHANGED
@@ -1,17 +1,17 @@
1
- # @mindforge/sdk
1
+ # mindforge-sdk
2
2
 
3
3
  TypeScript SDK for embedding MindForge in tools, dashboards, and CI pipelines.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @mindforge/sdk
8
+ npm install mindforge-sdk
9
9
  ```
10
10
 
11
11
  ## Quick start
12
12
 
13
13
  ```typescript
14
- import { MindForgeClient } from '@mindforge/sdk';
14
+ import { MindForgeClient } from 'mindforge-sdk';
15
15
 
16
16
  const client = new MindForgeClient({
17
17
  projectRoot: '/path/to/project',
@@ -33,8 +33,29 @@ console.log(metrics);
33
33
 
34
34
  ## Real-time event streaming
35
35
 
36
+ `MindForgeEventStream` is the supported path and it is self-contained: it starts its own SSE server,
37
+ tails `.planning/AUDIT.jsonl`, and broadcasts each new entry as an `audit_entry` event. Verified end to
38
+ end — `GET /events` returns `text/event-stream`, and appending to the audit log produces a broadcast.
39
+ Note the `watchAuditLog()` call below is required: `start()` serves the stream but does not begin
40
+ tailing on its own.
41
+
42
+ `WebSocketEventStream` is also exported, and it comes with two constraints worth knowing before you
43
+ reach for it:
44
+
45
+ - **It needs a global `WebSocket` that this package does not provide.** `engines.node` is `>=18.0.0`
46
+ and `dependencies` is empty, so on Node 18 or 20 you must install `ws` yourself and assign it to
47
+ `globalThis.WebSocket`. On Node 22+ the global exists. Calling `connect()` without one throws an
48
+ error saying so, rather than a bare `ReferenceError`.
49
+ - **MindForge ships no WebSocket server.** The default URL is `ws://127.0.0.1:7337/ws`, but the
50
+ dashboard exposes no `/ws` upgrade path — so this client is for connecting to a server *you* run,
51
+ not to MindForge itself. Use `MindForgeEventStream` if you want events from MindForge.
52
+
53
+ Reconnection is automatic (5 attempts, linear backoff). A reconnect that fails is delivered to an
54
+ `'error'` listener registered with `on('error', handler)`; once the attempts are exhausted a `'close'`
55
+ event fires with the reason, so a dead stream is observable rather than silent.
56
+
36
57
  ```typescript
37
- import { MindForgeEventStream } from '@mindforge/sdk';
58
+ import { MindForgeEventStream } from 'mindforge-sdk';
38
59
 
39
60
  const stream = new MindForgeEventStream();
40
61
  await stream.start(7337);
@@ -64,7 +85,7 @@ if (!valid) console.error(errors);
64
85
  - The SDK operates on local files and provides no network authentication. Do not expose SDK
65
86
  endpoints to the public internet.
66
87
 
67
- ## New in v11.8.0
88
+ ## New in v11.9.5
68
89
 
69
90
  ### Additional exports
70
91
 
@@ -73,7 +94,7 @@ import {
73
94
  MindForgeClient,
74
95
  MindForgeEventStream,
75
96
  WebSocketEventStream,
76
- VERSION, // '11.8.0'
97
+ VERSION, // '11.9.5'
77
98
  } from 'mindforge-sdk';
78
99
 
79
100
  import type {
@@ -89,7 +110,7 @@ import type {
89
110
  ### Streaming execution
90
111
 
91
112
  ```typescript
92
- import { MindForgeClient, WebSocketEventStream } from 'mindforge-sdk';
113
+ import { MindForgeClient } from 'mindforge-sdk';
93
114
 
94
115
  const client = new MindForgeClient({ projectRoot: '.' });
95
116
  const { stream } = await client.streamExecution(1);
package/dist/events.d.ts CHANGED
@@ -33,6 +33,14 @@ export declare class WebSocketEventStream {
33
33
  private maxReconnectAttempts;
34
34
  private listeners;
35
35
  constructor(url?: string);
36
+ /**
37
+ * Dispatch to registered listeners. One dispatch path for messages, reconnect failures and
38
+ * stream death, so those three cannot drift apart in how they treat a throwing listener.
39
+ *
40
+ * A missing 'error' listener does NOT mean silence: a reconnect that fails invisibly leaves the
41
+ * consumer believing the stream is live, which is the failure mode this class was already in.
42
+ */
43
+ private emit;
36
44
  connect(): Promise<void>;
37
45
  on(eventType: string, handler: EventHandler): void;
38
46
  off(eventType: string, handler: EventHandler): void;
package/dist/events.js CHANGED
@@ -192,7 +192,37 @@ class WebSocketEventStream {
192
192
  this.maxReconnectAttempts = 5;
193
193
  this.listeners = new Map();
194
194
  }
195
+ /**
196
+ * Dispatch to registered listeners. One dispatch path for messages, reconnect failures and
197
+ * stream death, so those three cannot drift apart in how they treat a throwing listener.
198
+ *
199
+ * A missing 'error' listener does NOT mean silence: a reconnect that fails invisibly leaves the
200
+ * consumer believing the stream is live, which is the failure mode this class was already in.
201
+ */
202
+ emit(eventType, data) {
203
+ const handlers = this.listeners.get(eventType);
204
+ if (!handlers || handlers.size === 0) {
205
+ if (eventType === 'error' && typeof process !== 'undefined' && process.stderr) {
206
+ const message = data instanceof Error ? data.message : String(data);
207
+ process.stderr.write(`[MindForge SDK] event stream error: ${message}\n`);
208
+ }
209
+ return;
210
+ }
211
+ // A listener that throws must not take the stream — or the process — with it.
212
+ handlers.forEach((handler) => { try {
213
+ handler(data);
214
+ }
215
+ catch { /* listener fault */ } });
216
+ }
195
217
  async connect() {
218
+ // Fail fast and legibly. `WebSocket` is declared, not imported, and sdk/package.json has NO
219
+ // dependencies while engines.node is >=18.0.0 — so on Node 18 or 20 the constructor below is a
220
+ // bare `ReferenceError: WebSocket is not defined`, which tells the caller nothing about why.
221
+ if (typeof WebSocket === 'undefined') {
222
+ throw new Error('WebSocketEventStream requires a global WebSocket: Node 22+, a browser, or the optional '
223
+ + '\'ws\' package installed and assigned to globalThis.WebSocket. This SDK declares no '
224
+ + 'runtime dependencies, so it does not install one for you.');
225
+ }
196
226
  return new Promise((resolve, reject) => {
197
227
  this.ws = new WebSocket(this.url);
198
228
  this.ws.onopen = () => {
@@ -203,15 +233,33 @@ class WebSocketEventStream {
203
233
  this.ws.onmessage = (event) => {
204
234
  try {
205
235
  const parsed = JSON.parse(String(event.data));
206
- const handlers = this.listeners.get(parsed.type) || new Set();
207
- handlers.forEach(handler => handler(parsed.data));
236
+ this.emit(parsed.type, parsed.data);
208
237
  }
209
238
  catch { /* malformed message */ }
210
239
  };
211
240
  this.ws.onclose = () => {
212
241
  if (this.reconnectAttempts < this.maxReconnectAttempts) {
213
242
  this.reconnectAttempts++;
214
- setTimeout(() => this.connect(), 1000 * this.reconnectAttempts);
243
+ setTimeout(() => {
244
+ // A scheduled reconnect is fire-and-forget, so nothing awaits the promise it returns.
245
+ // Without this .catch(), `connect()` rejecting via onerror is an UNHANDLED REJECTION —
246
+ // and under Node's default mode that is fatal: it TERMINATES THE CALLER'S PROCESS.
247
+ // Reproduced against the compiled module with a stub socket whose reconnect calls
248
+ // onerror: exit code 1, and the line after the wait never ran.
249
+ this.connect().catch((err) => this.emit('error', err));
250
+ }, 1000 * this.reconnectAttempts);
251
+ }
252
+ else if (this.maxReconnectAttempts > 0) {
253
+ // Attempts exhausted. This branch did not exist: the stream simply went quiet, leaving
254
+ // the consumer with no way to learn it was dead.
255
+ //
256
+ // Guarded on maxReconnectAttempts > 0 because disconnect() sets it to 0 (:276). Without
257
+ // the guard, a DELIBERATE disconnect would emit 'close' with reason "reconnect attempts
258
+ // exhausted" — telling the caller their stream died when they closed it themselves.
259
+ this.emit('close', {
260
+ reason: 'reconnect attempts exhausted',
261
+ attempts: this.reconnectAttempts,
262
+ });
215
263
  }
216
264
  };
217
265
  });
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * MindForge SDK — Public API
3
- * @module @mindforge/sdk
3
+ * @module mindforge-sdk
4
4
  */
5
5
  export { MindForgeClient } from './client';
6
6
  export { MindForgeEventStream, WebSocketEventStream } from './events';
@@ -8,4 +8,4 @@ export { commands, batch } from './commands';
8
8
  export { MindForgeMemory } from './memory';
9
9
  export type { CommandOptions } from './commands';
10
10
  export type { MindForgeConfig, PhaseResult, TaskResult, SecurityFinding, GateResult, HealthReport, HealthIssue, MindForgeEvent, AuditLogEntry, WaveExecutionResult, MigrationResult, StreamChunk, StreamingExecutionResult, BatchExecutionRequest, BatchExecutionResult, } from './types';
11
- export declare const VERSION = "11.8.0";
11
+ export declare const VERSION = "11.9.5";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /**
3
3
  * MindForge SDK — Public API
4
- * @module @mindforge/sdk
4
+ * @module mindforge-sdk
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.VERSION = exports.MindForgeMemory = exports.batch = exports.commands = exports.WebSocketEventStream = exports.MindForgeEventStream = exports.MindForgeClient = void 0;
@@ -15,4 +15,4 @@ Object.defineProperty(exports, "commands", { enumerable: true, get: function ()
15
15
  Object.defineProperty(exports, "batch", { enumerable: true, get: function () { return commands_1.batch; } });
16
16
  var memory_1 = require("./memory");
17
17
  Object.defineProperty(exports, "MindForgeMemory", { enumerable: true, get: function () { return memory_1.MindForgeMemory; } });
18
- exports.VERSION = '11.8.0';
18
+ exports.VERSION = '11.9.5';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mindforge-sdk",
3
- "version": "11.8.0",
4
- "description": "MindForge SDK \u2014 Programmatic API for embedding MindForge in tools",
3
+ "version": "11.9.5",
4
+ "description": "MindForge SDK Programmatic API for embedding MindForge in tools",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
@@ -32,6 +32,11 @@
32
32
  "sdk"
33
33
  ],
34
34
  "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/sairam0424/MindForge.git",
38
+ "directory": "sdk"
39
+ },
35
40
  "publishConfig": {
36
41
  "access": "public"
37
42
  },
@@ -40,7 +45,7 @@
40
45
  },
41
46
  "devDependencies": {
42
47
  "@eslint/js": "^9.0.0",
43
- "@types/node": "^20.0.0",
48
+ "@types/node": "^25.9.1",
44
49
  "eslint": "^9.0.0",
45
50
  "globals": "^15.0.0",
46
51
  "typescript": "^5.4.0",