@dastageer_44/eco-code 1.1.0 → 1.1.2
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/README.md +54 -72
- package/dist/config.d.ts +7 -1
- package/dist/config.js +62 -4
- package/dist/config.js.map +1 -1
- package/dist/harness/agent.d.ts +8 -2
- package/dist/harness/agent.js +66 -20
- package/dist/harness/agent.js.map +1 -1
- package/dist/harness/context.d.ts +6 -1
- package/dist/harness/context.js +57 -6
- package/dist/harness/context.js.map +1 -1
- package/dist/index.js +197 -40
- package/dist/index.js.map +1 -1
- package/dist/tools/file-ops.js +7 -0
- package/dist/tools/file-ops.js.map +1 -1
- package/dist/tools/index.js +14 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/ui/banner.d.ts +1 -1
- package/dist/ui/banner.js +12 -8
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/markdown.d.ts +1 -0
- package/dist/ui/markdown.js +78 -0
- package/dist/ui/markdown.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,105 +1,87 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
> Powered by OpenRouter free models with dynamic discovery and a taste-adaptation harness.
|
|
3
|
+
# 🌍 eco-code
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
[](https://npmjs.com/package/eco-code)
|
|
8
|
-
[](https://nodejs.org/)
|
|
5
|
+
### The coding agent that does it all. Learns the way you code. Until coding feels like thinking.
|
|
9
6
|
|
|
10
|
-
|
|
7
|
+
**Code 10× faster. Reviews, 2× quicker. Bugs 5× fewer.** <br>
|
|
8
|
+
*Powered by 100% free open-source frontier models via OpenRouter.*
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
[](https://www.npmjs.com/package/@dastageer_44/eco-code)
|
|
11
|
+
[](https://opensource.org/licenses/MIT)
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<br>
|
|
16
|
+
|
|
17
|
+
## 🚀 Quick Install
|
|
18
|
+
|
|
19
|
+
Get started instantly! Copy the command below for your operating system to install `eco-code` globally on your machine.
|
|
20
|
+
|
|
21
|
+
### 🪟 Windows (PowerShell / Command Prompt)
|
|
22
|
+
```powershell
|
|
23
|
+
npm install -g @dastageer_44/eco-code
|
|
17
24
|
```
|
|
18
25
|
|
|
19
|
-
###
|
|
26
|
+
### 🍎 macOS
|
|
20
27
|
```bash
|
|
21
|
-
npm install -g eco-code
|
|
22
|
-
eco-code
|
|
28
|
+
sudo npm install -g @dastageer_44/eco-code
|
|
23
29
|
```
|
|
24
30
|
|
|
25
|
-
###
|
|
31
|
+
### 🐧 Linux
|
|
26
32
|
```bash
|
|
27
|
-
npm
|
|
33
|
+
sudo npm install -g @dastageer_44/eco-code
|
|
28
34
|
```
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
## ✨ Features
|
|
33
|
-
|
|
34
|
-
- **Zero-Cost Coding**: Automatically queries OpenRouter's live API to discover and connect to available **free tier models** (Qwen 2.5 Coder, DeepSeek, Llama 3.3, Gemini Flash, etc.) at $0/token.
|
|
35
|
-
- **Autonomous Tool Harness**: Equipped with file inspection, line-level editing, creation, directory exploration, and shell command execution.
|
|
36
|
-
- **"Taste" Adaptation Engine**: Inspired by modern meta-agent research (such as Command Code), `eco-code` maintains a `.agent/taste.md` style profile that learns your repository conventions, testing frameworks, and formatting preferences.
|
|
37
|
-
- **Dynamic Model Switching**: Switch between available free models on-the-fly using `/model`.
|
|
38
|
-
- **Direct Shell Escape**: Prefix any command with `!` (e.g. `!git status`, `!npm test`) to run terminal commands without exiting.
|
|
39
|
-
- **Auto-Update Notifier**: Notifies you directly in your terminal whenever a new version is released.
|
|
36
|
+
*(Note: GitHub and npm automatically add a handy "Copy" button to the top right of these code blocks!)*
|
|
40
37
|
|
|
41
38
|
---
|
|
42
39
|
|
|
43
|
-
##
|
|
40
|
+
## ⚡ Why eco-code?
|
|
44
41
|
|
|
45
|
-
|
|
42
|
+
While most coding agents drain expensive API credits, `eco-code` bridges the **Harness Gap**. By engineering a hyper-optimized deterministic runtime—complete with auto-repairing JSON tool calls, chunked file reading, and asynchronous background shells—we make free models (like *DeepSeek*, *Qwen*, and *Llama*) perform like expensive proprietary models.
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
| `/taste` | View or add directives to the project taste memory (`.agent/taste.md`) |
|
|
52
|
-
| `/key` | Update or rotate your OpenRouter API key |
|
|
53
|
-
| `/clear` | Reset conversation history & context |
|
|
54
|
-
| `!<command>` | Execute a direct terminal command (e.g. `!git diff`, `!npm run build`) |
|
|
55
|
-
| `/exit` | Exit the CLI agent |
|
|
44
|
+
* **💸 100% Free Inference:** Automatically scrapes OpenRouter for $0/token models.
|
|
45
|
+
* **🧠 Taste Engine:** Learns your specific coding style and injects it into every prompt.
|
|
46
|
+
* **🛡️ Token Optimized:** Prevents context blowouts with 2000-line read limits and streaming shell cursors.
|
|
47
|
+
* **⚡ Slash Commands:** Instantly drop into a menu with `/` to swap models, clear history, or manage context.
|
|
56
48
|
|
|
57
49
|
---
|
|
58
50
|
|
|
59
|
-
##
|
|
51
|
+
## 📖 Usage Guide
|
|
60
52
|
|
|
61
|
-
|
|
53
|
+
After installing, simply navigate to any project folder in your terminal and type:
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
---
|
|
55
|
+
```bash
|
|
56
|
+
eco-code
|
|
57
|
+
```
|
|
58
|
+
*(You can also use the aliases `ecocode` or `eco`)*
|
|
70
59
|
|
|
71
|
-
|
|
60
|
+
### Initial Setup
|
|
61
|
+
On your first run, the CLI will ask for an **OpenRouter API Key**.
|
|
62
|
+
1. Head to [openrouter.ai/keys](https://openrouter.ai/keys) and create a free account.
|
|
63
|
+
2. Generate a key and paste it into the terminal.
|
|
64
|
+
3. The agent will immediately fetch the best free models available that day.
|
|
72
65
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
git clone https://github.com/your-username/eco-code.git
|
|
76
|
-
cd eco-code
|
|
77
|
-
```
|
|
66
|
+
### Conversing & Coding
|
|
67
|
+
Just start typing in plain English!
|
|
78
68
|
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
npm install
|
|
82
|
-
```
|
|
69
|
+
> *"Find the login button component and change it to be rounded with a blue background."*
|
|
83
70
|
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
npm run build
|
|
87
|
-
```
|
|
71
|
+
> *"Run my test suite in the background and fix any failing tests."*
|
|
88
72
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
npm link
|
|
92
|
-
eco-code
|
|
93
|
-
```
|
|
73
|
+
### Slash Commands
|
|
74
|
+
Press `/` (and hit Enter) at any time to open the quick-action menu:
|
|
94
75
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
76
|
+
* `/compact` - Summarizes older chat history to free up token space.
|
|
77
|
+
* `/models` - Browse and switch between the currently available free models.
|
|
78
|
+
* `/taste` - View or add new project-specific coding rules (e.g., "Always use Tailwind").
|
|
79
|
+
* `/resume` - Boot up the context from your last coding session.
|
|
80
|
+
* `/exit` - Quit the CLI.
|
|
100
81
|
|
|
101
82
|
---
|
|
102
83
|
|
|
103
|
-
##
|
|
84
|
+
## 🛠️ Built for the Community
|
|
85
|
+
`eco-code` is open source. It relies on a rigorous "Tool Repair Pipeline" meaning the agent catches its own mistakes before they crash your code.
|
|
104
86
|
|
|
105
|
-
|
|
87
|
+
Happy Coding! 👋
|
package/dist/config.d.ts
CHANGED
|
@@ -16,11 +16,13 @@ export interface EcoConfig {
|
|
|
16
16
|
systemPromptAddition?: string;
|
|
17
17
|
autoApproveTools?: boolean;
|
|
18
18
|
modelCache?: ModelCache;
|
|
19
|
+
agentMode?: 'plan' | 'auto';
|
|
19
20
|
}
|
|
20
21
|
export interface SavedSession {
|
|
21
22
|
id: string;
|
|
22
23
|
timestamp: number;
|
|
23
24
|
model: string;
|
|
25
|
+
title?: string;
|
|
24
26
|
messages: any[];
|
|
25
27
|
}
|
|
26
28
|
export declare class ConfigManager {
|
|
@@ -36,9 +38,13 @@ export declare class ConfigManager {
|
|
|
36
38
|
setApiKey(key: string): void;
|
|
37
39
|
getDefaultModel(): string | undefined;
|
|
38
40
|
setDefaultModel(model: string): void;
|
|
41
|
+
getAgentMode(): 'plan' | 'auto';
|
|
42
|
+
setAgentMode(mode: 'plan' | 'auto'): void;
|
|
39
43
|
getCachedModels(): FreeModelInfo[] | null;
|
|
40
44
|
setCachedModels(models: FreeModelInfo[]): void;
|
|
41
|
-
saveSession(messages: any[], model: string):
|
|
45
|
+
saveSession(messages: any[], model: string, sessionId?: string): string;
|
|
46
|
+
listSessions(): SavedSession[];
|
|
47
|
+
loadSession(id: string): SavedSession | null;
|
|
42
48
|
loadLatestSession(): SavedSession | null;
|
|
43
49
|
clear(): void;
|
|
44
50
|
}
|
package/dist/config.js
CHANGED
|
@@ -52,6 +52,14 @@ export class ConfigManager {
|
|
|
52
52
|
config.defaultModel = model;
|
|
53
53
|
this.save(config);
|
|
54
54
|
}
|
|
55
|
+
getAgentMode() {
|
|
56
|
+
return this.load().agentMode || 'plan';
|
|
57
|
+
}
|
|
58
|
+
setAgentMode(mode) {
|
|
59
|
+
const config = this.load();
|
|
60
|
+
config.agentMode = mode;
|
|
61
|
+
this.save(config);
|
|
62
|
+
}
|
|
55
63
|
// --- Model Cache (Daily / 24h invalidation) ---
|
|
56
64
|
getCachedModels() {
|
|
57
65
|
const config = this.load();
|
|
@@ -77,19 +85,68 @@ export class ConfigManager {
|
|
|
77
85
|
this.save(config);
|
|
78
86
|
}
|
|
79
87
|
// --- Session Persistence & Resume ---
|
|
80
|
-
saveSession(messages, model) {
|
|
88
|
+
saveSession(messages, model, sessionId) {
|
|
81
89
|
this.ensureDirectoryExists();
|
|
82
|
-
const
|
|
90
|
+
const id = sessionId || `session_${Date.now()}`;
|
|
91
|
+
// Extract title from the first user message
|
|
92
|
+
let title = 'General Session';
|
|
93
|
+
const firstUserMsg = messages.find((m) => m.role === 'user');
|
|
94
|
+
if (firstUserMsg && typeof firstUserMsg.content === 'string') {
|
|
95
|
+
title = firstUserMsg.content.trim().slice(0, 50).replace(/\n/g, ' ');
|
|
96
|
+
}
|
|
83
97
|
const sessionData = {
|
|
84
|
-
id
|
|
98
|
+
id,
|
|
85
99
|
timestamp: Date.now(),
|
|
86
100
|
model,
|
|
101
|
+
title,
|
|
87
102
|
messages,
|
|
88
103
|
};
|
|
89
104
|
try {
|
|
105
|
+
// Save specific session file
|
|
106
|
+
const sessionPath = path.join(this.sessionsDir, `${id}.json`);
|
|
107
|
+
fs.writeFileSync(sessionPath, JSON.stringify(sessionData, null, 2), 'utf-8');
|
|
108
|
+
// Also update latest.json for quick single-resume fallback
|
|
109
|
+
const latestPath = path.join(this.sessionsDir, 'latest.json');
|
|
90
110
|
fs.writeFileSync(latestPath, JSON.stringify(sessionData, null, 2), 'utf-8');
|
|
91
111
|
}
|
|
92
112
|
catch { }
|
|
113
|
+
return id;
|
|
114
|
+
}
|
|
115
|
+
listSessions() {
|
|
116
|
+
this.ensureDirectoryExists();
|
|
117
|
+
try {
|
|
118
|
+
const files = fs.readdirSync(this.sessionsDir);
|
|
119
|
+
const sessions = [];
|
|
120
|
+
for (const file of files) {
|
|
121
|
+
if (!file.endsWith('.json') || file === 'latest.json')
|
|
122
|
+
continue;
|
|
123
|
+
try {
|
|
124
|
+
const raw = fs.readFileSync(path.join(this.sessionsDir, file), 'utf-8');
|
|
125
|
+
const data = JSON.parse(raw);
|
|
126
|
+
if (data && data.messages && data.messages.length > 0) {
|
|
127
|
+
sessions.push(data);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch { }
|
|
131
|
+
}
|
|
132
|
+
return sessions.sort((a, b) => b.timestamp - a.timestamp);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
loadSession(id) {
|
|
139
|
+
this.ensureDirectoryExists();
|
|
140
|
+
const filename = id.endsWith('.json') ? id : `${id}.json`;
|
|
141
|
+
const sessionPath = path.join(this.sessionsDir, filename);
|
|
142
|
+
try {
|
|
143
|
+
if (fs.existsSync(sessionPath)) {
|
|
144
|
+
const raw = fs.readFileSync(sessionPath, 'utf-8');
|
|
145
|
+
return JSON.parse(raw);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch { }
|
|
149
|
+
return null;
|
|
93
150
|
}
|
|
94
151
|
loadLatestSession() {
|
|
95
152
|
const latestPath = path.join(this.sessionsDir, 'latest.json');
|
|
@@ -100,7 +157,8 @@ export class ConfigManager {
|
|
|
100
157
|
}
|
|
101
158
|
}
|
|
102
159
|
catch { }
|
|
103
|
-
|
|
160
|
+
const sessions = this.listSessions();
|
|
161
|
+
return sessions.length > 0 ? sessions[0] : null;
|
|
104
162
|
}
|
|
105
163
|
clear() {
|
|
106
164
|
if (fs.existsSync(this.configFile)) {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/harness/agent.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ export interface ContextStats {
|
|
|
10
10
|
usedTokens: number;
|
|
11
11
|
maxTokens: number;
|
|
12
12
|
sessionTotalTokens: number;
|
|
13
|
+
sessionInputTokens: number;
|
|
14
|
+
sessionOutputTokens: number;
|
|
15
|
+
sessionCacheReadTokens: number;
|
|
13
16
|
percentage: number;
|
|
14
17
|
isWarning: boolean;
|
|
15
18
|
isCritical: boolean;
|
|
@@ -20,13 +23,16 @@ export declare class AgentHarness {
|
|
|
20
23
|
private model;
|
|
21
24
|
private maxTokens;
|
|
22
25
|
private currentTokens;
|
|
23
|
-
private
|
|
26
|
+
private sessionInputTokens;
|
|
27
|
+
private sessionOutputTokens;
|
|
28
|
+
private sessionCacheReadTokens;
|
|
24
29
|
private contextManager;
|
|
25
30
|
private configManager;
|
|
26
31
|
private history;
|
|
27
32
|
private workspaceDir;
|
|
28
33
|
constructor(client: OpenAI, model: string, maxTokens: number, configManager: ConfigManager, workspaceDir?: string);
|
|
29
34
|
resetContext(): void;
|
|
35
|
+
updateSystemPrompt(modeOverride?: 'plan' | 'auto'): void;
|
|
30
36
|
setModel(newModel: string, maxTokens?: number): void;
|
|
31
37
|
getModel(): string;
|
|
32
38
|
getMaxTokens(): number;
|
|
@@ -47,5 +53,5 @@ export declare class AgentHarness {
|
|
|
47
53
|
after: number;
|
|
48
54
|
savedPercentage: number;
|
|
49
55
|
};
|
|
50
|
-
runTurn(userInput: string, callbacks?: TurnCallbacks): Promise<string>;
|
|
56
|
+
runTurn(userInput: string, callbacks?: TurnCallbacks, modeOverride?: 'plan' | 'auto'): Promise<string>;
|
|
51
57
|
}
|
package/dist/harness/agent.js
CHANGED
|
@@ -5,7 +5,9 @@ export class AgentHarness {
|
|
|
5
5
|
model;
|
|
6
6
|
maxTokens;
|
|
7
7
|
currentTokens = 0;
|
|
8
|
-
|
|
8
|
+
sessionInputTokens = 0;
|
|
9
|
+
sessionOutputTokens = 0;
|
|
10
|
+
sessionCacheReadTokens = 0;
|
|
9
11
|
contextManager;
|
|
10
12
|
configManager;
|
|
11
13
|
history = [];
|
|
@@ -20,14 +22,23 @@ export class AgentHarness {
|
|
|
20
22
|
this.resetContext();
|
|
21
23
|
}
|
|
22
24
|
resetContext() {
|
|
23
|
-
this.history = [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
];
|
|
25
|
+
this.history = [];
|
|
26
|
+
this.sessionInputTokens = 0;
|
|
27
|
+
this.sessionOutputTokens = 0;
|
|
28
|
+
this.sessionCacheReadTokens = 0;
|
|
29
|
+
this.updateSystemPrompt();
|
|
29
30
|
this.recalculateEstimatedTokens();
|
|
30
31
|
}
|
|
32
|
+
updateSystemPrompt(modeOverride) {
|
|
33
|
+
const mode = modeOverride || this.configManager.getAgentMode();
|
|
34
|
+
const systemContent = this.contextManager.buildSystemPrompt(mode);
|
|
35
|
+
if (this.history.length > 0 && this.history[0].role === 'system') {
|
|
36
|
+
this.history[0].content = systemContent;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.history.unshift({ role: 'system', content: systemContent });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
31
42
|
setModel(newModel, maxTokens) {
|
|
32
43
|
this.model = newModel;
|
|
33
44
|
if (maxTokens) {
|
|
@@ -41,7 +52,7 @@ export class AgentHarness {
|
|
|
41
52
|
return this.maxTokens;
|
|
42
53
|
}
|
|
43
54
|
getSessionTotalTokens() {
|
|
44
|
-
return this.
|
|
55
|
+
return this.sessionInputTokens + this.sessionOutputTokens;
|
|
45
56
|
}
|
|
46
57
|
getContextManager() {
|
|
47
58
|
return this.contextManager;
|
|
@@ -73,10 +84,14 @@ export class AgentHarness {
|
|
|
73
84
|
const filledBars = Math.min(totalBars, Math.round((percentage / 100) * totalBars));
|
|
74
85
|
const emptyBars = totalBars - filledBars;
|
|
75
86
|
const progressBar = `[${'█'.repeat(filledBars)}${'░'.repeat(emptyBars)}]`;
|
|
87
|
+
const totalBilled = this.sessionInputTokens + this.sessionOutputTokens;
|
|
76
88
|
return {
|
|
77
89
|
usedTokens: this.currentTokens,
|
|
78
90
|
maxTokens: this.maxTokens,
|
|
79
|
-
sessionTotalTokens:
|
|
91
|
+
sessionTotalTokens: totalBilled,
|
|
92
|
+
sessionInputTokens: this.sessionInputTokens,
|
|
93
|
+
sessionOutputTokens: this.sessionOutputTokens,
|
|
94
|
+
sessionCacheReadTokens: this.sessionCacheReadTokens,
|
|
80
95
|
percentage,
|
|
81
96
|
isWarning,
|
|
82
97
|
isCritical,
|
|
@@ -96,19 +111,29 @@ export class AgentHarness {
|
|
|
96
111
|
const savedPercentage = Math.max(0, beforeStats.percentage - afterStats.percentage);
|
|
97
112
|
return { before, after, savedPercentage };
|
|
98
113
|
}
|
|
99
|
-
async runTurn(userInput, callbacks = {}) {
|
|
100
|
-
|
|
114
|
+
async runTurn(userInput, callbacks = {}, modeOverride) {
|
|
115
|
+
if (userInput) {
|
|
116
|
+
this.history.push({ role: 'user', content: userInput });
|
|
117
|
+
}
|
|
118
|
+
// Ensure system prompt is synced with the current mode
|
|
119
|
+
const activeMode = modeOverride || this.configManager.getAgentMode();
|
|
120
|
+
this.updateSystemPrompt(activeMode);
|
|
101
121
|
this.history = this.contextManager.autoCompactHistory(this.history);
|
|
102
122
|
let maxSteps = 15;
|
|
103
123
|
let stepCount = 0;
|
|
124
|
+
const writeTools = ['write_file', 'replace_in_file', 'run_command'];
|
|
125
|
+
const activeTools = activeMode === 'plan'
|
|
126
|
+
? TOOL_SCHEMAS.filter(t => !writeTools.includes(t.function.name))
|
|
127
|
+
: TOOL_SCHEMAS.filter(t => t.function.name !== 'submit_plan');
|
|
104
128
|
while (stepCount < maxSteps) {
|
|
105
129
|
stepCount++;
|
|
130
|
+
const payloadMessages = this.contextManager.pruneToolOutputs(this.history);
|
|
106
131
|
let response;
|
|
107
132
|
try {
|
|
108
133
|
response = await this.client.chat.completions.create({
|
|
109
134
|
model: this.model,
|
|
110
|
-
messages:
|
|
111
|
-
tools:
|
|
135
|
+
messages: payloadMessages,
|
|
136
|
+
tools: activeTools,
|
|
112
137
|
tool_choice: 'auto',
|
|
113
138
|
temperature: 0.2,
|
|
114
139
|
});
|
|
@@ -116,16 +141,37 @@ export class AgentHarness {
|
|
|
116
141
|
catch (err) {
|
|
117
142
|
throw new Error(`OpenRouter API error with model [${this.model}]: ${err.message}`);
|
|
118
143
|
}
|
|
119
|
-
// Record live usage from OpenRouter
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
144
|
+
// Record live usage from OpenRouter matching OpenCode standard
|
|
145
|
+
const usage = response.usage;
|
|
146
|
+
if (usage) {
|
|
147
|
+
const promptTokens = usage.prompt_tokens || 0;
|
|
148
|
+
const completionTokens = usage.completion_tokens || 0;
|
|
149
|
+
const cachedTokens = usage.prompt_tokens_details?.cached_tokens || 0;
|
|
150
|
+
this.currentTokens = promptTokens + completionTokens;
|
|
151
|
+
if (stepCount === 1) {
|
|
152
|
+
const freshInput = Math.max(0, promptTokens - cachedTokens);
|
|
153
|
+
this.sessionInputTokens += freshInput;
|
|
154
|
+
this.sessionCacheReadTokens += cachedTokens;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
if (cachedTokens > 0) {
|
|
158
|
+
this.sessionCacheReadTokens += cachedTokens;
|
|
159
|
+
this.sessionInputTokens += Math.max(0, promptTokens - cachedTokens);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
this.sessionCacheReadTokens += promptTokens;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
this.sessionOutputTokens += completionTokens;
|
|
123
166
|
}
|
|
124
167
|
else {
|
|
125
168
|
this.recalculateEstimatedTokens();
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
169
|
+
if (stepCount === 1) {
|
|
170
|
+
this.sessionInputTokens += this.currentTokens;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
this.sessionCacheReadTokens += this.currentTokens;
|
|
174
|
+
}
|
|
129
175
|
}
|
|
130
176
|
const message = response.choices[0]?.message;
|
|
131
177
|
if (!message) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/harness/agent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/harness/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,8 +4,13 @@ export declare class ContextManager {
|
|
|
4
4
|
private tasteEngine;
|
|
5
5
|
private workspaceDir;
|
|
6
6
|
constructor(workspaceDir?: string);
|
|
7
|
-
buildSystemPrompt(): string;
|
|
7
|
+
buildSystemPrompt(mode: 'plan' | 'auto'): string;
|
|
8
8
|
getTasteEngine(): TasteEngine;
|
|
9
|
+
/**
|
|
10
|
+
* Ephemeral tool output pruning (RTK Pattern):
|
|
11
|
+
* Keeps the latest 3 tool outputs in full, and condenses older large tool outputs.
|
|
12
|
+
*/
|
|
13
|
+
pruneToolOutputs(messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[], keepFullRecent?: number): OpenAI.Chat.Completions.ChatCompletionMessageParam[];
|
|
9
14
|
/**
|
|
10
15
|
* Automatically compacts history if it exceeds rolling limit
|
|
11
16
|
*/
|
package/dist/harness/context.js
CHANGED
|
@@ -7,14 +7,36 @@ export class ContextManager {
|
|
|
7
7
|
this.workspaceDir = workspaceDir;
|
|
8
8
|
this.tasteEngine = new TasteEngine(workspaceDir);
|
|
9
9
|
}
|
|
10
|
-
buildSystemPrompt() {
|
|
10
|
+
buildSystemPrompt(mode) {
|
|
11
11
|
const taste = this.tasteEngine.getTastePrompt();
|
|
12
|
+
let modeDirectives = '';
|
|
13
|
+
if (mode === 'plan') {
|
|
14
|
+
modeDirectives = `
|
|
15
|
+
## PLAN MODE ACTIVE
|
|
16
|
+
1. You MUST NOT execute any commands that modify state (no creating files, no editing code, no destructive shell commands).
|
|
17
|
+
2. You should only use read-only tools to research the user's request.
|
|
18
|
+
3. Once you understand what needs to be done, formulate your plan and call the \`submit_plan\` tool.
|
|
19
|
+
`;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
modeDirectives = `
|
|
23
|
+
## AUTO MODE ACTIVE
|
|
24
|
+
You have full permission to research, write code, edit files, and run commands to complete the user's request autonomously.
|
|
25
|
+
`;
|
|
26
|
+
}
|
|
27
|
+
const toneDirectives = `
|
|
28
|
+
## CONVERSATIONAL TONE (CRITICAL)
|
|
29
|
+
- NEVER announce that you are an AI or explain your limitations.
|
|
30
|
+
- NEVER announce what mode you are in (e.g. do not say "I am in Plan Mode").
|
|
31
|
+
- Be strictly professional, concise, and direct. No fluff, no pleasantries, no AI slop.
|
|
32
|
+
`;
|
|
12
33
|
return `You are eco-code, an autonomous and intelligent CLI coding assistant.
|
|
13
34
|
You are running directly in the developer's terminal environment.
|
|
14
35
|
|
|
15
36
|
Current Workspace: ${this.workspaceDir}
|
|
16
37
|
Operating System: ${os.platform()} (${os.arch()})
|
|
17
|
-
|
|
38
|
+
${modeDirectives}
|
|
39
|
+
${toneDirectives}
|
|
18
40
|
## Tools — IMPORTANT CONTRACT
|
|
19
41
|
Always prefer these deterministic tools:
|
|
20
42
|
- Use \`read_file\` for all file reading. It is windowed and limits reads to 2000 lines. Do not re-read large files from the beginning.
|
|
@@ -26,10 +48,11 @@ Always prefer these deterministic tools:
|
|
|
26
48
|
|
|
27
49
|
## CORE CAPABILITIES & RULES:
|
|
28
50
|
1. Always inspect a file using read_file before attempting to edit it with replace_in_file.
|
|
29
|
-
2.
|
|
30
|
-
3.
|
|
31
|
-
4.
|
|
32
|
-
5.
|
|
51
|
+
2. For editing existing files, ALWAYS prefer replace_in_file (targeted diffs). Do NOT rewrite entire files with write_file unless creating a brand new file.
|
|
52
|
+
3. Be precise with replace_in_file: target_content must match the file content verbatim.
|
|
53
|
+
4. When writing code, write complete, working code without placeholders or omissions.
|
|
54
|
+
5. Verify your changes when appropriate.
|
|
55
|
+
6. Keep conversational replies concise, direct, and token-efficient. Do not pad responses or repeat unchanged code.
|
|
33
56
|
|
|
34
57
|
TASTE & DIRECTIVES:
|
|
35
58
|
${taste}`;
|
|
@@ -37,6 +60,34 @@ ${taste}`;
|
|
|
37
60
|
getTasteEngine() {
|
|
38
61
|
return this.tasteEngine;
|
|
39
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Ephemeral tool output pruning (RTK Pattern):
|
|
65
|
+
* Keeps the latest 3 tool outputs in full, and condenses older large tool outputs.
|
|
66
|
+
*/
|
|
67
|
+
pruneToolOutputs(messages, keepFullRecent = 3) {
|
|
68
|
+
const toolIndices = [];
|
|
69
|
+
messages.forEach((m, idx) => {
|
|
70
|
+
if (m.role === 'tool')
|
|
71
|
+
toolIndices.push(idx);
|
|
72
|
+
});
|
|
73
|
+
if (toolIndices.length <= keepFullRecent) {
|
|
74
|
+
return messages;
|
|
75
|
+
}
|
|
76
|
+
const olderToolIndices = new Set(toolIndices.slice(0, -keepFullRecent));
|
|
77
|
+
return messages.map((m, idx) => {
|
|
78
|
+
if (olderToolIndices.has(idx) && m.role === 'tool' && typeof m.content === 'string') {
|
|
79
|
+
if (m.content.length > 250) {
|
|
80
|
+
const lines = m.content.split('\n');
|
|
81
|
+
const preview = lines.slice(0, 3).join('\n');
|
|
82
|
+
return {
|
|
83
|
+
...m,
|
|
84
|
+
content: `${preview}\n... [${lines.length} lines of older tool output condensed by harness to save tokens]`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return m;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
40
91
|
/**
|
|
41
92
|
* Automatically compacts history if it exceeds rolling limit
|
|
42
93
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/harness/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,OAAO,cAAc;IACjB,WAAW,CAAc;IACzB,YAAY,CAAS;IAE7B,YAAY,eAAuB,OAAO,CAAC,GAAG,EAAE;QAC9C,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,YAAY,CAAC,CAAC;IACnD,CAAC;IAED,iBAAiB;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/harness/context.ts"],"names":[],"mappings":"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"}
|