compact-agent 1.22.0 → 1.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.d.ts CHANGED
@@ -2,7 +2,18 @@ import OpenAI from 'openai';
2
2
  import type { CrowcoderConfig, Message } from './types.js';
3
3
  import type { Tool } from './tools/types.js';
4
4
  export declare function getClient(config: CrowcoderConfig): OpenAI;
5
+ /**
6
+ * Same as getClient but explicitly reports the active key in use, so
7
+ * callers (streamChat) can attribute success/failure back to the
8
+ * specific key for rotation health-tracking.
9
+ */
10
+ export declare function getClientWithKey(config: CrowcoderConfig): {
11
+ client: OpenAI;
12
+ activeKey: string;
13
+ };
5
14
  export declare function resetClient(): void;
15
+ /** Re-export so callers (index.ts /keys) can introspect pool status. */
16
+ export { reportFailure, reportSuccess, poolSize } from './key-rotation.js';
6
17
  export declare function toolsToFunctions(tools: Tool[]): OpenAI.Chat.ChatCompletionTool[];
7
18
  export declare function streamChat(config: CrowcoderConfig, messages: Message[], tools: Tool[], signal?: AbortSignal): AsyncGenerator<{
8
19
  type: 'text' | 'thinking' | 'tool_call' | 'done';
package/dist/api.js CHANGED
@@ -1,32 +1,63 @@
1
1
  import OpenAI from 'openai';
2
2
  import { withRetry } from './retry.js';
3
+ import { setPool, pickKey, reportFailure, reportSuccess, poolSize } from './key-rotation.js';
3
4
  let client = null;
4
5
  let lastConfigHash = '';
6
+ let lastClientKey = ''; // which key the current client was built with
5
7
  function configHash(config) {
6
- return `${config.baseURL}:${config.apiKey}`;
8
+ // The client cache key depends on the CURRENT pool key, not the config
9
+ // apiKey, so a rotation picks a fresh client without re-checking config.
10
+ const poolKeys = (config.apiKeys || []).join(',');
11
+ return `${config.baseURL}:${config.apiKey}:${poolKeys}`;
12
+ }
13
+ /**
14
+ * Sync the rotation pool with the latest config. Called from getClient
15
+ * on every request so /config or env-var changes flow through.
16
+ */
17
+ function syncPool(config) {
18
+ setPool(config.apiKey, config.apiKeys || []);
7
19
  }
8
20
  export function getClient(config) {
21
+ syncPool(config);
22
+ // Pick the current key from the pool (round-robin, skipping cool keys).
23
+ // Falls back to config.apiKey when the pool is empty or all keys are
24
+ // cool — the original request will fail with a clear error in that
25
+ // case, which is the right behavior.
26
+ const activeKey = pickKey() || config.apiKey;
9
27
  const hash = configHash(config);
10
- if (!client || hash !== lastConfigHash) {
28
+ if (!client || hash !== lastConfigHash || activeKey !== lastClientKey) {
11
29
  const isAnthropic = config.baseURL.includes('anthropic.com');
12
30
  client = new OpenAI({
13
- apiKey: config.apiKey || 'not-needed',
31
+ apiKey: activeKey || 'not-needed',
14
32
  baseURL: config.baseURL,
15
33
  ...(isAnthropic ? {
16
34
  defaultHeaders: {
17
- 'x-api-key': config.apiKey,
35
+ 'x-api-key': activeKey,
18
36
  'anthropic-version': '2023-06-01',
19
37
  },
20
38
  } : {}),
21
39
  });
22
40
  lastConfigHash = hash;
41
+ lastClientKey = activeKey;
23
42
  }
24
43
  return client;
25
44
  }
45
+ /**
46
+ * Same as getClient but explicitly reports the active key in use, so
47
+ * callers (streamChat) can attribute success/failure back to the
48
+ * specific key for rotation health-tracking.
49
+ */
50
+ export function getClientWithKey(config) {
51
+ const c = getClient(config);
52
+ return { client: c, activeKey: lastClientKey };
53
+ }
26
54
  export function resetClient() {
27
55
  client = null;
28
56
  lastConfigHash = '';
57
+ lastClientKey = '';
29
58
  }
59
+ /** Re-export so callers (index.ts /keys) can introspect pool status. */
60
+ export { reportFailure, reportSuccess, poolSize } from './key-rotation.js';
30
61
  export function toolsToFunctions(tools) {
31
62
  return tools.map((t) => ({
32
63
  type: 'function',
@@ -38,21 +69,40 @@ export function toolsToFunctions(tools) {
38
69
  }));
39
70
  }
40
71
  export async function* streamChat(config, messages, tools, signal) {
41
- const api = getClient(config);
72
+ // Capture the active key so we can attribute success/failure to it
73
+ // for the rotation health tracker. Multi-key users (multiple OpenRouter
74
+ // accounts) get automatic round-robin when a key 429s or exhausts quota.
75
+ const { client: api, activeKey } = getClientWithKey(config);
42
76
  const toolDefs = toolsToFunctions(tools);
43
77
  // Bail early if the caller already cancelled before we even started
44
78
  if (signal?.aborted)
45
79
  throw new Error('Aborted before stream start');
46
- const stream = await withRetry(() => api.chat.completions.create({
47
- model: config.model,
48
- messages: messages,
49
- tools: toolDefs.length > 0 ? toolDefs : undefined,
50
- max_tokens: config.maxTokens,
51
- temperature: config.temperature,
52
- stream: true,
53
- // OpenAI SDK supports cancellation via signal; pass it through
54
- // so the underlying fetch can be aborted on Steer.
55
- }, signal ? { signal } : undefined), { maxRetries: 3, baseDelay: 1000, maxDelay: 30000 });
80
+ let stream;
81
+ try {
82
+ stream = await withRetry(() => api.chat.completions.create({
83
+ model: config.model,
84
+ messages: messages,
85
+ tools: toolDefs.length > 0 ? toolDefs : undefined,
86
+ max_tokens: config.maxTokens,
87
+ temperature: config.temperature,
88
+ stream: true,
89
+ // OpenAI SDK supports cancellation via signal; pass it through
90
+ // so the underlying fetch can be aborted on Steer.
91
+ }, signal ? { signal } : undefined), { maxRetries: 3, baseDelay: 1000, maxDelay: 30000 });
92
+ }
93
+ catch (err) {
94
+ // Hand the failure to the rotation pool so subsequent calls skip
95
+ // this key for the cool-down window. Re-throw so the outer error
96
+ // handling (auto-fallback model, error UI) still fires.
97
+ if (activeKey && poolSize() > 1)
98
+ reportFailure(activeKey, err);
99
+ throw err;
100
+ }
101
+ // If we get this far, the request was at least accepted — record success.
102
+ // (We don't wait for completion; mid-stream errors are vanishingly rare
103
+ // for OpenAI-compatible APIs vs upfront 4xx/5xx).
104
+ if (activeKey && poolSize() > 1)
105
+ reportSuccess(activeKey);
56
106
  let currentText = '';
57
107
  const toolCallAccumulator = new Map();
58
108
  for await (const chunk of stream) {
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/dist/config.js CHANGED
@@ -136,7 +136,7 @@ function validateConfig(config) {
136
136
  config.permissionMode = 'ask';
137
137
  }
138
138
  // Warn on unexpected fields
139
- const expectedFields = new Set(['apiKey', 'baseURL', 'model', 'fallbackModel', 'provider', 'maxTokens', 'temperature', 'permissionMode', 'alwaysAllowedTools', 'dryRun', 'theme', 'palette', 'showThinking', 'voice', 'memory', 'sandbox']);
139
+ const expectedFields = new Set(['apiKey', 'apiKeys', 'baseURL', 'model', 'fallbackModel', 'provider', 'maxTokens', 'temperature', 'permissionMode', 'alwaysAllowedTools', 'dryRun', 'theme', 'palette', 'showThinking', 'voice', 'memory', 'sandbox']);
140
140
  for (const key in config) {
141
141
  if (!expectedFields.has(key) && !_alreadyWarnedFields.has(key)) {
142
142
  _alreadyWarnedFields.add(key);
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -61,6 +61,10 @@ import * as mempalace from './mempalace/index.js';
61
61
  import { runCurator } from './curator.js';
62
62
  // Sandbox — OS-native isolation for bash tool (/sandbox)
63
63
  import { status as sandboxStatus } from './sandbox.js';
64
+ // API key rotation pool (/keys)
65
+ import { listStatus as keyPoolStatus } from './key-rotation.js';
66
+ // Agentic swarm — fan-out concurrent agents on the same task (/swarm)
67
+ import { runSwarm, resolveAgents, formatSwarmResults } from './swarm.js';
64
68
  // Voice / accessibility — built-in dictation (Whisper) + readout (ElevenLabs)
65
69
  import { printVoiceStatus, isVoiceEnabled, getTtsConfig, getSttConfig, getAccessibilityConfig, speak, dictateOnce, } from './voice.js';
66
70
  import { isFfmpegAvailable, audioCue, startRecording, probeMic, micProbeMessage } from './audio.js';
@@ -197,6 +201,7 @@ export function handleSlashCommand(input, config, messages, session, mode) {
197
201
  console.log(d(' ') + c('/models') + d(' — list available models for provider'));
198
202
  console.log(d(' ') + c('/fallback [model]') + d(' — set/show the model auto-retried on cryptic provider errors'));
199
203
  console.log(d(' ') + c('/provider') + d(' — show provider info'));
204
+ console.log(d(' ') + c('/keys [add|rm]') + d(' — multi-key rotation pool (e.g. several OpenRouter accounts)'));
200
205
  console.log(d(' ') + c('/route') + d(' — auto-route model based on next message'));
201
206
  console.log(h('\n ── Modes ──'));
202
207
  console.log(d(' ') + c('/mode [name]') + d(' — switch mode (dev/review/tdd/research/plan/debug/architect/hermes/design)'));
@@ -254,6 +259,7 @@ export function handleSlashCommand(input, config, messages, session, mode) {
254
259
  // silent aliases for power users but are not listed here.
255
260
  console.log(h('\n ── Orchestration ──'));
256
261
  console.log(d(' ') + c('/orchestrate <task>') + d(' — decompose into parallel sub-agents'));
262
+ console.log(d(' ') + c('/swarm <agents> <task>') + d(' — true parallel fan-out: N agents on same task, results merged with attribution'));
257
263
  console.log(d(' ') + c('/pr-loop') + d(' — autonomous PR review loop'));
258
264
  console.log(d(' ') + c('/multi-plan <task>') + d(' — multi-agent planning'));
259
265
  console.log(d(' ') + c('/multi-execute') + d(' — multi-agent execution'));
@@ -757,6 +763,30 @@ export function handleSlashCommand(input, config, messages, session, mode) {
757
763
  mode.current = 'architect';
758
764
  const orchPrompt = buildOrchestrationPrompt(args);
759
765
  return { handled: false, injectPrompt: orchPrompt };
766
+ // ── Agentic swarm — true parallel fan-out (M3 swarm audit) ──
767
+ // Run N agents concurrently on the same task. Each agent gets its
768
+ // own ECC prompt + the task as user message; outputs are merged
769
+ // with attribution headers. No tools available to swarm agents —
770
+ // analysis only, no file edits.
771
+ //
772
+ // /swarm <agent1,agent2,...> <task>
773
+ //
774
+ // Each agent's request uses the key rotation pool from v1.23.0,
775
+ // so multi-account users get true parallel throughput.
776
+ case '/swarm': {
777
+ // Match: first whitespace-free token is the agents list, rest is task
778
+ const m = args.match(/^(\S+)\s+([\s\S]+)$/);
779
+ if (!m) {
780
+ console.log(chalk.yellow(' Usage: /swarm <agent1,agent2,...> <task>'));
781
+ console.log(chalk.dim(' Example: /swarm code-architect,silent-failure-hunter,type-design-analyzer audit the auth flow'));
782
+ console.log(chalk.dim(' Run /ecc-guide agents to see available agents.'));
783
+ return { handled: true };
784
+ }
785
+ const [, agentsList, task] = m;
786
+ // Use a sentinel + delimiter approach so the main REPL loop can
787
+ // pick up the async swarm dispatch (slash handlers are sync).
788
+ return { handled: false, injectPrompt: '__SWARM__' + agentsList + '|||' + task };
789
+ }
760
790
  // ── Verification & Build ─────────────────────────
761
791
  case '/verify': {
762
792
  const prompt = buildVerifyPrompt(process.cwd(), args || undefined);
@@ -1555,6 +1585,77 @@ export function handleSlashCommand(input, config, messages, session, mode) {
1555
1585
  console.log(chalk.dim(' Restart the REPL for the tool to appear in /tools.'));
1556
1586
  return { handled: true };
1557
1587
  }
1588
+ // ── API key pool (multi-account rotation) ────────────────
1589
+ // /keys show pool with health + stats
1590
+ // /keys add <key> append to the rotation pool
1591
+ // /keys remove <key> remove a specific key (or partial tail-match)
1592
+ // /keys clear empty the extras pool (keeps primary apiKey)
1593
+ case '/keys': {
1594
+ const parts = args.trim().split(/\s+/).filter(Boolean);
1595
+ const sub = (parts[0] || '').toLowerCase();
1596
+ if (!sub || sub === 'status' || sub === 'list') {
1597
+ const status = keyPoolStatus();
1598
+ if (status.length === 0) {
1599
+ console.log(chalk.dim(' Key pool is empty. /keys add <key> to start rotation.'));
1600
+ return { handled: true };
1601
+ }
1602
+ console.log(chalk.cyan(`\n API key pool (${status.length}):`));
1603
+ for (const k of status) {
1604
+ const health = k.healthy
1605
+ ? chalk.green('✓ healthy')
1606
+ : chalk.yellow(`✗ cooling ${k.coolDownRemainingSec}s${k.lastReason ? ' (' + k.lastReason + ')' : ''}`);
1607
+ console.log(chalk.dim(` [${k.index}] ${k.tail} ${health} · ${k.successes} ok / ${k.failures} fail`));
1608
+ }
1609
+ console.log(chalk.dim('\n /keys add <key> add to pool'));
1610
+ console.log(chalk.dim(' /keys remove <tail> drop a key (last-4 char match)'));
1611
+ console.log(chalk.dim(' /keys clear empty the extras pool\n'));
1612
+ return { handled: true };
1613
+ }
1614
+ if (sub === 'add') {
1615
+ const newKey = parts.slice(1).join(' ').trim();
1616
+ if (!newKey) {
1617
+ console.log(chalk.yellow(' Usage: /keys add <api-key>'));
1618
+ return { handled: true };
1619
+ }
1620
+ const extras = (config.apiKeys || []).slice();
1621
+ if (extras.includes(newKey) || newKey === config.apiKey) {
1622
+ console.log(chalk.yellow(' Key already in the pool.'));
1623
+ return { handled: true };
1624
+ }
1625
+ extras.push(newKey);
1626
+ config.apiKeys = extras;
1627
+ saveConfig(config);
1628
+ resetClient();
1629
+ console.log(chalk.green(` Key added (…${newKey.slice(-4)}). Pool size: ${1 + extras.length}.`));
1630
+ return { handled: true };
1631
+ }
1632
+ if (sub === 'remove' || sub === 'rm') {
1633
+ const target = parts[1] || '';
1634
+ if (!target) {
1635
+ console.log(chalk.yellow(' Usage: /keys remove <tail-chars>'));
1636
+ return { handled: true };
1637
+ }
1638
+ const extras = (config.apiKeys || []).filter((k) => !k.endsWith(target) && k !== target);
1639
+ if (extras.length === (config.apiKeys || []).length) {
1640
+ console.log(chalk.yellow(` No key matched "${target}".`));
1641
+ return { handled: true };
1642
+ }
1643
+ config.apiKeys = extras;
1644
+ saveConfig(config);
1645
+ resetClient();
1646
+ console.log(chalk.green(` Key removed. Pool size: ${1 + extras.length}.`));
1647
+ return { handled: true };
1648
+ }
1649
+ if (sub === 'clear') {
1650
+ config.apiKeys = [];
1651
+ saveConfig(config);
1652
+ resetClient();
1653
+ console.log(chalk.green(' Extras pool cleared. Primary key remains.'));
1654
+ return { handled: true };
1655
+ }
1656
+ console.log(chalk.yellow(` Unknown /keys subcommand: ${sub}. Try: status, add, remove, clear`));
1657
+ return { handled: true };
1658
+ }
1558
1659
  // ── Sandbox — OS-native isolation for bash tool ──────────
1559
1660
  // /sandbox show backend + current level
1560
1661
  // /sandbox off|standard|strict
@@ -2344,6 +2445,38 @@ async function main() {
2344
2445
  console.log(theme.dim(' [dictate] ') + chalk.white(transcript));
2345
2446
  messages.push({ role: 'user', content: transcript });
2346
2447
  }
2448
+ else if (result.injectPrompt.startsWith('__SWARM__')) {
2449
+ // Swarm dispatch: __SWARM__<agentsCsv>|||<task>. Same sentinel
2450
+ // trick as /dictate so the slash handler stays sync; the async
2451
+ // fan-out happens here in the main REPL loop where we already
2452
+ // have await + the live config object.
2453
+ const payload = result.injectPrompt.slice('__SWARM__'.length);
2454
+ const sepIdx = payload.indexOf('|||');
2455
+ const agentsCsv = payload.slice(0, sepIdx);
2456
+ const task = payload.slice(sepIdx + 3);
2457
+ const slugs = agentsCsv.split(',').map((s) => s.trim()).filter(Boolean);
2458
+ try {
2459
+ const agents = resolveAgents(slugs);
2460
+ console.log(chalk.cyan(` Swarming ${agents.length} agent(s) in parallel: ${agents.map((a) => a.name).join(', ')}`));
2461
+ console.log(chalk.dim(` Task: ${task.length > 100 ? task.slice(0, 97) + '...' : task}`));
2462
+ const swarmStart = Date.now();
2463
+ const results = await runSwarm(agents, task, config);
2464
+ const output = formatSwarmResults(results);
2465
+ console.log(output);
2466
+ const elapsed = ((Date.now() - swarmStart) / 1000).toFixed(1);
2467
+ const ok = results.filter((r) => !r.error).length;
2468
+ console.log(chalk.dim(`\n swarm complete: ${ok}/${results.length} agent(s) succeeded in ${elapsed}s`));
2469
+ // Push the swarm as conversational context so follow-up
2470
+ // turns can reason about the consolidated output.
2471
+ messages.push({ role: 'user', content: `[/swarm ${agents.map((a) => a.name).join(',')}] ${task}` });
2472
+ messages.push({ role: 'assistant', content: output.slice(0, 8000) });
2473
+ }
2474
+ catch (e) {
2475
+ console.log(chalk.red(` Swarm failed: ${e instanceof Error ? e.message : e}`));
2476
+ }
2477
+ await autoSave(session, messages);
2478
+ continue;
2479
+ }
2347
2480
  else {
2348
2481
  messages.push({ role: 'user', content: result.injectPrompt });
2349
2482
  }