@mapick/cost-firewall 0.1.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 +21 -0
- package/README.md +161 -0
- package/dist/breaker.d.ts +30 -0
- package/dist/breaker.d.ts.map +1 -0
- package/dist/breaker.js +131 -0
- package/dist/breaker.js.map +1 -0
- package/dist/cli/index.d.ts +18 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +244 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config-warn.d.ts +11 -0
- package/dist/config-warn.d.ts.map +1 -0
- package/dist/config-warn.js +26 -0
- package/dist/config-warn.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +32 -0
- package/dist/config.js.map +1 -0
- package/dist/dashboard/html.d.ts +2 -0
- package/dist/dashboard/html.d.ts.map +1 -0
- package/dist/dashboard/html.js +898 -0
- package/dist/dashboard/html.js.map +1 -0
- package/dist/dashboard/index.d.ts +8 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +163 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/dashboard/sse.d.ts +9 -0
- package/dist/dashboard/sse.d.ts.map +1 -0
- package/dist/dashboard/sse.js +22 -0
- package/dist/dashboard/sse.js.map +1 -0
- package/dist/hooks/agent-end.d.ts +18 -0
- package/dist/hooks/agent-end.d.ts.map +1 -0
- package/dist/hooks/agent-end.js +25 -0
- package/dist/hooks/agent-end.js.map +1 -0
- package/dist/hooks/before-agent-reply.d.ts +29 -0
- package/dist/hooks/before-agent-reply.d.ts.map +1 -0
- package/dist/hooks/before-agent-reply.js +42 -0
- package/dist/hooks/before-agent-reply.js.map +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +17 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/model-call.d.ts +39 -0
- package/dist/hooks/model-call.d.ts.map +1 -0
- package/dist/hooks/model-call.js +120 -0
- package/dist/hooks/model-call.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/pricing.d.ts +12 -0
- package/dist/pricing.d.ts.map +1 -0
- package/dist/pricing.js +43 -0
- package/dist/pricing.js.map +1 -0
- package/dist/provider/auth.d.ts +14 -0
- package/dist/provider/auth.d.ts.map +1 -0
- package/dist/provider/auth.js +53 -0
- package/dist/provider/auth.js.map +1 -0
- package/dist/provider/index.d.ts +12 -0
- package/dist/provider/index.d.ts.map +1 -0
- package/dist/provider/index.js +134 -0
- package/dist/provider/index.js.map +1 -0
- package/dist/provider/route.d.ts +10 -0
- package/dist/provider/route.d.ts.map +1 -0
- package/dist/provider/route.js +19 -0
- package/dist/provider/route.js.map +1 -0
- package/dist/provider/stream.d.ts +10 -0
- package/dist/provider/stream.d.ts.map +1 -0
- package/dist/provider/stream.js +120 -0
- package/dist/provider/stream.js.map +1 -0
- package/dist/provider/synthetic.d.ts +13 -0
- package/dist/provider/synthetic.d.ts.map +1 -0
- package/dist/provider/synthetic.js +59 -0
- package/dist/provider/synthetic.js.map +1 -0
- package/dist/provider/upstream/anthropic.d.ts +13 -0
- package/dist/provider/upstream/anthropic.d.ts.map +1 -0
- package/dist/provider/upstream/anthropic.js +62 -0
- package/dist/provider/upstream/anthropic.js.map +1 -0
- package/dist/provider/upstream/openai.d.ts +17 -0
- package/dist/provider/upstream/openai.d.ts.map +1 -0
- package/dist/provider/upstream/openai.js +75 -0
- package/dist/provider/upstream/openai.js.map +1 -0
- package/dist/source.d.ts +35 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +41 -0
- package/dist/source.js.map +1 -0
- package/dist/state.d.ts +56 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +178 -0
- package/dist/state.js.map +1 -0
- package/dist/store.d.ts +23 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +68 -0
- package/dist/store.js.map +1 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +63 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types.d.ts +98 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/openclaw.plugin.json +44 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mapick
|
|
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,161 @@
|
|
|
1
|
+
# @mapick/cost-firewall
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
AI Call Firewall — real-time monitoring, budget control, automatic circuit breaker.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
openclaw plugins install @mapick/cost-firewall
|
|
16
|
+
openclaw plugins enable mapick-firewall
|
|
17
|
+
openclaw gateway restart
|
|
18
|
+
openclaw firewall status
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Dashboard: **http://localhost:18789/mapick/dashboard**
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Commands
|
|
26
|
+
|
|
27
|
+
| In Chat | CLI | Action |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| `/firewall` | `openclaw firewall status` | Status |
|
|
30
|
+
| `/firewall stop` | `openclaw firewall stop` | 🛑 Emergency stop |
|
|
31
|
+
| `/firewall resume` | `openclaw firewall resume` | ▶️ Resume |
|
|
32
|
+
| — | `openclaw firewall mode observe\|protect` | Toggle mode |
|
|
33
|
+
| `/firewall budget` | `openclaw firewall budget set\|reset` | Daily token limit |
|
|
34
|
+
| `/firewall log` | `openclaw firewall log` | Recent events |
|
|
35
|
+
| — | `openclaw firewall reset <source>` | Clear cooldown |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Config
|
|
40
|
+
|
|
41
|
+
```jsonc
|
|
42
|
+
{
|
|
43
|
+
"plugins": {
|
|
44
|
+
"entries": {
|
|
45
|
+
"mapick-firewall": {
|
|
46
|
+
"enabled": true,
|
|
47
|
+
"config": {
|
|
48
|
+
"dailyTokenLimit": null,
|
|
49
|
+
"breaker": {
|
|
50
|
+
"consecutiveFailures": 3,
|
|
51
|
+
"cooldownSec": 30,
|
|
52
|
+
"tokenVelocityThreshold": 100000,
|
|
53
|
+
"tokenVelocityWindowSec": 60,
|
|
54
|
+
"callFrequencyThreshold": 30,
|
|
55
|
+
"callFrequencyWindowSec": 60
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Defaults
|
|
67
|
+
|
|
68
|
+
| Rule | Threshold | Window | Cooldown |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| Consecutive Failures | 3 | — | 30s |
|
|
71
|
+
| Token Velocity | 100K tokens | 60s | 30s |
|
|
72
|
+
| Call Frequency | 30 calls | 60s | 30s |
|
|
73
|
+
| Daily Token Limit | unlimited | — | — |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## AI Installation Checklist
|
|
78
|
+
|
|
79
|
+
Use this checklist when installing the firewall automatically:
|
|
80
|
+
|
|
81
|
+
```markdown
|
|
82
|
+
## Installation Steps
|
|
83
|
+
|
|
84
|
+
1. Install the npm package:
|
|
85
|
+
```bash
|
|
86
|
+
openclaw plugins install @mapick/cost-firewall
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
2. Enable the plugin:
|
|
90
|
+
```bash
|
|
91
|
+
openclaw plugins enable mapick-firewall
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
3. Verify it's registered:
|
|
95
|
+
```bash
|
|
96
|
+
openclaw plugins list | grep mapick-firewall
|
|
97
|
+
```
|
|
98
|
+
Expected: should show `mapick-firewall` in the list.
|
|
99
|
+
|
|
100
|
+
4. Restart gateway:
|
|
101
|
+
```bash
|
|
102
|
+
openclaw gateway restart
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
5. Verify it's working:
|
|
106
|
+
```bash
|
|
107
|
+
openclaw firewall status
|
|
108
|
+
```
|
|
109
|
+
Expected: returns JSON with mode, today_tokens, today_blocked, etc.
|
|
110
|
+
|
|
111
|
+
6. Optionally, set a daily token budget:
|
|
112
|
+
```bash
|
|
113
|
+
openclaw firewall budget set 500000
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Routing calls through the firewall
|
|
117
|
+
|
|
118
|
+
To route AI calls through the firewall, configure the model with `mapick/` prefix:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"agents": {
|
|
123
|
+
"defaults": {
|
|
124
|
+
"model": {
|
|
125
|
+
"primary": "mapick/deepseek/deepseek-chat",
|
|
126
|
+
"fallbacks": ["mapick/anthropic/claude-sonnet-4-20250514"]
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Format: `mapick/<upstream>/<model-id>`
|
|
134
|
+
Supported upstreams: `openai`, `anthropic`, `deepseek`, `openrouter`, `qwen`
|
|
135
|
+
|
|
136
|
+
## Validation
|
|
137
|
+
|
|
138
|
+
After installation, the AI should verify:
|
|
139
|
+
- [ ] `openclaw plugins list` shows `mapick-firewall` (enabled)
|
|
140
|
+
- [ ] `openclaw firewall status` returns valid JSON
|
|
141
|
+
- [ ] Dashboard accessible at http://localhost:18789/mapick/dashboard
|
|
142
|
+
- [ ] Model config uses `mapick/` prefix if firewall protection is desired
|
|
143
|
+
- [ ] Fallbacks also use `mapick/` prefix (non-mapick fallbacks bypass the firewall)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Development
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
pnpm install
|
|
152
|
+
pnpm build
|
|
153
|
+
pnpm test
|
|
154
|
+
pnpm dev # tsc --watch
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
See [RELEASE.md](./RELEASE.md) for release process.
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Breaker logic
|
|
3
|
+
*
|
|
4
|
+
* Three rules:
|
|
5
|
+
* 1. Consecutive failures (consecutiveFailures)
|
|
6
|
+
* 2. Token velocity (tokenVelocity) — token consumption exceeds threshold within window
|
|
7
|
+
* 3. Call frequency (callFrequency) — call count exceeds threshold within window
|
|
8
|
+
*/
|
|
9
|
+
import type { FirewallConfig, SourceKey } from "./types.js";
|
|
10
|
+
export declare class Breaker {
|
|
11
|
+
private states;
|
|
12
|
+
private config;
|
|
13
|
+
constructor(config: FirewallConfig);
|
|
14
|
+
private getState;
|
|
15
|
+
recordFailure(source: SourceKey): void;
|
|
16
|
+
recordSuccess(source: SourceKey): void;
|
|
17
|
+
recordTokens(source: SourceKey, tokens: number): string | undefined;
|
|
18
|
+
recordCall(source: SourceKey): string | undefined;
|
|
19
|
+
isCoolingDown(source: SourceKey): boolean;
|
|
20
|
+
getBlockedReason(source: SourceKey): string | undefined;
|
|
21
|
+
reset(source: SourceKey): void;
|
|
22
|
+
getCooldownRemaining(source: SourceKey): number;
|
|
23
|
+
/** Return list of all cooling sources */
|
|
24
|
+
getCoolingSources(): {
|
|
25
|
+
source: string;
|
|
26
|
+
reason: string;
|
|
27
|
+
remainingSec: number;
|
|
28
|
+
}[];
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=breaker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breaker.d.ts","sourceRoot":"","sources":["../src/breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAgB,MAAM,YAAY,CAAC;AAoB1E,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,cAAc;IAWlC,OAAO,CAAC,QAAQ;IAchB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAStC,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAOtC,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAuBnE,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS;IAqBjD,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO;IAYzC,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS;IAIvD,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAI9B,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM;IAM/C,yCAAyC;IACzC,iBAAiB,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EAAE;CAchF"}
|
package/dist/breaker.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Breaker logic
|
|
3
|
+
*
|
|
4
|
+
* Three rules:
|
|
5
|
+
* 1. Consecutive failures (consecutiveFailures)
|
|
6
|
+
* 2. Token velocity (tokenVelocity) — token consumption exceeds threshold within window
|
|
7
|
+
* 3. Call frequency (callFrequency) — call count exceeds threshold within window
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_BREAKER = {
|
|
10
|
+
consecutiveFailures: 3,
|
|
11
|
+
cooldownSec: 30,
|
|
12
|
+
tokenVelocityWindowSec: 60,
|
|
13
|
+
tokenVelocityThreshold: 100000,
|
|
14
|
+
callFrequencyWindowSec: 60,
|
|
15
|
+
callFrequencyThreshold: 30,
|
|
16
|
+
};
|
|
17
|
+
export class Breaker {
|
|
18
|
+
states = new Map();
|
|
19
|
+
config;
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.config = {
|
|
22
|
+
consecutiveFailures: config.breaker?.consecutiveFailures ?? DEFAULT_BREAKER.consecutiveFailures,
|
|
23
|
+
cooldownSec: config.breaker?.cooldownSec ?? DEFAULT_BREAKER.cooldownSec,
|
|
24
|
+
tokenVelocityWindowSec: config.breaker?.tokenVelocityWindowSec ?? DEFAULT_BREAKER.tokenVelocityWindowSec,
|
|
25
|
+
tokenVelocityThreshold: config.breaker?.tokenVelocityThreshold ?? DEFAULT_BREAKER.tokenVelocityThreshold,
|
|
26
|
+
callFrequencyWindowSec: config.breaker?.callFrequencyWindowSec ?? DEFAULT_BREAKER.callFrequencyWindowSec,
|
|
27
|
+
callFrequencyThreshold: config.breaker?.callFrequencyThreshold ?? DEFAULT_BREAKER.callFrequencyThreshold,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
getState(source) {
|
|
31
|
+
if (!this.states.has(source)) {
|
|
32
|
+
this.states.set(source, {
|
|
33
|
+
source,
|
|
34
|
+
consecutiveFailures: 0,
|
|
35
|
+
tokenHistory: [],
|
|
36
|
+
callTimestamps: [],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return this.states.get(source);
|
|
40
|
+
}
|
|
41
|
+
// ----- Consecutive failures -----
|
|
42
|
+
recordFailure(source) {
|
|
43
|
+
const state = this.getState(source);
|
|
44
|
+
state.consecutiveFailures++;
|
|
45
|
+
if (state.consecutiveFailures >= this.config.consecutiveFailures && this.config.consecutiveFailures > 0) {
|
|
46
|
+
state.brokenUntil = Date.now() + this.config.cooldownSec * 1000;
|
|
47
|
+
state.reason = "consecutive_failures";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
recordSuccess(source) {
|
|
51
|
+
const state = this.getState(source);
|
|
52
|
+
state.consecutiveFailures = 0;
|
|
53
|
+
}
|
|
54
|
+
// ----- Token velocity (sliding window) -----
|
|
55
|
+
recordTokens(source, tokens) {
|
|
56
|
+
const state = this.getState(source);
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
const windowMs = this.config.tokenVelocityWindowSec * 1000;
|
|
59
|
+
const threshold = this.config.tokenVelocityThreshold;
|
|
60
|
+
if (threshold <= 0)
|
|
61
|
+
return undefined;
|
|
62
|
+
state.tokenHistory.push({ ts: now, tokens });
|
|
63
|
+
// Purge expired records
|
|
64
|
+
state.tokenHistory = state.tokenHistory.filter((h) => now - h.ts < windowMs);
|
|
65
|
+
const total = state.tokenHistory.reduce((sum, h) => sum + h.tokens, 0);
|
|
66
|
+
if (total >= threshold) {
|
|
67
|
+
state.brokenUntil = now + this.config.cooldownSec * 1000;
|
|
68
|
+
state.reason = "token_velocity";
|
|
69
|
+
return "token_velocity";
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
// ----- Call frequency (sliding window) -----
|
|
74
|
+
recordCall(source) {
|
|
75
|
+
const state = this.getState(source);
|
|
76
|
+
const now = Date.now();
|
|
77
|
+
const windowMs = this.config.callFrequencyWindowSec * 1000;
|
|
78
|
+
const threshold = this.config.callFrequencyThreshold;
|
|
79
|
+
if (threshold <= 0)
|
|
80
|
+
return undefined;
|
|
81
|
+
state.callTimestamps.push(now);
|
|
82
|
+
state.callTimestamps = state.callTimestamps.filter((t) => now - t < windowMs);
|
|
83
|
+
if (state.callTimestamps.length >= threshold) {
|
|
84
|
+
state.brokenUntil = now + this.config.cooldownSec * 1000;
|
|
85
|
+
state.reason = "call_frequency";
|
|
86
|
+
return "call_frequency";
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
// ----- Common -----
|
|
91
|
+
isCoolingDown(source) {
|
|
92
|
+
const state = this.getState(source);
|
|
93
|
+
if (!state.brokenUntil)
|
|
94
|
+
return false;
|
|
95
|
+
if (Date.now() > state.brokenUntil) {
|
|
96
|
+
state.brokenUntil = undefined;
|
|
97
|
+
state.reason = undefined;
|
|
98
|
+
state.consecutiveFailures = 0;
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
getBlockedReason(source) {
|
|
104
|
+
return this.isCoolingDown(source) ? this.getState(source).reason : undefined;
|
|
105
|
+
}
|
|
106
|
+
reset(source) {
|
|
107
|
+
this.states.delete(source);
|
|
108
|
+
}
|
|
109
|
+
getCooldownRemaining(source) {
|
|
110
|
+
const state = this.getState(source);
|
|
111
|
+
if (!state.brokenUntil)
|
|
112
|
+
return 0;
|
|
113
|
+
return Math.max(0, state.brokenUntil - Date.now());
|
|
114
|
+
}
|
|
115
|
+
/** Return list of all cooling sources */
|
|
116
|
+
getCoolingSources() {
|
|
117
|
+
const now = Date.now();
|
|
118
|
+
const result = [];
|
|
119
|
+
for (const [source, state] of this.states) {
|
|
120
|
+
if (state.brokenUntil && now < state.brokenUntil) {
|
|
121
|
+
result.push({
|
|
122
|
+
source,
|
|
123
|
+
reason: state.reason ?? "unknown",
|
|
124
|
+
remainingSec: Math.max(0, Math.round((state.brokenUntil - now) / 1000)),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=breaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breaker.js","sourceRoot":"","sources":["../src/breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,MAAM,eAAe,GAAkB;IACrC,mBAAmB,EAAE,CAAC;IACtB,WAAW,EAAE,EAAE;IACf,sBAAsB,EAAE,EAAE;IAC1B,sBAAsB,EAAE,MAAM;IAC9B,sBAAsB,EAAE,EAAE;IAC1B,sBAAsB,EAAE,EAAE;CAC3B,CAAC;AAEF,MAAM,OAAO,OAAO;IACV,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC5C,MAAM,CAAgB;IAE9B,YAAY,MAAsB;QAChC,IAAI,CAAC,MAAM,GAAG;YACZ,mBAAmB,EAAE,MAAM,CAAC,OAAO,EAAE,mBAAmB,IAAI,eAAe,CAAC,mBAAmB;YAC/F,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,IAAI,eAAe,CAAC,WAAW;YACvE,sBAAsB,EAAE,MAAM,CAAC,OAAO,EAAE,sBAAsB,IAAI,eAAe,CAAC,sBAAsB;YACxG,sBAAsB,EAAE,MAAM,CAAC,OAAO,EAAE,sBAAsB,IAAI,eAAe,CAAC,sBAAsB;YACxG,sBAAsB,EAAE,MAAM,CAAC,OAAO,EAAE,sBAAsB,IAAI,eAAe,CAAC,sBAAsB;YACxG,sBAAsB,EAAE,MAAM,CAAC,OAAO,EAAE,sBAAsB,IAAI,eAAe,CAAC,sBAAsB;SACzG,CAAC;IACJ,CAAC;IAEO,QAAQ,CAAC,MAAiB;QAChC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE;gBACtB,MAAM;gBACN,mBAAmB,EAAE,CAAC;gBACtB,YAAY,EAAE,EAAE;gBAChB,cAAc,EAAE,EAAE;aACnB,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;IAClC,CAAC;IAED,mCAAmC;IAEnC,aAAa,CAAC,MAAiB;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpC,KAAK,CAAC,mBAAmB,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,mBAAmB,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,GAAG,CAAC,EAAE,CAAC;YACxG,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC;YAChE,KAAK,CAAC,MAAM,GAAG,sBAAsB,CAAC;QACxC,CAAC;IACH,CAAC;IAED,aAAa,CAAC,MAAiB;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpC,KAAK,CAAC,mBAAmB,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,8CAA8C;IAE9C,YAAY,CAAC,MAAiB,EAAE,MAAc;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,sBAAsB,GAAG,IAAI,CAAC;QAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC;QAErD,IAAI,SAAS,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QAErC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7C,wBAAwB;QACxB,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC;QAE7E,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACvE,IAAI,KAAK,IAAI,SAAS,EAAE,CAAC;YACvB,KAAK,CAAC,WAAW,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC;YACzD,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC;YAChC,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,8CAA8C;IAE9C,UAAU,CAAC,MAAiB;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,sBAAsB,GAAG,IAAI,CAAC;QAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC;QAErD,IAAI,SAAS,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QAErC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;QAE9E,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;YAC7C,KAAK,CAAC,WAAW,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC;YACzD,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC;YAChC,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,qBAAqB;IAErB,aAAa,CAAC,MAAiB;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;QACrC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YACnC,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC;YAC9B,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;YACzB,KAAK,CAAC,mBAAmB,GAAG,CAAC,CAAC;YAC9B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gBAAgB,CAAC,MAAiB;QAChC,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,MAAiB;QACrB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAED,oBAAoB,CAAC,MAAiB;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,CAAC,WAAW;YAAE,OAAO,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,yCAAyC;IACzC,iBAAiB;QACf,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAA+D,EAAE,CAAC;QAC9E,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC1C,IAAI,KAAK,CAAC,WAAW,IAAI,GAAG,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;gBACjD,MAAM,CAAC,IAAI,CAAC;oBACV,MAAM;oBACN,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,SAAS;oBACjC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;iBACxE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command implementation
|
|
3
|
+
*
|
|
4
|
+
* Register openclaw mapick <subcommand> command group
|
|
5
|
+
*/
|
|
6
|
+
import type { FirewallState } from "../state.js";
|
|
7
|
+
import { EventStore } from "../store.js";
|
|
8
|
+
import type { FirewallEvent } from "../types.js";
|
|
9
|
+
/** Aggregate today's stats from JSONL */
|
|
10
|
+
export declare function aggregateFromJsonl(store: EventStore, memTokens: number, memBlocked: number): Promise<{
|
|
11
|
+
today_tokens: number;
|
|
12
|
+
today_blocked: number;
|
|
13
|
+
events: FirewallEvent[];
|
|
14
|
+
}>;
|
|
15
|
+
export declare function registerCli(api: any, state: FirewallState, store: EventStore): void;
|
|
16
|
+
export declare function getStatus(state: FirewallState, store?: EventStore): Promise<object>;
|
|
17
|
+
export declare function getLog(store: EventStore, count: number): Promise<object[]>;
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAqBjD,yCAAyC;AACzC,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1G,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB,CAAC,CAmBD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAwHnF;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAyDzF;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAKhF"}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command implementation
|
|
3
|
+
*
|
|
4
|
+
* Register openclaw mapick <subcommand> command group
|
|
5
|
+
*/
|
|
6
|
+
import { readFile } from "node:fs/promises";
|
|
7
|
+
import http from "node:http";
|
|
8
|
+
const API_BASE = "http://127.0.0.1:18789";
|
|
9
|
+
function apiGet(path) {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
http.get(`${API_BASE}${path}`, () => resolve()).on("error", () => resolve());
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function apiPost(body) {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
const data = JSON.stringify(body);
|
|
17
|
+
const url = new URL(`${API_BASE}/mapick/api/config`);
|
|
18
|
+
const req = http.request(url, { method: "POST", headers: { "Content-Type": "application/json" } }, () => resolve());
|
|
19
|
+
req.on("error", () => resolve());
|
|
20
|
+
req.write(data);
|
|
21
|
+
req.end();
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/** Aggregate today's stats from JSONL */
|
|
25
|
+
export async function aggregateFromJsonl(store, memTokens, memBlocked) {
|
|
26
|
+
const todayStart = new Date();
|
|
27
|
+
todayStart.setHours(0, 0, 0, 0);
|
|
28
|
+
const todayTs = todayStart.getTime();
|
|
29
|
+
const events = [];
|
|
30
|
+
try {
|
|
31
|
+
const raw = await readFile(store.getEventsFilePath(), "utf-8");
|
|
32
|
+
for (const line of raw.trim().split("\n")) {
|
|
33
|
+
try {
|
|
34
|
+
const e = JSON.parse(line);
|
|
35
|
+
if (e.timestamp >= todayTs)
|
|
36
|
+
events.push(e);
|
|
37
|
+
}
|
|
38
|
+
catch { /* skip */ }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch { /* file not found */ }
|
|
42
|
+
const jsonlTokens = events.filter((e) => e.type === "model_call_ended").reduce((sum, e) => sum + (e.estimatedCost ?? 0), 0);
|
|
43
|
+
const jsonlBlocked = events.filter((e) => e.type === "blocked").length;
|
|
44
|
+
return { today_tokens: Math.max(memTokens, jsonlTokens), today_blocked: Math.max(memBlocked, jsonlBlocked), events };
|
|
45
|
+
}
|
|
46
|
+
export function registerCli(api, state, store) {
|
|
47
|
+
api.registerCli(({ program }) => {
|
|
48
|
+
const firewall = program.command("firewall").description("Mapick Cost Firewall commands");
|
|
49
|
+
firewall.command("status")
|
|
50
|
+
.description("Show firewall status")
|
|
51
|
+
.action(async () => {
|
|
52
|
+
const agg = await aggregateFromJsonl(store, state.globalStats.todayTokens, state.globalStats.todayBlocked);
|
|
53
|
+
const cooling = state.breaker.getCoolingSources();
|
|
54
|
+
console.log(JSON.stringify({
|
|
55
|
+
mode: state.globalStats.mode,
|
|
56
|
+
emergency_stop: state.globalStats.emergencyStop,
|
|
57
|
+
today_tokens: agg.today_tokens,
|
|
58
|
+
today_blocked: agg.today_blocked,
|
|
59
|
+
daily_token_limit: state.config.dailyTokenLimit,
|
|
60
|
+
cooldown_sec: state.config.breaker?.cooldownSec,
|
|
61
|
+
cooling_sources: cooling,
|
|
62
|
+
}, null, 2));
|
|
63
|
+
});
|
|
64
|
+
firewall.command("reset")
|
|
65
|
+
.description("Reset a source from cooldown")
|
|
66
|
+
.argument("<source>", "Source name to reset")
|
|
67
|
+
.action((source) => {
|
|
68
|
+
state.breaker.reset(source);
|
|
69
|
+
console.log(`Source ${source} reset.`);
|
|
70
|
+
});
|
|
71
|
+
firewall.command("mode")
|
|
72
|
+
.description("Switch mode (observe|protect)")
|
|
73
|
+
.argument("<mode>", "observe or protect")
|
|
74
|
+
.action(async (mode) => {
|
|
75
|
+
if (mode !== "observe" && mode !== "protect") {
|
|
76
|
+
console.error("Invalid mode. Use 'observe' or 'protect'.");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
state.setMode(mode);
|
|
80
|
+
await apiPost({ mode });
|
|
81
|
+
console.log(`Mode set to ${mode}`);
|
|
82
|
+
});
|
|
83
|
+
firewall.command("stop")
|
|
84
|
+
.description("Emergency stop all AI calls")
|
|
85
|
+
.action(async () => {
|
|
86
|
+
state.setEmergencyStop(true);
|
|
87
|
+
await apiPost({});
|
|
88
|
+
await apiGet("/mapick/api/stop");
|
|
89
|
+
console.log("Emergency stop activated.");
|
|
90
|
+
});
|
|
91
|
+
firewall.command("resume")
|
|
92
|
+
.description("Resume AI calls after emergency stop")
|
|
93
|
+
.action(async () => {
|
|
94
|
+
state.setEmergencyStop(false);
|
|
95
|
+
await apiGet("/mapick/api/resume");
|
|
96
|
+
console.log("Resumed.");
|
|
97
|
+
});
|
|
98
|
+
firewall.command("budget")
|
|
99
|
+
.description("Set or reset daily token limit")
|
|
100
|
+
.argument("<action>", "set <amount> or reset")
|
|
101
|
+
.argument("[amount]", "Token count")
|
|
102
|
+
.action(async (action, amount) => {
|
|
103
|
+
// Update via gateway's /config API (don't write file directly to avoid breaking format)
|
|
104
|
+
const http = await import("node:http");
|
|
105
|
+
let body;
|
|
106
|
+
if (action === "set" && amount) {
|
|
107
|
+
body = JSON.stringify({ dailyTokenLimit: parseInt(amount, 10) });
|
|
108
|
+
state.config.dailyTokenLimit = parseInt(amount, 10);
|
|
109
|
+
}
|
|
110
|
+
else if (action === "reset") {
|
|
111
|
+
body = JSON.stringify({ dailyTokenLimit: null });
|
|
112
|
+
state.config.dailyTokenLimit = null;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.error("Usage: firewall budget set <amount> | firewall budget reset");
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Write to memory + notify gateway (fire-and-forget)
|
|
119
|
+
const url = new URL("http://127.0.0.1:18789/mapick/api/config");
|
|
120
|
+
const req = http.request(url, { method: "POST", headers: { "Content-Type": "application/json" } }, (res) => {
|
|
121
|
+
let data = "";
|
|
122
|
+
res.on("data", (c) => data += c);
|
|
123
|
+
res.on("end", () => {
|
|
124
|
+
try {
|
|
125
|
+
const d = JSON.parse(data);
|
|
126
|
+
console.log(d.ok ? "Saved." : "Error: " + (d.error || "unknown"));
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
console.log("Config updated.");
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
req.on("error", () => console.log("Config updated (gateway unreachable, memory only)."));
|
|
134
|
+
req.write(body);
|
|
135
|
+
req.end();
|
|
136
|
+
});
|
|
137
|
+
firewall.command("log")
|
|
138
|
+
.description("Show recent events")
|
|
139
|
+
.option("--last <count>", "Number of events", "10")
|
|
140
|
+
.action(async (opts) => {
|
|
141
|
+
const count = parseInt(opts.last, 10) || 10;
|
|
142
|
+
try {
|
|
143
|
+
const raw = await readFile(store.getEventsFilePath(), "utf-8");
|
|
144
|
+
const lines = raw.trim().split("\n");
|
|
145
|
+
const recent = lines.slice(-count).map((l) => {
|
|
146
|
+
try {
|
|
147
|
+
return JSON.parse(l);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}).filter(Boolean);
|
|
153
|
+
for (const e of recent) {
|
|
154
|
+
const t = new Date(e.timestamp).toISOString().slice(11, 19);
|
|
155
|
+
const cost = e.estimatedCost ? `${Math.round(e.estimatedCost ?? 0)}t` : "";
|
|
156
|
+
console.log(`${t} | ${e.type.padEnd(22)} | ${(e.provider ?? "").padEnd(12)} | ${(e.model ?? "").padEnd(30)} | ${(e.outcome ?? "").padEnd(10)} | ${cost}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
console.log("No events recorded yet.");
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}, {
|
|
164
|
+
descriptors: [
|
|
165
|
+
{ name: "firewall", description: "Mapick Cost Firewall commands", hasSubcommands: true },
|
|
166
|
+
],
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
export async function getStatus(state, store) {
|
|
170
|
+
let spent = state.globalStats.todayTokens;
|
|
171
|
+
let blocked = state.globalStats.todayBlocked;
|
|
172
|
+
let coolingSources = state.breaker.getCoolingSources();
|
|
173
|
+
let activeRuns = state.getActiveRuns();
|
|
174
|
+
if (store) {
|
|
175
|
+
const agg = await aggregateFromJsonl(store, spent, blocked);
|
|
176
|
+
spent = agg.today_tokens;
|
|
177
|
+
blocked = agg.today_blocked;
|
|
178
|
+
// Aggregate cooling sources from events (source+reason of recent blocked events)
|
|
179
|
+
const recentBlocks = agg.events
|
|
180
|
+
.filter((e) => e.type === "blocked")
|
|
181
|
+
.slice(-10);
|
|
182
|
+
if (recentBlocks.length > 0 && coolingSources.length === 0) {
|
|
183
|
+
coolingSources = recentBlocks.map((e) => ({
|
|
184
|
+
source: e.source || "unknown",
|
|
185
|
+
reason: e.reason || "unknown",
|
|
186
|
+
remainingSec: 0,
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
// Aggregate active runs from events (runs without corresponding agent_end)
|
|
190
|
+
const runEnded = new Set(agg.events.filter((e) => e.type === "agent_end").map((e) => e.runId));
|
|
191
|
+
const activeRunMap = new Map();
|
|
192
|
+
for (const e of agg.events) {
|
|
193
|
+
if (e.runId && !runEnded.has(e.runId) && (e.type === "model_call_ended" || e.type === "run_status_change")) {
|
|
194
|
+
const r = activeRunMap.get(e.runId) || { runId: e.runId, source: e.source || "", calls: 0, tokens: 0, status: "healthy" };
|
|
195
|
+
if (e.type === "model_call_ended") {
|
|
196
|
+
r.calls++;
|
|
197
|
+
r.tokens += (e.estimatedCost || 0);
|
|
198
|
+
}
|
|
199
|
+
if (e.type === "run_status_change" && e.status) {
|
|
200
|
+
r.status = e.status;
|
|
201
|
+
if (e.reason)
|
|
202
|
+
r.reason = e.reason;
|
|
203
|
+
}
|
|
204
|
+
activeRunMap.set(e.runId, r);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (activeRunMap.size > 0 && activeRuns.length === 0) {
|
|
208
|
+
activeRuns = Array.from(activeRunMap.values());
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
mode: state.globalStats.mode,
|
|
213
|
+
emergency_stop: state.globalStats.emergencyStop,
|
|
214
|
+
today_tokens: spent,
|
|
215
|
+
today_blocked: blocked,
|
|
216
|
+
today_saved_estimate: state.globalStats.todaySavedEstimate,
|
|
217
|
+
daily_token_limit: state.config.dailyTokenLimit,
|
|
218
|
+
breaker: {
|
|
219
|
+
consecutive_failures: state.config.breaker?.consecutiveFailures,
|
|
220
|
+
cooldown_sec: state.config.breaker?.cooldownSec,
|
|
221
|
+
token_velocity_threshold: state.config.breaker?.tokenVelocityThreshold,
|
|
222
|
+
token_velocity_window_sec: state.config.breaker?.tokenVelocityWindowSec,
|
|
223
|
+
call_frequency_threshold: state.config.breaker?.callFrequencyThreshold,
|
|
224
|
+
call_frequency_window_sec: state.config.breaker?.callFrequencyWindowSec,
|
|
225
|
+
},
|
|
226
|
+
cooling_sources: coolingSources,
|
|
227
|
+
active_runs: activeRuns,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
export async function getLog(store, count) {
|
|
231
|
+
try {
|
|
232
|
+
const raw = await readFile(store.getEventsFilePath(), "utf-8");
|
|
233
|
+
return raw.trim().split("\n").slice(-count).map((l) => { try {
|
|
234
|
+
return JSON.parse(l);
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return null;
|
|
238
|
+
} }).filter(Boolean);
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
return [];
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config risk detection
|
|
3
|
+
*
|
|
4
|
+
* Check at startup whether fallback config may bypass Mapick
|
|
5
|
+
*/
|
|
6
|
+
export interface ConfigWarning {
|
|
7
|
+
level: "warn" | "error";
|
|
8
|
+
message: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function detectConfigRisks(config: any): ConfigWarning[];
|
|
11
|
+
//# sourceMappingURL=config-warn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-warn.d.ts","sourceRoot":"","sources":["../src/config-warn.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,GAAG,GAAG,aAAa,EAAE,CAuB9D"}
|