mythos-router 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 thewaltero
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,229 @@
1
+ <div align="center">
2
+
3
+ # MYTHOS
4
+
5
+ ### Capybara Tier ยท Claude Opus 4.6 ยท Strict Write Discipline
6
+
7
+ **The leaked Anthropic reasoning protocol. Running locally.**
8
+
9
+ [![npm](https://img.shields.io/npm/v/mythos-router?style=flat-square&color=cc785c)](https://www.npmjs.com/package/mythos-router)
10
+ [![Node.js](https://img.shields.io/badge/Node.js-20+-339933?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org)
11
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-3178C6?style=flat-square&logo=typescript&logoColor=white)](https://typescriptlang.org)
12
+ [![Claude](https://img.shields.io/badge/Claude-Opus_4.6-cc785c?style=flat-square)](https://anthropic.com)
13
+ [![License](https://img.shields.io/badge/License-MIT-green?style=flat-square)](./LICENSE)
14
+ [![GitHub stars](https://img.shields.io/github/stars/thewaltero/mythos-router?style=social)](https://github.com/thewaltero/mythos-router)
15
+
16
+ <p align="center">
17
+ <img src="assets/demo.png" alt="mythos-router terminal demo" width="700" />
18
+ </p>
19
+
20
+ ```bash
21
+ # Try it now
22
+ npx mythos-router chat
23
+ ```
24
+
25
+ </div>
26
+
27
+ ---
28
+
29
+ ## What is this?
30
+
31
+ **mythos-router** is a local CLI power tool that implements the *leaked Anthropic "Capybara" reasoning protocol* โ€” the specialized tier designed for PhD-level reasoning and cybersecurity analysis.
32
+
33
+ Unlike standard Claude wrappers, mythos-router enforces **Strict Write Discipline (SWD)**: every file operation the AI claims to perform is *verified against the actual filesystem*. If the model hallucinates a write, it gets a Correction Turn. If it fails twice, it yields to the human.
34
+
35
+ Zero slop. Zero hallucinated state. Full adaptive thinking.
36
+
37
+ ---
38
+
39
+ ## Features
40
+
41
+ | Feature | Description |
42
+ |---------|-------------|
43
+ | ๐Ÿง  **Adaptive Thinking** | Opus 4.6 with configurable effort levels (high/medium/low) |
44
+ | ๐Ÿ”’ **Strict Write Discipline** | Pre/post filesystem snapshots verify every model claim |
45
+ | ๐Ÿ’ค **Self-Healing Memory** | `MEMORY.md` logs every action; auto-compresses via "Dream" |
46
+ | โŸฒ **Correction Turns** | Model gets 2 retries to match filesystem reality, then yields |
47
+ | ๐Ÿ“‹ **Drift Detection** | `verify` command syncs codebase state with memory |
48
+ | ๐Ÿš€ **Zero Build** | Runs directly via `tsx` โ€” no compile step in dev |
49
+
50
+ ---
51
+
52
+ ## Installation
53
+
54
+ ### Quick Start (npm)
55
+
56
+ ```bash
57
+ # Install globally
58
+ npm install -g mythos-router
59
+
60
+ # Set your API key
61
+ export ANTHROPIC_API_KEY="sk-ant-..."
62
+ # Windows: $env:ANTHROPIC_API_KEY = "sk-ant-..."
63
+
64
+ # Go
65
+ mythos chat
66
+ ```
67
+
68
+ ### Or try without installing
69
+
70
+ ```bash
71
+ npx mythos-router chat
72
+ ```
73
+
74
+ ### From Source
75
+
76
+ ```bash
77
+ git clone https://github.com/thewaltero/mythos-router.git
78
+ cd mythos-router
79
+ npm install
80
+ npm run chat
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Usage
86
+
87
+ ### `mythos chat` โ€” Interactive Capybara Session
88
+
89
+ ```bash
90
+ mythos chat # Full power (high effort)
91
+ mythos chat --effort low # Budget mode
92
+ mythos chat --effort medium # Balanced
93
+ ```
94
+
95
+ In-session commands:
96
+ - `/exit` โ€” End session
97
+ - `/memory` โ€” Show memory status
98
+ - `/clear` โ€” Clear conversation (memory persists)
99
+
100
+ ### `mythos verify` โ€” Zero-Drift Codebase Scan
101
+
102
+ ```bash
103
+ mythos verify
104
+ ```
105
+
106
+ Scans every file in your project and cross-references against `MEMORY.md`:
107
+ - โœ… **Verified** โ€” File state matches memory
108
+ - โš ๏ธ **Drift** โ€” File changed but memory doesn't reflect it
109
+ - โŒ **Missing** โ€” Memory references a file that doesn't exist
110
+
111
+ ### `mythos dream` โ€” Memory Compression
112
+
113
+ ```bash
114
+ mythos dream # Auto-compress when needed
115
+ mythos dream --force # Force compression
116
+ ```
117
+
118
+ When `MEMORY.md` exceeds 100 entries, older logs are compressed into a summary block using Claude (low effort, minimal token burn). Recent entries are preserved intact.
119
+
120
+ ---
121
+
122
+ ## Architecture
123
+
124
+ ```
125
+ mythos-router/
126
+ โ”œโ”€โ”€ src/
127
+ โ”‚ โ”œโ”€โ”€ cli.ts # Commander.js entry point
128
+ โ”‚ โ”œโ”€โ”€ config.ts # Capybara system prompt + constants
129
+ โ”‚ โ”œโ”€โ”€ client.ts # Anthropic SDK (adaptive thinking)
130
+ โ”‚ โ”œโ”€โ”€ swd.ts # Strict Write Discipline engine
131
+ โ”‚ โ”œโ”€โ”€ memory.ts # MEMORY.md self-healing manager
132
+ โ”‚ โ”œโ”€โ”€ utils.ts # Terminal formatting (zero-dep)
133
+ โ”‚ โ””โ”€โ”€ commands/
134
+ โ”‚ โ”œโ”€โ”€ chat.ts # Interactive REPL
135
+ โ”‚ โ”œโ”€โ”€ verify.ts # Codebase โ†” Memory scanner
136
+ โ”‚ โ””โ”€โ”€ dream.ts # Memory compression
137
+ โ”œโ”€โ”€ .mythosignore # SWD scan exclusions
138
+ โ”œโ”€โ”€ MEMORY.md # Auto-generated agentic memory
139
+ โ””โ”€โ”€ AGENTS.md # Project conventions
140
+ ```
141
+
142
+ ### The SWD Protocol
143
+
144
+ ```
145
+ User Input
146
+ โ”‚
147
+ โ–ผ
148
+ [Pre-Snapshot] โ”€โ”€ filesystem state captured
149
+ โ”‚
150
+ โ–ผ
151
+ [Claude Opus 4.6] โ”€โ”€ adaptive thinking (high effort)
152
+ โ”‚
153
+ โ–ผ
154
+ [Parse FILE_ACTION blocks] โ”€โ”€ extract claimed operations
155
+ โ”‚
156
+ โ–ผ
157
+ [Post-Snapshot] โ”€โ”€ filesystem state re-captured
158
+ โ”‚
159
+ โ–ผ
160
+ [Verify] โ”€โ”€ before vs. after vs. model claims
161
+ โ”‚
162
+ โ”œโ”€โ”€ โœ… All verified โ†’ Log to MEMORY.md
163
+ โ”‚
164
+ โ””โ”€โ”€ โŒ Mismatch โ†’ Correction Turn (max 2 retries)
165
+ โ”‚
166
+ โ””โ”€โ”€ Still failing โ†’ Yield to human
167
+ ```
168
+
169
+ ---
170
+
171
+ ## MEMORY.md โ€” Should You Commit It?
172
+
173
+ **Yes.** `MEMORY.md` is designed to be committed to your repository. It becomes a "collaborative brain" where:
174
+ - Multiple developers can see what the AI did in previous sessions
175
+ - Different AI agents can reference past context
176
+ - You get a full audit trail of every AI-assisted file operation
177
+
178
+ If you prefer to keep it private, add `MEMORY.md` to your `.gitignore`.
179
+
180
+ ---
181
+
182
+ ## The Capybara System Prompt
183
+
184
+ The system prompt implements the leaked Anthropic protocol:
185
+
186
+ > **Tier: Capybara** (Specialized in Cybersecurity & PhD Reasoning)
187
+ >
188
+ > Follow 'Strict Write Discipline' and never hallucinate filesystem state.
189
+ > Every file operation must be wrapped in `[FILE_ACTION]` blocks for verification.
190
+
191
+ The model is instructed to emit machine-readable delimiters around every file operation, making SWD verification 100% reliable.
192
+
193
+ ---
194
+
195
+ ## Configuration
196
+
197
+ | Env Variable | Required | Description |
198
+ |-------------|----------|-------------|
199
+ | `ANTHROPIC_API_KEY` | โœ… | Your Anthropic API key |
200
+
201
+ | File | Purpose |
202
+ |------|---------|
203
+ | `.mythosignore` | Patterns to exclude from SWD scanning |
204
+ | `MEMORY.md` | Auto-generated agentic memory log |
205
+
206
+ ---
207
+
208
+ ## Token Usage
209
+
210
+ | Mode | Typical Cost Per Turn |
211
+ |------|----------------------|
212
+ | `--effort high` | Full Opus 4.6 pricing (deep reasoning) |
213
+ | `--effort medium` | Balanced โ€” good for most tasks |
214
+ | `--effort low` | Minimal thinking โ€” quick answers |
215
+ | `dream` | Low effort summarization (~500 tokens) |
216
+
217
+ Token counts are displayed after every chat response.
218
+
219
+ ---
220
+
221
+ ## License
222
+
223
+ MIT
224
+
225
+ ---
226
+
227
+ <div align="center">
228
+ <sub>Built with the leaked Capybara protocol. No affiliation with Anthropic. Use responsibly.</sub>
229
+ </div>
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
3
+ // mythos-router :: cli.ts
4
+ // Main CLI entry point โ€” Commander.js program
5
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
6
+ import { Command } from 'commander';
7
+ import { chatCommand } from './commands/chat.js';
8
+ import { verifyCommand } from './commands/verify.js';
9
+ import { dreamCommand } from './commands/dream.js';
10
+ const program = new Command();
11
+ program
12
+ .name('mythos')
13
+ .description('Capybara-tier CLI router โ€” Claude Opus 4.6 with Adaptive Thinking, ' +
14
+ 'Strict Write Discipline, and Self-Healing Memory.')
15
+ .version('1.0.0');
16
+ // โ”€โ”€ mythos chat โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
17
+ program
18
+ .command('chat')
19
+ .description('Interactive chat with the Capybara thinking protocol')
20
+ .option('-e, --effort <level>', 'Thinking effort: high (default), medium, low', 'high')
21
+ .action(async (options) => {
22
+ await chatCommand(options);
23
+ });
24
+ // โ”€โ”€ mythos verify โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
25
+ program
26
+ .command('verify')
27
+ .description('Scan codebase and sync with MEMORY.md for zero drift')
28
+ .action(async () => {
29
+ await verifyCommand();
30
+ });
31
+ // โ”€โ”€ mythos dream โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
32
+ program
33
+ .command('dream')
34
+ .description('Summarize and compress agentic memory for context optimization')
35
+ .option('-f, --force', 'Force dream even with few entries', false)
36
+ .action(async (options) => {
37
+ await dreamCommand(options);
38
+ });
39
+ // โ”€โ”€ Default: show help โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
40
+ if (process.argv.length <= 2) {
41
+ // Import banner and show it before help
42
+ import('./utils.js').then(({ BANNER }) => {
43
+ console.log(BANNER);
44
+ program.help();
45
+ });
46
+ }
47
+ else {
48
+ program.parse();
49
+ }
50
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,gEAAgE;AAChE,2BAA2B;AAC3B,+CAA+C;AAC/C,gEAAgE;AAEhE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CACV,qEAAqE;IACnE,mDAAmD,CACtD;KACA,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,gEAAgE;AAChE,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CACL,sBAAsB,EACtB,8CAA8C,EAC9C,MAAM,CACP;KACA,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEL,gEAAgE;AAChE,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,aAAa,EAAE,CAAC;AACxB,CAAC,CAAC,CAAC;AAEL,gEAAgE;AAChE,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,aAAa,EAAE,mCAAmC,EAAE,KAAK,CAAC;KACjE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEL,gEAAgE;AAChE,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;IAC7B,wCAAwC;IACxC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;QACvC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,OAAO,CAAC,IAAI,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,KAAK,EAAE,CAAC;AAClB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { type EffortLevel } from './config.js';
3
+ export interface Message {
4
+ role: 'user' | 'assistant';
5
+ content: string;
6
+ }
7
+ export interface MythosResponse {
8
+ thinking: string;
9
+ text: string;
10
+ inputTokens: number;
11
+ outputTokens: number;
12
+ }
13
+ export declare function getClient(): Anthropic;
14
+ export declare function streamMessage(messages: Message[], effort?: EffortLevel, onThinkingDelta?: (text: string) => void, onTextDelta?: (text: string) => void): Promise<MythosResponse>;
15
+ export declare function sendMessage(messages: Message[], effort?: EffortLevel, systemOverride?: string): Promise<MythosResponse>;
16
+ export declare function formatTokenUsage(resp: MythosResponse): string;
17
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAKA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD,wBAAgB,SAAS,IAAI,SAAS,CAMrC;AAGD,wBAAsB,aAAa,CACjC,QAAQ,EAAE,OAAO,EAAE,EACnB,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,CA8CzB;AAGD,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,GAAE,WAAmB,EAC3B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,cAAc,CAAC,CAkCzB;AAGD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAO7D"}
package/dist/client.js ADDED
@@ -0,0 +1,98 @@
1
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
2
+ // mythos-router :: client.ts
3
+ // Anthropic SDK client with adaptive thinking
4
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
5
+ import Anthropic from '@anthropic-ai/sdk';
6
+ import { MODEL_ID, CAPYBARA_SYSTEM_PROMPT, validateApiKey, } from './config.js';
7
+ import { c } from './utils.js';
8
+ // โ”€โ”€ Client Factory โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
9
+ let _client = null;
10
+ export function getClient() {
11
+ if (!_client) {
12
+ const apiKey = validateApiKey();
13
+ _client = new Anthropic({ apiKey });
14
+ }
15
+ return _client;
16
+ }
17
+ // โ”€โ”€ Streaming Message โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
18
+ export async function streamMessage(messages, effort = 'high', onThinkingDelta, onTextDelta) {
19
+ const client = getClient();
20
+ const apiMessages = messages.map((m) => ({
21
+ role: m.role,
22
+ content: m.content,
23
+ }));
24
+ let thinkingText = '';
25
+ let responseText = '';
26
+ let inputTokens = 0;
27
+ let outputTokens = 0;
28
+ const stream = await client.messages.stream({
29
+ model: MODEL_ID,
30
+ max_tokens: 16384,
31
+ thinking: { type: 'adaptive' },
32
+ output_config: { effort },
33
+ system: CAPYBARA_SYSTEM_PROMPT,
34
+ messages: apiMessages,
35
+ });
36
+ for await (const event of stream) {
37
+ if (event.type === 'content_block_delta') {
38
+ const delta = event.delta;
39
+ if (delta.type === 'thinking_delta') {
40
+ thinkingText += delta.thinking;
41
+ onThinkingDelta?.(delta.thinking);
42
+ }
43
+ else if (delta.type === 'text_delta') {
44
+ responseText += delta.text;
45
+ onTextDelta?.(delta.text);
46
+ }
47
+ }
48
+ }
49
+ const finalMessage = await stream.finalMessage();
50
+ inputTokens = finalMessage.usage?.input_tokens ?? 0;
51
+ outputTokens = finalMessage.usage?.output_tokens ?? 0;
52
+ return {
53
+ thinking: thinkingText,
54
+ text: responseText,
55
+ inputTokens,
56
+ outputTokens,
57
+ };
58
+ }
59
+ // โ”€โ”€ Non-streaming Message (for Dream/Verify) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
60
+ export async function sendMessage(messages, effort = 'low', systemOverride) {
61
+ const client = getClient();
62
+ const apiMessages = messages.map((m) => ({
63
+ role: m.role,
64
+ content: m.content,
65
+ }));
66
+ const response = await client.messages.create({
67
+ model: MODEL_ID,
68
+ max_tokens: 8192,
69
+ thinking: { type: 'adaptive' },
70
+ output_config: { effort },
71
+ system: systemOverride ?? CAPYBARA_SYSTEM_PROMPT,
72
+ messages: apiMessages,
73
+ });
74
+ let thinkingText = '';
75
+ let responseText = '';
76
+ for (const block of response.content) {
77
+ if (block.type === 'thinking') {
78
+ thinkingText += block.thinking ?? '';
79
+ }
80
+ else if (block.type === 'text') {
81
+ responseText += block.text;
82
+ }
83
+ }
84
+ return {
85
+ thinking: thinkingText,
86
+ text: responseText,
87
+ inputTokens: response.usage?.input_tokens ?? 0,
88
+ outputTokens: response.usage?.output_tokens ?? 0,
89
+ };
90
+ }
91
+ // โ”€โ”€ Token cost display โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
92
+ export function formatTokenUsage(resp) {
93
+ const total = resp.inputTokens + resp.outputTokens;
94
+ return (`${c.dim}tokens: ${c.cyan}${resp.inputTokens.toLocaleString()}${c.dim} in ยท ` +
95
+ `${c.cyan}${resp.outputTokens.toLocaleString()}${c.dim} out ยท ` +
96
+ `${c.yellow}${total.toLocaleString()}${c.dim} total${c.reset}`);
97
+ }
98
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function chatCommand(options: {
2
+ effort?: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/commands/chat.ts"],"names":[],"mappings":"AA8BA,wBAAsB,WAAW,CAAC,OAAO,EAAE;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuKhB"}
@@ -0,0 +1,214 @@
1
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
2
+ // mythos-router :: commands/chat.ts
3
+ // Interactive REPL with Capybara thinking protocol
4
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
5
+ import * as readline from 'node:readline';
6
+ import { resolve } from 'node:path';
7
+ import { readdirSync } from 'node:fs';
8
+ import { streamMessage, formatTokenUsage, } from '../client.js';
9
+ import { snapshotFiles, runSWD, printSWDResults, parseFileActions, } from '../swd.js';
10
+ import { appendEntry, needsDream, printMemoryStatus, getMemoryContext, } from '../memory.js';
11
+ import { MAX_CORRECTION_RETRIES } from '../config.js';
12
+ import { c, Spinner, BANNER, hr } from '../utils.js';
13
+ // โ”€โ”€ Chat Command โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
14
+ export async function chatCommand(options) {
15
+ const effort = (options.effort ?? 'high');
16
+ console.log(BANNER);
17
+ console.log(`${c.dim} effort: ${c.cyan}${effort}${c.dim} ยท model: ${c.cyan}claude-opus-4-6${c.dim} ยท swd: ${c.green}active${c.reset}`);
18
+ printMemoryStatus();
19
+ console.log(hr());
20
+ console.log(`${c.dim} Type your message. Use ${c.cyan}/exit${c.dim} to quit, ${c.cyan}/dream${c.dim} to compress memory.${c.reset}\n`);
21
+ const rl = readline.createInterface({
22
+ input: process.stdin,
23
+ output: process.stdout,
24
+ prompt: `${c.green}โฏ${c.reset} `,
25
+ });
26
+ const conversationHistory = [];
27
+ const spinner = new Spinner();
28
+ // Inject memory context as first user message context
29
+ const memCtx = getMemoryContext();
30
+ if (memCtx) {
31
+ conversationHistory.push({
32
+ role: 'user',
33
+ content: `[MEMORY CONTEXT โ€” Previous session state]\n${memCtx}\n[/MEMORY CONTEXT]\n\nAcknowledge memory loaded. Ready for instructions.`,
34
+ });
35
+ conversationHistory.push({
36
+ role: 'assistant',
37
+ content: 'Memory loaded. Capybara tier active. Strict Write Discipline engaged. Ready.',
38
+ });
39
+ }
40
+ rl.prompt();
41
+ rl.on('line', async (line) => {
42
+ const input = line.trim();
43
+ if (!input) {
44
+ rl.prompt();
45
+ return;
46
+ }
47
+ // Handle commands
48
+ if (input === '/exit' || input === '/quit' || input === '/q') {
49
+ console.log(`\n${c.dim}Capybara signing off. ๐Ÿพ${c.reset}\n`);
50
+ rl.close();
51
+ process.exit(0);
52
+ }
53
+ if (input === '/dream') {
54
+ console.log(`${c.dim}Use ${c.cyan}mythos dream${c.dim} command for memory compression.${c.reset}`);
55
+ rl.prompt();
56
+ return;
57
+ }
58
+ if (input === '/memory') {
59
+ printMemoryStatus();
60
+ rl.prompt();
61
+ return;
62
+ }
63
+ if (input === '/clear') {
64
+ conversationHistory.length = 0;
65
+ console.log(`${c.dim}Conversation cleared. Memory persists in MEMORY.md.${c.reset}`);
66
+ rl.prompt();
67
+ return;
68
+ }
69
+ // โ”€โ”€ Pre-SWD: Snapshot files in CWD โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
70
+ const cwdFiles = shallowScan(process.cwd());
71
+ const beforeSnapshots = snapshotFiles(cwdFiles);
72
+ // Add user message
73
+ conversationHistory.push({ role: 'user', content: input });
74
+ // โ”€โ”€ Stream response โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
75
+ spinner.start('Capybara is thinking...');
76
+ let thinkingStarted = false;
77
+ let streamStarted = false;
78
+ try {
79
+ const response = await streamMessage(conversationHistory, effort,
80
+ // onThinkingDelta
81
+ (delta) => {
82
+ if (!thinkingStarted) {
83
+ spinner.stop();
84
+ process.stdout.write(`\n${c.dim}${c.italic}๐Ÿ’ญ `);
85
+ thinkingStarted = true;
86
+ }
87
+ // Show a condensed version of thinking
88
+ const condensed = delta.replace(/\n/g, ' ').slice(0, 200);
89
+ process.stdout.write(`${c.dim}${condensed}`);
90
+ },
91
+ // onTextDelta
92
+ (delta) => {
93
+ if (!streamStarted) {
94
+ if (thinkingStarted) {
95
+ process.stdout.write(`${c.reset}\n\n`);
96
+ }
97
+ else {
98
+ spinner.stop();
99
+ process.stdout.write('\n');
100
+ }
101
+ streamStarted = true;
102
+ }
103
+ process.stdout.write(delta);
104
+ });
105
+ if (!streamStarted) {
106
+ spinner.stop();
107
+ process.stdout.write('\n' + response.text);
108
+ }
109
+ process.stdout.write('\n');
110
+ // Add to history
111
+ conversationHistory.push({ role: 'assistant', content: response.text });
112
+ // โ”€โ”€ SWD Check โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
113
+ const swdResult = runSWD(response.text, beforeSnapshots);
114
+ printSWDResults(swdResult);
115
+ // Correction loop
116
+ if (!swdResult.verified && swdResult.correctionPrompt) {
117
+ await correctionLoop(conversationHistory, swdResult.correctionPrompt, beforeSnapshots, effort, spinner);
118
+ }
119
+ // โ”€โ”€ Memory Write โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
120
+ const actionSummary = summarizeActions(response.text, input);
121
+ const verifyStatus = swdResult.verified
122
+ ? 'โœ… verified'
123
+ : `โš ๏ธ ${swdResult.actions.filter((a) => a.status !== 'verified').length} issues`;
124
+ appendEntry(actionSummary, verifyStatus);
125
+ // Token usage
126
+ console.log(`\n${formatTokenUsage(response)}`);
127
+ // Dream check
128
+ if (needsDream()) {
129
+ console.log(`\n${c.yellow}๐Ÿ’ค Memory approaching capacity. Run ${c.cyan}mythos dream${c.yellow} to compress.${c.reset}`);
130
+ }
131
+ }
132
+ catch (err) {
133
+ spinner.stop();
134
+ console.error(`\n${c.red}โœ– API Error: ${err.message}${c.reset}`);
135
+ // Remove the failed user message from history
136
+ conversationHistory.pop();
137
+ }
138
+ console.log(hr());
139
+ rl.prompt();
140
+ });
141
+ rl.on('close', () => {
142
+ process.exit(0);
143
+ });
144
+ }
145
+ // โ”€โ”€ Correction Loop โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
146
+ async function correctionLoop(history, correctionPrompt, initialSnapshots, effort, spinner) {
147
+ for (let attempt = 1; attempt <= MAX_CORRECTION_RETRIES; attempt++) {
148
+ console.log(`\n${c.yellow}โŸฒ SWD Correction Turn ${attempt}/${MAX_CORRECTION_RETRIES}${c.reset}`);
149
+ history.push({ role: 'user', content: correctionPrompt });
150
+ spinner.start(`Correction attempt ${attempt}...`);
151
+ try {
152
+ const correctionResponse = await streamMessage(history, effort, undefined, (delta) => {
153
+ if (spinner)
154
+ spinner.stop();
155
+ process.stdout.write(delta);
156
+ });
157
+ process.stdout.write('\n');
158
+ history.push({
159
+ role: 'assistant',
160
+ content: correctionResponse.text,
161
+ });
162
+ const swdResult = runSWD(correctionResponse.text, initialSnapshots);
163
+ printSWDResults(swdResult);
164
+ if (swdResult.verified) {
165
+ console.log(`${c.green}โœ” Correction successful.${c.reset}`);
166
+ return;
167
+ }
168
+ if (attempt >= MAX_CORRECTION_RETRIES) {
169
+ console.log(`\n${c.red}โœ– Max corrections reached. Yielding to human.${c.reset}`);
170
+ appendEntry('SWD: Max corrections reached', 'โŒ Yielded to human after ' + MAX_CORRECTION_RETRIES + ' attempts');
171
+ return;
172
+ }
173
+ if (swdResult.correctionPrompt) {
174
+ correctionPrompt = swdResult.correctionPrompt.replace(/You have \d+ correction attempts remaining\./, `You have ${MAX_CORRECTION_RETRIES - attempt} correction attempt(s) remaining.`);
175
+ }
176
+ }
177
+ catch (err) {
178
+ spinner.stop();
179
+ console.error(`${c.red}โœ– Correction failed: ${err.message}${c.reset}`);
180
+ return;
181
+ }
182
+ }
183
+ }
184
+ // โ”€โ”€ Helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
185
+ function shallowScan(dir) {
186
+ const results = [];
187
+ try {
188
+ const entries = readdirSync(dir, { withFileTypes: true });
189
+ for (const entry of entries) {
190
+ if (entry.name.startsWith('.') ||
191
+ entry.name === 'node_modules' ||
192
+ entry.name === 'dist') {
193
+ continue;
194
+ }
195
+ const full = resolve(dir, entry.name);
196
+ if (entry.isFile()) {
197
+ results.push(full);
198
+ }
199
+ }
200
+ }
201
+ catch {
202
+ // ignore
203
+ }
204
+ return results;
205
+ }
206
+ function summarizeActions(output, userInput) {
207
+ const actions = parseFileActions(output);
208
+ if (actions.length > 0) {
209
+ return actions.map((a) => `${a.operation}: ${a.path}`).join('; ');
210
+ }
211
+ // Fallback: first 80 chars of user input
212
+ return `chat: ${userInput.slice(0, 80)}`;
213
+ }
214
+ //# sourceMappingURL=chat.js.map