@topce/pizx 0.1.0 → 0.3.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 +261 -20
- package/dist/cli.js +681 -722
- package/dist/cli.js.map +4 -4
- package/dist/index.js +673 -715
- package/dist/index.js.map +4 -4
- package/package.json +13 -7
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,11 @@ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:f
|
|
|
11
11
|
import { homedir as homedir2 } from "node:os";
|
|
12
12
|
import { join as join2 } from "node:path";
|
|
13
13
|
|
|
14
|
+
// src/utils.ts
|
|
15
|
+
function getErrorMessage(err) {
|
|
16
|
+
return err instanceof Error ? err.message : String(err);
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
// src/load-pi-settings.ts
|
|
15
20
|
import { existsSync, readFileSync } from "node:fs";
|
|
16
21
|
import { homedir } from "node:os";
|
|
@@ -88,46 +93,21 @@ function loadPiAuth() {
|
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
95
|
} catch (err) {
|
|
91
|
-
console.warn(`pizx: failed to parse ${path}: ${err
|
|
96
|
+
console.warn(`pizx: failed to parse ${path}: ${getErrorMessage(err)}`);
|
|
92
97
|
}
|
|
93
98
|
}
|
|
94
99
|
}
|
|
95
100
|
|
|
96
101
|
// src/patterns/types.ts
|
|
97
|
-
import {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
endTime;
|
|
107
|
-
/** Duration in milliseconds */
|
|
108
|
-
get duration() {
|
|
109
|
-
return this.endTime - this.startTime;
|
|
110
|
-
}
|
|
111
|
-
toString() {
|
|
112
|
-
return this.text;
|
|
113
|
-
}
|
|
114
|
-
valueOf() {
|
|
115
|
-
return this.text;
|
|
116
|
-
}
|
|
117
|
-
[Symbol.toPrimitive]() {
|
|
118
|
-
return this.text;
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
var PatternPromise = class extends Promise {
|
|
122
|
-
};
|
|
123
|
-
function build(pieces, args) {
|
|
124
|
-
let s = "";
|
|
125
|
-
for (let i = 0; i < pieces.length; i++) {
|
|
126
|
-
s += pieces[i];
|
|
127
|
-
if (i < args.length) s += String(args[i]);
|
|
128
|
-
}
|
|
129
|
-
return s.trim();
|
|
130
|
-
}
|
|
102
|
+
import { createInterface } from "node:readline";
|
|
103
|
+
import { completeSimple } from "@earendil-works/pi-ai";
|
|
104
|
+
|
|
105
|
+
// src/model-picker.ts
|
|
106
|
+
import {
|
|
107
|
+
getEnvApiKey,
|
|
108
|
+
getModels,
|
|
109
|
+
getProviders
|
|
110
|
+
} from "@earendil-works/pi-ai";
|
|
131
111
|
var _piSettings;
|
|
132
112
|
function getPiDefaults() {
|
|
133
113
|
if (_piSettings === void 0) {
|
|
@@ -171,7 +151,8 @@ function pickModel(preferred) {
|
|
|
171
151
|
if (hit) return hit;
|
|
172
152
|
}
|
|
173
153
|
if (settings.defaultProvider) {
|
|
174
|
-
const
|
|
154
|
+
const provider = settings.defaultProvider;
|
|
155
|
+
const providerModels = getModels(provider);
|
|
175
156
|
if (providerModels && providerModels.length > 0) {
|
|
176
157
|
const configured = new Set(getConfiguredProviders());
|
|
177
158
|
if (configured.has(settings.defaultProvider)) {
|
|
@@ -197,9 +178,138 @@ function pickModel(preferred) {
|
|
|
197
178
|
}
|
|
198
179
|
return models[0];
|
|
199
180
|
}
|
|
181
|
+
|
|
182
|
+
// src/patterns/types.ts
|
|
183
|
+
var PatternOutput = class {
|
|
184
|
+
constructor(text, startTime = Date.now(), endTime = Date.now()) {
|
|
185
|
+
this.text = text;
|
|
186
|
+
this.startTime = startTime;
|
|
187
|
+
this.endTime = endTime;
|
|
188
|
+
}
|
|
189
|
+
text;
|
|
190
|
+
startTime;
|
|
191
|
+
endTime;
|
|
192
|
+
/** Execution trace: one entry per LLM call within this pattern run. Populated by createPatternTag. */
|
|
193
|
+
trace = [];
|
|
194
|
+
/** Structured phase log: key phases during execution, populated by each pattern. */
|
|
195
|
+
phaseLog = [];
|
|
196
|
+
/** Duration in milliseconds */
|
|
197
|
+
get duration() {
|
|
198
|
+
return this.endTime - this.startTime;
|
|
199
|
+
}
|
|
200
|
+
/** Total input tokens across all calls */
|
|
201
|
+
get inputTokens() {
|
|
202
|
+
return this.trace.reduce((s, t) => s + t.inputTokens, 0);
|
|
203
|
+
}
|
|
204
|
+
/** Total output tokens across all calls */
|
|
205
|
+
get outputTokens() {
|
|
206
|
+
return this.trace.reduce((s, t) => s + t.outputTokens, 0);
|
|
207
|
+
}
|
|
208
|
+
/** Total tokens (input + output) across all calls */
|
|
209
|
+
get totalTokens() {
|
|
210
|
+
return this.trace.reduce((s, t) => s + t.totalTokens, 0);
|
|
211
|
+
}
|
|
212
|
+
/** Total cost in USD across all calls */
|
|
213
|
+
get totalCost() {
|
|
214
|
+
return this.trace.reduce((s, t) => s + t.cost, 0);
|
|
215
|
+
}
|
|
216
|
+
/** Number of LLM calls made during this pattern execution */
|
|
217
|
+
get callCount() {
|
|
218
|
+
return this.trace.length;
|
|
219
|
+
}
|
|
220
|
+
toString() {
|
|
221
|
+
return this.text;
|
|
222
|
+
}
|
|
223
|
+
valueOf() {
|
|
224
|
+
return this.text;
|
|
225
|
+
}
|
|
226
|
+
[Symbol.toPrimitive]() {
|
|
227
|
+
return this.text;
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
var PatternPromise = class extends Promise {
|
|
231
|
+
};
|
|
232
|
+
var _trace = null;
|
|
233
|
+
function beginTrace() {
|
|
234
|
+
_trace = [];
|
|
235
|
+
}
|
|
236
|
+
function collectTrace() {
|
|
237
|
+
const t = _trace ?? [];
|
|
238
|
+
_trace = null;
|
|
239
|
+
return t;
|
|
240
|
+
}
|
|
241
|
+
function pushTrace(entry) {
|
|
242
|
+
if (_trace) _trace.push(entry);
|
|
243
|
+
}
|
|
244
|
+
function createPatternTag(defaults17, execute17) {
|
|
245
|
+
function make(opts = {}) {
|
|
246
|
+
const merged = { ...defaults17, ...opts };
|
|
247
|
+
const fn = ((pieces, ...args) => {
|
|
248
|
+
if (!Array.isArray(pieces)) {
|
|
249
|
+
return make({ ...merged, ...pieces });
|
|
250
|
+
}
|
|
251
|
+
beginTrace();
|
|
252
|
+
return new PatternPromise((resolve, reject) => {
|
|
253
|
+
execute17(pieces, args, merged).then(
|
|
254
|
+
(output) => {
|
|
255
|
+
output.trace = collectTrace();
|
|
256
|
+
resolve(output);
|
|
257
|
+
},
|
|
258
|
+
(err) => {
|
|
259
|
+
collectTrace();
|
|
260
|
+
reject(err);
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
let _quiet;
|
|
266
|
+
Object.defineProperty(fn, "quiet", {
|
|
267
|
+
get() {
|
|
268
|
+
if (!_quiet) _quiet = make({ ...merged, quiet: true });
|
|
269
|
+
return _quiet;
|
|
270
|
+
},
|
|
271
|
+
enumerable: true,
|
|
272
|
+
configurable: true
|
|
273
|
+
});
|
|
274
|
+
return fn;
|
|
275
|
+
}
|
|
276
|
+
return make();
|
|
277
|
+
}
|
|
278
|
+
function build(pieces, args) {
|
|
279
|
+
let s = "";
|
|
280
|
+
for (let i = 0; i < pieces.length; i++) {
|
|
281
|
+
s += pieces[i];
|
|
282
|
+
if (i < args.length) s += String(args[i]);
|
|
283
|
+
}
|
|
284
|
+
return s.trim();
|
|
285
|
+
}
|
|
286
|
+
function mergeSystem(userSystem, patternSystem) {
|
|
287
|
+
if (!userSystem) return patternSystem;
|
|
288
|
+
return `${userSystem}
|
|
289
|
+
|
|
290
|
+
${patternSystem}`;
|
|
291
|
+
}
|
|
292
|
+
async function confirmPhase(description, opts) {
|
|
293
|
+
if (!opts.confirm) return true;
|
|
294
|
+
if (!opts.quiet) {
|
|
295
|
+
process.stderr.write(`
|
|
296
|
+
\u2500\u2500 Confirm \u2500\u2500
|
|
297
|
+
${description}
|
|
298
|
+
Proceed? [Y/n] `);
|
|
299
|
+
}
|
|
300
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
301
|
+
const answer = await new Promise((resolve) => {
|
|
302
|
+
rl.question("", (ans) => resolve(ans));
|
|
303
|
+
});
|
|
304
|
+
rl.close();
|
|
305
|
+
const trimmed = answer.trim().toLowerCase();
|
|
306
|
+
if (trimmed === "" || trimmed === "y" || trimmed === "yes") return true;
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
200
309
|
async function ask(prompt, opts = {}) {
|
|
201
310
|
const model = pickModel(opts.model);
|
|
202
311
|
if (!model) throw new Error("pizx/patterns: No AI models configured. Run `pi auth login` first.");
|
|
312
|
+
const t0 = Date.now();
|
|
203
313
|
const result = await completeSimple(
|
|
204
314
|
model,
|
|
205
315
|
{
|
|
@@ -208,12 +318,74 @@ async function ask(prompt, opts = {}) {
|
|
|
208
318
|
},
|
|
209
319
|
{
|
|
210
320
|
maxTokens: opts.maxTokens ?? 4096,
|
|
211
|
-
reasoning: opts.thinkingLevel ?? "medium"
|
|
321
|
+
reasoning: opts.thinkingLevel ?? "medium",
|
|
322
|
+
timeoutMs: opts.timeoutMs,
|
|
323
|
+
maxRetries: opts.maxRetries
|
|
212
324
|
}
|
|
213
325
|
);
|
|
326
|
+
const durationMs = Date.now() - t0;
|
|
327
|
+
if (!result.content || !Array.isArray(result.content)) {
|
|
328
|
+
throw new Error("pizx/patterns: Unexpected response format from AI model.");
|
|
329
|
+
}
|
|
214
330
|
const text = result.content.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
331
|
+
if (_trace !== null) {
|
|
332
|
+
pushTrace({
|
|
333
|
+
call: _trace.length + 1,
|
|
334
|
+
modelId: result.model,
|
|
335
|
+
promptPreview: prompt.slice(0, 200),
|
|
336
|
+
outputPreview: text.slice(0, 200),
|
|
337
|
+
inputTokens: result.usage.input,
|
|
338
|
+
outputTokens: result.usage.output,
|
|
339
|
+
cacheReadTokens: result.usage.cacheRead,
|
|
340
|
+
cacheWriteTokens: result.usage.cacheWrite,
|
|
341
|
+
totalTokens: result.usage.totalTokens,
|
|
342
|
+
cost: result.usage.cost.total,
|
|
343
|
+
durationMs
|
|
344
|
+
});
|
|
345
|
+
}
|
|
215
346
|
return text.trim();
|
|
216
347
|
}
|
|
348
|
+
var QUALITY_REVIEW_SYSTEM = `You are a quality assurance reviewer. Evaluate the final deliverable against the original request.
|
|
349
|
+
|
|
350
|
+
Output format:
|
|
351
|
+
SCORE: 0.XX (quality score from 0.0 to 1.0)
|
|
352
|
+
ASSESSMENT: (1-2 sentences \u2014 is the output complete, consistent, and actionable?)
|
|
353
|
+
RECOMMENDATION: (1 sentence \u2014 what would improve this output?)`;
|
|
354
|
+
async function runQualityReview(originalRequest, finalOutput, opts) {
|
|
355
|
+
if (!opts.qualityCheck) return void 0;
|
|
356
|
+
const reviewText = await ask(
|
|
357
|
+
`Original request:
|
|
358
|
+
${originalRequest}
|
|
359
|
+
|
|
360
|
+
Final deliverable:
|
|
361
|
+
${finalOutput}
|
|
362
|
+
|
|
363
|
+
Evaluate the quality.`,
|
|
364
|
+
{
|
|
365
|
+
model: opts.plannerModel ?? opts.model,
|
|
366
|
+
maxTokens: 512,
|
|
367
|
+
thinkingLevel: "high",
|
|
368
|
+
timeoutMs: opts.timeoutMs,
|
|
369
|
+
maxRetries: opts.maxRetries,
|
|
370
|
+
system: QUALITY_REVIEW_SYSTEM
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
const scoreMatch = reviewText.match(/SCORE:\s*([\d.]+)/i);
|
|
374
|
+
const assessMatch = reviewText.match(/ASSESSMENT:\s*(.+)/i);
|
|
375
|
+
const recMatch = reviewText.match(/RECOMMENDATION:\s*(.+)/i);
|
|
376
|
+
const result = {
|
|
377
|
+
score: scoreMatch ? parseFloat(scoreMatch[1]) : 0.5,
|
|
378
|
+
assessment: assessMatch?.[1]?.trim() ?? "(no assessment)",
|
|
379
|
+
recommendation: recMatch?.[1]?.trim() ?? "(no recommendation)"
|
|
380
|
+
};
|
|
381
|
+
if (!opts.quiet) {
|
|
382
|
+
process.stderr.write(` Quality score: ${result.score.toFixed(2)}
|
|
383
|
+
`);
|
|
384
|
+
process.stderr.write(` ${result.assessment.slice(0, 80)}...
|
|
385
|
+
`);
|
|
386
|
+
}
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
217
389
|
|
|
218
390
|
// src/patterns/adaptive.ts
|
|
219
391
|
var defaults = {
|
|
@@ -277,10 +449,10 @@ async function execute(pieces, args, opts) {
|
|
|
277
449
|
}
|
|
278
450
|
if (!opts.quiet) process.stderr.write(" \u2192 Planning...\n");
|
|
279
451
|
const planText = await ask(goal, {
|
|
452
|
+
...opts,
|
|
280
453
|
model: plannerModel,
|
|
281
|
-
maxTokens: opts.maxTokens,
|
|
282
454
|
thinkingLevel: "high",
|
|
283
|
-
system: PLAN_SYSTEM
|
|
455
|
+
system: mergeSystem(opts.system, PLAN_SYSTEM)
|
|
284
456
|
});
|
|
285
457
|
const planLines = planText.split("\n");
|
|
286
458
|
const plannedSteps = [];
|
|
@@ -310,10 +482,9 @@ async function execute(pieces, args, opts) {
|
|
|
310
482
|
process.stderr.write(` \u2192 Step ${executionStep}: ${currentStep.slice(0, 60)}...
|
|
311
483
|
`);
|
|
312
484
|
const result = await ask(currentStep, {
|
|
485
|
+
...opts,
|
|
313
486
|
model: workerModel,
|
|
314
|
-
|
|
315
|
-
thinkingLevel: opts.thinkingLevel,
|
|
316
|
-
system: EXECUTE_SYSTEM
|
|
487
|
+
system: mergeSystem(opts.system, EXECUTE_SYSTEM)
|
|
317
488
|
});
|
|
318
489
|
const evaluation = await ask(
|
|
319
490
|
`Goal: ${goal}
|
|
@@ -322,10 +493,11 @@ Result: ${result}
|
|
|
322
493
|
|
|
323
494
|
Evaluate the result.`,
|
|
324
495
|
{
|
|
496
|
+
...opts,
|
|
325
497
|
model: plannerModel,
|
|
326
498
|
maxTokens: 512,
|
|
327
499
|
thinkingLevel: "high",
|
|
328
|
-
system: EVALUATE_SYSTEM
|
|
500
|
+
system: mergeSystem(opts.system, EVALUATE_SYSTEM)
|
|
329
501
|
}
|
|
330
502
|
);
|
|
331
503
|
const scoreMatch = evaluation.match(/SCORE:\s*([\d.]+)/i);
|
|
@@ -348,8 +520,7 @@ Evaluate the result.`,
|
|
|
348
520
|
break;
|
|
349
521
|
}
|
|
350
522
|
const adaptUpper = adaptation.toUpperCase();
|
|
351
|
-
if (adaptUpper.startsWith("
|
|
352
|
-
} else if (adaptUpper.startsWith("SKIP_NEXT")) {
|
|
523
|
+
if (adaptUpper.startsWith("SKIP_NEXT")) {
|
|
353
524
|
stepIndex += 2;
|
|
354
525
|
} else if (adaptUpper.startsWith("ADD")) {
|
|
355
526
|
const newStep = adaptation.replace(/^ADD\s*/i, "");
|
|
@@ -368,36 +539,76 @@ Evaluate the result.`,
|
|
|
368
539
|
).join("\n\n");
|
|
369
540
|
return new AdaptiveOutput(summary, finalResult, adaptiveSteps, executionStep, t0, t1);
|
|
370
541
|
}
|
|
371
|
-
|
|
372
|
-
const merged = { ...defaults, ...opts };
|
|
373
|
-
const fn = ((pieces, ...args) => {
|
|
374
|
-
if (!Array.isArray(pieces)) {
|
|
375
|
-
return makeAdaptive({ ...merged, ...pieces });
|
|
376
|
-
}
|
|
377
|
-
return new PatternPromise((resolve, reject) => {
|
|
378
|
-
execute(pieces, args, merged).then(resolve, reject);
|
|
379
|
-
});
|
|
380
|
-
});
|
|
381
|
-
let _quiet;
|
|
382
|
-
Object.defineProperty(fn, "quiet", {
|
|
383
|
-
get() {
|
|
384
|
-
if (!_quiet) _quiet = makeAdaptive({ ...merged, quiet: true });
|
|
385
|
-
return _quiet;
|
|
386
|
-
},
|
|
387
|
-
enumerable: true,
|
|
388
|
-
configurable: true
|
|
389
|
-
});
|
|
390
|
-
return fn;
|
|
391
|
-
}
|
|
392
|
-
var \u0391 = makeAdaptive();
|
|
542
|
+
var \u0391 = createPatternTag(defaults, execute);
|
|
393
543
|
|
|
394
|
-
// src/patterns/
|
|
395
|
-
var
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
544
|
+
// src/patterns/role-sets.ts
|
|
545
|
+
var DEBATE_ROLE_SETS = {
|
|
546
|
+
2: [
|
|
547
|
+
"Optimist \u2014 advocate for the most ambitious approach",
|
|
548
|
+
"Pessimist \u2014 identify risks and failure modes"
|
|
549
|
+
],
|
|
550
|
+
3: [
|
|
551
|
+
"Optimist \u2014 advocate the benefits and opportunities",
|
|
552
|
+
"Pessimist \u2014 identify risks, costs, and failure modes",
|
|
553
|
+
"Pragmatist \u2014 focus on practical trade-offs and implementation"
|
|
554
|
+
],
|
|
555
|
+
4: [
|
|
556
|
+
"Optimist \u2014 argue for the best-case potential",
|
|
557
|
+
"Pessimist \u2014 highlight worst-case risks and downsides",
|
|
558
|
+
"Pragmatist \u2014 balance pros/cons with practical constraints",
|
|
559
|
+
"Innovator \u2014 propose creative alternatives and novel approaches"
|
|
560
|
+
],
|
|
561
|
+
5: [
|
|
562
|
+
"Optimist",
|
|
563
|
+
"Pessimist",
|
|
564
|
+
"Pragmatist",
|
|
565
|
+
"Innovator",
|
|
566
|
+
"User Advocate \u2014 focus on end-user experience and accessibility"
|
|
567
|
+
]
|
|
399
568
|
};
|
|
400
|
-
var
|
|
569
|
+
var MEMORY_ROLE_SETS = {
|
|
570
|
+
2: ["Analyst \u2014 deep analysis of core aspects", "Reviewer \u2014 check for gaps and blind spots"],
|
|
571
|
+
3: [
|
|
572
|
+
"Analyst \u2014 deep analysis of core aspects",
|
|
573
|
+
"Reviewer \u2014 check for gaps, edge cases, and blind spots",
|
|
574
|
+
"Strategist \u2014 connect findings to actionable insights"
|
|
575
|
+
],
|
|
576
|
+
4: [
|
|
577
|
+
"Analyst",
|
|
578
|
+
"Reviewer",
|
|
579
|
+
"Strategist",
|
|
580
|
+
"Innovator \u2014 propose novel angles and creative solutions"
|
|
581
|
+
],
|
|
582
|
+
5: [
|
|
583
|
+
"Analyst",
|
|
584
|
+
"Reviewer",
|
|
585
|
+
"Strategist",
|
|
586
|
+
"Innovator",
|
|
587
|
+
"Skeptic \u2014 challenge assumptions and stress-test conclusions"
|
|
588
|
+
]
|
|
589
|
+
};
|
|
590
|
+
var THREAD_ROLE_SETS = {
|
|
591
|
+
2: ["Proposer \u2014 advocate the best approach", "Critic \u2014 identify weaknesses and gaps"],
|
|
592
|
+
3: [
|
|
593
|
+
"Proposer \u2014 suggest the best approach",
|
|
594
|
+
"Critic \u2014 identify weaknesses, risks, and missing pieces",
|
|
595
|
+
"Synthesizer \u2014 combine the best ideas into a practical plan"
|
|
596
|
+
],
|
|
597
|
+
4: [
|
|
598
|
+
"Proposer \u2014 advocate a bold solution",
|
|
599
|
+
"Critic \u2014 identify risks and weaknesses",
|
|
600
|
+
"Pragmatist \u2014 focus on practical implementation",
|
|
601
|
+
"Innovator \u2014 propose creative alternatives"
|
|
602
|
+
],
|
|
603
|
+
5: [
|
|
604
|
+
"Proposer",
|
|
605
|
+
"Critic",
|
|
606
|
+
"Pragmatist",
|
|
607
|
+
"Innovator",
|
|
608
|
+
"Devil's Advocate \u2014 challenge every assumption"
|
|
609
|
+
]
|
|
610
|
+
};
|
|
611
|
+
var BROADCAST_ROLE_SETS = {
|
|
401
612
|
2: [
|
|
402
613
|
"Technical Expert \u2014 evaluate technical feasibility",
|
|
403
614
|
"Business Expert \u2014 evaluate business viability"
|
|
@@ -421,6 +632,13 @@ var ROLE_SETS = {
|
|
|
421
632
|
"Innovation Expert \u2014 suggest novel approaches and alternatives"
|
|
422
633
|
]
|
|
423
634
|
};
|
|
635
|
+
|
|
636
|
+
// src/patterns/broadcast.ts
|
|
637
|
+
var defaults2 = {
|
|
638
|
+
maxTokens: 4096,
|
|
639
|
+
thinkingLevel: "medium",
|
|
640
|
+
workers: 4
|
|
641
|
+
};
|
|
424
642
|
var BroadcastResponse = class {
|
|
425
643
|
constructor(role, response, success, error) {
|
|
426
644
|
this.role = role;
|
|
@@ -434,13 +652,15 @@ var BroadcastResponse = class {
|
|
|
434
652
|
error;
|
|
435
653
|
};
|
|
436
654
|
var BroadcastOutput = class extends PatternOutput {
|
|
437
|
-
constructor(text, synthesis, responses, startTime, endTime) {
|
|
655
|
+
constructor(text, synthesis, responses, startTime, endTime, qualityReview) {
|
|
438
656
|
super(text, startTime, endTime);
|
|
439
657
|
this.synthesis = synthesis;
|
|
440
658
|
this.responses = responses;
|
|
659
|
+
this.qualityReview = qualityReview;
|
|
441
660
|
}
|
|
442
661
|
synthesis;
|
|
443
662
|
responses;
|
|
663
|
+
qualityReview;
|
|
444
664
|
};
|
|
445
665
|
var WORKER_PROMPT = `You are a {role}.
|
|
446
666
|
|
|
@@ -455,7 +675,7 @@ async function execute2(pieces, args, opts) {
|
|
|
455
675
|
const question = build(pieces, args);
|
|
456
676
|
const t0 = Date.now();
|
|
457
677
|
const workerCount = opts.workers ?? 4;
|
|
458
|
-
const roles = opts.roles ??
|
|
678
|
+
const roles = opts.roles ?? BROADCAST_ROLE_SETS[workerCount] ?? BROADCAST_ROLE_SETS[4] ?? [];
|
|
459
679
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
460
680
|
const workerModel = opts.workerModel ?? opts.model;
|
|
461
681
|
if (!opts.quiet) {
|
|
@@ -470,11 +690,7 @@ async function execute2(pieces, args, opts) {
|
|
|
470
690
|
const broadcastResults = await Promise.allSettled(
|
|
471
691
|
roles.map(async (role) => {
|
|
472
692
|
const prompt = WORKER_PROMPT.replace("{role}", role).replace("{question}", question);
|
|
473
|
-
const text = await ask(prompt, {
|
|
474
|
-
model: workerModel,
|
|
475
|
-
maxTokens: opts.maxTokens,
|
|
476
|
-
thinkingLevel: opts.thinkingLevel
|
|
477
|
-
});
|
|
693
|
+
const text = await ask(prompt, { ...opts, model: workerModel });
|
|
478
694
|
return new BroadcastResponse(role, text, true);
|
|
479
695
|
})
|
|
480
696
|
);
|
|
@@ -499,40 +715,21 @@ ${responsesText}
|
|
|
499
715
|
|
|
500
716
|
Synthesize a cohesive, actionable recommendation.`,
|
|
501
717
|
{
|
|
718
|
+
...opts,
|
|
502
719
|
model: plannerModel,
|
|
503
|
-
maxTokens: opts.maxTokens,
|
|
504
720
|
thinkingLevel: "high",
|
|
505
|
-
system: SYNTHESIS_SYSTEM
|
|
721
|
+
system: mergeSystem(opts.system, SYNTHESIS_SYSTEM)
|
|
506
722
|
}
|
|
507
723
|
);
|
|
724
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
725
|
+
const qualityReview = await runQualityReview(question, synthesis, opts);
|
|
508
726
|
const t1 = Date.now();
|
|
509
727
|
const summary = responses.map(
|
|
510
728
|
(wr) => `[${wr.role}]: ${wr.response.slice(0, 150)}${wr.response.length > 150 ? "..." : ""}`
|
|
511
729
|
).join("\n");
|
|
512
|
-
return new BroadcastOutput(summary, synthesis, responses, t0, t1);
|
|
513
|
-
}
|
|
514
|
-
function makeBroadcast(opts = {}) {
|
|
515
|
-
const merged = { ...defaults2, ...opts };
|
|
516
|
-
const fn = ((pieces, ...args) => {
|
|
517
|
-
if (!Array.isArray(pieces)) {
|
|
518
|
-
return makeBroadcast({ ...merged, ...pieces });
|
|
519
|
-
}
|
|
520
|
-
return new PatternPromise((resolve, reject) => {
|
|
521
|
-
execute2(pieces, args, merged).then(resolve, reject);
|
|
522
|
-
});
|
|
523
|
-
});
|
|
524
|
-
let _quiet;
|
|
525
|
-
Object.defineProperty(fn, "quiet", {
|
|
526
|
-
get() {
|
|
527
|
-
if (!_quiet) _quiet = makeBroadcast({ ...merged, quiet: true });
|
|
528
|
-
return _quiet;
|
|
529
|
-
},
|
|
530
|
-
enumerable: true,
|
|
531
|
-
configurable: true
|
|
532
|
-
});
|
|
533
|
-
return fn;
|
|
730
|
+
return new BroadcastOutput(summary, synthesis, responses, t0, t1, qualityReview);
|
|
534
731
|
}
|
|
535
|
-
var \u0392 =
|
|
732
|
+
var \u0392 = createPatternTag(defaults2, execute2);
|
|
536
733
|
|
|
537
734
|
// src/patterns/chi.ts
|
|
538
735
|
var defaults3 = {
|
|
@@ -552,15 +749,17 @@ var LearningInsight = class {
|
|
|
552
749
|
confidence;
|
|
553
750
|
};
|
|
554
751
|
var ChiOutput = class extends PatternOutput {
|
|
555
|
-
constructor(text, insights, summary, suggestedChanges, startTime, endTime) {
|
|
752
|
+
constructor(text, insights, summary, suggestedChanges, startTime, endTime, qualityReview) {
|
|
556
753
|
super(text, startTime, endTime);
|
|
557
754
|
this.insights = insights;
|
|
558
755
|
this.summary = summary;
|
|
559
756
|
this.suggestedChanges = suggestedChanges;
|
|
757
|
+
this.qualityReview = qualityReview;
|
|
560
758
|
}
|
|
561
759
|
insights;
|
|
562
760
|
summary;
|
|
563
761
|
suggestedChanges;
|
|
762
|
+
qualityReview;
|
|
564
763
|
};
|
|
565
764
|
var ANALYSIS_SYSTEM = `You are an agent team performance analyst. Review a multi-agent execution and extract structured learnings.
|
|
566
765
|
|
|
@@ -629,12 +828,13 @@ async function execute3(pieces, args, opts) {
|
|
|
629
828
|
`);
|
|
630
829
|
}
|
|
631
830
|
const response = await ask(input, {
|
|
831
|
+
...opts,
|
|
632
832
|
model: plannerModel,
|
|
633
|
-
|
|
634
|
-
thinkingLevel: opts.thinkingLevel,
|
|
635
|
-
system: ANALYSIS_SYSTEM
|
|
833
|
+
system: mergeSystem(opts.system, ANALYSIS_SYSTEM)
|
|
636
834
|
});
|
|
637
835
|
const { insights, summary, suggestedChanges } = parseInsights(response);
|
|
836
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
837
|
+
const qualityReview = await runQualityReview(input, response, opts);
|
|
638
838
|
const t1 = Date.now();
|
|
639
839
|
const text = [
|
|
640
840
|
`Insights: ${insights.length} extracted`,
|
|
@@ -646,30 +846,9 @@ Summary: ${summary}`,
|
|
|
646
846
|
`
|
|
647
847
|
Changes: ${suggestedChanges}`
|
|
648
848
|
].join("\n");
|
|
649
|
-
return new ChiOutput(text, insights, summary, suggestedChanges, t0, t1);
|
|
849
|
+
return new ChiOutput(text, insights, summary, suggestedChanges, t0, t1, qualityReview);
|
|
650
850
|
}
|
|
651
|
-
|
|
652
|
-
const merged = { ...defaults3, ...opts };
|
|
653
|
-
const fn = ((pieces, ...args) => {
|
|
654
|
-
if (!Array.isArray(pieces)) {
|
|
655
|
-
return makeChi({ ...merged, ...pieces });
|
|
656
|
-
}
|
|
657
|
-
return new PatternPromise((resolve, reject) => {
|
|
658
|
-
execute3(pieces, args, merged).then(resolve, reject);
|
|
659
|
-
});
|
|
660
|
-
});
|
|
661
|
-
let _quiet;
|
|
662
|
-
Object.defineProperty(fn, "quiet", {
|
|
663
|
-
get() {
|
|
664
|
-
if (!_quiet) _quiet = makeChi({ ...merged, quiet: true });
|
|
665
|
-
return _quiet;
|
|
666
|
-
},
|
|
667
|
-
enumerable: true,
|
|
668
|
-
configurable: true
|
|
669
|
-
});
|
|
670
|
-
return fn;
|
|
671
|
-
}
|
|
672
|
-
var \u03A7 = makeChi();
|
|
851
|
+
var \u03A7 = createPatternTag(defaults3, execute3);
|
|
673
852
|
|
|
674
853
|
// src/patterns/critique.ts
|
|
675
854
|
var defaults4 = {
|
|
@@ -724,12 +903,7 @@ async function execute4(pieces, args, opts) {
|
|
|
724
903
|
for (let r = 0; r < rounds; r++) {
|
|
725
904
|
if (r === 0) {
|
|
726
905
|
if (!opts.quiet) process.stderr.write(" \u2192 Generating initial content...\n");
|
|
727
|
-
currentContent = await ask(prompt, {
|
|
728
|
-
model: workerModel,
|
|
729
|
-
maxTokens: opts.maxTokens,
|
|
730
|
-
thinkingLevel: opts.thinkingLevel,
|
|
731
|
-
system: void 0
|
|
732
|
-
});
|
|
906
|
+
currentContent = await ask(prompt, { ...opts, model: workerModel, system: opts.system });
|
|
733
907
|
} else {
|
|
734
908
|
if (!opts.quiet) process.stderr.write(` \u2192 Improving (round ${r + 1})...
|
|
735
909
|
`);
|
|
@@ -744,21 +918,15 @@ Content to improve:
|
|
|
744
918
|
${currentContent}
|
|
745
919
|
|
|
746
920
|
Revise the content based on the critique.`,
|
|
747
|
-
{
|
|
748
|
-
model: workerModel,
|
|
749
|
-
maxTokens: opts.maxTokens,
|
|
750
|
-
thinkingLevel: opts.thinkingLevel,
|
|
751
|
-
system: IMPROVE_SYSTEM
|
|
752
|
-
}
|
|
921
|
+
{ ...opts, model: workerModel, system: mergeSystem(opts.system, IMPROVE_SYSTEM) }
|
|
753
922
|
);
|
|
754
923
|
}
|
|
755
924
|
if (!opts.quiet) process.stderr.write(` \u2192 Critiquing (round ${r + 1})...
|
|
756
925
|
`);
|
|
757
926
|
const critique = await ask(currentContent, {
|
|
927
|
+
...opts,
|
|
758
928
|
model: plannerModel,
|
|
759
|
-
|
|
760
|
-
thinkingLevel: opts.thinkingLevel,
|
|
761
|
-
system: CRITIQUE_SYSTEM
|
|
929
|
+
system: mergeSystem(opts.system, CRITIQUE_SYSTEM)
|
|
762
930
|
});
|
|
763
931
|
critiqueRounds.push(new CritiqueRound(currentContent, critique, r));
|
|
764
932
|
}
|
|
@@ -771,28 +939,7 @@ Critique: ${cr.critique.slice(0, 200)}${cr.critique.length > 200 ? "..." : ""}`
|
|
|
771
939
|
).join("\n\n");
|
|
772
940
|
return new CritiqueOutput(summary, finalContent, critiqueRounds, t0, t1);
|
|
773
941
|
}
|
|
774
|
-
|
|
775
|
-
const merged = { ...defaults4, ...opts };
|
|
776
|
-
const fn = ((pieces, ...args) => {
|
|
777
|
-
if (!Array.isArray(pieces)) {
|
|
778
|
-
return makeCritique({ ...merged, ...pieces });
|
|
779
|
-
}
|
|
780
|
-
return new PatternPromise((resolve, reject) => {
|
|
781
|
-
execute4(pieces, args, merged).then(resolve, reject);
|
|
782
|
-
});
|
|
783
|
-
});
|
|
784
|
-
let _quiet;
|
|
785
|
-
Object.defineProperty(fn, "quiet", {
|
|
786
|
-
get() {
|
|
787
|
-
if (!_quiet) _quiet = makeCritique({ ...merged, quiet: true });
|
|
788
|
-
return _quiet;
|
|
789
|
-
},
|
|
790
|
-
enumerable: true,
|
|
791
|
-
configurable: true
|
|
792
|
-
});
|
|
793
|
-
return fn;
|
|
794
|
-
}
|
|
795
|
-
var \u03A8 = makeCritique();
|
|
942
|
+
var \u03A8 = createPatternTag(defaults4, execute4);
|
|
796
943
|
|
|
797
944
|
// src/patterns/debate.ts
|
|
798
945
|
var defaults5 = {
|
|
@@ -801,30 +948,6 @@ var defaults5 = {
|
|
|
801
948
|
perspectives: 3,
|
|
802
949
|
rounds: 1
|
|
803
950
|
};
|
|
804
|
-
var ROLE_SETS2 = {
|
|
805
|
-
2: [
|
|
806
|
-
"Optimist \u2014 advocate for the most ambitious approach",
|
|
807
|
-
"Pessimist \u2014 identify risks and failure modes"
|
|
808
|
-
],
|
|
809
|
-
3: [
|
|
810
|
-
"Optimist \u2014 advocate the benefits and opportunities",
|
|
811
|
-
"Pessimist \u2014 identify risks, costs, and failure modes",
|
|
812
|
-
"Pragmatist \u2014 focus on practical trade-offs and implementation"
|
|
813
|
-
],
|
|
814
|
-
4: [
|
|
815
|
-
"Optimist \u2014 argue for the best-case potential",
|
|
816
|
-
"Pessimist \u2014 highlight worst-case risks and downsides",
|
|
817
|
-
"Pragmatist \u2014 balance pros/cons with practical constraints",
|
|
818
|
-
"Innovator \u2014 propose creative alternatives and novel approaches"
|
|
819
|
-
],
|
|
820
|
-
5: [
|
|
821
|
-
"Optimist",
|
|
822
|
-
"Pessimist",
|
|
823
|
-
"Pragmatist",
|
|
824
|
-
"Innovator",
|
|
825
|
-
"User Advocate \u2014 focus on end-user experience and accessibility"
|
|
826
|
-
]
|
|
827
|
-
};
|
|
828
951
|
var DebatePerspective = class {
|
|
829
952
|
constructor(role, argument, round = 1) {
|
|
830
953
|
this.role = role;
|
|
@@ -836,15 +959,17 @@ var DebatePerspective = class {
|
|
|
836
959
|
round;
|
|
837
960
|
};
|
|
838
961
|
var DebateOutput = class extends PatternOutput {
|
|
839
|
-
constructor(text, conclusion, perspectives, rounds, startTime, endTime) {
|
|
962
|
+
constructor(text, conclusion, perspectives, rounds, startTime, endTime, qualityReview) {
|
|
840
963
|
super(text, startTime, endTime);
|
|
841
964
|
this.conclusion = conclusion;
|
|
842
965
|
this.perspectives = perspectives;
|
|
843
966
|
this.rounds = rounds;
|
|
967
|
+
this.qualityReview = qualityReview;
|
|
844
968
|
}
|
|
845
969
|
conclusion;
|
|
846
970
|
perspectives;
|
|
847
971
|
rounds;
|
|
972
|
+
qualityReview;
|
|
848
973
|
};
|
|
849
974
|
var PERSPECTIVE_SYSTEM = (role) => `You are a debater with the role: ${role}. Analyze the question from your perspective. Be thorough and specific. Provide evidence and reasoning for your position.`;
|
|
850
975
|
var REBUTTAL_SYSTEM = (role) => `You are a debater with the role: ${role}. Review the debate so far \u2014 including arguments from all other perspectives \u2014 and refine your position. Address counter-arguments directly. Challenge weak points in opposing views. Strengthen your original position with rebuttals. Be specific and responsive.`;
|
|
@@ -854,7 +979,7 @@ async function execute5(pieces, args, opts) {
|
|
|
854
979
|
const t0 = Date.now();
|
|
855
980
|
const count = opts.perspectives ?? 3;
|
|
856
981
|
const totalRounds = opts.rounds ?? 1;
|
|
857
|
-
const roles = opts.roles ??
|
|
982
|
+
const roles = opts.roles ?? DEBATE_ROLE_SETS[count] ?? DEBATE_ROLE_SETS[3] ?? [];
|
|
858
983
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
859
984
|
const workerModel = opts.workerModel ?? opts.model;
|
|
860
985
|
if (!opts.quiet) {
|
|
@@ -872,10 +997,9 @@ async function execute5(pieces, args, opts) {
|
|
|
872
997
|
const round1Results = await Promise.allSettled(
|
|
873
998
|
roles.map(
|
|
874
999
|
(role) => ask(question, {
|
|
1000
|
+
...opts,
|
|
875
1001
|
model: workerModel,
|
|
876
|
-
|
|
877
|
-
thinkingLevel: opts.thinkingLevel,
|
|
878
|
-
system: PERSPECTIVE_SYSTEM(role)
|
|
1002
|
+
system: mergeSystem(opts.system, PERSPECTIVE_SYSTEM(role))
|
|
879
1003
|
}).then((text) => new DebatePerspective(role, text, 1))
|
|
880
1004
|
)
|
|
881
1005
|
);
|
|
@@ -909,10 +1033,9 @@ ${othersText}
|
|
|
909
1033
|
|
|
910
1034
|
Refine your position. Address the counter-arguments directly. Strengthen your argument with rebuttals.`;
|
|
911
1035
|
return ask(prompt, {
|
|
1036
|
+
...opts,
|
|
912
1037
|
model: workerModel,
|
|
913
|
-
|
|
914
|
-
thinkingLevel: opts.thinkingLevel,
|
|
915
|
-
system: REBUTTAL_SYSTEM(role)
|
|
1038
|
+
system: mergeSystem(opts.system, REBUTTAL_SYSTEM(role))
|
|
916
1039
|
}).then((text) => new DebatePerspective(role, text, round));
|
|
917
1040
|
})
|
|
918
1041
|
);
|
|
@@ -936,37 +1059,26 @@ Refine your position. Address the counter-arguments directly. Strengthen your ar
|
|
|
936
1059
|
|
|
937
1060
|
Synthesize a balanced conclusion from the full debate above. Weigh the evidence from all rounds.`,
|
|
938
1061
|
{
|
|
1062
|
+
...opts,
|
|
939
1063
|
model: plannerModel,
|
|
940
|
-
maxTokens: opts.maxTokens,
|
|
941
1064
|
thinkingLevel: "high",
|
|
942
|
-
system: SYNTHESIS_SYSTEM2
|
|
1065
|
+
system: mergeSystem(opts.system, SYNTHESIS_SYSTEM2)
|
|
943
1066
|
}
|
|
944
1067
|
);
|
|
1068
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1069
|
+
const qualityReview = await runQualityReview(question, conclusion, opts);
|
|
945
1070
|
const t1 = Date.now();
|
|
946
|
-
return new DebateOutput(
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
execute5(pieces, args, merged).then(resolve, reject);
|
|
956
|
-
});
|
|
957
|
-
});
|
|
958
|
-
let _quiet;
|
|
959
|
-
Object.defineProperty(fn, "quiet", {
|
|
960
|
-
get() {
|
|
961
|
-
if (!_quiet) _quiet = makeDebate({ ...merged, quiet: true });
|
|
962
|
-
return _quiet;
|
|
963
|
-
},
|
|
964
|
-
enumerable: true,
|
|
965
|
-
configurable: true
|
|
966
|
-
});
|
|
967
|
-
return fn;
|
|
1071
|
+
return new DebateOutput(
|
|
1072
|
+
conclusion,
|
|
1073
|
+
conclusion,
|
|
1074
|
+
allPerspectives,
|
|
1075
|
+
totalRounds,
|
|
1076
|
+
t0,
|
|
1077
|
+
t1,
|
|
1078
|
+
qualityReview
|
|
1079
|
+
);
|
|
968
1080
|
}
|
|
969
|
-
var \u0394 =
|
|
1081
|
+
var \u0394 = createPatternTag(defaults5, execute5);
|
|
970
1082
|
|
|
971
1083
|
// src/patterns/fleet.ts
|
|
972
1084
|
var defaults6 = {
|
|
@@ -987,11 +1099,13 @@ var FleetMemberOutput = class {
|
|
|
987
1099
|
error;
|
|
988
1100
|
};
|
|
989
1101
|
var FleetOutput = class extends PatternOutput {
|
|
990
|
-
constructor(text, members, startTime, endTime) {
|
|
1102
|
+
constructor(text, members, startTime, endTime, qualityReview) {
|
|
991
1103
|
super(text, startTime, endTime);
|
|
992
1104
|
this.members = members;
|
|
1105
|
+
this.qualityReview = qualityReview;
|
|
993
1106
|
}
|
|
994
1107
|
members;
|
|
1108
|
+
qualityReview;
|
|
995
1109
|
/** Number of successful members */
|
|
996
1110
|
get successCount() {
|
|
997
1111
|
return this.members.filter((m) => m.success).length;
|
|
@@ -1011,20 +1125,30 @@ function parseTasks(template, explicitTasks) {
|
|
|
1011
1125
|
if (lines.length > 1) return lines;
|
|
1012
1126
|
return [template];
|
|
1013
1127
|
}
|
|
1128
|
+
function describeTask(task) {
|
|
1129
|
+
if (typeof task === "function") return "(composed pattern)";
|
|
1130
|
+
return task;
|
|
1131
|
+
}
|
|
1014
1132
|
var FLEET_SYSTEM = `You are a focused task specialist. Complete the assigned task concisely and accurately. Output only the result \u2014 no commentary about being an AI.`;
|
|
1015
1133
|
async function executeTask(task, opts, workerModel) {
|
|
1134
|
+
if (typeof task === "function") {
|
|
1135
|
+
try {
|
|
1136
|
+
const text = await task("");
|
|
1137
|
+
return new FleetMemberOutput("(composed pattern)", text, true);
|
|
1138
|
+
} catch (err) {
|
|
1139
|
+
return new FleetMemberOutput("(composed pattern)", "", false, getErrorMessage(err));
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1016
1142
|
const model = workerModel ?? opts.model;
|
|
1017
1143
|
try {
|
|
1018
1144
|
const text = await ask(task, {
|
|
1145
|
+
...opts,
|
|
1019
1146
|
model,
|
|
1020
|
-
|
|
1021
|
-
thinkingLevel: opts.thinkingLevel,
|
|
1022
|
-
system: opts.system ?? FLEET_SYSTEM
|
|
1147
|
+
system: mergeSystem(opts.system, FLEET_SYSTEM)
|
|
1023
1148
|
});
|
|
1024
1149
|
return new FleetMemberOutput(task, text, true);
|
|
1025
1150
|
} catch (err) {
|
|
1026
|
-
|
|
1027
|
-
return new FleetMemberOutput(task, "", false, msg);
|
|
1151
|
+
return new FleetMemberOutput(task, "", false, getErrorMessage(err));
|
|
1028
1152
|
}
|
|
1029
1153
|
}
|
|
1030
1154
|
async function execute6(pieces, args, opts) {
|
|
@@ -1036,11 +1160,16 @@ async function execute6(pieces, args, opts) {
|
|
|
1036
1160
|
process.stderr.write(`\u03A6: Fleet executing ${tasks.length} task(s) in parallel
|
|
1037
1161
|
`);
|
|
1038
1162
|
for (let i = 0; i < tasks.length; i++) {
|
|
1039
|
-
const t = tasks[i];
|
|
1163
|
+
const t = describeTask(tasks[i]);
|
|
1040
1164
|
process.stderr.write(` [${i + 1}] ${t.slice(0, 60)}${t.length > 60 ? "..." : ""}
|
|
1041
1165
|
`);
|
|
1042
1166
|
}
|
|
1043
1167
|
}
|
|
1168
|
+
const taskSummary = `Execute ${tasks.length} fleet task(s)?
|
|
1169
|
+
${tasks.map((t, i) => `${i + 1}. ${describeTask(t).slice(0, 80)}`).join("\n ")}`;
|
|
1170
|
+
if (!await confirmPhase(taskSummary, opts)) {
|
|
1171
|
+
throw new Error("pizx/\u03A6: Execution cancelled by user.");
|
|
1172
|
+
}
|
|
1044
1173
|
const results = [];
|
|
1045
1174
|
const concurrency = opts.concurrency ?? 5;
|
|
1046
1175
|
for (let i = 0; i < tasks.length; i += concurrency) {
|
|
@@ -1052,7 +1181,9 @@ async function execute6(pieces, args, opts) {
|
|
|
1052
1181
|
if (r.status === "fulfilled") {
|
|
1053
1182
|
results.push(r.value);
|
|
1054
1183
|
} else {
|
|
1055
|
-
results.push(
|
|
1184
|
+
results.push(
|
|
1185
|
+
new FleetMemberOutput(describeTask(batch[idx]), "", false, r.reason?.toString())
|
|
1186
|
+
);
|
|
1056
1187
|
}
|
|
1057
1188
|
});
|
|
1058
1189
|
}
|
|
@@ -1064,30 +1195,11 @@ async function execute6(pieces, args, opts) {
|
|
|
1064
1195
|
const header = `Fleet Results: ${results.filter((r) => r.success).length}/${results.length} succeeded
|
|
1065
1196
|
|
|
1066
1197
|
`;
|
|
1067
|
-
|
|
1198
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1199
|
+
const qualityReview = await runQualityReview(template, header + summary, opts);
|
|
1200
|
+
return new FleetOutput(header + summary, results, t0, t1, qualityReview);
|
|
1068
1201
|
}
|
|
1069
|
-
|
|
1070
|
-
const merged = { ...defaults6, ...opts };
|
|
1071
|
-
const fn = ((pieces, ...args) => {
|
|
1072
|
-
if (!Array.isArray(pieces)) {
|
|
1073
|
-
return makeFleet({ ...merged, ...pieces });
|
|
1074
|
-
}
|
|
1075
|
-
return new PatternPromise((resolve, reject) => {
|
|
1076
|
-
execute6(pieces, args, merged).then(resolve, reject);
|
|
1077
|
-
});
|
|
1078
|
-
});
|
|
1079
|
-
let _quiet;
|
|
1080
|
-
Object.defineProperty(fn, "quiet", {
|
|
1081
|
-
get() {
|
|
1082
|
-
if (!_quiet) _quiet = makeFleet({ ...merged, quiet: true });
|
|
1083
|
-
return _quiet;
|
|
1084
|
-
},
|
|
1085
|
-
enumerable: true,
|
|
1086
|
-
configurable: true
|
|
1087
|
-
});
|
|
1088
|
-
return fn;
|
|
1089
|
-
}
|
|
1090
|
-
var \u03A6 = makeFleet();
|
|
1202
|
+
var \u03A6 = createPatternTag(defaults6, execute6);
|
|
1091
1203
|
|
|
1092
1204
|
// src/patterns/graph.ts
|
|
1093
1205
|
var defaults7 = {
|
|
@@ -1107,13 +1219,15 @@ var GraphNodeResult = class {
|
|
|
1107
1219
|
success;
|
|
1108
1220
|
};
|
|
1109
1221
|
var GraphOutput = class extends PatternOutput {
|
|
1110
|
-
constructor(text, finalOutput, nodeResults, startTime, endTime) {
|
|
1222
|
+
constructor(text, finalOutput, nodeResults, startTime, endTime, qualityReview) {
|
|
1111
1223
|
super(text, startTime, endTime);
|
|
1112
1224
|
this.finalOutput = finalOutput;
|
|
1113
1225
|
this.nodeResults = nodeResults;
|
|
1226
|
+
this.qualityReview = qualityReview;
|
|
1114
1227
|
}
|
|
1115
1228
|
finalOutput;
|
|
1116
1229
|
nodeResults;
|
|
1230
|
+
qualityReview;
|
|
1117
1231
|
};
|
|
1118
1232
|
function parseGraph(template, separator) {
|
|
1119
1233
|
const sep = separator ?? "\u2192";
|
|
@@ -1209,10 +1323,9 @@ Your task: ${node.task}`;
|
|
|
1209
1323
|
}
|
|
1210
1324
|
}
|
|
1211
1325
|
const text = await ask(context, {
|
|
1326
|
+
...opts,
|
|
1212
1327
|
model: workerModel,
|
|
1213
|
-
|
|
1214
|
-
thinkingLevel: opts.thinkingLevel,
|
|
1215
|
-
system: NODE_SYSTEM
|
|
1328
|
+
system: mergeSystem(opts.system, NODE_SYSTEM)
|
|
1216
1329
|
});
|
|
1217
1330
|
return { nodeId, task: node.task, text, success: true };
|
|
1218
1331
|
})
|
|
@@ -1230,34 +1343,15 @@ Your task: ${node.task}`;
|
|
|
1230
1343
|
const lastBatch = batches[batches.length - 1] ?? [];
|
|
1231
1344
|
const finalNodeResults = lastBatch.map((id) => results.get(id)).filter(Boolean);
|
|
1232
1345
|
const finalOutput = finalNodeResults.length > 0 ? finalNodeResults.join("\n\n") : "";
|
|
1346
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1347
|
+
const qualityReview = await runQualityReview(template, finalOutput, opts);
|
|
1233
1348
|
const summary = nodeResults.map(
|
|
1234
1349
|
(nr) => `[${nr.nodeId}] ${nr.task.slice(0, 80)}...
|
|
1235
1350
|
${nr.output.slice(0, 200)}${nr.output.length > 200 ? "..." : ""}`
|
|
1236
1351
|
).join("\n\n");
|
|
1237
|
-
return new GraphOutput(summary, finalOutput, nodeResults, t0, t1);
|
|
1238
|
-
}
|
|
1239
|
-
function makeGraph(opts = {}) {
|
|
1240
|
-
const merged = { ...defaults7, ...opts };
|
|
1241
|
-
const fn = ((pieces, ...args) => {
|
|
1242
|
-
if (!Array.isArray(pieces)) {
|
|
1243
|
-
return makeGraph({ ...merged, ...pieces });
|
|
1244
|
-
}
|
|
1245
|
-
return new PatternPromise((resolve, reject) => {
|
|
1246
|
-
execute7(pieces, args, merged).then(resolve, reject);
|
|
1247
|
-
});
|
|
1248
|
-
});
|
|
1249
|
-
let _quiet;
|
|
1250
|
-
Object.defineProperty(fn, "quiet", {
|
|
1251
|
-
get() {
|
|
1252
|
-
if (!_quiet) _quiet = makeGraph({ ...merged, quiet: true });
|
|
1253
|
-
return _quiet;
|
|
1254
|
-
},
|
|
1255
|
-
enumerable: true,
|
|
1256
|
-
configurable: true
|
|
1257
|
-
});
|
|
1258
|
-
return fn;
|
|
1352
|
+
return new GraphOutput(summary, finalOutput, nodeResults, t0, t1, qualityReview);
|
|
1259
1353
|
}
|
|
1260
|
-
var \u0393 =
|
|
1354
|
+
var \u0393 = createPatternTag(defaults7, execute7);
|
|
1261
1355
|
|
|
1262
1356
|
// src/patterns/memory.ts
|
|
1263
1357
|
var defaults8 = {
|
|
@@ -1266,27 +1360,6 @@ var defaults8 = {
|
|
|
1266
1360
|
agents: 3,
|
|
1267
1361
|
rounds: 1
|
|
1268
1362
|
};
|
|
1269
|
-
var ROLE_SETS3 = {
|
|
1270
|
-
2: ["Analyst \u2014 deep analysis of core aspects", "Reviewer \u2014 check for gaps and blind spots"],
|
|
1271
|
-
3: [
|
|
1272
|
-
"Analyst \u2014 deep analysis of core aspects",
|
|
1273
|
-
"Reviewer \u2014 check for gaps, edge cases, and blind spots",
|
|
1274
|
-
"Strategist \u2014 connect findings to actionable insights"
|
|
1275
|
-
],
|
|
1276
|
-
4: [
|
|
1277
|
-
"Analyst",
|
|
1278
|
-
"Reviewer",
|
|
1279
|
-
"Strategist",
|
|
1280
|
-
"Innovator \u2014 propose novel angles and creative solutions"
|
|
1281
|
-
],
|
|
1282
|
-
5: [
|
|
1283
|
-
"Analyst",
|
|
1284
|
-
"Reviewer",
|
|
1285
|
-
"Strategist",
|
|
1286
|
-
"Innovator",
|
|
1287
|
-
"Skeptic \u2014 challenge assumptions and stress-test conclusions"
|
|
1288
|
-
]
|
|
1289
|
-
};
|
|
1290
1363
|
var MemoryEntry = class {
|
|
1291
1364
|
constructor(role, round, content) {
|
|
1292
1365
|
this.role = role;
|
|
@@ -1298,13 +1371,15 @@ var MemoryEntry = class {
|
|
|
1298
1371
|
content;
|
|
1299
1372
|
};
|
|
1300
1373
|
var MemoryOutput = class extends PatternOutput {
|
|
1301
|
-
constructor(text, synthesis, entries, startTime, endTime) {
|
|
1374
|
+
constructor(text, synthesis, entries, startTime, endTime, qualityReview) {
|
|
1302
1375
|
super(text, startTime, endTime);
|
|
1303
1376
|
this.synthesis = synthesis;
|
|
1304
1377
|
this.entries = entries;
|
|
1378
|
+
this.qualityReview = qualityReview;
|
|
1305
1379
|
}
|
|
1306
1380
|
synthesis;
|
|
1307
1381
|
entries;
|
|
1382
|
+
qualityReview;
|
|
1308
1383
|
};
|
|
1309
1384
|
var WRITER_PROMPT = `You are a specialist with role: {role}.
|
|
1310
1385
|
|
|
@@ -1325,7 +1400,7 @@ async function execute8(pieces, args, opts) {
|
|
|
1325
1400
|
const t0 = Date.now();
|
|
1326
1401
|
const agentCount = opts.agents ?? 3;
|
|
1327
1402
|
const totalRounds = opts.rounds ?? 1;
|
|
1328
|
-
const roles = opts.roles ??
|
|
1403
|
+
const roles = opts.roles ?? MEMORY_ROLE_SETS[agentCount] ?? MEMORY_ROLE_SETS[3] ?? [];
|
|
1329
1404
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
1330
1405
|
const workerModel = opts.workerModel ?? opts.model;
|
|
1331
1406
|
if (!opts.quiet) {
|
|
@@ -1342,11 +1417,7 @@ async function execute8(pieces, args, opts) {
|
|
|
1342
1417
|
const roundResults = await Promise.allSettled(
|
|
1343
1418
|
roles.map(async (role) => {
|
|
1344
1419
|
const prompt = buildWriterPrompt(role, topic, blackboard);
|
|
1345
|
-
const text = await ask(prompt, {
|
|
1346
|
-
model: workerModel,
|
|
1347
|
-
maxTokens: opts.maxTokens,
|
|
1348
|
-
thinkingLevel: opts.thinkingLevel
|
|
1349
|
-
});
|
|
1420
|
+
const text = await ask(prompt, { ...opts, model: workerModel });
|
|
1350
1421
|
return { role, text };
|
|
1351
1422
|
})
|
|
1352
1423
|
);
|
|
@@ -1368,40 +1439,21 @@ ${blackboard}
|
|
|
1368
1439
|
|
|
1369
1440
|
Consolidate into a comprehensive, structured synthesis.`,
|
|
1370
1441
|
{
|
|
1442
|
+
...opts,
|
|
1371
1443
|
model: plannerModel,
|
|
1372
|
-
maxTokens: opts.maxTokens,
|
|
1373
1444
|
thinkingLevel: "high",
|
|
1374
|
-
system: CONSOLIDATOR_SYSTEM
|
|
1445
|
+
system: mergeSystem(opts.system, CONSOLIDATOR_SYSTEM)
|
|
1375
1446
|
}
|
|
1376
1447
|
);
|
|
1448
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1449
|
+
const qualityReview = await runQualityReview(topic, synthesis, opts);
|
|
1377
1450
|
const t1 = Date.now();
|
|
1378
1451
|
const summary = entries.map(
|
|
1379
1452
|
(e) => `[${e.role}] Round ${e.round}: ${e.content.slice(0, 150)}${e.content.length > 150 ? "..." : ""}`
|
|
1380
1453
|
).join("\n");
|
|
1381
|
-
return new MemoryOutput(summary, synthesis, entries, t0, t1);
|
|
1382
|
-
}
|
|
1383
|
-
function makeMemory(opts = {}) {
|
|
1384
|
-
const merged = { ...defaults8, ...opts };
|
|
1385
|
-
const fn = ((pieces, ...args) => {
|
|
1386
|
-
if (!Array.isArray(pieces)) {
|
|
1387
|
-
return makeMemory({ ...merged, ...pieces });
|
|
1388
|
-
}
|
|
1389
|
-
return new PatternPromise((resolve, reject) => {
|
|
1390
|
-
execute8(pieces, args, merged).then(resolve, reject);
|
|
1391
|
-
});
|
|
1392
|
-
});
|
|
1393
|
-
let _quiet;
|
|
1394
|
-
Object.defineProperty(fn, "quiet", {
|
|
1395
|
-
get() {
|
|
1396
|
-
if (!_quiet) _quiet = makeMemory({ ...merged, quiet: true });
|
|
1397
|
-
return _quiet;
|
|
1398
|
-
},
|
|
1399
|
-
enumerable: true,
|
|
1400
|
-
configurable: true
|
|
1401
|
-
});
|
|
1402
|
-
return fn;
|
|
1454
|
+
return new MemoryOutput(summary, synthesis, entries, t0, t1, qualityReview);
|
|
1403
1455
|
}
|
|
1404
|
-
var \u039C =
|
|
1456
|
+
var \u039C = createPatternTag(defaults8, execute8);
|
|
1405
1457
|
|
|
1406
1458
|
// src/patterns/nu.ts
|
|
1407
1459
|
var defaults9 = {
|
|
@@ -1421,19 +1473,21 @@ var NuRole = class {
|
|
|
1421
1473
|
goal;
|
|
1422
1474
|
};
|
|
1423
1475
|
var NuOutput = class extends PatternOutput {
|
|
1424
|
-
constructor(text, negotiatedRoles, workflow, workflowReasoning, roleResults, synthesis, startTime, endTime) {
|
|
1476
|
+
constructor(text, negotiatedRoles, workflow, workflowReasoning, roleResults, synthesis, startTime, endTime, qualityReview) {
|
|
1425
1477
|
super(text, startTime, endTime);
|
|
1426
1478
|
this.negotiatedRoles = negotiatedRoles;
|
|
1427
1479
|
this.workflow = workflow;
|
|
1428
1480
|
this.workflowReasoning = workflowReasoning;
|
|
1429
1481
|
this.roleResults = roleResults;
|
|
1430
1482
|
this.synthesis = synthesis;
|
|
1483
|
+
this.qualityReview = qualityReview;
|
|
1431
1484
|
}
|
|
1432
1485
|
negotiatedRoles;
|
|
1433
1486
|
workflow;
|
|
1434
1487
|
workflowReasoning;
|
|
1435
1488
|
roleResults;
|
|
1436
1489
|
synthesis;
|
|
1490
|
+
qualityReview;
|
|
1437
1491
|
};
|
|
1438
1492
|
var NEGOTIATE_SYSTEM = `You are a team architect. Given a task, propose a team of specialized agents. Each role must have a distinct name, expertise, and goal.
|
|
1439
1493
|
|
|
@@ -1471,6 +1525,7 @@ async function negotiateRoles(task, opts) {
|
|
|
1471
1525
|
const response = await ask(`Task: ${task}
|
|
1472
1526
|
|
|
1473
1527
|
${prompt}`, {
|
|
1528
|
+
...opts,
|
|
1474
1529
|
model: opts.plannerModel ?? opts.model,
|
|
1475
1530
|
maxTokens: 2048,
|
|
1476
1531
|
thinkingLevel: "high"
|
|
@@ -1507,10 +1562,11 @@ ${rolesText}
|
|
|
1507
1562
|
|
|
1508
1563
|
Determine the best execution strategy.`,
|
|
1509
1564
|
{
|
|
1565
|
+
...opts,
|
|
1510
1566
|
model: opts.plannerModel ?? opts.model,
|
|
1511
1567
|
maxTokens: 512,
|
|
1512
1568
|
thinkingLevel: "high",
|
|
1513
|
-
system: WORKFLOW_SYSTEM
|
|
1569
|
+
system: mergeSystem(opts.system, WORKFLOW_SYSTEM)
|
|
1514
1570
|
}
|
|
1515
1571
|
);
|
|
1516
1572
|
const wfMatch = response.match(/WORKFLOW\s*:\s*(.+)/i);
|
|
@@ -1529,10 +1585,9 @@ async function executeRoles(roles, task, workflow, opts) {
|
|
|
1529
1585
|
let context = task;
|
|
1530
1586
|
for (const role of roles) {
|
|
1531
1587
|
const output = await ask(context, {
|
|
1588
|
+
...opts,
|
|
1532
1589
|
model: workerModel,
|
|
1533
|
-
|
|
1534
|
-
thinkingLevel: opts.thinkingLevel,
|
|
1535
|
-
system: EXECUTE_SYSTEM2(role)
|
|
1590
|
+
system: mergeSystem(opts.system, EXECUTE_SYSTEM2(role))
|
|
1536
1591
|
});
|
|
1537
1592
|
results.push({ role: role.name, output });
|
|
1538
1593
|
context = `Previous output from ${role.name}:
|
|
@@ -1544,10 +1599,9 @@ Continue with: ${task}`;
|
|
|
1544
1599
|
const parallelResults = await Promise.allSettled(
|
|
1545
1600
|
roles.map(
|
|
1546
1601
|
(role) => ask(task, {
|
|
1602
|
+
...opts,
|
|
1547
1603
|
model: workerModel,
|
|
1548
|
-
|
|
1549
|
-
thinkingLevel: opts.thinkingLevel,
|
|
1550
|
-
system: EXECUTE_SYSTEM2(role)
|
|
1604
|
+
system: mergeSystem(opts.system, EXECUTE_SYSTEM2(role))
|
|
1551
1605
|
}).then((text) => ({ role: role.name, output: text })).catch((err) => ({ role: role.name, output: `(failed: ${String(err)})` }))
|
|
1552
1606
|
)
|
|
1553
1607
|
);
|
|
@@ -1569,10 +1623,10 @@ ${resultsText}
|
|
|
1569
1623
|
|
|
1570
1624
|
Synthesize a comprehensive final answer.`,
|
|
1571
1625
|
{
|
|
1626
|
+
...opts,
|
|
1572
1627
|
model: opts.plannerModel ?? opts.model,
|
|
1573
|
-
maxTokens: opts.maxTokens,
|
|
1574
1628
|
thinkingLevel: "high",
|
|
1575
|
-
system: SYNTHESIS_SYSTEM3
|
|
1629
|
+
system: mergeSystem(opts.system, SYNTHESIS_SYSTEM3)
|
|
1576
1630
|
}
|
|
1577
1631
|
);
|
|
1578
1632
|
}
|
|
@@ -1613,6 +1667,8 @@ async function execute9(pieces, args, opts) {
|
|
|
1613
1667
|
const roleResults = await executeRoles(roles, task, workflow, opts);
|
|
1614
1668
|
if (!opts.quiet) process.stderr.write(" \u2192 Synthesizing...\n");
|
|
1615
1669
|
const synthesis = await synthesize(task, roleResults, { ...opts, plannerModel });
|
|
1670
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1671
|
+
const qualityReview = await runQualityReview(task, synthesis, opts);
|
|
1616
1672
|
const t1 = Date.now();
|
|
1617
1673
|
const summary = [
|
|
1618
1674
|
`Roles: ${roles.map((r) => r.name).join(", ")}`,
|
|
@@ -1620,30 +1676,19 @@ async function execute9(pieces, args, opts) {
|
|
|
1620
1676
|
`Results: ${roleResults.length}/${roles.length} succeeded`,
|
|
1621
1677
|
`Synthesis: ${synthesis}`
|
|
1622
1678
|
].join("\n\n");
|
|
1623
|
-
return new NuOutput(
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
});
|
|
1635
|
-
let _quiet;
|
|
1636
|
-
Object.defineProperty(fn, "quiet", {
|
|
1637
|
-
get() {
|
|
1638
|
-
if (!_quiet) _quiet = makeNu({ ...merged, quiet: true });
|
|
1639
|
-
return _quiet;
|
|
1640
|
-
},
|
|
1641
|
-
enumerable: true,
|
|
1642
|
-
configurable: true
|
|
1643
|
-
});
|
|
1644
|
-
return fn;
|
|
1679
|
+
return new NuOutput(
|
|
1680
|
+
summary,
|
|
1681
|
+
roles,
|
|
1682
|
+
workflow,
|
|
1683
|
+
reasoning,
|
|
1684
|
+
roleResults,
|
|
1685
|
+
synthesis,
|
|
1686
|
+
t0,
|
|
1687
|
+
t1,
|
|
1688
|
+
qualityReview
|
|
1689
|
+
);
|
|
1645
1690
|
}
|
|
1646
|
-
var \u039D =
|
|
1691
|
+
var \u039D = createPatternTag(defaults9, execute9);
|
|
1647
1692
|
|
|
1648
1693
|
// src/patterns/orchestrator.ts
|
|
1649
1694
|
var defaults10 = {
|
|
@@ -1663,15 +1708,17 @@ var OrchestratorWorkerResult = class {
|
|
|
1663
1708
|
success;
|
|
1664
1709
|
};
|
|
1665
1710
|
var OrchestratorOutput = class extends PatternOutput {
|
|
1666
|
-
constructor(text, plan, synthesis, workerResults, startTime, endTime) {
|
|
1711
|
+
constructor(text, plan, synthesis, workerResults, startTime, endTime, qualityReview) {
|
|
1667
1712
|
super(text, startTime, endTime);
|
|
1668
1713
|
this.plan = plan;
|
|
1669
1714
|
this.synthesis = synthesis;
|
|
1670
1715
|
this.workerResults = workerResults;
|
|
1716
|
+
this.qualityReview = qualityReview;
|
|
1671
1717
|
}
|
|
1672
1718
|
plan;
|
|
1673
1719
|
synthesis;
|
|
1674
1720
|
workerResults;
|
|
1721
|
+
qualityReview;
|
|
1675
1722
|
};
|
|
1676
1723
|
var PLANNER_SYSTEM = `You are a senior architect and project planner. Given a high-level request, create a detailed execution plan.
|
|
1677
1724
|
|
|
@@ -1694,6 +1741,7 @@ async function execute10(pieces, args, opts) {
|
|
|
1694
1741
|
const request = build(pieces, args);
|
|
1695
1742
|
const t0 = Date.now();
|
|
1696
1743
|
const workerCount = opts.workers ?? 3;
|
|
1744
|
+
const phases = [];
|
|
1697
1745
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
1698
1746
|
const workerModel = opts.workerModel ?? opts.model;
|
|
1699
1747
|
if (!opts.quiet) {
|
|
@@ -1703,11 +1751,18 @@ async function execute10(pieces, args, opts) {
|
|
|
1703
1751
|
);
|
|
1704
1752
|
}
|
|
1705
1753
|
if (!opts.quiet) process.stderr.write(" \u2192 Planning...\n");
|
|
1754
|
+
const planStart = Date.now();
|
|
1706
1755
|
const planText = await ask(request, {
|
|
1756
|
+
...opts,
|
|
1707
1757
|
model: plannerModel,
|
|
1708
|
-
maxTokens: opts.maxTokens,
|
|
1709
1758
|
thinkingLevel: "high",
|
|
1710
|
-
system: PLANNER_SYSTEM.replace("{$workerCount}", String(workerCount))
|
|
1759
|
+
system: mergeSystem(opts.system, PLANNER_SYSTEM.replace("{$workerCount}", String(workerCount)))
|
|
1760
|
+
});
|
|
1761
|
+
phases.push({
|
|
1762
|
+
phase: "plan",
|
|
1763
|
+
durationMs: Date.now() - planStart,
|
|
1764
|
+
description: `Generated plan with ${workerCount} workers`,
|
|
1765
|
+
modelUsed: plannerModel
|
|
1711
1766
|
});
|
|
1712
1767
|
const subTasks = [];
|
|
1713
1768
|
const taskLines = planText.split("\n");
|
|
@@ -1731,27 +1786,37 @@ async function execute10(pieces, args, opts) {
|
|
|
1731
1786
|
`);
|
|
1732
1787
|
}
|
|
1733
1788
|
}
|
|
1789
|
+
const planSummary = tasks.length > 0 ? `Execute ${tasks.length} sub-task(s) as planned?
|
|
1790
|
+
${tasks.map((t, i) => `${i + 1}. ${t.slice(0, 80)}`).join("\n ")}` : `Execute the plan?`;
|
|
1791
|
+
if (!await confirmPhase(planSummary, opts)) {
|
|
1792
|
+
throw new Error("pizx/\u03A9: Execution cancelled by user.");
|
|
1793
|
+
}
|
|
1734
1794
|
const workerResults = [];
|
|
1735
1795
|
const concurrency = opts.concurrency ?? 3;
|
|
1796
|
+
const dispatchStart = Date.now();
|
|
1736
1797
|
for (let i = 0; i < tasks.length; i += concurrency) {
|
|
1737
1798
|
const batch = tasks.slice(i, i + concurrency);
|
|
1738
1799
|
const batchResults = await Promise.allSettled(
|
|
1739
1800
|
batch.map(
|
|
1740
|
-
(task) => ask(task, {
|
|
1741
|
-
model: workerModel,
|
|
1742
|
-
maxTokens: opts.maxTokens,
|
|
1743
|
-
thinkingLevel: opts.thinkingLevel,
|
|
1744
|
-
system: WORKER_SYSTEM
|
|
1745
|
-
}).then((text) => new OrchestratorWorkerResult(task, text, true)).catch((err) => new OrchestratorWorkerResult(task, String(err), false))
|
|
1801
|
+
(task) => ask(task, { ...opts, model: workerModel, system: mergeSystem(opts.system, WORKER_SYSTEM) }).then((text) => new OrchestratorWorkerResult(task, text, true)).catch((err) => new OrchestratorWorkerResult(task, String(err), false))
|
|
1746
1802
|
)
|
|
1747
1803
|
);
|
|
1748
1804
|
batchResults.forEach((r) => {
|
|
1749
1805
|
if (r.status === "fulfilled") workerResults.push(r.value);
|
|
1750
1806
|
});
|
|
1751
1807
|
}
|
|
1808
|
+
const succeeded = workerResults.filter((w) => w.success).length;
|
|
1809
|
+
phases.push({
|
|
1810
|
+
phase: "dispatch",
|
|
1811
|
+
durationMs: Date.now() - dispatchStart,
|
|
1812
|
+
description: `Executed ${workerResults.length} worker(s), ${succeeded} succeeded`,
|
|
1813
|
+
modelUsed: workerModel,
|
|
1814
|
+
callCount: workerResults.length
|
|
1815
|
+
});
|
|
1752
1816
|
if (!opts.quiet) process.stderr.write(" \u2192 Synthesizing results...\n");
|
|
1753
1817
|
const workerTexts = workerResults.map((wr, i) => `Task ${i + 1}: ${wr.task}
|
|
1754
1818
|
Result: ${wr.output}`).join("\n\n");
|
|
1819
|
+
const synthStart = Date.now();
|
|
1755
1820
|
const synthesis = await ask(
|
|
1756
1821
|
`Original request:
|
|
1757
1822
|
${request}
|
|
@@ -1764,46 +1829,60 @@ ${workerTexts}
|
|
|
1764
1829
|
|
|
1765
1830
|
Synthesize a final deliverable.`,
|
|
1766
1831
|
{
|
|
1832
|
+
...opts,
|
|
1767
1833
|
model: plannerModel,
|
|
1768
|
-
maxTokens: opts.maxTokens,
|
|
1769
1834
|
thinkingLevel: "high",
|
|
1770
|
-
system: SYNTHESIS_SYSTEM4
|
|
1835
|
+
system: mergeSystem(opts.system, SYNTHESIS_SYSTEM4)
|
|
1771
1836
|
}
|
|
1772
1837
|
);
|
|
1838
|
+
phases.push({
|
|
1839
|
+
phase: "synthesize",
|
|
1840
|
+
durationMs: Date.now() - synthStart,
|
|
1841
|
+
description: "Synthesized worker results into final deliverable",
|
|
1842
|
+
modelUsed: plannerModel
|
|
1843
|
+
});
|
|
1844
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1845
|
+
const qualityStart = Date.now();
|
|
1846
|
+
const qualityReview = await runQualityReview(request, synthesis, opts);
|
|
1847
|
+
if (qualityReview) {
|
|
1848
|
+
phases.push({
|
|
1849
|
+
phase: "quality-review",
|
|
1850
|
+
durationMs: Date.now() - qualityStart,
|
|
1851
|
+
description: `Score: ${qualityReview.score.toFixed(2)} \u2014 ${qualityReview.assessment.slice(0, 60)}`,
|
|
1852
|
+
modelUsed: plannerModel
|
|
1853
|
+
});
|
|
1854
|
+
}
|
|
1773
1855
|
const t1 = Date.now();
|
|
1856
|
+
const reviewSection = qualityReview ? `
|
|
1857
|
+
|
|
1858
|
+
Quality Review: ${qualityReview.score.toFixed(2)} \u2014 ${qualityReview.assessment}
|
|
1859
|
+
Recommendation: ${qualityReview.recommendation}` : "";
|
|
1774
1860
|
const summary = `Plan:
|
|
1775
1861
|
${planText}
|
|
1776
1862
|
|
|
1777
1863
|
Workers: ${workerResults.filter((w) => w.success).length}/${workerResults.length} succeeded
|
|
1778
1864
|
|
|
1779
1865
|
Synthesis:
|
|
1780
|
-
${synthesis}`;
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
});
|
|
1793
|
-
let _quiet;
|
|
1794
|
-
Object.defineProperty(fn, "quiet", {
|
|
1795
|
-
get() {
|
|
1796
|
-
if (!_quiet) _quiet = makeOrchestrator({ ...merged, quiet: true });
|
|
1797
|
-
return _quiet;
|
|
1798
|
-
},
|
|
1799
|
-
enumerable: true,
|
|
1800
|
-
configurable: true
|
|
1801
|
-
});
|
|
1802
|
-
return fn;
|
|
1866
|
+
${synthesis}${reviewSection}`;
|
|
1867
|
+
const output = new OrchestratorOutput(
|
|
1868
|
+
summary,
|
|
1869
|
+
planText,
|
|
1870
|
+
synthesis,
|
|
1871
|
+
workerResults,
|
|
1872
|
+
t0,
|
|
1873
|
+
t1,
|
|
1874
|
+
qualityReview
|
|
1875
|
+
);
|
|
1876
|
+
output.phaseLog = phases;
|
|
1877
|
+
return output;
|
|
1803
1878
|
}
|
|
1804
|
-
var \u03A9 =
|
|
1879
|
+
var \u03A9 = createPatternTag(defaults10, execute10);
|
|
1805
1880
|
|
|
1806
1881
|
// src/patterns/pipeline.ts
|
|
1882
|
+
function describeStage(stage) {
|
|
1883
|
+
if (typeof stage === "function") return "(composed pattern)";
|
|
1884
|
+
return stage;
|
|
1885
|
+
}
|
|
1807
1886
|
var defaults11 = {
|
|
1808
1887
|
maxTokens: 4096,
|
|
1809
1888
|
thinkingLevel: "medium"
|
|
@@ -1819,13 +1898,15 @@ var PipelineStageResult = class {
|
|
|
1819
1898
|
index;
|
|
1820
1899
|
};
|
|
1821
1900
|
var PipelineOutput = class extends PatternOutput {
|
|
1822
|
-
constructor(text, finalOutput, stages, startTime, endTime) {
|
|
1901
|
+
constructor(text, finalOutput, stages, startTime, endTime, qualityReview) {
|
|
1823
1902
|
super(text, startTime, endTime);
|
|
1824
1903
|
this.finalOutput = finalOutput;
|
|
1825
1904
|
this.stages = stages;
|
|
1905
|
+
this.qualityReview = qualityReview;
|
|
1826
1906
|
}
|
|
1827
1907
|
finalOutput;
|
|
1828
1908
|
stages;
|
|
1909
|
+
qualityReview;
|
|
1829
1910
|
};
|
|
1830
1911
|
function parseStages(template, explicitStages, separator) {
|
|
1831
1912
|
if (explicitStages && explicitStages.length > 0) return explicitStages;
|
|
@@ -1867,55 +1948,46 @@ async function execute11(pieces, args, opts) {
|
|
|
1867
1948
|
`);
|
|
1868
1949
|
}
|
|
1869
1950
|
}
|
|
1951
|
+
const stageSummary = `Run ${stages.length} pipeline stage(s)?
|
|
1952
|
+
${stages.map((s, i) => `${i + 1}. ${describeStage(s)}`).join("\n ")}`;
|
|
1953
|
+
if (!await confirmPhase(stageSummary, opts)) {
|
|
1954
|
+
throw new Error("pizx/\u039B: Execution cancelled by user.");
|
|
1955
|
+
}
|
|
1870
1956
|
const stageResults = [];
|
|
1871
1957
|
let currentInput = "";
|
|
1872
1958
|
for (let i = 0; i < stages.length; i++) {
|
|
1873
1959
|
const stage = stages[i];
|
|
1960
|
+
const stageLabel = describeStage(stage);
|
|
1874
1961
|
const customPrompt = opts.stagePrompts?.[i];
|
|
1875
1962
|
if (!opts.quiet)
|
|
1876
|
-
process.stderr.write(` \u2192 Stage ${i + 1}/${stages.length}: ${
|
|
1963
|
+
process.stderr.write(` \u2192 Stage ${i + 1}/${stages.length}: ${stageLabel.slice(0, 50)}...
|
|
1877
1964
|
`);
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1965
|
+
let output;
|
|
1966
|
+
if (typeof stage === "function") {
|
|
1967
|
+
output = await stage(currentInput);
|
|
1968
|
+
} else {
|
|
1969
|
+
const prompt = customPrompt ?? generateStagePrompt(stage, currentInput, i === 0);
|
|
1970
|
+
const systemMessage = i === 0 ? `You are a specialist executing stage ${i + 1}: ${stage}. Focus only on this stage's output.` : `You are a specialist executing stage ${i + 1}: ${stage}. Process the previous stage's output according to your instructions. Maintain all important information from previous stages.`;
|
|
1971
|
+
output = await ask(prompt, {
|
|
1972
|
+
...opts,
|
|
1973
|
+
model: workerModel,
|
|
1974
|
+
system: mergeSystem(opts.system, systemMessage)
|
|
1975
|
+
});
|
|
1976
|
+
}
|
|
1977
|
+
stageResults.push(new PipelineStageResult(stageLabel, output, i));
|
|
1887
1978
|
currentInput = output;
|
|
1888
1979
|
}
|
|
1889
1980
|
const t1 = Date.now();
|
|
1890
1981
|
const finalOutput = currentInput;
|
|
1982
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1983
|
+
const qualityReview = await runQualityReview(template, finalOutput, opts);
|
|
1891
1984
|
const summary = stageResults.map(
|
|
1892
1985
|
(sr) => `Stage ${sr.index + 1} (${sr.stage}):
|
|
1893
1986
|
${sr.output.slice(0, 200)}${sr.output.length > 200 ? "..." : ""}`
|
|
1894
1987
|
).join("\n\n");
|
|
1895
|
-
return new PipelineOutput(summary, finalOutput, stageResults, t0, t1);
|
|
1896
|
-
}
|
|
1897
|
-
function makePipeline(opts = {}) {
|
|
1898
|
-
const merged = { ...defaults11, ...opts };
|
|
1899
|
-
const fn = ((pieces, ...args) => {
|
|
1900
|
-
if (!Array.isArray(pieces)) {
|
|
1901
|
-
return makePipeline({ ...merged, ...pieces });
|
|
1902
|
-
}
|
|
1903
|
-
return new PatternPromise((resolve, reject) => {
|
|
1904
|
-
execute11(pieces, args, merged).then(resolve, reject);
|
|
1905
|
-
});
|
|
1906
|
-
});
|
|
1907
|
-
let _quiet;
|
|
1908
|
-
Object.defineProperty(fn, "quiet", {
|
|
1909
|
-
get() {
|
|
1910
|
-
if (!_quiet) _quiet = makePipeline({ ...merged, quiet: true });
|
|
1911
|
-
return _quiet;
|
|
1912
|
-
},
|
|
1913
|
-
enumerable: true,
|
|
1914
|
-
configurable: true
|
|
1915
|
-
});
|
|
1916
|
-
return fn;
|
|
1988
|
+
return new PipelineOutput(summary, finalOutput, stageResults, t0, t1, qualityReview);
|
|
1917
1989
|
}
|
|
1918
|
-
var \u039B =
|
|
1990
|
+
var \u039B = createPatternTag(defaults11, execute11);
|
|
1919
1991
|
|
|
1920
1992
|
// src/patterns/ralph.ts
|
|
1921
1993
|
import { createAgentSession } from "@earendil-works/pi-coding-agent";
|
|
@@ -1950,17 +2022,17 @@ async function executeWithTools(goal, opts) {
|
|
|
1950
2022
|
});
|
|
1951
2023
|
try {
|
|
1952
2024
|
await session.sendUserMessage(goal);
|
|
1953
|
-
const
|
|
1954
|
-
for (let i =
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2025
|
+
const messages = session.messages;
|
|
2026
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2027
|
+
const msg = messages[i];
|
|
2028
|
+
if (msg?.role !== "assistant") continue;
|
|
2029
|
+
const c = "content" in msg ? msg.content : void 0;
|
|
2030
|
+
if (typeof c === "string") return c.trim();
|
|
2031
|
+
if (Array.isArray(c)) {
|
|
2032
|
+
const texts = c.filter(
|
|
2033
|
+
(x) => x.type === "text" && typeof x.text === "string"
|
|
2034
|
+
).map((x) => x.text);
|
|
2035
|
+
if (texts.length > 0) return texts.join("").trim();
|
|
1964
2036
|
}
|
|
1965
2037
|
}
|
|
1966
2038
|
return "(no assistant response)";
|
|
@@ -1995,10 +2067,9 @@ async function execute12(pieces, args, opts) {
|
|
|
1995
2067
|
}
|
|
1996
2068
|
if (!opts.quiet) process.stderr.write(" \u2192 Analyzing...\n");
|
|
1997
2069
|
const analysis = await ask(currentGoal, {
|
|
2070
|
+
...opts,
|
|
1998
2071
|
model: plannerModel,
|
|
1999
|
-
|
|
2000
|
-
thinkingLevel: opts.thinkingLevel,
|
|
2001
|
-
system: ANALYSIS_SYSTEM2
|
|
2072
|
+
system: mergeSystem(opts.system, ANALYSIS_SYSTEM2)
|
|
2002
2073
|
});
|
|
2003
2074
|
if (!opts.quiet) process.stderr.write(" \u2192 Planning...\n");
|
|
2004
2075
|
const plan = await ask(
|
|
@@ -2007,12 +2078,7 @@ async function execute12(pieces, args, opts) {
|
|
|
2007
2078
|
Analysis: ${analysis}
|
|
2008
2079
|
|
|
2009
2080
|
Generate an implementation plan.`,
|
|
2010
|
-
{
|
|
2011
|
-
model: plannerModel,
|
|
2012
|
-
maxTokens: opts.maxTokens,
|
|
2013
|
-
thinkingLevel: opts.thinkingLevel,
|
|
2014
|
-
system: PLAN_SYSTEM2
|
|
2015
|
-
}
|
|
2081
|
+
{ ...opts, model: plannerModel, system: mergeSystem(opts.system, PLAN_SYSTEM2) }
|
|
2016
2082
|
);
|
|
2017
2083
|
if (!opts.quiet) process.stderr.write(" \u2192 Executing...\n");
|
|
2018
2084
|
const result = opts.useTools ? await executeWithTools(`Implement this plan:
|
|
@@ -2025,9 +2091,8 @@ Goal: ${currentGoal}`, {
|
|
|
2025
2091
|
${plan}
|
|
2026
2092
|
|
|
2027
2093
|
Goal: ${currentGoal}`, {
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
thinkingLevel: opts.thinkingLevel
|
|
2094
|
+
...opts,
|
|
2095
|
+
model: workerModel
|
|
2031
2096
|
});
|
|
2032
2097
|
if (!opts.quiet) process.stderr.write(" \u2192 Reviewing...\n");
|
|
2033
2098
|
const review = await ask(`Plan:
|
|
@@ -2037,10 +2102,11 @@ Result:
|
|
|
2037
2102
|
${result}
|
|
2038
2103
|
|
|
2039
2104
|
Review the implementation.`, {
|
|
2105
|
+
...opts,
|
|
2040
2106
|
model: plannerModel,
|
|
2041
2107
|
maxTokens: 1024,
|
|
2042
2108
|
thinkingLevel: "high",
|
|
2043
|
-
system: REVIEW_SYSTEM
|
|
2109
|
+
system: mergeSystem(opts.system, REVIEW_SYSTEM)
|
|
2044
2110
|
});
|
|
2045
2111
|
const shouldContinue = review.includes("ITERATE") && !review.includes("DONE");
|
|
2046
2112
|
iterations.push({
|
|
@@ -2076,28 +2142,7 @@ Original goal: ${goal}`;
|
|
|
2076
2142
|
t1
|
|
2077
2143
|
);
|
|
2078
2144
|
}
|
|
2079
|
-
|
|
2080
|
-
const merged = { ...defaults12, ...opts };
|
|
2081
|
-
const fn = ((pieces, ...args) => {
|
|
2082
|
-
if (!Array.isArray(pieces)) {
|
|
2083
|
-
return makeRalph({ ...merged, ...pieces });
|
|
2084
|
-
}
|
|
2085
|
-
return new PatternPromise((resolve, reject) => {
|
|
2086
|
-
execute12(pieces, args, merged).then(resolve, reject);
|
|
2087
|
-
});
|
|
2088
|
-
});
|
|
2089
|
-
let _quiet;
|
|
2090
|
-
Object.defineProperty(fn, "quiet", {
|
|
2091
|
-
get() {
|
|
2092
|
-
if (!_quiet) _quiet = makeRalph({ ...merged, quiet: true });
|
|
2093
|
-
return _quiet;
|
|
2094
|
-
},
|
|
2095
|
-
enumerable: true,
|
|
2096
|
-
configurable: true
|
|
2097
|
-
});
|
|
2098
|
-
return fn;
|
|
2099
|
-
}
|
|
2100
|
-
var \u03A1 = makeRalph();
|
|
2145
|
+
var \u03A1 = createPatternTag(defaults12, execute12);
|
|
2101
2146
|
|
|
2102
2147
|
// src/patterns/subagent.ts
|
|
2103
2148
|
var defaults13 = {
|
|
@@ -2117,13 +2162,15 @@ var SubagentResult = class {
|
|
|
2117
2162
|
success;
|
|
2118
2163
|
};
|
|
2119
2164
|
var SubagentOutput = class extends PatternOutput {
|
|
2120
|
-
constructor(text, synthesis, subResults, startTime, endTime) {
|
|
2165
|
+
constructor(text, synthesis, subResults, startTime, endTime, qualityReview) {
|
|
2121
2166
|
super(text, startTime, endTime);
|
|
2122
2167
|
this.synthesis = synthesis;
|
|
2123
2168
|
this.subResults = subResults;
|
|
2169
|
+
this.qualityReview = qualityReview;
|
|
2124
2170
|
}
|
|
2125
2171
|
synthesis;
|
|
2126
2172
|
subResults;
|
|
2173
|
+
qualityReview;
|
|
2127
2174
|
};
|
|
2128
2175
|
var DECOMPOSE_SYSTEM = `You are a task decomposition specialist. Break down complex tasks into independent sub-tasks that can be worked on in parallel. Output ONLY a JSON array of strings, each being a self-contained sub-task description. No markdown, no explanation.`;
|
|
2129
2176
|
var SYNTHESIS_SYSTEM5 = `You are a synthesis specialist. Combine the results from multiple sub-agent analyses into a coherent, comprehensive answer. Identify patterns, conflicts, and gaps.`;
|
|
@@ -2136,10 +2183,11 @@ ${task}
|
|
|
2136
2183
|
|
|
2137
2184
|
Output a JSON array of strings.`,
|
|
2138
2185
|
{
|
|
2186
|
+
...opts,
|
|
2139
2187
|
model: opts.model,
|
|
2140
2188
|
maxTokens: 1024,
|
|
2141
2189
|
thinkingLevel: "medium",
|
|
2142
|
-
system: DECOMPOSE_SYSTEM
|
|
2190
|
+
system: mergeSystem(opts.system, DECOMPOSE_SYSTEM)
|
|
2143
2191
|
}
|
|
2144
2192
|
);
|
|
2145
2193
|
try {
|
|
@@ -2160,6 +2208,7 @@ var SUBAGENT_SYSTEM = `You are a domain specialist. Complete your assigned sub-t
|
|
|
2160
2208
|
async function execute13(pieces, args, opts) {
|
|
2161
2209
|
const task = build(pieces, args);
|
|
2162
2210
|
const t0 = Date.now();
|
|
2211
|
+
const phases = [];
|
|
2163
2212
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
2164
2213
|
const workerModel = opts.workerModel ?? opts.model;
|
|
2165
2214
|
if (!opts.quiet) {
|
|
@@ -2169,7 +2218,14 @@ async function execute13(pieces, args, opts) {
|
|
|
2169
2218
|
);
|
|
2170
2219
|
}
|
|
2171
2220
|
if (!opts.quiet) process.stderr.write(" \u2192 Decomposing task into sub-tasks...\n");
|
|
2221
|
+
const decomposeStart = Date.now();
|
|
2172
2222
|
const subTasks = await decomposeTask(task, { ...opts, model: plannerModel });
|
|
2223
|
+
phases.push({
|
|
2224
|
+
phase: "decompose",
|
|
2225
|
+
durationMs: Date.now() - decomposeStart,
|
|
2226
|
+
description: `Decomposed into ${subTasks.length} sub-task(s)`,
|
|
2227
|
+
modelUsed: plannerModel
|
|
2228
|
+
});
|
|
2173
2229
|
if (!opts.quiet) {
|
|
2174
2230
|
process.stderr.write(` \u2192 ${subTasks.length} sub-task(s) identified:
|
|
2175
2231
|
`);
|
|
@@ -2179,27 +2235,37 @@ async function execute13(pieces, args, opts) {
|
|
|
2179
2235
|
`);
|
|
2180
2236
|
}
|
|
2181
2237
|
}
|
|
2238
|
+
const subTaskSummary = `Execute ${subTasks.length} sub-task(s)?
|
|
2239
|
+
${subTasks.map((st, i) => `${i + 1}. ${st.slice(0, 80)}`).join("\n ")}`;
|
|
2240
|
+
if (!await confirmPhase(subTaskSummary, opts)) {
|
|
2241
|
+
throw new Error("pizx/\u03A3: Execution cancelled by user.");
|
|
2242
|
+
}
|
|
2182
2243
|
const subResults = [];
|
|
2183
2244
|
const concurrency = opts.concurrency ?? 4;
|
|
2245
|
+
const execStart = Date.now();
|
|
2184
2246
|
for (let i = 0; i < subTasks.length; i += concurrency) {
|
|
2185
2247
|
const batch = subTasks.slice(i, i + concurrency);
|
|
2186
2248
|
const batchResults = await Promise.allSettled(
|
|
2187
2249
|
batch.map(
|
|
2188
|
-
(st) => ask(st, {
|
|
2189
|
-
model: workerModel,
|
|
2190
|
-
maxTokens: opts.maxTokens,
|
|
2191
|
-
thinkingLevel: opts.thinkingLevel,
|
|
2192
|
-
system: SUBAGENT_SYSTEM
|
|
2193
|
-
}).then((text) => new SubagentResult(st, text, true)).catch((err) => new SubagentResult(st, String(err), false))
|
|
2250
|
+
(st) => ask(st, { ...opts, model: workerModel, system: mergeSystem(opts.system, SUBAGENT_SYSTEM) }).then((text) => new SubagentResult(st, text, true)).catch((err) => new SubagentResult(st, String(err), false))
|
|
2194
2251
|
)
|
|
2195
2252
|
);
|
|
2196
2253
|
batchResults.forEach((r) => {
|
|
2197
2254
|
if (r.status === "fulfilled") subResults.push(r.value);
|
|
2198
2255
|
});
|
|
2199
2256
|
}
|
|
2257
|
+
const succeeded = subResults.filter((r) => r.success).length;
|
|
2258
|
+
phases.push({
|
|
2259
|
+
phase: "execute",
|
|
2260
|
+
durationMs: Date.now() - execStart,
|
|
2261
|
+
description: `Executed ${subResults.length} sub-task(s), ${succeeded} succeeded`,
|
|
2262
|
+
modelUsed: workerModel,
|
|
2263
|
+
callCount: subResults.length
|
|
2264
|
+
});
|
|
2200
2265
|
if (!opts.quiet) process.stderr.write(" \u2192 Synthesizing results...\n");
|
|
2201
2266
|
const subResultsText = subResults.map((sr, i) => `Sub-task ${i + 1}: ${sr.subTask}
|
|
2202
2267
|
Result: ${sr.text}`).join("\n\n");
|
|
2268
|
+
const synthStart = Date.now();
|
|
2203
2269
|
const synthesis = await ask(
|
|
2204
2270
|
`Original task:
|
|
2205
2271
|
${task}
|
|
@@ -2208,38 +2274,31 @@ Sub-task results:
|
|
|
2208
2274
|
${subResultsText}
|
|
2209
2275
|
|
|
2210
2276
|
Synthesize a comprehensive answer.`,
|
|
2211
|
-
{
|
|
2212
|
-
model: plannerModel,
|
|
2213
|
-
maxTokens: opts.maxTokens,
|
|
2214
|
-
thinkingLevel: opts.thinkingLevel,
|
|
2215
|
-
system: SYNTHESIS_SYSTEM5
|
|
2216
|
-
}
|
|
2277
|
+
{ ...opts, model: plannerModel, system: mergeSystem(opts.system, SYNTHESIS_SYSTEM5) }
|
|
2217
2278
|
);
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
const fn = ((pieces, ...args) => {
|
|
2224
|
-
if (!Array.isArray(pieces)) {
|
|
2225
|
-
return makeSubagent({ ...merged, ...pieces });
|
|
2226
|
-
}
|
|
2227
|
-
return new PatternPromise((resolve, reject) => {
|
|
2228
|
-
execute13(pieces, args, merged).then(resolve, reject);
|
|
2229
|
-
});
|
|
2230
|
-
});
|
|
2231
|
-
let _quiet;
|
|
2232
|
-
Object.defineProperty(fn, "quiet", {
|
|
2233
|
-
get() {
|
|
2234
|
-
if (!_quiet) _quiet = makeSubagent({ ...merged, quiet: true });
|
|
2235
|
-
return _quiet;
|
|
2236
|
-
},
|
|
2237
|
-
enumerable: true,
|
|
2238
|
-
configurable: true
|
|
2279
|
+
phases.push({
|
|
2280
|
+
phase: "synthesize",
|
|
2281
|
+
durationMs: Date.now() - synthStart,
|
|
2282
|
+
description: "Synthesized sub-agent results",
|
|
2283
|
+
modelUsed: plannerModel
|
|
2239
2284
|
});
|
|
2240
|
-
|
|
2285
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
2286
|
+
const qStart = Date.now();
|
|
2287
|
+
const qualityReview = await runQualityReview(task, synthesis, opts);
|
|
2288
|
+
if (qualityReview) {
|
|
2289
|
+
phases.push({
|
|
2290
|
+
phase: "quality-review",
|
|
2291
|
+
durationMs: Date.now() - qStart,
|
|
2292
|
+
description: `Score: ${qualityReview.score.toFixed(2)}`,
|
|
2293
|
+
modelUsed: plannerModel
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2296
|
+
const t1 = Date.now();
|
|
2297
|
+
const output = new SubagentOutput(synthesis, synthesis, subResults, t0, t1, qualityReview);
|
|
2298
|
+
output.phaseLog = phases;
|
|
2299
|
+
return output;
|
|
2241
2300
|
}
|
|
2242
|
-
var \u03A3 =
|
|
2301
|
+
var \u03A3 = createPatternTag(defaults13, execute13);
|
|
2243
2302
|
|
|
2244
2303
|
// src/patterns/tau.ts
|
|
2245
2304
|
var defaults14 = {
|
|
@@ -2263,15 +2322,17 @@ var ToolMediatedEntry = class {
|
|
|
2263
2322
|
content;
|
|
2264
2323
|
};
|
|
2265
2324
|
var TauOutput = class extends PatternOutput {
|
|
2266
|
-
constructor(text, entries, finalState, synthesis, startTime, endTime) {
|
|
2325
|
+
constructor(text, entries, finalState, synthesis, startTime, endTime, qualityReview) {
|
|
2267
2326
|
super(text, startTime, endTime);
|
|
2268
2327
|
this.entries = entries;
|
|
2269
2328
|
this.finalState = finalState;
|
|
2270
2329
|
this.synthesis = synthesis;
|
|
2330
|
+
this.qualityReview = qualityReview;
|
|
2271
2331
|
}
|
|
2272
2332
|
entries;
|
|
2273
2333
|
finalState;
|
|
2274
2334
|
synthesis;
|
|
2335
|
+
qualityReview;
|
|
2275
2336
|
};
|
|
2276
2337
|
var SCHEMA_SYSTEM = `You are a coordination architect. Given a task, design a shared structured context for agent collaboration.
|
|
2277
2338
|
|
|
@@ -2326,6 +2387,7 @@ async function defineSchema(task, opts) {
|
|
|
2326
2387
|
const response = await ask(`Task: ${task}
|
|
2327
2388
|
|
|
2328
2389
|
${prompt}`, {
|
|
2390
|
+
...opts,
|
|
2329
2391
|
model: opts.plannerModel ?? opts.model,
|
|
2330
2392
|
maxTokens: 1024,
|
|
2331
2393
|
thinkingLevel: "high"
|
|
@@ -2378,10 +2440,9 @@ async function executeRound(roles, assignments, store, round, opts) {
|
|
|
2378
2440
|
const systemPrompt = isWrite ? WRITE_SYSTEM(role, keysStr).replace("{store}", storeText) : UPDATE_SYSTEM(role, keysStr).replace("{store}", storeText);
|
|
2379
2441
|
const task = isWrite ? `Write your initial findings to your assigned keys: ${keysStr}` : `Review the shared context and update your entries for keys: ${keysStr}`;
|
|
2380
2442
|
const response = await ask(task, {
|
|
2443
|
+
...opts,
|
|
2381
2444
|
model: workerModel,
|
|
2382
|
-
|
|
2383
|
-
thinkingLevel: opts.thinkingLevel,
|
|
2384
|
-
system: systemPrompt
|
|
2445
|
+
system: mergeSystem(opts.system, systemPrompt)
|
|
2385
2446
|
});
|
|
2386
2447
|
return { role, response };
|
|
2387
2448
|
})
|
|
@@ -2421,10 +2482,10 @@ ${storeText}
|
|
|
2421
2482
|
|
|
2422
2483
|
Consolidate into a comprehensive, well-structured synthesis.`,
|
|
2423
2484
|
{
|
|
2485
|
+
...opts,
|
|
2424
2486
|
model: opts.plannerModel ?? opts.model,
|
|
2425
|
-
maxTokens: opts.maxTokens,
|
|
2426
2487
|
thinkingLevel: "high",
|
|
2427
|
-
system: CONSOLIDATE_SYSTEM
|
|
2488
|
+
system: mergeSystem(opts.system, CONSOLIDATE_SYSTEM)
|
|
2428
2489
|
}
|
|
2429
2490
|
);
|
|
2430
2491
|
}
|
|
@@ -2469,6 +2530,8 @@ async function execute14(pieces, args, opts) {
|
|
|
2469
2530
|
}
|
|
2470
2531
|
if (!opts.quiet) process.stderr.write(" \u2192 Consolidating store...\n");
|
|
2471
2532
|
const synthesis = await consolidateStore(task, store, { ...opts, plannerModel });
|
|
2533
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
2534
|
+
const qualityReview = await runQualityReview(task, synthesis, opts);
|
|
2472
2535
|
const t1 = Date.now();
|
|
2473
2536
|
const summary = [
|
|
2474
2537
|
`Schema keys: ${keys.join(", ")}`,
|
|
@@ -2477,30 +2540,9 @@ async function execute14(pieces, args, opts) {
|
|
|
2477
2540
|
`Entries: ${allEntries.length}`,
|
|
2478
2541
|
`Synthesis: ${synthesis}`
|
|
2479
2542
|
].join("\n\n");
|
|
2480
|
-
return new TauOutput(summary, allEntries, store, synthesis, t0, t1);
|
|
2481
|
-
}
|
|
2482
|
-
function makeTau(opts = {}) {
|
|
2483
|
-
const merged = { ...defaults14, ...opts };
|
|
2484
|
-
const fn = ((pieces, ...args) => {
|
|
2485
|
-
if (!Array.isArray(pieces)) {
|
|
2486
|
-
return makeTau({ ...merged, ...pieces });
|
|
2487
|
-
}
|
|
2488
|
-
return new PatternPromise((resolve, reject) => {
|
|
2489
|
-
execute14(pieces, args, merged).then(resolve, reject);
|
|
2490
|
-
});
|
|
2491
|
-
});
|
|
2492
|
-
let _quiet;
|
|
2493
|
-
Object.defineProperty(fn, "quiet", {
|
|
2494
|
-
get() {
|
|
2495
|
-
if (!_quiet) _quiet = makeTau({ ...merged, quiet: true });
|
|
2496
|
-
return _quiet;
|
|
2497
|
-
},
|
|
2498
|
-
enumerable: true,
|
|
2499
|
-
configurable: true
|
|
2500
|
-
});
|
|
2501
|
-
return fn;
|
|
2543
|
+
return new TauOutput(summary, allEntries, store, synthesis, t0, t1, qualityReview);
|
|
2502
2544
|
}
|
|
2503
|
-
var \u03A4 =
|
|
2545
|
+
var \u03A4 = createPatternTag(defaults14, execute14);
|
|
2504
2546
|
|
|
2505
2547
|
// src/patterns/thread.ts
|
|
2506
2548
|
var defaults15 = {
|
|
@@ -2509,27 +2551,6 @@ var defaults15 = {
|
|
|
2509
2551
|
agents: 3,
|
|
2510
2552
|
turns: 3
|
|
2511
2553
|
};
|
|
2512
|
-
var ROLE_SETS4 = {
|
|
2513
|
-
2: ["Proposer \u2014 advocate the best approach", "Critic \u2014 identify weaknesses and gaps"],
|
|
2514
|
-
3: [
|
|
2515
|
-
"Proposer \u2014 suggest the best approach",
|
|
2516
|
-
"Critic \u2014 identify weaknesses, risks, and missing pieces",
|
|
2517
|
-
"Synthesizer \u2014 combine the best ideas into a practical plan"
|
|
2518
|
-
],
|
|
2519
|
-
4: [
|
|
2520
|
-
"Proposer \u2014 advocate a bold solution",
|
|
2521
|
-
"Critic \u2014 identify risks and weaknesses",
|
|
2522
|
-
"Pragmatist \u2014 focus on practical implementation",
|
|
2523
|
-
"Innovator \u2014 propose creative alternatives"
|
|
2524
|
-
],
|
|
2525
|
-
5: [
|
|
2526
|
-
"Proposer",
|
|
2527
|
-
"Critic",
|
|
2528
|
-
"Pragmatist",
|
|
2529
|
-
"Innovator",
|
|
2530
|
-
"Devil's Advocate \u2014 challenge every assumption"
|
|
2531
|
-
]
|
|
2532
|
-
};
|
|
2533
2554
|
var ThreadMessage = class {
|
|
2534
2555
|
constructor(role, turn, content) {
|
|
2535
2556
|
this.role = role;
|
|
@@ -2541,13 +2562,15 @@ var ThreadMessage = class {
|
|
|
2541
2562
|
content;
|
|
2542
2563
|
};
|
|
2543
2564
|
var ThreadOutput = class extends PatternOutput {
|
|
2544
|
-
constructor(text, conclusion, messages, startTime, endTime) {
|
|
2565
|
+
constructor(text, conclusion, messages, startTime, endTime, qualityReview) {
|
|
2545
2566
|
super(text, startTime, endTime);
|
|
2546
2567
|
this.conclusion = conclusion;
|
|
2547
2568
|
this.messages = messages;
|
|
2569
|
+
this.qualityReview = qualityReview;
|
|
2548
2570
|
}
|
|
2549
2571
|
conclusion;
|
|
2550
2572
|
messages;
|
|
2573
|
+
qualityReview;
|
|
2551
2574
|
};
|
|
2552
2575
|
var THREAD_PROMPT = `You are an agent with the role: {role}.
|
|
2553
2576
|
Engage in a multi-agent conversation about the topic.
|
|
@@ -2569,7 +2592,7 @@ async function execute15(pieces, args, opts) {
|
|
|
2569
2592
|
const t0 = Date.now();
|
|
2570
2593
|
const agentCount = opts.agents ?? 3;
|
|
2571
2594
|
const maxTurns = opts.turns ?? 3;
|
|
2572
|
-
const roles = opts.roles ??
|
|
2595
|
+
const roles = opts.roles ?? THREAD_ROLE_SETS[agentCount] ?? THREAD_ROLE_SETS[3] ?? [];
|
|
2573
2596
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
2574
2597
|
const workerModel = opts.workerModel ?? opts.model;
|
|
2575
2598
|
if (!opts.quiet) {
|
|
@@ -2587,11 +2610,7 @@ async function execute15(pieces, args, opts) {
|
|
|
2587
2610
|
for (let a = 0; a < roles.length; a++) {
|
|
2588
2611
|
const role = roles[a] ?? `Agent ${a + 1}`;
|
|
2589
2612
|
const prompt = buildThreadPrompt(role, thread);
|
|
2590
|
-
const response = await ask(prompt, {
|
|
2591
|
-
model: workerModel,
|
|
2592
|
-
maxTokens: opts.maxTokens,
|
|
2593
|
-
thinkingLevel: opts.thinkingLevel
|
|
2594
|
-
});
|
|
2613
|
+
const response = await ask(prompt, { ...opts, model: workerModel });
|
|
2595
2614
|
messages.push(new ThreadMessage(role, turn, response));
|
|
2596
2615
|
thread += `
|
|
2597
2616
|
[${role}] (Turn ${turn}): ${response}
|
|
@@ -2607,46 +2626,24 @@ ${thread}
|
|
|
2607
2626
|
|
|
2608
2627
|
Synthesize a clear, actionable conclusion.`,
|
|
2609
2628
|
{
|
|
2629
|
+
...opts,
|
|
2610
2630
|
model: plannerModel,
|
|
2611
|
-
maxTokens: opts.maxTokens,
|
|
2612
2631
|
thinkingLevel: "high",
|
|
2613
|
-
system: SYNTHESIS_SYSTEM6
|
|
2632
|
+
system: mergeSystem(opts.system, SYNTHESIS_SYSTEM6)
|
|
2614
2633
|
}
|
|
2615
2634
|
);
|
|
2635
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
2636
|
+
const qualityReview = await runQualityReview(topic, conclusion, opts);
|
|
2616
2637
|
const t1 = Date.now();
|
|
2617
2638
|
const summary = messages.map(
|
|
2618
2639
|
(m) => `[${m.role}] Turn ${m.turn}: ${m.content.slice(0, 150)}${m.content.length > 150 ? "..." : ""}`
|
|
2619
2640
|
).join("\n");
|
|
2620
|
-
return new ThreadOutput(summary, conclusion, messages, t0, t1);
|
|
2621
|
-
}
|
|
2622
|
-
function makeThread(opts = {}) {
|
|
2623
|
-
const merged = { ...defaults15, ...opts };
|
|
2624
|
-
const fn = ((pieces, ...args) => {
|
|
2625
|
-
if (!Array.isArray(pieces)) {
|
|
2626
|
-
return makeThread({ ...merged, ...pieces });
|
|
2627
|
-
}
|
|
2628
|
-
return new PatternPromise((resolve, reject) => {
|
|
2629
|
-
execute15(pieces, args, merged).then(resolve, reject);
|
|
2630
|
-
});
|
|
2631
|
-
});
|
|
2632
|
-
let _quiet;
|
|
2633
|
-
Object.defineProperty(fn, "quiet", {
|
|
2634
|
-
get() {
|
|
2635
|
-
if (!_quiet) _quiet = makeThread({ ...merged, quiet: true });
|
|
2636
|
-
return _quiet;
|
|
2637
|
-
},
|
|
2638
|
-
enumerable: true,
|
|
2639
|
-
configurable: true
|
|
2640
|
-
});
|
|
2641
|
-
return fn;
|
|
2641
|
+
return new ThreadOutput(summary, conclusion, messages, t0, t1, qualityReview);
|
|
2642
2642
|
}
|
|
2643
|
-
var \u0398 =
|
|
2643
|
+
var \u0398 = createPatternTag(defaults15, execute15);
|
|
2644
2644
|
|
|
2645
2645
|
// src/pi.ts
|
|
2646
2646
|
import {
|
|
2647
|
-
getEnvApiKey as getEnvApiKey2,
|
|
2648
|
-
getModels as getModels2,
|
|
2649
|
-
getProviders as getProviders2,
|
|
2650
2647
|
streamSimple
|
|
2651
2648
|
} from "@earendil-works/pi-ai";
|
|
2652
2649
|
|
|
@@ -2664,10 +2661,28 @@ var PiOutput = class {
|
|
|
2664
2661
|
events;
|
|
2665
2662
|
startTime;
|
|
2666
2663
|
endTime;
|
|
2664
|
+
/** Trace entry for this single LLM call. Populated by the π tag. */
|
|
2665
|
+
trace = [];
|
|
2667
2666
|
/** Duration in milliseconds */
|
|
2668
2667
|
get duration() {
|
|
2669
2668
|
return this.endTime - this.startTime;
|
|
2670
2669
|
}
|
|
2670
|
+
/** Total input tokens (convenience accessor) */
|
|
2671
|
+
get inputTokens() {
|
|
2672
|
+
return this.trace[0]?.inputTokens ?? 0;
|
|
2673
|
+
}
|
|
2674
|
+
/** Total output tokens (convenience accessor) */
|
|
2675
|
+
get outputTokens() {
|
|
2676
|
+
return this.trace[0]?.outputTokens ?? 0;
|
|
2677
|
+
}
|
|
2678
|
+
/** Total tokens (convenience accessor) */
|
|
2679
|
+
get totalTokens() {
|
|
2680
|
+
return this.trace[0]?.totalTokens ?? 0;
|
|
2681
|
+
}
|
|
2682
|
+
/** Total cost in USD (convenience accessor) */
|
|
2683
|
+
get totalCost() {
|
|
2684
|
+
return this.trace[0]?.cost ?? 0;
|
|
2685
|
+
}
|
|
2671
2686
|
toString() {
|
|
2672
2687
|
return this.text;
|
|
2673
2688
|
}
|
|
@@ -2693,90 +2708,13 @@ var defaults16 = {
|
|
|
2693
2708
|
quiet: false,
|
|
2694
2709
|
maxTokens: 4096
|
|
2695
2710
|
};
|
|
2696
|
-
var _piSettings2;
|
|
2697
|
-
function getPiDefaults2() {
|
|
2698
|
-
if (_piSettings2 === void 0) {
|
|
2699
|
-
_piSettings2 = isPiInstalled() ? loadPiSettings() : {};
|
|
2700
|
-
}
|
|
2701
|
-
return _piSettings2;
|
|
2702
|
-
}
|
|
2703
|
-
function allModels2() {
|
|
2704
|
-
const result = [];
|
|
2705
|
-
for (const p of getProviders2()) {
|
|
2706
|
-
const ms = getModels2(p);
|
|
2707
|
-
if (ms && ms.length > 0) result.push(...ms);
|
|
2708
|
-
}
|
|
2709
|
-
return result;
|
|
2710
|
-
}
|
|
2711
|
-
function getConfiguredProviders2() {
|
|
2712
|
-
return getProviders2().filter((p) => getEnvApiKey2(p) !== void 0);
|
|
2713
|
-
}
|
|
2714
|
-
function configuredModels2() {
|
|
2715
|
-
const configured = new Set(getConfiguredProviders2());
|
|
2716
|
-
return allModels2().filter((m) => configured.has(m.provider));
|
|
2717
|
-
}
|
|
2718
|
-
function findModelById2(id) {
|
|
2719
|
-
const all = allModels2();
|
|
2720
|
-
if (id.includes("/")) {
|
|
2721
|
-
const [provider, modelId] = id.split("/", 2);
|
|
2722
|
-
return all.find(
|
|
2723
|
-
(m) => m.provider === provider && (m.id === modelId || m.id.endsWith(`/${modelId}`))
|
|
2724
|
-
);
|
|
2725
|
-
}
|
|
2726
|
-
return all.find((m) => m.id === id || m.id.endsWith(`/${id}`));
|
|
2727
|
-
}
|
|
2728
|
-
function pickModel2(preferred) {
|
|
2729
|
-
if (preferred) {
|
|
2730
|
-
const hit = findModelById2(preferred);
|
|
2731
|
-
if (hit) return hit;
|
|
2732
|
-
}
|
|
2733
|
-
const settings = getPiDefaults2();
|
|
2734
|
-
if (settings.defaultModel) {
|
|
2735
|
-
const hit = findModelById2(settings.defaultModel);
|
|
2736
|
-
if (hit) return hit;
|
|
2737
|
-
}
|
|
2738
|
-
if (settings.defaultProvider) {
|
|
2739
|
-
const providerModels = getModels2(settings.defaultProvider);
|
|
2740
|
-
if (providerModels && providerModels.length > 0) {
|
|
2741
|
-
const configured = new Set(getConfiguredProviders2());
|
|
2742
|
-
if (configured.has(settings.defaultProvider)) {
|
|
2743
|
-
return providerModels[0];
|
|
2744
|
-
}
|
|
2745
|
-
}
|
|
2746
|
-
}
|
|
2747
|
-
const available = configuredModels2();
|
|
2748
|
-
if (available.length > 0) {
|
|
2749
|
-
const order2 = ["claude-sonnet-4-5", "claude-sonnet-4", "gemini-2.5-flash", "gpt-4o-mini"];
|
|
2750
|
-
for (const id of order2) {
|
|
2751
|
-
const m = available.find((m2) => m2.id.includes(id));
|
|
2752
|
-
if (m) return m;
|
|
2753
|
-
}
|
|
2754
|
-
return available[0];
|
|
2755
|
-
}
|
|
2756
|
-
const models = allModels2();
|
|
2757
|
-
if (models.length === 0) return void 0;
|
|
2758
|
-
const order = ["claude-sonnet-4-5", "claude-sonnet-4", "gemini-2.5-flash", "gpt-4o-mini"];
|
|
2759
|
-
for (const id of order) {
|
|
2760
|
-
const m = models.find((m2) => m2.id.includes(id));
|
|
2761
|
-
if (m) return m;
|
|
2762
|
-
}
|
|
2763
|
-
return models[0];
|
|
2764
|
-
}
|
|
2765
|
-
function build2(pieces, args) {
|
|
2766
|
-
let s = "";
|
|
2767
|
-
for (let i = 0; i < pieces.length; i++) {
|
|
2768
|
-
s += pieces[i];
|
|
2769
|
-
if (i < args.length) s += String(args[i]);
|
|
2770
|
-
}
|
|
2771
|
-
return s;
|
|
2772
|
-
}
|
|
2773
2711
|
function makeContext(pieces, args, opts) {
|
|
2774
2712
|
return {
|
|
2775
2713
|
systemPrompt: opts.system,
|
|
2776
2714
|
messages: [
|
|
2777
2715
|
{
|
|
2778
2716
|
role: "user",
|
|
2779
|
-
content:
|
|
2717
|
+
content: build(pieces, args),
|
|
2780
2718
|
timestamp: Date.now()
|
|
2781
2719
|
}
|
|
2782
2720
|
]
|
|
@@ -2785,25 +2723,51 @@ function makeContext(pieces, args, opts) {
|
|
|
2785
2723
|
function makeOpts(opts) {
|
|
2786
2724
|
return {
|
|
2787
2725
|
maxTokens: opts.maxTokens,
|
|
2788
|
-
reasoning: opts.thinkingLevel
|
|
2726
|
+
reasoning: opts.thinkingLevel,
|
|
2727
|
+
timeoutMs: opts.timeoutMs,
|
|
2728
|
+
maxRetries: opts.maxRetries
|
|
2789
2729
|
};
|
|
2790
2730
|
}
|
|
2791
2731
|
async function run(pieces, args, opts) {
|
|
2792
|
-
const model =
|
|
2732
|
+
const model = pickModel(opts.model);
|
|
2793
2733
|
if (!model) throw new Error("pizx/\u03C0: No AI models configured. Run `pi auth login` first.");
|
|
2794
2734
|
const t0 = Date.now();
|
|
2795
2735
|
let text = "";
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
if (
|
|
2736
|
+
let traceEntry;
|
|
2737
|
+
try {
|
|
2738
|
+
for await (const ev of streamSimple(model, makeContext(pieces, args, opts), makeOpts(opts))) {
|
|
2739
|
+
if (ev.type === "text_delta") {
|
|
2740
|
+
text += ev.delta;
|
|
2741
|
+
if (!opts.quiet) process.stdout.write(ev.delta);
|
|
2742
|
+
} else if (ev.type === "done") {
|
|
2743
|
+
const msg = ev.message;
|
|
2744
|
+
if (msg?.usage) {
|
|
2745
|
+
traceEntry = {
|
|
2746
|
+
call: 1,
|
|
2747
|
+
modelId: model.id,
|
|
2748
|
+
promptPreview: build(pieces, args).slice(0, 200),
|
|
2749
|
+
outputPreview: text.slice(0, 200),
|
|
2750
|
+
inputTokens: msg.usage.input,
|
|
2751
|
+
outputTokens: msg.usage.output,
|
|
2752
|
+
cacheReadTokens: msg.usage.cacheRead,
|
|
2753
|
+
cacheWriteTokens: msg.usage.cacheWrite,
|
|
2754
|
+
totalTokens: msg.usage.totalTokens,
|
|
2755
|
+
cost: msg.usage.cost.total,
|
|
2756
|
+
durationMs: Date.now() - t0
|
|
2757
|
+
};
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2800
2760
|
}
|
|
2761
|
+
} catch (err) {
|
|
2762
|
+
throw new Error(`pizx/\u03C0: AI generation failed: ${getErrorMessage(err)}`);
|
|
2801
2763
|
}
|
|
2802
2764
|
if (!opts.quiet && text) process.stdout.write("\n");
|
|
2803
|
-
|
|
2765
|
+
const output = new PiOutput(text.trim(), model.id, [], t0, Date.now());
|
|
2766
|
+
if (traceEntry) output.trace = [traceEntry];
|
|
2767
|
+
return output;
|
|
2804
2768
|
}
|
|
2805
2769
|
async function* runStream(pieces, args, opts) {
|
|
2806
|
-
const model =
|
|
2770
|
+
const model = pickModel(opts.model);
|
|
2807
2771
|
if (!model) throw new Error("pizx/\u03C0: No AI models configured");
|
|
2808
2772
|
for await (const ev of streamSimple(model, makeContext(pieces, args, opts), makeOpts(opts))) {
|
|
2809
2773
|
if (ev.type === "text_delta") yield ev.delta;
|
|
@@ -2880,22 +2844,18 @@ var AgentPromise = class extends Promise {
|
|
|
2880
2844
|
var _sharedSession = null;
|
|
2881
2845
|
async function getSession(opts) {
|
|
2882
2846
|
if (_sharedSession && !opts.model) return _sharedSession;
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
for (let i = 0; i < pieces.length; i++) {
|
|
2895
|
-
s += pieces[i];
|
|
2896
|
-
if (i < args.length) s += String(args[i]);
|
|
2847
|
+
try {
|
|
2848
|
+
const result = await createAgentSession2({
|
|
2849
|
+
cwd: opts.cwd,
|
|
2850
|
+
thinkingLevel: opts.thinkingLevel,
|
|
2851
|
+
tools: opts.tools,
|
|
2852
|
+
excludeTools: opts.excludeTools
|
|
2853
|
+
});
|
|
2854
|
+
_sharedSession = result.session;
|
|
2855
|
+
return _sharedSession;
|
|
2856
|
+
} catch (err) {
|
|
2857
|
+
throw new Error(`pizx/\u03A0: Failed to create agent session: ${getErrorMessage(err)}`);
|
|
2897
2858
|
}
|
|
2898
|
-
return s.trim();
|
|
2899
2859
|
}
|
|
2900
2860
|
function getMessageText(msg) {
|
|
2901
2861
|
const content = msg.content;
|
|
@@ -2917,7 +2877,7 @@ function getLastAssistantText(session) {
|
|
|
2917
2877
|
return "";
|
|
2918
2878
|
}
|
|
2919
2879
|
async function execute16(pieces, args, opts) {
|
|
2920
|
-
const prompt =
|
|
2880
|
+
const prompt = build(pieces, args);
|
|
2921
2881
|
const session = await getSession(opts);
|
|
2922
2882
|
const t0 = Date.now();
|
|
2923
2883
|
if (!opts.quiet) {
|
|
@@ -2928,15 +2888,12 @@ async function execute16(pieces, args, opts) {
|
|
|
2928
2888
|
await session.sendUserMessage(prompt);
|
|
2929
2889
|
const t1 = Date.now();
|
|
2930
2890
|
const text = getLastAssistantText(session);
|
|
2931
|
-
const turnCount = session.messages.filter(
|
|
2932
|
-
(m) => m.role === "assistant"
|
|
2933
|
-
).length;
|
|
2891
|
+
const turnCount = session.messages.filter((m) => m.role === "assistant").length;
|
|
2934
2892
|
return new AgentOutput(text || "(no assistant response)", turnCount, t0, t1);
|
|
2935
2893
|
} catch (err) {
|
|
2936
2894
|
const t1 = Date.now();
|
|
2937
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
2938
2895
|
console.error("\u03A0 error:", err);
|
|
2939
|
-
return new AgentOutput(`\u03A0 error: ${
|
|
2896
|
+
return new AgentOutput(`\u03A0 error: ${getErrorMessage(err)}`, 0, t0, t1);
|
|
2940
2897
|
}
|
|
2941
2898
|
}
|
|
2942
2899
|
function makeAgent(opts = {}) {
|
|
@@ -2998,7 +2955,7 @@ function parseArgs(argv) {
|
|
|
2998
2955
|
if (argv[i + 1] && !argv[i + 1].startsWith("-")) flags.model = argv[++i];
|
|
2999
2956
|
break;
|
|
3000
2957
|
case "--system":
|
|
3001
|
-
if (argv[i + 1]) flags.system = argv[++i];
|
|
2958
|
+
if (argv[i + 1] && !argv[i + 1].startsWith("-")) flags.system = argv[++i];
|
|
3002
2959
|
break;
|
|
3003
2960
|
case "-q":
|
|
3004
2961
|
case "--quiet":
|
|
@@ -3039,6 +2996,7 @@ function printHelp() {
|
|
|
3039
2996
|
\`\u039B\` Pipeline \u2014 sequential agent chain
|
|
3040
2997
|
\`\u03A8\` Critique \u2014 generate, critique, improve
|
|
3041
2998
|
\`\u03A9\` Orchestrator \u2014 plan, dispatch, synthesize
|
|
2999
|
+
\`\u039D\` Nu \u2014 Self-Organizing Teams
|
|
3042
3000
|
|
|
3043
3001
|
${chalk.bold("Communication Patterns")}
|
|
3044
3002
|
\`\u0398\` Thread \u2014 multi-agent conversation
|
|
@@ -3048,6 +3006,8 @@ function printHelp() {
|
|
|
3048
3006
|
${chalk.bold("Orchestration Topologies")}
|
|
3049
3007
|
\`\u0391\` Adaptive \u2014 self-adjusting orchestration
|
|
3050
3008
|
\`\u0393\` Graph \u2014 DAG-based task execution
|
|
3009
|
+
\`\u03A7\` Chi \u2014 Cross-Agent Learning
|
|
3010
|
+
\`\u03A4\` Tau \u2014 Tool-Mediated Orchestration
|
|
3051
3011
|
|
|
3052
3012
|
${chalk.bold("Example Script")}
|
|
3053
3013
|
#!/usr/bin/env pizx
|
|
@@ -3078,7 +3038,7 @@ async function runPrintMode(flags, args) {
|
|
|
3078
3038
|
`);
|
|
3079
3039
|
}
|
|
3080
3040
|
} catch (err) {
|
|
3081
|
-
console.error("pizx: pi-ai error:", err
|
|
3041
|
+
console.error("pizx: pi-ai error:", getErrorMessage(err));
|
|
3082
3042
|
process2.exit(1);
|
|
3083
3043
|
}
|
|
3084
3044
|
}
|
|
@@ -3098,6 +3058,9 @@ async function runScriptMode(scriptPath) {
|
|
|
3098
3058
|
g.\u03A9 = \u03A9;
|
|
3099
3059
|
g.\u0398 = \u0398;
|
|
3100
3060
|
g.\u039C = \u039C;
|
|
3061
|
+
g.\u039D = \u039D;
|
|
3062
|
+
g.\u03A4 = \u03A4;
|
|
3063
|
+
g.\u03A7 = \u03A7;
|
|
3101
3064
|
g.\u0392 = \u0392;
|
|
3102
3065
|
g.\u0391 = \u0391;
|
|
3103
3066
|
g.\u0393 = \u0393;
|
|
@@ -3109,11 +3072,7 @@ async function runScriptMode(scriptPath) {
|
|
|
3109
3072
|
try {
|
|
3110
3073
|
await import(url.pathToFileURL(absPath).toString());
|
|
3111
3074
|
} catch (err) {
|
|
3112
|
-
|
|
3113
|
-
console.error("pizx:", err.message);
|
|
3114
|
-
} else {
|
|
3115
|
-
console.error("pizx:", err);
|
|
3116
|
-
}
|
|
3075
|
+
console.error("pizx:", getErrorMessage(err));
|
|
3117
3076
|
process2.exit(1);
|
|
3118
3077
|
}
|
|
3119
3078
|
}
|
|
@@ -3140,7 +3099,7 @@ async function main() {
|
|
|
3140
3099
|
await runScriptMode(script);
|
|
3141
3100
|
}
|
|
3142
3101
|
main().catch((err) => {
|
|
3143
|
-
console.error("pizx:", err
|
|
3102
|
+
console.error("pizx:", getErrorMessage(err));
|
|
3144
3103
|
process2.exit(1);
|
|
3145
3104
|
});
|
|
3146
3105
|
//# sourceMappingURL=cli.js.map
|