duocode 0.1.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 (220) hide show
  1. package/.env.example +36 -0
  2. package/LICENSE +21 -0
  3. package/README.md +52 -0
  4. package/dist/ast/context.d.ts +16 -0
  5. package/dist/ast/context.js +37 -0
  6. package/dist/ast/context.js.map +1 -0
  7. package/dist/ast/diff.d.ts +27 -0
  8. package/dist/ast/diff.js +44 -0
  9. package/dist/ast/diff.js.map +1 -0
  10. package/dist/ast/locks.d.ts +47 -0
  11. package/dist/ast/locks.js +88 -0
  12. package/dist/ast/locks.js.map +1 -0
  13. package/dist/ast/merge.d.ts +22 -0
  14. package/dist/ast/merge.js +120 -0
  15. package/dist/ast/merge.js.map +1 -0
  16. package/dist/ast/ownership.d.ts +31 -0
  17. package/dist/ast/ownership.js +111 -0
  18. package/dist/ast/ownership.js.map +1 -0
  19. package/dist/ast/parser.d.ts +44 -0
  20. package/dist/ast/parser.js +134 -0
  21. package/dist/ast/parser.js.map +1 -0
  22. package/dist/cli.d.ts +2 -0
  23. package/dist/cli.js +423 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/commands/doctor.d.ts +5 -0
  26. package/dist/commands/doctor.js +63 -0
  27. package/dist/commands/doctor.js.map +1 -0
  28. package/dist/commands/duo.d.ts +9 -0
  29. package/dist/commands/duo.js +285 -0
  30. package/dist/commands/duo.js.map +1 -0
  31. package/dist/commands/github.d.ts +2 -0
  32. package/dist/commands/github.js +85 -0
  33. package/dist/commands/github.js.map +1 -0
  34. package/dist/commands/init.d.ts +2 -0
  35. package/dist/commands/init.js +33 -0
  36. package/dist/commands/init.js.map +1 -0
  37. package/dist/commands/negotiation.d.ts +2 -0
  38. package/dist/commands/negotiation.js +160 -0
  39. package/dist/commands/negotiation.js.map +1 -0
  40. package/dist/commands/repl_commands.d.ts +26 -0
  41. package/dist/commands/repl_commands.js +226 -0
  42. package/dist/commands/repl_commands.js.map +1 -0
  43. package/dist/commands/shell.d.ts +1 -0
  44. package/dist/commands/shell.js +110 -0
  45. package/dist/commands/shell.js.map +1 -0
  46. package/dist/commands/start.d.ts +2 -0
  47. package/dist/commands/start.js +231 -0
  48. package/dist/commands/start.js.map +1 -0
  49. package/dist/commands/task.d.ts +2 -0
  50. package/dist/commands/task.js +215 -0
  51. package/dist/commands/task.js.map +1 -0
  52. package/dist/config/loader.d.ts +193 -0
  53. package/dist/config/loader.js +106 -0
  54. package/dist/config/loader.js.map +1 -0
  55. package/dist/context/project_context.d.ts +79 -0
  56. package/dist/context/project_context.js +292 -0
  57. package/dist/context/project_context.js.map +1 -0
  58. package/dist/context/token_budget.d.ts +35 -0
  59. package/dist/context/token_budget.js +81 -0
  60. package/dist/context/token_budget.js.map +1 -0
  61. package/dist/db/queries.d.ts +121 -0
  62. package/dist/db/queries.js +109 -0
  63. package/dist/db/queries.js.map +1 -0
  64. package/dist/db/schema.d.ts +110 -0
  65. package/dist/db/schema.js +346 -0
  66. package/dist/db/schema.js.map +1 -0
  67. package/dist/duo/duo_orchestrator.d.ts +50 -0
  68. package/dist/duo/duo_orchestrator.js +510 -0
  69. package/dist/duo/duo_orchestrator.js.map +1 -0
  70. package/dist/duo/duo_session.d.ts +47 -0
  71. package/dist/duo/duo_session.js +127 -0
  72. package/dist/duo/duo_session.js.map +1 -0
  73. package/dist/duo/duo_types.d.ts +168 -0
  74. package/dist/duo/duo_types.js +53 -0
  75. package/dist/duo/duo_types.js.map +1 -0
  76. package/dist/duo/session_store.d.ts +71 -0
  77. package/dist/duo/session_store.js +177 -0
  78. package/dist/duo/session_store.js.map +1 -0
  79. package/dist/git/worktree.d.ts +21 -0
  80. package/dist/git/worktree.js +86 -0
  81. package/dist/git/worktree.js.map +1 -0
  82. package/dist/github/cache.d.ts +23 -0
  83. package/dist/github/cache.js +67 -0
  84. package/dist/github/cache.js.map +1 -0
  85. package/dist/github/issues.d.ts +17 -0
  86. package/dist/github/issues.js +93 -0
  87. package/dist/github/issues.js.map +1 -0
  88. package/dist/github/mcp_client.d.ts +57 -0
  89. package/dist/github/mcp_client.js +214 -0
  90. package/dist/github/mcp_client.js.map +1 -0
  91. package/dist/github/sync.d.ts +11 -0
  92. package/dist/github/sync.js +65 -0
  93. package/dist/github/sync.js.map +1 -0
  94. package/dist/github/webhook.d.ts +25 -0
  95. package/dist/github/webhook.js +197 -0
  96. package/dist/github/webhook.js.map +1 -0
  97. package/dist/negotiation/index.d.ts +1 -0
  98. package/dist/negotiation/index.js +2 -0
  99. package/dist/negotiation/index.js.map +1 -0
  100. package/dist/negotiation/protocol.d.ts +62 -0
  101. package/dist/negotiation/protocol.js +188 -0
  102. package/dist/negotiation/protocol.js.map +1 -0
  103. package/dist/orchestrator/complexity_scorer.d.ts +2 -0
  104. package/dist/orchestrator/complexity_scorer.js +79 -0
  105. package/dist/orchestrator/complexity_scorer.js.map +1 -0
  106. package/dist/orchestrator/dependency_graph.d.ts +7 -0
  107. package/dist/orchestrator/dependency_graph.js +73 -0
  108. package/dist/orchestrator/dependency_graph.js.map +1 -0
  109. package/dist/orchestrator/intent_parser.d.ts +11 -0
  110. package/dist/orchestrator/intent_parser.js +116 -0
  111. package/dist/orchestrator/intent_parser.js.map +1 -0
  112. package/dist/orchestrator/task_runner.d.ts +56 -0
  113. package/dist/orchestrator/task_runner.js +181 -0
  114. package/dist/orchestrator/task_runner.js.map +1 -0
  115. package/dist/orchestrator/types.d.ts +44 -0
  116. package/dist/orchestrator/types.js +21 -0
  117. package/dist/orchestrator/types.js.map +1 -0
  118. package/dist/providers/anthropic.d.ts +12 -0
  119. package/dist/providers/anthropic.js +258 -0
  120. package/dist/providers/anthropic.js.map +1 -0
  121. package/dist/providers/auction.d.ts +42 -0
  122. package/dist/providers/auction.js +190 -0
  123. package/dist/providers/auction.js.map +1 -0
  124. package/dist/providers/base.d.ts +103 -0
  125. package/dist/providers/base.js +2 -0
  126. package/dist/providers/base.js.map +1 -0
  127. package/dist/providers/cost_tracker.d.ts +45 -0
  128. package/dist/providers/cost_tracker.js +111 -0
  129. package/dist/providers/cost_tracker.js.map +1 -0
  130. package/dist/providers/duo_pair_router.d.ts +11 -0
  131. package/dist/providers/duo_pair_router.js +67 -0
  132. package/dist/providers/duo_pair_router.js.map +1 -0
  133. package/dist/providers/factory.d.ts +7 -0
  134. package/dist/providers/factory.js +130 -0
  135. package/dist/providers/factory.js.map +1 -0
  136. package/dist/providers/grading_rubric.d.ts +37 -0
  137. package/dist/providers/grading_rubric.js +238 -0
  138. package/dist/providers/grading_rubric.js.map +1 -0
  139. package/dist/providers/openai.d.ts +12 -0
  140. package/dist/providers/openai.js +229 -0
  141. package/dist/providers/openai.js.map +1 -0
  142. package/dist/providers/openrouter.d.ts +14 -0
  143. package/dist/providers/openrouter.js +178 -0
  144. package/dist/providers/openrouter.js.map +1 -0
  145. package/dist/providers/performance_tracker.d.ts +21 -0
  146. package/dist/providers/performance_tracker.js +63 -0
  147. package/dist/providers/performance_tracker.js.map +1 -0
  148. package/dist/providers/registry_loader.d.ts +6 -0
  149. package/dist/providers/registry_loader.js +54 -0
  150. package/dist/providers/registry_loader.js.map +1 -0
  151. package/dist/providers/retry.d.ts +66 -0
  152. package/dist/providers/retry.js +203 -0
  153. package/dist/providers/retry.js.map +1 -0
  154. package/dist/providers/role_scorer.d.ts +16 -0
  155. package/dist/providers/role_scorer.js +16 -0
  156. package/dist/providers/role_scorer.js.map +1 -0
  157. package/dist/providers/router.d.ts +84 -0
  158. package/dist/providers/router.js +542 -0
  159. package/dist/providers/router.js.map +1 -0
  160. package/dist/security/credentials.d.ts +6 -0
  161. package/dist/security/credentials.js +16 -0
  162. package/dist/security/credentials.js.map +1 -0
  163. package/dist/setup/browser.d.ts +1 -0
  164. package/dist/setup/browser.js +12 -0
  165. package/dist/setup/browser.js.map +1 -0
  166. package/dist/setup/global_config.d.ts +14 -0
  167. package/dist/setup/global_config.js +54 -0
  168. package/dist/setup/global_config.js.map +1 -0
  169. package/dist/setup/wizard.d.ts +2 -0
  170. package/dist/setup/wizard.js +206 -0
  171. package/dist/setup/wizard.js.map +1 -0
  172. package/dist/tools/agent_loop.d.ts +38 -0
  173. package/dist/tools/agent_loop.js +72 -0
  174. package/dist/tools/agent_loop.js.map +1 -0
  175. package/dist/tools/approval.d.ts +64 -0
  176. package/dist/tools/approval.js +172 -0
  177. package/dist/tools/approval.js.map +1 -0
  178. package/dist/tools/checkpoint.d.ts +65 -0
  179. package/dist/tools/checkpoint.js +342 -0
  180. package/dist/tools/checkpoint.js.map +1 -0
  181. package/dist/tools/definitions.d.ts +13 -0
  182. package/dist/tools/definitions.js +103 -0
  183. package/dist/tools/definitions.js.map +1 -0
  184. package/dist/tools/diff_display.d.ts +46 -0
  185. package/dist/tools/diff_display.js +298 -0
  186. package/dist/tools/diff_display.js.map +1 -0
  187. package/dist/tools/executor.d.ts +12 -0
  188. package/dist/tools/executor.js +340 -0
  189. package/dist/tools/executor.js.map +1 -0
  190. package/dist/tools/permissions.d.ts +17 -0
  191. package/dist/tools/permissions.js +139 -0
  192. package/dist/tools/permissions.js.map +1 -0
  193. package/dist/tools/tool_types.d.ts +48 -0
  194. package/dist/tools/tool_types.js +7 -0
  195. package/dist/tools/tool_types.js.map +1 -0
  196. package/dist/ui/banner.d.ts +4 -0
  197. package/dist/ui/banner.js +104 -0
  198. package/dist/ui/banner.js.map +1 -0
  199. package/dist/ui/callbacks.d.ts +30 -0
  200. package/dist/ui/callbacks.js +132 -0
  201. package/dist/ui/callbacks.js.map +1 -0
  202. package/dist/ui/colors.d.ts +14 -0
  203. package/dist/ui/colors.js +28 -0
  204. package/dist/ui/colors.js.map +1 -0
  205. package/dist/ui/dashboard.d.ts +51 -0
  206. package/dist/ui/dashboard.js +181 -0
  207. package/dist/ui/dashboard.js.map +1 -0
  208. package/dist/ui/leaderboard.d.ts +16 -0
  209. package/dist/ui/leaderboard.js +43 -0
  210. package/dist/ui/leaderboard.js.map +1 -0
  211. package/dist/ui/logger.d.ts +28 -0
  212. package/dist/ui/logger.js +117 -0
  213. package/dist/ui/logger.js.map +1 -0
  214. package/dist/ui/progress.d.ts +16 -0
  215. package/dist/ui/progress.js +62 -0
  216. package/dist/ui/progress.js.map +1 -0
  217. package/dist/ui/tokenizer.d.ts +5 -0
  218. package/dist/ui/tokenizer.js +54 -0
  219. package/dist/ui/tokenizer.js.map +1 -0
  220. package/package.json +63 -0
@@ -0,0 +1,104 @@
1
+ import { R, B, DM, CYN, DCY, BLU, GRN, MAG } from "./colors.js";
2
+ import { buildProviders } from "../commands/duo.js";
3
+ import { createLogger } from "./logger.js";
4
+ export function banner() {
5
+ const L1 = `${CYN}${B}█████${DCY}▄${CYN} ██ ██ ${DCY}▄${CYN}████${DCY}▄${CYN} ${DCY}▄${CYN}█████ ${DCY}▄${CYN}████${DCY}▄${CYN} █████${DCY}▄${CYN} ██████${R}`;
6
+ const L2 = `${CYN}${B}██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██${R}`;
7
+ const L3 = `${CYN}${B}██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █████${R}`;
8
+ const L4 = `${CYN}${B}██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██${R}`;
9
+ const L5 = `${CYN}${B}█████${DCY}▀${CYN} ${DCY}▀${CYN}████${DCY}▀${CYN} ${DCY}▀${CYN}████${DCY}▀${CYN} ${DCY}▀${CYN}█████ ${DCY}▀${CYN}████${DCY}▀${CYN} █████${DCY}▀${CYN} ██████${R}`;
10
+ return [
11
+ "",
12
+ ` ${L1}`,
13
+ ` ${L2}`,
14
+ ` ${L3}`,
15
+ ` ${L4}`,
16
+ ` ${L5}`,
17
+ "",
18
+ ` ${DM}Multi-agent code orchestrator${R} ${DM}v0.1.0${R}`,
19
+ ` ${DM}Author${R} ${DCY}=>${R} ${CYN}Kbinkenaid${R}`,
20
+ "",
21
+ ].join("\n");
22
+ }
23
+ const log = createLogger("banner");
24
+ export function printManPage() {
25
+ const cmd = (suffix) => suffix;
26
+ const sections = [
27
+ {
28
+ heading: "Core",
29
+ rows: [
30
+ [cmd("start \"<prompt>\""), "Send a prompt to AI and stream the response"],
31
+ [cmd("shell"), "Open interactive mode; then run commands directly"],
32
+ [cmd("start \"...\" --model <id>"), "Use a specific model (e.g. openai/gpt-4o)"],
33
+ [cmd("start \"...\" --output <path>"), "Save output to a specific file"],
34
+ [cmd("login"), "Re-authenticate with AI providers"],
35
+ ],
36
+ },
37
+ {
38
+ heading: "Project",
39
+ rows: [
40
+ [cmd("init"), "Initialize a project in the current git repo"],
41
+ [cmd("task create <title>"), "Create a new task"],
42
+ [cmd("task execute --task-id ..."), "Run Layer 4 merge with dashboard output"],
43
+ [cmd("task list"), "List tasks (--status to filter)"],
44
+ [cmd("task show <id>"), "Show task details"],
45
+ [cmd("negotiation run <session>"), "Run a negotiation session"],
46
+ [cmd("github sync"), "Sync tasks with GitHub issues/PRs"],
47
+ ],
48
+ },
49
+ {
50
+ heading: "DuoPair",
51
+ rows: [
52
+ [cmd("duo run"), "Run DuoPair pipeline (interactive)"],
53
+ [cmd("duo run --prompt \"...\""), "Run DuoPair with a specific task"],
54
+ [cmd("duo run --judge <model>"), "Explicit cross-provider judge for grading"],
55
+ [cmd("duo preview --prompt \"...\""), "Preview pair assignment without executing"],
56
+ [cmd("duo leaderboard"), "Show ELO rankings by role"],
57
+ [cmd("duo config"), "Show scoring weights and grading rubric"],
58
+ ],
59
+ },
60
+ {
61
+ heading: "Help",
62
+ rows: [
63
+ [cmd("man"), "Show this manual"],
64
+ [cmd("models"), "List available model profiles"],
65
+ [cmd("<command> --help"), "Show help for a specific command"],
66
+ ],
67
+ },
68
+ ];
69
+ for (const section of sections) {
70
+ log.raw(`\n ${B}${section.heading}${R}\n\n`);
71
+ for (const [c, desc] of section.rows) {
72
+ log.raw(` ${CYN}${c.padEnd(38)}${R} ${DM}${desc}${R}\n`);
73
+ }
74
+ }
75
+ log.raw("\n");
76
+ }
77
+ export function printModels() {
78
+ const { capabilityRouter, costTracker } = buildProviders();
79
+ const profiles = capabilityRouter.listProfiles();
80
+ log.raw(`\n ${B}Available Models${R} ${DM}(${profiles.length} registered)${R}\n\n`);
81
+ for (const p of profiles) {
82
+ const pr = costTracker.getPricing(p.model);
83
+ const cost = pr ? `$${(pr.inputPer1kUsd * 1000).toFixed(2)}/$${(pr.outputPer1kUsd * 1000).toFixed(2)} /M` : "";
84
+ const tag = p.provider === "openai" ? BLU : p.provider === "anthropic" ? GRN : MAG;
85
+ const caps = p.capabilities.slice(0, 4).join(", ");
86
+ log.raw(` ${tag}${p.model.padEnd(24)}${R} ${DM}${p.provider.padEnd(12)}${R} ${DM}ctx:${String(Math.round((p.contextWindow ?? 0) / 1000)).padEnd(4)}K ${cost.padEnd(22)} ${caps}${R}\n`);
87
+ }
88
+ log.raw("\n");
89
+ }
90
+ export function checkPromptClarity(input) {
91
+ const words = input.split(/\s+/).filter(Boolean);
92
+ const charCount = input.length;
93
+ if (charCount < 3) {
94
+ return `"${input}" is too short to be a task. Could you describe what you want built?`;
95
+ }
96
+ if (words.length === 1) {
97
+ return `"${input}" — not sure what you mean. Could you be more specific? (e.g. "Write a ${input} function" or "Explain ${input}")`;
98
+ }
99
+ if (words.length === 2 && charCount < 8) {
100
+ return `"${input}" is a bit vague. Could you add more detail about what you need?`;
101
+ }
102
+ return null;
103
+ }
104
+ //# sourceMappingURL=banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/ui/banner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ /**
3
+ * Shared interactive callback factories for confirmation, model picking,
4
+ * and architect review. Used by both cli.ts conversational mode and
5
+ * commands/duo.ts to eliminate duplication.
6
+ */
7
+ import type { Interface as ReadlineInterface } from "node:readline/promises";
8
+ import type { ConfirmationCallback, ModelPickerCallback, ArchitectReviewCallback } from "../duo/duo_types.js";
9
+ export declare function makeConfirmationCallback(getRl: () => ReadlineInterface | null, opts?: {
10
+ autoConfirm?: () => boolean;
11
+ }): ConfirmationCallback;
12
+ /**
13
+ * Single-shot variant that creates (and cleans up) its own readline.
14
+ * Used by `duo run --prompt "..."` where there's no persistent readline.
15
+ */
16
+ export declare function makeSingleShotConfirmation(opts?: {
17
+ skip?: boolean;
18
+ }): ConfirmationCallback;
19
+ export declare function makeModelPickerCallback(getRl: () => ReadlineInterface | null, opts?: {
20
+ autoConfirm?: () => boolean;
21
+ }): ModelPickerCallback;
22
+ export declare function makeSingleShotModelPicker(opts?: {
23
+ skip?: boolean;
24
+ }): ModelPickerCallback;
25
+ export declare function makeArchitectReviewCallback(getRl: () => ReadlineInterface | null, opts?: {
26
+ autoConfirm?: () => boolean;
27
+ }): ArchitectReviewCallback;
28
+ export declare function makeSingleShotArchitectReview(opts?: {
29
+ skip?: boolean;
30
+ }): ArchitectReviewCallback;
@@ -0,0 +1,132 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import { R, B, CYN, BLU, DM } from "./colors.js";
3
+ import { createLogger } from "./logger.js";
4
+ const log = createLogger("callbacks");
5
+ // ── Confirmation ────────────────────────────────────────────────
6
+ export function makeConfirmationCallback(getRl, opts) {
7
+ return async () => {
8
+ if (opts?.autoConfirm?.())
9
+ return "proceed";
10
+ const rl = getRl();
11
+ if (!rl)
12
+ return "proceed";
13
+ const answer = await rl.question(`${CYN}[Y]es / [n]o / change [a]rchitect / change [e]xecutor?${R} `);
14
+ const trimmed = answer.trim().toLowerCase();
15
+ if (trimmed === "n" || trimmed === "no")
16
+ return "abort";
17
+ if (trimmed === "a")
18
+ return "pick-architect";
19
+ if (trimmed === "e")
20
+ return "pick-executor";
21
+ return "proceed";
22
+ };
23
+ }
24
+ /**
25
+ * Single-shot variant that creates (and cleans up) its own readline.
26
+ * Used by `duo run --prompt "..."` where there's no persistent readline.
27
+ */
28
+ export function makeSingleShotConfirmation(opts) {
29
+ return async () => {
30
+ if (opts?.skip)
31
+ return "proceed";
32
+ const tmpRl = createInterface({ input: process.stdin, output: process.stdout });
33
+ try {
34
+ const answer = await tmpRl.question(`${CYN}[Y]es / [n]o / change [a]rchitect / change [e]xecutor?${R} `);
35
+ const trimmed = answer.trim().toLowerCase();
36
+ if (trimmed === "n" || trimmed === "no")
37
+ return "abort";
38
+ if (trimmed === "a")
39
+ return "pick-architect";
40
+ if (trimmed === "e")
41
+ return "pick-executor";
42
+ return "proceed";
43
+ }
44
+ finally {
45
+ tmpRl.close();
46
+ }
47
+ };
48
+ }
49
+ // ── Model Picker ────────────────────────────────────────────────
50
+ function renderPickerOptions(options, role) {
51
+ log.raw(`\n ${B}Select ${role} model:${R}\n`);
52
+ for (let i = 0; i < options.length; i++) {
53
+ const opt = options[i];
54
+ const marker = opt.isCurrent ? ` ${CYN}<- current${R}` : "";
55
+ log.raw(` ${B}${String(i + 1).padStart(2)}.${R} ${opt.model.padEnd(22)} ${DM}${opt.provider.padEnd(12)}${R} ` +
56
+ `affinity: ${opt.roleAffinity.toFixed(2)} ~$${opt.estimatedCostUsd.toFixed(4)}${marker}\n`);
57
+ }
58
+ log.raw("\n");
59
+ }
60
+ function parsePickerChoice(answer, max) {
61
+ const idx = parseInt(answer.trim(), 10);
62
+ if (isNaN(idx) || idx < 1 || idx > max)
63
+ return null;
64
+ return String(idx);
65
+ }
66
+ export function makeModelPickerCallback(getRl, opts) {
67
+ return async (role, options, _currentModel) => {
68
+ if (opts?.autoConfirm?.())
69
+ return null;
70
+ const rl = getRl();
71
+ if (!rl)
72
+ return null;
73
+ renderPickerOptions(options, role);
74
+ const answer = await rl.question(`${CYN}Pick [1-${options.length}]:${R} `);
75
+ const choice = parsePickerChoice(answer, options.length);
76
+ if (!choice)
77
+ return null;
78
+ return options[parseInt(choice, 10) - 1].model;
79
+ };
80
+ }
81
+ export function makeSingleShotModelPicker(opts) {
82
+ return async (role, options, _currentModel) => {
83
+ if (opts?.skip)
84
+ return null;
85
+ const tmpRl = createInterface({ input: process.stdin, output: process.stdout });
86
+ try {
87
+ renderPickerOptions(options, role);
88
+ const answer = await tmpRl.question(`${CYN}Pick [1-${options.length}]:${R} `);
89
+ const choice = parsePickerChoice(answer, options.length);
90
+ if (!choice)
91
+ return null;
92
+ return options[parseInt(choice, 10) - 1].model;
93
+ }
94
+ finally {
95
+ tmpRl.close();
96
+ }
97
+ };
98
+ }
99
+ // ── Architect Review ────────────────────────────────────────────
100
+ export function makeArchitectReviewCallback(getRl, opts) {
101
+ return async (plan) => {
102
+ if (opts?.autoConfirm?.())
103
+ return true;
104
+ const rl = getRl();
105
+ if (!rl)
106
+ return true;
107
+ const sectionCount = (plan.match(/^## /gm) || []).length;
108
+ const sectionInfo = sectionCount > 0 ? ` (${sectionCount} sections)` : "";
109
+ log.raw(`\n${BLU}${B}Architect plan complete${sectionInfo}.${R}\n`);
110
+ log.raw(`${DM}Review the plan above before proceeding to executor.${R}\n\n`);
111
+ const answer = await rl.question(`${CYN}Proceed to executor? [Y/n]${R} `);
112
+ const trimmed = answer.trim().toLowerCase();
113
+ return trimmed === "" || trimmed === "y" || trimmed === "yes";
114
+ };
115
+ }
116
+ export function makeSingleShotArchitectReview(opts) {
117
+ return async (_plan) => {
118
+ if (opts?.skip)
119
+ return true;
120
+ log.raw(`\n${DM}Review the architect plan above before proceeding to executor.${R}\n\n`);
121
+ const tmpRl = createInterface({ input: process.stdin, output: process.stdout });
122
+ try {
123
+ const answer = await tmpRl.question(`${CYN}Proceed to executor? [Y/n]${R} `);
124
+ const trimmed = answer.trim().toLowerCase();
125
+ return trimmed === "" || trimmed === "y" || trimmed === "yes";
126
+ }
127
+ finally {
128
+ tmpRl.close();
129
+ }
130
+ };
131
+ }
132
+ //# sourceMappingURL=callbacks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callbacks.js","sourceRoot":"","sources":["../../src/ui/callbacks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /** Shared ANSI escape sequences — single source of truth. */
2
+ export declare const R = "\u001B[0m";
3
+ export declare const B = "\u001B[1m";
4
+ export declare const DM = "\u001B[2m";
5
+ export declare const CYN = "\u001B[96m";
6
+ export declare const DCY = "\u001B[36m";
7
+ export declare const BLU = "\u001B[94m";
8
+ export declare const GRN = "\u001B[92m";
9
+ export declare const YLW = "\u001B[93m";
10
+ export declare const RED = "\u001B[91m";
11
+ export declare const MAG = "\u001B[95m";
12
+ export declare function stripAnsi(str: string): string;
13
+ export declare function bar(value: number, max: number, width?: number): string;
14
+ export declare function scoreColor(score: number): string;
@@ -0,0 +1,28 @@
1
+ /** Shared ANSI escape sequences — single source of truth. */
2
+ export const R = "\x1b[0m"; // reset
3
+ export const B = "\x1b[1m"; // bold
4
+ export const DM = "\x1b[2m"; // dim
5
+ export const CYN = "\x1b[96m"; // bright cyan
6
+ export const DCY = "\x1b[36m"; // cyan (dim)
7
+ export const BLU = "\x1b[94m"; // bright blue
8
+ export const GRN = "\x1b[92m"; // bright green
9
+ export const YLW = "\x1b[93m"; // bright yellow
10
+ export const RED = "\x1b[91m"; // bright red
11
+ export const MAG = "\x1b[95m"; // bright magenta
12
+ export function stripAnsi(str) {
13
+ // eslint-disable-next-line no-control-regex
14
+ return str.replace(/\x1b\[[0-9;]*m/g, "");
15
+ }
16
+ export function bar(value, max, width = 20) {
17
+ const filled = Math.round((value / max) * width);
18
+ const empty = width - filled;
19
+ return `${"█".repeat(filled)}${"░".repeat(empty)}`;
20
+ }
21
+ export function scoreColor(score) {
22
+ if (score >= 4)
23
+ return GRN;
24
+ if (score >= 3)
25
+ return YLW;
26
+ return RED;
27
+ }
28
+ //# sourceMappingURL=colors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/ui/colors.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,MAAM,CAAC,MAAM,CAAC,GAAK,SAAS,CAAC,CAAO,QAAQ;AAC5C,MAAM,CAAC,MAAM,CAAC,GAAK,SAAS,CAAC,CAAO,OAAO;AAC3C,MAAM,CAAC,MAAM,EAAE,GAAI,SAAS,CAAC,CAAO,MAAM;AAC1C,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAM,cAAc;AAClD,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAM,aAAa;AACjD,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAM,cAAc;AAClD,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAM,eAAe;AACnD,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAM,gBAAgB;AACpD,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAM,aAAa;AACjD,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAM,iBAAiB;AAErD,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,4CAA4C;IAC5C,OAAO,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,KAAa,EAAE,GAAW,EAAE,KAAK,GAAG,EAAE;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC7B,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IAC3B,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IAC3B,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,51 @@
1
+ import type { AuctionDecision } from "../providers/auction.js";
2
+ import type { IntentAnalysis } from "../orchestrator/types.js";
3
+ export interface DashboardHeaderOpts {
4
+ model: string;
5
+ contextWindow?: number;
6
+ provider?: string;
7
+ }
8
+ export interface DashboardFooterOpts {
9
+ inputTokens: number;
10
+ outputTokens: number;
11
+ costUsd: number;
12
+ savedPath?: string;
13
+ }
14
+ export interface DashboardAuctionOpts {
15
+ auction: AuctionDecision;
16
+ }
17
+ export interface DashboardNegotiationOpts {
18
+ negotiationId: string;
19
+ taskId: string;
20
+ filePath: string;
21
+ language: "typescript" | "python" | "go";
22
+ phase: string;
23
+ conflictCount: number;
24
+ resolutionMethod: "auto_compose" | "debate_winner" | "escalated";
25
+ winnerAgentId: string | null;
26
+ confidence: number;
27
+ explanation: string;
28
+ rounds: Array<{
29
+ round_number: number;
30
+ left_score: number;
31
+ right_score: number;
32
+ consensus: number;
33
+ }>;
34
+ conflicts: Array<{
35
+ ownership_path: string;
36
+ left_type: string;
37
+ right_type: string;
38
+ }>;
39
+ learning?: {
40
+ consensusTrend: number;
41
+ recommendedAction: string;
42
+ };
43
+ }
44
+ export interface DashboardIntentOpts {
45
+ analysis: IntentAnalysis;
46
+ }
47
+ export declare function printDashboardHeader(opts: DashboardHeaderOpts): void;
48
+ export declare function printDashboardIntent(opts: DashboardIntentOpts): void;
49
+ export declare function printDashboardAuction(opts: DashboardAuctionOpts): void;
50
+ export declare function printDashboardFooter(opts: DashboardFooterOpts): void;
51
+ export declare function printDashboardNegotiation(opts: DashboardNegotiationOpts): void;
@@ -0,0 +1,181 @@
1
+ import { R, B, DM, DCY, GRN, YLW, BLU, MAG } from "./colors.js";
2
+ import { createLogger } from "./logger.js";
3
+ const CYN = DCY;
4
+ const MGN = MAG;
5
+ function formatContext(tokens) {
6
+ if (!tokens)
7
+ return "unknown";
8
+ if (tokens >= 1000000)
9
+ return `${(tokens / 1000000).toFixed(0)}M tokens`;
10
+ return `${(tokens / 1000).toFixed(0)}k tokens`;
11
+ }
12
+ function formatNumber(n) {
13
+ return n.toLocaleString("en-US");
14
+ }
15
+ const log = createLogger("dashboard");
16
+ export function printDashboardHeader(opts) {
17
+ const provider = opts.provider ?? "OpenRouter";
18
+ const w = (s) => log.raw(s);
19
+ w("\n");
20
+ w(` ${DM}Model${R} ${B}${opts.model}${R} ${DM}via ${provider}${R}\n`);
21
+ w(` ${DM}Context${R} ${formatContext(opts.contextWindow)}\n`);
22
+ w(` ${DM}Status${R} ${GRN}\u25CF${R} Generating...\n`);
23
+ w("\n");
24
+ }
25
+ function formatComplexity(score) {
26
+ if (score <= 3)
27
+ return `${GRN}${score}${R}`;
28
+ if (score <= 6)
29
+ return `${YLW}${score}${R}`;
30
+ return `${MGN}${score}${R}`;
31
+ }
32
+ export function printDashboardIntent(opts) {
33
+ const w = (s) => log.raw(s);
34
+ const { analysis } = opts;
35
+ const c = analysis.complexity;
36
+ const g = analysis.graph;
37
+ w("\n");
38
+ w(` ${DM}Complexity${R} ${formatComplexity(c.score)}/10 ${DM}(${c.explanation})${R}\n`);
39
+ w(` ${DM}Tier${R} ${B}${c.recommendedTier}${R}\n`);
40
+ if (analysis.intent.capabilities.length > 0) {
41
+ w(` ${DM}Detected${R} ${CYN}${analysis.intent.capabilities.join(`${R}, ${CYN}`)}${R}\n`);
42
+ }
43
+ w(` ${DM}Work Units${R} ${analysis.intent.workUnits.length} task${analysis.intent.workUnits.length === 1 ? "" : "s"}, ${g.layers.length} parallel group${g.layers.length === 1 ? "" : "s"}\n`);
44
+ w(` ${DM}Parsed in${R} ${analysis.parseTimeMs}ms\n`);
45
+ }
46
+ function bar(value, width = 18) {
47
+ const normalized = Math.max(0, Math.min(1, value));
48
+ const filled = Math.round(normalized * width);
49
+ const empty = width - filled;
50
+ return `${BLU}${"█".repeat(filled)}${DM}${"░".repeat(empty)}${R}`;
51
+ }
52
+ function shortModel(model) {
53
+ if (model.length <= 34)
54
+ return model;
55
+ return `${model.slice(0, 31)}...`;
56
+ }
57
+ export function printDashboardAuction(opts) {
58
+ const w = (s) => log.raw(s);
59
+ const { auction } = opts;
60
+ const modeColor = auction.mode === "hybrid" ? YLW : auction.mode === "ab_test" ? MGN : CYN;
61
+ w(` ${DM}Auction${R} ${modeColor}${B}${auction.mode.toUpperCase()}${R}\n`);
62
+ w(` ${DM}Winner${R} ${CYN}${auction.winner.model.model}${R}\n`);
63
+ if (auction.shadow) {
64
+ w(` ${DM}Shadow${R} ${YLW}${auction.shadow.model.model}${R}\n`);
65
+ }
66
+ w("\n");
67
+ // --- Reasoning ---
68
+ w(` ${B}Reasoning${R}\n`);
69
+ w(` ${auction.rationale}\n`);
70
+ w("\n");
71
+ // --- Scoring ---
72
+ w(` ${B}Scoring${R}\n`);
73
+ w(` ${DM}Each model is ranked with TOPSIS (deterministic multi-criteria analysis):${R}\n`);
74
+ w(` ${DM} 1) Normalize criteria to [0,1] utility scores${R}\n`);
75
+ w(` ${DM} 2) Apply task-intensity weights (light/moderate/complex)${R}\n`);
76
+ w(` ${DM} 3) Measure distance to ideal and anti-ideal points${R}\n`);
77
+ w(` ${DM} 4) ${CYN}score = d_minus / (d_plus + d_minus)${R}${DM} (higher is better)${R}\n`);
78
+ w(` ${DM} Criteria:${R} benchmark prior, capability fit, latency utility, cost utility, context fit\n`);
79
+ if (auction.mode === "hybrid") {
80
+ w(` ${DM} Hybrid triggers when runner-up score is within ${MGN}15%${R} ${DM}of winner${R}\n`);
81
+ }
82
+ else if (auction.mode === "ab_test") {
83
+ w(` ${DM} A/B test splits top 2 candidates via deterministic key hash${R}\n`);
84
+ }
85
+ w("\n");
86
+ if (auction.bids.length === 0) {
87
+ return;
88
+ }
89
+ // --- Winner breakdown ---
90
+ const winnerBid = auction.bids[0];
91
+ if (winnerBid) {
92
+ w(` ${B}Winner Breakdown${R} ${CYN}${winnerBid.model}${R}\n`);
93
+ for (const reason of winnerBid.reasons) {
94
+ w(` ${DM} -${R} ${reason}\n`);
95
+ }
96
+ w(` ${DM} -${R} final score: ${B}${winnerBid.score.toFixed(3)}${R} ${bar(Math.max(0, Math.min(1, winnerBid.score)))}\n`);
97
+ w(` ${DM} -${R} est. cost: ${GRN}$${winnerBid.estimatedCostUsd.toFixed(4)}${R}, latency: ~${winnerBid.estimatedLatencyMs}ms\n`);
98
+ }
99
+ if (auction.shadow && auction.bids.length > 1) {
100
+ const shadowBid = auction.bids[1];
101
+ if (shadowBid) {
102
+ w(` ${B}Shadow Breakdown${R} ${YLW}${shadowBid.model}${R}\n`);
103
+ for (const reason of shadowBid.reasons) {
104
+ w(` ${DM} -${R} ${reason}\n`);
105
+ }
106
+ w(` ${DM} -${R} final score: ${B}${shadowBid.score.toFixed(3)}${R} ${bar(Math.max(0, Math.min(1, shadowBid.score)))}\n`);
107
+ w(` ${DM} -${R} est. cost: ${GRN}$${shadowBid.estimatedCostUsd.toFixed(4)}${R}, latency: ~${shadowBid.estimatedLatencyMs}ms\n`);
108
+ }
109
+ }
110
+ w("\n");
111
+ // --- All Bids table ---
112
+ w(` ${B}All Bids${R}\n`);
113
+ w(` ${DM}rank provider model score confidence latency est.cost${R}\n`);
114
+ for (let i = 0; i < auction.bids.length; i += 1) {
115
+ const bid = auction.bids[i];
116
+ const rank = `${i + 1}`.padEnd(4);
117
+ const provider = bid.provider.padEnd(11);
118
+ const model = shortModel(bid.model).padEnd(35);
119
+ const score = bid.score.toFixed(3).padEnd(7);
120
+ const confidence = `${(bid.confidence * 100).toFixed(1)}%`.padEnd(11);
121
+ const latency = `${Math.round(bid.estimatedLatencyMs)}ms`.padEnd(8);
122
+ const estCost = `$${bid.estimatedCostUsd.toFixed(4)}`;
123
+ const lineColor = i === 0 ? GRN : i === 1 ? YLW : DM;
124
+ w(` ${lineColor}${rank} ${provider} ${model} ${score} ${confidence} ${latency} ${estCost}${R}\n`);
125
+ w(` ${DM} score-bar ${bar(Math.max(0, Math.min(1, bid.score)))}${R}\n`);
126
+ }
127
+ w("\n");
128
+ }
129
+ export function printDashboardFooter(opts) {
130
+ const w = (s) => log.raw(s);
131
+ w("\n\n");
132
+ const total = Math.max(1, opts.inputTokens + opts.outputTokens);
133
+ const outputRatio = opts.outputTokens / total;
134
+ w(` ${DM}Mix${R} ${DM}input${R}/${GRN}output${R} ${bar(outputRatio)} ${Math.round(outputRatio * 100)}% out\n`);
135
+ w(` ${DM}Tokens${R} ${formatNumber(opts.inputTokens)} in / ${formatNumber(opts.outputTokens)} out\n`);
136
+ w(` ${DM}Cost${R} $${opts.costUsd.toFixed(4)}\n`);
137
+ if (opts.savedPath) {
138
+ w(` ${DM}Saved${R} ${CYN}${opts.savedPath}${R}\n`);
139
+ }
140
+ w("\n");
141
+ }
142
+ export function printDashboardNegotiation(opts) {
143
+ const w = (s) => log.raw(s);
144
+ w("\n");
145
+ w(` ${B}Layer 4: Negotiated Merge${R}\n`);
146
+ w(` ${DM}Task${R} ${opts.taskId}\n`);
147
+ w(` ${DM}Session${R} ${opts.negotiationId}\n`);
148
+ w(` ${DM}File${R} ${opts.filePath} (${opts.language})\n`);
149
+ w(` ${DM}Phase${R} ${opts.phase}\n`);
150
+ w(` ${DM}Method${R} ${opts.resolutionMethod}\n`);
151
+ w(` ${DM}Confidence${R} ${(opts.confidence * 100).toFixed(1)}%\n`);
152
+ if (opts.winnerAgentId) {
153
+ w(` ${DM}Winner${R} ${opts.winnerAgentId}\n`);
154
+ }
155
+ w(` ${DM}Conflicts${R} ${opts.conflictCount}\n`);
156
+ w("\n");
157
+ if (opts.conflicts.length > 0) {
158
+ w(` ${B}Conflict Map${R}\n`);
159
+ for (const conflict of opts.conflicts) {
160
+ w(` ${YLW}${conflict.ownership_path}${R} ${DM}${conflict.left_type}${R} vs ${DM}${conflict.right_type}${R}\n`);
161
+ }
162
+ w("\n");
163
+ }
164
+ if (opts.rounds.length > 0) {
165
+ w(` ${B}Debate Rounds${R}\n`);
166
+ for (const round of opts.rounds) {
167
+ const winner = round.left_score >= round.right_score ? "left" : "right";
168
+ w(` r${round.round_number} left=${round.left_score.toFixed(3)} right=${round.right_score.toFixed(3)} consensus=${(round.consensus * 100).toFixed(1)}% winner=${winner}\n`);
169
+ w(` ${DM} consensus ${bar(round.consensus)}${R}\n`);
170
+ }
171
+ w("\n");
172
+ }
173
+ w(` ${DM}Decision${R} ${opts.explanation}\n`);
174
+ if (opts.learning) {
175
+ const trend = opts.learning.consensusTrend >= 0 ? `+${opts.learning.consensusTrend.toFixed(3)}` : opts.learning.consensusTrend.toFixed(3);
176
+ w(` ${DM}Learning${R} trend=${trend}\n`);
177
+ w(` ${DM}Action${R} ${opts.learning.recommendedAction}\n`);
178
+ }
179
+ w("\n");
180
+ }
181
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/ui/dashboard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,GAAG,GAAG,GAAG,CAAC;AAChB,MAAM,GAAG,GAAG,GAAG,CAAC;AAmDhB,SAAS,aAAa,CAAC,MAAe;IACpC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,IAAI,MAAM,IAAI,OAAS;QAAE,OAAO,GAAG,CAAC,MAAM,GAAG,OAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC7E,OAAO,GAAG,CAAC,MAAM,GAAG,IAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;AAClD,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;AAEtC,MAAM,UAAU,oBAAoB,CAAC,IAAyB;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,YAAY,CAAC;IAC/C,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC,IAAI,CAAC,CAAC;IACR,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,EAAE,OAAO,QAAQ,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3E,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,MAAM,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACjE,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,GAAG,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAC3D,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa;IACrC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;IAC5C,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;IAC5C,OAAO,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAyB;IAC5D,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC;IAC9B,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAEzB,CAAC,CAAC,IAAI,CAAC,CAAC;IACR,CAAC,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1F,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,eAAe,GAAG,CAAC,IAAI,CAAC,CAAC;IAE3D,IAAI,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,CAAC,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/F,CAAC;IAED,CAAC,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,QAAQ,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,kBAAkB,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjM,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,MAAM,QAAQ,CAAC,WAAW,MAAM,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,GAAG,CAAC,KAAa,EAAE,KAAK,GAAG,EAAE;IACpC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC7B,OAAO,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;AACpE,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IACrC,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAA0B;IAC9D,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACzB,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAE3F,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,SAAS,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/E,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;IACrE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;IACvE,CAAC;IACD,CAAC,CAAC,IAAI,CAAC,CAAC;IAER,oBAAoB;IACpB,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,KAAK,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC,IAAI,CAAC,CAAC;IAER,kBAAkB;IAClB,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC,KAAK,EAAE,4EAA4E,CAAC,IAAI,CAAC,CAAC;IAC5F,CAAC,CAAC,KAAK,EAAE,kDAAkD,CAAC,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC,KAAK,EAAE,6DAA6D,CAAC,IAAI,CAAC,CAAC;IAC7E,CAAC,CAAC,KAAK,EAAE,uDAAuD,CAAC,IAAI,CAAC,CAAC;IACvE,CAAC,CAAC,KAAK,EAAE,QAAQ,GAAG,uCAAuC,CAAC,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAC/F,CAAC,CAAC,KAAK,EAAE,cAAc,CAAC,gFAAgF,CAAC,CAAC;IAC1G,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,CAAC,CAAC,KAAK,EAAE,oDAAoD,GAAG,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAClG,CAAC;SAAM,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACtC,CAAC,CAAC,KAAK,EAAE,gEAAgE,CAAC,IAAI,CAAC,CAAC;IAClF,CAAC;IACD,CAAC,CAAC,IAAI,CAAC,CAAC;IAER,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,2BAA2B;IAC3B,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,IAAI,SAAS,EAAE,CAAC;QACd,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,KAAK,GAAG,GAAG,SAAS,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;QAChE,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACvC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC;QAClC,CAAC;QACD,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,iBAAiB,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3H,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,eAAe,GAAG,IAAI,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,SAAS,CAAC,kBAAkB,MAAM,CAAC,CAAC;IACpI,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,SAAS,EAAE,CAAC;YACd,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;YACjE,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;gBACvC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC;YAClC,CAAC;YACD,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,iBAAiB,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC3H,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,eAAe,GAAG,IAAI,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,SAAS,CAAC,kBAAkB,MAAM,CAAC,CAAC;QACpI,CAAC;IACH,CAAC;IACD,CAAC,CAAC,IAAI,CAAC,CAAC;IAER,yBAAyB;IACzB,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,KAAK,EAAE,iGAAiG,CAAC,IAAI,CAAC,CAAC;IACjH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAErD,CAAC,CAAC,KAAK,SAAS,GAAG,IAAI,KAAK,QAAQ,KAAK,KAAK,KAAK,KAAK,KAAK,UAAU,KAAK,OAAO,KAAK,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;QACzG,CAAC,CAAC,KAAK,EAAE,mBAAmB,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChF,CAAC;IACD,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAyB;IAC5D,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC,MAAM,CAAC,CAAC;IACV,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;IAChE,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC9C,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;IACtH,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1G,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,GAAG,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;IACD,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,IAA8B;IACtE,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAEpC,CAAC,CAAC,IAAI,CAAC,CAAC;IACR,CAAC,CAAC,KAAK,CAAC,4BAA4B,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,MAAM,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC;IAClD,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC;IAChE,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;IAC1C,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAC;IACrD,CAAC,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACpE,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC;IACpD,CAAC;IACD,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC;IAClD,CAAC,CAAC,IAAI,CAAC,CAAC;IAER,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC9B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,CAAC,CAAC,KAAK,GAAG,GAAG,QAAQ,CAAC,cAAc,GAAG,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,SAAS,GAAG,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,CAAC;QAClH,CAAC;QACD,CAAC,CAAC,IAAI,CAAC,CAAC;IACV,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YACxE,CAAC,CACC,MAAM,KAAK,CAAC,YAAY,SAAS,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,MAAM,IAAI,CACzK,CAAC;YACF,CAAC,CAAC,KAAK,EAAE,mBAAmB,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5D,CAAC;QACD,CAAC,CAAC,IAAI,CAAC,CAAC;IACV,CAAC;IAED,CAAC,CAAC,KAAK,EAAE,WAAW,CAAC,KAAK,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;IAEhD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1I,CAAC,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC;QAC1C,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,iBAAiB,IAAI,CAAC,CAAC;IAChE,CAAC;IAED,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Shared leaderboard rendering — used by both cli.ts and commands/duo.ts.
3
+ */
4
+ import type Database from "better-sqlite3";
5
+ import type { DuoRole } from "../duo/duo_types.js";
6
+ export interface AggregatedEloEntry {
7
+ model: string;
8
+ avgElo: number;
9
+ matches: number;
10
+ }
11
+ export declare function aggregateEloByModel(ratings: Array<{
12
+ model: string;
13
+ elo: number;
14
+ match_count: number;
15
+ }>): AggregatedEloEntry[];
16
+ export declare function printLeaderboard(db: Database.Database, roles?: DuoRole[]): void;