aura-code 0.6.3 → 0.10.1

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 (265) hide show
  1. package/README.md +47 -164
  2. package/dist/agent/affect.d.ts +13 -0
  3. package/dist/agent/affect.js +34 -0
  4. package/dist/agent/affect.js.map +1 -0
  5. package/dist/agent/compactor.d.ts +27 -4
  6. package/dist/agent/compactor.js +185 -54
  7. package/dist/agent/compactor.js.map +1 -1
  8. package/dist/agent/confess.d.ts +35 -0
  9. package/dist/agent/confess.js +296 -0
  10. package/dist/agent/confess.js.map +1 -0
  11. package/dist/agent/context.d.ts +0 -4
  12. package/dist/agent/context.js +0 -38
  13. package/dist/agent/context.js.map +1 -1
  14. package/dist/agent/domain-expertise.d.ts +22 -0
  15. package/dist/agent/domain-expertise.js +110 -0
  16. package/dist/agent/domain-expertise.js.map +1 -0
  17. package/dist/agent/executive-queue.d.ts +26 -0
  18. package/dist/agent/executive-queue.js +50 -0
  19. package/dist/agent/executive-queue.js.map +1 -0
  20. package/dist/agent/generational-flush.d.ts +28 -0
  21. package/dist/agent/generational-flush.js +48 -0
  22. package/dist/agent/generational-flush.js.map +1 -0
  23. package/dist/agent/loop-profile.d.ts +50 -0
  24. package/dist/agent/loop-profile.js +88 -0
  25. package/dist/agent/loop-profile.js.map +1 -0
  26. package/dist/agent/loop.d.ts +14 -5
  27. package/dist/agent/loop.js +167 -39
  28. package/dist/agent/loop.js.map +1 -1
  29. package/dist/agent/memory-consolidate.d.ts +14 -0
  30. package/dist/agent/memory-consolidate.js +141 -0
  31. package/dist/agent/memory-consolidate.js.map +1 -0
  32. package/dist/agent/mixture.d.ts +33 -0
  33. package/dist/agent/mixture.js +138 -0
  34. package/dist/agent/mixture.js.map +1 -0
  35. package/dist/agent/spawner.js +2 -2
  36. package/dist/agent/spawner.js.map +1 -1
  37. package/dist/agent/system-prompt.d.ts +1 -1
  38. package/dist/agent/system-prompt.js +50 -22
  39. package/dist/agent/system-prompt.js.map +1 -1
  40. package/dist/agent/unified-memory.d.ts +15 -0
  41. package/dist/agent/unified-memory.js +164 -0
  42. package/dist/agent/unified-memory.js.map +1 -0
  43. package/dist/checkpoints/engine.d.ts +44 -0
  44. package/dist/checkpoints/engine.js +324 -0
  45. package/dist/checkpoints/engine.js.map +1 -0
  46. package/dist/cli/command-palette.d.ts +26 -0
  47. package/dist/cli/command-palette.js +133 -0
  48. package/dist/cli/command-palette.js.map +1 -0
  49. package/dist/cli/context-health.d.ts +51 -0
  50. package/dist/cli/context-health.js +187 -0
  51. package/dist/cli/context-health.js.map +1 -0
  52. package/dist/cli/diamond.d.ts +67 -0
  53. package/dist/cli/diamond.js +222 -12
  54. package/dist/cli/diamond.js.map +1 -1
  55. package/dist/cli/dic.d.ts +2 -0
  56. package/dist/cli/dic.js +106 -0
  57. package/dist/cli/dic.js.map +1 -0
  58. package/dist/cli/diff-view.d.ts +18 -0
  59. package/dist/cli/diff-view.js +114 -0
  60. package/dist/cli/diff-view.js.map +1 -0
  61. package/dist/cli/display.d.ts +18 -4
  62. package/dist/cli/display.js +74 -151
  63. package/dist/cli/display.js.map +1 -1
  64. package/dist/cli/help-data.d.ts +7 -0
  65. package/dist/cli/help-data.js +80 -0
  66. package/dist/cli/help-data.js.map +1 -0
  67. package/dist/cli/index.js +1002 -852
  68. package/dist/cli/index.js.map +1 -1
  69. package/dist/cli/markdown.d.ts +5 -0
  70. package/dist/cli/markdown.js +128 -0
  71. package/dist/cli/markdown.js.map +1 -0
  72. package/dist/cli/model-select.d.ts +39 -0
  73. package/dist/cli/model-select.js +65 -0
  74. package/dist/cli/model-select.js.map +1 -0
  75. package/dist/cli/tui.d.ts +34 -0
  76. package/dist/cli/tui.js +1176 -0
  77. package/dist/cli/tui.js.map +1 -0
  78. package/dist/config/defaults.d.ts +6 -17
  79. package/dist/config/defaults.js +25 -46
  80. package/dist/config/defaults.js.map +1 -1
  81. package/dist/config/project-config.d.ts +2 -6
  82. package/dist/config/project-config.js +2 -2
  83. package/dist/config/project-config.js.map +1 -1
  84. package/dist/doctor/checks.d.ts +18 -0
  85. package/dist/doctor/checks.js +524 -0
  86. package/dist/doctor/checks.js.map +1 -0
  87. package/dist/doctor/index.d.ts +4 -0
  88. package/dist/doctor/index.js +229 -0
  89. package/dist/doctor/index.js.map +1 -0
  90. package/dist/doctor/repair.d.ts +19 -0
  91. package/dist/doctor/repair.js +126 -0
  92. package/dist/doctor/repair.js.map +1 -0
  93. package/dist/doctor/types.d.ts +38 -0
  94. package/dist/doctor/types.js +10 -0
  95. package/dist/doctor/types.js.map +1 -0
  96. package/dist/dream/dream.d.ts +79 -59
  97. package/dist/dream/dream.js +324 -144
  98. package/dist/dream/dream.js.map +1 -1
  99. package/dist/dream/episode.d.ts +17 -0
  100. package/dist/dream/episode.js +116 -0
  101. package/dist/dream/episode.js.map +1 -0
  102. package/dist/kanban/engine.d.ts +26 -0
  103. package/dist/kanban/engine.js +208 -0
  104. package/dist/kanban/engine.js.map +1 -0
  105. package/dist/kanban/types.d.ts +19 -0
  106. package/dist/kanban/types.js +9 -1
  107. package/dist/kanban/types.js.map +1 -1
  108. package/dist/machina/render-html.js +4 -2
  109. package/dist/machina/render-html.js.map +1 -1
  110. package/dist/machina/render-terminal.js +11 -4
  111. package/dist/machina/render-terminal.js.map +1 -1
  112. package/dist/machina/repair.d.ts +23 -0
  113. package/dist/machina/repair.js +98 -0
  114. package/dist/machina/repair.js.map +1 -0
  115. package/dist/machina/spec.js +12 -12
  116. package/dist/machina/spec.js.map +1 -1
  117. package/dist/machina/verify.d.ts +13 -1
  118. package/dist/machina/verify.js +12 -2
  119. package/dist/machina/verify.js.map +1 -1
  120. package/dist/mining/extract.d.ts +34 -0
  121. package/dist/mining/extract.js +229 -0
  122. package/dist/mining/extract.js.map +1 -0
  123. package/dist/mining/refine.d.ts +28 -0
  124. package/dist/mining/refine.js +256 -0
  125. package/dist/mining/refine.js.map +1 -0
  126. package/dist/perception/extractor.js +5 -3
  127. package/dist/perception/extractor.js.map +1 -1
  128. package/dist/perception/graph-store.d.ts +0 -11
  129. package/dist/perception/graph-store.js +0 -33
  130. package/dist/perception/graph-store.js.map +1 -1
  131. package/dist/perception/index.d.ts +1 -1
  132. package/dist/perception/index.js +1 -2
  133. package/dist/perception/index.js.map +1 -1
  134. package/dist/plugins/commands.d.ts +38 -0
  135. package/dist/plugins/commands.js +134 -0
  136. package/dist/plugins/commands.js.map +1 -0
  137. package/dist/plugins/frontmatter.d.ts +14 -0
  138. package/dist/plugins/frontmatter.js +78 -0
  139. package/dist/plugins/frontmatter.js.map +1 -0
  140. package/dist/plugins/hooks.d.ts +12 -0
  141. package/dist/plugins/hooks.js +148 -0
  142. package/dist/plugins/hooks.js.map +1 -0
  143. package/dist/plugins/loader.d.ts +7 -0
  144. package/dist/plugins/loader.js +255 -0
  145. package/dist/plugins/loader.js.map +1 -0
  146. package/dist/plugins/market.d.ts +23 -0
  147. package/dist/plugins/market.js +281 -0
  148. package/dist/plugins/market.js.map +1 -0
  149. package/dist/plugins/types.d.ts +90 -0
  150. package/dist/plugins/types.js +20 -0
  151. package/dist/plugins/types.js.map +1 -0
  152. package/dist/providers/anthropic-oauth-draft.d.ts +119 -0
  153. package/dist/providers/anthropic-oauth-draft.js +414 -0
  154. package/dist/providers/anthropic-oauth-draft.js.map +1 -0
  155. package/dist/providers/anthropic.d.ts +4 -1
  156. package/dist/providers/anthropic.js +35 -7
  157. package/dist/providers/anthropic.js.map +1 -1
  158. package/dist/providers/factory.d.ts +43 -19
  159. package/dist/providers/factory.js +183 -129
  160. package/dist/providers/factory.js.map +1 -1
  161. package/dist/providers/google.js +9 -22
  162. package/dist/providers/google.js.map +1 -1
  163. package/dist/providers/live-models.d.ts +23 -0
  164. package/dist/providers/live-models.js +145 -0
  165. package/dist/providers/live-models.js.map +1 -0
  166. package/dist/providers/openai-compatible.d.ts +1 -12
  167. package/dist/providers/openai-compatible.js +71 -108
  168. package/dist/providers/openai-compatible.js.map +1 -1
  169. package/dist/providers/resilient-factory.js +1 -1
  170. package/dist/providers/resilient-factory.js.map +1 -1
  171. package/dist/repl/queue.d.ts +22 -0
  172. package/dist/repl/queue.js +165 -0
  173. package/dist/repl/queue.js.map +1 -0
  174. package/dist/repl/side-channel.d.ts +23 -0
  175. package/dist/repl/side-channel.js +63 -0
  176. package/dist/repl/side-channel.js.map +1 -0
  177. package/dist/research/council.d.ts +2 -0
  178. package/dist/research/council.js +29 -4
  179. package/dist/research/council.js.map +1 -1
  180. package/dist/ruby/alternator.d.ts +11 -30
  181. package/dist/ruby/alternator.js +59 -38
  182. package/dist/ruby/alternator.js.map +1 -1
  183. package/dist/ruby/episode-capture.d.ts +0 -10
  184. package/dist/ruby/episode-capture.js +0 -33
  185. package/dist/ruby/episode-capture.js.map +1 -1
  186. package/dist/ruby/types.js +1 -1
  187. package/dist/ruby/types.js.map +1 -1
  188. package/dist/safety/path-jail.d.ts +17 -0
  189. package/dist/safety/path-jail.js +100 -0
  190. package/dist/safety/path-jail.js.map +1 -0
  191. package/dist/safety/permissions.d.ts +12 -21
  192. package/dist/safety/permissions.js +81 -216
  193. package/dist/safety/permissions.js.map +1 -1
  194. package/dist/safety/ssrf.d.ts +29 -0
  195. package/dist/safety/ssrf.js +185 -0
  196. package/dist/safety/ssrf.js.map +1 -0
  197. package/dist/server/index.js +64 -10
  198. package/dist/server/index.js.map +1 -1
  199. package/dist/setup/first-run.d.ts +0 -24
  200. package/dist/setup/first-run.js +10 -344
  201. package/dist/setup/first-run.js.map +1 -1
  202. package/dist/setup/key-store.d.ts +12 -0
  203. package/dist/setup/key-store.js +108 -0
  204. package/dist/setup/key-store.js.map +1 -0
  205. package/dist/setup/provider-registry.js +31 -18
  206. package/dist/setup/provider-registry.js.map +1 -1
  207. package/dist/setup/provider-test.d.ts +7 -0
  208. package/dist/setup/provider-test.js +73 -10
  209. package/dist/setup/provider-test.js.map +1 -1
  210. package/dist/setup/provider-wizard.d.ts +4 -1
  211. package/dist/setup/provider-wizard.js +92 -26
  212. package/dist/setup/provider-wizard.js.map +1 -1
  213. package/dist/setup/xiaomi.d.ts +1 -1
  214. package/dist/setup/xiaomi.js +3 -3
  215. package/dist/setup/xiaomi.js.map +1 -1
  216. package/dist/tools/browser.js +14 -10
  217. package/dist/tools/browser.js.map +1 -1
  218. package/dist/tools/clipboard.js +7 -1
  219. package/dist/tools/clipboard.js.map +1 -1
  220. package/dist/tools/dictate.d.ts +60 -0
  221. package/dist/tools/dictate.js +983 -0
  222. package/dist/tools/dictate.js.map +1 -0
  223. package/dist/tools/dictate_patched.js +1057 -0
  224. package/dist/tools/edit-file.js +10 -2
  225. package/dist/tools/edit-file.js.map +1 -1
  226. package/dist/tools/http-request.js +14 -4
  227. package/dist/tools/http-request.js.map +1 -1
  228. package/dist/tools/image-read.js +34 -2
  229. package/dist/tools/image-read.js.map +1 -1
  230. package/dist/tools/index.d.ts +16 -1
  231. package/dist/tools/index.js +59 -8
  232. package/dist/tools/index.js.map +1 -1
  233. package/dist/tools/mcp.js +12 -0
  234. package/dist/tools/mcp.js.map +1 -1
  235. package/dist/tools/read-file.js +10 -14
  236. package/dist/tools/read-file.js.map +1 -1
  237. package/dist/tools/telegram-audio-policy.d.ts +30 -0
  238. package/dist/tools/telegram-audio-policy.js +49 -0
  239. package/dist/tools/telegram-audio-policy.js.map +1 -0
  240. package/dist/tools/telegram-bot.js +1136 -537
  241. package/dist/tools/telegram-bot.js.map +1 -1
  242. package/dist/tools/telegram-voice.d.ts +18 -5
  243. package/dist/tools/telegram-voice.js +54 -12
  244. package/dist/tools/telegram-voice.js.map +1 -1
  245. package/dist/tools/telegram.d.ts +3 -3
  246. package/dist/tools/telegram.js +5 -84
  247. package/dist/tools/telegram.js.map +1 -1
  248. package/dist/tools/tools.d.ts +2 -14
  249. package/dist/tools/tools.js +79 -144
  250. package/dist/tools/tools.js.map +1 -1
  251. package/dist/tools/web-fetch.js +39 -7
  252. package/dist/tools/web-fetch.js.map +1 -1
  253. package/dist/tools/web-search.d.ts +0 -20
  254. package/dist/tools/web-search.js +40 -137
  255. package/dist/tools/web-search.js.map +1 -1
  256. package/dist/util/errors.js +1 -15
  257. package/dist/util/errors.js.map +1 -1
  258. package/dist/util/json-repair.d.ts +11 -0
  259. package/dist/util/json-repair.js +31 -0
  260. package/dist/util/json-repair.js.map +1 -0
  261. package/dist/util/rate-limiter.js +2 -8
  262. package/dist/util/rate-limiter.js.map +1 -1
  263. package/dist/viz/index.js +793 -792
  264. package/dist/viz/index.js.map +1 -1
  265. package/package.json +12 -32
@@ -0,0 +1,22 @@
1
+ import type { LLMProvider } from '../providers/types.js';
2
+ import type { ProjectContext } from '../agent/context.js';
3
+ import { createTerminalDisplay } from '../cli/display.js';
4
+ import { PermissionSystem } from '../safety/permissions.js';
5
+ export interface QueueItem {
6
+ id: string;
7
+ prompt: string;
8
+ createdAt: number;
9
+ status: 'pending' | 'running' | 'done' | 'failed';
10
+ }
11
+ export declare function loadQueue(): QueueItem[];
12
+ export declare function addToQueue(prompt: string): QueueItem;
13
+ export declare function removeFromQueue(index: number): QueueItem | null;
14
+ export declare function clearQueue(): number;
15
+ export interface QueueRunResult {
16
+ success: boolean;
17
+ output: string;
18
+ turns: number;
19
+ toolCalls: number;
20
+ }
21
+ export declare function runQueueItem(index: number, provider: LLMProvider, ctx: ProjectContext, permissions: PermissionSystem, display: ReturnType<typeof createTerminalDisplay>): Promise<QueueRunResult | null>;
22
+ export declare function formatQueue(items: QueueItem[]): string;
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.loadQueue = loadQueue;
40
+ exports.addToQueue = addToQueue;
41
+ exports.removeFromQueue = removeFromQueue;
42
+ exports.clearQueue = clearQueue;
43
+ exports.runQueueItem = runQueueItem;
44
+ exports.formatQueue = formatQueue;
45
+ /**
46
+ * :q — Persistent task queue for the REPL.
47
+ *
48
+ * Stores tasks in ~/.aura/queue.jsonl (append-only, atomic .tmp+rename on mutations).
49
+ * Each line is a JSON object with { id, prompt, createdAt, status }.
50
+ *
51
+ * Commands (dispatched from cli/index.ts):
52
+ * :q add <prompt> — enqueue a task
53
+ * :q list — show all items with index
54
+ * :q run <n> — execute item n in a fresh agent loop
55
+ * :q drop <n> — remove item n
56
+ * :q clear — wipe the queue (with confirmation)
57
+ */
58
+ const fs = __importStar(require("fs"));
59
+ const path = __importStar(require("path"));
60
+ const os = __importStar(require("os"));
61
+ const crypto = __importStar(require("crypto"));
62
+ const chalk_1 = __importDefault(require("chalk"));
63
+ const loop_js_1 = require("../agent/loop.js");
64
+ // ── Storage ─────────────────────────────────────────────────────────────────
65
+ function queuePath() {
66
+ return path.join(os.homedir(), '.aura', 'queue.jsonl');
67
+ }
68
+ function loadQueue() {
69
+ const p = queuePath();
70
+ if (!fs.existsSync(p))
71
+ return [];
72
+ const raw = fs.readFileSync(p, 'utf8').trim();
73
+ if (!raw)
74
+ return [];
75
+ return raw.split('\n').map(line => JSON.parse(line));
76
+ }
77
+ function saveQueue(items) {
78
+ const p = queuePath();
79
+ const tmp = p + '.tmp';
80
+ const data = items.map(i => JSON.stringify(i)).join('\n') + '\n';
81
+ fs.writeFileSync(tmp, data, 'utf8');
82
+ fs.renameSync(tmp, p);
83
+ }
84
+ function addToQueue(prompt) {
85
+ const items = loadQueue();
86
+ const item = {
87
+ id: crypto.randomUUID().slice(0, 8),
88
+ prompt,
89
+ createdAt: Date.now(),
90
+ status: 'pending',
91
+ };
92
+ // Append a single line (atomic enough — .tmp+rename on the whole file is done in saveQueue)
93
+ items.push(item);
94
+ saveQueue(items);
95
+ return item;
96
+ }
97
+ function removeFromQueue(index) {
98
+ const items = loadQueue();
99
+ if (index < 0 || index >= items.length)
100
+ return null;
101
+ const removed = items.splice(index, 1)[0];
102
+ saveQueue(items);
103
+ return removed;
104
+ }
105
+ function clearQueue() {
106
+ const count = loadQueue().length;
107
+ saveQueue([]);
108
+ return count;
109
+ }
110
+ async function runQueueItem(index, provider, ctx, permissions, display) {
111
+ const items = loadQueue();
112
+ if (index < 0 || index >= items.length)
113
+ return null;
114
+ const item = items[index];
115
+ item.status = 'running';
116
+ saveQueue(items);
117
+ try {
118
+ // Run a fresh agent loop for this task.
119
+ const result = await (0, loop_js_1.runAgentLoop)({
120
+ provider,
121
+ task: item.prompt,
122
+ context: ctx,
123
+ permissions,
124
+ display,
125
+ maxTurns: 25,
126
+ });
127
+ item.status = result.success ? 'done' : 'failed';
128
+ saveQueue(items);
129
+ return {
130
+ success: result.success,
131
+ output: result.summary,
132
+ turns: result.turns ?? 0,
133
+ toolCalls: result.toolCallCount ?? 0,
134
+ };
135
+ }
136
+ catch (err) {
137
+ item.status = 'failed';
138
+ saveQueue(items);
139
+ return {
140
+ success: false,
141
+ output: String(err),
142
+ turns: 0,
143
+ toolCalls: 0,
144
+ };
145
+ }
146
+ }
147
+ // ── Formatting (for REPL display) ───────────────────────────────────────────
148
+ function formatQueue(items) {
149
+ if (items.length === 0)
150
+ return chalk_1.default.hex('#8a7768')('\n Queue is empty. Use :q add <prompt> to enqueue a task.\n');
151
+ const lines = items.map((item, i) => {
152
+ const statusColor = {
153
+ pending: '#8a7768',
154
+ running: '#d4903a',
155
+ done: '#5a9e6e',
156
+ failed: '#b15439',
157
+ };
158
+ const color = statusColor[item.status] || '#8a7768';
159
+ const statusIcon = item.status === 'done' ? '✓' : item.status === 'running' ? '⟳' : item.status === 'failed' ? '✗' : '·';
160
+ const created = new Date(item.createdAt).toLocaleTimeString();
161
+ return ` ${chalk_1.default.hex('#cc785c')(String(i + 1).padEnd(3))} ${chalk_1.default.hex(color)(statusIcon)} ${chalk_1.default.hex('#ede0cc')(item.prompt.slice(0, 80))} ${chalk_1.default.hex('#4e3d30')(created)}`;
162
+ });
163
+ return `\n${lines.join('\n')}\n`;
164
+ }
165
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/repl/queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * :btw — Side channel for non-blocking parallel questions.
3
+ *
4
+ * Spawns an isolated LLM call (no session history, read-only) to answer
5
+ * a quick question while the main task keeps running. The answer is
6
+ * rendered as a simple overlay and never appears in chat history.
7
+ */
8
+ import type { LLMProvider } from '../providers/types.js';
9
+ import type { ProjectContext } from '../agent/context.js';
10
+ export interface BtwResult {
11
+ answer: string;
12
+ tokens: number;
13
+ }
14
+ /**
15
+ * Run a :btw query in the current provider but with a clean (empty) chat
16
+ * history — strictly a read-only knowledge question.
17
+ */
18
+ export declare function runBtwQuery(question: string, provider: LLMProvider, ctx: ProjectContext): Promise<BtwResult>;
19
+ /**
20
+ * Render a :btw answer as a minimalist overlay box.
21
+ * Returns an object with the rendered lines + a dismiss instruction.
22
+ */
23
+ export declare function renderBtwAnswer(answer: string, tokens: number): string;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runBtwQuery = runBtwQuery;
7
+ exports.renderBtwAnswer = renderBtwAnswer;
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const BTW_SYSTEM_PROMPT = `You are Aura's "by the way" side channel.
10
+ Answer the user's quick question concisely in 2-4 sentences.
11
+ Do NOT use tools. Do NOT write code. Just answer from knowledge.
12
+ If you don't know, say so briefly.`;
13
+ /**
14
+ * Run a :btw query in the current provider but with a clean (empty) chat
15
+ * history — strictly a read-only knowledge question.
16
+ */
17
+ async function runBtwQuery(question, provider, ctx) {
18
+ const stream = provider.stream(BTW_SYSTEM_PROMPT, [
19
+ { role: 'user', content: `:btw ${question}` },
20
+ ], []);
21
+ let answer = '';
22
+ let totalTokens = 0;
23
+ for await (const chunk of stream) {
24
+ if (chunk.type === 'text') {
25
+ answer += chunk.text;
26
+ }
27
+ else if (chunk.type === 'done') {
28
+ const usage = chunk.response.usage;
29
+ if (usage)
30
+ totalTokens = usage.inputTokens + usage.outputTokens;
31
+ }
32
+ }
33
+ return { answer: answer.trim(), tokens: totalTokens };
34
+ }
35
+ /**
36
+ * Render a :btw answer as a minimalist overlay box.
37
+ * Returns an object with the rendered lines + a dismiss instruction.
38
+ */
39
+ function renderBtwAnswer(answer, tokens) {
40
+ const maxWidth = 60;
41
+ const lines = [];
42
+ for (const word of answer.split(' ')) {
43
+ const last = lines[lines.length - 1];
44
+ if (!last || last.length + word.length + 1 > maxWidth) {
45
+ lines.push(word);
46
+ }
47
+ else {
48
+ lines[lines.length - 1] = last + ' ' + word;
49
+ }
50
+ }
51
+ const top = chalk_1.default.hex('#cc785c')(' ┌' + '─'.repeat(maxWidth + 2) + '┐');
52
+ const bottom = chalk_1.default.hex('#cc785c')(' └' + '─'.repeat(maxWidth + 2) + '┘');
53
+ const body = lines.map(l => chalk_1.default.hex('#ede0cc')(' │ ') + l.padEnd(maxWidth) + chalk_1.default.hex('#cc785c')(' │'));
54
+ return [
55
+ '',
56
+ top,
57
+ ...body,
58
+ bottom,
59
+ chalk_1.default.hex('#4e3d30')(` ⚡ ${tokens} tokens — press ENTER to dismiss`),
60
+ '',
61
+ ].join('\n');
62
+ }
63
+ //# sourceMappingURL=side-channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"side-channel.js","sourceRoot":"","sources":["../../src/repl/side-channel.ts"],"names":[],"mappings":";;;;;AAyBA,kCAqBC;AAMD,0CAwBC;AAnED,kDAA0B;AAE1B,MAAM,iBAAiB,GAAG;;;mCAGS,CAAC;AAOpC;;;GAGG;AACI,KAAK,UAAU,WAAW,CAC/B,QAAgB,EAChB,QAAqB,EACrB,GAAmB;IAEnB,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE;QAChD,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,QAAQ,EAAE,EAAE;KAC9C,EAAE,EAAE,CAAC,CAAC;IACP,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC;QACvB,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;YACnC,IAAI,KAAK;gBAAE,WAAW,GAAG,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,YAAY,CAAC;QAClE,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe,CAAC,MAAc,EAAE,MAAc;IAC5D,MAAM,QAAQ,GAAG,EAAE,CAAC;IACpB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,QAAQ,EAAE,CAAC;YACtD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAM,eAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,eAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAK,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,eAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,eAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAE9G,OAAO;QACL,EAAE;QACF,GAAG;QACH,GAAG,IAAI;QACP,MAAM;QACN,eAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,MAAM,kCAAkC,CAAC;QACrE,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -24,4 +24,6 @@ export declare function runCouncil(opts: {
24
24
  display: Display;
25
25
  panelSize?: number;
26
26
  panelModel?: string;
27
+ /** The session's configured routing model id (e.g. "deepseek/deepseek-v4-flash"). */
28
+ configuredModel?: string;
27
29
  }): Promise<CouncilResult>;
@@ -187,13 +187,19 @@ ${bodyHtml}
187
187
  * passing `undefined` to `createProvider` (which historically produced
188
188
  * opaque "400 Not supported model" errors).
189
189
  */
190
- function resolvePanelModel(synthesisProvider, override) {
190
+ function resolvePanelModel(synthesisProvider, override, configuredModel) {
191
191
  if (override && override.trim())
192
192
  return override.trim();
193
193
  const env = process.env.AURA_PANEL_MODEL;
194
194
  if (env && env.trim())
195
195
  return env.trim();
196
- // LLMProvider.model the configured model id for that provider instance.
196
+ // The caller's configured routing id (e.g. "deepseek/deepseek-v4-flash").
197
+ // Preferred over the provider instance's `.model`, which has the provider
198
+ // prefix stripped ("deepseek-v4-flash") and therefore re-resolves through
199
+ // the generic OpenAI-compatible provider — the wrong endpoint entirely
200
+ // (this produced five identical 401s on the first live Ecclesia run).
201
+ if (configuredModel && configuredModel.trim())
202
+ return configuredModel.trim();
197
203
  const fromProvider = synthesisProvider.model;
198
204
  if (fromProvider && fromProvider.trim())
199
205
  return fromProvider.trim();
@@ -208,7 +214,7 @@ function resolvePanelModel(synthesisProvider, override) {
208
214
  async function runCouncil(opts) {
209
215
  const { projectRoot, topic, synthesisProvider, context, permissions, display, } = opts;
210
216
  const panelSize = Math.max(1, opts.panelSize ?? DEFAULT_PANEL_SIZE);
211
- const panelModel = resolvePanelModel(synthesisProvider, opts.panelModel);
217
+ const panelModel = resolvePanelModel(synthesisProvider, opts.panelModel, opts.configuredModel);
212
218
  const findings = [];
213
219
  let agentFailures = 0;
214
220
  // Sequential by design — see module doc. Each agent is independent: no
@@ -225,7 +231,26 @@ async function runCouncil(opts) {
225
231
  maxTurns: 6,
226
232
  disableSpawn: true,
227
233
  });
228
- const text = (res.summary ?? '').trim();
234
+ let text = (res.summary ?? '').trim();
235
+ if (!res.success || /^Loop (ended|stalled)/i.test(text)) {
236
+ // The agent hit its turn cap (or stalled) before a final answer, so
237
+ // summary is just the loop-end marker. Salvage its last real message
238
+ // instead — feeding "Loop ended after 6 turns." to the synthesis
239
+ // makes the model fabricate an entire council from nothing (observed
240
+ // live: invented "3 of 5 agents" splits and fictional sources).
241
+ const lastAssistant = [...res.history].reverse().find((m) => m.role === 'assistant' && typeof m.content === 'string' && m.content.trim().length > 0);
242
+ text = lastAssistant?.content.trim() ?? '';
243
+ }
244
+ if (!text) {
245
+ // Tool-happy models (observed: DeepSeek) spend every turn on tool
246
+ // calls and never write prose, so there is nothing to salvage.
247
+ // Convert the research they DID gather into findings with one
248
+ // tool-less completion over their own history.
249
+ const wrap = await panelProvider.complete('Your tool budget is exhausted. Using ONLY what you already gathered in this conversation, ' +
250
+ 'write the findings now in the requested format: 4-8 specific bullet points with sources in ' +
251
+ 'parentheses, then one line "Stance: <bottom-line take>". Do not call tools. No preamble.', [...res.history, { role: 'user', content: 'Tool budget exhausted — write your findings list and stance NOW.' }], []);
252
+ text = (wrap.text ?? '').trim();
253
+ }
229
254
  findings.push(text || `(Agent ${seat} returned no findings.)`);
230
255
  }
231
256
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"council.js","sourceRoot":"","sources":["../../src/research/council.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"council.js","sourceRoot":"","sources":["../../src/research/council.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkNA,gCAqGC;AAvTD,uCAAyB;AACzB,2CAA6B;AAC7B,mCAAgC;AAChC,8CAAgD;AAChD,wDAAyD;AAMzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,eAAe,GAAG,SAAS,CAAC;AAClC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,MAAM,GAAG,yEAAyE,CAAC;AAEzF,SAAS,UAAU,CAAC,WAAmB;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,OAAO,CAAC,KAAa;IAC5B,OAAO,KAAK;SACT,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC;AAC7B,CAAC;AAED,SAAS,cAAc,CAAC,KAAa,EAAE,IAAY,EAAE,SAAiB;IACpE,OAAO,CACL,sBAAsB,IAAI,OAAO,SAAS,uDAAuD,KAAK,OAAO;QAC7G,2FAA2F;QAC3F,iEAAiE;QACjE,kGAAkG;QAClG,gGAAgG;QAChG,yEAAyE;QACzE,mFAAmF,CACpF,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa,EAAE,QAAkB;IAC7D,MAAM,MAAM,GACV,yFAAyF;QACzF,GAAG,QAAQ,CAAC,MAAM,6EAA6E;QAC/F,8FAA8F;QAC9F,eAAe;QACf,oGAAoG;QACpG,4GAA4G;QAC5G,+BAA+B;QAC/B,0HAA0H;QAC1H,2GAA2G;QAC3G,2CAA2C;QAC3C,oEAAoE,CAAC;IACvE,MAAM,IAAI,GACR,UAAU,KAAK,MAAM;QACrB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC1B,CAAC;AAED,SAAS,QAAQ,CAAC,EAAU;IAC1B,eAAM,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,OAAO,eAAM,CAAC,KAAK,CAAC,EAAE,CAAW,CAAC;AACpC,CAAC;AAED,SAAS,QAAQ,CAAC,KAAa,EAAE,QAAgB,EAAE,IAAY,EAAE,SAAiB;IAChF,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACxH,OAAO;;;;;SAKA,GAAG,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CA4CwB,SAAS;UAC1C,GAAG,CAAC,KAAK,CAAC;wBACI,IAAI;;;EAG1B,QAAQ;;;;;QAKF,CAAC;AACT,CAAC;AAWD;;;;;;;;;;;;;GAaG;AACH,SAAS,iBAAiB,CACxB,iBAA8B,EAC9B,QAAiB,EACjB,eAAwB;IAExB,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE;QAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IAExD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACzC,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IAEzC,0EAA0E;IAC1E,0EAA0E;IAC1E,0EAA0E;IAC1E,uEAAuE;IACvE,sEAAsE;IACtE,IAAI,eAAe,IAAI,eAAe,CAAC,IAAI,EAAE;QAAE,OAAO,eAAe,CAAC,IAAI,EAAE,CAAC;IAE7E,MAAM,YAAY,GAAI,iBAAmD,CAAC,KAAK,CAAC;IAChF,IAAI,YAAY,IAAI,YAAY,CAAC,IAAI,EAAE;QAAE,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC;IAEpE,MAAM,IAAI,KAAK,CACb,yDAAyD;QACzD,oEAAoE,CACrE,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACI,KAAK,UAAU,UAAU,CAAC,IAWhC;IACC,MAAM,EACJ,WAAW,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,GACrE,GAAG,IAAI,CAAC;IACT,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,iBAAiB,CAAC,iBAAiB,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IAE/F,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,uEAAuE;IACvE,uEAAuE;IACvE,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,IAAA,2BAAc,EAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;YAC5D,MAAM,GAAG,GAAG,MAAM,IAAA,sBAAY,EAAC;gBAC7B,QAAQ,EAAE,aAAa;gBACvB,IAAI,EAAE,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC;gBAC5C,OAAO;gBACP,WAAW;gBACX,OAAO;gBACP,QAAQ,EAAE,CAAC;gBACX,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;YACH,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxD,oEAAoE;gBACpE,qEAAqE;gBACrE,iEAAiE;gBACjE,qEAAqE;gBACrE,gEAAgE;gBAChE,MAAM,aAAa,GAAG,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CACnD,CAAC,CAAC,EAA+C,EAAE,CACjD,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CACzF,CAAC;gBACF,IAAI,GAAG,aAAa,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;YAC7C,CAAC;YACD,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,kEAAkE;gBAClE,+DAA+D;gBAC/D,8DAA8D;gBAC9D,+CAA+C;gBAC/C,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,QAAQ,CACvC,4FAA4F;oBAC5F,6FAA6F;oBAC7F,0FAA0F,EAC1F,CAAC,GAAG,GAAG,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kEAAkE,EAAE,CAAC,EAC/G,EAAE,CACH,CAAC;gBACF,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAClC,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,UAAU,IAAI,yBAAyB,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,aAAa,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC,UAAU,IAAI,YAAY,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC/D,IAAI,WAAmB,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9F,WAAW,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW;YACT,8CAA8C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO;gBACrG,gFAAgF;gBAChF,gDAAgD,SAAS,8EAA8E,CAAC;IAC5I,CAAC;IAED,MAAM,kBAAkB,GACtB,sCAAsC;QACtC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEpE,MAAM,EAAE,GAAG,eAAe,KAAK,OAAO,WAAW,GAAG,kBAAkB,KAAK,MAAM,EAAE,CAAC;IAEpF,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACpC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAE5B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,IAAI,KAAK,CAAC,CAAC;IACpD,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE7B,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,WAAW,GAAG,kBAAkB,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAClG,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,IAAI,OAAO,CAAC,CAAC;IACxD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEpC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;AACjF,CAAC"}
@@ -1,6 +1,5 @@
1
- import type { LLMProvider } from '../providers/types.js';
2
- import type { HistoryMessage } from '../providers/types.js';
3
- import type { LoopResult } from '../agent/loop.js';
1
+ import type { HistoryMessage, LLMProvider } from '../providers/types.js';
2
+ import { type LoopResult } from '../agent/loop.js';
4
3
  import type { ProjectContext } from '../agent/context.js';
5
4
  import { PermissionSystem } from '../safety/permissions.js';
6
5
  import type { Display } from '../cli/display.js';
@@ -15,39 +14,21 @@ export interface AlternatorOptions {
15
14
  /** When set, routing and loop events are surfaced to the user. */
16
15
  display?: Display;
17
16
  /**
18
- * The permission system governing the user's actual session. Pass this
19
- * through from the caller so Ruby's attempt respects whatever mode the
20
- * user chose (read-only / normal / auto) without it, this previously
21
- * defaulted to a hardcoded 'auto', meaning destructive operations could
22
- * get silently approved during the Ruby attempt even in a session the
23
- * user explicitly ran in confirmation-required 'normal' mode.
17
+ * The session's permission system. When omitted, defaults to the safe
18
+ * 'normal' level NEVER 'auto': the Ruby attempt must not auto-approve
19
+ * destructive operations the user's chosen mode would have prompted for.
24
20
  */
25
21
  permissions?: PermissionSystem;
26
- /**
27
- * Confirmation callback for destructive operations, passed through to
28
- * both the Ruby attempt and the large-model escalation. Pass the same
29
- * one the caller already uses (e.g. the REPL's readline-based prompt) —
30
- * without it, each inner loop falls back to its own default terminal
31
- * confirm(), which can behave inconsistently alongside an already-active
32
- * readline interface.
33
- */
22
+ /** Confirmation prompt for needs-confirm tool calls, threaded into the loop. */
34
23
  confirmFn?: (message: string) => Promise<boolean>;
35
- /**
36
- * Prior conversation history to resume from (e.g. the REPL's stay-active
37
- * history, or a loaded session). Without this, every Ruby-alternated
38
- * turn would silently start fresh, breaking multi-turn conversation
39
- * continuation any time alternation activates mid-conversation.
40
- */
24
+ /** Prior conversation history (multi-turn REPL), threaded into the loop. */
41
25
  initialHistory?: HistoryMessage[];
42
26
  }
43
27
  export interface AlternatorRunResult {
44
- /**
45
- * The full result from whichever path actually produced the final
46
- * output Ruby's if it succeeded without escalation, otherwise the
47
- * large model's. Treat this exactly like a normal runAgentLoop() result:
48
- * history, costUsd, turns, and toolCallLog are all populated correctly
49
- * from whichever path ran, so callers don't need special-case handling.
50
- */
28
+ /** Final user-facing output text (loopResult.summary, or an error note). */
29
+ result: string;
30
+ /** The full LoopResult from whichever model handled the task. Never undefined —
31
+ * a safe empty result is substituted when every path failed. */
51
32
  loopResult: LoopResult;
52
33
  episode: Episode;
53
34
  usedRuby: boolean;
@@ -7,6 +7,19 @@ const loop_js_1 = require("../agent/loop.js");
7
7
  const permissions_js_1 = require("../safety/permissions.js");
8
8
  const competence_js_1 = require("./competence.js");
9
9
  const episode_capture_js_1 = require("./episode-capture.js");
10
+ /** Inert LoopResult for the both-paths-failed case — run() never throws. */
11
+ function emptyLoopResult(summary) {
12
+ return {
13
+ success: false,
14
+ summary,
15
+ turns: 0,
16
+ toolCallCount: 0,
17
+ usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
18
+ costUsd: 0,
19
+ history: [],
20
+ toolCallLog: [],
21
+ };
22
+ }
10
23
  const RECENT_EPISODE_LIMIT = 50;
11
24
  const OLLAMA_PING_MS = 3_000;
12
25
  // ─────────────────────────────────────────────────────────────────────────────
@@ -29,6 +42,9 @@ function createNoopDisplay() {
29
42
  showPlan: () => { },
30
43
  stepStarted: () => { },
31
44
  stepCompleted: () => { },
45
+ contextBar: () => { },
46
+ contextDashboard: () => { },
47
+ compactionEvent: () => { },
32
48
  };
33
49
  }
34
50
  // ─────────────────────────────────────────────────────────────────────────────
@@ -101,7 +117,6 @@ class RubyAlternator {
101
117
  async run(task) {
102
118
  const startMs = Date.now();
103
119
  const { rubyConfig, largeModelProvider, projectRoot, context } = this.opts;
104
- const confirmFn = this.opts.confirmFn;
105
120
  let decision = {
106
121
  useRuby: false,
107
122
  reason: 'Initializing alternation.',
@@ -110,12 +125,13 @@ class RubyAlternator {
110
125
  };
111
126
  let rubyAttempted = false;
112
127
  let rubySucceeded = false;
113
- let rubyLoopResult;
114
- let largeModelLoopResult;
128
+ let rubyOutput;
129
+ let rubyTokens = 0;
130
+ let largeModelOutput;
131
+ let largeModelTokens = 0;
115
132
  let usedRuby = false;
116
- // Only used to build the error-path fallback LoopResult below; the
117
- // success paths read everything from rubyLoopResult/largeModelLoopResult.
118
- let errorSummary;
133
+ let result = '';
134
+ let finalLoopResult;
119
135
  try {
120
136
  const recent = await episode_capture_js_1.episodeStore.loadEpisodes(projectRoot, RECENT_EPISODE_LIMIT);
121
137
  decision = (0, competence_js_1.assessCompetence)(recent, task, rubyConfig);
@@ -131,20 +147,24 @@ class RubyAlternator {
131
147
  this.display.success(`Trying Ruby (${rubyConfig.modelName})…`);
132
148
  try {
133
149
  const rubyProvider = buildRubyProvider(rubyConfig);
134
- rubyLoopResult = await (0, loop_js_1.runAgentLoop)({
150
+ const loopResult = await (0, loop_js_1.runAgentLoop)({
135
151
  provider: rubyProvider,
136
152
  task,
137
153
  context,
138
154
  permissions: this.permissions,
139
155
  display: this.display,
140
- confirmFn,
141
- initialHistory: this.opts.initialHistory,
142
156
  disableSpawn: true,
143
157
  maxTurns: 15,
158
+ confirmFn: this.opts.confirmFn,
159
+ initialHistory: this.opts.initialHistory,
144
160
  });
145
- if (isNonEmptyResult(rubyLoopResult.summary) && rubyLoopResult.success) {
161
+ rubyTokens = loopResult.usage.totalTokens;
162
+ rubyOutput = loopResult.summary;
163
+ if (isNonEmptyResult(rubyOutput) && loopResult.success) {
146
164
  rubySucceeded = true;
147
165
  usedRuby = true;
166
+ result = rubyOutput;
167
+ finalLoopResult = loopResult;
148
168
  this.display.success('Ruby handled the task without escalation.');
149
169
  }
150
170
  else {
@@ -153,48 +173,43 @@ class RubyAlternator {
153
173
  }
154
174
  catch (e) {
155
175
  this.display.warning(`Ruby error: ${String(e)} — escalating.`);
176
+ rubyOutput = rubyOutput ?? `Error: ${String(e)}`;
156
177
  }
157
178
  }
158
179
  }
159
180
  if (!usedRuby) {
160
181
  this.display.header('Large model', largeModelProvider.name);
161
182
  try {
162
- largeModelLoopResult = await (0, loop_js_1.runAgentLoop)({
183
+ const loopResult = await (0, loop_js_1.runAgentLoop)({
163
184
  provider: largeModelProvider,
164
185
  task,
165
186
  context,
166
187
  permissions: this.permissions,
167
188
  display: this.display,
168
- confirmFn,
169
- initialHistory: this.opts.initialHistory,
170
189
  disableSpawn: true,
190
+ confirmFn: this.opts.confirmFn,
191
+ initialHistory: this.opts.initialHistory,
171
192
  });
193
+ largeModelTokens = loopResult.usage.totalTokens;
194
+ largeModelOutput = loopResult.summary;
195
+ finalLoopResult = loopResult;
196
+ result = isNonEmptyResult(largeModelOutput)
197
+ ? largeModelOutput
198
+ : loopResult.success
199
+ ? '(Task completed with no output)'
200
+ : `Large model did not complete: ${loopResult.summary}`;
172
201
  }
173
202
  catch (e) {
174
- errorSummary = `Large model error: ${String(e)}`;
175
- this.display.error(errorSummary);
203
+ result = `Large model error: ${String(e)}`;
204
+ largeModelOutput = result;
205
+ this.display.error(result);
176
206
  }
177
207
  }
178
208
  }
179
209
  catch (e) {
180
- errorSummary = `Alternation error: ${String(e)}`;
181
- this.display.error(errorSummary);
210
+ result = `Alternation error: ${String(e)}`;
211
+ this.display.error(result);
182
212
  }
183
- // The full result that actually represents this run's output — Ruby's
184
- // if it succeeded, otherwise the large model's, otherwise a safe empty
185
- // result for the case where something threw before either path ran.
186
- const finalLoopResult = usedRuby
187
- ? rubyLoopResult
188
- : largeModelLoopResult ?? {
189
- success: false,
190
- summary: errorSummary ?? 'Alternation failed before either model ran.',
191
- turns: 0,
192
- toolCallCount: 0,
193
- usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
194
- costUsd: 0,
195
- history: [],
196
- toolCallLog: [],
197
- };
198
213
  const episode = {
199
214
  id: (0, crypto_1.randomUUID)(),
200
215
  timestamp: Date.now(),
@@ -202,13 +217,13 @@ class RubyAlternator {
202
217
  projectRoot,
203
218
  rubyAttempted,
204
219
  rubySucceeded,
205
- rubyOutput: rubyLoopResult?.summary,
220
+ rubyOutput,
206
221
  largeModelUsed: usedRuby ? undefined : largeModelProvider.model,
207
- largeModelOutput: usedRuby ? undefined : largeModelLoopResult?.summary,
208
- reviewerApproved: isNonEmptyResult(finalLoopResult.summary) && finalLoopResult.success,
222
+ largeModelOutput: usedRuby ? undefined : largeModelOutput,
223
+ reviewerApproved: isNonEmptyResult(result),
209
224
  tokensUsed: {
210
- ruby: rubyAttempted ? rubyLoopResult?.usage.totalTokens : undefined,
211
- largeModel: usedRuby ? undefined : largeModelLoopResult?.usage.totalTokens,
225
+ ruby: rubyAttempted ? rubyTokens : undefined,
226
+ largeModel: usedRuby ? undefined : largeModelTokens,
212
227
  },
213
228
  durationMs: Date.now() - startMs,
214
229
  taskCategory: inferTaskCategory(task),
@@ -228,7 +243,13 @@ class RubyAlternator {
228
243
  catch {
229
244
  /* best-effort */
230
245
  }
231
- return { loopResult: finalLoopResult, episode, usedRuby, decision };
246
+ return {
247
+ result,
248
+ loopResult: finalLoopResult ?? emptyLoopResult(result),
249
+ episode,
250
+ usedRuby,
251
+ decision,
252
+ };
232
253
  }
233
254
  /**
234
255
  * Returns aggregate episode statistics for this alternator's project.