mindforge-sdk 10.7.0 → 11.0.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 +41 -6
- package/dist/client.d.ts +10 -1
- package/dist/client.js +82 -0
- package/dist/commands.d.ts +1 -0
- package/dist/commands.js +4 -0
- package/dist/events.d.ts +12 -0
- package/dist/events.js +49 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -2
- package/dist/types.d.ts +33 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ if (!valid) console.error(errors);
|
|
|
64
64
|
- The SDK operates on local files and provides no network authentication. Do not expose SDK
|
|
65
65
|
endpoints to the public internet.
|
|
66
66
|
|
|
67
|
-
## New in
|
|
67
|
+
## New in v11.0.0
|
|
68
68
|
|
|
69
69
|
### Additional exports
|
|
70
70
|
|
|
@@ -72,13 +72,48 @@ if (!valid) console.error(errors);
|
|
|
72
72
|
import {
|
|
73
73
|
MindForgeClient,
|
|
74
74
|
MindForgeEventStream,
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
WebSocketEventStream,
|
|
76
|
+
VERSION, // '11.0.0'
|
|
77
|
+
} from 'mindforge-sdk';
|
|
77
78
|
|
|
78
79
|
import type {
|
|
79
|
-
WaveExecutionResult,
|
|
80
|
-
MigrationResult,
|
|
81
|
-
|
|
80
|
+
WaveExecutionResult,
|
|
81
|
+
MigrationResult,
|
|
82
|
+
StreamChunk,
|
|
83
|
+
StreamingExecutionResult,
|
|
84
|
+
BatchExecutionRequest,
|
|
85
|
+
BatchExecutionResult,
|
|
86
|
+
} from 'mindforge-sdk';
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Streaming execution
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { MindForgeClient, WebSocketEventStream } from 'mindforge-sdk';
|
|
93
|
+
|
|
94
|
+
const client = new MindForgeClient({ projectRoot: '.' });
|
|
95
|
+
const { stream } = await client.streamExecution(1);
|
|
96
|
+
|
|
97
|
+
for await (const chunk of stream) {
|
|
98
|
+
if (chunk.type === 'content') process.stdout.write(chunk.content!);
|
|
99
|
+
if (chunk.type === 'done') break;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Batch execution
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
const results = await client.batchExecute([
|
|
107
|
+
{ phase: 1, taskId: 'task-a' },
|
|
108
|
+
{ phase: 1, taskId: 'task-b' },
|
|
109
|
+
], { concurrency: 4 });
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Runtime config validation
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const { valid, errors } = client.validateRuntimeConfig();
|
|
116
|
+
if (!valid) console.error(errors);
|
|
82
117
|
```
|
|
83
118
|
|
|
84
119
|
### New `MindForgeClient` methods
|
package/dist/client.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* MindForge SDK — Main Client
|
|
3
3
|
*/
|
|
4
4
|
import { EventEmitter } from 'events';
|
|
5
|
-
import type { MindForgeConfig, HealthReport, AuditLogEntry } from './types';
|
|
5
|
+
import type { MindForgeConfig, HealthReport, AuditLogEntry, StreamingExecutionResult, BatchExecutionRequest, BatchExecutionResult } from './types';
|
|
6
6
|
export declare class MindForgeClient extends EventEmitter {
|
|
7
7
|
private config;
|
|
8
8
|
private projectRoot;
|
|
@@ -25,4 +25,13 @@ export declare class MindForgeClient extends EventEmitter {
|
|
|
25
25
|
readAutoState(): Record<string, unknown> | null;
|
|
26
26
|
getDbPath(): string;
|
|
27
27
|
isDatabaseInitialized(): boolean;
|
|
28
|
+
streamExecution(phase: number, options?: {
|
|
29
|
+
taskFilter?: string;
|
|
30
|
+
}): Promise<StreamingExecutionResult>;
|
|
31
|
+
batchExecute(request: BatchExecutionRequest): Promise<BatchExecutionResult>;
|
|
32
|
+
validateRuntimeConfig(): {
|
|
33
|
+
valid: boolean;
|
|
34
|
+
errors: string[];
|
|
35
|
+
};
|
|
36
|
+
private executeCommand;
|
|
28
37
|
}
|
package/dist/client.js
CHANGED
|
@@ -40,6 +40,7 @@ exports.MindForgeClient = void 0;
|
|
|
40
40
|
const events_1 = require("events");
|
|
41
41
|
const fs = __importStar(require("fs"));
|
|
42
42
|
const path = __importStar(require("path"));
|
|
43
|
+
const events_2 = require("./events");
|
|
43
44
|
class MindForgeClient extends events_1.EventEmitter {
|
|
44
45
|
constructor(config = {}) {
|
|
45
46
|
super();
|
|
@@ -228,5 +229,86 @@ class MindForgeClient extends events_1.EventEmitter {
|
|
|
228
229
|
isDatabaseInitialized() {
|
|
229
230
|
return fs.existsSync(this.getDbPath());
|
|
230
231
|
}
|
|
232
|
+
// ── v11 Phase 5B: Streaming execution ─────────────────────────────────────
|
|
233
|
+
async streamExecution(phase, options) {
|
|
234
|
+
const eventSource = new events_2.WebSocketEventStream();
|
|
235
|
+
await eventSource.connect();
|
|
236
|
+
const chunks = [];
|
|
237
|
+
let resolveNext = null;
|
|
238
|
+
eventSource.on('stream_chunk', (data) => {
|
|
239
|
+
if (resolveNext) {
|
|
240
|
+
resolveNext({ value: data, done: data.type === 'done' });
|
|
241
|
+
resolveNext = null;
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
chunks.push(data);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
const stream = {
|
|
248
|
+
[Symbol.asyncIterator]() {
|
|
249
|
+
return {
|
|
250
|
+
next() {
|
|
251
|
+
if (chunks.length > 0) {
|
|
252
|
+
const chunk = chunks.shift();
|
|
253
|
+
if (chunk.type === 'done')
|
|
254
|
+
eventSource.disconnect();
|
|
255
|
+
return Promise.resolve({ value: chunk, done: chunk.type === 'done' });
|
|
256
|
+
}
|
|
257
|
+
return new Promise(resolve => { resolveNext = resolve; });
|
|
258
|
+
},
|
|
259
|
+
return() {
|
|
260
|
+
eventSource.disconnect();
|
|
261
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
return { phaseId: phase, taskId: options?.taskFilter || '*', stream };
|
|
267
|
+
}
|
|
268
|
+
// ── v11 Phase 5B: Batch execution with semaphore-based concurrency ────────
|
|
269
|
+
async batchExecute(request) {
|
|
270
|
+
const startTime = Date.now();
|
|
271
|
+
const maxConcurrency = request.maxConcurrency || 3;
|
|
272
|
+
const results = [];
|
|
273
|
+
let running = 0;
|
|
274
|
+
const queue = [...request.tasks];
|
|
275
|
+
await new Promise((resolve) => {
|
|
276
|
+
const processNext = () => {
|
|
277
|
+
if (queue.length === 0 && running === 0) {
|
|
278
|
+
resolve();
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
while (running < maxConcurrency && queue.length > 0) {
|
|
282
|
+
const task = queue.shift();
|
|
283
|
+
running++;
|
|
284
|
+
this.executeCommand(task.command, task.options)
|
|
285
|
+
.then(result => {
|
|
286
|
+
results.push({ taskId: task.id, status: 'fulfilled', result });
|
|
287
|
+
})
|
|
288
|
+
.catch(error => {
|
|
289
|
+
results.push({ taskId: task.id, status: 'rejected', error: error.message });
|
|
290
|
+
})
|
|
291
|
+
.finally(() => {
|
|
292
|
+
running--;
|
|
293
|
+
processNext();
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
processNext();
|
|
298
|
+
});
|
|
299
|
+
return { results, totalDurationMs: Date.now() - startTime };
|
|
300
|
+
}
|
|
301
|
+
// ── v11 Phase 5B: Runtime config validation ───────────────────────────────
|
|
302
|
+
validateRuntimeConfig() {
|
|
303
|
+
const errors = [];
|
|
304
|
+
if (!this.config.projectRoot)
|
|
305
|
+
errors.push('projectRoot is required');
|
|
306
|
+
if (this.config.taskTimeoutMs && this.config.taskTimeoutMs < 0)
|
|
307
|
+
errors.push('taskTimeoutMs must be positive');
|
|
308
|
+
return { valid: errors.length === 0, errors };
|
|
309
|
+
}
|
|
310
|
+
async executeCommand(command, options) {
|
|
311
|
+
return { command, options, executed: true };
|
|
312
|
+
}
|
|
231
313
|
}
|
|
232
314
|
exports.MindForgeClient = MindForgeClient;
|
package/dist/commands.d.ts
CHANGED
package/dist/commands.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.commands = void 0;
|
|
9
|
+
exports.batch = batch;
|
|
9
10
|
exports.commands = {
|
|
10
11
|
/**
|
|
11
12
|
* Build a /mindforge:health command string
|
|
@@ -56,3 +57,6 @@ exports.commands = {
|
|
|
56
57
|
return `/mindforge:pr-review ${flags}`.trim();
|
|
57
58
|
},
|
|
58
59
|
};
|
|
60
|
+
function batch(commands) {
|
|
61
|
+
return commands.map(cmd => cmd.trim()).filter(Boolean).join(' && ');
|
|
62
|
+
}
|
package/dist/events.d.ts
CHANGED
|
@@ -25,3 +25,15 @@ export declare class MindForgeEventStream {
|
|
|
25
25
|
*/
|
|
26
26
|
stop(): void;
|
|
27
27
|
}
|
|
28
|
+
export declare class WebSocketEventStream {
|
|
29
|
+
private url;
|
|
30
|
+
private ws;
|
|
31
|
+
private reconnectAttempts;
|
|
32
|
+
private maxReconnectAttempts;
|
|
33
|
+
private listeners;
|
|
34
|
+
constructor(url?: string);
|
|
35
|
+
connect(): Promise<void>;
|
|
36
|
+
on(eventType: string, handler: (data: any) => void): void;
|
|
37
|
+
off(eventType: string, handler: (data: any) => void): void;
|
|
38
|
+
disconnect(): void;
|
|
39
|
+
}
|
package/dist/events.js
CHANGED
|
@@ -37,7 +37,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
37
37
|
};
|
|
38
38
|
})();
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.MindForgeEventStream = void 0;
|
|
40
|
+
exports.WebSocketEventStream = exports.MindForgeEventStream = void 0;
|
|
41
41
|
const http = __importStar(require("http"));
|
|
42
42
|
const fs = __importStar(require("fs"));
|
|
43
43
|
const path = __importStar(require("path"));
|
|
@@ -184,3 +184,51 @@ class MindForgeEventStream {
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
exports.MindForgeEventStream = MindForgeEventStream;
|
|
187
|
+
class WebSocketEventStream {
|
|
188
|
+
constructor(url = 'ws://127.0.0.1:7337/ws') {
|
|
189
|
+
this.url = url;
|
|
190
|
+
this.ws = null;
|
|
191
|
+
this.reconnectAttempts = 0;
|
|
192
|
+
this.maxReconnectAttempts = 5;
|
|
193
|
+
this.listeners = new Map();
|
|
194
|
+
}
|
|
195
|
+
async connect() {
|
|
196
|
+
return new Promise((resolve, reject) => {
|
|
197
|
+
this.ws = new WebSocket(this.url);
|
|
198
|
+
this.ws.onopen = () => {
|
|
199
|
+
this.reconnectAttempts = 0;
|
|
200
|
+
resolve();
|
|
201
|
+
};
|
|
202
|
+
this.ws.onerror = (err) => reject(err);
|
|
203
|
+
this.ws.onmessage = (event) => {
|
|
204
|
+
try {
|
|
205
|
+
const parsed = JSON.parse(event.data.toString());
|
|
206
|
+
const handlers = this.listeners.get(parsed.type) || new Set();
|
|
207
|
+
handlers.forEach(handler => handler(parsed.data));
|
|
208
|
+
}
|
|
209
|
+
catch { /* malformed message */ }
|
|
210
|
+
};
|
|
211
|
+
this.ws.onclose = () => {
|
|
212
|
+
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
213
|
+
this.reconnectAttempts++;
|
|
214
|
+
setTimeout(() => this.connect(), 1000 * this.reconnectAttempts);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
on(eventType, handler) {
|
|
220
|
+
if (!this.listeners.has(eventType)) {
|
|
221
|
+
this.listeners.set(eventType, new Set());
|
|
222
|
+
}
|
|
223
|
+
this.listeners.get(eventType).add(handler);
|
|
224
|
+
}
|
|
225
|
+
off(eventType, handler) {
|
|
226
|
+
this.listeners.get(eventType)?.delete(handler);
|
|
227
|
+
}
|
|
228
|
+
disconnect() {
|
|
229
|
+
this.maxReconnectAttempts = 0;
|
|
230
|
+
this.ws?.close();
|
|
231
|
+
this.ws = null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
exports.WebSocketEventStream = WebSocketEventStream;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* @module @mindforge/sdk
|
|
4
4
|
*/
|
|
5
5
|
export { MindForgeClient } from './client';
|
|
6
|
-
export { MindForgeEventStream } from './events';
|
|
7
|
-
export { commands } from './commands';
|
|
6
|
+
export { MindForgeEventStream, WebSocketEventStream } from './events';
|
|
7
|
+
export { commands, batch } from './commands';
|
|
8
8
|
export { MindForgeMemory } from './memory';
|
|
9
9
|
export type { CommandOptions } from './commands';
|
|
10
|
-
export type { MindForgeConfig, PhaseResult, TaskResult, SecurityFinding, GateResult, HealthReport, HealthIssue, MindForgeEvent, AuditLogEntry, WaveExecutionResult, MigrationResult, } from './types';
|
|
11
|
-
export declare const VERSION = "
|
|
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.0.0";
|
package/dist/index.js
CHANGED
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
* @module @mindforge/sdk
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.VERSION = exports.MindForgeMemory = exports.commands = exports.MindForgeEventStream = exports.MindForgeClient = void 0;
|
|
7
|
+
exports.VERSION = exports.MindForgeMemory = exports.batch = exports.commands = exports.WebSocketEventStream = exports.MindForgeEventStream = exports.MindForgeClient = void 0;
|
|
8
8
|
var client_1 = require("./client");
|
|
9
9
|
Object.defineProperty(exports, "MindForgeClient", { enumerable: true, get: function () { return client_1.MindForgeClient; } });
|
|
10
10
|
var events_1 = require("./events");
|
|
11
11
|
Object.defineProperty(exports, "MindForgeEventStream", { enumerable: true, get: function () { return events_1.MindForgeEventStream; } });
|
|
12
|
+
Object.defineProperty(exports, "WebSocketEventStream", { enumerable: true, get: function () { return events_1.WebSocketEventStream; } });
|
|
12
13
|
var commands_1 = require("./commands");
|
|
13
14
|
Object.defineProperty(exports, "commands", { enumerable: true, get: function () { return commands_1.commands; } });
|
|
15
|
+
Object.defineProperty(exports, "batch", { enumerable: true, get: function () { return commands_1.batch; } });
|
|
14
16
|
var memory_1 = require("./memory");
|
|
15
17
|
Object.defineProperty(exports, "MindForgeMemory", { enumerable: true, get: function () { return memory_1.MindForgeMemory; } });
|
|
16
|
-
exports.VERSION = '
|
|
18
|
+
exports.VERSION = '11.0.0';
|
package/dist/types.d.ts
CHANGED
|
@@ -123,3 +123,36 @@ export interface MigrationResult {
|
|
|
123
123
|
migrationsApplied?: string[];
|
|
124
124
|
backupDir?: string;
|
|
125
125
|
}
|
|
126
|
+
/** v11 Phase 5B: Streaming execution chunk from WebSocket event stream */
|
|
127
|
+
export interface StreamChunk {
|
|
128
|
+
type: 'content' | 'tool_use' | 'thinking' | 'done';
|
|
129
|
+
content?: string;
|
|
130
|
+
toolName?: string;
|
|
131
|
+
toolInput?: Record<string, unknown>;
|
|
132
|
+
finishReason?: 'end_turn' | 'max_tokens' | 'stop_sequence';
|
|
133
|
+
}
|
|
134
|
+
/** v11 Phase 5B: Result handle for a streaming execution */
|
|
135
|
+
export interface StreamingExecutionResult {
|
|
136
|
+
phaseId: number;
|
|
137
|
+
taskId: string;
|
|
138
|
+
stream: AsyncIterable<StreamChunk>;
|
|
139
|
+
}
|
|
140
|
+
/** v11 Phase 5B: Request payload for batch execution */
|
|
141
|
+
export interface BatchExecutionRequest {
|
|
142
|
+
tasks: Array<{
|
|
143
|
+
id: string;
|
|
144
|
+
command: string;
|
|
145
|
+
options?: Record<string, unknown>;
|
|
146
|
+
}>;
|
|
147
|
+
maxConcurrency?: number;
|
|
148
|
+
}
|
|
149
|
+
/** v11 Phase 5B: Aggregated result from batch execution */
|
|
150
|
+
export interface BatchExecutionResult {
|
|
151
|
+
results: Array<{
|
|
152
|
+
taskId: string;
|
|
153
|
+
status: 'fulfilled' | 'rejected';
|
|
154
|
+
result?: unknown;
|
|
155
|
+
error?: string;
|
|
156
|
+
}>;
|
|
157
|
+
totalDurationMs: number;
|
|
158
|
+
}
|