agent-bober 0.15.0 → 0.17.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/.claude-plugin/marketplace.json +20 -0
- package/.claude-plugin/plugin.json +2 -2
- package/CHANGELOG.md +30 -0
- package/README.md +127 -3
- package/agents/bober-architect.md +34 -0
- package/agents/bober-code-reviewer.md +2 -0
- package/agents/bober-curator.md +12 -0
- package/agents/bober-documenter.md +129 -0
- package/agents/bober-evaluator.md +46 -0
- package/agents/bober-generator.md +12 -0
- package/agents/bober-planner.md +8 -1
- package/dist/cli/commands/graph.js +3 -3
- package/dist/cli/commands/graph.js.map +1 -1
- package/dist/cli/commands/init.js +4 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/memory.d.ts +14 -0
- package/dist/cli/commands/memory.d.ts.map +1 -0
- package/dist/cli/commands/memory.js +132 -0
- package/dist/cli/commands/memory.js.map +1 -0
- package/dist/cli/index.js +6 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +14 -3
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +7 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/role-providers.d.ts +29 -0
- package/dist/config/role-providers.d.ts.map +1 -0
- package/dist/config/role-providers.js +115 -0
- package/dist/config/role-providers.js.map +1 -0
- package/dist/config/schema.d.ts +383 -14
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +42 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/contracts/eval-result.d.ts +112 -56
- package/dist/contracts/eval-result.d.ts.map +1 -1
- package/dist/contracts/eval-result.js +3 -0
- package/dist/contracts/eval-result.js.map +1 -1
- package/dist/contracts/sprint-contract.d.ts +30 -30
- package/dist/fleet/aggregator.d.ts +5 -0
- package/dist/fleet/aggregator.d.ts.map +1 -0
- package/dist/fleet/aggregator.js +39 -0
- package/dist/fleet/aggregator.js.map +1 -0
- package/dist/fleet/child-config.d.ts +12 -0
- package/dist/fleet/child-config.d.ts.map +1 -0
- package/dist/fleet/child-config.js +38 -0
- package/dist/fleet/child-config.js.map +1 -0
- package/dist/fleet/coordinator.d.ts +25 -0
- package/dist/fleet/coordinator.d.ts.map +1 -0
- package/dist/fleet/coordinator.js +40 -0
- package/dist/fleet/coordinator.js.map +1 -0
- package/dist/fleet/index.d.ts +40 -0
- package/dist/fleet/index.d.ts.map +1 -0
- package/dist/fleet/index.js +117 -0
- package/dist/fleet/index.js.map +1 -0
- package/dist/fleet/manifest.d.ts +51 -0
- package/dist/fleet/manifest.d.ts.map +1 -0
- package/dist/fleet/manifest.js +32 -0
- package/dist/fleet/manifest.js.map +1 -0
- package/dist/fleet/reporter.d.ts +32 -0
- package/dist/fleet/reporter.d.ts.map +1 -0
- package/dist/fleet/reporter.js +71 -0
- package/dist/fleet/reporter.js.map +1 -0
- package/dist/fleet/runner.d.ts +48 -0
- package/dist/fleet/runner.d.ts.map +1 -0
- package/dist/fleet/runner.js +104 -0
- package/dist/fleet/runner.js.map +1 -0
- package/dist/fleet/scaffolder.d.ts +12 -0
- package/dist/fleet/scaffolder.d.ts.map +1 -0
- package/dist/fleet/scaffolder.js +82 -0
- package/dist/fleet/scaffolder.js.map +1 -0
- package/dist/fleet/types.d.ts +21 -0
- package/dist/fleet/types.d.ts.map +1 -0
- package/dist/fleet/types.js +2 -0
- package/dist/fleet/types.js.map +1 -0
- package/dist/graph/cli.d.ts +6 -2
- package/dist/graph/cli.d.ts.map +1 -1
- package/dist/graph/cli.js +53 -12
- package/dist/graph/cli.js.map +1 -1
- package/dist/graph/pipeline-lifecycle.d.ts +9 -0
- package/dist/graph/pipeline-lifecycle.d.ts.map +1 -1
- package/dist/graph/pipeline-lifecycle.js +12 -0
- package/dist/graph/pipeline-lifecycle.js.map +1 -1
- package/dist/graph/preflight-injector.d.ts +14 -0
- package/dist/graph/preflight-injector.d.ts.map +1 -1
- package/dist/graph/preflight-injector.js +84 -4
- package/dist/graph/preflight-injector.js.map +1 -1
- package/dist/incident/types.d.ts +24 -24
- package/dist/mcp/tools/graph-schemas.d.ts +7 -7
- package/dist/mcp/tools/init.d.ts.map +1 -1
- package/dist/mcp/tools/init.js +2 -0
- package/dist/mcp/tools/init.js.map +1 -1
- package/dist/orchestrator/agent-loader.d.ts.map +1 -1
- package/dist/orchestrator/agent-loader.js +15 -1
- package/dist/orchestrator/agent-loader.js.map +1 -1
- package/dist/orchestrator/agentic-loop.d.ts +51 -0
- package/dist/orchestrator/agentic-loop.d.ts.map +1 -1
- package/dist/orchestrator/agentic-loop.js +123 -4
- package/dist/orchestrator/agentic-loop.js.map +1 -1
- package/dist/orchestrator/arch-lenses.d.ts +7 -0
- package/dist/orchestrator/arch-lenses.d.ts.map +1 -0
- package/dist/orchestrator/arch-lenses.js +22 -0
- package/dist/orchestrator/arch-lenses.js.map +1 -0
- package/dist/orchestrator/architect-agent.d.ts +16 -0
- package/dist/orchestrator/architect-agent.d.ts.map +1 -1
- package/dist/orchestrator/architect-agent.js +509 -1
- package/dist/orchestrator/architect-agent.js.map +1 -1
- package/dist/orchestrator/curator-agent.js +1 -1
- package/dist/orchestrator/curator-agent.js.map +1 -1
- package/dist/orchestrator/deploy/types.d.ts +2 -2
- package/dist/orchestrator/documenter-agent.d.ts +57 -0
- package/dist/orchestrator/documenter-agent.d.ts.map +1 -0
- package/dist/orchestrator/documenter-agent.js +195 -0
- package/dist/orchestrator/documenter-agent.js.map +1 -0
- package/dist/orchestrator/environment.d.ts +45 -0
- package/dist/orchestrator/environment.d.ts.map +1 -0
- package/dist/orchestrator/environment.js +151 -0
- package/dist/orchestrator/environment.js.map +1 -0
- package/dist/orchestrator/eval-lenses.d.ts +7 -0
- package/dist/orchestrator/eval-lenses.d.ts.map +1 -0
- package/dist/orchestrator/eval-lenses.js +19 -0
- package/dist/orchestrator/eval-lenses.js.map +1 -0
- package/dist/orchestrator/eval-persist.d.ts +25 -0
- package/dist/orchestrator/eval-persist.d.ts.map +1 -0
- package/dist/orchestrator/eval-persist.js +74 -0
- package/dist/orchestrator/eval-persist.js.map +1 -0
- package/dist/orchestrator/evaluator-agent.d.ts +23 -0
- package/dist/orchestrator/evaluator-agent.d.ts.map +1 -1
- package/dist/orchestrator/evaluator-agent.js +60 -3
- package/dist/orchestrator/evaluator-agent.js.map +1 -1
- package/dist/orchestrator/generator-agent.d.ts.map +1 -1
- package/dist/orchestrator/generator-agent.js +32 -0
- package/dist/orchestrator/generator-agent.js.map +1 -1
- package/dist/orchestrator/memory/distill.d.ts +60 -0
- package/dist/orchestrator/memory/distill.d.ts.map +1 -0
- package/dist/orchestrator/memory/distill.js +177 -0
- package/dist/orchestrator/memory/distill.js.map +1 -0
- package/dist/orchestrator/memory/eval-source.d.ts +20 -0
- package/dist/orchestrator/memory/eval-source.d.ts.map +1 -0
- package/dist/orchestrator/memory/eval-source.js +88 -0
- package/dist/orchestrator/memory/eval-source.js.map +1 -0
- package/dist/orchestrator/memory/retrieve.d.ts +45 -0
- package/dist/orchestrator/memory/retrieve.d.ts.map +1 -0
- package/dist/orchestrator/memory/retrieve.js +102 -0
- package/dist/orchestrator/memory/retrieve.js.map +1 -0
- package/dist/orchestrator/model-resolver.d.ts.map +1 -1
- package/dist/orchestrator/model-resolver.js +12 -0
- package/dist/orchestrator/model-resolver.js.map +1 -1
- package/dist/orchestrator/pipeline.d.ts +10 -0
- package/dist/orchestrator/pipeline.d.ts.map +1 -1
- package/dist/orchestrator/pipeline.js +111 -3
- package/dist/orchestrator/pipeline.js.map +1 -1
- package/dist/orchestrator/planner-agent.d.ts +22 -1
- package/dist/orchestrator/planner-agent.d.ts.map +1 -1
- package/dist/orchestrator/planner-agent.js +160 -4
- package/dist/orchestrator/planner-agent.js.map +1 -1
- package/dist/orchestrator/research-agent.js +2 -2
- package/dist/orchestrator/research-agent.js.map +1 -1
- package/dist/orchestrator/tools/handlers.d.ts +14 -0
- package/dist/orchestrator/tools/handlers.d.ts.map +1 -1
- package/dist/orchestrator/tools/handlers.js +29 -4
- package/dist/orchestrator/tools/handlers.js.map +1 -1
- package/dist/orchestrator/tools/schemas.js +5 -5
- package/dist/orchestrator/tools/schemas.js.map +1 -1
- package/dist/orchestrator/workflow/args-builder.d.ts +35 -0
- package/dist/orchestrator/workflow/args-builder.d.ts.map +1 -0
- package/dist/orchestrator/workflow/args-builder.js +142 -0
- package/dist/orchestrator/workflow/args-builder.js.map +1 -0
- package/dist/orchestrator/workflow/budget.d.ts +57 -0
- package/dist/orchestrator/workflow/budget.d.ts.map +1 -0
- package/dist/orchestrator/workflow/budget.js +80 -0
- package/dist/orchestrator/workflow/budget.js.map +1 -0
- package/dist/orchestrator/workflow/conformance.d.ts +27 -0
- package/dist/orchestrator/workflow/conformance.d.ts.map +1 -0
- package/dist/orchestrator/workflow/conformance.js +111 -0
- package/dist/orchestrator/workflow/conformance.js.map +1 -0
- package/dist/orchestrator/workflow/eligibility.d.ts +8 -0
- package/dist/orchestrator/workflow/eligibility.d.ts.map +1 -0
- package/dist/orchestrator/workflow/eligibility.js +10 -0
- package/dist/orchestrator/workflow/eligibility.js.map +1 -0
- package/dist/orchestrator/workflow/engine.d.ts +10 -0
- package/dist/orchestrator/workflow/engine.d.ts.map +1 -0
- package/dist/orchestrator/workflow/engine.js +2 -0
- package/dist/orchestrator/workflow/engine.js.map +1 -0
- package/dist/orchestrator/workflow/errors.d.ts +13 -0
- package/dist/orchestrator/workflow/errors.d.ts.map +1 -0
- package/dist/orchestrator/workflow/errors.js +26 -0
- package/dist/orchestrator/workflow/errors.js.map +1 -0
- package/dist/orchestrator/workflow/flusher.d.ts +19 -0
- package/dist/orchestrator/workflow/flusher.d.ts.map +1 -0
- package/dist/orchestrator/workflow/flusher.js +81 -0
- package/dist/orchestrator/workflow/flusher.js.map +1 -0
- package/dist/orchestrator/workflow/interpreter.d.ts +48 -0
- package/dist/orchestrator/workflow/interpreter.d.ts.map +1 -0
- package/dist/orchestrator/workflow/interpreter.js +92 -0
- package/dist/orchestrator/workflow/interpreter.js.map +1 -0
- package/dist/orchestrator/workflow/pure-sprint.d.ts +65 -0
- package/dist/orchestrator/workflow/pure-sprint.d.ts.map +1 -0
- package/dist/orchestrator/workflow/pure-sprint.js +82 -0
- package/dist/orchestrator/workflow/pure-sprint.js.map +1 -0
- package/dist/orchestrator/workflow/reconciler.d.ts +15 -0
- package/dist/orchestrator/workflow/reconciler.d.ts.map +1 -0
- package/dist/orchestrator/workflow/reconciler.js +65 -0
- package/dist/orchestrator/workflow/reconciler.js.map +1 -0
- package/dist/orchestrator/workflow/resume-cursor.d.ts +10 -0
- package/dist/orchestrator/workflow/resume-cursor.d.ts.map +1 -0
- package/dist/orchestrator/workflow/resume-cursor.js +25 -0
- package/dist/orchestrator/workflow/resume-cursor.js.map +1 -0
- package/dist/orchestrator/workflow/retry.d.ts +50 -0
- package/dist/orchestrator/workflow/retry.d.ts.map +1 -0
- package/dist/orchestrator/workflow/retry.js +100 -0
- package/dist/orchestrator/workflow/retry.js.map +1 -0
- package/dist/orchestrator/workflow/scheduler.d.ts +87 -0
- package/dist/orchestrator/workflow/scheduler.d.ts.map +1 -0
- package/dist/orchestrator/workflow/scheduler.js +158 -0
- package/dist/orchestrator/workflow/scheduler.js.map +1 -0
- package/dist/orchestrator/workflow/selector.d.ts +26 -0
- package/dist/orchestrator/workflow/selector.d.ts.map +1 -0
- package/dist/orchestrator/workflow/selector.js +54 -0
- package/dist/orchestrator/workflow/selector.js.map +1 -0
- package/dist/orchestrator/workflow/synthesizer.d.ts +52 -0
- package/dist/orchestrator/workflow/synthesizer.d.ts.map +1 -0
- package/dist/orchestrator/workflow/synthesizer.js +75 -0
- package/dist/orchestrator/workflow/synthesizer.js.map +1 -0
- package/dist/orchestrator/workflow/ts-engine.d.ts +13 -0
- package/dist/orchestrator/workflow/ts-engine.d.ts.map +1 -0
- package/dist/orchestrator/workflow/ts-engine.js +14 -0
- package/dist/orchestrator/workflow/ts-engine.js.map +1 -0
- package/dist/orchestrator/workflow/types.d.ts +55 -0
- package/dist/orchestrator/workflow/types.d.ts.map +1 -0
- package/dist/orchestrator/workflow/types.js +3 -0
- package/dist/orchestrator/workflow/types.js.map +1 -0
- package/dist/orchestrator/workflow/workflow-engine.d.ts +31 -0
- package/dist/orchestrator/workflow/workflow-engine.d.ts.map +1 -0
- package/dist/orchestrator/workflow/workflow-engine.js +70 -0
- package/dist/orchestrator/workflow/workflow-engine.js.map +1 -0
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +49 -6
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/claude-code.d.ts +44 -0
- package/dist/providers/claude-code.d.ts.map +1 -0
- package/dist/providers/claude-code.js +143 -0
- package/dist/providers/claude-code.js.map +1 -0
- package/dist/providers/factory.d.ts +16 -2
- package/dist/providers/factory.d.ts.map +1 -1
- package/dist/providers/factory.js +66 -12
- package/dist/providers/factory.js.map +1 -1
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +27 -3
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/index.d.ts +3 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +3 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +24 -3
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/preflight.d.ts +22 -0
- package/dist/providers/preflight.d.ts.map +1 -0
- package/dist/providers/preflight.js +54 -0
- package/dist/providers/preflight.js.map +1 -0
- package/dist/providers/structured.d.ts +130 -0
- package/dist/providers/structured.d.ts.map +1 -0
- package/dist/providers/structured.js +205 -0
- package/dist/providers/structured.js.map +1 -0
- package/dist/providers/types.d.ts +28 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/state/history-rotation.d.ts +17 -0
- package/dist/state/history-rotation.d.ts.map +1 -0
- package/dist/state/history-rotation.js +84 -0
- package/dist/state/history-rotation.js.map +1 -0
- package/dist/state/history.d.ts +16 -4
- package/dist/state/history.d.ts.map +1 -1
- package/dist/state/history.js +62 -20
- package/dist/state/history.js.map +1 -1
- package/dist/state/index.d.ts +1 -1
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +1 -1
- package/dist/state/index.js.map +1 -1
- package/dist/state/memory.d.ts +60 -0
- package/dist/state/memory.d.ts.map +1 -0
- package/dist/state/memory.js +242 -0
- package/dist/state/memory.js.map +1 -0
- package/hooks/hooks.json +12 -2
- package/package.json +9 -5
- package/scripts/spike-claude-code-provider.mjs +66 -0
- package/scripts/spike-deepseek.mjs +63 -0
- package/scripts/sync-targets.json +12 -0
- package/scripts/update-all.mjs +255 -0
- package/skills/bober.architect/SKILL.md +13 -0
- package/skills/bober.architect/references/arch-lens-panel.md +126 -0
- package/skills/bober.eval/SKILL.md +9 -0
- package/skills/bober.eval/references/lens-panel.md +115 -0
- package/skills/bober.plan/SKILL.md +6 -0
- package/skills/bober.run/SKILL.md +23 -4
- package/skills/bober.run/references/lens-panel.md +115 -0
- package/skills/bober.sprint/SKILL.md +44 -2
- package/skills/bober.sprint/references/lens-panel.md +115 -0
- package/skills/shared/arch-lens-panel.md +126 -0
- package/skills/shared/lens-panel.md +115 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exponential-backoff retry for transient provider failures.
|
|
3
|
+
*
|
|
4
|
+
* Today the agentic loop ends on the first `client.chat()` error
|
|
5
|
+
* (agentic-loop.ts), which is fragile when hammering a single local model
|
|
6
|
+
* server (Ollama/vLLM return 429/503 under load). `withRetry` wraps a call in
|
|
7
|
+
* bounded exponential backoff with jitter, retrying only TRANSIENT failures
|
|
8
|
+
* (rate limits, overload, timeouts, network resets) and surfacing everything
|
|
9
|
+
* else immediately.
|
|
10
|
+
*
|
|
11
|
+
* The scheduler / interpreter wraps each provider call in this, so every
|
|
12
|
+
* provider benefits without per-adapter changes. `sleep` and `jitter` are
|
|
13
|
+
* injectable so tests are deterministic and instant.
|
|
14
|
+
*/
|
|
15
|
+
// ── Transient classification ────────────────────────────────────────
|
|
16
|
+
function asRecord(err) {
|
|
17
|
+
return typeof err === "object" && err !== null
|
|
18
|
+
? err
|
|
19
|
+
: undefined;
|
|
20
|
+
}
|
|
21
|
+
function getStatus(err) {
|
|
22
|
+
const e = asRecord(err);
|
|
23
|
+
if (!e)
|
|
24
|
+
return undefined;
|
|
25
|
+
const s = e["status"] ?? e["statusCode"];
|
|
26
|
+
return typeof s === "number" ? s : undefined;
|
|
27
|
+
}
|
|
28
|
+
function getCode(err) {
|
|
29
|
+
const e = asRecord(err);
|
|
30
|
+
const c = e?.["code"];
|
|
31
|
+
return typeof c === "string" ? c : undefined;
|
|
32
|
+
}
|
|
33
|
+
function getMessage(err) {
|
|
34
|
+
if (err instanceof Error)
|
|
35
|
+
return err.message;
|
|
36
|
+
const e = asRecord(err);
|
|
37
|
+
const m = e?.["message"];
|
|
38
|
+
return typeof m === "string" ? m : String(err);
|
|
39
|
+
}
|
|
40
|
+
const TRANSIENT_CODES = new Set([
|
|
41
|
+
"ETIMEDOUT",
|
|
42
|
+
"ECONNRESET",
|
|
43
|
+
"ECONNREFUSED",
|
|
44
|
+
"ENOTFOUND",
|
|
45
|
+
"EAI_AGAIN",
|
|
46
|
+
"EPIPE",
|
|
47
|
+
"ECONNABORTED",
|
|
48
|
+
]);
|
|
49
|
+
const TRANSIENT_MESSAGE = /rate.?limit|too many requests|overloaded|overload|temporarily|try again|timed? ?out|service unavailable|ECONNRESET|ETIMEDOUT|\b(?:429|500|502|503|504|529)\b/i;
|
|
50
|
+
/**
|
|
51
|
+
* Heuristic: is this error worth retrying? True for HTTP 408/429 and 5xx,
|
|
52
|
+
* known transient network codes, and overload/rate-limit/timeout messages.
|
|
53
|
+
*/
|
|
54
|
+
export function classifyTransient(err) {
|
|
55
|
+
const status = getStatus(err);
|
|
56
|
+
if (status !== undefined) {
|
|
57
|
+
if (status === 408 || status === 429)
|
|
58
|
+
return true;
|
|
59
|
+
if (status >= 500 && status < 600)
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
const code = getCode(err);
|
|
63
|
+
if (code && TRANSIENT_CODES.has(code))
|
|
64
|
+
return true;
|
|
65
|
+
return TRANSIENT_MESSAGE.test(getMessage(err));
|
|
66
|
+
}
|
|
67
|
+
const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
68
|
+
/**
|
|
69
|
+
* Run `fn`, retrying TRANSIENT failures with exponential backoff + jitter.
|
|
70
|
+
* Non-transient errors and the final exhausted error are rethrown.
|
|
71
|
+
*
|
|
72
|
+
* Backoff for retry `n` (0-based): `min(maxDelayMs, baseDelayMs * factor**n)`,
|
|
73
|
+
* then jittered to 50–100% of that value (decorrelated, avoids thundering herd).
|
|
74
|
+
*/
|
|
75
|
+
export async function withRetry(fn, opts = {}) {
|
|
76
|
+
const maxRetries = opts.maxRetries ?? 3;
|
|
77
|
+
const baseDelayMs = opts.baseDelayMs ?? 500;
|
|
78
|
+
const maxDelayMs = opts.maxDelayMs ?? 30_000;
|
|
79
|
+
const factor = opts.factor ?? 2;
|
|
80
|
+
const jitter = opts.jitter ?? Math.random;
|
|
81
|
+
const sleep = opts.sleep ?? defaultSleep;
|
|
82
|
+
const isTransient = opts.isTransient ?? classifyTransient;
|
|
83
|
+
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
|
|
84
|
+
try {
|
|
85
|
+
return await fn();
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (attempt === maxRetries || !isTransient(error)) {
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
const raw = Math.min(maxDelayMs, baseDelayMs * Math.pow(factor, attempt));
|
|
92
|
+
const delayMs = raw * (0.5 + 0.5 * jitter());
|
|
93
|
+
opts.onRetry?.({ attempt: attempt + 1, delayMs, error });
|
|
94
|
+
await sleep(delayMs);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Unreachable: the loop either returns or throws on the final attempt.
|
|
98
|
+
throw new Error("withRetry: retry loop exited unexpectedly.");
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../../src/orchestrator/workflow/retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Concurrency scheduler for the local-model workflow runtime.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the execution model of Claude Code's dynamic-workflow runtime:
|
|
5
|
+
* - `parallel(thunks)` — barrier; runs all thunks with bounded concurrency
|
|
6
|
+
* and awaits them all (order-preserving). Use for lens panels / N skeptics.
|
|
7
|
+
* - `pipeline(items, ...stages)` — per-item, NO barrier between stages; each
|
|
8
|
+
* item flows through every stage independently, so item A can be in stage 3
|
|
9
|
+
* while item B is still in stage 1. Total concurrent stage executions are
|
|
10
|
+
* bounded by the same cap.
|
|
11
|
+
*
|
|
12
|
+
* Concurrency is enforced by a hand-off semaphore (true bounded concurrency,
|
|
13
|
+
* unlike chunk-batching which idles fast tasks waiting on a slow one). A live
|
|
14
|
+
* agent counter caps total executions over the scheduler's lifetime (the
|
|
15
|
+
* runaway guard — Claude Code uses 1000/run).
|
|
16
|
+
*/
|
|
17
|
+
/** Raised when a scheduler exceeds its lifetime agent-execution cap. */
|
|
18
|
+
export declare class AgentCapError extends Error {
|
|
19
|
+
/** The cap that was hit. */
|
|
20
|
+
readonly cap: number;
|
|
21
|
+
constructor(message: string,
|
|
22
|
+
/** The cap that was hit. */
|
|
23
|
+
cap: number);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The default concurrency cap: `min(16, cores - 2)`, floored at 1. Matches the
|
|
27
|
+
* Claude Code dynamic-workflow runtime. For local model servers the real bound
|
|
28
|
+
* is usually the server's slot count (e.g. Ollama's OLLAMA_NUM_PARALLEL), so
|
|
29
|
+
* callers should override `maxConcurrent` to match their backend.
|
|
30
|
+
*/
|
|
31
|
+
export declare function defaultConcurrency(): number;
|
|
32
|
+
/**
|
|
33
|
+
* A counting semaphore with FIFO hand-off: when a holder releases and a waiter
|
|
34
|
+
* is queued, the slot transfers directly to that waiter (the active count never
|
|
35
|
+
* dips), giving true peak-concurrency === cap regardless of task duration.
|
|
36
|
+
*/
|
|
37
|
+
export declare class Semaphore {
|
|
38
|
+
private readonly cap;
|
|
39
|
+
private active;
|
|
40
|
+
private readonly waiters;
|
|
41
|
+
constructor(cap: number);
|
|
42
|
+
acquire(): Promise<void>;
|
|
43
|
+
release(): void;
|
|
44
|
+
/** Number of currently-held slots (for tests / introspection). */
|
|
45
|
+
get inFlight(): number;
|
|
46
|
+
}
|
|
47
|
+
export interface SchedulerOptions {
|
|
48
|
+
/** Max concurrent task executions. Default {@link defaultConcurrency}. */
|
|
49
|
+
maxConcurrent?: number;
|
|
50
|
+
/** Hard ceiling on total executions over this scheduler's lifetime. Default 1000. */
|
|
51
|
+
maxAgents?: number;
|
|
52
|
+
}
|
|
53
|
+
/** A pipeline stage: receives the previous stage's output, the original item, and its index. */
|
|
54
|
+
export type Stage<I> = (prev: unknown, item: I, index: number) => Promise<unknown>;
|
|
55
|
+
export declare class Scheduler {
|
|
56
|
+
readonly maxConcurrent: number;
|
|
57
|
+
readonly maxAgents: number;
|
|
58
|
+
private readonly sem;
|
|
59
|
+
private agentsStarted;
|
|
60
|
+
constructor(opts?: SchedulerOptions);
|
|
61
|
+
/** Total task executions started over this scheduler's lifetime. */
|
|
62
|
+
get agentsRun(): number;
|
|
63
|
+
/** Acquire a slot, run, release — counting the execution against the cap. */
|
|
64
|
+
private run;
|
|
65
|
+
/**
|
|
66
|
+
* Run all thunks concurrently (bounded by the cap) and await them all.
|
|
67
|
+
* Results are index-aligned with `thunks`. A thunk that throws rejects the
|
|
68
|
+
* whole call (use try/catch inside the thunk for {@link Promise.allSettled}-style
|
|
69
|
+
* tolerance).
|
|
70
|
+
*/
|
|
71
|
+
parallel<T>(thunks: ReadonlyArray<() => Promise<T>>): Promise<T[]>;
|
|
72
|
+
/**
|
|
73
|
+
* Run each item through every stage independently — no barrier between
|
|
74
|
+
* stages. Returns an array index-aligned with `items`. A stage that throws
|
|
75
|
+
* (other than {@link AgentCapError}) drops that item to `null` and skips its
|
|
76
|
+
* remaining stages; the runaway-cap error propagates.
|
|
77
|
+
*/
|
|
78
|
+
pipeline<I>(items: ReadonlyArray<I>, ...stages: Array<Stage<I>>): Promise<unknown[]>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Map over `items` applying `fn` with at most `cap` concurrent calls, preserving
|
|
82
|
+
* input order. Backed by a hand-off {@link Semaphore} (true bounded concurrency,
|
|
83
|
+
* superseding the chunk-batching copies previously duplicated in the evaluator
|
|
84
|
+
* and architect agents).
|
|
85
|
+
*/
|
|
86
|
+
export declare function mapBounded<T, R>(items: ReadonlyArray<T>, cap: number, fn: (x: T) => Promise<R>): Promise<R[]>;
|
|
87
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/workflow/scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,wEAAwE;AACxE,qBAAa,aAAc,SAAQ,KAAK;IAGpC,4BAA4B;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM;gBAFpB,OAAO,EAAE,MAAM;IACf,4BAA4B;IACnB,GAAG,EAAE,MAAM;CAKvB;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAID;;;;GAIG;AACH,qBAAa,SAAS;IAIR,OAAO,CAAC,QAAQ,CAAC,GAAG;IAHhC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;gBAEpB,GAAG,EAAE,MAAM;IAIlC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B,OAAO,IAAI,IAAI;IASf,kEAAkE;IAClE,IAAI,QAAQ,IAAI,MAAM,CAErB;CACF;AAID,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,gGAAgG;AAChG,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEnF,qBAAa,SAAS;IACpB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,aAAa,CAAK;gBAEd,IAAI,GAAE,gBAAqB;IAMvC,oEAAoE;IACpE,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,6EAA6E;YAC/D,GAAG;IAgBjB;;;;;OAKG;IACG,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAIxE;;;;;OAKG;IACG,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAgB3F;AAID;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAAE,CAAC,EACnC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EACvB,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,EAAE,CAAC,CAYd"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Concurrency scheduler for the local-model workflow runtime.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the execution model of Claude Code's dynamic-workflow runtime:
|
|
5
|
+
* - `parallel(thunks)` — barrier; runs all thunks with bounded concurrency
|
|
6
|
+
* and awaits them all (order-preserving). Use for lens panels / N skeptics.
|
|
7
|
+
* - `pipeline(items, ...stages)` — per-item, NO barrier between stages; each
|
|
8
|
+
* item flows through every stage independently, so item A can be in stage 3
|
|
9
|
+
* while item B is still in stage 1. Total concurrent stage executions are
|
|
10
|
+
* bounded by the same cap.
|
|
11
|
+
*
|
|
12
|
+
* Concurrency is enforced by a hand-off semaphore (true bounded concurrency,
|
|
13
|
+
* unlike chunk-batching which idles fast tasks waiting on a slow one). A live
|
|
14
|
+
* agent counter caps total executions over the scheduler's lifetime (the
|
|
15
|
+
* runaway guard — Claude Code uses 1000/run).
|
|
16
|
+
*/
|
|
17
|
+
import * as os from "node:os";
|
|
18
|
+
// ── Errors ──────────────────────────────────────────────────────────
|
|
19
|
+
/** Raised when a scheduler exceeds its lifetime agent-execution cap. */
|
|
20
|
+
export class AgentCapError extends Error {
|
|
21
|
+
cap;
|
|
22
|
+
constructor(message,
|
|
23
|
+
/** The cap that was hit. */
|
|
24
|
+
cap) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.cap = cap;
|
|
27
|
+
this.name = "AgentCapError";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// ── Default concurrency ─────────────────────────────────────────────
|
|
31
|
+
/**
|
|
32
|
+
* The default concurrency cap: `min(16, cores - 2)`, floored at 1. Matches the
|
|
33
|
+
* Claude Code dynamic-workflow runtime. For local model servers the real bound
|
|
34
|
+
* is usually the server's slot count (e.g. Ollama's OLLAMA_NUM_PARALLEL), so
|
|
35
|
+
* callers should override `maxConcurrent` to match their backend.
|
|
36
|
+
*/
|
|
37
|
+
export function defaultConcurrency() {
|
|
38
|
+
const cores = os.cpus().length;
|
|
39
|
+
return Math.max(1, Math.min(16, cores - 2));
|
|
40
|
+
}
|
|
41
|
+
// ── Hand-off semaphore ──────────────────────────────────────────────
|
|
42
|
+
/**
|
|
43
|
+
* A counting semaphore with FIFO hand-off: when a holder releases and a waiter
|
|
44
|
+
* is queued, the slot transfers directly to that waiter (the active count never
|
|
45
|
+
* dips), giving true peak-concurrency === cap regardless of task duration.
|
|
46
|
+
*/
|
|
47
|
+
export class Semaphore {
|
|
48
|
+
cap;
|
|
49
|
+
active = 0;
|
|
50
|
+
waiters = [];
|
|
51
|
+
constructor(cap) {
|
|
52
|
+
this.cap = cap;
|
|
53
|
+
if (cap < 1)
|
|
54
|
+
throw new Error(`Semaphore cap must be >= 1 (got ${String(cap)}).`);
|
|
55
|
+
}
|
|
56
|
+
async acquire() {
|
|
57
|
+
if (this.active < this.cap) {
|
|
58
|
+
this.active += 1;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Full: queue and wait. release() hands us the slot (active stays at cap),
|
|
62
|
+
// so we do NOT increment when resumed.
|
|
63
|
+
await new Promise((resolve) => this.waiters.push(resolve));
|
|
64
|
+
}
|
|
65
|
+
release() {
|
|
66
|
+
const next = this.waiters.shift();
|
|
67
|
+
if (next) {
|
|
68
|
+
next(); // hand the slot over; active unchanged
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.active -= 1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Number of currently-held slots (for tests / introspection). */
|
|
75
|
+
get inFlight() {
|
|
76
|
+
return this.active;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export class Scheduler {
|
|
80
|
+
maxConcurrent;
|
|
81
|
+
maxAgents;
|
|
82
|
+
sem;
|
|
83
|
+
agentsStarted = 0;
|
|
84
|
+
constructor(opts = {}) {
|
|
85
|
+
this.maxConcurrent = opts.maxConcurrent ?? defaultConcurrency();
|
|
86
|
+
this.maxAgents = opts.maxAgents ?? 1000;
|
|
87
|
+
this.sem = new Semaphore(Math.max(1, this.maxConcurrent));
|
|
88
|
+
}
|
|
89
|
+
/** Total task executions started over this scheduler's lifetime. */
|
|
90
|
+
get agentsRun() {
|
|
91
|
+
return this.agentsStarted;
|
|
92
|
+
}
|
|
93
|
+
/** Acquire a slot, run, release — counting the execution against the cap. */
|
|
94
|
+
async run(thunk) {
|
|
95
|
+
if (this.agentsStarted >= this.maxAgents) {
|
|
96
|
+
throw new AgentCapError(`Scheduler agent cap exceeded (${String(this.maxAgents)} executions).`, this.maxAgents);
|
|
97
|
+
}
|
|
98
|
+
this.agentsStarted += 1;
|
|
99
|
+
await this.sem.acquire();
|
|
100
|
+
try {
|
|
101
|
+
return await thunk();
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
this.sem.release();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Run all thunks concurrently (bounded by the cap) and await them all.
|
|
109
|
+
* Results are index-aligned with `thunks`. A thunk that throws rejects the
|
|
110
|
+
* whole call (use try/catch inside the thunk for {@link Promise.allSettled}-style
|
|
111
|
+
* tolerance).
|
|
112
|
+
*/
|
|
113
|
+
async parallel(thunks) {
|
|
114
|
+
return Promise.all(thunks.map((t) => this.run(t)));
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Run each item through every stage independently — no barrier between
|
|
118
|
+
* stages. Returns an array index-aligned with `items`. A stage that throws
|
|
119
|
+
* (other than {@link AgentCapError}) drops that item to `null` and skips its
|
|
120
|
+
* remaining stages; the runaway-cap error propagates.
|
|
121
|
+
*/
|
|
122
|
+
async pipeline(items, ...stages) {
|
|
123
|
+
return Promise.all(items.map(async (item, index) => {
|
|
124
|
+
let acc = item;
|
|
125
|
+
for (const stage of stages) {
|
|
126
|
+
try {
|
|
127
|
+
acc = await this.run(() => stage(acc, item, index));
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
if (e instanceof AgentCapError)
|
|
131
|
+
throw e;
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return acc;
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// ── mapBounded (drop-in for the legacy panel helper) ────────────────
|
|
140
|
+
/**
|
|
141
|
+
* Map over `items` applying `fn` with at most `cap` concurrent calls, preserving
|
|
142
|
+
* input order. Backed by a hand-off {@link Semaphore} (true bounded concurrency,
|
|
143
|
+
* superseding the chunk-batching copies previously duplicated in the evaluator
|
|
144
|
+
* and architect agents).
|
|
145
|
+
*/
|
|
146
|
+
export async function mapBounded(items, cap, fn) {
|
|
147
|
+
const sem = new Semaphore(Math.max(1, cap));
|
|
148
|
+
return Promise.all(items.map(async (item) => {
|
|
149
|
+
await sem.acquire();
|
|
150
|
+
try {
|
|
151
|
+
return await fn(item);
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
sem.release();
|
|
155
|
+
}
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../../src/orchestrator/workflow/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BoberConfig } from "../../config/schema.js";
|
|
2
|
+
import type { PipelineEngine, PipelineEngineName } from "./engine.js";
|
|
3
|
+
/**
|
|
4
|
+
* Pure resolver — returns the engine name without instantiating an engine.
|
|
5
|
+
*
|
|
6
|
+
* Resolution branches:
|
|
7
|
+
* - engine unset → 'ts'
|
|
8
|
+
* - engine === 'workflow' && ineligible → 'ts' (one downgrade log line)
|
|
9
|
+
* - engine === 'workflow' && mode === 'careful' → 'ts' (one downgrade log line)
|
|
10
|
+
* - else → engine verbatim ('ts' | 'skill' | 'workflow')
|
|
11
|
+
*
|
|
12
|
+
* Mirrors the pure-resolver pattern of resolveCheckpointMechanismName
|
|
13
|
+
* (src/orchestrator/checkpoints/registry.ts:65).
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveEngineName(config: BoberConfig): PipelineEngineName;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve config.pipeline.engine to a PipelineEngine instance.
|
|
18
|
+
*
|
|
19
|
+
* Belt-and-suspenders per ADR-6:
|
|
20
|
+
* - resolveEngineName (above) ALREADY downgrades workflow→ts when ineligible/careful.
|
|
21
|
+
* - In the eligible case, WorkflowEngine is returned; its run() has a second guard
|
|
22
|
+
* that catches WorkflowUnavailableError from the dormant invoke and re-dispatches TS.
|
|
23
|
+
* - 'skill' remains on TsPipelineEngine (no skill engine this sprint — non-goal).
|
|
24
|
+
*/
|
|
25
|
+
export declare function selectPipelineEngine(config: BoberConfig): PipelineEngine;
|
|
26
|
+
//# sourceMappingURL=selector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/workflow/selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAOtE;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,kBAAkB,CAezE;AAID;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,cAAc,CAaxE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { logger } from "../../utils/logger.js";
|
|
2
|
+
import { isWorkflowEligible } from "./eligibility.js";
|
|
3
|
+
import { TsPipelineEngine } from "./ts-engine.js";
|
|
4
|
+
import { WorkflowEngine } from "./workflow-engine.js";
|
|
5
|
+
// ── Resolver ───────────────────────────────────────────────────────
|
|
6
|
+
/**
|
|
7
|
+
* Pure resolver — returns the engine name without instantiating an engine.
|
|
8
|
+
*
|
|
9
|
+
* Resolution branches:
|
|
10
|
+
* - engine unset → 'ts'
|
|
11
|
+
* - engine === 'workflow' && ineligible → 'ts' (one downgrade log line)
|
|
12
|
+
* - engine === 'workflow' && mode === 'careful' → 'ts' (one downgrade log line)
|
|
13
|
+
* - else → engine verbatim ('ts' | 'skill' | 'workflow')
|
|
14
|
+
*
|
|
15
|
+
* Mirrors the pure-resolver pattern of resolveCheckpointMechanismName
|
|
16
|
+
* (src/orchestrator/checkpoints/registry.ts:65).
|
|
17
|
+
*/
|
|
18
|
+
export function resolveEngineName(config) {
|
|
19
|
+
const requested = config.pipeline?.engine ?? "ts";
|
|
20
|
+
if (requested === "workflow") {
|
|
21
|
+
const eligible = isWorkflowEligible(config);
|
|
22
|
+
const careful = config.pipeline?.mode === "careful";
|
|
23
|
+
if (!eligible || careful) {
|
|
24
|
+
logger.info(`Workflow engine requested but ${!eligible ? "ineligible" : "mode='careful'"}; downgrading to 'ts'.`);
|
|
25
|
+
return "ts";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return requested;
|
|
29
|
+
}
|
|
30
|
+
// ── Selector ───────────────────────────────────────────────────────
|
|
31
|
+
/**
|
|
32
|
+
* Resolve config.pipeline.engine to a PipelineEngine instance.
|
|
33
|
+
*
|
|
34
|
+
* Belt-and-suspenders per ADR-6:
|
|
35
|
+
* - resolveEngineName (above) ALREADY downgrades workflow→ts when ineligible/careful.
|
|
36
|
+
* - In the eligible case, WorkflowEngine is returned; its run() has a second guard
|
|
37
|
+
* that catches WorkflowUnavailableError from the dormant invoke and re-dispatches TS.
|
|
38
|
+
* - 'skill' remains on TsPipelineEngine (no skill engine this sprint — non-goal).
|
|
39
|
+
*/
|
|
40
|
+
export function selectPipelineEngine(config) {
|
|
41
|
+
const name = resolveEngineName(config);
|
|
42
|
+
switch (name) {
|
|
43
|
+
case "ts":
|
|
44
|
+
return new TsPipelineEngine();
|
|
45
|
+
case "skill":
|
|
46
|
+
// Skill engine deferred (non-goal this sprint); falls through to TS.
|
|
47
|
+
return new TsPipelineEngine();
|
|
48
|
+
case "workflow":
|
|
49
|
+
// Reachable only when resolveEngineName returns 'workflow' (eligible + not careful).
|
|
50
|
+
// WorkflowEngine.run has a belt-and-suspenders catch for WorkflowUnavailableError.
|
|
51
|
+
return new WorkflowEngine();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selector.js","sourceRoot":"","sources":["../../../src/orchestrator/workflow/selector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,sEAAsE;AAEtE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAmB;IACnD,MAAM,SAAS,GAAuB,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,IAAI,CAAC;IAEtE,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,EAAE,IAAI,KAAK,SAAS,CAAC;QACpD,IAAI,CAAC,QAAQ,IAAI,OAAO,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CACT,iCAAiC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB,wBAAwB,CACrG,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,sEAAsE;AAEtE;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAmB;IACtD,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,IAAI;YACP,OAAO,IAAI,gBAAgB,EAAE,CAAC;QAChC,KAAK,OAAO;YACV,qEAAqE;YACrE,OAAO,IAAI,gBAAgB,EAAE,CAAC;QAChC,KAAK,UAAU;YACb,qFAAqF;YACrF,mFAAmF;YACnF,OAAO,IAAI,cAAc,EAAE,CAAC;IAChC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SynthesisResult: the ranked output of synthesize() (ranking shape, not
|
|
3
|
+
* pass/fail — contrast with EvalResult returned by reconcile()).
|
|
4
|
+
*/
|
|
5
|
+
export interface SynthesisResult {
|
|
6
|
+
/** The approach with the highest aggregate score across all lenses. */
|
|
7
|
+
winner: string;
|
|
8
|
+
/**
|
|
9
|
+
* All approaches ordered descending by total score.
|
|
10
|
+
* Deterministic tie-break: lower original index in `approaches` wins
|
|
11
|
+
* when two approaches have equal totals (i.e. the approach that appeared
|
|
12
|
+
* earlier in the caller's list is ranked higher).
|
|
13
|
+
*/
|
|
14
|
+
ranking: Array<{
|
|
15
|
+
approach: string;
|
|
16
|
+
perLensScores: Record<string, number>;
|
|
17
|
+
total: number;
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Placeholder collection slot for cross-approach ideas worth grafting into
|
|
21
|
+
* the winner. This sprint uses runner-up approach names as a simple default;
|
|
22
|
+
* future sprints may populate this with extracted proposal fragments.
|
|
23
|
+
*/
|
|
24
|
+
graftedIdeas: string[];
|
|
25
|
+
/**
|
|
26
|
+
* Lenses whose individual top-scored approach differs from the overall winner.
|
|
27
|
+
* Each entry is a human-readable string identifying the lens and its preferred
|
|
28
|
+
* approach, e.g. "scalability: prefers approach-B".
|
|
29
|
+
*/
|
|
30
|
+
dissent: string[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Pure ranking reducer over per-lens approach scores (sibling of reconcile()).
|
|
34
|
+
* No Date.now / new Date / Math.random / fs — this function is deterministic
|
|
35
|
+
* given the same inputs.
|
|
36
|
+
*
|
|
37
|
+
* Tie-break rule (documented): when two approaches have equal aggregate totals,
|
|
38
|
+
* the approach whose index is LOWER in the original `approaches` array wins.
|
|
39
|
+
* This is achieved by capturing original indices before sorting and using them
|
|
40
|
+
* as a stable comparator secondary key.
|
|
41
|
+
*
|
|
42
|
+
* @param approaches - Ordered list of approach identifiers to rank.
|
|
43
|
+
* @param lensScores - Per-lens score maps: each entry has a lens name and a
|
|
44
|
+
* `scores` record mapping approach → numeric score. Missing approach keys
|
|
45
|
+
* contribute 0 for that lens.
|
|
46
|
+
* @throws {Error} if `approaches` is empty (mirrors reconcile() guard).
|
|
47
|
+
*/
|
|
48
|
+
export declare function synthesize(approaches: string[], lensScores: Array<{
|
|
49
|
+
lens: string;
|
|
50
|
+
scores: Record<string, number>;
|
|
51
|
+
}>): SynthesisResult;
|
|
52
|
+
//# sourceMappingURL=synthesizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synthesizer.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/workflow/synthesizer.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,OAAO,EAAE,KAAK,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACtC,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH;;;;OAIG;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB;;;;OAIG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAAE,EACpB,UAAU,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,GAClE,eAAe,CA4EjB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// ── Synthesizer ─────────────────────────────────────────────────────
|
|
2
|
+
// ── synthesize ──────────────────────────────────────────────────────
|
|
3
|
+
/**
|
|
4
|
+
* Pure ranking reducer over per-lens approach scores (sibling of reconcile()).
|
|
5
|
+
* No Date.now / new Date / Math.random / fs — this function is deterministic
|
|
6
|
+
* given the same inputs.
|
|
7
|
+
*
|
|
8
|
+
* Tie-break rule (documented): when two approaches have equal aggregate totals,
|
|
9
|
+
* the approach whose index is LOWER in the original `approaches` array wins.
|
|
10
|
+
* This is achieved by capturing original indices before sorting and using them
|
|
11
|
+
* as a stable comparator secondary key.
|
|
12
|
+
*
|
|
13
|
+
* @param approaches - Ordered list of approach identifiers to rank.
|
|
14
|
+
* @param lensScores - Per-lens score maps: each entry has a lens name and a
|
|
15
|
+
* `scores` record mapping approach → numeric score. Missing approach keys
|
|
16
|
+
* contribute 0 for that lens.
|
|
17
|
+
* @throws {Error} if `approaches` is empty (mirrors reconcile() guard).
|
|
18
|
+
*/
|
|
19
|
+
export function synthesize(approaches, lensScores) {
|
|
20
|
+
if (approaches.length === 0) {
|
|
21
|
+
throw new Error("synthesize: approaches must be non-empty");
|
|
22
|
+
}
|
|
23
|
+
// ── Build per-approach aggregates ───────────────────────────────────
|
|
24
|
+
// Capture original indices for deterministic tie-breaking before sort
|
|
25
|
+
const indexed = approaches.map((approach, originalIndex) => {
|
|
26
|
+
const perLensScores = {};
|
|
27
|
+
let total = 0;
|
|
28
|
+
for (const { lens, scores } of lensScores) {
|
|
29
|
+
const s = scores[approach] ?? 0;
|
|
30
|
+
perLensScores[lens] = s;
|
|
31
|
+
total = total + s;
|
|
32
|
+
}
|
|
33
|
+
return { approach, perLensScores, total, originalIndex };
|
|
34
|
+
});
|
|
35
|
+
// ── Sort descending by total; tie-break: lower original index wins ──
|
|
36
|
+
const sorted = indexed.slice().sort((a, b) => {
|
|
37
|
+
if (b.total !== a.total) {
|
|
38
|
+
return b.total - a.total; // higher total ranks first
|
|
39
|
+
}
|
|
40
|
+
return a.originalIndex - b.originalIndex; // lower index ranks first on tie
|
|
41
|
+
});
|
|
42
|
+
const ranking = sorted.map(({ approach, perLensScores, total }) => ({
|
|
43
|
+
approach,
|
|
44
|
+
perLensScores,
|
|
45
|
+
total,
|
|
46
|
+
}));
|
|
47
|
+
const winner = ranking[0].approach;
|
|
48
|
+
// ── Compute dissent ─────────────────────────────────────────────────
|
|
49
|
+
// A lens dissents when its own top-scored approach differs from winner.
|
|
50
|
+
// Tie-break within a single lens also uses lower original index.
|
|
51
|
+
const approachToIndex = new Map(approaches.map((a, i) => [a, i]));
|
|
52
|
+
const dissent = [];
|
|
53
|
+
for (const { lens, scores } of lensScores) {
|
|
54
|
+
let lensWinner;
|
|
55
|
+
let lensMax = -Infinity;
|
|
56
|
+
for (const approach of approaches) {
|
|
57
|
+
const s = scores[approach] ?? 0;
|
|
58
|
+
const idx = approachToIndex.get(approach) ?? 0;
|
|
59
|
+
if (s > lensMax ||
|
|
60
|
+
(s === lensMax &&
|
|
61
|
+
lensWinner !== undefined &&
|
|
62
|
+
idx < (approachToIndex.get(lensWinner) ?? 0))) {
|
|
63
|
+
lensMax = s;
|
|
64
|
+
lensWinner = approach;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (lensWinner !== undefined && lensWinner !== winner) {
|
|
68
|
+
dissent.push(`${lens}: prefers ${lensWinner}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// ── Compute graftedIdeas (runner-up approaches as placeholder) ──────
|
|
72
|
+
const graftedIdeas = ranking.slice(1).map((r) => r.approach);
|
|
73
|
+
return { winner, ranking, graftedIdeas, dissent };
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=synthesizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synthesizer.js","sourceRoot":"","sources":["../../../src/orchestrator/workflow/synthesizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BoberConfig } from "../../config/schema.js";
|
|
2
|
+
import type { PipelineResult } from "../pipeline.js";
|
|
3
|
+
import type { PipelineEngine, PipelineEngineName } from "./engine.js";
|
|
4
|
+
/**
|
|
5
|
+
* Engine adapter that wraps the original TypeScript pipeline implementation.
|
|
6
|
+
* Delegates to runTsPipeline — the extracted former runPipeline body — with
|
|
7
|
+
* ZERO behaviour change on the default 'ts' path.
|
|
8
|
+
*/
|
|
9
|
+
export declare class TsPipelineEngine implements PipelineEngine {
|
|
10
|
+
readonly name: PipelineEngineName;
|
|
11
|
+
run(userPrompt: string, projectRoot: string, config: BoberConfig): Promise<PipelineResult>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=ts-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ts-engine.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/workflow/ts-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAItE;;;;GAIG;AACH,qBAAa,gBAAiB,YAAW,cAAc;IACrD,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAQ;IAEzC,GAAG,CACD,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,cAAc,CAAC;CAG3B"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { runTsPipeline } from "../pipeline.js";
|
|
2
|
+
// ── TsPipelineEngine ───────────────────────────────────────────────
|
|
3
|
+
/**
|
|
4
|
+
* Engine adapter that wraps the original TypeScript pipeline implementation.
|
|
5
|
+
* Delegates to runTsPipeline — the extracted former runPipeline body — with
|
|
6
|
+
* ZERO behaviour change on the default 'ts' path.
|
|
7
|
+
*/
|
|
8
|
+
export class TsPipelineEngine {
|
|
9
|
+
name = "ts";
|
|
10
|
+
run(userPrompt, projectRoot, config) {
|
|
11
|
+
return runTsPipeline(userPrompt, projectRoot, config);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=ts-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ts-engine.js","sourceRoot":"","sources":["../../../src/orchestrator/workflow/ts-engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAI/C,sEAAsE;AAEtE;;;;GAIG;AACH,MAAM,OAAO,gBAAgB;IAClB,IAAI,GAAuB,IAAI,CAAC;IAEzC,GAAG,CACD,UAAkB,EAClB,WAAmB,EACnB,MAAmB;QAEnB,OAAO,aAAa,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;CACF"}
|