@topce/pizx 0.1.0 → 0.4.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 +312 -20
- package/dist/cli.js +775 -733
- package/dist/cli.js.map +4 -4
- package/dist/index.js +770 -726
- 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,23 +178,261 @@ function pickModel(preferred) {
|
|
|
197
178
|
}
|
|
198
179
|
return models[0];
|
|
199
180
|
}
|
|
181
|
+
|
|
182
|
+
// src/skill-loader.ts
|
|
183
|
+
import { readFile } from "node:fs/promises";
|
|
184
|
+
import { homedir as homedir3 } from "node:os";
|
|
185
|
+
import { join as join3 } from "node:path";
|
|
186
|
+
var SKILL_PATHS = [
|
|
187
|
+
".pi/skills",
|
|
188
|
+
".agents/skills",
|
|
189
|
+
"skills",
|
|
190
|
+
join3(homedir3(), ".pi", "agent", "skills"),
|
|
191
|
+
join3(homedir3(), ".codewhale", "skills"),
|
|
192
|
+
join3(homedir3(), ".claude", "skills")
|
|
193
|
+
];
|
|
194
|
+
async function loadSkillContent(name) {
|
|
195
|
+
for (const base of SKILL_PATHS) {
|
|
196
|
+
const candidate = join3(base, name, "SKILL.md");
|
|
197
|
+
try {
|
|
198
|
+
return await readFile(candidate, "utf-8");
|
|
199
|
+
} catch {
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return void 0;
|
|
203
|
+
}
|
|
204
|
+
async function loadSkillContents(names) {
|
|
205
|
+
const map = /* @__PURE__ */ new Map();
|
|
206
|
+
for (const name of names) {
|
|
207
|
+
const content = await loadSkillContent(name);
|
|
208
|
+
if (content) map.set(name, content);
|
|
209
|
+
}
|
|
210
|
+
return map;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/patterns/types.ts
|
|
214
|
+
var PatternOutput = class {
|
|
215
|
+
constructor(text, startTime = Date.now(), endTime = Date.now()) {
|
|
216
|
+
this.text = text;
|
|
217
|
+
this.startTime = startTime;
|
|
218
|
+
this.endTime = endTime;
|
|
219
|
+
}
|
|
220
|
+
text;
|
|
221
|
+
startTime;
|
|
222
|
+
endTime;
|
|
223
|
+
/** Execution trace: one entry per LLM call within this pattern run. Populated by createPatternTag. */
|
|
224
|
+
trace = [];
|
|
225
|
+
/** Structured phase log: key phases during execution, populated by each pattern. */
|
|
226
|
+
phaseLog = [];
|
|
227
|
+
/** Duration in milliseconds */
|
|
228
|
+
get duration() {
|
|
229
|
+
return this.endTime - this.startTime;
|
|
230
|
+
}
|
|
231
|
+
/** Total input tokens across all calls */
|
|
232
|
+
get inputTokens() {
|
|
233
|
+
return this.trace.reduce((s, t) => s + t.inputTokens, 0);
|
|
234
|
+
}
|
|
235
|
+
/** Total output tokens across all calls */
|
|
236
|
+
get outputTokens() {
|
|
237
|
+
return this.trace.reduce((s, t) => s + t.outputTokens, 0);
|
|
238
|
+
}
|
|
239
|
+
/** Total tokens (input + output) across all calls */
|
|
240
|
+
get totalTokens() {
|
|
241
|
+
return this.trace.reduce((s, t) => s + t.totalTokens, 0);
|
|
242
|
+
}
|
|
243
|
+
/** Total cost in USD across all calls */
|
|
244
|
+
get totalCost() {
|
|
245
|
+
return this.trace.reduce((s, t) => s + t.cost, 0);
|
|
246
|
+
}
|
|
247
|
+
/** Number of LLM calls made during this pattern execution */
|
|
248
|
+
get callCount() {
|
|
249
|
+
return this.trace.length;
|
|
250
|
+
}
|
|
251
|
+
toString() {
|
|
252
|
+
return this.text;
|
|
253
|
+
}
|
|
254
|
+
valueOf() {
|
|
255
|
+
return this.text;
|
|
256
|
+
}
|
|
257
|
+
[Symbol.toPrimitive]() {
|
|
258
|
+
return this.text;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
var PatternPromise = class extends Promise {
|
|
262
|
+
};
|
|
263
|
+
var _trace = null;
|
|
264
|
+
function beginTrace() {
|
|
265
|
+
_trace = [];
|
|
266
|
+
}
|
|
267
|
+
function collectTrace() {
|
|
268
|
+
const t = _trace ?? [];
|
|
269
|
+
_trace = null;
|
|
270
|
+
return t;
|
|
271
|
+
}
|
|
272
|
+
function pushTrace(entry) {
|
|
273
|
+
if (_trace) _trace.push(entry);
|
|
274
|
+
}
|
|
275
|
+
function createPatternTag(defaults17, execute17) {
|
|
276
|
+
function make(opts = {}) {
|
|
277
|
+
const merged = { ...defaults17, ...opts };
|
|
278
|
+
const fn = ((pieces, ...args) => {
|
|
279
|
+
if (!Array.isArray(pieces)) {
|
|
280
|
+
return make({ ...merged, ...pieces });
|
|
281
|
+
}
|
|
282
|
+
beginTrace();
|
|
283
|
+
return new PatternPromise((resolve, reject) => {
|
|
284
|
+
execute17(pieces, args, merged).then(
|
|
285
|
+
(output) => {
|
|
286
|
+
output.trace = collectTrace();
|
|
287
|
+
resolve(output);
|
|
288
|
+
},
|
|
289
|
+
(err) => {
|
|
290
|
+
collectTrace();
|
|
291
|
+
reject(err);
|
|
292
|
+
}
|
|
293
|
+
);
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
let _quiet;
|
|
297
|
+
Object.defineProperty(fn, "quiet", {
|
|
298
|
+
get() {
|
|
299
|
+
if (!_quiet) _quiet = make({ ...merged, quiet: true });
|
|
300
|
+
return _quiet;
|
|
301
|
+
},
|
|
302
|
+
enumerable: true,
|
|
303
|
+
configurable: true
|
|
304
|
+
});
|
|
305
|
+
return fn;
|
|
306
|
+
}
|
|
307
|
+
return make();
|
|
308
|
+
}
|
|
309
|
+
function build(pieces, args) {
|
|
310
|
+
let s = "";
|
|
311
|
+
for (let i = 0; i < pieces.length; i++) {
|
|
312
|
+
s += pieces[i];
|
|
313
|
+
if (i < args.length) s += String(args[i]);
|
|
314
|
+
}
|
|
315
|
+
return s.trim();
|
|
316
|
+
}
|
|
317
|
+
function mergeSystem(userSystem, patternSystem) {
|
|
318
|
+
if (!userSystem) return patternSystem;
|
|
319
|
+
return `${userSystem}
|
|
320
|
+
|
|
321
|
+
${patternSystem}`;
|
|
322
|
+
}
|
|
323
|
+
async function confirmPhase(description, opts) {
|
|
324
|
+
if (!opts.confirm) return true;
|
|
325
|
+
if (!opts.quiet) {
|
|
326
|
+
process.stderr.write(`
|
|
327
|
+
\u2500\u2500 Confirm \u2500\u2500
|
|
328
|
+
${description}
|
|
329
|
+
Proceed? [Y/n] `);
|
|
330
|
+
}
|
|
331
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
332
|
+
const answer = await new Promise((resolve) => {
|
|
333
|
+
rl.question("", (ans) => resolve(ans));
|
|
334
|
+
});
|
|
335
|
+
rl.close();
|
|
336
|
+
const trimmed = answer.trim().toLowerCase();
|
|
337
|
+
if (trimmed === "" || trimmed === "y" || trimmed === "yes") return true;
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
200
340
|
async function ask(prompt, opts = {}) {
|
|
201
341
|
const model = pickModel(opts.model);
|
|
202
342
|
if (!model) throw new Error("pizx/patterns: No AI models configured. Run `pi auth login` first.");
|
|
343
|
+
let systemPrompt = opts.system;
|
|
344
|
+
if (opts.skills && opts.skills.length > 0) {
|
|
345
|
+
const skillMap = await loadSkillContents(opts.skills);
|
|
346
|
+
if (skillMap.size > 0) {
|
|
347
|
+
const skillBlocks = [];
|
|
348
|
+
for (const [name, content] of skillMap) {
|
|
349
|
+
skillBlocks.push(`Skill context (${name}):
|
|
350
|
+
${content}`);
|
|
351
|
+
}
|
|
352
|
+
const skillContext = skillBlocks.join("\n\n");
|
|
353
|
+
systemPrompt = systemPrompt ? `${systemPrompt}
|
|
354
|
+
|
|
355
|
+
${skillContext}` : skillContext;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const t0 = Date.now();
|
|
203
359
|
const result = await completeSimple(
|
|
204
360
|
model,
|
|
205
361
|
{
|
|
206
|
-
systemPrompt
|
|
362
|
+
systemPrompt,
|
|
207
363
|
messages: [{ role: "user", content: prompt, timestamp: Date.now() }]
|
|
208
364
|
},
|
|
209
365
|
{
|
|
210
366
|
maxTokens: opts.maxTokens ?? 4096,
|
|
211
|
-
reasoning: opts.thinkingLevel ?? "medium"
|
|
367
|
+
reasoning: opts.thinkingLevel ?? "medium",
|
|
368
|
+
thinkingBudgets: opts.thinkingBudgets,
|
|
369
|
+
timeoutMs: opts.timeoutMs,
|
|
370
|
+
maxRetries: opts.maxRetries
|
|
212
371
|
}
|
|
213
372
|
);
|
|
373
|
+
const durationMs = Date.now() - t0;
|
|
374
|
+
if (!result.content || !Array.isArray(result.content)) {
|
|
375
|
+
throw new Error("pizx/patterns: Unexpected response format from AI model.");
|
|
376
|
+
}
|
|
214
377
|
const text = result.content.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
378
|
+
if (_trace !== null) {
|
|
379
|
+
pushTrace({
|
|
380
|
+
call: _trace.length + 1,
|
|
381
|
+
modelId: result.model,
|
|
382
|
+
promptPreview: prompt.slice(0, 200),
|
|
383
|
+
outputPreview: text.slice(0, 200),
|
|
384
|
+
inputTokens: result.usage.input,
|
|
385
|
+
outputTokens: result.usage.output,
|
|
386
|
+
cacheReadTokens: result.usage.cacheRead,
|
|
387
|
+
cacheWriteTokens: result.usage.cacheWrite,
|
|
388
|
+
totalTokens: result.usage.totalTokens,
|
|
389
|
+
cost: result.usage.cost.total,
|
|
390
|
+
durationMs
|
|
391
|
+
});
|
|
392
|
+
}
|
|
215
393
|
return text.trim();
|
|
216
394
|
}
|
|
395
|
+
var QUALITY_REVIEW_SYSTEM = `You are a quality assurance reviewer. Evaluate the final deliverable against the original request.
|
|
396
|
+
|
|
397
|
+
Output format:
|
|
398
|
+
SCORE: 0.XX (quality score from 0.0 to 1.0)
|
|
399
|
+
ASSESSMENT: (1-2 sentences \u2014 is the output complete, consistent, and actionable?)
|
|
400
|
+
RECOMMENDATION: (1 sentence \u2014 what would improve this output?)`;
|
|
401
|
+
async function runQualityReview(originalRequest, finalOutput, opts) {
|
|
402
|
+
if (!opts.qualityCheck) return void 0;
|
|
403
|
+
const reviewText = await ask(
|
|
404
|
+
`Original request:
|
|
405
|
+
${originalRequest}
|
|
406
|
+
|
|
407
|
+
Final deliverable:
|
|
408
|
+
${finalOutput}
|
|
409
|
+
|
|
410
|
+
Evaluate the quality.`,
|
|
411
|
+
{
|
|
412
|
+
model: opts.plannerModel ?? opts.model,
|
|
413
|
+
maxTokens: 512,
|
|
414
|
+
thinkingLevel: "high",
|
|
415
|
+
timeoutMs: opts.timeoutMs,
|
|
416
|
+
maxRetries: opts.maxRetries,
|
|
417
|
+
system: QUALITY_REVIEW_SYSTEM
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
const scoreMatch = reviewText.match(/SCORE:\s*([\d.]+)/i);
|
|
421
|
+
const assessMatch = reviewText.match(/ASSESSMENT:\s*(.+)/i);
|
|
422
|
+
const recMatch = reviewText.match(/RECOMMENDATION:\s*(.+)/i);
|
|
423
|
+
const result = {
|
|
424
|
+
score: scoreMatch ? parseFloat(scoreMatch[1]) : 0.5,
|
|
425
|
+
assessment: assessMatch?.[1]?.trim() ?? "(no assessment)",
|
|
426
|
+
recommendation: recMatch?.[1]?.trim() ?? "(no recommendation)"
|
|
427
|
+
};
|
|
428
|
+
if (!opts.quiet) {
|
|
429
|
+
process.stderr.write(` Quality score: ${result.score.toFixed(2)}
|
|
430
|
+
`);
|
|
431
|
+
process.stderr.write(` ${result.assessment.slice(0, 80)}...
|
|
432
|
+
`);
|
|
433
|
+
}
|
|
434
|
+
return result;
|
|
435
|
+
}
|
|
217
436
|
|
|
218
437
|
// src/patterns/adaptive.ts
|
|
219
438
|
var defaults = {
|
|
@@ -277,10 +496,10 @@ async function execute(pieces, args, opts) {
|
|
|
277
496
|
}
|
|
278
497
|
if (!opts.quiet) process.stderr.write(" \u2192 Planning...\n");
|
|
279
498
|
const planText = await ask(goal, {
|
|
499
|
+
...opts,
|
|
280
500
|
model: plannerModel,
|
|
281
|
-
maxTokens: opts.maxTokens,
|
|
282
501
|
thinkingLevel: "high",
|
|
283
|
-
system: PLAN_SYSTEM
|
|
502
|
+
system: mergeSystem(opts.system, PLAN_SYSTEM)
|
|
284
503
|
});
|
|
285
504
|
const planLines = planText.split("\n");
|
|
286
505
|
const plannedSteps = [];
|
|
@@ -310,10 +529,9 @@ async function execute(pieces, args, opts) {
|
|
|
310
529
|
process.stderr.write(` \u2192 Step ${executionStep}: ${currentStep.slice(0, 60)}...
|
|
311
530
|
`);
|
|
312
531
|
const result = await ask(currentStep, {
|
|
532
|
+
...opts,
|
|
313
533
|
model: workerModel,
|
|
314
|
-
|
|
315
|
-
thinkingLevel: opts.thinkingLevel,
|
|
316
|
-
system: EXECUTE_SYSTEM
|
|
534
|
+
system: mergeSystem(opts.system, EXECUTE_SYSTEM)
|
|
317
535
|
});
|
|
318
536
|
const evaluation = await ask(
|
|
319
537
|
`Goal: ${goal}
|
|
@@ -322,10 +540,11 @@ Result: ${result}
|
|
|
322
540
|
|
|
323
541
|
Evaluate the result.`,
|
|
324
542
|
{
|
|
543
|
+
...opts,
|
|
325
544
|
model: plannerModel,
|
|
326
545
|
maxTokens: 512,
|
|
327
546
|
thinkingLevel: "high",
|
|
328
|
-
system: EVALUATE_SYSTEM
|
|
547
|
+
system: mergeSystem(opts.system, EVALUATE_SYSTEM)
|
|
329
548
|
}
|
|
330
549
|
);
|
|
331
550
|
const scoreMatch = evaluation.match(/SCORE:\s*([\d.]+)/i);
|
|
@@ -348,8 +567,7 @@ Evaluate the result.`,
|
|
|
348
567
|
break;
|
|
349
568
|
}
|
|
350
569
|
const adaptUpper = adaptation.toUpperCase();
|
|
351
|
-
if (adaptUpper.startsWith("
|
|
352
|
-
} else if (adaptUpper.startsWith("SKIP_NEXT")) {
|
|
570
|
+
if (adaptUpper.startsWith("SKIP_NEXT")) {
|
|
353
571
|
stepIndex += 2;
|
|
354
572
|
} else if (adaptUpper.startsWith("ADD")) {
|
|
355
573
|
const newStep = adaptation.replace(/^ADD\s*/i, "");
|
|
@@ -368,36 +586,76 @@ Evaluate the result.`,
|
|
|
368
586
|
).join("\n\n");
|
|
369
587
|
return new AdaptiveOutput(summary, finalResult, adaptiveSteps, executionStep, t0, t1);
|
|
370
588
|
}
|
|
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();
|
|
589
|
+
var \u0391 = createPatternTag(defaults, execute);
|
|
393
590
|
|
|
394
|
-
// src/patterns/
|
|
395
|
-
var
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
591
|
+
// src/patterns/role-sets.ts
|
|
592
|
+
var DEBATE_ROLE_SETS = {
|
|
593
|
+
2: [
|
|
594
|
+
"Optimist \u2014 advocate for the most ambitious approach",
|
|
595
|
+
"Pessimist \u2014 identify risks and failure modes"
|
|
596
|
+
],
|
|
597
|
+
3: [
|
|
598
|
+
"Optimist \u2014 advocate the benefits and opportunities",
|
|
599
|
+
"Pessimist \u2014 identify risks, costs, and failure modes",
|
|
600
|
+
"Pragmatist \u2014 focus on practical trade-offs and implementation"
|
|
601
|
+
],
|
|
602
|
+
4: [
|
|
603
|
+
"Optimist \u2014 argue for the best-case potential",
|
|
604
|
+
"Pessimist \u2014 highlight worst-case risks and downsides",
|
|
605
|
+
"Pragmatist \u2014 balance pros/cons with practical constraints",
|
|
606
|
+
"Innovator \u2014 propose creative alternatives and novel approaches"
|
|
607
|
+
],
|
|
608
|
+
5: [
|
|
609
|
+
"Optimist",
|
|
610
|
+
"Pessimist",
|
|
611
|
+
"Pragmatist",
|
|
612
|
+
"Innovator",
|
|
613
|
+
"User Advocate \u2014 focus on end-user experience and accessibility"
|
|
614
|
+
]
|
|
615
|
+
};
|
|
616
|
+
var MEMORY_ROLE_SETS = {
|
|
617
|
+
2: ["Analyst \u2014 deep analysis of core aspects", "Reviewer \u2014 check for gaps and blind spots"],
|
|
618
|
+
3: [
|
|
619
|
+
"Analyst \u2014 deep analysis of core aspects",
|
|
620
|
+
"Reviewer \u2014 check for gaps, edge cases, and blind spots",
|
|
621
|
+
"Strategist \u2014 connect findings to actionable insights"
|
|
622
|
+
],
|
|
623
|
+
4: [
|
|
624
|
+
"Analyst",
|
|
625
|
+
"Reviewer",
|
|
626
|
+
"Strategist",
|
|
627
|
+
"Innovator \u2014 propose novel angles and creative solutions"
|
|
628
|
+
],
|
|
629
|
+
5: [
|
|
630
|
+
"Analyst",
|
|
631
|
+
"Reviewer",
|
|
632
|
+
"Strategist",
|
|
633
|
+
"Innovator",
|
|
634
|
+
"Skeptic \u2014 challenge assumptions and stress-test conclusions"
|
|
635
|
+
]
|
|
399
636
|
};
|
|
400
|
-
var
|
|
637
|
+
var THREAD_ROLE_SETS = {
|
|
638
|
+
2: ["Proposer \u2014 advocate the best approach", "Critic \u2014 identify weaknesses and gaps"],
|
|
639
|
+
3: [
|
|
640
|
+
"Proposer \u2014 suggest the best approach",
|
|
641
|
+
"Critic \u2014 identify weaknesses, risks, and missing pieces",
|
|
642
|
+
"Synthesizer \u2014 combine the best ideas into a practical plan"
|
|
643
|
+
],
|
|
644
|
+
4: [
|
|
645
|
+
"Proposer \u2014 advocate a bold solution",
|
|
646
|
+
"Critic \u2014 identify risks and weaknesses",
|
|
647
|
+
"Pragmatist \u2014 focus on practical implementation",
|
|
648
|
+
"Innovator \u2014 propose creative alternatives"
|
|
649
|
+
],
|
|
650
|
+
5: [
|
|
651
|
+
"Proposer",
|
|
652
|
+
"Critic",
|
|
653
|
+
"Pragmatist",
|
|
654
|
+
"Innovator",
|
|
655
|
+
"Devil's Advocate \u2014 challenge every assumption"
|
|
656
|
+
]
|
|
657
|
+
};
|
|
658
|
+
var BROADCAST_ROLE_SETS = {
|
|
401
659
|
2: [
|
|
402
660
|
"Technical Expert \u2014 evaluate technical feasibility",
|
|
403
661
|
"Business Expert \u2014 evaluate business viability"
|
|
@@ -421,6 +679,13 @@ var ROLE_SETS = {
|
|
|
421
679
|
"Innovation Expert \u2014 suggest novel approaches and alternatives"
|
|
422
680
|
]
|
|
423
681
|
};
|
|
682
|
+
|
|
683
|
+
// src/patterns/broadcast.ts
|
|
684
|
+
var defaults2 = {
|
|
685
|
+
maxTokens: 4096,
|
|
686
|
+
thinkingLevel: "medium",
|
|
687
|
+
workers: 4
|
|
688
|
+
};
|
|
424
689
|
var BroadcastResponse = class {
|
|
425
690
|
constructor(role, response, success, error) {
|
|
426
691
|
this.role = role;
|
|
@@ -434,13 +699,15 @@ var BroadcastResponse = class {
|
|
|
434
699
|
error;
|
|
435
700
|
};
|
|
436
701
|
var BroadcastOutput = class extends PatternOutput {
|
|
437
|
-
constructor(text, synthesis, responses, startTime, endTime) {
|
|
702
|
+
constructor(text, synthesis, responses, startTime, endTime, qualityReview) {
|
|
438
703
|
super(text, startTime, endTime);
|
|
439
704
|
this.synthesis = synthesis;
|
|
440
705
|
this.responses = responses;
|
|
706
|
+
this.qualityReview = qualityReview;
|
|
441
707
|
}
|
|
442
708
|
synthesis;
|
|
443
709
|
responses;
|
|
710
|
+
qualityReview;
|
|
444
711
|
};
|
|
445
712
|
var WORKER_PROMPT = `You are a {role}.
|
|
446
713
|
|
|
@@ -455,7 +722,7 @@ async function execute2(pieces, args, opts) {
|
|
|
455
722
|
const question = build(pieces, args);
|
|
456
723
|
const t0 = Date.now();
|
|
457
724
|
const workerCount = opts.workers ?? 4;
|
|
458
|
-
const roles = opts.roles ??
|
|
725
|
+
const roles = opts.roles ?? BROADCAST_ROLE_SETS[workerCount] ?? BROADCAST_ROLE_SETS[4] ?? [];
|
|
459
726
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
460
727
|
const workerModel = opts.workerModel ?? opts.model;
|
|
461
728
|
if (!opts.quiet) {
|
|
@@ -470,11 +737,7 @@ async function execute2(pieces, args, opts) {
|
|
|
470
737
|
const broadcastResults = await Promise.allSettled(
|
|
471
738
|
roles.map(async (role) => {
|
|
472
739
|
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
|
-
});
|
|
740
|
+
const text = await ask(prompt, { ...opts, model: workerModel });
|
|
478
741
|
return new BroadcastResponse(role, text, true);
|
|
479
742
|
})
|
|
480
743
|
);
|
|
@@ -499,40 +762,21 @@ ${responsesText}
|
|
|
499
762
|
|
|
500
763
|
Synthesize a cohesive, actionable recommendation.`,
|
|
501
764
|
{
|
|
765
|
+
...opts,
|
|
502
766
|
model: plannerModel,
|
|
503
|
-
maxTokens: opts.maxTokens,
|
|
504
767
|
thinkingLevel: "high",
|
|
505
|
-
system: SYNTHESIS_SYSTEM
|
|
768
|
+
system: mergeSystem(opts.system, SYNTHESIS_SYSTEM)
|
|
506
769
|
}
|
|
507
770
|
);
|
|
771
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
772
|
+
const qualityReview = await runQualityReview(question, synthesis, opts);
|
|
508
773
|
const t1 = Date.now();
|
|
509
774
|
const summary = responses.map(
|
|
510
775
|
(wr) => `[${wr.role}]: ${wr.response.slice(0, 150)}${wr.response.length > 150 ? "..." : ""}`
|
|
511
776
|
).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;
|
|
777
|
+
return new BroadcastOutput(summary, synthesis, responses, t0, t1, qualityReview);
|
|
534
778
|
}
|
|
535
|
-
var \u0392 =
|
|
779
|
+
var \u0392 = createPatternTag(defaults2, execute2);
|
|
536
780
|
|
|
537
781
|
// src/patterns/chi.ts
|
|
538
782
|
var defaults3 = {
|
|
@@ -552,15 +796,17 @@ var LearningInsight = class {
|
|
|
552
796
|
confidence;
|
|
553
797
|
};
|
|
554
798
|
var ChiOutput = class extends PatternOutput {
|
|
555
|
-
constructor(text, insights, summary, suggestedChanges, startTime, endTime) {
|
|
799
|
+
constructor(text, insights, summary, suggestedChanges, startTime, endTime, qualityReview) {
|
|
556
800
|
super(text, startTime, endTime);
|
|
557
801
|
this.insights = insights;
|
|
558
802
|
this.summary = summary;
|
|
559
803
|
this.suggestedChanges = suggestedChanges;
|
|
804
|
+
this.qualityReview = qualityReview;
|
|
560
805
|
}
|
|
561
806
|
insights;
|
|
562
807
|
summary;
|
|
563
808
|
suggestedChanges;
|
|
809
|
+
qualityReview;
|
|
564
810
|
};
|
|
565
811
|
var ANALYSIS_SYSTEM = `You are an agent team performance analyst. Review a multi-agent execution and extract structured learnings.
|
|
566
812
|
|
|
@@ -629,12 +875,13 @@ async function execute3(pieces, args, opts) {
|
|
|
629
875
|
`);
|
|
630
876
|
}
|
|
631
877
|
const response = await ask(input, {
|
|
878
|
+
...opts,
|
|
632
879
|
model: plannerModel,
|
|
633
|
-
|
|
634
|
-
thinkingLevel: opts.thinkingLevel,
|
|
635
|
-
system: ANALYSIS_SYSTEM
|
|
880
|
+
system: mergeSystem(opts.system, ANALYSIS_SYSTEM)
|
|
636
881
|
});
|
|
637
882
|
const { insights, summary, suggestedChanges } = parseInsights(response);
|
|
883
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
884
|
+
const qualityReview = await runQualityReview(input, response, opts);
|
|
638
885
|
const t1 = Date.now();
|
|
639
886
|
const text = [
|
|
640
887
|
`Insights: ${insights.length} extracted`,
|
|
@@ -646,30 +893,9 @@ Summary: ${summary}`,
|
|
|
646
893
|
`
|
|
647
894
|
Changes: ${suggestedChanges}`
|
|
648
895
|
].join("\n");
|
|
649
|
-
return new ChiOutput(text, insights, summary, suggestedChanges, t0, t1);
|
|
650
|
-
}
|
|
651
|
-
function makeChi(opts = {}) {
|
|
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;
|
|
896
|
+
return new ChiOutput(text, insights, summary, suggestedChanges, t0, t1, qualityReview);
|
|
671
897
|
}
|
|
672
|
-
var \u03A7 =
|
|
898
|
+
var \u03A7 = createPatternTag(defaults3, execute3);
|
|
673
899
|
|
|
674
900
|
// src/patterns/critique.ts
|
|
675
901
|
var defaults4 = {
|
|
@@ -724,12 +950,7 @@ async function execute4(pieces, args, opts) {
|
|
|
724
950
|
for (let r = 0; r < rounds; r++) {
|
|
725
951
|
if (r === 0) {
|
|
726
952
|
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
|
-
});
|
|
953
|
+
currentContent = await ask(prompt, { ...opts, model: workerModel, system: opts.system });
|
|
733
954
|
} else {
|
|
734
955
|
if (!opts.quiet) process.stderr.write(` \u2192 Improving (round ${r + 1})...
|
|
735
956
|
`);
|
|
@@ -744,21 +965,15 @@ Content to improve:
|
|
|
744
965
|
${currentContent}
|
|
745
966
|
|
|
746
967
|
Revise the content based on the critique.`,
|
|
747
|
-
{
|
|
748
|
-
model: workerModel,
|
|
749
|
-
maxTokens: opts.maxTokens,
|
|
750
|
-
thinkingLevel: opts.thinkingLevel,
|
|
751
|
-
system: IMPROVE_SYSTEM
|
|
752
|
-
}
|
|
968
|
+
{ ...opts, model: workerModel, system: mergeSystem(opts.system, IMPROVE_SYSTEM) }
|
|
753
969
|
);
|
|
754
970
|
}
|
|
755
971
|
if (!opts.quiet) process.stderr.write(` \u2192 Critiquing (round ${r + 1})...
|
|
756
972
|
`);
|
|
757
973
|
const critique = await ask(currentContent, {
|
|
974
|
+
...opts,
|
|
758
975
|
model: plannerModel,
|
|
759
|
-
|
|
760
|
-
thinkingLevel: opts.thinkingLevel,
|
|
761
|
-
system: CRITIQUE_SYSTEM
|
|
976
|
+
system: mergeSystem(opts.system, CRITIQUE_SYSTEM)
|
|
762
977
|
});
|
|
763
978
|
critiqueRounds.push(new CritiqueRound(currentContent, critique, r));
|
|
764
979
|
}
|
|
@@ -771,28 +986,7 @@ Critique: ${cr.critique.slice(0, 200)}${cr.critique.length > 200 ? "..." : ""}`
|
|
|
771
986
|
).join("\n\n");
|
|
772
987
|
return new CritiqueOutput(summary, finalContent, critiqueRounds, t0, t1);
|
|
773
988
|
}
|
|
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();
|
|
989
|
+
var \u03A8 = createPatternTag(defaults4, execute4);
|
|
796
990
|
|
|
797
991
|
// src/patterns/debate.ts
|
|
798
992
|
var defaults5 = {
|
|
@@ -801,30 +995,6 @@ var defaults5 = {
|
|
|
801
995
|
perspectives: 3,
|
|
802
996
|
rounds: 1
|
|
803
997
|
};
|
|
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
998
|
var DebatePerspective = class {
|
|
829
999
|
constructor(role, argument, round = 1) {
|
|
830
1000
|
this.role = role;
|
|
@@ -836,15 +1006,17 @@ var DebatePerspective = class {
|
|
|
836
1006
|
round;
|
|
837
1007
|
};
|
|
838
1008
|
var DebateOutput = class extends PatternOutput {
|
|
839
|
-
constructor(text, conclusion, perspectives, rounds, startTime, endTime) {
|
|
1009
|
+
constructor(text, conclusion, perspectives, rounds, startTime, endTime, qualityReview) {
|
|
840
1010
|
super(text, startTime, endTime);
|
|
841
1011
|
this.conclusion = conclusion;
|
|
842
1012
|
this.perspectives = perspectives;
|
|
843
1013
|
this.rounds = rounds;
|
|
1014
|
+
this.qualityReview = qualityReview;
|
|
844
1015
|
}
|
|
845
1016
|
conclusion;
|
|
846
1017
|
perspectives;
|
|
847
1018
|
rounds;
|
|
1019
|
+
qualityReview;
|
|
848
1020
|
};
|
|
849
1021
|
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
1022
|
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 +1026,7 @@ async function execute5(pieces, args, opts) {
|
|
|
854
1026
|
const t0 = Date.now();
|
|
855
1027
|
const count = opts.perspectives ?? 3;
|
|
856
1028
|
const totalRounds = opts.rounds ?? 1;
|
|
857
|
-
const roles = opts.roles ??
|
|
1029
|
+
const roles = opts.roles ?? DEBATE_ROLE_SETS[count] ?? DEBATE_ROLE_SETS[3] ?? [];
|
|
858
1030
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
859
1031
|
const workerModel = opts.workerModel ?? opts.model;
|
|
860
1032
|
if (!opts.quiet) {
|
|
@@ -872,10 +1044,9 @@ async function execute5(pieces, args, opts) {
|
|
|
872
1044
|
const round1Results = await Promise.allSettled(
|
|
873
1045
|
roles.map(
|
|
874
1046
|
(role) => ask(question, {
|
|
1047
|
+
...opts,
|
|
875
1048
|
model: workerModel,
|
|
876
|
-
|
|
877
|
-
thinkingLevel: opts.thinkingLevel,
|
|
878
|
-
system: PERSPECTIVE_SYSTEM(role)
|
|
1049
|
+
system: mergeSystem(opts.system, PERSPECTIVE_SYSTEM(role))
|
|
879
1050
|
}).then((text) => new DebatePerspective(role, text, 1))
|
|
880
1051
|
)
|
|
881
1052
|
);
|
|
@@ -909,10 +1080,9 @@ ${othersText}
|
|
|
909
1080
|
|
|
910
1081
|
Refine your position. Address the counter-arguments directly. Strengthen your argument with rebuttals.`;
|
|
911
1082
|
return ask(prompt, {
|
|
1083
|
+
...opts,
|
|
912
1084
|
model: workerModel,
|
|
913
|
-
|
|
914
|
-
thinkingLevel: opts.thinkingLevel,
|
|
915
|
-
system: REBUTTAL_SYSTEM(role)
|
|
1085
|
+
system: mergeSystem(opts.system, REBUTTAL_SYSTEM(role))
|
|
916
1086
|
}).then((text) => new DebatePerspective(role, text, round));
|
|
917
1087
|
})
|
|
918
1088
|
);
|
|
@@ -936,37 +1106,26 @@ Refine your position. Address the counter-arguments directly. Strengthen your ar
|
|
|
936
1106
|
|
|
937
1107
|
Synthesize a balanced conclusion from the full debate above. Weigh the evidence from all rounds.`,
|
|
938
1108
|
{
|
|
1109
|
+
...opts,
|
|
939
1110
|
model: plannerModel,
|
|
940
|
-
maxTokens: opts.maxTokens,
|
|
941
1111
|
thinkingLevel: "high",
|
|
942
|
-
system: SYNTHESIS_SYSTEM2
|
|
1112
|
+
system: mergeSystem(opts.system, SYNTHESIS_SYSTEM2)
|
|
943
1113
|
}
|
|
944
1114
|
);
|
|
1115
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1116
|
+
const qualityReview = await runQualityReview(question, conclusion, opts);
|
|
945
1117
|
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;
|
|
1118
|
+
return new DebateOutput(
|
|
1119
|
+
conclusion,
|
|
1120
|
+
conclusion,
|
|
1121
|
+
allPerspectives,
|
|
1122
|
+
totalRounds,
|
|
1123
|
+
t0,
|
|
1124
|
+
t1,
|
|
1125
|
+
qualityReview
|
|
1126
|
+
);
|
|
968
1127
|
}
|
|
969
|
-
var \u0394 =
|
|
1128
|
+
var \u0394 = createPatternTag(defaults5, execute5);
|
|
970
1129
|
|
|
971
1130
|
// src/patterns/fleet.ts
|
|
972
1131
|
var defaults6 = {
|
|
@@ -987,11 +1146,13 @@ var FleetMemberOutput = class {
|
|
|
987
1146
|
error;
|
|
988
1147
|
};
|
|
989
1148
|
var FleetOutput = class extends PatternOutput {
|
|
990
|
-
constructor(text, members, startTime, endTime) {
|
|
1149
|
+
constructor(text, members, startTime, endTime, qualityReview) {
|
|
991
1150
|
super(text, startTime, endTime);
|
|
992
1151
|
this.members = members;
|
|
1152
|
+
this.qualityReview = qualityReview;
|
|
993
1153
|
}
|
|
994
1154
|
members;
|
|
1155
|
+
qualityReview;
|
|
995
1156
|
/** Number of successful members */
|
|
996
1157
|
get successCount() {
|
|
997
1158
|
return this.members.filter((m) => m.success).length;
|
|
@@ -1011,20 +1172,30 @@ function parseTasks(template, explicitTasks) {
|
|
|
1011
1172
|
if (lines.length > 1) return lines;
|
|
1012
1173
|
return [template];
|
|
1013
1174
|
}
|
|
1175
|
+
function describeTask(task) {
|
|
1176
|
+
if (typeof task === "function") return "(composed pattern)";
|
|
1177
|
+
return task;
|
|
1178
|
+
}
|
|
1014
1179
|
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
1180
|
async function executeTask(task, opts, workerModel) {
|
|
1181
|
+
if (typeof task === "function") {
|
|
1182
|
+
try {
|
|
1183
|
+
const text = await task("");
|
|
1184
|
+
return new FleetMemberOutput("(composed pattern)", text, true);
|
|
1185
|
+
} catch (err) {
|
|
1186
|
+
return new FleetMemberOutput("(composed pattern)", "", false, getErrorMessage(err));
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1016
1189
|
const model = workerModel ?? opts.model;
|
|
1017
1190
|
try {
|
|
1018
1191
|
const text = await ask(task, {
|
|
1192
|
+
...opts,
|
|
1019
1193
|
model,
|
|
1020
|
-
|
|
1021
|
-
thinkingLevel: opts.thinkingLevel,
|
|
1022
|
-
system: opts.system ?? FLEET_SYSTEM
|
|
1194
|
+
system: mergeSystem(opts.system, FLEET_SYSTEM)
|
|
1023
1195
|
});
|
|
1024
1196
|
return new FleetMemberOutput(task, text, true);
|
|
1025
1197
|
} catch (err) {
|
|
1026
|
-
|
|
1027
|
-
return new FleetMemberOutput(task, "", false, msg);
|
|
1198
|
+
return new FleetMemberOutput(task, "", false, getErrorMessage(err));
|
|
1028
1199
|
}
|
|
1029
1200
|
}
|
|
1030
1201
|
async function execute6(pieces, args, opts) {
|
|
@@ -1036,11 +1207,16 @@ async function execute6(pieces, args, opts) {
|
|
|
1036
1207
|
process.stderr.write(`\u03A6: Fleet executing ${tasks.length} task(s) in parallel
|
|
1037
1208
|
`);
|
|
1038
1209
|
for (let i = 0; i < tasks.length; i++) {
|
|
1039
|
-
const t = tasks[i];
|
|
1210
|
+
const t = describeTask(tasks[i]);
|
|
1040
1211
|
process.stderr.write(` [${i + 1}] ${t.slice(0, 60)}${t.length > 60 ? "..." : ""}
|
|
1041
1212
|
`);
|
|
1042
1213
|
}
|
|
1043
1214
|
}
|
|
1215
|
+
const taskSummary = `Execute ${tasks.length} fleet task(s)?
|
|
1216
|
+
${tasks.map((t, i) => `${i + 1}. ${describeTask(t).slice(0, 80)}`).join("\n ")}`;
|
|
1217
|
+
if (!await confirmPhase(taskSummary, opts)) {
|
|
1218
|
+
throw new Error("pizx/\u03A6: Execution cancelled by user.");
|
|
1219
|
+
}
|
|
1044
1220
|
const results = [];
|
|
1045
1221
|
const concurrency = opts.concurrency ?? 5;
|
|
1046
1222
|
for (let i = 0; i < tasks.length; i += concurrency) {
|
|
@@ -1052,7 +1228,9 @@ async function execute6(pieces, args, opts) {
|
|
|
1052
1228
|
if (r.status === "fulfilled") {
|
|
1053
1229
|
results.push(r.value);
|
|
1054
1230
|
} else {
|
|
1055
|
-
results.push(
|
|
1231
|
+
results.push(
|
|
1232
|
+
new FleetMemberOutput(describeTask(batch[idx]), "", false, r.reason?.toString())
|
|
1233
|
+
);
|
|
1056
1234
|
}
|
|
1057
1235
|
});
|
|
1058
1236
|
}
|
|
@@ -1064,30 +1242,11 @@ async function execute6(pieces, args, opts) {
|
|
|
1064
1242
|
const header = `Fleet Results: ${results.filter((r) => r.success).length}/${results.length} succeeded
|
|
1065
1243
|
|
|
1066
1244
|
`;
|
|
1067
|
-
|
|
1068
|
-
|
|
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;
|
|
1245
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1246
|
+
const qualityReview = await runQualityReview(template, header + summary, opts);
|
|
1247
|
+
return new FleetOutput(header + summary, results, t0, t1, qualityReview);
|
|
1089
1248
|
}
|
|
1090
|
-
var \u03A6 =
|
|
1249
|
+
var \u03A6 = createPatternTag(defaults6, execute6);
|
|
1091
1250
|
|
|
1092
1251
|
// src/patterns/graph.ts
|
|
1093
1252
|
var defaults7 = {
|
|
@@ -1107,13 +1266,15 @@ var GraphNodeResult = class {
|
|
|
1107
1266
|
success;
|
|
1108
1267
|
};
|
|
1109
1268
|
var GraphOutput = class extends PatternOutput {
|
|
1110
|
-
constructor(text, finalOutput, nodeResults, startTime, endTime) {
|
|
1269
|
+
constructor(text, finalOutput, nodeResults, startTime, endTime, qualityReview) {
|
|
1111
1270
|
super(text, startTime, endTime);
|
|
1112
1271
|
this.finalOutput = finalOutput;
|
|
1113
1272
|
this.nodeResults = nodeResults;
|
|
1273
|
+
this.qualityReview = qualityReview;
|
|
1114
1274
|
}
|
|
1115
1275
|
finalOutput;
|
|
1116
1276
|
nodeResults;
|
|
1277
|
+
qualityReview;
|
|
1117
1278
|
};
|
|
1118
1279
|
function parseGraph(template, separator) {
|
|
1119
1280
|
const sep = separator ?? "\u2192";
|
|
@@ -1209,10 +1370,9 @@ Your task: ${node.task}`;
|
|
|
1209
1370
|
}
|
|
1210
1371
|
}
|
|
1211
1372
|
const text = await ask(context, {
|
|
1373
|
+
...opts,
|
|
1212
1374
|
model: workerModel,
|
|
1213
|
-
|
|
1214
|
-
thinkingLevel: opts.thinkingLevel,
|
|
1215
|
-
system: NODE_SYSTEM
|
|
1375
|
+
system: mergeSystem(opts.system, NODE_SYSTEM)
|
|
1216
1376
|
});
|
|
1217
1377
|
return { nodeId, task: node.task, text, success: true };
|
|
1218
1378
|
})
|
|
@@ -1230,34 +1390,15 @@ Your task: ${node.task}`;
|
|
|
1230
1390
|
const lastBatch = batches[batches.length - 1] ?? [];
|
|
1231
1391
|
const finalNodeResults = lastBatch.map((id) => results.get(id)).filter(Boolean);
|
|
1232
1392
|
const finalOutput = finalNodeResults.length > 0 ? finalNodeResults.join("\n\n") : "";
|
|
1393
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1394
|
+
const qualityReview = await runQualityReview(template, finalOutput, opts);
|
|
1233
1395
|
const summary = nodeResults.map(
|
|
1234
1396
|
(nr) => `[${nr.nodeId}] ${nr.task.slice(0, 80)}...
|
|
1235
1397
|
${nr.output.slice(0, 200)}${nr.output.length > 200 ? "..." : ""}`
|
|
1236
1398
|
).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;
|
|
1399
|
+
return new GraphOutput(summary, finalOutput, nodeResults, t0, t1, qualityReview);
|
|
1259
1400
|
}
|
|
1260
|
-
var \u0393 =
|
|
1401
|
+
var \u0393 = createPatternTag(defaults7, execute7);
|
|
1261
1402
|
|
|
1262
1403
|
// src/patterns/memory.ts
|
|
1263
1404
|
var defaults8 = {
|
|
@@ -1266,27 +1407,6 @@ var defaults8 = {
|
|
|
1266
1407
|
agents: 3,
|
|
1267
1408
|
rounds: 1
|
|
1268
1409
|
};
|
|
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
1410
|
var MemoryEntry = class {
|
|
1291
1411
|
constructor(role, round, content) {
|
|
1292
1412
|
this.role = role;
|
|
@@ -1298,13 +1418,15 @@ var MemoryEntry = class {
|
|
|
1298
1418
|
content;
|
|
1299
1419
|
};
|
|
1300
1420
|
var MemoryOutput = class extends PatternOutput {
|
|
1301
|
-
constructor(text, synthesis, entries, startTime, endTime) {
|
|
1421
|
+
constructor(text, synthesis, entries, startTime, endTime, qualityReview) {
|
|
1302
1422
|
super(text, startTime, endTime);
|
|
1303
1423
|
this.synthesis = synthesis;
|
|
1304
1424
|
this.entries = entries;
|
|
1425
|
+
this.qualityReview = qualityReview;
|
|
1305
1426
|
}
|
|
1306
1427
|
synthesis;
|
|
1307
1428
|
entries;
|
|
1429
|
+
qualityReview;
|
|
1308
1430
|
};
|
|
1309
1431
|
var WRITER_PROMPT = `You are a specialist with role: {role}.
|
|
1310
1432
|
|
|
@@ -1325,7 +1447,7 @@ async function execute8(pieces, args, opts) {
|
|
|
1325
1447
|
const t0 = Date.now();
|
|
1326
1448
|
const agentCount = opts.agents ?? 3;
|
|
1327
1449
|
const totalRounds = opts.rounds ?? 1;
|
|
1328
|
-
const roles = opts.roles ??
|
|
1450
|
+
const roles = opts.roles ?? MEMORY_ROLE_SETS[agentCount] ?? MEMORY_ROLE_SETS[3] ?? [];
|
|
1329
1451
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
1330
1452
|
const workerModel = opts.workerModel ?? opts.model;
|
|
1331
1453
|
if (!opts.quiet) {
|
|
@@ -1342,11 +1464,7 @@ async function execute8(pieces, args, opts) {
|
|
|
1342
1464
|
const roundResults = await Promise.allSettled(
|
|
1343
1465
|
roles.map(async (role) => {
|
|
1344
1466
|
const prompt = buildWriterPrompt(role, topic, blackboard);
|
|
1345
|
-
const text = await ask(prompt, {
|
|
1346
|
-
model: workerModel,
|
|
1347
|
-
maxTokens: opts.maxTokens,
|
|
1348
|
-
thinkingLevel: opts.thinkingLevel
|
|
1349
|
-
});
|
|
1467
|
+
const text = await ask(prompt, { ...opts, model: workerModel });
|
|
1350
1468
|
return { role, text };
|
|
1351
1469
|
})
|
|
1352
1470
|
);
|
|
@@ -1368,40 +1486,21 @@ ${blackboard}
|
|
|
1368
1486
|
|
|
1369
1487
|
Consolidate into a comprehensive, structured synthesis.`,
|
|
1370
1488
|
{
|
|
1489
|
+
...opts,
|
|
1371
1490
|
model: plannerModel,
|
|
1372
|
-
maxTokens: opts.maxTokens,
|
|
1373
1491
|
thinkingLevel: "high",
|
|
1374
|
-
system: CONSOLIDATOR_SYSTEM
|
|
1492
|
+
system: mergeSystem(opts.system, CONSOLIDATOR_SYSTEM)
|
|
1375
1493
|
}
|
|
1376
1494
|
);
|
|
1495
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1496
|
+
const qualityReview = await runQualityReview(topic, synthesis, opts);
|
|
1377
1497
|
const t1 = Date.now();
|
|
1378
1498
|
const summary = entries.map(
|
|
1379
1499
|
(e) => `[${e.role}] Round ${e.round}: ${e.content.slice(0, 150)}${e.content.length > 150 ? "..." : ""}`
|
|
1380
1500
|
).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;
|
|
1501
|
+
return new MemoryOutput(summary, synthesis, entries, t0, t1, qualityReview);
|
|
1403
1502
|
}
|
|
1404
|
-
var \u039C =
|
|
1503
|
+
var \u039C = createPatternTag(defaults8, execute8);
|
|
1405
1504
|
|
|
1406
1505
|
// src/patterns/nu.ts
|
|
1407
1506
|
var defaults9 = {
|
|
@@ -1421,19 +1520,21 @@ var NuRole = class {
|
|
|
1421
1520
|
goal;
|
|
1422
1521
|
};
|
|
1423
1522
|
var NuOutput = class extends PatternOutput {
|
|
1424
|
-
constructor(text, negotiatedRoles, workflow, workflowReasoning, roleResults, synthesis, startTime, endTime) {
|
|
1523
|
+
constructor(text, negotiatedRoles, workflow, workflowReasoning, roleResults, synthesis, startTime, endTime, qualityReview) {
|
|
1425
1524
|
super(text, startTime, endTime);
|
|
1426
1525
|
this.negotiatedRoles = negotiatedRoles;
|
|
1427
1526
|
this.workflow = workflow;
|
|
1428
1527
|
this.workflowReasoning = workflowReasoning;
|
|
1429
1528
|
this.roleResults = roleResults;
|
|
1430
1529
|
this.synthesis = synthesis;
|
|
1530
|
+
this.qualityReview = qualityReview;
|
|
1431
1531
|
}
|
|
1432
1532
|
negotiatedRoles;
|
|
1433
1533
|
workflow;
|
|
1434
1534
|
workflowReasoning;
|
|
1435
1535
|
roleResults;
|
|
1436
1536
|
synthesis;
|
|
1537
|
+
qualityReview;
|
|
1437
1538
|
};
|
|
1438
1539
|
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
1540
|
|
|
@@ -1471,6 +1572,7 @@ async function negotiateRoles(task, opts) {
|
|
|
1471
1572
|
const response = await ask(`Task: ${task}
|
|
1472
1573
|
|
|
1473
1574
|
${prompt}`, {
|
|
1575
|
+
...opts,
|
|
1474
1576
|
model: opts.plannerModel ?? opts.model,
|
|
1475
1577
|
maxTokens: 2048,
|
|
1476
1578
|
thinkingLevel: "high"
|
|
@@ -1507,10 +1609,11 @@ ${rolesText}
|
|
|
1507
1609
|
|
|
1508
1610
|
Determine the best execution strategy.`,
|
|
1509
1611
|
{
|
|
1612
|
+
...opts,
|
|
1510
1613
|
model: opts.plannerModel ?? opts.model,
|
|
1511
1614
|
maxTokens: 512,
|
|
1512
1615
|
thinkingLevel: "high",
|
|
1513
|
-
system: WORKFLOW_SYSTEM
|
|
1616
|
+
system: mergeSystem(opts.system, WORKFLOW_SYSTEM)
|
|
1514
1617
|
}
|
|
1515
1618
|
);
|
|
1516
1619
|
const wfMatch = response.match(/WORKFLOW\s*:\s*(.+)/i);
|
|
@@ -1529,10 +1632,9 @@ async function executeRoles(roles, task, workflow, opts) {
|
|
|
1529
1632
|
let context = task;
|
|
1530
1633
|
for (const role of roles) {
|
|
1531
1634
|
const output = await ask(context, {
|
|
1635
|
+
...opts,
|
|
1532
1636
|
model: workerModel,
|
|
1533
|
-
|
|
1534
|
-
thinkingLevel: opts.thinkingLevel,
|
|
1535
|
-
system: EXECUTE_SYSTEM2(role)
|
|
1637
|
+
system: mergeSystem(opts.system, EXECUTE_SYSTEM2(role))
|
|
1536
1638
|
});
|
|
1537
1639
|
results.push({ role: role.name, output });
|
|
1538
1640
|
context = `Previous output from ${role.name}:
|
|
@@ -1544,10 +1646,9 @@ Continue with: ${task}`;
|
|
|
1544
1646
|
const parallelResults = await Promise.allSettled(
|
|
1545
1647
|
roles.map(
|
|
1546
1648
|
(role) => ask(task, {
|
|
1649
|
+
...opts,
|
|
1547
1650
|
model: workerModel,
|
|
1548
|
-
|
|
1549
|
-
thinkingLevel: opts.thinkingLevel,
|
|
1550
|
-
system: EXECUTE_SYSTEM2(role)
|
|
1651
|
+
system: mergeSystem(opts.system, EXECUTE_SYSTEM2(role))
|
|
1551
1652
|
}).then((text) => ({ role: role.name, output: text })).catch((err) => ({ role: role.name, output: `(failed: ${String(err)})` }))
|
|
1552
1653
|
)
|
|
1553
1654
|
);
|
|
@@ -1569,10 +1670,10 @@ ${resultsText}
|
|
|
1569
1670
|
|
|
1570
1671
|
Synthesize a comprehensive final answer.`,
|
|
1571
1672
|
{
|
|
1673
|
+
...opts,
|
|
1572
1674
|
model: opts.plannerModel ?? opts.model,
|
|
1573
|
-
maxTokens: opts.maxTokens,
|
|
1574
1675
|
thinkingLevel: "high",
|
|
1575
|
-
system: SYNTHESIS_SYSTEM3
|
|
1676
|
+
system: mergeSystem(opts.system, SYNTHESIS_SYSTEM3)
|
|
1576
1677
|
}
|
|
1577
1678
|
);
|
|
1578
1679
|
}
|
|
@@ -1612,38 +1713,29 @@ async function execute9(pieces, args, opts) {
|
|
|
1612
1713
|
`);
|
|
1613
1714
|
const roleResults = await executeRoles(roles, task, workflow, opts);
|
|
1614
1715
|
if (!opts.quiet) process.stderr.write(" \u2192 Synthesizing...\n");
|
|
1615
|
-
const synthesis = await synthesize(task, roleResults, { ...opts, plannerModel });
|
|
1616
|
-
|
|
1617
|
-
const
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
`
|
|
1621
|
-
`
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
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;
|
|
1716
|
+
const synthesis = await synthesize(task, roleResults, { ...opts, plannerModel });
|
|
1717
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1718
|
+
const qualityReview = await runQualityReview(task, synthesis, opts);
|
|
1719
|
+
const t1 = Date.now();
|
|
1720
|
+
const summary = [
|
|
1721
|
+
`Roles: ${roles.map((r) => r.name).join(", ")}`,
|
|
1722
|
+
`Workflow: ${workflow} (${reasoning})`,
|
|
1723
|
+
`Results: ${roleResults.length}/${roles.length} succeeded`,
|
|
1724
|
+
`Synthesis: ${synthesis}`
|
|
1725
|
+
].join("\n\n");
|
|
1726
|
+
return new NuOutput(
|
|
1727
|
+
summary,
|
|
1728
|
+
roles,
|
|
1729
|
+
workflow,
|
|
1730
|
+
reasoning,
|
|
1731
|
+
roleResults,
|
|
1732
|
+
synthesis,
|
|
1733
|
+
t0,
|
|
1734
|
+
t1,
|
|
1735
|
+
qualityReview
|
|
1736
|
+
);
|
|
1645
1737
|
}
|
|
1646
|
-
var \u039D =
|
|
1738
|
+
var \u039D = createPatternTag(defaults9, execute9);
|
|
1647
1739
|
|
|
1648
1740
|
// src/patterns/orchestrator.ts
|
|
1649
1741
|
var defaults10 = {
|
|
@@ -1663,15 +1755,17 @@ var OrchestratorWorkerResult = class {
|
|
|
1663
1755
|
success;
|
|
1664
1756
|
};
|
|
1665
1757
|
var OrchestratorOutput = class extends PatternOutput {
|
|
1666
|
-
constructor(text, plan, synthesis, workerResults, startTime, endTime) {
|
|
1758
|
+
constructor(text, plan, synthesis, workerResults, startTime, endTime, qualityReview) {
|
|
1667
1759
|
super(text, startTime, endTime);
|
|
1668
1760
|
this.plan = plan;
|
|
1669
1761
|
this.synthesis = synthesis;
|
|
1670
1762
|
this.workerResults = workerResults;
|
|
1763
|
+
this.qualityReview = qualityReview;
|
|
1671
1764
|
}
|
|
1672
1765
|
plan;
|
|
1673
1766
|
synthesis;
|
|
1674
1767
|
workerResults;
|
|
1768
|
+
qualityReview;
|
|
1675
1769
|
};
|
|
1676
1770
|
var PLANNER_SYSTEM = `You are a senior architect and project planner. Given a high-level request, create a detailed execution plan.
|
|
1677
1771
|
|
|
@@ -1694,6 +1788,7 @@ async function execute10(pieces, args, opts) {
|
|
|
1694
1788
|
const request = build(pieces, args);
|
|
1695
1789
|
const t0 = Date.now();
|
|
1696
1790
|
const workerCount = opts.workers ?? 3;
|
|
1791
|
+
const phases = [];
|
|
1697
1792
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
1698
1793
|
const workerModel = opts.workerModel ?? opts.model;
|
|
1699
1794
|
if (!opts.quiet) {
|
|
@@ -1703,11 +1798,18 @@ async function execute10(pieces, args, opts) {
|
|
|
1703
1798
|
);
|
|
1704
1799
|
}
|
|
1705
1800
|
if (!opts.quiet) process.stderr.write(" \u2192 Planning...\n");
|
|
1801
|
+
const planStart = Date.now();
|
|
1706
1802
|
const planText = await ask(request, {
|
|
1803
|
+
...opts,
|
|
1707
1804
|
model: plannerModel,
|
|
1708
|
-
maxTokens: opts.maxTokens,
|
|
1709
1805
|
thinkingLevel: "high",
|
|
1710
|
-
system: PLANNER_SYSTEM.replace("{$workerCount}", String(workerCount))
|
|
1806
|
+
system: mergeSystem(opts.system, PLANNER_SYSTEM.replace("{$workerCount}", String(workerCount)))
|
|
1807
|
+
});
|
|
1808
|
+
phases.push({
|
|
1809
|
+
phase: "plan",
|
|
1810
|
+
durationMs: Date.now() - planStart,
|
|
1811
|
+
description: `Generated plan with ${workerCount} workers`,
|
|
1812
|
+
modelUsed: plannerModel
|
|
1711
1813
|
});
|
|
1712
1814
|
const subTasks = [];
|
|
1713
1815
|
const taskLines = planText.split("\n");
|
|
@@ -1731,27 +1833,37 @@ async function execute10(pieces, args, opts) {
|
|
|
1731
1833
|
`);
|
|
1732
1834
|
}
|
|
1733
1835
|
}
|
|
1836
|
+
const planSummary = tasks.length > 0 ? `Execute ${tasks.length} sub-task(s) as planned?
|
|
1837
|
+
${tasks.map((t, i) => `${i + 1}. ${t.slice(0, 80)}`).join("\n ")}` : `Execute the plan?`;
|
|
1838
|
+
if (!await confirmPhase(planSummary, opts)) {
|
|
1839
|
+
throw new Error("pizx/\u03A9: Execution cancelled by user.");
|
|
1840
|
+
}
|
|
1734
1841
|
const workerResults = [];
|
|
1735
1842
|
const concurrency = opts.concurrency ?? 3;
|
|
1843
|
+
const dispatchStart = Date.now();
|
|
1736
1844
|
for (let i = 0; i < tasks.length; i += concurrency) {
|
|
1737
1845
|
const batch = tasks.slice(i, i + concurrency);
|
|
1738
1846
|
const batchResults = await Promise.allSettled(
|
|
1739
1847
|
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))
|
|
1848
|
+
(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
1849
|
)
|
|
1747
1850
|
);
|
|
1748
1851
|
batchResults.forEach((r) => {
|
|
1749
1852
|
if (r.status === "fulfilled") workerResults.push(r.value);
|
|
1750
1853
|
});
|
|
1751
1854
|
}
|
|
1855
|
+
const succeeded = workerResults.filter((w) => w.success).length;
|
|
1856
|
+
phases.push({
|
|
1857
|
+
phase: "dispatch",
|
|
1858
|
+
durationMs: Date.now() - dispatchStart,
|
|
1859
|
+
description: `Executed ${workerResults.length} worker(s), ${succeeded} succeeded`,
|
|
1860
|
+
modelUsed: workerModel,
|
|
1861
|
+
callCount: workerResults.length
|
|
1862
|
+
});
|
|
1752
1863
|
if (!opts.quiet) process.stderr.write(" \u2192 Synthesizing results...\n");
|
|
1753
1864
|
const workerTexts = workerResults.map((wr, i) => `Task ${i + 1}: ${wr.task}
|
|
1754
1865
|
Result: ${wr.output}`).join("\n\n");
|
|
1866
|
+
const synthStart = Date.now();
|
|
1755
1867
|
const synthesis = await ask(
|
|
1756
1868
|
`Original request:
|
|
1757
1869
|
${request}
|
|
@@ -1764,46 +1876,60 @@ ${workerTexts}
|
|
|
1764
1876
|
|
|
1765
1877
|
Synthesize a final deliverable.`,
|
|
1766
1878
|
{
|
|
1879
|
+
...opts,
|
|
1767
1880
|
model: plannerModel,
|
|
1768
|
-
maxTokens: opts.maxTokens,
|
|
1769
1881
|
thinkingLevel: "high",
|
|
1770
|
-
system: SYNTHESIS_SYSTEM4
|
|
1882
|
+
system: mergeSystem(opts.system, SYNTHESIS_SYSTEM4)
|
|
1771
1883
|
}
|
|
1772
1884
|
);
|
|
1885
|
+
phases.push({
|
|
1886
|
+
phase: "synthesize",
|
|
1887
|
+
durationMs: Date.now() - synthStart,
|
|
1888
|
+
description: "Synthesized worker results into final deliverable",
|
|
1889
|
+
modelUsed: plannerModel
|
|
1890
|
+
});
|
|
1891
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
1892
|
+
const qualityStart = Date.now();
|
|
1893
|
+
const qualityReview = await runQualityReview(request, synthesis, opts);
|
|
1894
|
+
if (qualityReview) {
|
|
1895
|
+
phases.push({
|
|
1896
|
+
phase: "quality-review",
|
|
1897
|
+
durationMs: Date.now() - qualityStart,
|
|
1898
|
+
description: `Score: ${qualityReview.score.toFixed(2)} \u2014 ${qualityReview.assessment.slice(0, 60)}`,
|
|
1899
|
+
modelUsed: plannerModel
|
|
1900
|
+
});
|
|
1901
|
+
}
|
|
1773
1902
|
const t1 = Date.now();
|
|
1903
|
+
const reviewSection = qualityReview ? `
|
|
1904
|
+
|
|
1905
|
+
Quality Review: ${qualityReview.score.toFixed(2)} \u2014 ${qualityReview.assessment}
|
|
1906
|
+
Recommendation: ${qualityReview.recommendation}` : "";
|
|
1774
1907
|
const summary = `Plan:
|
|
1775
1908
|
${planText}
|
|
1776
1909
|
|
|
1777
1910
|
Workers: ${workerResults.filter((w) => w.success).length}/${workerResults.length} succeeded
|
|
1778
1911
|
|
|
1779
1912
|
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;
|
|
1913
|
+
${synthesis}${reviewSection}`;
|
|
1914
|
+
const output = new OrchestratorOutput(
|
|
1915
|
+
summary,
|
|
1916
|
+
planText,
|
|
1917
|
+
synthesis,
|
|
1918
|
+
workerResults,
|
|
1919
|
+
t0,
|
|
1920
|
+
t1,
|
|
1921
|
+
qualityReview
|
|
1922
|
+
);
|
|
1923
|
+
output.phaseLog = phases;
|
|
1924
|
+
return output;
|
|
1803
1925
|
}
|
|
1804
|
-
var \u03A9 =
|
|
1926
|
+
var \u03A9 = createPatternTag(defaults10, execute10);
|
|
1805
1927
|
|
|
1806
1928
|
// src/patterns/pipeline.ts
|
|
1929
|
+
function describeStage(stage) {
|
|
1930
|
+
if (typeof stage === "function") return "(composed pattern)";
|
|
1931
|
+
return stage;
|
|
1932
|
+
}
|
|
1807
1933
|
var defaults11 = {
|
|
1808
1934
|
maxTokens: 4096,
|
|
1809
1935
|
thinkingLevel: "medium"
|
|
@@ -1819,13 +1945,15 @@ var PipelineStageResult = class {
|
|
|
1819
1945
|
index;
|
|
1820
1946
|
};
|
|
1821
1947
|
var PipelineOutput = class extends PatternOutput {
|
|
1822
|
-
constructor(text, finalOutput, stages, startTime, endTime) {
|
|
1948
|
+
constructor(text, finalOutput, stages, startTime, endTime, qualityReview) {
|
|
1823
1949
|
super(text, startTime, endTime);
|
|
1824
1950
|
this.finalOutput = finalOutput;
|
|
1825
1951
|
this.stages = stages;
|
|
1952
|
+
this.qualityReview = qualityReview;
|
|
1826
1953
|
}
|
|
1827
1954
|
finalOutput;
|
|
1828
1955
|
stages;
|
|
1956
|
+
qualityReview;
|
|
1829
1957
|
};
|
|
1830
1958
|
function parseStages(template, explicitStages, separator) {
|
|
1831
1959
|
if (explicitStages && explicitStages.length > 0) return explicitStages;
|
|
@@ -1867,55 +1995,46 @@ async function execute11(pieces, args, opts) {
|
|
|
1867
1995
|
`);
|
|
1868
1996
|
}
|
|
1869
1997
|
}
|
|
1998
|
+
const stageSummary = `Run ${stages.length} pipeline stage(s)?
|
|
1999
|
+
${stages.map((s, i) => `${i + 1}. ${describeStage(s)}`).join("\n ")}`;
|
|
2000
|
+
if (!await confirmPhase(stageSummary, opts)) {
|
|
2001
|
+
throw new Error("pizx/\u039B: Execution cancelled by user.");
|
|
2002
|
+
}
|
|
1870
2003
|
const stageResults = [];
|
|
1871
2004
|
let currentInput = "";
|
|
1872
2005
|
for (let i = 0; i < stages.length; i++) {
|
|
1873
2006
|
const stage = stages[i];
|
|
2007
|
+
const stageLabel = describeStage(stage);
|
|
1874
2008
|
const customPrompt = opts.stagePrompts?.[i];
|
|
1875
2009
|
if (!opts.quiet)
|
|
1876
|
-
process.stderr.write(` \u2192 Stage ${i + 1}/${stages.length}: ${
|
|
2010
|
+
process.stderr.write(` \u2192 Stage ${i + 1}/${stages.length}: ${stageLabel.slice(0, 50)}...
|
|
1877
2011
|
`);
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
2012
|
+
let output;
|
|
2013
|
+
if (typeof stage === "function") {
|
|
2014
|
+
output = await stage(currentInput);
|
|
2015
|
+
} else {
|
|
2016
|
+
const prompt = customPrompt ?? generateStagePrompt(stage, currentInput, i === 0);
|
|
2017
|
+
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.`;
|
|
2018
|
+
output = await ask(prompt, {
|
|
2019
|
+
...opts,
|
|
2020
|
+
model: workerModel,
|
|
2021
|
+
system: mergeSystem(opts.system, systemMessage)
|
|
2022
|
+
});
|
|
2023
|
+
}
|
|
2024
|
+
stageResults.push(new PipelineStageResult(stageLabel, output, i));
|
|
1887
2025
|
currentInput = output;
|
|
1888
2026
|
}
|
|
1889
2027
|
const t1 = Date.now();
|
|
1890
2028
|
const finalOutput = currentInput;
|
|
2029
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
2030
|
+
const qualityReview = await runQualityReview(template, finalOutput, opts);
|
|
1891
2031
|
const summary = stageResults.map(
|
|
1892
2032
|
(sr) => `Stage ${sr.index + 1} (${sr.stage}):
|
|
1893
2033
|
${sr.output.slice(0, 200)}${sr.output.length > 200 ? "..." : ""}`
|
|
1894
2034
|
).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;
|
|
2035
|
+
return new PipelineOutput(summary, finalOutput, stageResults, t0, t1, qualityReview);
|
|
1917
2036
|
}
|
|
1918
|
-
var \u039B =
|
|
2037
|
+
var \u039B = createPatternTag(defaults11, execute11);
|
|
1919
2038
|
|
|
1920
2039
|
// src/patterns/ralph.ts
|
|
1921
2040
|
import { createAgentSession } from "@earendil-works/pi-coding-agent";
|
|
@@ -1950,17 +2069,17 @@ async function executeWithTools(goal, opts) {
|
|
|
1950
2069
|
});
|
|
1951
2070
|
try {
|
|
1952
2071
|
await session.sendUserMessage(goal);
|
|
1953
|
-
const
|
|
1954
|
-
for (let i =
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2072
|
+
const messages = session.messages;
|
|
2073
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2074
|
+
const msg = messages[i];
|
|
2075
|
+
if (msg?.role !== "assistant") continue;
|
|
2076
|
+
const c = "content" in msg ? msg.content : void 0;
|
|
2077
|
+
if (typeof c === "string") return c.trim();
|
|
2078
|
+
if (Array.isArray(c)) {
|
|
2079
|
+
const texts = c.filter(
|
|
2080
|
+
(x) => x.type === "text" && typeof x.text === "string"
|
|
2081
|
+
).map((x) => x.text);
|
|
2082
|
+
if (texts.length > 0) return texts.join("").trim();
|
|
1964
2083
|
}
|
|
1965
2084
|
}
|
|
1966
2085
|
return "(no assistant response)";
|
|
@@ -1995,10 +2114,9 @@ async function execute12(pieces, args, opts) {
|
|
|
1995
2114
|
}
|
|
1996
2115
|
if (!opts.quiet) process.stderr.write(" \u2192 Analyzing...\n");
|
|
1997
2116
|
const analysis = await ask(currentGoal, {
|
|
2117
|
+
...opts,
|
|
1998
2118
|
model: plannerModel,
|
|
1999
|
-
|
|
2000
|
-
thinkingLevel: opts.thinkingLevel,
|
|
2001
|
-
system: ANALYSIS_SYSTEM2
|
|
2119
|
+
system: mergeSystem(opts.system, ANALYSIS_SYSTEM2)
|
|
2002
2120
|
});
|
|
2003
2121
|
if (!opts.quiet) process.stderr.write(" \u2192 Planning...\n");
|
|
2004
2122
|
const plan = await ask(
|
|
@@ -2007,12 +2125,7 @@ async function execute12(pieces, args, opts) {
|
|
|
2007
2125
|
Analysis: ${analysis}
|
|
2008
2126
|
|
|
2009
2127
|
Generate an implementation plan.`,
|
|
2010
|
-
{
|
|
2011
|
-
model: plannerModel,
|
|
2012
|
-
maxTokens: opts.maxTokens,
|
|
2013
|
-
thinkingLevel: opts.thinkingLevel,
|
|
2014
|
-
system: PLAN_SYSTEM2
|
|
2015
|
-
}
|
|
2128
|
+
{ ...opts, model: plannerModel, system: mergeSystem(opts.system, PLAN_SYSTEM2) }
|
|
2016
2129
|
);
|
|
2017
2130
|
if (!opts.quiet) process.stderr.write(" \u2192 Executing...\n");
|
|
2018
2131
|
const result = opts.useTools ? await executeWithTools(`Implement this plan:
|
|
@@ -2025,9 +2138,8 @@ Goal: ${currentGoal}`, {
|
|
|
2025
2138
|
${plan}
|
|
2026
2139
|
|
|
2027
2140
|
Goal: ${currentGoal}`, {
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
thinkingLevel: opts.thinkingLevel
|
|
2141
|
+
...opts,
|
|
2142
|
+
model: workerModel
|
|
2031
2143
|
});
|
|
2032
2144
|
if (!opts.quiet) process.stderr.write(" \u2192 Reviewing...\n");
|
|
2033
2145
|
const review = await ask(`Plan:
|
|
@@ -2037,10 +2149,11 @@ Result:
|
|
|
2037
2149
|
${result}
|
|
2038
2150
|
|
|
2039
2151
|
Review the implementation.`, {
|
|
2152
|
+
...opts,
|
|
2040
2153
|
model: plannerModel,
|
|
2041
2154
|
maxTokens: 1024,
|
|
2042
2155
|
thinkingLevel: "high",
|
|
2043
|
-
system: REVIEW_SYSTEM
|
|
2156
|
+
system: mergeSystem(opts.system, REVIEW_SYSTEM)
|
|
2044
2157
|
});
|
|
2045
2158
|
const shouldContinue = review.includes("ITERATE") && !review.includes("DONE");
|
|
2046
2159
|
iterations.push({
|
|
@@ -2076,28 +2189,7 @@ Original goal: ${goal}`;
|
|
|
2076
2189
|
t1
|
|
2077
2190
|
);
|
|
2078
2191
|
}
|
|
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();
|
|
2192
|
+
var \u03A1 = createPatternTag(defaults12, execute12);
|
|
2101
2193
|
|
|
2102
2194
|
// src/patterns/subagent.ts
|
|
2103
2195
|
var defaults13 = {
|
|
@@ -2117,13 +2209,15 @@ var SubagentResult = class {
|
|
|
2117
2209
|
success;
|
|
2118
2210
|
};
|
|
2119
2211
|
var SubagentOutput = class extends PatternOutput {
|
|
2120
|
-
constructor(text, synthesis, subResults, startTime, endTime) {
|
|
2212
|
+
constructor(text, synthesis, subResults, startTime, endTime, qualityReview) {
|
|
2121
2213
|
super(text, startTime, endTime);
|
|
2122
2214
|
this.synthesis = synthesis;
|
|
2123
2215
|
this.subResults = subResults;
|
|
2216
|
+
this.qualityReview = qualityReview;
|
|
2124
2217
|
}
|
|
2125
2218
|
synthesis;
|
|
2126
2219
|
subResults;
|
|
2220
|
+
qualityReview;
|
|
2127
2221
|
};
|
|
2128
2222
|
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
2223
|
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 +2230,11 @@ ${task}
|
|
|
2136
2230
|
|
|
2137
2231
|
Output a JSON array of strings.`,
|
|
2138
2232
|
{
|
|
2233
|
+
...opts,
|
|
2139
2234
|
model: opts.model,
|
|
2140
2235
|
maxTokens: 1024,
|
|
2141
2236
|
thinkingLevel: "medium",
|
|
2142
|
-
system: DECOMPOSE_SYSTEM
|
|
2237
|
+
system: mergeSystem(opts.system, DECOMPOSE_SYSTEM)
|
|
2143
2238
|
}
|
|
2144
2239
|
);
|
|
2145
2240
|
try {
|
|
@@ -2160,6 +2255,7 @@ var SUBAGENT_SYSTEM = `You are a domain specialist. Complete your assigned sub-t
|
|
|
2160
2255
|
async function execute13(pieces, args, opts) {
|
|
2161
2256
|
const task = build(pieces, args);
|
|
2162
2257
|
const t0 = Date.now();
|
|
2258
|
+
const phases = [];
|
|
2163
2259
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
2164
2260
|
const workerModel = opts.workerModel ?? opts.model;
|
|
2165
2261
|
if (!opts.quiet) {
|
|
@@ -2169,7 +2265,14 @@ async function execute13(pieces, args, opts) {
|
|
|
2169
2265
|
);
|
|
2170
2266
|
}
|
|
2171
2267
|
if (!opts.quiet) process.stderr.write(" \u2192 Decomposing task into sub-tasks...\n");
|
|
2268
|
+
const decomposeStart = Date.now();
|
|
2172
2269
|
const subTasks = await decomposeTask(task, { ...opts, model: plannerModel });
|
|
2270
|
+
phases.push({
|
|
2271
|
+
phase: "decompose",
|
|
2272
|
+
durationMs: Date.now() - decomposeStart,
|
|
2273
|
+
description: `Decomposed into ${subTasks.length} sub-task(s)`,
|
|
2274
|
+
modelUsed: plannerModel
|
|
2275
|
+
});
|
|
2173
2276
|
if (!opts.quiet) {
|
|
2174
2277
|
process.stderr.write(` \u2192 ${subTasks.length} sub-task(s) identified:
|
|
2175
2278
|
`);
|
|
@@ -2179,27 +2282,37 @@ async function execute13(pieces, args, opts) {
|
|
|
2179
2282
|
`);
|
|
2180
2283
|
}
|
|
2181
2284
|
}
|
|
2285
|
+
const subTaskSummary = `Execute ${subTasks.length} sub-task(s)?
|
|
2286
|
+
${subTasks.map((st, i) => `${i + 1}. ${st.slice(0, 80)}`).join("\n ")}`;
|
|
2287
|
+
if (!await confirmPhase(subTaskSummary, opts)) {
|
|
2288
|
+
throw new Error("pizx/\u03A3: Execution cancelled by user.");
|
|
2289
|
+
}
|
|
2182
2290
|
const subResults = [];
|
|
2183
2291
|
const concurrency = opts.concurrency ?? 4;
|
|
2292
|
+
const execStart = Date.now();
|
|
2184
2293
|
for (let i = 0; i < subTasks.length; i += concurrency) {
|
|
2185
2294
|
const batch = subTasks.slice(i, i + concurrency);
|
|
2186
2295
|
const batchResults = await Promise.allSettled(
|
|
2187
2296
|
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))
|
|
2297
|
+
(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
2298
|
)
|
|
2195
2299
|
);
|
|
2196
2300
|
batchResults.forEach((r) => {
|
|
2197
2301
|
if (r.status === "fulfilled") subResults.push(r.value);
|
|
2198
2302
|
});
|
|
2199
2303
|
}
|
|
2304
|
+
const succeeded = subResults.filter((r) => r.success).length;
|
|
2305
|
+
phases.push({
|
|
2306
|
+
phase: "execute",
|
|
2307
|
+
durationMs: Date.now() - execStart,
|
|
2308
|
+
description: `Executed ${subResults.length} sub-task(s), ${succeeded} succeeded`,
|
|
2309
|
+
modelUsed: workerModel,
|
|
2310
|
+
callCount: subResults.length
|
|
2311
|
+
});
|
|
2200
2312
|
if (!opts.quiet) process.stderr.write(" \u2192 Synthesizing results...\n");
|
|
2201
2313
|
const subResultsText = subResults.map((sr, i) => `Sub-task ${i + 1}: ${sr.subTask}
|
|
2202
2314
|
Result: ${sr.text}`).join("\n\n");
|
|
2315
|
+
const synthStart = Date.now();
|
|
2203
2316
|
const synthesis = await ask(
|
|
2204
2317
|
`Original task:
|
|
2205
2318
|
${task}
|
|
@@ -2208,38 +2321,31 @@ Sub-task results:
|
|
|
2208
2321
|
${subResultsText}
|
|
2209
2322
|
|
|
2210
2323
|
Synthesize a comprehensive answer.`,
|
|
2211
|
-
{
|
|
2212
|
-
model: plannerModel,
|
|
2213
|
-
maxTokens: opts.maxTokens,
|
|
2214
|
-
thinkingLevel: opts.thinkingLevel,
|
|
2215
|
-
system: SYNTHESIS_SYSTEM5
|
|
2216
|
-
}
|
|
2324
|
+
{ ...opts, model: plannerModel, system: mergeSystem(opts.system, SYNTHESIS_SYSTEM5) }
|
|
2217
2325
|
);
|
|
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
|
|
2326
|
+
phases.push({
|
|
2327
|
+
phase: "synthesize",
|
|
2328
|
+
durationMs: Date.now() - synthStart,
|
|
2329
|
+
description: "Synthesized sub-agent results",
|
|
2330
|
+
modelUsed: plannerModel
|
|
2239
2331
|
});
|
|
2240
|
-
|
|
2332
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
2333
|
+
const qStart = Date.now();
|
|
2334
|
+
const qualityReview = await runQualityReview(task, synthesis, opts);
|
|
2335
|
+
if (qualityReview) {
|
|
2336
|
+
phases.push({
|
|
2337
|
+
phase: "quality-review",
|
|
2338
|
+
durationMs: Date.now() - qStart,
|
|
2339
|
+
description: `Score: ${qualityReview.score.toFixed(2)}`,
|
|
2340
|
+
modelUsed: plannerModel
|
|
2341
|
+
});
|
|
2342
|
+
}
|
|
2343
|
+
const t1 = Date.now();
|
|
2344
|
+
const output = new SubagentOutput(synthesis, synthesis, subResults, t0, t1, qualityReview);
|
|
2345
|
+
output.phaseLog = phases;
|
|
2346
|
+
return output;
|
|
2241
2347
|
}
|
|
2242
|
-
var \u03A3 =
|
|
2348
|
+
var \u03A3 = createPatternTag(defaults13, execute13);
|
|
2243
2349
|
|
|
2244
2350
|
// src/patterns/tau.ts
|
|
2245
2351
|
var defaults14 = {
|
|
@@ -2263,15 +2369,17 @@ var ToolMediatedEntry = class {
|
|
|
2263
2369
|
content;
|
|
2264
2370
|
};
|
|
2265
2371
|
var TauOutput = class extends PatternOutput {
|
|
2266
|
-
constructor(text, entries, finalState, synthesis, startTime, endTime) {
|
|
2372
|
+
constructor(text, entries, finalState, synthesis, startTime, endTime, qualityReview) {
|
|
2267
2373
|
super(text, startTime, endTime);
|
|
2268
2374
|
this.entries = entries;
|
|
2269
2375
|
this.finalState = finalState;
|
|
2270
2376
|
this.synthesis = synthesis;
|
|
2377
|
+
this.qualityReview = qualityReview;
|
|
2271
2378
|
}
|
|
2272
2379
|
entries;
|
|
2273
2380
|
finalState;
|
|
2274
2381
|
synthesis;
|
|
2382
|
+
qualityReview;
|
|
2275
2383
|
};
|
|
2276
2384
|
var SCHEMA_SYSTEM = `You are a coordination architect. Given a task, design a shared structured context for agent collaboration.
|
|
2277
2385
|
|
|
@@ -2326,6 +2434,7 @@ async function defineSchema(task, opts) {
|
|
|
2326
2434
|
const response = await ask(`Task: ${task}
|
|
2327
2435
|
|
|
2328
2436
|
${prompt}`, {
|
|
2437
|
+
...opts,
|
|
2329
2438
|
model: opts.plannerModel ?? opts.model,
|
|
2330
2439
|
maxTokens: 1024,
|
|
2331
2440
|
thinkingLevel: "high"
|
|
@@ -2378,10 +2487,9 @@ async function executeRound(roles, assignments, store, round, opts) {
|
|
|
2378
2487
|
const systemPrompt = isWrite ? WRITE_SYSTEM(role, keysStr).replace("{store}", storeText) : UPDATE_SYSTEM(role, keysStr).replace("{store}", storeText);
|
|
2379
2488
|
const task = isWrite ? `Write your initial findings to your assigned keys: ${keysStr}` : `Review the shared context and update your entries for keys: ${keysStr}`;
|
|
2380
2489
|
const response = await ask(task, {
|
|
2490
|
+
...opts,
|
|
2381
2491
|
model: workerModel,
|
|
2382
|
-
|
|
2383
|
-
thinkingLevel: opts.thinkingLevel,
|
|
2384
|
-
system: systemPrompt
|
|
2492
|
+
system: mergeSystem(opts.system, systemPrompt)
|
|
2385
2493
|
});
|
|
2386
2494
|
return { role, response };
|
|
2387
2495
|
})
|
|
@@ -2421,10 +2529,10 @@ ${storeText}
|
|
|
2421
2529
|
|
|
2422
2530
|
Consolidate into a comprehensive, well-structured synthesis.`,
|
|
2423
2531
|
{
|
|
2532
|
+
...opts,
|
|
2424
2533
|
model: opts.plannerModel ?? opts.model,
|
|
2425
|
-
maxTokens: opts.maxTokens,
|
|
2426
2534
|
thinkingLevel: "high",
|
|
2427
|
-
system: CONSOLIDATE_SYSTEM
|
|
2535
|
+
system: mergeSystem(opts.system, CONSOLIDATE_SYSTEM)
|
|
2428
2536
|
}
|
|
2429
2537
|
);
|
|
2430
2538
|
}
|
|
@@ -2469,6 +2577,8 @@ async function execute14(pieces, args, opts) {
|
|
|
2469
2577
|
}
|
|
2470
2578
|
if (!opts.quiet) process.stderr.write(" \u2192 Consolidating store...\n");
|
|
2471
2579
|
const synthesis = await consolidateStore(task, store, { ...opts, plannerModel });
|
|
2580
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
2581
|
+
const qualityReview = await runQualityReview(task, synthesis, opts);
|
|
2472
2582
|
const t1 = Date.now();
|
|
2473
2583
|
const summary = [
|
|
2474
2584
|
`Schema keys: ${keys.join(", ")}`,
|
|
@@ -2477,30 +2587,9 @@ async function execute14(pieces, args, opts) {
|
|
|
2477
2587
|
`Entries: ${allEntries.length}`,
|
|
2478
2588
|
`Synthesis: ${synthesis}`
|
|
2479
2589
|
].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;
|
|
2590
|
+
return new TauOutput(summary, allEntries, store, synthesis, t0, t1, qualityReview);
|
|
2502
2591
|
}
|
|
2503
|
-
var \u03A4 =
|
|
2592
|
+
var \u03A4 = createPatternTag(defaults14, execute14);
|
|
2504
2593
|
|
|
2505
2594
|
// src/patterns/thread.ts
|
|
2506
2595
|
var defaults15 = {
|
|
@@ -2509,27 +2598,6 @@ var defaults15 = {
|
|
|
2509
2598
|
agents: 3,
|
|
2510
2599
|
turns: 3
|
|
2511
2600
|
};
|
|
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
2601
|
var ThreadMessage = class {
|
|
2534
2602
|
constructor(role, turn, content) {
|
|
2535
2603
|
this.role = role;
|
|
@@ -2541,13 +2609,15 @@ var ThreadMessage = class {
|
|
|
2541
2609
|
content;
|
|
2542
2610
|
};
|
|
2543
2611
|
var ThreadOutput = class extends PatternOutput {
|
|
2544
|
-
constructor(text, conclusion, messages, startTime, endTime) {
|
|
2612
|
+
constructor(text, conclusion, messages, startTime, endTime, qualityReview) {
|
|
2545
2613
|
super(text, startTime, endTime);
|
|
2546
2614
|
this.conclusion = conclusion;
|
|
2547
2615
|
this.messages = messages;
|
|
2616
|
+
this.qualityReview = qualityReview;
|
|
2548
2617
|
}
|
|
2549
2618
|
conclusion;
|
|
2550
2619
|
messages;
|
|
2620
|
+
qualityReview;
|
|
2551
2621
|
};
|
|
2552
2622
|
var THREAD_PROMPT = `You are an agent with the role: {role}.
|
|
2553
2623
|
Engage in a multi-agent conversation about the topic.
|
|
@@ -2569,7 +2639,7 @@ async function execute15(pieces, args, opts) {
|
|
|
2569
2639
|
const t0 = Date.now();
|
|
2570
2640
|
const agentCount = opts.agents ?? 3;
|
|
2571
2641
|
const maxTurns = opts.turns ?? 3;
|
|
2572
|
-
const roles = opts.roles ??
|
|
2642
|
+
const roles = opts.roles ?? THREAD_ROLE_SETS[agentCount] ?? THREAD_ROLE_SETS[3] ?? [];
|
|
2573
2643
|
const plannerModel = opts.plannerModel ?? opts.model;
|
|
2574
2644
|
const workerModel = opts.workerModel ?? opts.model;
|
|
2575
2645
|
if (!opts.quiet) {
|
|
@@ -2587,11 +2657,7 @@ async function execute15(pieces, args, opts) {
|
|
|
2587
2657
|
for (let a = 0; a < roles.length; a++) {
|
|
2588
2658
|
const role = roles[a] ?? `Agent ${a + 1}`;
|
|
2589
2659
|
const prompt = buildThreadPrompt(role, thread);
|
|
2590
|
-
const response = await ask(prompt, {
|
|
2591
|
-
model: workerModel,
|
|
2592
|
-
maxTokens: opts.maxTokens,
|
|
2593
|
-
thinkingLevel: opts.thinkingLevel
|
|
2594
|
-
});
|
|
2660
|
+
const response = await ask(prompt, { ...opts, model: workerModel });
|
|
2595
2661
|
messages.push(new ThreadMessage(role, turn, response));
|
|
2596
2662
|
thread += `
|
|
2597
2663
|
[${role}] (Turn ${turn}): ${response}
|
|
@@ -2607,46 +2673,24 @@ ${thread}
|
|
|
2607
2673
|
|
|
2608
2674
|
Synthesize a clear, actionable conclusion.`,
|
|
2609
2675
|
{
|
|
2676
|
+
...opts,
|
|
2610
2677
|
model: plannerModel,
|
|
2611
|
-
maxTokens: opts.maxTokens,
|
|
2612
2678
|
thinkingLevel: "high",
|
|
2613
|
-
system: SYNTHESIS_SYSTEM6
|
|
2679
|
+
system: mergeSystem(opts.system, SYNTHESIS_SYSTEM6)
|
|
2614
2680
|
}
|
|
2615
2681
|
);
|
|
2682
|
+
if (!opts.quiet && opts.qualityCheck) process.stderr.write(" \u2192 Quality review...\n");
|
|
2683
|
+
const qualityReview = await runQualityReview(topic, conclusion, opts);
|
|
2616
2684
|
const t1 = Date.now();
|
|
2617
2685
|
const summary = messages.map(
|
|
2618
2686
|
(m) => `[${m.role}] Turn ${m.turn}: ${m.content.slice(0, 150)}${m.content.length > 150 ? "..." : ""}`
|
|
2619
2687
|
).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;
|
|
2688
|
+
return new ThreadOutput(summary, conclusion, messages, t0, t1, qualityReview);
|
|
2642
2689
|
}
|
|
2643
|
-
var \u0398 =
|
|
2690
|
+
var \u0398 = createPatternTag(defaults15, execute15);
|
|
2644
2691
|
|
|
2645
2692
|
// src/pi.ts
|
|
2646
2693
|
import {
|
|
2647
|
-
getEnvApiKey as getEnvApiKey2,
|
|
2648
|
-
getModels as getModels2,
|
|
2649
|
-
getProviders as getProviders2,
|
|
2650
2694
|
streamSimple
|
|
2651
2695
|
} from "@earendil-works/pi-ai";
|
|
2652
2696
|
|
|
@@ -2664,10 +2708,28 @@ var PiOutput = class {
|
|
|
2664
2708
|
events;
|
|
2665
2709
|
startTime;
|
|
2666
2710
|
endTime;
|
|
2711
|
+
/** Trace entry for this single LLM call. Populated by the π tag. */
|
|
2712
|
+
trace = [];
|
|
2667
2713
|
/** Duration in milliseconds */
|
|
2668
2714
|
get duration() {
|
|
2669
2715
|
return this.endTime - this.startTime;
|
|
2670
2716
|
}
|
|
2717
|
+
/** Total input tokens (convenience accessor) */
|
|
2718
|
+
get inputTokens() {
|
|
2719
|
+
return this.trace[0]?.inputTokens ?? 0;
|
|
2720
|
+
}
|
|
2721
|
+
/** Total output tokens (convenience accessor) */
|
|
2722
|
+
get outputTokens() {
|
|
2723
|
+
return this.trace[0]?.outputTokens ?? 0;
|
|
2724
|
+
}
|
|
2725
|
+
/** Total tokens (convenience accessor) */
|
|
2726
|
+
get totalTokens() {
|
|
2727
|
+
return this.trace[0]?.totalTokens ?? 0;
|
|
2728
|
+
}
|
|
2729
|
+
/** Total cost in USD (convenience accessor) */
|
|
2730
|
+
get totalCost() {
|
|
2731
|
+
return this.trace[0]?.cost ?? 0;
|
|
2732
|
+
}
|
|
2671
2733
|
toString() {
|
|
2672
2734
|
return this.text;
|
|
2673
2735
|
}
|
|
@@ -2693,90 +2755,16 @@ var defaults16 = {
|
|
|
2693
2755
|
quiet: false,
|
|
2694
2756
|
maxTokens: 4096
|
|
2695
2757
|
};
|
|
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
2758
|
function makeContext(pieces, args, opts) {
|
|
2759
|
+
const systemParts = [];
|
|
2760
|
+
if (opts.system) systemParts.push(opts.system);
|
|
2761
|
+
if (opts.appendSystemPrompt) systemParts.push(opts.appendSystemPrompt);
|
|
2774
2762
|
return {
|
|
2775
|
-
systemPrompt:
|
|
2763
|
+
systemPrompt: systemParts.length > 0 ? systemParts.join("\n\n") : void 0,
|
|
2776
2764
|
messages: [
|
|
2777
2765
|
{
|
|
2778
2766
|
role: "user",
|
|
2779
|
-
content:
|
|
2767
|
+
content: build(pieces, args),
|
|
2780
2768
|
timestamp: Date.now()
|
|
2781
2769
|
}
|
|
2782
2770
|
]
|
|
@@ -2785,25 +2773,52 @@ function makeContext(pieces, args, opts) {
|
|
|
2785
2773
|
function makeOpts(opts) {
|
|
2786
2774
|
return {
|
|
2787
2775
|
maxTokens: opts.maxTokens,
|
|
2788
|
-
reasoning: opts.thinkingLevel
|
|
2776
|
+
reasoning: opts.thinkingLevel,
|
|
2777
|
+
thinkingBudgets: opts.thinkingBudgets,
|
|
2778
|
+
timeoutMs: opts.timeoutMs,
|
|
2779
|
+
maxRetries: opts.maxRetries
|
|
2789
2780
|
};
|
|
2790
2781
|
}
|
|
2791
2782
|
async function run(pieces, args, opts) {
|
|
2792
|
-
const model =
|
|
2783
|
+
const model = pickModel(opts.model);
|
|
2793
2784
|
if (!model) throw new Error("pizx/\u03C0: No AI models configured. Run `pi auth login` first.");
|
|
2794
2785
|
const t0 = Date.now();
|
|
2795
2786
|
let text = "";
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
if (
|
|
2787
|
+
let traceEntry;
|
|
2788
|
+
try {
|
|
2789
|
+
for await (const ev of streamSimple(model, makeContext(pieces, args, opts), makeOpts(opts))) {
|
|
2790
|
+
if (ev.type === "text_delta") {
|
|
2791
|
+
text += ev.delta;
|
|
2792
|
+
if (!opts.quiet) process.stdout.write(ev.delta);
|
|
2793
|
+
} else if (ev.type === "done") {
|
|
2794
|
+
const msg = ev.message;
|
|
2795
|
+
if (msg?.usage) {
|
|
2796
|
+
traceEntry = {
|
|
2797
|
+
call: 1,
|
|
2798
|
+
modelId: model.id,
|
|
2799
|
+
promptPreview: build(pieces, args).slice(0, 200),
|
|
2800
|
+
outputPreview: text.slice(0, 200),
|
|
2801
|
+
inputTokens: msg.usage.input,
|
|
2802
|
+
outputTokens: msg.usage.output,
|
|
2803
|
+
cacheReadTokens: msg.usage.cacheRead,
|
|
2804
|
+
cacheWriteTokens: msg.usage.cacheWrite,
|
|
2805
|
+
totalTokens: msg.usage.totalTokens,
|
|
2806
|
+
cost: msg.usage.cost.total,
|
|
2807
|
+
durationMs: Date.now() - t0
|
|
2808
|
+
};
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2800
2811
|
}
|
|
2812
|
+
} catch (err) {
|
|
2813
|
+
throw new Error(`pizx/\u03C0: AI generation failed: ${getErrorMessage(err)}`);
|
|
2801
2814
|
}
|
|
2802
2815
|
if (!opts.quiet && text) process.stdout.write("\n");
|
|
2803
|
-
|
|
2816
|
+
const output = new PiOutput(text.trim(), model.id, [], t0, Date.now());
|
|
2817
|
+
if (traceEntry) output.trace = [traceEntry];
|
|
2818
|
+
return output;
|
|
2804
2819
|
}
|
|
2805
2820
|
async function* runStream(pieces, args, opts) {
|
|
2806
|
-
const model =
|
|
2821
|
+
const model = pickModel(opts.model);
|
|
2807
2822
|
if (!model) throw new Error("pizx/\u03C0: No AI models configured");
|
|
2808
2823
|
for await (const ev of streamSimple(model, makeContext(pieces, args, opts), makeOpts(opts))) {
|
|
2809
2824
|
if (ev.type === "text_delta") yield ev.delta;
|
|
@@ -2846,7 +2861,10 @@ function makePi(opts = {}) {
|
|
|
2846
2861
|
var \u03C0 = makePi();
|
|
2847
2862
|
|
|
2848
2863
|
// src/pi-agent.ts
|
|
2849
|
-
import {
|
|
2864
|
+
import {
|
|
2865
|
+
createAgentSession as createAgentSession2,
|
|
2866
|
+
DefaultResourceLoader
|
|
2867
|
+
} from "@earendil-works/pi-coding-agent";
|
|
2850
2868
|
var _agentDefaults = {
|
|
2851
2869
|
quiet: false,
|
|
2852
2870
|
maxTurns: 10
|
|
@@ -2878,24 +2896,49 @@ var AgentOutput = class {
|
|
|
2878
2896
|
var AgentPromise = class extends Promise {
|
|
2879
2897
|
};
|
|
2880
2898
|
var _sharedSession = null;
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
const
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2899
|
+
function createLoader(opts) {
|
|
2900
|
+
const hasSystem = opts.system !== void 0;
|
|
2901
|
+
const hasAppend = opts.appendSystemPrompt !== void 0;
|
|
2902
|
+
const hasSkills = opts.skills && opts.skills.length > 0;
|
|
2903
|
+
if (!hasSystem && !hasAppend && !hasSkills) return void 0;
|
|
2904
|
+
return new DefaultResourceLoader({
|
|
2905
|
+
cwd: opts.cwd ?? process.cwd(),
|
|
2906
|
+
agentDir: "",
|
|
2907
|
+
systemPrompt: opts.system,
|
|
2908
|
+
appendSystemPrompt: opts.appendSystemPrompt ? [opts.appendSystemPrompt] : void 0
|
|
2888
2909
|
});
|
|
2889
|
-
_sharedSession = result.session;
|
|
2890
|
-
return _sharedSession;
|
|
2891
2910
|
}
|
|
2892
|
-
function
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
if (
|
|
2911
|
+
async function getSession(opts) {
|
|
2912
|
+
if (_sharedSession && !opts.model) return _sharedSession;
|
|
2913
|
+
try {
|
|
2914
|
+
const loader = createLoader(opts);
|
|
2915
|
+
if (opts.skills && opts.skills.length > 0 && loader) {
|
|
2916
|
+
const skillMap = await loadSkillContents(opts.skills);
|
|
2917
|
+
const skillPaths = [];
|
|
2918
|
+
for (const [name] of skillMap) {
|
|
2919
|
+
for (const base of SKILL_PATHS) {
|
|
2920
|
+
skillPaths.push({
|
|
2921
|
+
path: `${base}/${name}`,
|
|
2922
|
+
metadata: { source: "pizx", scope: "project", origin: "top-level" }
|
|
2923
|
+
});
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
if (skillPaths.length > 0) {
|
|
2927
|
+
loader.extendResources({ skillPaths });
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
const result = await createAgentSession2({
|
|
2931
|
+
cwd: opts.cwd,
|
|
2932
|
+
thinkingLevel: opts.thinkingLevel,
|
|
2933
|
+
tools: opts.tools,
|
|
2934
|
+
excludeTools: opts.excludeTools,
|
|
2935
|
+
resourceLoader: loader
|
|
2936
|
+
});
|
|
2937
|
+
_sharedSession = result.session;
|
|
2938
|
+
return _sharedSession;
|
|
2939
|
+
} catch (err) {
|
|
2940
|
+
throw new Error(`pizx/\u03A0: Failed to create agent session: ${getErrorMessage(err)}`);
|
|
2897
2941
|
}
|
|
2898
|
-
return s.trim();
|
|
2899
2942
|
}
|
|
2900
2943
|
function getMessageText(msg) {
|
|
2901
2944
|
const content = msg.content;
|
|
@@ -2917,7 +2960,7 @@ function getLastAssistantText(session) {
|
|
|
2917
2960
|
return "";
|
|
2918
2961
|
}
|
|
2919
2962
|
async function execute16(pieces, args, opts) {
|
|
2920
|
-
const prompt =
|
|
2963
|
+
const prompt = build(pieces, args);
|
|
2921
2964
|
const session = await getSession(opts);
|
|
2922
2965
|
const t0 = Date.now();
|
|
2923
2966
|
if (!opts.quiet) {
|
|
@@ -2928,15 +2971,12 @@ async function execute16(pieces, args, opts) {
|
|
|
2928
2971
|
await session.sendUserMessage(prompt);
|
|
2929
2972
|
const t1 = Date.now();
|
|
2930
2973
|
const text = getLastAssistantText(session);
|
|
2931
|
-
const turnCount = session.messages.filter(
|
|
2932
|
-
(m) => m.role === "assistant"
|
|
2933
|
-
).length;
|
|
2974
|
+
const turnCount = session.messages.filter((m) => m.role === "assistant").length;
|
|
2934
2975
|
return new AgentOutput(text || "(no assistant response)", turnCount, t0, t1);
|
|
2935
2976
|
} catch (err) {
|
|
2936
2977
|
const t1 = Date.now();
|
|
2937
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
2938
2978
|
console.error("\u03A0 error:", err);
|
|
2939
|
-
return new AgentOutput(`\u03A0 error: ${
|
|
2979
|
+
return new AgentOutput(`\u03A0 error: ${getErrorMessage(err)}`, 0, t0, t1);
|
|
2940
2980
|
}
|
|
2941
2981
|
}
|
|
2942
2982
|
function makeAgent(opts = {}) {
|
|
@@ -2998,7 +3038,7 @@ function parseArgs(argv) {
|
|
|
2998
3038
|
if (argv[i + 1] && !argv[i + 1].startsWith("-")) flags.model = argv[++i];
|
|
2999
3039
|
break;
|
|
3000
3040
|
case "--system":
|
|
3001
|
-
if (argv[i + 1]) flags.system = argv[++i];
|
|
3041
|
+
if (argv[i + 1] && !argv[i + 1].startsWith("-")) flags.system = argv[++i];
|
|
3002
3042
|
break;
|
|
3003
3043
|
case "-q":
|
|
3004
3044
|
case "--quiet":
|
|
@@ -3039,6 +3079,7 @@ function printHelp() {
|
|
|
3039
3079
|
\`\u039B\` Pipeline \u2014 sequential agent chain
|
|
3040
3080
|
\`\u03A8\` Critique \u2014 generate, critique, improve
|
|
3041
3081
|
\`\u03A9\` Orchestrator \u2014 plan, dispatch, synthesize
|
|
3082
|
+
\`\u039D\` Nu \u2014 Self-Organizing Teams
|
|
3042
3083
|
|
|
3043
3084
|
${chalk.bold("Communication Patterns")}
|
|
3044
3085
|
\`\u0398\` Thread \u2014 multi-agent conversation
|
|
@@ -3048,6 +3089,8 @@ function printHelp() {
|
|
|
3048
3089
|
${chalk.bold("Orchestration Topologies")}
|
|
3049
3090
|
\`\u0391\` Adaptive \u2014 self-adjusting orchestration
|
|
3050
3091
|
\`\u0393\` Graph \u2014 DAG-based task execution
|
|
3092
|
+
\`\u03A7\` Chi \u2014 Cross-Agent Learning
|
|
3093
|
+
\`\u03A4\` Tau \u2014 Tool-Mediated Orchestration
|
|
3051
3094
|
|
|
3052
3095
|
${chalk.bold("Example Script")}
|
|
3053
3096
|
#!/usr/bin/env pizx
|
|
@@ -3078,7 +3121,7 @@ async function runPrintMode(flags, args) {
|
|
|
3078
3121
|
`);
|
|
3079
3122
|
}
|
|
3080
3123
|
} catch (err) {
|
|
3081
|
-
console.error("pizx: pi-ai error:", err
|
|
3124
|
+
console.error("pizx: pi-ai error:", getErrorMessage(err));
|
|
3082
3125
|
process2.exit(1);
|
|
3083
3126
|
}
|
|
3084
3127
|
}
|
|
@@ -3098,6 +3141,9 @@ async function runScriptMode(scriptPath) {
|
|
|
3098
3141
|
g.\u03A9 = \u03A9;
|
|
3099
3142
|
g.\u0398 = \u0398;
|
|
3100
3143
|
g.\u039C = \u039C;
|
|
3144
|
+
g.\u039D = \u039D;
|
|
3145
|
+
g.\u03A4 = \u03A4;
|
|
3146
|
+
g.\u03A7 = \u03A7;
|
|
3101
3147
|
g.\u0392 = \u0392;
|
|
3102
3148
|
g.\u0391 = \u0391;
|
|
3103
3149
|
g.\u0393 = \u0393;
|
|
@@ -3109,11 +3155,7 @@ async function runScriptMode(scriptPath) {
|
|
|
3109
3155
|
try {
|
|
3110
3156
|
await import(url.pathToFileURL(absPath).toString());
|
|
3111
3157
|
} catch (err) {
|
|
3112
|
-
|
|
3113
|
-
console.error("pizx:", err.message);
|
|
3114
|
-
} else {
|
|
3115
|
-
console.error("pizx:", err);
|
|
3116
|
-
}
|
|
3158
|
+
console.error("pizx:", getErrorMessage(err));
|
|
3117
3159
|
process2.exit(1);
|
|
3118
3160
|
}
|
|
3119
3161
|
}
|
|
@@ -3140,7 +3182,7 @@ async function main() {
|
|
|
3140
3182
|
await runScriptMode(script);
|
|
3141
3183
|
}
|
|
3142
3184
|
main().catch((err) => {
|
|
3143
|
-
console.error("pizx:", err
|
|
3185
|
+
console.error("pizx:", getErrorMessage(err));
|
|
3144
3186
|
process2.exit(1);
|
|
3145
3187
|
});
|
|
3146
3188
|
//# sourceMappingURL=cli.js.map
|