@dotsetlabs/dotclaw 2.4.0 → 2.6.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/.env.example +9 -10
- package/README.md +8 -4
- package/config-examples/runtime.json +34 -8
- package/config-examples/tool-policy.json +12 -2
- package/container/agent-runner/package-lock.json +2 -2
- package/container/agent-runner/package.json +1 -1
- package/container/agent-runner/src/agent-config.ts +19 -3
- package/container/agent-runner/src/container-protocol.ts +11 -0
- package/container/agent-runner/src/context-overflow-recovery.ts +39 -0
- package/container/agent-runner/src/index.ts +603 -165
- package/container/agent-runner/src/openrouter-input.ts +159 -0
- package/container/agent-runner/src/system-prompt.ts +13 -3
- package/container/agent-runner/src/tool-loop-policy.ts +741 -0
- package/container/agent-runner/src/tools.ts +211 -8
- package/dist/agent-context.d.ts +1 -0
- package/dist/agent-context.d.ts.map +1 -1
- package/dist/agent-context.js +21 -9
- package/dist/agent-context.js.map +1 -1
- package/dist/agent-execution.d.ts +2 -0
- package/dist/agent-execution.d.ts.map +1 -1
- package/dist/agent-execution.js +164 -15
- package/dist/agent-execution.js.map +1 -1
- package/dist/agent-semaphore.d.ts +24 -1
- package/dist/agent-semaphore.d.ts.map +1 -1
- package/dist/agent-semaphore.js +109 -20
- package/dist/agent-semaphore.js.map +1 -1
- package/dist/cli.js +3 -11
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/container-protocol.d.ts +22 -0
- package/dist/container-protocol.d.ts.map +1 -1
- package/dist/container-protocol.js.map +1 -1
- package/dist/container-runner.d.ts +7 -0
- package/dist/container-runner.d.ts.map +1 -1
- package/dist/container-runner.js +417 -143
- package/dist/container-runner.js.map +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +46 -12
- package/dist/db.js.map +1 -1
- package/dist/error-messages.d.ts.map +1 -1
- package/dist/error-messages.js +18 -4
- package/dist/error-messages.js.map +1 -1
- package/dist/failover-policy.d.ts +41 -0
- package/dist/failover-policy.d.ts.map +1 -0
- package/dist/failover-policy.js +261 -0
- package/dist/failover-policy.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/ipc-dispatcher.d.ts.map +1 -1
- package/dist/ipc-dispatcher.js +27 -43
- package/dist/ipc-dispatcher.js.map +1 -1
- package/dist/mcp-config.d.ts +22 -0
- package/dist/mcp-config.d.ts.map +1 -0
- package/dist/mcp-config.js +94 -0
- package/dist/mcp-config.js.map +1 -0
- package/dist/memory-backend.d.ts +27 -0
- package/dist/memory-backend.d.ts.map +1 -0
- package/dist/memory-backend.js +112 -0
- package/dist/memory-backend.js.map +1 -0
- package/dist/memory-recall.d.ts.map +1 -1
- package/dist/memory-recall.js +135 -22
- package/dist/memory-recall.js.map +1 -1
- package/dist/memory-store.d.ts +1 -0
- package/dist/memory-store.d.ts.map +1 -1
- package/dist/memory-store.js +55 -7
- package/dist/memory-store.js.map +1 -1
- package/dist/message-pipeline.d.ts +24 -0
- package/dist/message-pipeline.d.ts.map +1 -1
- package/dist/message-pipeline.js +131 -27
- package/dist/message-pipeline.js.map +1 -1
- package/dist/metrics.d.ts +1 -0
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +9 -0
- package/dist/metrics.js.map +1 -1
- package/dist/providers/discord/discord-provider.d.ts.map +1 -1
- package/dist/providers/discord/discord-provider.js +72 -4
- package/dist/providers/discord/discord-provider.js.map +1 -1
- package/dist/providers/telegram/telegram-provider.d.ts.map +1 -1
- package/dist/providers/telegram/telegram-provider.js +65 -3
- package/dist/providers/telegram/telegram-provider.js.map +1 -1
- package/dist/recall-policy.d.ts +12 -0
- package/dist/recall-policy.d.ts.map +1 -0
- package/dist/recall-policy.js +89 -0
- package/dist/recall-policy.js.map +1 -0
- package/dist/runtime-config.d.ts +33 -0
- package/dist/runtime-config.d.ts.map +1 -1
- package/dist/runtime-config.js +109 -9
- package/dist/runtime-config.js.map +1 -1
- package/dist/streaming.d.ts.map +1 -1
- package/dist/streaming.js +125 -33
- package/dist/streaming.js.map +1 -1
- package/dist/task-scheduler.d.ts.map +1 -1
- package/dist/task-scheduler.js +4 -2
- package/dist/task-scheduler.js.map +1 -1
- package/dist/tool-policy.d.ts.map +1 -1
- package/dist/tool-policy.js +26 -4
- package/dist/tool-policy.js.map +1 -1
- package/dist/trace-writer.d.ts +12 -0
- package/dist/trace-writer.d.ts.map +1 -1
- package/dist/trace-writer.js.map +1 -1
- package/dist/turn-hygiene.d.ts +14 -0
- package/dist/turn-hygiene.d.ts.map +1 -0
- package/dist/turn-hygiene.js +214 -0
- package/dist/turn-hygiene.js.map +1 -0
- package/dist/webhook.d.ts.map +1 -1
- package/dist/webhook.js +1 -0
- package/dist/webhook.js.map +1 -1
- package/package.json +15 -1
- package/scripts/benchmark-baseline.js +365 -0
- package/scripts/benchmark-harness.js +1413 -0
- package/scripts/benchmark-scenarios.js +301 -0
- package/scripts/canary-suite.js +123 -0
- package/scripts/generate-controlled-traces.js +230 -0
- package/scripts/release-slo-check.js +214 -0
- package/scripts/run-live-canary.js +339 -0
package/.env.example
CHANGED
|
@@ -8,16 +8,18 @@
|
|
|
8
8
|
# (they are NOT read from .env unless the script explicitly loads dotenv).
|
|
9
9
|
|
|
10
10
|
# --- Required (app runtime) ---
|
|
11
|
+
# Set at least one provider token (Telegram or Discord).
|
|
12
|
+
|
|
11
13
|
# Telegram bot token from @BotFather
|
|
12
|
-
TELEGRAM_BOT_TOKEN=123456789:replace-with-real-token
|
|
14
|
+
# TELEGRAM_BOT_TOKEN=123456789:replace-with-real-token
|
|
15
|
+
|
|
16
|
+
# Discord bot token (from Discord Developer Portal)
|
|
17
|
+
# DISCORD_BOT_TOKEN=replace-with-discord-token
|
|
13
18
|
|
|
14
19
|
# OpenRouter API key
|
|
15
20
|
OPENROUTER_API_KEY=sk-or-replace-with-real-key
|
|
16
21
|
|
|
17
22
|
# --- Optional (app runtime) ---
|
|
18
|
-
# Discord bot token (enables Discord provider)
|
|
19
|
-
# DISCORD_BOT_TOKEN=replace-with-discord-token
|
|
20
|
-
|
|
21
23
|
# Brave Search API key (enables WebSearch tool in the agent)
|
|
22
24
|
BRAVE_SEARCH_API_KEY=replace-with-brave-key
|
|
23
25
|
|
|
@@ -27,11 +29,8 @@ TZ=America/New_York
|
|
|
27
29
|
# GitHub Personal Access Token (enables gh CLI in containers)
|
|
28
30
|
# GH_TOKEN=ghp_your_token_here
|
|
29
31
|
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
|
|
33
|
-
# Override vision model for the AnalyzeImage tool (defaults to openai/gpt-4o)
|
|
34
|
-
# DOTCLAW_VISION_MODEL=openai/gpt-4o
|
|
32
|
+
# Container-only overrides (for example OPENAI_API_KEY or DOTCLAW_VISION_MODEL)
|
|
33
|
+
# should be set per group in ~/.dotclaw/data/registered_groups.json under containerConfig.env.
|
|
35
34
|
|
|
36
35
|
# --- Optional: System (set in shell before starting) ---
|
|
37
36
|
# Override DotClaw home directory (defaults to ~/.dotclaw)
|
|
@@ -63,7 +62,7 @@ TZ=America/New_York
|
|
|
63
62
|
# AUTOTUNE_OUTPUT_DIR=~/.dotclaw/prompts
|
|
64
63
|
# AUTOTUNE_CANARY_FRACTION=0.1
|
|
65
64
|
# AUTOTUNE_BEHAVIOR_CONFIG_PATH=~/.dotclaw/config/behavior.json
|
|
66
|
-
# AUTOTUNE_BEHAVIOR_REPORT_DIR=~/.dotclaw/
|
|
65
|
+
# AUTOTUNE_BEHAVIOR_REPORT_DIR=~/.dotclaw/data
|
|
67
66
|
# AUTOTUNE_BEHAVIOR_ENABLED=1
|
|
68
67
|
|
|
69
68
|
# --- Internal (do not set) ---
|
package/README.md
CHANGED
|
@@ -23,9 +23,10 @@ Personal OpenRouter-based assistant for Telegram and Discord. Each request runs
|
|
|
23
23
|
|
|
24
24
|
- Node.js 20+
|
|
25
25
|
- Docker (running)
|
|
26
|
-
-
|
|
26
|
+
- At least one provider token:
|
|
27
|
+
- Telegram bot token (from @BotFather), or
|
|
28
|
+
- Discord bot token
|
|
27
29
|
- OpenRouter API key
|
|
28
|
-
- Discord bot token (optional — for Discord provider)
|
|
29
30
|
|
|
30
31
|
## Quick Start
|
|
31
32
|
|
|
@@ -64,7 +65,10 @@ dotclaw groups # List registered chats
|
|
|
64
65
|
dotclaw build # Build the Docker container image
|
|
65
66
|
dotclaw add-instance # Create and start an isolated instance
|
|
66
67
|
dotclaw instances # List discovered instances
|
|
68
|
+
dotclaw install-service # Install launchd/systemd service
|
|
69
|
+
dotclaw uninstall-service # Remove launchd/systemd service
|
|
67
70
|
dotclaw version # Show installed version
|
|
71
|
+
dotclaw help # Show help
|
|
68
72
|
```
|
|
69
73
|
|
|
70
74
|
Instance flags:
|
|
@@ -80,7 +84,7 @@ All configuration and data is stored in `~/.dotclaw/`:
|
|
|
80
84
|
|
|
81
85
|
```
|
|
82
86
|
~/.dotclaw/
|
|
83
|
-
.env # Secrets (
|
|
87
|
+
.env # Secrets (provider tokens, OpenRouter key, optional Brave/GH keys)
|
|
84
88
|
config/
|
|
85
89
|
runtime.json # Runtime overrides
|
|
86
90
|
model.json # Model selection
|
|
@@ -119,7 +123,7 @@ Or see:
|
|
|
119
123
|
## Development
|
|
120
124
|
|
|
121
125
|
```bash
|
|
122
|
-
npm run dev # Run
|
|
126
|
+
npm run dev # Run from source (tsx)
|
|
123
127
|
npm run dev:up # Full dev cycle: rebuild container + kill stale daemons + start dev
|
|
124
128
|
npm run dev:down # Remove all running dotclaw agent containers
|
|
125
129
|
npm run build # Compile TypeScript (host)
|
|
@@ -4,8 +4,17 @@
|
|
|
4
4
|
"container": {
|
|
5
5
|
"mode": "daemon",
|
|
6
6
|
"privileged": true,
|
|
7
|
+
"daemonPollMs": 100,
|
|
7
8
|
"instanceId": ""
|
|
8
9
|
},
|
|
10
|
+
"messageQueue": {
|
|
11
|
+
"promptMaxChars": 24000
|
|
12
|
+
},
|
|
13
|
+
"concurrency": {
|
|
14
|
+
"maxAgents": 4,
|
|
15
|
+
"laneStarvationMs": 15000,
|
|
16
|
+
"maxConsecutiveInteractive": 3
|
|
17
|
+
},
|
|
9
18
|
"metrics": {
|
|
10
19
|
"port": 3001,
|
|
11
20
|
"enabled": true
|
|
@@ -20,6 +29,10 @@
|
|
|
20
29
|
},
|
|
21
30
|
"embeddings": {
|
|
22
31
|
"enabled": true
|
|
32
|
+
},
|
|
33
|
+
"backend": {
|
|
34
|
+
"strategy": "builtin",
|
|
35
|
+
"modulePath": ""
|
|
23
36
|
}
|
|
24
37
|
},
|
|
25
38
|
"routing": {
|
|
@@ -30,7 +43,11 @@
|
|
|
30
43
|
"maxToolSteps": 200,
|
|
31
44
|
"temperature": 0.6,
|
|
32
45
|
"recallMaxResults": 8,
|
|
33
|
-
"recallMaxTokens": 1500
|
|
46
|
+
"recallMaxTokens": 1500,
|
|
47
|
+
"hostFailover": {
|
|
48
|
+
"enabled": true,
|
|
49
|
+
"maxRetries": 1
|
|
50
|
+
}
|
|
34
51
|
},
|
|
35
52
|
"webhook": {
|
|
36
53
|
"enabled": false,
|
|
@@ -39,7 +56,7 @@
|
|
|
39
56
|
},
|
|
40
57
|
"streaming": {
|
|
41
58
|
"enabled": true,
|
|
42
|
-
"chunkFlushIntervalMs":
|
|
59
|
+
"chunkFlushIntervalMs": 120,
|
|
43
60
|
"editIntervalMs": 400,
|
|
44
61
|
"maxEditLength": 3800
|
|
45
62
|
},
|
|
@@ -57,6 +74,7 @@
|
|
|
57
74
|
"assistantName": "Rain",
|
|
58
75
|
"reasoning": { "effort": "medium" },
|
|
59
76
|
"context": {
|
|
77
|
+
"recentContextTokens": 0,
|
|
60
78
|
"maxHistoryTurns": 40,
|
|
61
79
|
"contextPruning": {
|
|
62
80
|
"softTrimMaxChars": 4000,
|
|
@@ -72,22 +90,30 @@
|
|
|
72
90
|
"enableBash": true,
|
|
73
91
|
"enableWebSearch": true,
|
|
74
92
|
"enableWebFetch": true,
|
|
93
|
+
"completionGuard": {
|
|
94
|
+
"idempotentRetryAttempts": 2,
|
|
95
|
+
"idempotentRetryBackoffMs": 500,
|
|
96
|
+
"repeatedSignatureThreshold": 3,
|
|
97
|
+
"repeatedRoundThreshold": 2,
|
|
98
|
+
"nonRetryableFailureThreshold": 3,
|
|
99
|
+
"forceSynthesisAfterTools": true
|
|
100
|
+
},
|
|
75
101
|
"bash": {
|
|
76
102
|
"timeoutMs": 600000
|
|
77
|
-
},
|
|
78
|
-
"process": {
|
|
79
|
-
"maxSessions": 16,
|
|
80
|
-
"maxOutputBytes": 1048576,
|
|
81
|
-
"defaultTimeoutMs": 1800000
|
|
82
103
|
}
|
|
83
104
|
},
|
|
105
|
+
"process": {
|
|
106
|
+
"maxSessions": 16,
|
|
107
|
+
"maxOutputBytes": 1048576,
|
|
108
|
+
"defaultTimeoutMs": 1800000
|
|
109
|
+
},
|
|
84
110
|
"tts": {
|
|
85
111
|
"provider": "edge-tts",
|
|
86
112
|
"openaiModel": "tts-1",
|
|
87
113
|
"openaiVoice": "alloy"
|
|
88
114
|
},
|
|
89
115
|
"mcp": {
|
|
90
|
-
"enabled":
|
|
116
|
+
"enabled": false,
|
|
91
117
|
"servers": []
|
|
92
118
|
}
|
|
93
119
|
}
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
"Bash",
|
|
14
14
|
"Python",
|
|
15
15
|
"Browser",
|
|
16
|
+
"Process",
|
|
17
|
+
"AnalyzeImage",
|
|
16
18
|
"mcp__dotclaw__send_message",
|
|
17
19
|
"mcp__dotclaw__send_file",
|
|
18
20
|
"mcp__dotclaw__send_photo",
|
|
@@ -41,14 +43,22 @@
|
|
|
41
43
|
"mcp__dotclaw__memory_forget",
|
|
42
44
|
"mcp__dotclaw__memory_list",
|
|
43
45
|
"mcp__dotclaw__memory_search",
|
|
44
|
-
"mcp__dotclaw__memory_stats"
|
|
46
|
+
"mcp__dotclaw__memory_stats",
|
|
47
|
+
"mcp__dotclaw__get_config",
|
|
48
|
+
"mcp__dotclaw__set_tool_policy",
|
|
49
|
+
"mcp__dotclaw__set_behavior",
|
|
50
|
+
"mcp__dotclaw__set_mcp_config",
|
|
51
|
+
"mcp__dotclaw__subagent"
|
|
45
52
|
],
|
|
46
53
|
"deny": [],
|
|
47
54
|
"max_per_run": {
|
|
48
55
|
"Bash": 128,
|
|
49
56
|
"Python": 64,
|
|
50
57
|
"WebSearch": 40,
|
|
51
|
-
"WebFetch": 60
|
|
58
|
+
"WebFetch": 60,
|
|
59
|
+
"Process": 128,
|
|
60
|
+
"AnalyzeImage": 16,
|
|
61
|
+
"mcp__dotclaw__subagent": 8
|
|
52
62
|
},
|
|
53
63
|
"default_max_per_run": 256
|
|
54
64
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dotclaw-agent-runner",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "dotclaw-agent-runner",
|
|
9
|
-
"version": "
|
|
9
|
+
"version": "2.3.0",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@openrouter/sdk": "^0.3.0",
|
|
12
12
|
"cron-parser": "^5.0.0",
|
|
@@ -56,6 +56,14 @@ export type AgentRuntimeConfig = {
|
|
|
56
56
|
enableBash: boolean;
|
|
57
57
|
enableWebSearch: boolean;
|
|
58
58
|
enableWebFetch: boolean;
|
|
59
|
+
completionGuard: {
|
|
60
|
+
idempotentRetryAttempts: number;
|
|
61
|
+
idempotentRetryBackoffMs: number;
|
|
62
|
+
repeatedSignatureThreshold: number;
|
|
63
|
+
repeatedRoundThreshold: number;
|
|
64
|
+
nonRetryableFailureThreshold: number;
|
|
65
|
+
forceSynthesisAfterTools: boolean;
|
|
66
|
+
};
|
|
59
67
|
webfetch: {
|
|
60
68
|
blockPrivate: boolean;
|
|
61
69
|
allowlist: string[];
|
|
@@ -143,7 +151,7 @@ export type AgentRuntimeConfig = {
|
|
|
143
151
|
|
|
144
152
|
const CONFIG_PATH = '/workspace/config/runtime.json';
|
|
145
153
|
const DEFAULT_DEFAULT_MODEL = 'moonshotai/kimi-k2.5';
|
|
146
|
-
const DEFAULT_DAEMON_POLL_MS =
|
|
154
|
+
const DEFAULT_DAEMON_POLL_MS = 100;
|
|
147
155
|
const DEFAULT_DAEMON_HEARTBEAT_INTERVAL_MS = 1_000;
|
|
148
156
|
|
|
149
157
|
const DEFAULT_AGENT_CONFIG: AgentRuntimeConfig['agent'] = {
|
|
@@ -163,7 +171,7 @@ const DEFAULT_AGENT_CONFIG: AgentRuntimeConfig['agent'] = {
|
|
|
163
171
|
context: {
|
|
164
172
|
maxContextTokens: 128_000,
|
|
165
173
|
compactionTriggerTokens: 120_000,
|
|
166
|
-
recentContextTokens: 0, // 0 = auto:
|
|
174
|
+
recentContextTokens: 0, // 0 = auto: 35% of model context window (capped at 24K)
|
|
167
175
|
summaryUpdateEveryMessages: 20,
|
|
168
176
|
maxOutputTokens: 8192,
|
|
169
177
|
summaryMaxOutputTokens: 2048,
|
|
@@ -198,6 +206,14 @@ const DEFAULT_AGENT_CONFIG: AgentRuntimeConfig['agent'] = {
|
|
|
198
206
|
enableBash: true,
|
|
199
207
|
enableWebSearch: true,
|
|
200
208
|
enableWebFetch: true,
|
|
209
|
+
completionGuard: {
|
|
210
|
+
idempotentRetryAttempts: 2,
|
|
211
|
+
idempotentRetryBackoffMs: 500,
|
|
212
|
+
repeatedSignatureThreshold: 3,
|
|
213
|
+
repeatedRoundThreshold: 2,
|
|
214
|
+
nonRetryableFailureThreshold: 3,
|
|
215
|
+
forceSynthesisAfterTools: true
|
|
216
|
+
},
|
|
201
217
|
webfetch: {
|
|
202
218
|
blockPrivate: true,
|
|
203
219
|
allowlist: [],
|
|
@@ -256,7 +272,7 @@ const DEFAULT_AGENT_CONFIG: AgentRuntimeConfig['agent'] = {
|
|
|
256
272
|
screenshotQuality: 80
|
|
257
273
|
},
|
|
258
274
|
mcp: {
|
|
259
|
-
enabled:
|
|
275
|
+
enabled: false,
|
|
260
276
|
servers: [],
|
|
261
277
|
connectionTimeoutMs: 10_000
|
|
262
278
|
},
|
|
@@ -13,6 +13,7 @@ export interface ContainerInput {
|
|
|
13
13
|
userName?: string;
|
|
14
14
|
maxToolSteps?: number;
|
|
15
15
|
memoryRecall?: string[];
|
|
16
|
+
memoryRecallAttempted?: boolean;
|
|
16
17
|
userProfile?: string | null;
|
|
17
18
|
memoryStats?: {
|
|
18
19
|
total: number;
|
|
@@ -92,4 +93,14 @@ export interface ContainerOutput {
|
|
|
92
93
|
replyToId?: string;
|
|
93
94
|
/** Set by the host container-runner when stdout was truncated before parsing */
|
|
94
95
|
stdoutTruncated?: boolean;
|
|
96
|
+
/** Number of in-loop idempotent tool retries attempted */
|
|
97
|
+
tool_retry_attempts?: number;
|
|
98
|
+
/** True when a forced final synthesis pass was used after tool execution */
|
|
99
|
+
tool_outcome_verification_forced?: boolean;
|
|
100
|
+
/** True when repeated tool signatures triggered loop-break protection */
|
|
101
|
+
tool_loop_breaker_triggered?: boolean;
|
|
102
|
+
/** Reason emitted when the tool loop breaker triggered */
|
|
103
|
+
tool_loop_breaker_reason?: string;
|
|
104
|
+
/** Error from fire-and-forget memory extraction in daemon mode */
|
|
105
|
+
memory_extraction_error?: string;
|
|
95
106
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type ContextMessageLike = {
|
|
2
|
+
role: 'user' | 'assistant';
|
|
3
|
+
content: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export type ContextOverflowRecoveryPlan = {
|
|
7
|
+
toCompact: ContextMessageLike[];
|
|
8
|
+
toKeep: ContextMessageLike[];
|
|
9
|
+
retryInput: Array<{ role: 'user' | 'assistant'; content: string }>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function buildContextOverflowRecoveryPlan(params: {
|
|
13
|
+
contextMessages: ContextMessageLike[];
|
|
14
|
+
emergencySummary?: string | null;
|
|
15
|
+
keepRecentCount?: number;
|
|
16
|
+
}): ContextOverflowRecoveryPlan {
|
|
17
|
+
const keepRecentCount = Number.isFinite(params.keepRecentCount)
|
|
18
|
+
? Math.max(1, Math.floor(Number(params.keepRecentCount)))
|
|
19
|
+
: 4;
|
|
20
|
+
const contextMessages = Array.isArray(params.contextMessages)
|
|
21
|
+
? params.contextMessages
|
|
22
|
+
: [];
|
|
23
|
+
|
|
24
|
+
const keepStart = Math.max(0, contextMessages.length - keepRecentCount);
|
|
25
|
+
const toCompact = contextMessages.slice(0, keepStart);
|
|
26
|
+
const toKeep = contextMessages.slice(keepStart);
|
|
27
|
+
const emergencySummary = (params.emergencySummary || '').trim();
|
|
28
|
+
|
|
29
|
+
const retryInput = emergencySummary
|
|
30
|
+
? [{ role: 'user' as const, content: `[Previous conversation summary: ${emergencySummary}]` },
|
|
31
|
+
...toKeep.map(msg => ({ role: msg.role, content: msg.content }))]
|
|
32
|
+
: toKeep.map(msg => ({ role: msg.role, content: msg.content }));
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
toCompact,
|
|
36
|
+
toKeep,
|
|
37
|
+
retryInput
|
|
38
|
+
};
|
|
39
|
+
}
|