mythos-router 1.2.0 → 1.2.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.
- package/CHANGELOG.md +28 -5
- package/README.md +24 -3
- package/dist/cache.d.ts +28 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +169 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.js +4 -1
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +20 -7
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +85 -102
- package/dist/client.js.map +1 -1
- package/dist/commands/chat.d.ts +3 -0
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +181 -30
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/dream.d.ts.map +1 -1
- package/dist/commands/dream.js +8 -1
- package/dist/commands/dream.js.map +1 -1
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +21 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.d.ts +12 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +179 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/openai.d.ts +20 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +194 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/orchestrator.d.ts +38 -0
- package/dist/providers/orchestrator.d.ts.map +1 -0
- package/dist/providers/orchestrator.js +398 -0
- package/dist/providers/orchestrator.js.map +1 -0
- package/dist/providers/pricing.d.ts +22 -0
- package/dist/providers/pricing.d.ts.map +1 -0
- package/dist/providers/pricing.js +60 -0
- package/dist/providers/pricing.js.map +1 -0
- package/dist/providers/types.d.ts +72 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +6 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/skills.d.ts +41 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +227 -0
- package/dist/skills.js.map +1 -0
- package/dist/swd.d.ts.map +1 -1
- package/dist/swd.js +46 -11
- package/dist/swd.js.map +1 -1
- package/dist/utils.d.ts +5 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +39 -0
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [1.2.1]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Multi-Provider Orchestration Engine** — Decoupled the core application from the Anthropic SDK. The system now supports fallback routing, adaptive watchdogs, circuit breakers, and EMA-based performance scoring across multiple providers.
|
|
14
|
+
- **OpenAI & DeepSeek Support** — Added a native, zero-dependency `fetch`-based provider (`OpenAIProvider`) to seamlessly support OpenAI and DeepSeek endpoints (including streaming reasoning content for `o1` and `DeepSeek-R1`).
|
|
15
|
+
- **Skills Protocol** — Modular expert plugins via zero-dependency YAML frontmatter parsing. Skills (`-s <skill>`) can inject customized instructions, modify budget multipliers, and enforce deterministic provider selection.
|
|
16
|
+
- **Deterministic Response Caching** — SQLite-backed response caching for pure-reasoning requests (like `verify` or `dream`). Bypass rule strictly ensures file-mutating responses are never cached.
|
|
17
|
+
- **Centralized Pricing Registry** — Unified token cost calculator across different providers, feeding exact financial data into the budget metrics.
|
|
18
|
+
- **Auto-Healing TDD Loop** — Bounded, error-driven autonomy. Passing `--test-cmd` will automatically execute tests after a successful SWD mutation. If tests fail, the CLI intercepts `stderr`, truncates it, identifies TS/Runtime issues, and feeds it back to Claude for a self-healing iteration.
|
|
19
|
+
- **TDD Anti-Thrashing Guards** — The orchestrator will automatically abort the healing loop if Claude attempts the exact same fix or if output remains identically broken, preventing runaway API costs.
|
|
20
|
+
- **Contributor Covenant** — Added `CODE_OF_CONDUCT.md` to formally establish community standards.
|
|
21
|
+
|
|
22
|
+
### Security
|
|
23
|
+
- **CodeQL Integration** — Added GitHub CodeQL scanning badge to `README.md`.
|
|
24
|
+
- **Dependency Audit** — Triaged and validated false-positive Socket.dev supply chain alerts for `@anthropic-ai/sdk`.
|
|
25
|
+
|
|
26
|
+
---
|
|
10
27
|
## [1.2.0] — 2026-04-23
|
|
11
28
|
|
|
12
29
|
### Added
|
|
@@ -137,9 +154,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
137
154
|
- **Correction Turns** — max 2 retries before yielding to human.
|
|
138
155
|
- **Dream/Verify Commands** — memory compression and drift detection.
|
|
139
156
|
|
|
140
|
-
|
|
141
|
-
[1.1
|
|
142
|
-
[1.
|
|
143
|
-
[1.1.
|
|
144
|
-
[1.1.
|
|
157
|
+
|
|
158
|
+
[1.2.1]: https://github.com/thewaltero/mythos-router/releases/tag/v1.2.1
|
|
159
|
+
[1.2.0]: https://github.com/thewaltero/mythos-router/releases/tag/v1.2.0
|
|
160
|
+
[1.1.9]: https://github.com/thewaltero/mythos-router/releases/tag/v1.1.9
|
|
161
|
+
[1.1.8]: https://github.com/thewaltero/mythos-router/releases/tag/v1.1.8
|
|
162
|
+
[1.1.7]: https://github.com/thewaltero/mythos-router/releases/tag/v1.1.7
|
|
163
|
+
[1.1.6]: https://github.com/thewaltero/mythos-router/releases/tag/v1.1.6
|
|
164
|
+
[1.1.3]: https://github.com/thewaltero/mythos-router/releases/tag/v1.1.3
|
|
165
|
+
[1.1.2]: https://github.com/thewaltero/mythos-router/releases/tag/v1.1.2
|
|
166
|
+
[1.1.1]: https://github.com/thewaltero/mythos-router/releases/tag/v1.1.1
|
|
167
|
+
[1.1.0]: https://github.com/thewaltero/mythos-router/releases/tag/v1.1.0
|
|
145
168
|
[1.0.0]: https://github.com/thewaltero/mythos-router/releases/tag/v1.0.0
|
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<img src="assets/banner.png" alt="Mythos Router Banner" width="864" />
|
|
3
3
|
|
|
4
|
+
[](https://github.com/thewaltero/mythos-router/actions/workflows/github-code-scanning/codeql)
|
|
4
5
|
[](https://www.npmjs.com/package/mythos-router)
|
|
5
6
|
[](https://nodejs.org)
|
|
6
7
|
[](https://typescriptlang.org)
|
|
@@ -12,6 +13,11 @@
|
|
|
12
13
|
## Claude Opus 4.7 · Strict Write Discipline · Zero Slop
|
|
13
14
|
**A local CLI power tool for verifiable AI-assisted coding.**
|
|
14
15
|
|
|
16
|
+
<br />
|
|
17
|
+
|
|
18
|
+
[What is this?](#what-is-this) • [Features](#features) • [Installation](#installation) • [Usage](#usage) • [Architecture](#architecture) • [Token Budget](#token-usage--budget) • [SDK](#-sdk-usage-for-agentic-systems)
|
|
19
|
+
|
|
20
|
+
|
|
15
21
|
---
|
|
16
22
|
|
|
17
23
|
### Support the project
|
|
@@ -47,9 +53,13 @@ Zero slop. Zero hallucinated state. Full adaptive thinking.
|
|
|
47
53
|
|
|
48
54
|
| Feature | Description |
|
|
49
55
|
|---------|-------------|
|
|
56
|
+
| **Multi-Provider Fallback** | Auto-routes between Anthropic, DeepSeek, and OpenAI with circuit breakers |
|
|
57
|
+
| **Skills Protocol** | Inject modular expert plugins via YAML frontmatter (`-s mcp`, `-s react`) |
|
|
58
|
+
| **Deterministic Caching** | SQLite-backed caching for zero-cost, zero-latency repetitive reasoning |
|
|
50
59
|
| **Adaptive Thinking** | Opus 4.7 with configurable effort levels (high/medium/low) |
|
|
51
60
|
| **Strict Write Discipline** | Pre/post filesystem snapshots verify every model claim |
|
|
52
61
|
| **Self-Healing Memory** | Authority-based logging with a rebuildable SQLite FTS5 search index |
|
|
62
|
+
| **Auto-Healing TDD** | Pass `--test-cmd` for bounded, error-driven autonomous repair loops |
|
|
53
63
|
| **Correction Turns** | Model gets 2 retries to match filesystem reality, then yields |
|
|
54
64
|
| **Integrity Gate** | `verify` command and startup hashing ensure zero drift |
|
|
55
65
|
| **Token Limiter** | Budget cap with graceful save — progress saved to MEMORY.md, never lose work |
|
|
@@ -91,9 +101,10 @@ As memory approaches capacity, the `dream` command delegates a compression phase
|
|
|
91
101
|
# Install globally
|
|
92
102
|
npm install -g mythos-router
|
|
93
103
|
|
|
94
|
-
# Set your API
|
|
104
|
+
# Set your API keys (Anthropic is primary, others are fallbacks)
|
|
95
105
|
export ANTHROPIC_API_KEY="sk-ant-..."
|
|
96
|
-
|
|
106
|
+
export OPENAI_API_KEY="sk-proj-..."
|
|
107
|
+
export DEEPSEEK_API_KEY="sk-..."
|
|
97
108
|
|
|
98
109
|
# Go
|
|
99
110
|
mythos chat
|
|
@@ -122,6 +133,8 @@ npm run chat
|
|
|
122
133
|
|
|
123
134
|
```bash
|
|
124
135
|
mythos chat # Full power (high effort, Opus 4.7)
|
|
136
|
+
mythos chat -s react # Load the 'react' expert skill
|
|
137
|
+
mythos chat --test-cmd "npm test" # Enable autonomous test-driven self-healing
|
|
125
138
|
mythos chat --effort low # Budget mode (Haiku 3)
|
|
126
139
|
mythos chat --effort medium # Balanced (Sonnet 3.5)
|
|
127
140
|
mythos chat --dry-run # Preview all file changes before executing
|
|
@@ -270,6 +283,12 @@ mythos-router/
|
|
|
270
283
|
│ ├── verify.ts # Codebase ↔ Memory scanner (dry-run aware)
|
|
271
284
|
│ ├── dream.ts # Memory compression (dry-run aware)
|
|
272
285
|
│ └── stats.ts # Budget analytics reporter
|
|
286
|
+
├── src/providers/ # Multi-Provider Orchestration Engine
|
|
287
|
+
│ ├── orchestrator.ts # Adaptive routing, circuit breakers, scoring
|
|
288
|
+
│ ├── pricing.ts # Centralized token cost registry
|
|
289
|
+
│ ├── types.ts # Unified BaseProvider contracts
|
|
290
|
+
│ ├── anthropic.ts # Claude provider
|
|
291
|
+
│ └── openai.ts # Fetch-based OpenAI & DeepSeek provider
|
|
273
292
|
├── test/ # Automated test suite (node:test)
|
|
274
293
|
├── .mythosignore # SWD scan exclusions
|
|
275
294
|
├── MEMORY.md # Auto-generated agentic memory
|
|
@@ -317,7 +336,9 @@ If you prefer to keep it private, add `MEMORY.md` to your `.gitignore`.
|
|
|
317
336
|
|
|
318
337
|
| Env Variable | Required | Description |
|
|
319
338
|
|-------------|----------|-------------|
|
|
320
|
-
| `ANTHROPIC_API_KEY` | ✅ | Your Anthropic API key |
|
|
339
|
+
| `ANTHROPIC_API_KEY` | ✅ | Your Anthropic API key (Primary Provider) |
|
|
340
|
+
| `OPENAI_API_KEY` | ❌ | OpenAI API Key (Fallback Provider) |
|
|
341
|
+
| `DEEPSEEK_API_KEY` | ❌ | DeepSeek API Key (Fallback Provider, reasoning capable) |
|
|
321
342
|
|
|
322
343
|
| File | Purpose |
|
|
323
344
|
|------|---------|
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { UnifiedResponse } from './providers/types.js';
|
|
2
|
+
export interface CacheKeyInput {
|
|
3
|
+
model: string;
|
|
4
|
+
systemPrompt: string;
|
|
5
|
+
messages: Array<{
|
|
6
|
+
role: string;
|
|
7
|
+
content: string;
|
|
8
|
+
}>;
|
|
9
|
+
}
|
|
10
|
+
export declare function generateCacheKey(input: CacheKeyInput): string;
|
|
11
|
+
export declare class ResponseCache {
|
|
12
|
+
private db;
|
|
13
|
+
private ttlMs;
|
|
14
|
+
private enabled;
|
|
15
|
+
constructor(ttlMs?: number, enabled?: boolean);
|
|
16
|
+
private ensureDb;
|
|
17
|
+
get(key: string): UnifiedResponse | null;
|
|
18
|
+
set(key: string, response: UnifiedResponse, model: string): void;
|
|
19
|
+
evictExpired(): number;
|
|
20
|
+
clear(): void;
|
|
21
|
+
stats(): {
|
|
22
|
+
entries: number;
|
|
23
|
+
totalHits: number;
|
|
24
|
+
oldestMs: number;
|
|
25
|
+
};
|
|
26
|
+
close(): void;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AA4B5D,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAG7D;AAGD,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAAwE;IAClF,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAU;gBAEb,KAAK,GAAE,MAAuB,EAAE,OAAO,GAAE,OAAc;IAMnE,OAAO,CAAC,QAAQ;IAgChB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IA0BxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAmBhE,YAAY,IAAI,MAAM;IActB,KAAK,IAAI,IAAI;IAYb,KAAK,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAoBjE,KAAK,IAAI,IAAI;CAMd"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// mythos-router :: cache.ts
|
|
3
|
+
// Deterministic Response Cache — SQLite-backed
|
|
4
|
+
//
|
|
5
|
+
// Rules:
|
|
6
|
+
// - Cache is DISABLED for `chat` (external state changes)
|
|
7
|
+
// - Cache is ACTIVE for `verify` and `dream` (pure reasoning)
|
|
8
|
+
// - Tool invocations BYPASS the cache entirely
|
|
9
|
+
// - Keys use canonical JSON (sorted keys) + SHA-256
|
|
10
|
+
// - TTL-based expiration (default: 1 hour)
|
|
11
|
+
// ─────────────────────────────────────────────────────────────
|
|
12
|
+
import * as fs from 'node:fs';
|
|
13
|
+
import * as path from 'node:path';
|
|
14
|
+
import * as os from 'node:os';
|
|
15
|
+
import { createHash } from 'node:crypto';
|
|
16
|
+
// ── Constants ────────────────────────────────────────────────
|
|
17
|
+
const CACHE_DIR = path.join(os.homedir(), '.mythos-router');
|
|
18
|
+
const CACHE_DB_FILE = path.join(CACHE_DIR, 'cache.db');
|
|
19
|
+
const DEFAULT_TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
20
|
+
// ── Canonical JSON Stringify (sorted keys) ───────────────────
|
|
21
|
+
// Ensures identical objects always produce the same string,
|
|
22
|
+
// regardless of key insertion order.
|
|
23
|
+
function canonicalStringify(obj) {
|
|
24
|
+
if (obj === null || typeof obj !== 'object') {
|
|
25
|
+
return JSON.stringify(obj);
|
|
26
|
+
}
|
|
27
|
+
if (Array.isArray(obj)) {
|
|
28
|
+
return '[' + obj.map(item => canonicalStringify(item)).join(',') + ']';
|
|
29
|
+
}
|
|
30
|
+
const sorted = Object.keys(obj).sort();
|
|
31
|
+
const pairs = sorted.map(key => {
|
|
32
|
+
const val = obj[key];
|
|
33
|
+
return `${JSON.stringify(key)}:${canonicalStringify(val)}`;
|
|
34
|
+
});
|
|
35
|
+
return '{' + pairs.join(',') + '}';
|
|
36
|
+
}
|
|
37
|
+
export function generateCacheKey(input) {
|
|
38
|
+
const payload = canonicalStringify(input);
|
|
39
|
+
return createHash('sha256').update(payload).digest('hex');
|
|
40
|
+
}
|
|
41
|
+
// ── Response Cache ───────────────────────────────────────────
|
|
42
|
+
export class ResponseCache {
|
|
43
|
+
db = null;
|
|
44
|
+
ttlMs;
|
|
45
|
+
enabled;
|
|
46
|
+
constructor(ttlMs = DEFAULT_TTL_MS, enabled = true) {
|
|
47
|
+
this.ttlMs = ttlMs;
|
|
48
|
+
this.enabled = enabled;
|
|
49
|
+
}
|
|
50
|
+
// ── Lazy Initialization ──────────────────────────────────
|
|
51
|
+
ensureDb() {
|
|
52
|
+
if (this.db)
|
|
53
|
+
return this.db;
|
|
54
|
+
// Dynamic import to avoid crash if sqlite is unavailable
|
|
55
|
+
try {
|
|
56
|
+
const { DatabaseSync } = require('node:sqlite');
|
|
57
|
+
if (!fs.existsSync(CACHE_DIR)) {
|
|
58
|
+
fs.mkdirSync(CACHE_DIR, { recursive: true });
|
|
59
|
+
}
|
|
60
|
+
this.db = new DatabaseSync(CACHE_DB_FILE);
|
|
61
|
+
this.db.exec(`
|
|
62
|
+
CREATE TABLE IF NOT EXISTS cache_entries (
|
|
63
|
+
key TEXT PRIMARY KEY,
|
|
64
|
+
response TEXT NOT NULL,
|
|
65
|
+
model TEXT NOT NULL,
|
|
66
|
+
created_at INTEGER NOT NULL,
|
|
67
|
+
hit_count INTEGER DEFAULT 0
|
|
68
|
+
);
|
|
69
|
+
CREATE INDEX IF NOT EXISTS idx_cache_created ON cache_entries(created_at);
|
|
70
|
+
`);
|
|
71
|
+
return this.db;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// SQLite not available — cache is a no-op
|
|
75
|
+
this.enabled = false;
|
|
76
|
+
throw new Error('SQLite not available for caching');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// ── Get cached response ──────────────────────────────────
|
|
80
|
+
get(key) {
|
|
81
|
+
if (!this.enabled)
|
|
82
|
+
return null;
|
|
83
|
+
try {
|
|
84
|
+
const db = this.ensureDb();
|
|
85
|
+
const now = Date.now();
|
|
86
|
+
const cutoff = now - this.ttlMs;
|
|
87
|
+
const stmt = db.prepare('SELECT response, created_at FROM cache_entries WHERE key = ? AND created_at > ?');
|
|
88
|
+
const row = stmt.get(key, cutoff);
|
|
89
|
+
if (!row)
|
|
90
|
+
return null;
|
|
91
|
+
// Update hit count
|
|
92
|
+
db.prepare('UPDATE cache_entries SET hit_count = hit_count + 1 WHERE key = ?').run(key);
|
|
93
|
+
return JSON.parse(row.response);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// ── Store response in cache ──────────────────────────────
|
|
100
|
+
// INVARIANT: Responses with tool calls are NEVER cached.
|
|
101
|
+
set(key, response, model) {
|
|
102
|
+
if (!this.enabled)
|
|
103
|
+
return;
|
|
104
|
+
// Tool Invocation Bypass — never cache responses with tool calls
|
|
105
|
+
if (response.toolCalls.length > 0)
|
|
106
|
+
return;
|
|
107
|
+
try {
|
|
108
|
+
const db = this.ensureDb();
|
|
109
|
+
const serialized = JSON.stringify(response);
|
|
110
|
+
db.prepare('INSERT OR REPLACE INTO cache_entries (key, response, model, created_at, hit_count) VALUES (?, ?, ?, ?, 0)').run(key, serialized, model, Date.now());
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Fail silently — caching is non-critical
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// ── Evict expired entries ────────────────────────────────
|
|
117
|
+
evictExpired() {
|
|
118
|
+
if (!this.enabled)
|
|
119
|
+
return 0;
|
|
120
|
+
try {
|
|
121
|
+
const db = this.ensureDb();
|
|
122
|
+
const cutoff = Date.now() - this.ttlMs;
|
|
123
|
+
const result = db.prepare('DELETE FROM cache_entries WHERE created_at <= ?').run(cutoff);
|
|
124
|
+
return result.changes ?? 0;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// ── Clear entire cache ───────────────────────────────────
|
|
131
|
+
clear() {
|
|
132
|
+
if (!this.enabled)
|
|
133
|
+
return;
|
|
134
|
+
try {
|
|
135
|
+
const db = this.ensureDb();
|
|
136
|
+
db.prepare('DELETE FROM cache_entries').run();
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Fail silently
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// ── Stats ────────────────────────────────────────────────
|
|
143
|
+
stats() {
|
|
144
|
+
if (!this.enabled)
|
|
145
|
+
return { entries: 0, totalHits: 0, oldestMs: 0 };
|
|
146
|
+
try {
|
|
147
|
+
const db = this.ensureDb();
|
|
148
|
+
const countRow = db.prepare('SELECT COUNT(*) as cnt FROM cache_entries').get();
|
|
149
|
+
const hitsRow = db.prepare('SELECT COALESCE(SUM(hit_count), 0) as total FROM cache_entries').get();
|
|
150
|
+
const oldestRow = db.prepare('SELECT MIN(created_at) as oldest FROM cache_entries').get();
|
|
151
|
+
return {
|
|
152
|
+
entries: countRow.cnt,
|
|
153
|
+
totalHits: hitsRow.total,
|
|
154
|
+
oldestMs: oldestRow.oldest ? Date.now() - oldestRow.oldest : 0,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return { entries: 0, totalHits: 0, oldestMs: 0 };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// ── Close ────────────────────────────────────────────────
|
|
162
|
+
close() {
|
|
163
|
+
if (this.db) {
|
|
164
|
+
this.db.close();
|
|
165
|
+
this.db = null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -14,7 +14,7 @@ program
|
|
|
14
14
|
.name('mythos')
|
|
15
15
|
.description('Capybara-tier CLI router — Claude Opus 4.7 with Adaptive Thinking, ' +
|
|
16
16
|
'Strict Write Discipline, and Self-Healing Memory.')
|
|
17
|
-
.version('1.2.
|
|
17
|
+
.version('1.2.1');
|
|
18
18
|
// ── mythos chat ──────────────────────────────────────────────
|
|
19
19
|
program
|
|
20
20
|
.command('chat')
|
|
@@ -26,6 +26,9 @@ program
|
|
|
26
26
|
.option('--dry-run', 'Preview all file operations without executing them')
|
|
27
27
|
.option('--verbose', 'Show detailed SWD traces and memory operations')
|
|
28
28
|
.option('-b, --branch <name>', 'Run session in a new git branch for sandboxed reasoning')
|
|
29
|
+
.option('-t, --test-cmd <cmd>', 'Command to run after successful SWD execution (WARNING: assumes a trusted environment and executes arbitrary shell commands)')
|
|
30
|
+
.option('--max-test-retries <n>', 'Maximum number of times Claude can attempt to fix failing tests', '3')
|
|
31
|
+
.option('-s, --skill <names...>', 'Inject specific expert skills (e.g., -s mcp -s react)')
|
|
29
32
|
.action(async (options) => {
|
|
30
33
|
await chatCommand(options);
|
|
31
34
|
});
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ProviderOrchestrator } from './providers/orchestrator.js';
|
|
2
2
|
import { type EffortLevel } from './config.js';
|
|
3
|
-
export
|
|
4
|
-
role: 'user' | 'assistant';
|
|
5
|
-
content: string;
|
|
6
|
-
}
|
|
3
|
+
export type { Message } from './providers/types.js';
|
|
7
4
|
export interface MythosResponse {
|
|
8
5
|
thinking: string;
|
|
9
6
|
text: string;
|
|
10
7
|
inputTokens: number;
|
|
11
8
|
outputTokens: number;
|
|
9
|
+
/** Provider metadata (new — optional for backward compat) */
|
|
10
|
+
_orchestration?: {
|
|
11
|
+
providerId: string;
|
|
12
|
+
modelId: string;
|
|
13
|
+
fallbackTriggered: boolean;
|
|
14
|
+
incomplete: boolean;
|
|
15
|
+
latencyMs: number;
|
|
16
|
+
};
|
|
12
17
|
}
|
|
18
|
+
export declare function getOrchestrator(): ProviderOrchestrator;
|
|
19
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
13
20
|
export declare function getClient(): Anthropic;
|
|
14
|
-
export declare function streamMessage(messages:
|
|
15
|
-
|
|
21
|
+
export declare function streamMessage(messages: {
|
|
22
|
+
role: 'user' | 'assistant';
|
|
23
|
+
content: string;
|
|
24
|
+
}[], effort?: EffortLevel, onThinkingDelta?: (text: string) => void, onTextDelta?: (text: string) => void): Promise<MythosResponse>;
|
|
25
|
+
export declare function sendMessage(messages: {
|
|
26
|
+
role: 'user' | 'assistant';
|
|
27
|
+
content: string;
|
|
28
|
+
}[], effort?: EffortLevel, systemOverride?: string): Promise<MythosResponse>;
|
|
16
29
|
export declare function formatTokenUsage(resp: MythosResponse): string;
|
|
17
30
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAML,KAAK,WAAW,EACjB,MAAM,aAAa,CAAC;AAIrB,YAAY,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGpD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,cAAc,CAAC,EAAE;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,UAAU,EAAE,OAAO,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAKD,wBAAgB,eAAe,IAAI,oBAAoB,CAyCtD;AAGD,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAG1C,wBAAgB,SAAS,IAAI,SAAS,CAMrC;AAoBD,wBAAsB,aAAa,CACjC,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,EAC3D,MAAM,GAAE,WAAoB,EAC5B,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EACxC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GACnC,OAAO,CAAC,cAAc,CAAC,CAYzB;AAGD,wBAAsB,WAAW,CAC/B,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,EAC3D,MAAM,GAAE,WAAmB,EAC3B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,cAAc,CAAC,CAUzB;AAGD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAe7D"}
|
package/dist/client.js
CHANGED
|
@@ -1,11 +1,51 @@
|
|
|
1
1
|
// ─────────────────────────────────────────────────────────────
|
|
2
2
|
// mythos-router :: client.ts
|
|
3
|
-
//
|
|
3
|
+
// Backward-compatible facade over the Provider Orchestrator
|
|
4
|
+
//
|
|
5
|
+
// This file preserves the original API surface so that existing
|
|
6
|
+
// consumers (chat.ts, dream.ts, verify.ts, SDK users) continue
|
|
7
|
+
// to work without changes. Under the hood, it delegates to the
|
|
8
|
+
// ProviderOrchestrator for retry, fallback, and scoring.
|
|
4
9
|
// ─────────────────────────────────────────────────────────────
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
10
|
+
import { AnthropicProvider } from './providers/anthropic.js';
|
|
11
|
+
import { OpenAIProvider } from './providers/openai.js';
|
|
12
|
+
import { ProviderOrchestrator } from './providers/orchestrator.js';
|
|
13
|
+
import { CAPYBARA_SYSTEM_PROMPT, validateApiKey, getOpenAIKey, getDeepSeekKey, } from './config.js';
|
|
7
14
|
import { c } from './utils.js';
|
|
8
|
-
// ──
|
|
15
|
+
// ── Singleton Orchestrator ───────────────────────────────────
|
|
16
|
+
let _orchestrator = null;
|
|
17
|
+
export function getOrchestrator() {
|
|
18
|
+
if (!_orchestrator) {
|
|
19
|
+
const apiKey = validateApiKey();
|
|
20
|
+
_orchestrator = new ProviderOrchestrator();
|
|
21
|
+
// Primary: Anthropic (always registered)
|
|
22
|
+
_orchestrator.registerProvider(new AnthropicProvider(apiKey), { priority: 0 });
|
|
23
|
+
// Fallback: OpenAI (if OPENAI_API_KEY is set)
|
|
24
|
+
const openaiKey = getOpenAIKey();
|
|
25
|
+
if (openaiKey) {
|
|
26
|
+
_orchestrator.registerProvider(new OpenAIProvider({
|
|
27
|
+
id: 'openai',
|
|
28
|
+
apiKey: openaiKey,
|
|
29
|
+
baseUrl: 'https://api.openai.com/v1',
|
|
30
|
+
defaultModel: 'gpt-4o',
|
|
31
|
+
}), { priority: 1 });
|
|
32
|
+
}
|
|
33
|
+
// Fallback: DeepSeek (if DEEPSEEK_API_KEY is set)
|
|
34
|
+
const deepseekKey = getDeepSeekKey();
|
|
35
|
+
if (deepseekKey) {
|
|
36
|
+
_orchestrator.registerProvider(new OpenAIProvider({
|
|
37
|
+
id: 'deepseek',
|
|
38
|
+
apiKey: deepseekKey,
|
|
39
|
+
baseUrl: 'https://api.deepseek.com/v1',
|
|
40
|
+
defaultModel: 'deepseek-chat',
|
|
41
|
+
supportsThinking: true,
|
|
42
|
+
}), { priority: 2 });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return _orchestrator;
|
|
46
|
+
}
|
|
47
|
+
// ── Legacy getClient() (for direct SDK access if needed) ─────
|
|
48
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
9
49
|
let _client = null;
|
|
10
50
|
export function getClient() {
|
|
11
51
|
if (!_client) {
|
|
@@ -14,113 +54,56 @@ export function getClient() {
|
|
|
14
54
|
}
|
|
15
55
|
return _client;
|
|
16
56
|
}
|
|
17
|
-
// ──
|
|
18
|
-
function
|
|
19
|
-
return messages.map((m, i) => {
|
|
20
|
-
if (m.role !== 'user' && m.role !== 'assistant') {
|
|
21
|
-
throw new Error(`Invalid role at message[${i}]: ${String(m.role)}`);
|
|
22
|
-
}
|
|
23
|
-
if (typeof m.content !== 'string') {
|
|
24
|
-
throw new Error(`Message[${i}] content must be a string`);
|
|
25
|
-
}
|
|
26
|
-
const trimmed = m.content.trim();
|
|
27
|
-
if (trimmed.length === 0) {
|
|
28
|
-
throw new Error(`Empty message content at message[${i}]`);
|
|
29
|
-
}
|
|
30
|
-
return { role: m.role, content: trimmed };
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
// ── Streaming Message ────────────────────────────────────────
|
|
34
|
-
export async function streamMessage(messages, effort = 'high', onThinkingDelta, onTextDelta) {
|
|
35
|
-
const client = getClient();
|
|
36
|
-
const apiMessages = sanitizeMessages(messages);
|
|
37
|
-
let thinkingText = '';
|
|
38
|
-
let responseText = '';
|
|
39
|
-
let inputTokens = 0;
|
|
40
|
-
let outputTokens = 0;
|
|
41
|
-
let stream;
|
|
42
|
-
try {
|
|
43
|
-
stream = await client.messages.stream({
|
|
44
|
-
model: MODELS[effort],
|
|
45
|
-
max_tokens: 16384,
|
|
46
|
-
thinking: { type: 'adaptive' },
|
|
47
|
-
output_config: { effort },
|
|
48
|
-
system: CAPYBARA_SYSTEM_PROMPT,
|
|
49
|
-
messages: apiMessages,
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
catch (err) {
|
|
53
|
-
throw new Error(`Failed to start stream: ${err instanceof Error ? err.message : String(err)}`);
|
|
54
|
-
}
|
|
55
|
-
try {
|
|
56
|
-
for await (const event of stream) {
|
|
57
|
-
if (event.type === 'content_block_delta') {
|
|
58
|
-
const delta = event.delta;
|
|
59
|
-
if (delta.type === 'thinking_delta') {
|
|
60
|
-
thinkingText += delta.thinking;
|
|
61
|
-
onThinkingDelta?.(delta.thinking);
|
|
62
|
-
}
|
|
63
|
-
else if (delta.type === 'text_delta') {
|
|
64
|
-
responseText += delta.text;
|
|
65
|
-
onTextDelta?.(delta.text);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
throw new Error(`Stream interrupted: ${err instanceof Error ? err.message : String(err)}`);
|
|
72
|
-
}
|
|
73
|
-
const finalMessage = await stream.finalMessage();
|
|
74
|
-
inputTokens = finalMessage.usage?.input_tokens ?? 0;
|
|
75
|
-
outputTokens = finalMessage.usage?.output_tokens ?? 0;
|
|
57
|
+
// ── Convert UnifiedResponse → MythosResponse ─────────────────
|
|
58
|
+
function toMythosResponse(unified) {
|
|
76
59
|
return {
|
|
77
|
-
thinking:
|
|
78
|
-
text:
|
|
79
|
-
inputTokens,
|
|
80
|
-
outputTokens,
|
|
60
|
+
thinking: unified.thinking,
|
|
61
|
+
text: unified.text,
|
|
62
|
+
inputTokens: unified.usage.inputTokens,
|
|
63
|
+
outputTokens: unified.usage.outputTokens,
|
|
64
|
+
_orchestration: {
|
|
65
|
+
providerId: unified.metadata.providerId,
|
|
66
|
+
modelId: unified.metadata.modelId,
|
|
67
|
+
fallbackTriggered: unified.metadata.fallbackTriggered,
|
|
68
|
+
incomplete: unified.metadata.incomplete,
|
|
69
|
+
latencyMs: unified.usage.latencyMs,
|
|
70
|
+
},
|
|
81
71
|
};
|
|
82
72
|
}
|
|
83
|
-
// ──
|
|
73
|
+
// ── Streaming Message (backward-compatible API) ──────────────
|
|
74
|
+
export async function streamMessage(messages, effort = 'high', onThinkingDelta, onTextDelta) {
|
|
75
|
+
const orchestrator = getOrchestrator();
|
|
76
|
+
const unified = await orchestrator.streamMessage(messages, {
|
|
77
|
+
systemPrompt: CAPYBARA_SYSTEM_PROMPT,
|
|
78
|
+
maxTokens: 16384,
|
|
79
|
+
effort,
|
|
80
|
+
onThinkingDelta,
|
|
81
|
+
onTextDelta,
|
|
82
|
+
});
|
|
83
|
+
return toMythosResponse(unified);
|
|
84
|
+
}
|
|
85
|
+
// ── Non-streaming Message (backward-compatible API) ──────────
|
|
84
86
|
export async function sendMessage(messages, effort = 'low', systemOverride) {
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
thinking: { type: 'adaptive' },
|
|
93
|
-
output_config: { effort },
|
|
94
|
-
system: systemOverride ?? CAPYBARA_SYSTEM_PROMPT,
|
|
95
|
-
messages: apiMessages,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
throw new Error(`API request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
100
|
-
}
|
|
101
|
-
let thinkingText = '';
|
|
102
|
-
let responseText = '';
|
|
103
|
-
for (const block of response.content) {
|
|
104
|
-
if (block.type === 'thinking') {
|
|
105
|
-
const thinkingBlock = block;
|
|
106
|
-
thinkingText += thinkingBlock.thinking ?? '';
|
|
107
|
-
}
|
|
108
|
-
else if (block.type === 'text') {
|
|
109
|
-
responseText += block.text;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
thinking: thinkingText,
|
|
114
|
-
text: responseText,
|
|
115
|
-
inputTokens: response.usage?.input_tokens ?? 0,
|
|
116
|
-
outputTokens: response.usage?.output_tokens ?? 0,
|
|
117
|
-
};
|
|
87
|
+
const orchestrator = getOrchestrator();
|
|
88
|
+
const unified = await orchestrator.sendMessage(messages, {
|
|
89
|
+
systemPrompt: systemOverride ?? CAPYBARA_SYSTEM_PROMPT,
|
|
90
|
+
maxTokens: 8192,
|
|
91
|
+
effort,
|
|
92
|
+
});
|
|
93
|
+
return toMythosResponse(unified);
|
|
118
94
|
}
|
|
119
95
|
// ── Token cost display ───────────────────────────────────────
|
|
120
96
|
export function formatTokenUsage(resp) {
|
|
121
97
|
const total = resp.inputTokens + resp.outputTokens;
|
|
98
|
+
const providerInfo = resp._orchestration
|
|
99
|
+
? ` ${c.dim}via ${c.cyan}${resp._orchestration.providerId}${c.dim}/${resp._orchestration.modelId}${c.reset}`
|
|
100
|
+
: '';
|
|
101
|
+
const fallbackInfo = resp._orchestration?.fallbackTriggered
|
|
102
|
+
? ` ${c.yellow}(fallback)${c.reset}`
|
|
103
|
+
: '';
|
|
122
104
|
return (`${c.dim}tokens: ${c.cyan}${resp.inputTokens.toLocaleString()}${c.dim} in · ` +
|
|
123
105
|
`${c.cyan}${resp.outputTokens.toLocaleString()}${c.dim} out · ` +
|
|
124
|
-
`${c.yellow}${total.toLocaleString()}${c.dim} total${c.reset}`
|
|
106
|
+
`${c.yellow}${total.toLocaleString()}${c.dim} total${c.reset}` +
|
|
107
|
+
providerInfo + fallbackInfo);
|
|
125
108
|
}
|
|
126
109
|
//# sourceMappingURL=client.js.map
|