@hham21/circe 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.
Files changed (83) hide show
  1. package/README.md +185 -0
  2. package/dist/agent.d.ts +73 -0
  3. package/dist/agent.js +334 -0
  4. package/dist/agent.js.map +1 -0
  5. package/dist/cli/agents-cmd.d.ts +2 -0
  6. package/dist/cli/agents-cmd.js +77 -0
  7. package/dist/cli/agents-cmd.js.map +1 -0
  8. package/dist/cli/index.d.ts +4 -0
  9. package/dist/cli/index.js +29 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/output.d.ts +20 -0
  12. package/dist/cli/output.js +136 -0
  13. package/dist/cli/output.js.map +1 -0
  14. package/dist/cli/run.d.ts +10 -0
  15. package/dist/cli/run.js +90 -0
  16. package/dist/cli/run.js.map +1 -0
  17. package/dist/cli/skills-cmd.d.ts +2 -0
  18. package/dist/cli/skills-cmd.js +95 -0
  19. package/dist/cli/skills-cmd.js.map +1 -0
  20. package/dist/cli/workflows-cmd.d.ts +2 -0
  21. package/dist/cli/workflows-cmd.js +61 -0
  22. package/dist/cli/workflows-cmd.js.map +1 -0
  23. package/dist/context.d.ts +8 -0
  24. package/dist/context.js +23 -0
  25. package/dist/context.js.map +1 -0
  26. package/dist/events.d.ts +134 -0
  27. package/dist/events.js +127 -0
  28. package/dist/events.js.map +1 -0
  29. package/dist/handoff.d.ts +153 -0
  30. package/dist/handoff.js +42 -0
  31. package/dist/handoff.js.map +1 -0
  32. package/dist/index.d.ts +9 -0
  33. package/dist/index.js +10 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/orchestration/contract.d.ts +27 -0
  36. package/dist/orchestration/contract.js +104 -0
  37. package/dist/orchestration/contract.js.map +1 -0
  38. package/dist/orchestration/index.d.ts +10 -0
  39. package/dist/orchestration/index.js +6 -0
  40. package/dist/orchestration/index.js.map +1 -0
  41. package/dist/orchestration/loop.d.ts +25 -0
  42. package/dist/orchestration/loop.js +81 -0
  43. package/dist/orchestration/loop.js.map +1 -0
  44. package/dist/orchestration/parallel.d.ts +27 -0
  45. package/dist/orchestration/parallel.js +78 -0
  46. package/dist/orchestration/parallel.js.map +1 -0
  47. package/dist/orchestration/pipeline.d.ts +23 -0
  48. package/dist/orchestration/pipeline.js +100 -0
  49. package/dist/orchestration/pipeline.js.map +1 -0
  50. package/dist/orchestration/sprint.d.ts +21 -0
  51. package/dist/orchestration/sprint.js +56 -0
  52. package/dist/orchestration/sprint.js.map +1 -0
  53. package/dist/presets/frontend.d.ts +8 -0
  54. package/dist/presets/frontend.js +113 -0
  55. package/dist/presets/frontend.js.map +1 -0
  56. package/dist/presets/fullstack.d.ts +9 -0
  57. package/dist/presets/fullstack.js +118 -0
  58. package/dist/presets/fullstack.js.map +1 -0
  59. package/dist/presets/index.d.ts +2 -0
  60. package/dist/presets/index.js +3 -0
  61. package/dist/presets/index.js.map +1 -0
  62. package/dist/session/index.d.ts +1 -0
  63. package/dist/session/index.js +2 -0
  64. package/dist/session/index.js.map +1 -0
  65. package/dist/session/manager.d.ts +17 -0
  66. package/dist/session/manager.js +50 -0
  67. package/dist/session/manager.js.map +1 -0
  68. package/dist/tools/custom.d.ts +5 -0
  69. package/dist/tools/custom.js +7 -0
  70. package/dist/tools/custom.js.map +1 -0
  71. package/dist/tools/index.d.ts +1 -0
  72. package/dist/tools/index.js +2 -0
  73. package/dist/tools/index.js.map +1 -0
  74. package/dist/tools/skills.d.ts +18 -0
  75. package/dist/tools/skills.js +99 -0
  76. package/dist/tools/skills.js.map +1 -0
  77. package/dist/types.d.ts +36 -0
  78. package/dist/types.js +12 -0
  79. package/dist/types.js.map +1 -0
  80. package/dist/utils.d.ts +24 -0
  81. package/dist/utils.js +85 -0
  82. package/dist/utils.js.map +1 -0
  83. package/package.json +49 -0
@@ -0,0 +1,25 @@
1
+ import type { Runnable } from "../types.js";
2
+ import type { EventBus, RetryPolicy } from "../events.js";
3
+ export interface LoopOptions<TEval = unknown> {
4
+ maxRounds?: number;
5
+ stopWhen?: (result: TEval) => boolean;
6
+ retryPolicy?: RetryPolicy;
7
+ eventBus?: EventBus;
8
+ }
9
+ export declare class Loop<TIn = unknown, TProducer = unknown, TEval = unknown> implements Runnable<TIn, TProducer> {
10
+ name?: string;
11
+ private agents;
12
+ private maxRounds;
13
+ private stopWhen;
14
+ private retryPolicy;
15
+ private eventBus;
16
+ private _lastMetrics;
17
+ private _lastProducerResult;
18
+ private _lastEvaluatorResult;
19
+ constructor(...args: [...Runnable<any, any>[], LoopOptions<TEval>] | Runnable<any, any>[]);
20
+ get lastMetrics(): import("../types.js").MetricsSnapshot | null;
21
+ get lastEvaluatorResult(): TEval | null;
22
+ run(input: TIn): Promise<TProducer>;
23
+ private executeRound;
24
+ private runAgent;
25
+ }
@@ -0,0 +1,81 @@
1
+ import { runWithOptionalRetry, errorMessage } from "../events.js";
2
+ import { parseTrailingOptions, createMetrics, accumulateMetrics } from "../utils.js";
3
+ const DEFAULT_MAX_ROUNDS = 3;
4
+ export class Loop {
5
+ name;
6
+ agents;
7
+ maxRounds;
8
+ stopWhen;
9
+ retryPolicy;
10
+ eventBus;
11
+ _lastMetrics = null;
12
+ _lastProducerResult = null;
13
+ _lastEvaluatorResult = null;
14
+ constructor(...args) {
15
+ const { agents, options } = parseTrailingOptions(args);
16
+ if (agents.length < 2) {
17
+ throw new Error("Loop requires at least two agents");
18
+ }
19
+ this.agents = agents;
20
+ this.maxRounds = options.maxRounds ?? DEFAULT_MAX_ROUNDS;
21
+ this.stopWhen = options.stopWhen ?? null;
22
+ this.retryPolicy = options.retryPolicy ?? null;
23
+ this.eventBus = options.eventBus ?? null;
24
+ }
25
+ get lastMetrics() { return this._lastMetrics; }
26
+ get lastEvaluatorResult() { return this._lastEvaluatorResult; }
27
+ async run(input) {
28
+ this._lastMetrics = null;
29
+ this._lastProducerResult = null;
30
+ this._lastEvaluatorResult = null;
31
+ const accumulated = createMetrics();
32
+ let result = input;
33
+ try {
34
+ for (let round = 0; round < this.maxRounds; round++) {
35
+ this.eventBus?.emit({ type: "round:start", round, timestamp: Date.now() });
36
+ result = await this.executeRound(round, result, accumulated);
37
+ if (this.stopWhen?.(result)) {
38
+ this._lastMetrics = { ...accumulated };
39
+ return this._lastProducerResult;
40
+ }
41
+ }
42
+ this._lastMetrics = { ...accumulated };
43
+ return result;
44
+ }
45
+ finally {
46
+ if (!this._lastMetrics) {
47
+ this._lastMetrics = { ...accumulated };
48
+ }
49
+ }
50
+ }
51
+ async executeRound(round, input, accumulated) {
52
+ try {
53
+ let result = input;
54
+ let roundCost = 0;
55
+ for (let i = 0; i < this.agents.length; i++) {
56
+ const agent = this.agents[i];
57
+ result = await this.runAgent(agent, result);
58
+ const m = agent.lastMetrics;
59
+ accumulateMetrics(accumulated, m);
60
+ if (m)
61
+ roundCost += m.cost;
62
+ if (i === 0) {
63
+ this._lastProducerResult = result;
64
+ }
65
+ if (i === this.agents.length - 1) {
66
+ this._lastEvaluatorResult = result;
67
+ }
68
+ }
69
+ this.eventBus?.emit({ type: "round:done", round, result, cost: roundCost || undefined, timestamp: Date.now() });
70
+ return result;
71
+ }
72
+ catch (err) {
73
+ this.eventBus?.emit({ type: "round:error", round, error: errorMessage(err), timestamp: Date.now() });
74
+ throw new Error(`[Loop:round-${round + 1}] ${errorMessage(err)}`);
75
+ }
76
+ }
77
+ async runAgent(agent, input) {
78
+ return runWithOptionalRetry(agent, input, this.retryPolicy, this.eventBus);
79
+ }
80
+ }
81
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/orchestration/loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { Runnable } from "../types.js";
2
+ import type { EventBus, RetryPolicy } from "../events.js";
3
+ export interface ParallelOptions {
4
+ throwOnError?: boolean;
5
+ retryPolicy?: RetryPolicy;
6
+ eventBus?: EventBus;
7
+ }
8
+ export type ParallelResult<T = unknown> = Record<string, {
9
+ status: "fulfilled";
10
+ value: T;
11
+ } | {
12
+ status: "rejected";
13
+ error: string;
14
+ }>;
15
+ export declare class Parallel<TIn = unknown, TOut = unknown> implements Runnable<TIn, ParallelResult<TOut>> {
16
+ name?: string;
17
+ private agents;
18
+ private throwOnError;
19
+ private retryPolicy;
20
+ private eventBus;
21
+ private _lastMetrics;
22
+ constructor(...args: [...Runnable<TIn, TOut>[], ParallelOptions] | Runnable<TIn, TOut>[]);
23
+ get lastMetrics(): import("../types.js").MetricsSnapshot | null;
24
+ run(input: TIn): Promise<ParallelResult<TOut>>;
25
+ private runAgent;
26
+ private collectResults;
27
+ }
@@ -0,0 +1,78 @@
1
+ import { runWithOptionalRetry, errorMessage } from "../events.js";
2
+ import { parseTrailingOptions, createMetrics, accumulateMetrics } from "../utils.js";
3
+ export class Parallel {
4
+ name;
5
+ agents;
6
+ throwOnError;
7
+ retryPolicy;
8
+ eventBus;
9
+ _lastMetrics = null;
10
+ constructor(...args) {
11
+ const { agents, options } = parseTrailingOptions(args);
12
+ if (agents.length === 0) {
13
+ throw new Error("Parallel requires at least one agent");
14
+ }
15
+ this.agents = agents;
16
+ this.throwOnError = options.throwOnError ?? true;
17
+ this.retryPolicy = options.retryPolicy ?? null;
18
+ this.eventBus = options.eventBus ?? null;
19
+ }
20
+ get lastMetrics() { return this._lastMetrics; }
21
+ async run(input) {
22
+ this._lastMetrics = null;
23
+ const settledOutcomes = await Promise.allSettled(this.agents.map((agent, index) => this.runAgent(agent, input, index)));
24
+ const accumulated = createMetrics();
25
+ for (const a of this.agents)
26
+ accumulateMetrics(accumulated, a.lastMetrics);
27
+ this._lastMetrics = accumulated;
28
+ return this.collectResults(settledOutcomes);
29
+ }
30
+ async runAgent(agent, input, index) {
31
+ const name = agent.name ?? `agent-${index}`;
32
+ this.eventBus?.emit({ type: "branch:start", branch: name, timestamp: Date.now() });
33
+ try {
34
+ const result = await runWithOptionalRetry(agent, input, this.retryPolicy, this.eventBus);
35
+ const metrics = agent.lastMetrics;
36
+ this.eventBus?.emit({
37
+ type: "branch:done",
38
+ branch: name,
39
+ result,
40
+ cost: metrics?.cost,
41
+ timestamp: Date.now(),
42
+ });
43
+ return { name, result };
44
+ }
45
+ catch (err) {
46
+ this.eventBus?.emit({
47
+ type: "branch:error",
48
+ branch: name,
49
+ error: errorMessage(err),
50
+ timestamp: Date.now(),
51
+ });
52
+ throw err;
53
+ }
54
+ }
55
+ collectResults(settledOutcomes) {
56
+ const results = {};
57
+ let firstError = null;
58
+ for (const [i, outcome] of settledOutcomes.entries()) {
59
+ if (outcome.status === "fulfilled") {
60
+ const { name, result } = outcome.value;
61
+ results[name] = { status: "fulfilled", value: result };
62
+ }
63
+ else {
64
+ const name = this.agents[i].name ?? `agent-${i}`;
65
+ const errorMsg = outcome.reason?.message ?? String(outcome.reason);
66
+ results[name] = { status: "rejected", error: errorMsg };
67
+ if (!firstError) {
68
+ firstError = outcome.reason instanceof Error ? outcome.reason : new Error(errorMsg);
69
+ }
70
+ }
71
+ }
72
+ if (this.throwOnError && firstError) {
73
+ throw firstError;
74
+ }
75
+ return results;
76
+ }
77
+ }
78
+ //# sourceMappingURL=parallel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../src/orchestration/parallel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { Runnable } from "../types.js";
2
+ import type { EventBus, RetryPolicy, OrchestratorEvent } from "../events.js";
3
+ export interface PipelineOptions {
4
+ retryPolicy?: RetryPolicy;
5
+ eventBus?: EventBus;
6
+ }
7
+ export declare class Pipeline<TIn = unknown, TOut = unknown> implements Runnable<TIn, TOut> {
8
+ private agents;
9
+ private retryPolicy;
10
+ private eventBus;
11
+ private _lastMetrics;
12
+ constructor(...args: [...Runnable<any, any>[], PipelineOptions] | Runnable<any, any>[]);
13
+ get lastMetrics(): import("../types.js").MetricsSnapshot | null;
14
+ run(input: TIn): Promise<TOut>;
15
+ resume(history: OrchestratorEvent[], input: TIn): Promise<TOut>;
16
+ private runStep;
17
+ private findLastCompletedStep;
18
+ private emitPipelineDone;
19
+ }
20
+ export declare function pipe<A, B>(s1: Runnable<A, B>, options?: PipelineOptions): Pipeline<A, B>;
21
+ export declare function pipe<A, B, C>(s1: Runnable<A, B>, s2: Runnable<B, C>, options?: PipelineOptions): Pipeline<A, C>;
22
+ export declare function pipe<A, B, C, D>(s1: Runnable<A, B>, s2: Runnable<B, C>, s3: Runnable<C, D>, options?: PipelineOptions): Pipeline<A, D>;
23
+ export declare function pipe<A, B, C, D, E>(s1: Runnable<A, B>, s2: Runnable<B, C>, s3: Runnable<C, D>, s4: Runnable<D, E>, options?: PipelineOptions): Pipeline<A, E>;
@@ -0,0 +1,100 @@
1
+ import { runWithOptionalRetry, errorMessage } from "../events.js";
2
+ import { parseTrailingOptions, createMetrics, accumulateMetrics } from "../utils.js";
3
+ export class Pipeline {
4
+ agents;
5
+ retryPolicy;
6
+ eventBus;
7
+ _lastMetrics = null;
8
+ constructor(...args) {
9
+ const { agents, options } = parseTrailingOptions(args);
10
+ if (agents.length === 0) {
11
+ throw new Error("Pipeline requires at least one agent");
12
+ }
13
+ this.agents = agents;
14
+ this.retryPolicy = options.retryPolicy ?? null;
15
+ this.eventBus = options.eventBus ?? null;
16
+ }
17
+ get lastMetrics() { return this._lastMetrics; }
18
+ async run(input) {
19
+ this._lastMetrics = null;
20
+ const accumulated = createMetrics();
21
+ let result = input;
22
+ try {
23
+ for (let i = 0; i < this.agents.length; i++) {
24
+ result = await this.runStep(this.agents[i], i, result);
25
+ accumulateMetrics(accumulated, this.agents[i].lastMetrics);
26
+ }
27
+ this._lastMetrics = { ...accumulated };
28
+ this.emitPipelineDone();
29
+ return result;
30
+ }
31
+ finally {
32
+ if (!this._lastMetrics) {
33
+ this._lastMetrics = { ...accumulated };
34
+ }
35
+ }
36
+ }
37
+ resume(history, input) {
38
+ const { lastCompletedStep, lastOutput } = this.findLastCompletedStep(history, input);
39
+ if (lastCompletedStep < 0) {
40
+ return this.run(input);
41
+ }
42
+ const remainingAgents = this.agents.slice(lastCompletedStep + 1);
43
+ if (remainingAgents.length === 0) {
44
+ return Promise.resolve(lastOutput);
45
+ }
46
+ const resumePipeline = new Pipeline(...remainingAgents, {
47
+ retryPolicy: this.retryPolicy ?? undefined,
48
+ eventBus: this.eventBus ?? undefined,
49
+ });
50
+ return resumePipeline.run(lastOutput);
51
+ }
52
+ async runStep(agent, stepIndex, input) {
53
+ const agentName = agent.name ?? `step-${stepIndex}`;
54
+ this.eventBus?.emit({ type: "step:start", step: stepIndex, agent: agentName, timestamp: Date.now() });
55
+ try {
56
+ const output = await runWithOptionalRetry(agent, input, this.retryPolicy, this.eventBus);
57
+ const metrics = agent.lastMetrics;
58
+ this.eventBus?.emit({
59
+ type: "step:done",
60
+ step: stepIndex,
61
+ agent: agentName,
62
+ output,
63
+ cost: metrics?.cost,
64
+ tokens: metrics ? [metrics.inputTokens, metrics.outputTokens] : undefined,
65
+ timestamp: Date.now(),
66
+ });
67
+ return output;
68
+ }
69
+ catch (err) {
70
+ this.eventBus?.emit({
71
+ type: "step:error",
72
+ step: stepIndex,
73
+ agent: agentName,
74
+ error: errorMessage(err),
75
+ timestamp: Date.now(),
76
+ });
77
+ throw new Error(`[Pipeline:step-${stepIndex}/${agentName}] ${errorMessage(err)}`);
78
+ }
79
+ }
80
+ findLastCompletedStep(history, input) {
81
+ for (let i = history.length - 1; i >= 0; i--) {
82
+ const event = history[i];
83
+ if (event.type === "step:done") {
84
+ return { lastCompletedStep: event.step, lastOutput: event.output };
85
+ }
86
+ }
87
+ return { lastCompletedStep: -1, lastOutput: input };
88
+ }
89
+ emitPipelineDone() {
90
+ const summary = this.eventBus?.getCostSummary();
91
+ if (this.eventBus && summary) {
92
+ this.eventBus.emit({ type: "pipeline:done", totalCost: summary.total, timestamp: Date.now() });
93
+ }
94
+ }
95
+ }
96
+ export function pipe(...args) {
97
+ const { agents, options } = parseTrailingOptions(args);
98
+ return new Pipeline(...agents, options);
99
+ }
100
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/orchestration/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { Runnable } from "../types.js";
2
+ import type { EventBus, RetryPolicy } from "../events.js";
3
+ export interface SprintOptions {
4
+ retryPolicy?: RetryPolicy;
5
+ eventBus?: EventBus;
6
+ }
7
+ export declare class Sprint<TIn = unknown, TOut = unknown> implements Runnable<TIn, {
8
+ sprintResults: TOut[];
9
+ }> {
10
+ name?: string;
11
+ private runner;
12
+ private retryPolicy;
13
+ private eventBus;
14
+ private _lastMetrics;
15
+ constructor(runner: Runnable<any, TOut>, options?: SprintOptions);
16
+ get lastMetrics(): import("../types.js").MetricsSnapshot | null;
17
+ run(spec: TIn): Promise<{
18
+ sprintResults: TOut[];
19
+ }>;
20
+ private extractSprintDefinitions;
21
+ }
@@ -0,0 +1,56 @@
1
+ import { runWithOptionalRetry, errorMessage } from "../events.js";
2
+ import { createMetrics, accumulateMetrics } from "../utils.js";
3
+ export class Sprint {
4
+ name;
5
+ runner;
6
+ retryPolicy;
7
+ eventBus;
8
+ _lastMetrics = null;
9
+ constructor(runner, options) {
10
+ this.runner = runner;
11
+ this.retryPolicy = options?.retryPolicy ?? null;
12
+ this.eventBus = options?.eventBus ?? null;
13
+ }
14
+ get lastMetrics() { return this._lastMetrics; }
15
+ async run(spec) {
16
+ this._lastMetrics = null;
17
+ const accumulated = createMetrics();
18
+ const definitions = this.extractSprintDefinitions(spec);
19
+ const sprintResults = [];
20
+ try {
21
+ for (let index = 0; index < definitions.length; index++) {
22
+ const sprintDef = definitions[index];
23
+ this.eventBus?.emit({ type: "sprint:start", index, definition: sprintDef, timestamp: Date.now() });
24
+ try {
25
+ const result = await runWithOptionalRetry(this.runner, sprintDef, this.retryPolicy, this.eventBus);
26
+ sprintResults.push(result);
27
+ const m = this.runner.lastMetrics;
28
+ accumulateMetrics(accumulated, m);
29
+ this.eventBus?.emit({ type: "sprint:done", index, result, cost: m?.cost, timestamp: Date.now() });
30
+ }
31
+ catch (error) {
32
+ this.eventBus?.emit({
33
+ type: "sprint:error",
34
+ index,
35
+ error: errorMessage(error),
36
+ timestamp: Date.now(),
37
+ });
38
+ throw new Error(`[Sprint:item-${index}] ${errorMessage(error)}`);
39
+ }
40
+ }
41
+ this._lastMetrics = { ...accumulated };
42
+ return { sprintResults };
43
+ }
44
+ finally {
45
+ if (!this._lastMetrics) {
46
+ this._lastMetrics = { ...accumulated };
47
+ }
48
+ }
49
+ }
50
+ extractSprintDefinitions(spec) {
51
+ if (spec == null || typeof spec !== "object")
52
+ return [];
53
+ return spec.sprints ?? [];
54
+ }
55
+ }
56
+ //# sourceMappingURL=sprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sprint.js","sourceRoot":"","sources":["../../src/orchestration/sprint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { Loop } from "../orchestration/loop.js";
2
+ interface FrontendDesignOptions {
3
+ model?: string;
4
+ iterations?: number;
5
+ passThreshold?: number;
6
+ }
7
+ export declare function frontendDesign(options?: FrontendDesignOptions): Loop;
8
+ export {};
@@ -0,0 +1,113 @@
1
+ import { Agent } from "../agent.js";
2
+ import { QAReportSchema, hasQAPassed } from "../handoff.js";
3
+ import { Loop } from "../orchestration/loop.js";
4
+ import { PLAYWRIGHT_MCP_SERVER } from "../utils.js";
5
+ const DEFAULT_ITERATIONS = 10;
6
+ const DEFAULT_PASS_THRESHOLD = 9.5;
7
+ export function frontendDesign(options) {
8
+ const iterations = options?.iterations ?? DEFAULT_ITERATIONS;
9
+ const passThreshold = options?.passThreshold ?? DEFAULT_PASS_THRESHOLD;
10
+ const generator = createGenerator(passThreshold);
11
+ const evaluator = createEvaluator(passThreshold);
12
+ return new Loop(generator, evaluator, {
13
+ maxRounds: iterations,
14
+ stopWhen: hasQAPassed,
15
+ });
16
+ }
17
+ function createGenerator(passThreshold) {
18
+ return new Agent({
19
+ name: "generator",
20
+ prompt: `You are an elite frontend craftsperson. Build pure HTML/CSS/JS (no frameworks).
21
+
22
+ Rules:
23
+ - Create index.html in the working directory
24
+ - Commit each round to git
25
+ - If _scores.md exists, read it to track progress. If it doesn't exist, this is the first round — just build.
26
+ - If scores plateau, pivot your aesthetic approach entirely — try a completely different visual direction
27
+ - If scores drop, git checkout to restore the best version
28
+ - Do NOT start a web server. The evaluator handles that.
29
+ - Do NOT wait for scores or poll for files. Just build and finish.
30
+
31
+ Priority order:
32
+ 1. Fix any bugs tagged CRITICAL or BUG in _scores.md BEFORE adding new features
33
+ 2. Address specific feedback items from the evaluator
34
+ 3. Add new features or improvements
35
+
36
+ Strategic decisions:
37
+ - After each evaluation, decide: refine the current direction if scores are trending well, or pivot to an entirely different aesthetic if the approach is not working
38
+ - The best designs are museum quality — pursue a distinct mood and identity, not safe defaults
39
+
40
+ Images:
41
+ - Download real images using curl and save to an img/ directory in the working directory
42
+ - Use public domain sources: Wikimedia Commons, Met Museum Open Access, Rijksmuseum API
43
+ - Example: curl -sL -o img/painting.jpg "https://upload.wikimedia.org/wikipedia/commons/thumb/..."
44
+ - NEVER use external URLs in <img src> — always reference local files (e.g., src="img/painting.jpg")
45
+ - NEVER substitute real images with SVG shapes or gradient placeholders
46
+
47
+ Target: ALL criteria must score ${passThreshold}/10 or higher.`,
48
+ });
49
+ }
50
+ function createEvaluator(passThreshold) {
51
+ return new Agent({
52
+ name: "evaluator",
53
+ prompt: `You are a ruthless design critic with no memory of previous rounds. Load the design-critique skill via use_skill("design-critique") for detailed methodology, anti-patterns, and scoring guide.
54
+
55
+ First, kill any existing serve process and start fresh:
56
+ pkill -f "serve -l 8080" 2>/dev/null; sleep 1; npx serve -l 8080 . &
57
+ Then wait 3 seconds and evaluate the design at http://localhost:8080.
58
+
59
+ CRITICAL RULES:
60
+ - Do NOT read _scores.md. Ever. It is not for you.
61
+ - Do NOT reference, check, or verify "previous feedback" — you have none.
62
+ - You are seeing this site for the FIRST TIME. Evaluate absolute quality, not improvement.
63
+ - Do NOT read any file except index.html and CSS/JS files linked from it.
64
+
65
+ Determine the current round number by counting existing screenshot folders:
66
+ ROUND=$(( $(ls -d ./screenshots/round-* 2>/dev/null | wc -l) + 1 ))
67
+ mkdir -p ./screenshots/round-$ROUND
68
+
69
+ Use Playwright MCP to navigate the live page directly — click through it, scroll, interact with elements, test responsiveness at different viewports. Do not score from a static screenshot alone.
70
+
71
+ Score each criterion (1-10):
72
+ - design_quality (weight 0.35): Does the design feel like a coherent whole rather than a collection of parts? Strong work means colors, typography, layout, imagery combine to create a distinct mood and identity.
73
+ - originality (weight 0.35): Is there evidence of custom creative decisions, or is this template layouts, library defaults, and AI-generated patterns? Unmodified stock components or telltale AI slop (purple gradients over white cards) fail here.
74
+ - craft (weight 0.15): Typography hierarchy, spacing consistency, color harmony, contrast ratios. A competence check — most reasonable implementations do fine; failing means broken fundamentals.
75
+ - functionality (weight 0.15): Usability independent of aesthetics. Can users understand the interface, find primary actions, and complete tasks without guessing?
76
+
77
+ SCORING CALIBRATION:
78
+ - 9-10: Exceptional. A professional designer would be impressed. Distinct identity that could not be mistaken for another site.
79
+ - 7-8: Good. Competent and polished, but you've seen this layout before. Lacks a signature element.
80
+ - 5-6: Generic. Template-quality. AI slop patterns. Safe choices everywhere.
81
+ - 3-4: Poor. Broken fundamentals, clashing styles, or amateur execution.
82
+ A score of 9+ means you would genuinely bookmark this site. Do not give 9 just because it is "good enough."
83
+
84
+ Pass only if ALL criteria >= ${passThreshold}/10.
85
+ APPEND scores to ./_scores.md using Bash (do NOT overwrite — the generator tracks score trends across rounds):
86
+ cat >> ./_scores.md << EOF
87
+ ## Round $ROUND
88
+ | design_quality | originality | craft | functionality | passed |
89
+ |---|---|---|---|---|
90
+ | X | X | X | X | YES/NO |
91
+ EOF
92
+
93
+ When giving feedback:
94
+ - Tag critical bugs as "CRITICAL BUG:"
95
+ - Be specific: exact elements, colors, sizes, font weights
96
+ - Suggest concrete fixes, not vague directions
97
+
98
+ Output JSON:
99
+ {
100
+ "passed": true/false,
101
+ "scores": {"design_quality": N, "originality": N, "craft": N, "functionality": N},
102
+ "feedback": ["specific feedback 1", ...]
103
+ }`,
104
+ skills: ["design-critique"],
105
+ tools: ["Bash", "Glob"],
106
+ contextStrategy: "reset",
107
+ mcpServers: {
108
+ playwright: PLAYWRIGHT_MCP_SERVER,
109
+ },
110
+ outputSchema: QAReportSchema,
111
+ });
112
+ }
113
+ //# sourceMappingURL=frontend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontend.js","sourceRoot":"","sources":["../../src/presets/frontend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAC9B,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAQnC,MAAM,UAAU,cAAc,CAAC,OAA+B;IAC5D,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,kBAAkB,CAAC;IAC7D,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,IAAI,sBAAsB,CAAC;IAEvE,MAAM,SAAS,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;IAEjD,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE;QACpC,SAAS,EAAE,UAAU;QACrB,QAAQ,EAAE,WAAW;KACtB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,aAAqB;IAC5C,OAAO,IAAI,KAAK,CAAC;QACf,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;kCA2BsB,aAAa,gBAAgB;KAC5D,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,aAAqB;IAC5C,OAAO,IAAI,KAAK,CAAC;QACf,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BA+BmB,aAAa;;;;;;;;;;;;;;;;;;;EAmB1C;QACE,MAAM,EAAE,CAAC,iBAAiB,CAAC;QAC3B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,OAAO;QACxB,UAAU,EAAE;YACV,UAAU,EAAE,qBAAqB;SAClC;QACD,YAAY,EAAE,cAAc;KAC7B,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Pipeline } from "../orchestration/pipeline.js";
2
+ interface FullstackOptions {
3
+ model?: string;
4
+ maxRounds?: number;
5
+ evaluatorCriteria?: Record<string, number>;
6
+ passThreshold?: number;
7
+ }
8
+ export declare function fullstackApp(options?: FullstackOptions): Pipeline;
9
+ export {};