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.
@@ -0,0 +1,117 @@
1
+ /**
2
+ * API key rotation pool — for users with multiple OpenRouter (or any
3
+ * compatible) accounts who want to round-robin / failover across them
4
+ * when one hits a rate limit or runs out of free credits.
5
+ *
6
+ * Pool composition: config.apiKey + config.apiKeys (deduplicated, order
7
+ * preserved). The single `apiKey` field always becomes pool[0] so users
8
+ * with only the legacy config see no change in behavior.
9
+ *
10
+ * Rotation strategy: on 401 / 429 / quota errors, the failing key is
11
+ * marked "cool" for `COOL_DOWN_MS`, the next healthy key takes over.
12
+ * If all keys are cool, the request fails normally — the user will see
13
+ * the last error message. Health state lives in module memory; restart
14
+ * = fresh start.
15
+ *
16
+ * Why module-level vs persisted: rate-limit windows are usually 60s-5m
17
+ * and reset naturally. Persisting cool-down across processes would
18
+ * make the agent worse at recovering from transient blips.
19
+ */
20
+ const COOL_DOWN_MS = 60_000; // 1 min — typical free-tier RPM window
21
+ const QUOTA_COOL_DOWN_MS = 60 * 60_000; // 1 hour — daily/monthly quota errors
22
+ let pool = [];
23
+ let cursor = 0; // round-robin pointer for which key to try first
24
+ /**
25
+ * Build the pool from a config snapshot. Idempotent; if the same keys
26
+ * are passed in the same order, the existing state is preserved
27
+ * (so cool-downs persist across rebuilds in the same process).
28
+ */
29
+ export function setPool(primary, extras = []) {
30
+ // Dedupe in order: primary first, then extras
31
+ const seen = new Set();
32
+ const all = [];
33
+ for (const k of [primary, ...extras]) {
34
+ if (k && !seen.has(k)) {
35
+ seen.add(k);
36
+ all.push(k);
37
+ }
38
+ }
39
+ // Preserve state for keys that are still in the pool
40
+ const existing = new Map(pool.map((s) => [s.key, s]));
41
+ pool = all.map((k) => existing.get(k) || {
42
+ key: k, coolUntil: 0, successes: 0, failures: 0,
43
+ });
44
+ if (cursor >= pool.length)
45
+ cursor = 0;
46
+ }
47
+ /**
48
+ * Pick the next healthy key to use. Round-robin from the current cursor.
49
+ * Returns null if the pool is empty or all keys are cool.
50
+ */
51
+ export function pickKey() {
52
+ if (pool.length === 0)
53
+ return null;
54
+ const now = Date.now();
55
+ // Try each key once, starting from cursor
56
+ for (let i = 0; i < pool.length; i++) {
57
+ const idx = (cursor + i) % pool.length;
58
+ if (pool[idx].coolUntil <= now) {
59
+ cursor = (idx + 1) % pool.length; // next call rotates one further
60
+ return pool[idx].key;
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+ /**
66
+ * Mark a key as failed. The classifier maps the error to either a
67
+ * short cooldown (rate-limit) or a long one (quota / auth). Used by
68
+ * api.ts's retry logic to skip dead keys without re-trying them.
69
+ */
70
+ export function reportFailure(key, err) {
71
+ const state = pool.find((s) => s.key === key);
72
+ if (!state)
73
+ return;
74
+ const msg = err instanceof Error ? err.message : String(err);
75
+ const lower = msg.toLowerCase();
76
+ let cooldown = COOL_DOWN_MS;
77
+ let reason = msg.slice(0, 80);
78
+ if (/quota|insufficient|credit|payment|billing/.test(lower)) {
79
+ cooldown = QUOTA_COOL_DOWN_MS;
80
+ reason = 'quota/credit exhausted';
81
+ }
82
+ else if (/auth|invalid.*key|forbidden|401|403/.test(lower)) {
83
+ cooldown = QUOTA_COOL_DOWN_MS;
84
+ reason = 'auth rejected (bad/revoked key)';
85
+ }
86
+ else if (/rate.?limit|429|too.many/.test(lower)) {
87
+ cooldown = COOL_DOWN_MS;
88
+ reason = 'rate limited';
89
+ }
90
+ state.coolUntil = Date.now() + cooldown;
91
+ state.lastReason = reason;
92
+ state.failures++;
93
+ }
94
+ /** Mark a key as having succeeded — clears any cool-down + records stat. */
95
+ export function reportSuccess(key) {
96
+ const state = pool.find((s) => s.key === key);
97
+ if (!state)
98
+ return;
99
+ state.coolUntil = 0;
100
+ state.lastReason = undefined;
101
+ state.successes++;
102
+ }
103
+ export function listStatus() {
104
+ const now = Date.now();
105
+ return pool.map((s, i) => ({
106
+ index: i,
107
+ tail: `…${s.key.slice(-4)}`,
108
+ healthy: s.coolUntil <= now,
109
+ coolDownRemainingSec: s.coolUntil > now ? Math.ceil((s.coolUntil - now) / 1000) : undefined,
110
+ successes: s.successes,
111
+ failures: s.failures,
112
+ lastReason: s.lastReason,
113
+ }));
114
+ }
115
+ /** Currently-active pool size (post-dedup). */
116
+ export function poolSize() { return pool.length; }
117
+ //# sourceMappingURL=key-rotation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-rotation.js","sourceRoot":"","sources":["../src/key-rotation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Agentic swarming — fan out N specialized agents on the same task
3
+ * concurrently and merge their outputs.
4
+ *
5
+ * Inspired by LangGraph's `Send` map-reduce primitive and OpenAI Agents
6
+ * SDK's handoff pattern. The audit ranked these as the two most-portable
7
+ * concepts from the swarming-framework ecosystem; this is the map-reduce
8
+ * half (Send-style fan-out). Sequential handoff stays on the roadmap
9
+ * for /multi-execute.
10
+ *
11
+ * Usage:
12
+ * /swarm code-architect,silent-failure-hunter,type-design-analyzer audit the auth flow
13
+ *
14
+ * Each agent receives:
15
+ * - System prompt: its own ECC agent prompt (the role-specific persona)
16
+ * - User message: the task verbatim
17
+ * - Empty tool list: swarm runs are analysis-only; no file edits or
18
+ * bash commands. If you want a swarm to make changes, /architect (or
19
+ * other agent slash) first, then act on the synthesis manually.
20
+ *
21
+ * Concurrency: Promise.allSettled — one agent failing doesn't kill the
22
+ * others. Errors surface in the result block.
23
+ *
24
+ * Key pool: every concurrent agent uses streamChat which goes through
25
+ * the key rotation pool from v1.23.0. Users with multiple OpenRouter
26
+ * accounts get true parallel throughput across keys.
27
+ *
28
+ * Cost note: N agents = N model calls. The orchestrator's /help text
29
+ * surfaces this so it isn't surprising.
30
+ */
31
+ import type { CrowcoderConfig } from './types.js';
32
+ export interface SwarmAgent {
33
+ /** Display name (matches the ECC slug like 'code-architect') */
34
+ name: string;
35
+ /** The system prompt the agent runs with — usually the ECC skill body */
36
+ prompt: string;
37
+ }
38
+ export interface SwarmResult {
39
+ agent: string;
40
+ text: string;
41
+ durationMs: number;
42
+ /** Set when this agent's call threw — others may still have succeeded */
43
+ error?: string;
44
+ }
45
+ /**
46
+ * Look up agents by slug and return their full prompts. Throws on the
47
+ * first unknown slug so the caller can correct + retry rather than
48
+ * partially running.
49
+ *
50
+ * Accepts both bare slugs ("code-architect") and the "agent: <slug>"
51
+ * form that listSkills() returns.
52
+ */
53
+ export declare function resolveAgents(slugs: string[]): SwarmAgent[];
54
+ /**
55
+ * Run all agents concurrently against the same task. Each agent gets a
56
+ * private message history (its prompt + the task); they don't see each
57
+ * other's output. Merging is the caller's job — usually print-with-
58
+ * attribution + an optional synthesis prompt.
59
+ *
60
+ * No tools available to swarm agents — analysis only. If we exposed
61
+ * tools we'd need lock coordination on the filesystem + permission
62
+ * prompts for every parallel write, which defeats the purpose.
63
+ */
64
+ export declare function runSwarm(agents: SwarmAgent[], task: string, config: CrowcoderConfig): Promise<SwarmResult[]>;
65
+ /**
66
+ * Format swarm results for stdout — attribution headers + clear visual
67
+ * separation between agents. The caller can pipe this into a follow-up
68
+ * synthesis prompt if they want consensus or comparison.
69
+ */
70
+ export declare function formatSwarmResults(results: SwarmResult[]): string;
package/dist/swarm.js ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Agentic swarming — fan out N specialized agents on the same task
3
+ * concurrently and merge their outputs.
4
+ *
5
+ * Inspired by LangGraph's `Send` map-reduce primitive and OpenAI Agents
6
+ * SDK's handoff pattern. The audit ranked these as the two most-portable
7
+ * concepts from the swarming-framework ecosystem; this is the map-reduce
8
+ * half (Send-style fan-out). Sequential handoff stays on the roadmap
9
+ * for /multi-execute.
10
+ *
11
+ * Usage:
12
+ * /swarm code-architect,silent-failure-hunter,type-design-analyzer audit the auth flow
13
+ *
14
+ * Each agent receives:
15
+ * - System prompt: its own ECC agent prompt (the role-specific persona)
16
+ * - User message: the task verbatim
17
+ * - Empty tool list: swarm runs are analysis-only; no file edits or
18
+ * bash commands. If you want a swarm to make changes, /architect (or
19
+ * other agent slash) first, then act on the synthesis manually.
20
+ *
21
+ * Concurrency: Promise.allSettled — one agent failing doesn't kill the
22
+ * others. Errors surface in the result block.
23
+ *
24
+ * Key pool: every concurrent agent uses streamChat which goes through
25
+ * the key rotation pool from v1.23.0. Users with multiple OpenRouter
26
+ * accounts get true parallel throughput across keys.
27
+ *
28
+ * Cost note: N agents = N model calls. The orchestrator's /help text
29
+ * surfaces this so it isn't surprising.
30
+ */
31
+ import { streamChat } from './api.js';
32
+ import { findEccSkillByName } from './ecc.js';
33
+ /**
34
+ * Look up agents by slug and return their full prompts. Throws on the
35
+ * first unknown slug so the caller can correct + retry rather than
36
+ * partially running.
37
+ *
38
+ * Accepts both bare slugs ("code-architect") and the "agent: <slug>"
39
+ * form that listSkills() returns.
40
+ */
41
+ export function resolveAgents(slugs) {
42
+ const out = [];
43
+ for (const raw of slugs) {
44
+ const slug = raw.trim();
45
+ if (!slug)
46
+ continue;
47
+ // Try direct name match first ("agent: <slug>"), then bare slug
48
+ const skill = findEccSkillByName(`agent: ${slug}`) ?? findEccSkillByName(slug);
49
+ if (!skill) {
50
+ throw new Error(`Unknown agent: "${slug}". Run /ecc-guide agents to see what's available.`);
51
+ }
52
+ out.push({ name: slug, prompt: skill.prompt });
53
+ }
54
+ return out;
55
+ }
56
+ /**
57
+ * Run all agents concurrently against the same task. Each agent gets a
58
+ * private message history (its prompt + the task); they don't see each
59
+ * other's output. Merging is the caller's job — usually print-with-
60
+ * attribution + an optional synthesis prompt.
61
+ *
62
+ * No tools available to swarm agents — analysis only. If we exposed
63
+ * tools we'd need lock coordination on the filesystem + permission
64
+ * prompts for every parallel write, which defeats the purpose.
65
+ */
66
+ export async function runSwarm(agents, task, config) {
67
+ const results = await Promise.allSettled(agents.map(async (agent) => {
68
+ const start = Date.now();
69
+ try {
70
+ const messages = [
71
+ { role: 'system', content: agent.prompt },
72
+ { role: 'user', content: task },
73
+ ];
74
+ let text = '';
75
+ for await (const event of streamChat(config, messages, [])) {
76
+ if (event.type === 'text' && event.content)
77
+ text += event.content;
78
+ }
79
+ return { agent: agent.name, text, durationMs: Date.now() - start };
80
+ }
81
+ catch (err) {
82
+ return {
83
+ agent: agent.name,
84
+ text: '',
85
+ durationMs: Date.now() - start,
86
+ error: err instanceof Error ? err.message : String(err),
87
+ };
88
+ }
89
+ }));
90
+ // Promise.allSettled always resolves; un-pack the values.
91
+ return results.map((r) => (r.status === 'fulfilled' ? r.value : {
92
+ agent: 'unknown',
93
+ text: '',
94
+ durationMs: 0,
95
+ error: `swarm task crashed: ${r.reason}`,
96
+ }));
97
+ }
98
+ /**
99
+ * Format swarm results for stdout — attribution headers + clear visual
100
+ * separation between agents. The caller can pipe this into a follow-up
101
+ * synthesis prompt if they want consensus or comparison.
102
+ */
103
+ export function formatSwarmResults(results) {
104
+ const lines = [];
105
+ for (const r of results) {
106
+ lines.push('');
107
+ lines.push(`══════════════════════════════════════════════`);
108
+ lines.push(` ${r.agent} (${(r.durationMs / 1000).toFixed(1)}s${r.error ? ', ERROR' : ''})`);
109
+ lines.push(`──────────────────────────────────────────────`);
110
+ if (r.error) {
111
+ lines.push(` error: ${r.error}`);
112
+ }
113
+ else {
114
+ lines.push(r.text.trim() || '(no output)');
115
+ }
116
+ }
117
+ return lines.join('\n');
118
+ }
119
+ //# sourceMappingURL=swarm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swarm.js","sourceRoot":"","sources":["../src/swarm.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -9,6 +9,7 @@ export interface Message {
9
9
  }
10
10
  export interface CrowcoderConfig {
11
11
  apiKey: string;
12
+ apiKeys?: string[];
12
13
  baseURL: string;
13
14
  model: string;
14
15
  fallbackModel?: string;
package/dist/types.js CHANGED
@@ -47,6 +47,17 @@ export const PROVIDERS = {
47
47
  defaultModel: 'glm-4-plus',
48
48
  requiresKey: true,
49
49
  },
50
+ nvidia: {
51
+ name: 'NVIDIA NIM',
52
+ baseURL: 'https://integrate.api.nvidia.com/v1',
53
+ // meta/llama-3.1-70b-instruct is the most-reliable widely-available
54
+ // default on build.nvidia.com's free tier as of 2026. Users can switch
55
+ // to nvidia/nemotron-4-340b-instruct, qwen/qwen-2.5-coder-32b-instruct,
56
+ // deepseek-ai/deepseek-coder-6.7b-instruct, or any of the ~100 models
57
+ // exposed at /v1/chat/completions via /model.
58
+ defaultModel: 'meta/llama-3.1-70b-instruct',
59
+ requiresKey: true,
60
+ },
50
61
  custom: {
51
62
  name: 'Custom',
52
63
  baseURL: '',
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA2GA,MAAM,CAAC,MAAM,SAAS,GAAmC;IACvD,SAAS,EAAE;QACT,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,+BAA+B;QACxC,YAAY,EAAE,0BAA0B;QACxC,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,IAAI;KAClB;IACD,UAAU,EAAE;QACV,IAAI,EAAE,wBAAwB;QAC9B,OAAO,EAAE,8BAA8B;QACvC,YAAY,EAAE,2BAA2B;QACzC,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,0DAA0D;QACnE,YAAY,EAAE,kBAAkB;QAChC,WAAW,EAAE,IAAI;KAClB;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,6BAA6B;QACtC,YAAY,EAAE,eAAe;QAC7B,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,sBAAsB;QACpC,WAAW,EAAE,KAAK;KACnB;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,0BAA0B;QACnC,YAAY,EAAE,cAAc;QAC5B,WAAW,EAAE,KAAK;KACnB;IACD,GAAG,EAAE;QACH,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,sCAAsC;QAC/C,YAAY,EAAE,YAAY;QAC1B,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,EAAE;QACX,YAAY,EAAE,EAAE;QAChB,WAAW,EAAE,IAAI;KAClB;CACF,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAiHA,MAAM,CAAC,MAAM,SAAS,GAAmC;IACvD,SAAS,EAAE;QACT,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,+BAA+B;QACxC,YAAY,EAAE,0BAA0B;QACxC,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,IAAI;KAClB;IACD,UAAU,EAAE;QACV,IAAI,EAAE,wBAAwB;QAC9B,OAAO,EAAE,8BAA8B;QACvC,YAAY,EAAE,2BAA2B;QACzC,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,0DAA0D;QACnE,YAAY,EAAE,kBAAkB;QAChC,WAAW,EAAE,IAAI;KAClB;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,6BAA6B;QACtC,YAAY,EAAE,eAAe;QAC7B,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,sBAAsB;QACpC,WAAW,EAAE,KAAK;KACnB;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,0BAA0B;QACnC,YAAY,EAAE,cAAc;QAC5B,WAAW,EAAE,KAAK;KACnB;IACD,GAAG,EAAE;QACH,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,sCAAsC;QAC/C,YAAY,EAAE,YAAY;QAC1B,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,qCAAqC;QAC9C,oEAAoE;QACpE,uEAAuE;QACvE,wEAAwE;QACxE,sEAAsE;QACtE,8CAA8C;QAC9C,YAAY,EAAE,6BAA6B;QAC3C,WAAW,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,EAAE;QACX,YAAY,EAAE,EAAE;QAChB,WAAW,EAAE,IAAI;KAClB;CACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compact-agent",
3
- "version": "1.22.0",
3
+ "version": "1.24.0",
4
4
  "description": "A dense, feature-rich AI coding agent for the terminal. Built-in voice dictation (Whisper) + TTS readout (ElevenLabs) + screen-reader mode for blind / low-vision users. 80+ slash commands, 9 modes including Hermes self-improving loop, multi-agent orchestration, bundled everything-claude-code skills library, learning system, and observable LLM transport. Works with OpenRouter, OpenAI, Anthropic-compatible, Ollama, LM Studio, DeepSeek, or any OpenAI-compatible API.",
5
5
  "type": "module",
6
6
  "license": "MIT",