compact-agent 1.21.0 → 1.23.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,37 @@
1
+ export type SandboxBackend = 'seatbelt' | 'bwrap' | 'none';
2
+ export type SandboxLevel = 'off' | 'standard' | 'strict';
3
+ interface BackendDetect {
4
+ backend: SandboxBackend;
5
+ available: boolean;
6
+ reason?: string;
7
+ }
8
+ /**
9
+ * Detect which sandbox backend (if any) is available on this machine.
10
+ * Cached after the first call; pass force=true to re-probe.
11
+ */
12
+ export declare function detectBackend(force?: boolean): BackendDetect;
13
+ /**
14
+ * Wrap a shell command for the active backend at the requested level.
15
+ * Returns the wrapped command string and a label for logging. If the
16
+ * backend isn't available or level is 'off', returns the command
17
+ * unchanged (callers don't need to special-case).
18
+ */
19
+ export declare function wrapCommand(cmd: string, opts: {
20
+ level: SandboxLevel;
21
+ cwd: string;
22
+ }): {
23
+ cmd: string;
24
+ label: string;
25
+ };
26
+ /**
27
+ * Status snapshot for the /sandbox slash command. Tells the user what's
28
+ * supported on this machine + what's currently active.
29
+ */
30
+ export interface SandboxStatus {
31
+ backend: SandboxBackend;
32
+ available: boolean;
33
+ reason?: string;
34
+ platform: NodeJS.Platform;
35
+ }
36
+ export declare function status(): SandboxStatus;
37
+ export {};
@@ -0,0 +1,192 @@
1
+ /**
2
+ * OS-native sandbox wrapper for the bash tool.
3
+ *
4
+ * Defense-in-depth on top of the execpolicy DSL from 1.19.0. Where
5
+ * execpolicy gates INTENT before the command runs (block "rm -rf /",
6
+ * prompt for "sudo"), this layer adds RUNTIME ISOLATION: the command
7
+ * runs under an OS-native sandbox that limits filesystem write access,
8
+ * network reach, and process privileges even if the intent gate
9
+ * approved or the model is trying to evade detection.
10
+ *
11
+ * Backends:
12
+ * macOS → sandbox-exec (Seatbelt). Shipped with macOS since 10.5.
13
+ * Policy described in scheme-like .sb syntax.
14
+ * Linux → bubblewrap (bwrap). Usually preinstalled (Flatpak runtime)
15
+ * or one apt/yum/dnf install away. Combines user
16
+ * namespaces, mount namespaces, seccomp.
17
+ * Windows → no-op for now. Job Objects + restricted tokens + AppContainer
18
+ * are doable but a much larger project. Documented in /sandbox
19
+ * output so the user knows.
20
+ *
21
+ * Policy levels (config: sandbox.level):
22
+ * off — wrap nothing; behave as before
23
+ * standard — read everywhere, write only to cwd + /tmp, no network
24
+ * (still gives access to the project + scratch space)
25
+ * strict — read cwd only, write only to cwd, no network, no /tmp
26
+ *
27
+ * Default: 'off'. Users opt in via /sandbox standard (or strict) — we
28
+ * don't want to surprise anyone whose workflow needs network or writes
29
+ * outside cwd.
30
+ *
31
+ * Failure mode: if the sandbox tool isn't installed or the wrap fails
32
+ * to construct, we LOG and fall through to the un-sandboxed command.
33
+ * Better to run + work than fail closed silently for a missing tool.
34
+ */
35
+ import { existsSync } from 'node:fs';
36
+ import { execSync } from 'node:child_process';
37
+ let cachedDetection = null;
38
+ /**
39
+ * Detect which sandbox backend (if any) is available on this machine.
40
+ * Cached after the first call; pass force=true to re-probe.
41
+ */
42
+ export function detectBackend(force = false) {
43
+ if (cachedDetection && !force)
44
+ return cachedDetection;
45
+ if (process.platform === 'darwin') {
46
+ // sandbox-exec is at /usr/bin/sandbox-exec on every macOS install
47
+ // since 10.5. Deprecated by Apple but still functional in 2026.
48
+ const path = '/usr/bin/sandbox-exec';
49
+ cachedDetection = existsSync(path)
50
+ ? { backend: 'seatbelt', available: true }
51
+ : { backend: 'seatbelt', available: false, reason: 'sandbox-exec not found at /usr/bin/' };
52
+ }
53
+ else if (process.platform === 'linux') {
54
+ // bwrap could be anywhere on PATH. Use `which` since it's fast.
55
+ try {
56
+ execSync('which bwrap', { stdio: 'ignore', timeout: 1000 });
57
+ cachedDetection = { backend: 'bwrap', available: true };
58
+ }
59
+ catch {
60
+ cachedDetection = { backend: 'bwrap', available: false, reason: 'bwrap (bubblewrap) not on PATH. Install with: apt install bubblewrap | dnf install bubblewrap | brew install bubblewrap' };
61
+ }
62
+ }
63
+ else {
64
+ cachedDetection = { backend: 'none', available: false, reason: `${process.platform} doesn't have a supported sandbox backend yet (Windows Job Objects planned)` };
65
+ }
66
+ return cachedDetection;
67
+ }
68
+ /**
69
+ * Construct a Seatbelt (.sb) policy for the given level and cwd.
70
+ *
71
+ * Seatbelt operates on a deny-by-default model: we declare allowed
72
+ * operations, anything else is denied. The base policy here is
73
+ * deliberately permissive for system reads (so node, git, etc. can
74
+ * find their libraries) while gating writes + network.
75
+ *
76
+ * Quirks:
77
+ * - file-write* requires the absolute resolved path (no shell expansion)
78
+ * - network-outbound to localhost is allowed regardless of level so
79
+ * dev servers + IPC keep working
80
+ */
81
+ function buildSeatbeltPolicy(level, cwd) {
82
+ // Common: deny all by default; allow process spawning + signal +
83
+ // sysctl reads + IPC (otherwise nothing runs).
84
+ const common = [
85
+ '(version 1)',
86
+ '(deny default)',
87
+ '(allow process-exec*)',
88
+ '(allow process-fork)',
89
+ '(allow signal (target self))',
90
+ '(allow sysctl-read)',
91
+ '(allow mach-lookup)',
92
+ '(allow ipc-posix-shm*)',
93
+ '(allow file-read*)', // permissive system-wide read for tool deps
94
+ '(allow file-read-metadata)',
95
+ '(allow file-issue-extension)',
96
+ ];
97
+ const networkLocal = ['(allow network-outbound (local ip "*:*"))'];
98
+ const networkAll = ['(allow network*)'];
99
+ const writeCwd = [`(allow file-write* (subpath "${cwd}"))`];
100
+ const writeTmp = ['(allow file-write* (subpath "/tmp"))', '(allow file-write* (subpath "/private/tmp"))'];
101
+ if (level === 'strict') {
102
+ return [...common, ...networkLocal, ...writeCwd].join('\n');
103
+ }
104
+ // standard: cwd + /tmp writable, full network. Network restriction
105
+ // breaks too many real workflows (npm install, pip, curl docs); we
106
+ // keep that on the execpolicy intent gate instead.
107
+ return [...common, ...networkAll, ...writeCwd, ...writeTmp].join('\n');
108
+ }
109
+ /**
110
+ * Construct a bwrap argument list. bwrap is invoked as
111
+ * bwrap [args...] <command>
112
+ * so we return the prefix array; the caller concatenates the user
113
+ * command afterward (typically as `sh -c "..."`).
114
+ */
115
+ function buildBwrapArgs(level, cwd) {
116
+ // Common: a fresh user namespace, /proc, /dev, /tmp, share host's
117
+ // /usr + /etc as read-only so binaries + configs work, share network
118
+ // namespace by default (we restrict via execpolicy / level).
119
+ const common = [
120
+ '--unshare-user-try', // fall back gracefully if not allowed
121
+ '--unshare-uts',
122
+ '--unshare-pid',
123
+ '--unshare-ipc',
124
+ '--die-with-parent',
125
+ '--proc', '/proc',
126
+ '--dev', '/dev',
127
+ '--ro-bind', '/usr', '/usr',
128
+ '--ro-bind', '/etc', '/etc',
129
+ '--ro-bind', '/lib', '/lib',
130
+ '--ro-bind-try', '/lib64', '/lib64',
131
+ '--ro-bind-try', '/bin', '/bin',
132
+ '--ro-bind-try', '/sbin', '/sbin',
133
+ // HOME read-only (config files, .ssh) — strict drops this
134
+ ...(level === 'strict' ? [] : ['--ro-bind-try', process.env.HOME || '/home', process.env.HOME || '/home']),
135
+ // cwd bind-mounted read-write — this is the project the agent edits
136
+ '--bind', cwd, cwd,
137
+ '--chdir', cwd,
138
+ // /tmp writable in standard, omitted in strict
139
+ ...(level === 'strict' ? [] : ['--tmpfs', '/tmp']),
140
+ ];
141
+ // Network: standard allows, strict disallows
142
+ const network = level === 'strict' ? ['--unshare-net'] : [];
143
+ return [...common, ...network];
144
+ }
145
+ /**
146
+ * Wrap a shell command for the active backend at the requested level.
147
+ * Returns the wrapped command string and a label for logging. If the
148
+ * backend isn't available or level is 'off', returns the command
149
+ * unchanged (callers don't need to special-case).
150
+ */
151
+ export function wrapCommand(cmd, opts) {
152
+ if (opts.level === 'off')
153
+ return { cmd, label: 'no-sandbox' };
154
+ const det = detectBackend();
155
+ if (!det.available) {
156
+ // Caller logs the warning; we just pass through.
157
+ return { cmd, label: `unsandboxed (${det.reason || 'no backend'})` };
158
+ }
159
+ if (det.backend === 'seatbelt') {
160
+ const policy = buildSeatbeltPolicy(opts.level, opts.cwd);
161
+ // sandbox-exec -p '<policy>' /bin/sh -c '<command>'
162
+ // Single-quote the policy + escape internal quotes
163
+ const policyEscaped = policy.replace(/'/g, "'\"'\"'");
164
+ const cmdEscaped = cmd.replace(/'/g, "'\"'\"'");
165
+ return {
166
+ cmd: `/usr/bin/sandbox-exec -p '${policyEscaped}' /bin/sh -c '${cmdEscaped}'`,
167
+ label: `seatbelt (${opts.level})`,
168
+ };
169
+ }
170
+ if (det.backend === 'bwrap') {
171
+ const args = buildBwrapArgs(opts.level, opts.cwd);
172
+ // bwrap doesn't accept commands as a single string — use exec form
173
+ // wrapped through sh -c. Shell escaping handled by the outer exec.
174
+ const cmdEscaped = cmd.replace(/'/g, "'\"'\"'");
175
+ const argString = args.map((a) => `'${a.replace(/'/g, "'\"'\"'")}'`).join(' ');
176
+ return {
177
+ cmd: `bwrap ${argString} /bin/sh -c '${cmdEscaped}'`,
178
+ label: `bwrap (${opts.level})`,
179
+ };
180
+ }
181
+ return { cmd, label: 'unsandboxed (unknown backend)' };
182
+ }
183
+ export function status() {
184
+ const det = detectBackend();
185
+ return {
186
+ backend: det.backend,
187
+ available: det.available,
188
+ reason: det.reason,
189
+ platform: process.platform,
190
+ };
191
+ }
192
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
1
  import { exec } from 'node:child_process';
2
+ import { loadConfig } from '../config.js';
3
+ import { wrapCommand, detectBackend } from '../sandbox.js';
2
4
  /**
3
5
  * Shell tool. Kept named `bash` for tool-call API compatibility, but on
4
6
  * Windows we route through cmd.exe by default — the platform-native shell.
@@ -55,9 +57,33 @@ export const BashTool = {
55
57
  isReadOnly: false,
56
58
  isDestructive: true,
57
59
  async call(input, cwd) {
58
- const command = input.command;
60
+ const rawCommand = input.command;
59
61
  const timeout = input.timeout || 120_000;
60
62
  const shell = pickShell();
63
+ // Sandbox wrap (no-op when level=off or backend unavailable).
64
+ // Loading config per-call keeps the bash tool stateless and means
65
+ // /sandbox level changes apply on the very next command.
66
+ const cfg = loadConfig();
67
+ const level = cfg.sandbox?.level || 'off';
68
+ let command = rawCommand;
69
+ let sandboxLabel = '';
70
+ if (level !== 'off') {
71
+ const det = detectBackend();
72
+ if (det.available) {
73
+ const wrapped = wrapCommand(rawCommand, { level, cwd });
74
+ command = wrapped.cmd;
75
+ sandboxLabel = wrapped.label;
76
+ }
77
+ else {
78
+ // Sandbox requested but unavailable on this platform — print
79
+ // once-per-call diagnostic. Doesn't block; falls through to
80
+ // unsandboxed exec because failing closed silently is worse.
81
+ process.stderr.write(` [sandbox] requested ${level} but ${det.reason}\n`);
82
+ }
83
+ }
84
+ if (sandboxLabel) {
85
+ process.stderr.write(` [sandbox] ${sandboxLabel}\n`);
86
+ }
61
87
  return new Promise((resolve) => {
62
88
  exec(command, {
63
89
  cwd,
@@ -1 +1 @@
1
- {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/tools/bash.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;
@@ -23,6 +24,11 @@ export interface CrowcoderConfig {
23
24
  showThinking?: boolean;
24
25
  voice?: VoiceConfig;
25
26
  memory?: MemoryConfig;
27
+ sandbox?: SandboxConfig;
28
+ }
29
+ export interface SandboxConfig {
30
+ /** off (no wrap) | standard (cwd + /tmp writable, net allowed) | strict (cwd-only) */
31
+ level?: 'off' | 'standard' | 'strict';
26
32
  }
27
33
  export interface MemoryConfig {
28
34
  enabled?: boolean;
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":"AA+FA,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.21.0",
3
+ "version": "1.23.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",