@botiverse/raft-daemon 0.66.0 → 0.67.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.
@@ -1,5 +1,5 @@
1
1
  // src/core.ts
2
- import path18 from "path";
2
+ import path19 from "path";
3
3
  import os8 from "os";
4
4
  import { createRequire as createRequire3 } from "module";
5
5
  import { accessSync } from "fs";
@@ -50,427 +50,420 @@ var PI_BUILTIN_PROVIDER_MODELS_GENERATED = {
50
50
  { id: "deepseek/deepseek-v4-flash", label: "DeepSeek V4 Flash" }
51
51
  ],
52
52
  "minimax": [
53
+ { id: "minimax/MiniMax-M3", label: "MiniMax-M3" },
53
54
  { id: "minimax/MiniMax-M2.7", label: "MiniMax-M2.7" },
54
- { id: "minimax/MiniMax-M2.7-highspeed", label: "MiniMax-M2.7-highspeed" },
55
- { id: "minimax/MiniMax-M3", label: "MiniMax-M3" }
55
+ { id: "minimax/MiniMax-M2.7-highspeed", label: "MiniMax-M2.7-highspeed" }
56
56
  ],
57
57
  "minimax-cn": [
58
+ { id: "minimax-cn/MiniMax-M3", label: "MiniMax-M3" },
58
59
  { id: "minimax-cn/MiniMax-M2.7", label: "MiniMax-M2.7" },
59
- { id: "minimax-cn/MiniMax-M2.7-highspeed", label: "MiniMax-M2.7-highspeed" },
60
- { id: "minimax-cn/MiniMax-M3", label: "MiniMax-M3" }
60
+ { id: "minimax-cn/MiniMax-M2.7-highspeed", label: "MiniMax-M2.7-highspeed" }
61
61
  ],
62
62
  "zai": [
63
+ { id: "zai/glm-5.2", label: "GLM-5.2" },
63
64
  { id: "zai/glm-5.1", label: "GLM-5.1" },
64
- { id: "zai/glm-4.5-air", label: "GLM-4.5-Air" },
65
65
  { id: "zai/glm-4.7", label: "GLM-4.7" },
66
+ { id: "zai/glm-4.5-air", label: "GLM-4.5-Air" },
66
67
  { id: "zai/glm-5-turbo", label: "GLM-5-Turbo" },
67
- { id: "zai/glm-5.2", label: "GLM-5.2" },
68
68
  { id: "zai/glm-5v-turbo", label: "GLM-5V-Turbo" }
69
69
  ],
70
70
  "zai-coding-cn": [
71
+ { id: "zai-coding-cn/glm-5.2", label: "GLM-5.2" },
71
72
  { id: "zai-coding-cn/glm-5.1", label: "GLM-5.1" },
72
- { id: "zai-coding-cn/glm-4.5-air", label: "GLM-4.5-Air" },
73
73
  { id: "zai-coding-cn/glm-4.7", label: "GLM-4.7" },
74
+ { id: "zai-coding-cn/glm-4.5-air", label: "GLM-4.5-Air" },
74
75
  { id: "zai-coding-cn/glm-5-turbo", label: "GLM-5-Turbo" },
75
- { id: "zai-coding-cn/glm-5.2", label: "GLM-5.2" },
76
76
  { id: "zai-coding-cn/glm-5v-turbo", label: "GLM-5V-Turbo" }
77
77
  ],
78
78
  "moonshotai": [
79
- { id: "moonshotai/kimi-k2.6", label: "Kimi K2.6" },
80
- { id: "moonshotai/kimi-k2-0711-preview", label: "Kimi K2 0711" },
81
- { id: "moonshotai/kimi-k2-0905-preview", label: "Kimi K2 0905" },
79
+ { id: "moonshotai/kimi-k2.7-code", label: "Kimi K2.7 Code" },
82
80
  { id: "moonshotai/kimi-k2-thinking", label: "Kimi K2 Thinking" },
81
+ { id: "moonshotai/kimi-k2.7-code-highspeed", label: "Kimi K2.7 Code HighSpeed" },
83
82
  { id: "moonshotai/kimi-k2-thinking-turbo", label: "Kimi K2 Thinking Turbo" },
84
- { id: "moonshotai/kimi-k2-turbo-preview", label: "Kimi K2 Turbo" },
83
+ { id: "moonshotai/kimi-k2-0905-preview", label: "Kimi K2 0905" },
84
+ { id: "moonshotai/kimi-k2-0711-preview", label: "Kimi K2 0711" },
85
+ { id: "moonshotai/kimi-k2.6", label: "Kimi K2.6" },
85
86
  { id: "moonshotai/kimi-k2.5", label: "Kimi K2.5" },
86
- { id: "moonshotai/kimi-k2.7-code", label: "Kimi K2.7 Code" },
87
- { id: "moonshotai/kimi-k2.7-code-highspeed", label: "Kimi K2.7 Code HighSpeed" }
87
+ { id: "moonshotai/kimi-k2-turbo-preview", label: "Kimi K2 Turbo" }
88
88
  ],
89
89
  "moonshotai-cn": [
90
- { id: "moonshotai-cn/kimi-k2.6", label: "Kimi K2.6" },
91
- { id: "moonshotai-cn/kimi-k2-0711-preview", label: "Kimi K2 0711" },
92
- { id: "moonshotai-cn/kimi-k2-0905-preview", label: "Kimi K2 0905" },
90
+ { id: "moonshotai-cn/kimi-k2.7-code", label: "Kimi K2.7 Code" },
93
91
  { id: "moonshotai-cn/kimi-k2-thinking", label: "Kimi K2 Thinking" },
92
+ { id: "moonshotai-cn/kimi-k2.7-code-highspeed", label: "Kimi K2.7 Code HighSpeed" },
94
93
  { id: "moonshotai-cn/kimi-k2-thinking-turbo", label: "Kimi K2 Thinking Turbo" },
95
- { id: "moonshotai-cn/kimi-k2-turbo-preview", label: "Kimi K2 Turbo" },
94
+ { id: "moonshotai-cn/kimi-k2-0905-preview", label: "Kimi K2 0905" },
95
+ { id: "moonshotai-cn/kimi-k2-0711-preview", label: "Kimi K2 0711" },
96
+ { id: "moonshotai-cn/kimi-k2.6", label: "Kimi K2.6" },
96
97
  { id: "moonshotai-cn/kimi-k2.5", label: "Kimi K2.5" },
97
- { id: "moonshotai-cn/kimi-k2.7-code", label: "Kimi K2.7 Code" },
98
- { id: "moonshotai-cn/kimi-k2.7-code-highspeed", label: "Kimi K2.7 Code HighSpeed" }
98
+ { id: "moonshotai-cn/kimi-k2-turbo-preview", label: "Kimi K2 Turbo" }
99
99
  ],
100
100
  "kimi-coding": [
101
- { id: "kimi-coding/kimi-for-coding", label: "Kimi For Coding" },
101
+ { id: "kimi-coding/kimi-k2-thinking", label: "Kimi K2 Thinking" },
102
102
  { id: "kimi-coding/k2p7", label: "Kimi K2.7 Code" },
103
- { id: "kimi-coding/kimi-k2-thinking", label: "Kimi K2 Thinking" }
103
+ { id: "kimi-coding/kimi-for-coding", label: "Kimi For Coding" }
104
104
  ],
105
105
  "openrouter": [
106
- { id: "openrouter/moonshotai/kimi-k2.6", label: "MoonshotAI: Kimi K2.6" },
107
- { id: "openrouter/ai21/jamba-large-1.7", label: "AI21: Jamba Large 1.7" },
108
- { id: "openrouter/amazon/nova-2-lite-v1", label: "Amazon: Nova 2 Lite" },
109
- { id: "openrouter/amazon/nova-lite-v1", label: "Amazon: Nova Lite 1.0" },
110
- { id: "openrouter/amazon/nova-micro-v1", label: "Amazon: Nova Micro 1.0" },
111
- { id: "openrouter/amazon/nova-premier-v1", label: "Amazon: Nova Premier 1.0" },
112
- { id: "openrouter/amazon/nova-pro-v1", label: "Amazon: Nova Pro 1.0" },
113
- { id: "openrouter/anthropic/claude-3-haiku", label: "Anthropic: Claude 3 Haiku" },
114
- { id: "openrouter/anthropic/claude-3.5-haiku", label: "Anthropic: Claude 3.5 Haiku" },
115
106
  { id: "openrouter/anthropic/claude-fable-5", label: "Anthropic: Claude Fable 5" },
116
- { id: "openrouter/anthropic/claude-haiku-4.5", label: "Anthropic: Claude Haiku 4.5" },
117
- { id: "openrouter/anthropic/claude-opus-4", label: "Anthropic: Claude Opus 4" },
118
- { id: "openrouter/anthropic/claude-opus-4.1", label: "Anthropic: Claude Opus 4.1" },
119
- { id: "openrouter/anthropic/claude-opus-4.5", label: "Anthropic: Claude Opus 4.5" },
120
- { id: "openrouter/anthropic/claude-opus-4.6", label: "Anthropic: Claude Opus 4.6" },
121
- { id: "openrouter/anthropic/claude-opus-4.6-fast", label: "Anthropic: Claude Opus 4.6 (Fast)" },
122
- { id: "openrouter/anthropic/claude-opus-4.7", label: "Anthropic: Claude Opus 4.7" },
123
- { id: "openrouter/anthropic/claude-opus-4.7-fast", label: "Anthropic: Claude Opus 4.7 (Fast)" },
107
+ { id: "openrouter/~anthropic/claude-fable-latest", label: "Anthropic: Claude Fable Latest" },
124
108
  { id: "openrouter/anthropic/claude-opus-4.8", label: "Anthropic: Claude Opus 4.8" },
109
+ { id: "openrouter/anthropic/claude-opus-4.7", label: "Anthropic: Claude Opus 4.7" },
110
+ { id: "openrouter/anthropic/claude-opus-4.6", label: "Anthropic: Claude Opus 4.6" },
111
+ { id: "openrouter/anthropic/claude-opus-4.5", label: "Anthropic: Claude Opus 4.5" },
112
+ { id: "openrouter/anthropic/claude-opus-4.1", label: "Anthropic: Claude Opus 4.1" },
113
+ { id: "openrouter/anthropic/claude-opus-4", label: "Anthropic: Claude Opus 4" },
114
+ { id: "openrouter/~anthropic/claude-opus-latest", label: "Anthropic: Claude Opus Latest" },
125
115
  { id: "openrouter/anthropic/claude-opus-4.8-fast", label: "Anthropic: Claude Opus 4.8 (Fast)" },
126
- { id: "openrouter/anthropic/claude-sonnet-4", label: "Anthropic: Claude Sonnet 4" },
127
- { id: "openrouter/anthropic/claude-sonnet-4.5", label: "Anthropic: Claude Sonnet 4.5" },
116
+ { id: "openrouter/anthropic/claude-opus-4.7-fast", label: "Anthropic: Claude Opus 4.7 (Fast)" },
117
+ { id: "openrouter/anthropic/claude-sonnet-5", label: "Anthropic: Claude Sonnet 5" },
128
118
  { id: "openrouter/anthropic/claude-sonnet-4.6", label: "Anthropic: Claude Sonnet 4.6" },
129
- { id: "openrouter/arcee-ai/trinity-large-thinking", label: "Arcee AI: Trinity Large Thinking" },
130
- { id: "openrouter/arcee-ai/trinity-mini", label: "Arcee AI: Trinity Mini" },
131
- { id: "openrouter/arcee-ai/virtuoso-large", label: "Arcee AI: Virtuoso Large" },
132
- { id: "openrouter/auto", label: "Auto" },
133
- { id: "openrouter/bytedance-seed/seed-1.6", label: "ByteDance Seed: Seed 1.6" },
134
- { id: "openrouter/bytedance-seed/seed-1.6-flash", label: "ByteDance Seed: Seed 1.6 Flash" },
135
- { id: "openrouter/bytedance-seed/seed-2.0-lite", label: "ByteDance Seed: Seed-2.0-Lite" },
136
- { id: "openrouter/bytedance-seed/seed-2.0-mini", label: "ByteDance Seed: Seed-2.0-Mini" },
137
- { id: "openrouter/cohere/command-r-08-2024", label: "Cohere: Command R (08-2024)" },
138
- { id: "openrouter/cohere/command-r-plus-08-2024", label: "Cohere: Command R+ (08-2024)" },
139
- { id: "openrouter/cohere/north-mini-code:free", label: "Cohere: North Mini Code (free)" },
140
- { id: "openrouter/deepseek/deepseek-chat", label: "DeepSeek: DeepSeek V3" },
141
- { id: "openrouter/deepseek/deepseek-chat-v3-0324", label: "DeepSeek: DeepSeek V3 0324" },
142
- { id: "openrouter/deepseek/deepseek-chat-v3.1", label: "DeepSeek: DeepSeek V3.1" },
143
- { id: "openrouter/deepseek/deepseek-r1", label: "DeepSeek: R1" },
144
- { id: "openrouter/deepseek/deepseek-r1-0528", label: "DeepSeek: R1 0528" },
145
- { id: "openrouter/deepseek/deepseek-v3.1-terminus", label: "DeepSeek: DeepSeek V3.1 Terminus" },
146
- { id: "openrouter/deepseek/deepseek-v3.2", label: "DeepSeek: DeepSeek V3.2" },
147
- { id: "openrouter/deepseek/deepseek-v3.2-exp", label: "DeepSeek: DeepSeek V3.2 Exp" },
148
- { id: "openrouter/deepseek/deepseek-v4-flash", label: "DeepSeek: DeepSeek V4 Flash" },
149
- { id: "openrouter/deepseek/deepseek-v4-pro", label: "DeepSeek: DeepSeek V4 Pro" },
150
- { id: "openrouter/essentialai/rnj-1-instruct", label: "EssentialAI: Rnj 1 Instruct" },
151
- { id: "openrouter/google/gemini-2.5-flash", label: "Google: Gemini 2.5 Flash" },
152
- { id: "openrouter/google/gemini-2.5-flash-lite", label: "Google: Gemini 2.5 Flash Lite" },
153
- { id: "openrouter/google/gemini-2.5-flash-lite-preview-09-2025", label: "Google: Gemini 2.5 Flash Lite Preview 09-2025" },
154
- { id: "openrouter/google/gemini-2.5-pro", label: "Google: Gemini 2.5 Pro" },
119
+ { id: "openrouter/anthropic/claude-sonnet-4.5", label: "Anthropic: Claude Sonnet 4.5" },
120
+ { id: "openrouter/anthropic/claude-sonnet-4", label: "Anthropic: Claude Sonnet 4" },
121
+ { id: "openrouter/~anthropic/claude-sonnet-latest", label: "Anthropic Claude Sonnet Latest" },
122
+ { id: "openrouter/anthropic/claude-haiku-4.5", label: "Anthropic: Claude Haiku 4.5" },
123
+ { id: "openrouter/anthropic/claude-3-haiku", label: "Anthropic: Claude 3 Haiku" },
124
+ { id: "openrouter/~anthropic/claude-haiku-latest", label: "Anthropic Claude Haiku Latest" },
125
+ { id: "openrouter/openai/gpt-5.1-codex-max", label: "OpenAI: GPT-5.1-Codex-Max" },
126
+ { id: "openrouter/kwaipilot/kat-coder-pro-v2", label: "Kwaipilot: KAT-Coder-Pro V2" },
127
+ { id: "openrouter/qwen/qwen3-max-thinking", label: "Qwen: Qwen3 Max Thinking" },
128
+ { id: "openrouter/nvidia/nemotron-3-ultra-550b-a55b", label: "NVIDIA: Nemotron 3 Ultra" },
155
129
  { id: "openrouter/google/gemini-2.5-pro-preview", label: "Google: Gemini 2.5 Pro Preview 06-05" },
156
130
  { id: "openrouter/google/gemini-2.5-pro-preview-05-06", label: "Google: Gemini 2.5 Pro Preview 05-06" },
157
- { id: "openrouter/google/gemini-3-flash-preview", label: "Google: Gemini 3 Flash Preview" },
158
- { id: "openrouter/google/gemini-3-pro-image", label: "Google: Nano Banana Pro (Gemini 3 Pro Image)" },
159
- { id: "openrouter/google/gemini-3.1-flash-lite", label: "Google: Gemini 3.1 Flash Lite" },
160
- { id: "openrouter/google/gemini-3.1-flash-lite-preview", label: "Google: Gemini 3.1 Flash Lite Preview" },
131
+ { id: "openrouter/openai/gpt-5.5-pro", label: "OpenAI: GPT-5.5 Pro" },
132
+ { id: "openrouter/openai/gpt-5.4-pro", label: "OpenAI: GPT-5.4 Pro" },
133
+ { id: "openrouter/openai/gpt-5.2-pro", label: "OpenAI: GPT-5.2 Pro" },
134
+ { id: "openrouter/openai/gpt-5-pro", label: "OpenAI: GPT-5 Pro" },
135
+ { id: "openrouter/deepseek/deepseek-v4-pro", label: "DeepSeek: DeepSeek V4 Pro" },
136
+ { id: "openrouter/qwen/qwen3.7-max", label: "Qwen: Qwen3.7 Max" },
137
+ { id: "openrouter/qwen/qwen3.6-max-preview", label: "Qwen: Qwen3.6 Max Preview" },
161
138
  { id: "openrouter/google/gemini-3.1-pro-preview", label: "Google: Gemini 3.1 Pro Preview" },
162
139
  { id: "openrouter/google/gemini-3.1-pro-preview-customtools", label: "Google: Gemini 3.1 Pro Preview Custom Tools" },
163
- { id: "openrouter/google/gemini-3.5-flash", label: "Google: Gemini 3.5 Flash" },
164
- { id: "openrouter/google/gemma-3-12b-it", label: "Google: Gemma 3 12B" },
165
- { id: "openrouter/google/gemma-3-27b-it", label: "Google: Gemma 3 27B" },
166
- { id: "openrouter/google/gemma-4-26b-a4b-it", label: "Google: Gemma 4 26B A4B " },
167
- { id: "openrouter/google/gemma-4-26b-a4b-it:free", label: "Google: Gemma 4 26B A4B (free)" },
168
- { id: "openrouter/google/gemma-4-31b-it", label: "Google: Gemma 4 31B" },
169
- { id: "openrouter/google/gemma-4-31b-it:free", label: "Google: Gemma 4 31B (free)" },
170
- { id: "openrouter/ibm-granite/granite-4.1-8b", label: "IBM: Granite 4.1 8B" },
171
- { id: "openrouter/inception/mercury-2", label: "Inception: Mercury 2" },
172
- { id: "openrouter/inclusionai/ling-2.6-1t", label: "inclusionAI: Ling-2.6-1T" },
173
- { id: "openrouter/inclusionai/ling-2.6-flash", label: "inclusionAI: Ling-2.6-flash" },
174
- { id: "openrouter/inclusionai/ring-2.6-1t", label: "inclusionAI: Ring-2.6-1T" },
175
- { id: "openrouter/kwaipilot/kat-coder-pro-v2", label: "Kwaipilot: KAT-Coder-Pro V2" },
176
- { id: "openrouter/liquid/lfm-2.5-1.2b-thinking:free", label: "LiquidAI: LFM2.5-1.2B-Thinking (free)" },
177
- { id: "openrouter/meta-llama/llama-3.1-70b-instruct", label: "Meta: Llama 3.1 70B Instruct" },
178
- { id: "openrouter/meta-llama/llama-3.1-8b-instruct", label: "Meta: Llama 3.1 8B Instruct" },
179
- { id: "openrouter/meta-llama/llama-3.3-70b-instruct", label: "Meta: Llama 3.3 70B Instruct" },
180
- { id: "openrouter/meta-llama/llama-3.3-70b-instruct:free", label: "Meta: Llama 3.3 70B Instruct (free)" },
181
- { id: "openrouter/meta-llama/llama-4-maverick", label: "Meta: Llama 4 Maverick" },
182
- { id: "openrouter/meta-llama/llama-4-scout", label: "Meta: Llama 4 Scout" },
183
- { id: "openrouter/minimax/minimax-m1", label: "MiniMax: MiniMax M1" },
184
- { id: "openrouter/minimax/minimax-m2", label: "MiniMax: MiniMax M2" },
185
- { id: "openrouter/minimax/minimax-m2.1", label: "MiniMax: MiniMax M2.1" },
186
- { id: "openrouter/minimax/minimax-m2.5", label: "MiniMax: MiniMax M2.5" },
187
- { id: "openrouter/minimax/minimax-m2.7", label: "MiniMax: MiniMax M2.7" },
188
- { id: "openrouter/minimax/minimax-m3", label: "MiniMax: MiniMax M3" },
189
- { id: "openrouter/mistralai/codestral-2508", label: "Mistral: Codestral 2508" },
190
- { id: "openrouter/mistralai/devstral-2512", label: "Mistral: Devstral 2 2512" },
191
- { id: "openrouter/mistralai/ministral-14b-2512", label: "Mistral: Ministral 3 14B 2512" },
192
- { id: "openrouter/mistralai/ministral-3b-2512", label: "Mistral: Ministral 3 3B 2512" },
193
- { id: "openrouter/mistralai/ministral-8b-2512", label: "Mistral: Ministral 3 8B 2512" },
194
- { id: "openrouter/mistralai/mistral-large", label: "Mistral Large" },
195
- { id: "openrouter/mistralai/mistral-large-2407", label: "Mistral Large 2407" },
196
- { id: "openrouter/mistralai/mistral-large-2512", label: "Mistral: Mistral Large 3 2512" },
197
- { id: "openrouter/mistralai/mistral-medium-3", label: "Mistral: Mistral Medium 3" },
198
- { id: "openrouter/mistralai/mistral-medium-3-5", label: "Mistral: Mistral Medium 3.5" },
199
- { id: "openrouter/mistralai/mistral-medium-3.1", label: "Mistral: Mistral Medium 3.1" },
200
- { id: "openrouter/mistralai/mistral-nemo", label: "Mistral: Mistral Nemo" },
201
- { id: "openrouter/mistralai/mistral-saba", label: "Mistral: Saba" },
202
- { id: "openrouter/mistralai/mistral-small-2603", label: "Mistral: Mistral Small 4" },
203
- { id: "openrouter/mistralai/mistral-small-3.2-24b-instruct", label: "Mistral: Mistral Small 3.2 24B" },
204
- { id: "openrouter/mistralai/mixtral-8x22b-instruct", label: "Mistral: Mixtral 8x22B Instruct" },
205
- { id: "openrouter/mistralai/voxtral-small-24b-2507", label: "Mistral: Voxtral Small 24B 2507" },
206
- { id: "openrouter/moonshotai/kimi-k2", label: "MoonshotAI: Kimi K2 0711" },
207
- { id: "openrouter/moonshotai/kimi-k2-0905", label: "MoonshotAI: Kimi K2 0905" },
208
- { id: "openrouter/moonshotai/kimi-k2-thinking", label: "MoonshotAI: Kimi K2 Thinking" },
209
- { id: "openrouter/moonshotai/kimi-k2.5", label: "MoonshotAI: Kimi K2.5" },
210
- { id: "openrouter/moonshotai/kimi-k2.7-code", label: "MoonshotAI: Kimi K2.7 Code" },
211
- { id: "openrouter/nex-agi/nex-n2-pro:free", label: "Nex AGI: Nex-N2-Pro (free)" },
212
- { id: "openrouter/nvidia/llama-3.3-nemotron-super-49b-v1.5", label: "NVIDIA: Llama 3.3 Nemotron Super 49B V1.5" },
213
- { id: "openrouter/nvidia/nemotron-3-nano-30b-a3b", label: "NVIDIA: Nemotron 3 Nano 30B A3B" },
214
- { id: "openrouter/nvidia/nemotron-3-nano-30b-a3b:free", label: "NVIDIA: Nemotron 3 Nano 30B A3B (free)" },
215
- { id: "openrouter/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free", label: "NVIDIA: Nemotron 3 Nano Omni (free)" },
216
- { id: "openrouter/nvidia/nemotron-3-super-120b-a12b", label: "NVIDIA: Nemotron 3 Super" },
217
- { id: "openrouter/nvidia/nemotron-3-super-120b-a12b:free", label: "NVIDIA: Nemotron 3 Super (free)" },
218
- { id: "openrouter/nvidia/nemotron-3-ultra-550b-a55b", label: "NVIDIA: Nemotron 3 Ultra" },
219
- { id: "openrouter/nvidia/nemotron-3-ultra-550b-a55b:free", label: "NVIDIA: Nemotron 3 Ultra (free)" },
220
- { id: "openrouter/nvidia/nemotron-nano-12b-v2-vl:free", label: "NVIDIA: Nemotron Nano 12B 2 VL (free)" },
221
- { id: "openrouter/nvidia/nemotron-nano-9b-v2:free", label: "NVIDIA: Nemotron Nano 9B V2 (free)" },
222
- { id: "openrouter/openai/gpt-3.5-turbo", label: "OpenAI: GPT-3.5 Turbo" },
223
- { id: "openrouter/openai/gpt-3.5-turbo-0613", label: "OpenAI: GPT-3.5 Turbo (older v0613)" },
224
- { id: "openrouter/openai/gpt-3.5-turbo-16k", label: "OpenAI: GPT-3.5 Turbo 16k" },
225
- { id: "openrouter/openai/gpt-4", label: "OpenAI: GPT-4" },
226
- { id: "openrouter/openai/gpt-4-turbo", label: "OpenAI: GPT-4 Turbo" },
227
- { id: "openrouter/openai/gpt-4-turbo-preview", label: "OpenAI: GPT-4 Turbo Preview" },
228
- { id: "openrouter/openai/gpt-4.1", label: "OpenAI: GPT-4.1" },
229
- { id: "openrouter/openai/gpt-4.1-mini", label: "OpenAI: GPT-4.1 Mini" },
230
- { id: "openrouter/openai/gpt-4.1-nano", label: "OpenAI: GPT-4.1 Nano" },
231
- { id: "openrouter/openai/gpt-4o", label: "OpenAI: GPT-4o" },
232
- { id: "openrouter/openai/gpt-4o-2024-05-13", label: "OpenAI: GPT-4o (2024-05-13)" },
233
- { id: "openrouter/openai/gpt-4o-2024-08-06", label: "OpenAI: GPT-4o (2024-08-06)" },
234
- { id: "openrouter/openai/gpt-4o-2024-11-20", label: "OpenAI: GPT-4o (2024-11-20)" },
235
- { id: "openrouter/openai/gpt-4o-mini", label: "OpenAI: GPT-4o-mini" },
236
- { id: "openrouter/openai/gpt-4o-mini-2024-07-18", label: "OpenAI: GPT-4o-mini (2024-07-18)" },
237
- { id: "openrouter/openai/gpt-5", label: "OpenAI: GPT-5" },
238
- { id: "openrouter/openai/gpt-5-codex", label: "OpenAI: GPT-5 Codex" },
239
- { id: "openrouter/openai/gpt-5-mini", label: "OpenAI: GPT-5 Mini" },
240
- { id: "openrouter/openai/gpt-5-nano", label: "OpenAI: GPT-5 Nano" },
241
- { id: "openrouter/openai/gpt-5-pro", label: "OpenAI: GPT-5 Pro" },
242
- { id: "openrouter/openai/gpt-5.1", label: "OpenAI: GPT-5.1" },
243
- { id: "openrouter/openai/gpt-5.1-chat", label: "OpenAI: GPT-5.1 Chat" },
244
- { id: "openrouter/openai/gpt-5.1-codex", label: "OpenAI: GPT-5.1-Codex" },
245
- { id: "openrouter/openai/gpt-5.1-codex-max", label: "OpenAI: GPT-5.1-Codex-Max" },
246
- { id: "openrouter/openai/gpt-5.1-codex-mini", label: "OpenAI: GPT-5.1-Codex-Mini" },
247
- { id: "openrouter/openai/gpt-5.2", label: "OpenAI: GPT-5.2" },
248
- { id: "openrouter/openai/gpt-5.2-chat", label: "OpenAI: GPT-5.2 Chat" },
249
- { id: "openrouter/openai/gpt-5.2-codex", label: "OpenAI: GPT-5.2-Codex" },
250
- { id: "openrouter/openai/gpt-5.2-pro", label: "OpenAI: GPT-5.2 Pro" },
251
- { id: "openrouter/openai/gpt-5.3-chat", label: "OpenAI: GPT-5.3 Chat" },
252
- { id: "openrouter/openai/gpt-5.3-codex", label: "OpenAI: GPT-5.3-Codex" },
253
- { id: "openrouter/openai/gpt-5.4", label: "OpenAI: GPT-5.4" },
254
- { id: "openrouter/openai/gpt-5.4-mini", label: "OpenAI: GPT-5.4 Mini" },
255
- { id: "openrouter/openai/gpt-5.4-nano", label: "OpenAI: GPT-5.4 Nano" },
256
- { id: "openrouter/openai/gpt-5.4-pro", label: "OpenAI: GPT-5.4 Pro" },
257
- { id: "openrouter/openai/gpt-5.5", label: "OpenAI: GPT-5.5" },
258
- { id: "openrouter/openai/gpt-5.5-pro", label: "OpenAI: GPT-5.5 Pro" },
259
- { id: "openrouter/openai/gpt-audio", label: "OpenAI: GPT Audio" },
260
- { id: "openrouter/openai/gpt-audio-mini", label: "OpenAI: GPT Audio Mini" },
261
- { id: "openrouter/openai/gpt-chat-latest", label: "OpenAI: GPT Chat Latest" },
262
- { id: "openrouter/openai/gpt-oss-120b", label: "OpenAI: gpt-oss-120b" },
263
- { id: "openrouter/openai/gpt-oss-120b:free", label: "OpenAI: gpt-oss-120b (free)" },
264
- { id: "openrouter/openai/gpt-oss-20b", label: "OpenAI: gpt-oss-20b" },
265
- { id: "openrouter/openai/gpt-oss-20b:free", label: "OpenAI: gpt-oss-20b (free)" },
266
- { id: "openrouter/openai/gpt-oss-safeguard-20b", label: "OpenAI: gpt-oss-safeguard-20b" },
267
- { id: "openrouter/openai/o1", label: "OpenAI: o1" },
268
- { id: "openrouter/openai/o3", label: "OpenAI: o3" },
269
- { id: "openrouter/openai/o3-deep-research", label: "OpenAI: o3 Deep Research" },
270
- { id: "openrouter/openai/o3-mini", label: "OpenAI: o3 Mini" },
271
- { id: "openrouter/openai/o3-mini-high", label: "OpenAI: o3 Mini High" },
272
140
  { id: "openrouter/openai/o3-pro", label: "OpenAI: o3 Pro" },
273
- { id: "openrouter/openai/o4-mini", label: "OpenAI: o4 Mini" },
274
- { id: "openrouter/openai/o4-mini-deep-research", label: "OpenAI: o4 Mini Deep Research" },
275
- { id: "openrouter/openai/o4-mini-high", label: "OpenAI: o4 Mini High" },
276
- { id: "openrouter/openrouter/auto", label: "Auto Router" },
277
- { id: "openrouter/openrouter/free", label: "Free Models Router" },
278
- { id: "openrouter/openrouter/fusion", label: "OpenRouter: Fusion" },
279
- { id: "openrouter/openrouter/owl-alpha", label: "Owl Alpha" },
280
- { id: "openrouter/poolside/laguna-m.1", label: "Poolside: Laguna M.1" },
281
- { id: "openrouter/poolside/laguna-m.1:free", label: "Poolside: Laguna M.1 (free)" },
282
- { id: "openrouter/poolside/laguna-xs.2", label: "Poolside: Laguna XS.2" },
283
- { id: "openrouter/poolside/laguna-xs.2:free", label: "Poolside: Laguna XS.2 (free)" },
284
- { id: "openrouter/prime-intellect/intellect-3", label: "Prime Intellect: INTELLECT-3" },
285
- { id: "openrouter/qwen/qwen-2.5-72b-instruct", label: "Qwen2.5 72B Instruct" },
286
- { id: "openrouter/qwen/qwen-2.5-7b-instruct", label: "Qwen: Qwen2.5 7B Instruct" },
287
- { id: "openrouter/qwen/qwen-plus", label: "Qwen: Qwen-Plus" },
288
- { id: "openrouter/qwen/qwen-plus-2025-07-28", label: "Qwen: Qwen Plus 0728" },
289
- { id: "openrouter/qwen/qwen-plus-2025-07-28:thinking", label: "Qwen: Qwen Plus 0728 (thinking)" },
290
- { id: "openrouter/qwen/qwen3-14b", label: "Qwen: Qwen3 14B" },
291
- { id: "openrouter/qwen/qwen3-235b-a22b", label: "Qwen: Qwen3 235B A22B" },
292
- { id: "openrouter/qwen/qwen3-235b-a22b-2507", label: "Qwen: Qwen3 235B A22B Instruct 2507" },
293
- { id: "openrouter/qwen/qwen3-235b-a22b-thinking-2507", label: "Qwen: Qwen3 235B A22B Thinking 2507" },
294
- { id: "openrouter/qwen/qwen3-30b-a3b", label: "Qwen: Qwen3 30B A3B" },
295
- { id: "openrouter/qwen/qwen3-30b-a3b-instruct-2507", label: "Qwen: Qwen3 30B A3B Instruct 2507" },
296
- { id: "openrouter/qwen/qwen3-30b-a3b-thinking-2507", label: "Qwen: Qwen3 30B A3B Thinking 2507" },
297
- { id: "openrouter/qwen/qwen3-32b", label: "Qwen: Qwen3 32B" },
298
- { id: "openrouter/qwen/qwen3-8b", label: "Qwen: Qwen3 8B" },
141
+ { id: "openrouter/qwen/qwen3-max", label: "Qwen: Qwen3 Max" },
142
+ { id: "openrouter/upstage/solar-pro-3", label: "Upstage: Solar Pro 3" },
143
+ { id: "openrouter/google/gemini-2.5-pro", label: "Google: Gemini 2.5 Pro" },
144
+ { id: "openrouter/xiaomi/mimo-v2.5-pro", label: "Xiaomi: MiMo-V2.5-Pro" },
145
+ { id: "openrouter/amazon/nova-premier-v1", label: "Amazon: Nova Premier 1.0" },
146
+ { id: "openrouter/amazon/nova-pro-v1", label: "Amazon: Nova Pro 1.0" },
147
+ { id: "openrouter/~google/gemini-pro-latest", label: "Google Gemini Pro Latest" },
148
+ { id: "openrouter/sakana/fugu-ultra", label: "Sakana: Fugu Ultra" },
149
+ { id: "openrouter/arcee-ai/trinity-large-thinking", label: "Arcee AI: Trinity Large Thinking" },
299
150
  { id: "openrouter/qwen/qwen3-coder", label: "Qwen: Qwen3 Coder 480B A35B" },
300
151
  { id: "openrouter/qwen/qwen3-coder-30b-a3b-instruct", label: "Qwen: Qwen3 Coder 30B A3B Instruct" },
301
- { id: "openrouter/qwen/qwen3-coder-flash", label: "Qwen: Qwen3 Coder Flash" },
152
+ { id: "openrouter/openai/gpt-5.3-codex", label: "OpenAI: GPT-5.3-Codex" },
153
+ { id: "openrouter/openai/gpt-5.2-codex", label: "OpenAI: GPT-5.2-Codex" },
154
+ { id: "openrouter/openai/gpt-5.1-codex", label: "OpenAI: GPT-5.1-Codex" },
155
+ { id: "openrouter/openai/gpt-5-codex", label: "OpenAI: GPT-5 Codex" },
302
156
  { id: "openrouter/qwen/qwen3-coder-next", label: "Qwen: Qwen3 Coder Next" },
303
157
  { id: "openrouter/qwen/qwen3-coder-plus", label: "Qwen: Qwen3 Coder Plus" },
304
- { id: "openrouter/qwen/qwen3-coder:free", label: "Qwen: Qwen3 Coder 480B A35B (free)" },
305
- { id: "openrouter/qwen/qwen3-max", label: "Qwen: Qwen3 Max" },
306
- { id: "openrouter/qwen/qwen3-max-thinking", label: "Qwen: Qwen3 Max Thinking" },
307
- { id: "openrouter/qwen/qwen3-next-80b-a3b-instruct", label: "Qwen: Qwen3 Next 80B A3B Instruct" },
308
- { id: "openrouter/qwen/qwen3-next-80b-a3b-instruct:free", label: "Qwen: Qwen3 Next 80B A3B Instruct (free)" },
309
- { id: "openrouter/qwen/qwen3-next-80b-a3b-thinking", label: "Qwen: Qwen3 Next 80B A3B Thinking" },
310
- { id: "openrouter/qwen/qwen3-vl-235b-a22b-instruct", label: "Qwen: Qwen3 VL 235B A22B Instruct" },
158
+ { id: "openrouter/moonshotai/kimi-k2.7-code", label: "MoonshotAI: Kimi K2.7 Code" },
159
+ { id: "openrouter/qwen/qwen3-235b-a22b-thinking-2507", label: "Qwen: Qwen3 235B A22B Thinking 2507" },
160
+ { id: "openrouter/qwen/qwen3-30b-a3b-thinking-2507", label: "Qwen: Qwen3 30B A3B Thinking 2507" },
161
+ { id: "openrouter/qwen/qwen-plus-2025-07-28:thinking", label: "Qwen: Qwen Plus 0728 (thinking)" },
311
162
  { id: "openrouter/qwen/qwen3-vl-235b-a22b-thinking", label: "Qwen: Qwen3 VL 235B A22B Thinking" },
312
- { id: "openrouter/qwen/qwen3-vl-30b-a3b-instruct", label: "Qwen: Qwen3 VL 30B A3B Instruct" },
163
+ { id: "openrouter/qwen/qwen3-next-80b-a3b-thinking", label: "Qwen: Qwen3 Next 80B A3B Thinking" },
313
164
  { id: "openrouter/qwen/qwen3-vl-30b-a3b-thinking", label: "Qwen: Qwen3 VL 30B A3B Thinking" },
314
- { id: "openrouter/qwen/qwen3-vl-32b-instruct", label: "Qwen: Qwen3 VL 32B Instruct" },
315
- { id: "openrouter/qwen/qwen3-vl-8b-instruct", label: "Qwen: Qwen3 VL 8B Instruct" },
316
165
  { id: "openrouter/qwen/qwen3-vl-8b-thinking", label: "Qwen: Qwen3 VL 8B Thinking" },
317
- { id: "openrouter/qwen/qwen3.5-122b-a10b", label: "Qwen: Qwen3.5-122B-A10B" },
318
- { id: "openrouter/qwen/qwen3.5-27b", label: "Qwen: Qwen3.5-27B" },
319
- { id: "openrouter/qwen/qwen3.5-35b-a3b", label: "Qwen: Qwen3.5-35B-A3B" },
320
- { id: "openrouter/qwen/qwen3.5-397b-a17b", label: "Qwen: Qwen3.5 397B A17B" },
321
- { id: "openrouter/qwen/qwen3.5-9b", label: "Qwen: Qwen3.5-9B" },
322
- { id: "openrouter/qwen/qwen3.5-flash-02-23", label: "Qwen: Qwen3.5-Flash" },
323
- { id: "openrouter/qwen/qwen3.5-plus-02-15", label: "Qwen: Qwen3.5 Plus 2026-02-15" },
166
+ { id: "openrouter/google/gemini-3-pro-image", label: "Google: Nano Banana Pro (Gemini 3 Pro Image)" },
167
+ { id: "openrouter/moonshotai/kimi-k2-thinking", label: "MoonshotAI: Kimi K2 Thinking" },
168
+ { id: "openrouter/qwen/qwen3-coder-flash", label: "Qwen: Qwen3 Coder Flash" },
169
+ { id: "openrouter/mistralai/mistral-large-2512", label: "Mistral: Mistral Large 3 2512" },
170
+ { id: "openrouter/mistralai/mistral-large-2407", label: "Mistral Large 2407" },
171
+ { id: "openrouter/nvidia/nemotron-3-super-120b-a12b", label: "NVIDIA: Nemotron 3 Super" },
172
+ { id: "openrouter/nvidia/llama-3.3-nemotron-super-49b-v1.5", label: "NVIDIA: Llama 3.3 Nemotron Super 49B V1.5" },
173
+ { id: "openrouter/ai21/jamba-large-1.7", label: "AI21: Jamba Large 1.7" },
174
+ { id: "openrouter/arcee-ai/virtuoso-large", label: "Arcee AI: Virtuoso Large" },
175
+ { id: "openrouter/mistralai/mistral-large", label: "Mistral Large" },
176
+ { id: "openrouter/nvidia/nemotron-3-ultra-550b-a55b:free", label: "NVIDIA: Nemotron 3 Ultra (free)" },
177
+ { id: "openrouter/openai/gpt-5.1-codex-mini", label: "OpenAI: GPT-5.1-Codex-Mini" },
324
178
  { id: "openrouter/qwen/qwen3.5-plus-20260420", label: "Qwen: Qwen3.5 Plus 2026-04-20" },
325
- { id: "openrouter/qwen/qwen3.6-27b", label: "Qwen: Qwen3.6 27B" },
326
- { id: "openrouter/qwen/qwen3.6-35b-a3b", label: "Qwen: Qwen3.6 35B A3B" },
327
- { id: "openrouter/qwen/qwen3.6-flash", label: "Qwen: Qwen3.6 Flash" },
328
- { id: "openrouter/qwen/qwen3.6-max-preview", label: "Qwen: Qwen3.6 Max Preview" },
329
- { id: "openrouter/qwen/qwen3.6-plus", label: "Qwen: Qwen3.6 Plus" },
330
- { id: "openrouter/qwen/qwen3.7-max", label: "Qwen: Qwen3.7 Max" },
331
- { id: "openrouter/qwen/qwen3.7-plus", label: "Qwen: Qwen3.7 Plus" },
332
- { id: "openrouter/rekaai/reka-edge", label: "Reka Edge" },
333
- { id: "openrouter/relace/relace-search", label: "Relace: Relace Search" },
179
+ { id: "openrouter/mistralai/mistral-small-2603", label: "Mistral: Mistral Small 4" },
180
+ { id: "openrouter/mistralai/devstral-2512", label: "Mistral: Devstral 2 2512" },
181
+ { id: "openrouter/mistralai/ministral-14b-2512", label: "Mistral: Ministral 3 14B 2512" },
182
+ { id: "openrouter/mistralai/ministral-3b-2512", label: "Mistral: Ministral 3 3B 2512" },
183
+ { id: "openrouter/mistralai/ministral-8b-2512", label: "Mistral: Ministral 3 8B 2512" },
184
+ { id: "openrouter/mistralai/codestral-2508", label: "Mistral: Codestral 2508" },
185
+ { id: "openrouter/mistralai/voxtral-small-24b-2507", label: "Mistral: Voxtral Small 24B 2507" },
186
+ { id: "openrouter/qwen/qwen3-235b-a22b-2507", label: "Qwen: Qwen3 235B A22B Instruct 2507" },
187
+ { id: "openrouter/qwen/qwen3-30b-a3b-instruct-2507", label: "Qwen: Qwen3 30B A3B Instruct 2507" },
188
+ { id: "openrouter/qwen/qwen3.5-plus-02-15", label: "Qwen: Qwen3.5 Plus 2026-02-15" },
189
+ { id: "openrouter/qwen/qwen-plus-2025-07-28", label: "Qwen: Qwen Plus 0728" },
190
+ { id: "openrouter/openai/gpt-4o-2024-11-20", label: "OpenAI: GPT-4o (2024-11-20)" },
191
+ { id: "openrouter/openai/gpt-4o-2024-08-06", label: "OpenAI: GPT-4o (2024-08-06)" },
192
+ { id: "openrouter/openai/gpt-4o-2024-05-13", label: "OpenAI: GPT-4o (2024-05-13)" },
193
+ { id: "openrouter/moonshotai/kimi-k2-0905", label: "MoonshotAI: Kimi K2 0905" },
194
+ { id: "openrouter/moonshotai/kimi-k2", label: "MoonshotAI: Kimi K2 0711" },
195
+ { id: "openrouter/deepseek/deepseek-r1-0528", label: "DeepSeek: R1 0528" },
196
+ { id: "openrouter/qwen/qwen3-coder:free", label: "Qwen: Qwen3 Coder 480B A35B (free)" },
197
+ { id: "openrouter/qwen/qwen3.5-397b-a17b", label: "Qwen: Qwen3.5 397B A17B" },
198
+ { id: "openrouter/deepseek/deepseek-chat-v3-0324", label: "DeepSeek: DeepSeek V3 0324" },
199
+ { id: "openrouter/qwen/qwen3-235b-a22b", label: "Qwen: Qwen3 235B A22B" },
200
+ { id: "openrouter/qwen/qwen3-vl-235b-a22b-instruct", label: "Qwen: Qwen3 VL 235B A22B Instruct" },
201
+ { id: "openrouter/openai/gpt-oss-120b", label: "OpenAI: gpt-oss-120b" },
202
+ { id: "openrouter/qwen/qwen3-next-80b-a3b-instruct", label: "Qwen: Qwen3 Next 80B A3B Instruct" },
203
+ { id: "openrouter/qwen/qwen-2.5-72b-instruct", label: "Qwen2.5 72B Instruct" },
204
+ { id: "openrouter/meta-llama/llama-3.1-70b-instruct", label: "Meta: Llama 3.1 70B Instruct" },
205
+ { id: "openrouter/meta-llama/llama-3.3-70b-instruct", label: "Meta: Llama 3.3 70B Instruct" },
334
206
  { id: "openrouter/sao10k/l3.1-euryale-70b", label: "Sao10K: Llama 3.1 Euryale 70B v2.2" },
335
- { id: "openrouter/stepfun/step-3.5-flash", label: "StepFun: Step 3.5 Flash" },
336
- { id: "openrouter/stepfun/step-3.7-flash", label: "StepFun: Step 3.7 Flash" },
337
- { id: "openrouter/tencent/hy3-preview", label: "Tencent: Hy3 preview" },
338
- { id: "openrouter/thedrummer/rocinante-12b", label: "TheDrummer: Rocinante 12B" },
207
+ { id: "openrouter/qwen/qwen3.6-35b-a3b", label: "Qwen: Qwen3.6 35B A3B" },
208
+ { id: "openrouter/qwen/qwen3-32b", label: "Qwen: Qwen3 32B" },
209
+ { id: "openrouter/qwen/qwen3-vl-32b-instruct", label: "Qwen: Qwen3 VL 32B Instruct" },
210
+ { id: "openrouter/google/gemma-4-31b-it", label: "Google: Gemma 4 31B" },
211
+ { id: "openrouter/qwen/qwen3-30b-a3b", label: "Qwen: Qwen3 30B A3B" },
212
+ { id: "openrouter/qwen/qwen3-vl-30b-a3b-instruct", label: "Qwen: Qwen3 VL 30B A3B Instruct" },
213
+ { id: "openrouter/cohere/command-r-08-2024", label: "Cohere: Command R (08-2024)" },
214
+ { id: "openrouter/cohere/command-r-plus-08-2024", label: "Cohere: Command R+ (08-2024)" },
215
+ { id: "openrouter/google/gemma-3-27b-it", label: "Google: Gemma 3 27B" },
216
+ { id: "openrouter/qwen/qwen3.6-27b", label: "Qwen: Qwen3.6 27B" },
217
+ { id: "openrouter/google/gemma-4-26b-a4b-it", label: "Google: Gemma 4 26B A4B " },
218
+ { id: "openrouter/mistralai/mistral-small-3.2-24b-instruct", label: "Mistral: Mistral Small 3.2 24B" },
219
+ { id: "openrouter/mistralai/mixtral-8x22b-instruct", label: "Mistral: Mixtral 8x22B Instruct" },
220
+ { id: "openrouter/openai/gpt-oss-20b", label: "OpenAI: gpt-oss-20b" },
221
+ { id: "openrouter/openai/gpt-oss-safeguard-20b", label: "OpenAI: gpt-oss-safeguard-20b" },
222
+ { id: "openrouter/qwen/qwen3-14b", label: "Qwen: Qwen3 14B" },
223
+ { id: "openrouter/google/gemma-3-12b-it", label: "Google: Gemma 3 12B" },
339
224
  { id: "openrouter/thedrummer/unslopnemo-12b", label: "TheDrummer: UnslopNemo 12B" },
340
- { id: "openrouter/upstage/solar-pro-3", label: "Upstage: Solar Pro 3" },
225
+ { id: "openrouter/qwen/qwen3.5-122b-a10b", label: "Qwen: Qwen3.5-122B-A10B" },
226
+ { id: "openrouter/ibm-granite/granite-4.1-8b", label: "IBM: Granite 4.1 8B" },
227
+ { id: "openrouter/meta-llama/llama-3.1-8b-instruct", label: "Meta: Llama 3.1 8B Instruct" },
228
+ { id: "openrouter/qwen/qwen3-8b", label: "Qwen: Qwen3 8B" },
229
+ { id: "openrouter/qwen/qwen3-vl-8b-instruct", label: "Qwen: Qwen3 VL 8B Instruct" },
230
+ { id: "openrouter/qwen/qwen-2.5-7b-instruct", label: "Qwen: Qwen2.5 7B Instruct" },
231
+ { id: "openrouter/openai/gpt-5.5", label: "OpenAI: GPT-5.5" },
232
+ { id: "openrouter/openai/gpt-5.4", label: "OpenAI: GPT-5.4" },
233
+ { id: "openrouter/openai/gpt-5.3-chat", label: "OpenAI: GPT-5.3 Chat" },
234
+ { id: "openrouter/openai/gpt-5.2", label: "OpenAI: GPT-5.2" },
235
+ { id: "openrouter/openai/gpt-5.2-chat", label: "OpenAI: GPT-5.2 Chat" },
236
+ { id: "openrouter/z-ai/glm-5.2", label: "Z.ai: GLM 5.2" },
237
+ { id: "openrouter/openai/gpt-5.1", label: "OpenAI: GPT-5.1" },
238
+ { id: "openrouter/openai/gpt-5.1-chat", label: "OpenAI: GPT-5.1 Chat" },
239
+ { id: "openrouter/z-ai/glm-5.1", label: "Z.ai: GLM 5.1" },
240
+ { id: "openrouter/openai/gpt-5", label: "OpenAI: GPT-5" },
241
+ { id: "openrouter/z-ai/glm-5", label: "Z.ai: GLM 5" },
341
242
  { id: "openrouter/x-ai/grok-4.20", label: "xAI: Grok 4.20" },
342
- { id: "openrouter/x-ai/grok-4.3", label: "xAI: Grok 4.3" },
343
- { id: "openrouter/x-ai/grok-build-0.1", label: "xAI: Grok Build 0.1" },
344
- { id: "openrouter/xiaomi/mimo-v2.5", label: "Xiaomi: MiMo-V2.5" },
345
- { id: "openrouter/xiaomi/mimo-v2.5-pro", label: "Xiaomi: MiMo-V2.5-Pro" },
243
+ { id: "openrouter/z-ai/glm-4.7", label: "Z.ai: GLM 4.7" },
244
+ { id: "openrouter/z-ai/glm-4.6", label: "Z.ai: GLM 4.6" },
245
+ { id: "openrouter/z-ai/glm-4.6v", label: "Z.ai: GLM 4.6V" },
346
246
  { id: "openrouter/z-ai/glm-4.5", label: "Z.ai: GLM 4.5" },
347
247
  { id: "openrouter/z-ai/glm-4.5-air", label: "Z.ai: GLM 4.5 Air" },
348
248
  { id: "openrouter/z-ai/glm-4.5v", label: "Z.ai: GLM 4.5V" },
349
- { id: "openrouter/z-ai/glm-4.6", label: "Z.ai: GLM 4.6" },
350
- { id: "openrouter/z-ai/glm-4.6v", label: "Z.ai: GLM 4.6V" },
351
- { id: "openrouter/z-ai/glm-4.7", label: "Z.ai: GLM 4.7" },
352
- { id: "openrouter/z-ai/glm-4.7-flash", label: "Z.ai: GLM 4.7 Flash" },
353
- { id: "openrouter/z-ai/glm-5", label: "Z.ai: GLM 5" },
354
- { id: "openrouter/z-ai/glm-5-turbo", label: "Z.ai: GLM 5 Turbo" },
355
- { id: "openrouter/z-ai/glm-5.1", label: "Z.ai: GLM 5.1" },
356
- { id: "openrouter/z-ai/glm-5.2", label: "Z.ai: GLM 5.2" },
357
- { id: "openrouter/~anthropic/claude-fable-latest", label: "Anthropic: Claude Fable Latest" },
358
- { id: "openrouter/~anthropic/claude-haiku-latest", label: "Anthropic Claude Haiku Latest" },
359
- { id: "openrouter/~anthropic/claude-opus-latest", label: "Anthropic: Claude Opus Latest" },
360
- { id: "openrouter/~anthropic/claude-sonnet-latest", label: "Anthropic Claude Sonnet Latest" },
361
- { id: "openrouter/~google/gemini-flash-latest", label: "Google Gemini Flash Latest" },
362
- { id: "openrouter/~google/gemini-pro-latest", label: "Google Gemini Pro Latest" },
249
+ { id: "openrouter/x-ai/grok-4.3", label: "xAI: Grok 4.3" },
250
+ { id: "openrouter/openai/gpt-4.1", label: "OpenAI: GPT-4.1" },
251
+ { id: "openrouter/meta-llama/llama-4-maverick", label: "Meta: Llama 4 Maverick" },
252
+ { id: "openrouter/meta-llama/llama-4-scout", label: "Meta: Llama 4 Scout" },
253
+ { id: "openrouter/openai/gpt-4", label: "OpenAI: GPT-4" },
254
+ { id: "openrouter/openai/gpt-4o", label: "OpenAI: GPT-4o" },
255
+ { id: "openrouter/qwen/qwen3.7-plus", label: "Qwen: Qwen3.7 Plus" },
256
+ { id: "openrouter/qwen/qwen3.6-plus", label: "Qwen: Qwen3.6 Plus" },
257
+ { id: "openrouter/qwen/qwen3.5-35b-a3b", label: "Qwen: Qwen3.5-35B-A3B" },
258
+ { id: "openrouter/qwen/qwen3.5-27b", label: "Qwen: Qwen3.5-27B" },
259
+ { id: "openrouter/qwen/qwen3.5-9b", label: "Qwen: Qwen3.5-9B" },
260
+ { id: "openrouter/mistralai/mistral-medium-3-5", label: "Mistral: Mistral Medium 3.5" },
261
+ { id: "openrouter/deepseek/deepseek-v3.2", label: "DeepSeek: DeepSeek V3.2" },
262
+ { id: "openrouter/deepseek/deepseek-v3.2-exp", label: "DeepSeek: DeepSeek V3.2 Exp" },
263
+ { id: "openrouter/deepseek/deepseek-chat-v3.1", label: "DeepSeek: DeepSeek V3.1" },
264
+ { id: "openrouter/deepseek/deepseek-v3.1-terminus", label: "DeepSeek: DeepSeek V3.1 Terminus" },
265
+ { id: "openrouter/mistralai/mistral-medium-3.1", label: "Mistral: Mistral Medium 3.1" },
266
+ { id: "openrouter/deepseek/deepseek-chat", label: "DeepSeek: DeepSeek V3" },
267
+ { id: "openrouter/minimax/minimax-m3", label: "MiniMax: MiniMax M3" },
268
+ { id: "openrouter/mistralai/mistral-medium-3", label: "Mistral: Mistral Medium 3" },
269
+ { id: "openrouter/openai/o3", label: "OpenAI: o3" },
270
+ { id: "openrouter/openai/o3-deep-research", label: "OpenAI: o3 Deep Research" },
271
+ { id: "openrouter/tencent/hy3-preview", label: "Tencent: Hy3 preview" },
272
+ { id: "openrouter/minimax/minimax-m2.7", label: "MiniMax: MiniMax M2.7" },
273
+ { id: "openrouter/inclusionai/ling-2.6-1t", label: "inclusionAI: Ling-2.6-1T" },
274
+ { id: "openrouter/inclusionai/ring-2.6-1t", label: "inclusionAI: Ring-2.6-1T" },
275
+ { id: "openrouter/moonshotai/kimi-k2.6", label: "MoonshotAI: Kimi K2.6" },
276
+ { id: "openrouter/minimax/minimax-m2.5", label: "MiniMax: MiniMax M2.5" },
277
+ { id: "openrouter/moonshotai/kimi-k2.5", label: "MoonshotAI: Kimi K2.5" },
278
+ { id: "openrouter/xiaomi/mimo-v2.5", label: "Xiaomi: MiMo-V2.5" },
279
+ { id: "openrouter/minimax/minimax-m2.1", label: "MiniMax: MiniMax M2.1" },
280
+ { id: "openrouter/inception/mercury-2", label: "Inception: Mercury 2" },
281
+ { id: "openrouter/minimax/minimax-m2", label: "MiniMax: MiniMax M2" },
282
+ { id: "openrouter/poolside/laguna-xs.2", label: "Poolside: Laguna XS.2" },
283
+ { id: "openrouter/bytedance-seed/seed-1.6", label: "ByteDance Seed: Seed 1.6" },
284
+ { id: "openrouter/deepseek/deepseek-r1", label: "DeepSeek: R1" },
285
+ { id: "openrouter/minimax/minimax-m1", label: "MiniMax: MiniMax M1" },
286
+ { id: "openrouter/openai/o1", label: "OpenAI: o1" },
287
+ { id: "openrouter/poolside/laguna-m.1", label: "Poolside: Laguna M.1" },
288
+ { id: "openrouter/x-ai/grok-build-0.1", label: "xAI: Grok Build 0.1" },
289
+ { id: "openrouter/auto", label: "Auto" },
290
+ { id: "openrouter/openrouter/auto", label: "Auto Router" },
291
+ { id: "openrouter/mistralai/mistral-nemo", label: "Mistral: Mistral Nemo" },
292
+ { id: "openrouter/mistralai/mistral-saba", label: "Mistral: Saba" },
363
293
  { id: "openrouter/~moonshotai/kimi-latest", label: "MoonshotAI Kimi Latest" },
364
294
  { id: "openrouter/~openai/gpt-latest", label: "OpenAI GPT Latest" },
365
- { id: "openrouter/~openai/gpt-mini-latest", label: "OpenAI GPT Mini Latest" }
295
+ { id: "openrouter/openai/gpt-audio", label: "OpenAI: GPT Audio" },
296
+ { id: "openrouter/openai/gpt-chat-latest", label: "OpenAI: GPT Chat Latest" },
297
+ { id: "openrouter/openrouter/fusion", label: "OpenRouter: Fusion" },
298
+ { id: "openrouter/qwen/qwen-plus", label: "Qwen: Qwen-Plus" },
299
+ { id: "openrouter/rekaai/reka-edge", label: "Reka Edge" },
300
+ { id: "openrouter/relace/relace-search", label: "Relace: Relace Search" },
301
+ { id: "openrouter/liquid/lfm-2.5-1.2b-thinking:free", label: "LiquidAI: LFM2.5-1.2B-Thinking (free)" },
302
+ { id: "openrouter/openai/gpt-3.5-turbo-0613", label: "OpenAI: GPT-3.5 Turbo (older v0613)" },
303
+ { id: "openrouter/openai/gpt-3.5-turbo-16k", label: "OpenAI: GPT-3.5 Turbo 16k" },
304
+ { id: "openrouter/z-ai/glm-5-turbo", label: "Z.ai: GLM 5 Turbo" },
305
+ { id: "openrouter/z-ai/glm-5v-turbo", label: "Z.ai: GLM 5V Turbo" },
306
+ { id: "openrouter/z-ai/glm-4.7-flash", label: "Z.ai: GLM 4.7 Flash" },
307
+ { id: "openrouter/deepseek/deepseek-v4-flash", label: "DeepSeek: DeepSeek V4 Flash" },
308
+ { id: "openrouter/openai/gpt-4-turbo", label: "OpenAI: GPT-4 Turbo" },
309
+ { id: "openrouter/openai/gpt-4-turbo-preview", label: "OpenAI: GPT-4 Turbo Preview" },
310
+ { id: "openrouter/stepfun/step-3.7-flash", label: "StepFun: Step 3.7 Flash" },
311
+ { id: "openrouter/qwen/qwen3.6-flash", label: "Qwen: Qwen3.6 Flash" },
312
+ { id: "openrouter/google/gemini-3.5-flash", label: "Google: Gemini 3.5 Flash" },
313
+ { id: "openrouter/openai/gpt-3.5-turbo", label: "OpenAI: GPT-3.5 Turbo" },
314
+ { id: "openrouter/qwen/qwen3.5-flash-02-23", label: "Qwen: Qwen3.5-Flash" },
315
+ { id: "openrouter/stepfun/step-3.5-flash", label: "StepFun: Step 3.5 Flash" },
316
+ { id: "openrouter/google/gemini-3-flash-preview", label: "Google: Gemini 3 Flash Preview" },
317
+ { id: "openrouter/inclusionai/ling-2.6-flash", label: "inclusionAI: Ling-2.6-flash" },
318
+ { id: "openrouter/google/gemini-2.5-flash", label: "Google: Gemini 2.5 Flash" },
319
+ { id: "openrouter/bytedance-seed/seed-1.6-flash", label: "ByteDance Seed: Seed 1.6 Flash" },
320
+ { id: "openrouter/~google/gemini-flash-latest", label: "Google Gemini Flash Latest" },
321
+ { id: "openrouter/nvidia/nemotron-3-super-120b-a12b:free", label: "NVIDIA: Nemotron 3 Super (free)" },
322
+ { id: "openrouter/openai/gpt-4o-mini-2024-07-18", label: "OpenAI: GPT-4o-mini (2024-07-18)" },
323
+ { id: "openrouter/nvidia/nemotron-3-nano-30b-a3b", label: "NVIDIA: Nemotron 3 Nano 30B A3B" },
324
+ { id: "openrouter/openai/gpt-5.4-mini", label: "OpenAI: GPT-5.4 Mini" },
325
+ { id: "openrouter/openai/gpt-5.4-nano", label: "OpenAI: GPT-5.4 Nano" },
326
+ { id: "openrouter/openai/gpt-5-mini", label: "OpenAI: GPT-5 Mini" },
327
+ { id: "openrouter/openai/gpt-5-nano", label: "OpenAI: GPT-5 Nano" },
328
+ { id: "openrouter/openai/gpt-4.1-mini", label: "OpenAI: GPT-4.1 Mini" },
329
+ { id: "openrouter/openai/gpt-4.1-nano", label: "OpenAI: GPT-4.1 Nano" },
330
+ { id: "openrouter/openai/gpt-4o-mini", label: "OpenAI: GPT-4o-mini" },
331
+ { id: "openrouter/openai/o4-mini", label: "OpenAI: o4 Mini" },
332
+ { id: "openrouter/openai/o4-mini-deep-research", label: "OpenAI: o4 Mini Deep Research" },
333
+ { id: "openrouter/openai/o4-mini-high", label: "OpenAI: o4 Mini High" },
334
+ { id: "openrouter/openai/o3-mini", label: "OpenAI: o3 Mini" },
335
+ { id: "openrouter/openai/o3-mini-high", label: "OpenAI: o3 Mini High" },
336
+ { id: "openrouter/amazon/nova-2-lite-v1", label: "Amazon: Nova 2 Lite" },
337
+ { id: "openrouter/bytedance-seed/seed-2.0-lite", label: "ByteDance Seed: Seed-2.0-Lite" },
338
+ { id: "openrouter/bytedance-seed/seed-2.0-mini", label: "ByteDance Seed: Seed-2.0-Mini" },
339
+ { id: "openrouter/amazon/nova-lite-v1", label: "Amazon: Nova Lite 1.0" },
340
+ { id: "openrouter/amazon/nova-micro-v1", label: "Amazon: Nova Micro 1.0" },
341
+ { id: "openrouter/arcee-ai/trinity-mini", label: "Arcee AI: Trinity Mini" },
342
+ { id: "openrouter/cohere/north-mini-code:free", label: "Cohere: North Mini Code (free)" },
343
+ { id: "openrouter/~openai/gpt-mini-latest", label: "OpenAI GPT Mini Latest" },
344
+ { id: "openrouter/openai/gpt-audio-mini", label: "OpenAI: GPT Audio Mini" },
345
+ { id: "openrouter/openai/gpt-oss-120b:free", label: "OpenAI: gpt-oss-120b (free)" },
346
+ { id: "openrouter/qwen/qwen3-next-80b-a3b-instruct:free", label: "Qwen: Qwen3 Next 80B A3B Instruct (free)" },
347
+ { id: "openrouter/meta-llama/llama-3.3-70b-instruct:free", label: "Meta: Llama 3.3 70B Instruct (free)" },
348
+ { id: "openrouter/google/gemma-4-31b-it:free", label: "Google: Gemma 4 31B (free)" },
349
+ { id: "openrouter/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free", label: "NVIDIA: Nemotron 3 Nano Omni (free)" },
350
+ { id: "openrouter/google/gemma-4-26b-a4b-it:free", label: "Google: Gemma 4 26B A4B (free)" },
351
+ { id: "openrouter/openai/gpt-oss-20b:free", label: "OpenAI: gpt-oss-20b (free)" },
352
+ { id: "openrouter/poolside/laguna-xs.2:free", label: "Poolside: Laguna XS.2 (free)" },
353
+ { id: "openrouter/poolside/laguna-m.1:free", label: "Poolside: Laguna M.1 (free)" },
354
+ { id: "openrouter/openrouter/free", label: "Free Models Router" },
355
+ { id: "openrouter/google/gemini-2.5-flash-lite-preview-09-2025", label: "Google: Gemini 2.5 Flash Lite Preview 09-2025" },
356
+ { id: "openrouter/google/gemini-3.1-flash-lite", label: "Google: Gemini 3.1 Flash Lite" },
357
+ { id: "openrouter/google/gemini-3.1-flash-lite-preview", label: "Google: Gemini 3.1 Flash Lite Preview" },
358
+ { id: "openrouter/google/gemini-2.5-flash-lite", label: "Google: Gemini 2.5 Flash Lite" },
359
+ { id: "openrouter/nvidia/nemotron-3-nano-30b-a3b:free", label: "NVIDIA: Nemotron 3 Nano 30B A3B (free)" },
360
+ { id: "openrouter/nvidia/nemotron-nano-12b-v2-vl:free", label: "NVIDIA: Nemotron Nano 12B 2 VL (free)" },
361
+ { id: "openrouter/nvidia/nemotron-nano-9b-v2:free", label: "NVIDIA: Nemotron Nano 9B V2 (free)" }
366
362
  ],
367
363
  "openai": [
368
- { id: "openai/gpt-5.4", label: "GPT-5.4" },
369
- { id: "openai/gpt-4", label: "GPT-4" },
370
- { id: "openai/gpt-4-turbo", label: "GPT-4 Turbo" },
371
- { id: "openai/gpt-4.1", label: "GPT-4.1" },
372
- { id: "openai/gpt-4.1-mini", label: "GPT-4.1 mini" },
373
- { id: "openai/gpt-4.1-nano", label: "GPT-4.1 nano" },
374
- { id: "openai/gpt-4o", label: "GPT-4o" },
375
- { id: "openai/gpt-4o-2024-05-13", label: "GPT-4o (2024-05-13)" },
376
- { id: "openai/gpt-4o-2024-08-06", label: "GPT-4o (2024-08-06)" },
377
- { id: "openai/gpt-4o-2024-11-20", label: "GPT-4o (2024-11-20)" },
378
- { id: "openai/gpt-4o-mini", label: "GPT-4o mini" },
379
- { id: "openai/gpt-5", label: "GPT-5" },
380
- { id: "openai/gpt-5-chat-latest", label: "GPT-5 Chat Latest" },
381
- { id: "openai/gpt-5-codex", label: "GPT-5-Codex" },
382
- { id: "openai/gpt-5-mini", label: "GPT-5 Mini" },
383
- { id: "openai/gpt-5-nano", label: "GPT-5 Nano" },
384
- { id: "openai/gpt-5-pro", label: "GPT-5 Pro" },
385
- { id: "openai/gpt-5.1", label: "GPT-5.1" },
386
- { id: "openai/gpt-5.1-chat-latest", label: "GPT-5.1 Chat" },
387
- { id: "openai/gpt-5.1-codex", label: "GPT-5.1 Codex" },
388
364
  { id: "openai/gpt-5.1-codex-max", label: "GPT-5.1 Codex Max" },
389
- { id: "openai/gpt-5.1-codex-mini", label: "GPT-5.1 Codex mini" },
390
- { id: "openai/gpt-5.2", label: "GPT-5.2" },
391
- { id: "openai/gpt-5.2-chat-latest", label: "GPT-5.2 Chat" },
392
- { id: "openai/gpt-5.2-codex", label: "GPT-5.2 Codex" },
365
+ { id: "openai/gpt-5.5-pro", label: "GPT-5.5 Pro" },
366
+ { id: "openai/gpt-5.4-pro", label: "GPT-5.4 Pro" },
393
367
  { id: "openai/gpt-5.2-pro", label: "GPT-5.2 Pro" },
394
- { id: "openai/gpt-5.3-chat-latest", label: "GPT-5.3 Chat (latest)" },
368
+ { id: "openai/gpt-5-pro", label: "GPT-5 Pro" },
369
+ { id: "openai/o3-pro", label: "o3-pro" },
370
+ { id: "openai/o1-pro", label: "o1-pro" },
395
371
  { id: "openai/gpt-5.3-codex", label: "GPT-5.3 Codex" },
396
372
  { id: "openai/gpt-5.3-codex-spark", label: "GPT-5.3 Codex Spark" },
397
- { id: "openai/gpt-5.4-mini", label: "GPT-5.4 mini" },
398
- { id: "openai/gpt-5.4-nano", label: "GPT-5.4 nano" },
399
- { id: "openai/gpt-5.4-pro", label: "GPT-5.4 Pro" },
373
+ { id: "openai/gpt-5.2-codex", label: "GPT-5.2 Codex" },
374
+ { id: "openai/gpt-5.1-codex", label: "GPT-5.1 Codex" },
375
+ { id: "openai/gpt-5-codex", label: "GPT-5-Codex" },
376
+ { id: "openai/gpt-5.1-codex-mini", label: "GPT-5.1 Codex mini" },
377
+ { id: "openai/gpt-4o-2024-11-20", label: "GPT-4o (2024-11-20)" },
378
+ { id: "openai/gpt-4o-2024-08-06", label: "GPT-4o (2024-08-06)" },
379
+ { id: "openai/gpt-4o-2024-05-13", label: "GPT-4o (2024-05-13)" },
400
380
  { id: "openai/gpt-5.5", label: "GPT-5.5" },
401
- { id: "openai/gpt-5.5-pro", label: "GPT-5.5 Pro" },
402
- { id: "openai/o1", label: "o1" },
403
- { id: "openai/o1-pro", label: "o1-pro" },
381
+ { id: "openai/gpt-5.4", label: "GPT-5.4" },
382
+ { id: "openai/gpt-5.3-chat-latest", label: "GPT-5.3 Chat (latest)" },
383
+ { id: "openai/gpt-5.2", label: "GPT-5.2" },
384
+ { id: "openai/gpt-5.2-chat-latest", label: "GPT-5.2 Chat" },
385
+ { id: "openai/gpt-5.1", label: "GPT-5.1" },
386
+ { id: "openai/gpt-5.1-chat-latest", label: "GPT-5.1 Chat" },
387
+ { id: "openai/gpt-5", label: "GPT-5" },
388
+ { id: "openai/gpt-5-chat-latest", label: "GPT-5 Chat Latest" },
389
+ { id: "openai/gpt-4.1", label: "GPT-4.1" },
390
+ { id: "openai/gpt-4", label: "GPT-4" },
391
+ { id: "openai/gpt-4o", label: "GPT-4o" },
404
392
  { id: "openai/o3", label: "o3" },
405
393
  { id: "openai/o3-deep-research", label: "o3-deep-research" },
406
- { id: "openai/o3-mini", label: "o3-mini" },
407
- { id: "openai/o3-pro", label: "o3-pro" },
394
+ { id: "openai/o1", label: "o1" },
395
+ { id: "openai/gpt-4-turbo", label: "GPT-4 Turbo" },
396
+ { id: "openai/gpt-5.4-mini", label: "GPT-5.4 mini" },
397
+ { id: "openai/gpt-5.4-nano", label: "GPT-5.4 nano" },
398
+ { id: "openai/gpt-5-mini", label: "GPT-5 Mini" },
399
+ { id: "openai/gpt-5-nano", label: "GPT-5 Nano" },
400
+ { id: "openai/gpt-4.1-mini", label: "GPT-4.1 mini" },
401
+ { id: "openai/gpt-4.1-nano", label: "GPT-4.1 nano" },
402
+ { id: "openai/gpt-4o-mini", label: "GPT-4o mini" },
408
403
  { id: "openai/o4-mini", label: "o4-mini" },
409
- { id: "openai/o4-mini-deep-research", label: "o4-mini-deep-research" }
404
+ { id: "openai/o4-mini-deep-research", label: "o4-mini-deep-research" },
405
+ { id: "openai/o3-mini", label: "o3-mini" }
410
406
  ],
411
407
  "anthropic": [
412
- { id: "anthropic/claude-opus-4-8", label: "Claude Opus 4.8" },
413
- { id: "anthropic/claude-3-5-haiku-20241022", label: "Claude Haiku 3.5" },
414
- { id: "anthropic/claude-3-5-haiku-latest", label: "Claude Haiku 3.5 (latest)" },
415
- { id: "anthropic/claude-3-5-sonnet-20240620", label: "Claude Sonnet 3.5" },
416
- { id: "anthropic/claude-3-5-sonnet-20241022", label: "Claude Sonnet 3.5 v2" },
417
- { id: "anthropic/claude-3-7-sonnet-20250219", label: "Claude Sonnet 3.7" },
418
- { id: "anthropic/claude-3-haiku-20240307", label: "Claude Haiku 3" },
419
- { id: "anthropic/claude-3-opus-20240229", label: "Claude Opus 3" },
420
- { id: "anthropic/claude-3-sonnet-20240229", label: "Claude Sonnet 3" },
421
408
  { id: "anthropic/claude-fable-5", label: "Claude Fable 5" },
422
- { id: "anthropic/claude-haiku-4-5", label: "Claude Haiku 4.5 (latest)" },
423
- { id: "anthropic/claude-haiku-4-5-20251001", label: "Claude Haiku 4.5" },
424
- { id: "anthropic/claude-opus-4-0", label: "Claude Opus 4 (latest)" },
425
- { id: "anthropic/claude-opus-4-1", label: "Claude Opus 4.1 (latest)" },
426
- { id: "anthropic/claude-opus-4-1-20250805", label: "Claude Opus 4.1" },
409
+ { id: "anthropic/claude-3-opus-20240229", label: "Claude Opus 3" },
427
410
  { id: "anthropic/claude-opus-4-20250514", label: "Claude Opus 4" },
428
- { id: "anthropic/claude-opus-4-5", label: "Claude Opus 4.5 (latest)" },
429
411
  { id: "anthropic/claude-opus-4-5-20251101", label: "Claude Opus 4.5" },
430
- { id: "anthropic/claude-opus-4-6", label: "Claude Opus 4.6" },
412
+ { id: "anthropic/claude-opus-4-1-20250805", label: "Claude Opus 4.1" },
413
+ { id: "anthropic/claude-opus-4-8", label: "Claude Opus 4.8" },
431
414
  { id: "anthropic/claude-opus-4-7", label: "Claude Opus 4.7" },
432
- { id: "anthropic/claude-sonnet-4-0", label: "Claude Sonnet 4 (latest)" },
415
+ { id: "anthropic/claude-opus-4-6", label: "Claude Opus 4.6" },
416
+ { id: "anthropic/claude-opus-4-5", label: "Claude Opus 4.5 (latest)" },
417
+ { id: "anthropic/claude-opus-4-1", label: "Claude Opus 4.1 (latest)" },
418
+ { id: "anthropic/claude-opus-4-0", label: "Claude Opus 4 (latest)" },
419
+ { id: "anthropic/claude-3-7-sonnet-20250219", label: "Claude Sonnet 3.7" },
420
+ { id: "anthropic/claude-3-5-sonnet-20241022", label: "Claude Sonnet 3.5 v2" },
421
+ { id: "anthropic/claude-3-5-sonnet-20240620", label: "Claude Sonnet 3.5" },
422
+ { id: "anthropic/claude-3-sonnet-20240229", label: "Claude Sonnet 3" },
433
423
  { id: "anthropic/claude-sonnet-4-20250514", label: "Claude Sonnet 4" },
434
- { id: "anthropic/claude-sonnet-4-5", label: "Claude Sonnet 4.5 (latest)" },
435
424
  { id: "anthropic/claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5" },
436
- { id: "anthropic/claude-sonnet-4-6", label: "Claude Sonnet 4.6" }
425
+ { id: "anthropic/claude-sonnet-5", label: "Claude Sonnet 5" },
426
+ { id: "anthropic/claude-sonnet-4-6", label: "Claude Sonnet 4.6" },
427
+ { id: "anthropic/claude-sonnet-4-5", label: "Claude Sonnet 4.5 (latest)" },
428
+ { id: "anthropic/claude-sonnet-4-0", label: "Claude Sonnet 4 (latest)" },
429
+ { id: "anthropic/claude-3-haiku-20240307", label: "Claude Haiku 3" },
430
+ { id: "anthropic/claude-haiku-4-5-20251001", label: "Claude Haiku 4.5" },
431
+ { id: "anthropic/claude-haiku-4-5", label: "Claude Haiku 4.5 (latest)" }
437
432
  ],
438
433
  "google": [
439
434
  { id: "google/gemini-3.1-pro-preview", label: "Gemini 3.1 Pro Preview" },
440
- { id: "google/gemini-2.0-flash", label: "Gemini 2.0 Flash" },
441
- { id: "google/gemini-2.0-flash-lite", label: "Gemini 2.0 Flash-Lite" },
442
- { id: "google/gemini-2.5-flash", label: "Gemini 2.5 Flash" },
443
- { id: "google/gemini-2.5-flash-lite", label: "Gemini 2.5 Flash-Lite" },
444
- { id: "google/gemini-2.5-pro", label: "Gemini 2.5 Pro" },
445
- { id: "google/gemini-3-flash-preview", label: "Gemini 3 Flash Preview" },
446
- { id: "google/gemini-3-pro-preview", label: "Gemini 3 Pro Preview" },
447
- { id: "google/gemini-3.1-flash-lite", label: "Gemini 3.1 Flash Lite" },
448
- { id: "google/gemini-3.1-flash-lite-preview", label: "Gemini 3.1 Flash Lite Preview" },
449
435
  { id: "google/gemini-3.1-pro-preview-customtools", label: "Gemini 3.1 Pro Preview Custom Tools" },
436
+ { id: "google/gemini-3-pro-preview", label: "Gemini 3 Pro Preview" },
437
+ { id: "google/gemini-2.5-pro", label: "Gemini 2.5 Pro" },
438
+ { id: "google/gemma-4-31b-it", label: "Gemma 4 31B IT" },
439
+ { id: "google/gemma-4-26b-a4b-it", label: "Gemma 4 26B A4B IT" },
450
440
  { id: "google/gemini-3.5-flash", label: "Gemini 3.5 Flash" },
441
+ { id: "google/gemini-3-flash-preview", label: "Gemini 3 Flash Preview" },
442
+ { id: "google/gemini-2.5-flash", label: "Gemini 2.5 Flash" },
443
+ { id: "google/gemini-2.0-flash", label: "Gemini 2.0 Flash" },
451
444
  { id: "google/gemini-flash-latest", label: "Gemini Flash Latest" },
452
- { id: "google/gemini-flash-lite-latest", label: "Gemini Flash-Lite Latest" },
453
- { id: "google/gemma-4-26b-a4b-it", label: "Gemma 4 26B A4B IT" },
454
- { id: "google/gemma-4-31b-it", label: "Gemma 4 31B IT" },
455
- { id: "google/gemma-4-E2B-it", label: "Gemma 4 E2B IT" },
456
- { id: "google/gemma-4-E4B-it", label: "Gemma 4 E4B IT" }
445
+ { id: "google/gemini-3.1-flash-lite", label: "Gemini 3.1 Flash Lite" },
446
+ { id: "google/gemini-3.1-flash-lite-preview", label: "Gemini 3.1 Flash Lite Preview" },
447
+ { id: "google/gemini-2.5-flash-lite", label: "Gemini 2.5 Flash-Lite" },
448
+ { id: "google/gemini-2.0-flash-lite", label: "Gemini 2.0 Flash-Lite" },
449
+ { id: "google/gemini-flash-lite-latest", label: "Gemini Flash-Lite Latest" }
457
450
  ],
458
451
  "xai": [
459
- { id: "xai/grok-4.20-0309-reasoning", label: "Grok 4.20 (Reasoning)" },
460
- { id: "xai/grok-3", label: "Grok 3" },
461
- { id: "xai/grok-3-fast", label: "Grok 3 Fast" },
462
452
  { id: "xai/grok-4.20-0309-non-reasoning", label: "Grok 4.20 (Non-Reasoning)" },
453
+ { id: "xai/grok-4.20-0309-reasoning", label: "Grok 4.20 (Reasoning)" },
454
+ { id: "xai/grok-code-fast-1", label: "Grok Code Fast 1" },
463
455
  { id: "xai/grok-4.3", label: "Grok 4.3" },
456
+ { id: "xai/grok-3", label: "Grok 3" },
464
457
  { id: "xai/grok-build-0.1", label: "Grok Build 0.1" },
465
- { id: "xai/grok-code-fast-1", label: "Grok Code Fast 1" }
458
+ { id: "xai/grok-3-fast", label: "Grok 3 Fast" }
466
459
  ],
467
460
  "xiaomi": [
468
461
  { id: "xiaomi/mimo-v2.5-pro", label: "MiMo-V2.5-Pro" },
469
- { id: "xiaomi/mimo-v2-flash", label: "MiMo-V2-Flash" },
470
- { id: "xiaomi/mimo-v2-omni", label: "MiMo-V2-Omni" },
462
+ { id: "xiaomi/mimo-v2.5-pro-ultraspeed", label: "MiMo-V2.5-Pro-UltraSpeed" },
471
463
  { id: "xiaomi/mimo-v2-pro", label: "MiMo-V2-Pro" },
472
464
  { id: "xiaomi/mimo-v2.5", label: "MiMo-V2.5" },
473
- { id: "xiaomi/mimo-v2.5-pro-ultraspeed", label: "MiMo-V2.5-Pro-UltraSpeed" }
465
+ { id: "xiaomi/mimo-v2-omni", label: "MiMo-V2-Omni" },
466
+ { id: "xiaomi/mimo-v2-flash", label: "MiMo-V2-Flash" }
474
467
  ]
475
468
  };
476
469
 
@@ -823,7 +816,9 @@ function projectApmHeldFreshnessActivity(input) {
823
816
  const statusEntry = {
824
817
  kind: "status",
825
818
  activity: "working",
819
+ activityKind: "working",
826
820
  detail: title,
821
+ detailKind: "slock_action",
827
822
  producerFactId: input.producerFactId
828
823
  };
829
824
  const entry = {
@@ -2165,6 +2160,9 @@ var agentApiServerInfoResponseSchema = passthroughObject({
2165
2160
  })),
2166
2161
  agents: z2.array(passthroughObject({
2167
2162
  name: z2.string(),
2163
+ status: z2.string().optional(),
2164
+ activity: z2.string().nullable().optional(),
2165
+ activityDetail: z2.string().nullable().optional(),
2168
2166
  role: z2.enum(["owner", "admin", "member"]).nullable().optional()
2169
2167
  })),
2170
2168
  humans: z2.array(passthroughObject({
@@ -3277,6 +3275,37 @@ var BUILTIN_RUNTIME_HOST_PROVIDER_ENV_SCRUB_KEYS = Array.from(/* @__PURE__ */ ne
3277
3275
  var PI_BUILTIN_PROVIDER_MODELS = PI_BUILTIN_PROVIDER_MODELS_GENERATED;
3278
3276
  var AGENT_ACTIVITIES = ["online", "thinking", "working", "error", "offline"];
3279
3277
  var isAgentActivity = makeIsMember(AGENT_ACTIVITIES);
3278
+ var AGENT_ACTIVITY_DETAIL_KINDS = [
3279
+ "none",
3280
+ "message_received",
3281
+ "starting",
3282
+ "runtime_starting",
3283
+ "idle",
3284
+ "running_command",
3285
+ "checking_messages",
3286
+ "compacting_context",
3287
+ "compaction_finished",
3288
+ "compaction_stale",
3289
+ "reviewing_changes",
3290
+ "review_finished",
3291
+ "runtime_reconnecting",
3292
+ "runtime_error",
3293
+ "runtime_crashed",
3294
+ "runtime_unavailable",
3295
+ "runtime_stalled",
3296
+ "stalled_recovery",
3297
+ "stopped",
3298
+ "ready",
3299
+ "runtime_interrupted",
3300
+ "machine_disconnected",
3301
+ "daemon_activity",
3302
+ "external_activity",
3303
+ "synthetic_repair",
3304
+ "slock_action",
3305
+ "system_message",
3306
+ "other"
3307
+ ];
3308
+ var isAgentActivityDetailKind = makeIsMember(AGENT_ACTIVITY_DETAIL_KINDS);
3280
3309
  var VALID_ACTIVITIES = new Set(AGENT_ACTIVITIES);
3281
3310
  var EXTERNAL_AGENT_RUNTIME_ID = "external";
3282
3311
  var EXTERNAL_AGENT_RUNTIME_MODEL = "external";
@@ -3304,13 +3333,15 @@ var RUNTIME_MODELS = {
3304
3333
  builtin: Object.values(PI_BUILTIN_PROVIDER_MODELS).flat().map((model) => ({ id: model.id, label: model.label || formatRuntimeProviderModelLabel(model.id), verified: "launchable" })),
3305
3334
  claude: [
3306
3335
  { id: "opus", label: "Claude Opus" },
3336
+ { id: "fable", label: "Claude Fable" },
3337
+ { id: "sonnet", label: "Claude Sonnet" },
3338
+ { id: "haiku", label: "Claude Haiku" },
3307
3339
  { id: "claude-opus-4-8", label: "Claude Opus 4.8" },
3308
3340
  { id: "claude-opus-4-7", label: "Claude Opus 4.7" },
3309
3341
  { id: "claude-opus-4-6", label: "Claude Opus 4.6" },
3310
- { id: "fable", label: "Claude Fable" },
3311
- { id: "sonnet", label: "Claude Sonnet" },
3342
+ { id: "claude-fable-5", label: "Claude Fable 5" },
3343
+ { id: "claude-sonnet-5", label: "Claude Sonnet 5" },
3312
3344
  { id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6" },
3313
- { id: "haiku", label: "Claude Haiku" },
3314
3345
  { id: "claude-haiku-4-5", label: "Claude Haiku 4.5" }
3315
3346
  ],
3316
3347
  codex: [
@@ -3978,8 +4009,8 @@ async function executeResponseRequest(url, init, {
3978
4009
  }
3979
4010
 
3980
4011
  // src/directUploadCapability.ts
3981
- function joinUrl(base, path19) {
3982
- return `${base.replace(/\/+$/, "")}${path19}`;
4012
+ function joinUrl(base, path20) {
4013
+ return `${base.replace(/\/+$/, "")}${path20}`;
3983
4014
  }
3984
4015
  function jsonHeaders(apiKey) {
3985
4016
  return {
@@ -5062,7 +5093,7 @@ function projectApmRuntimeProgressStalledTrace(input) {
5062
5093
  }
5063
5094
  function projectApmRuntimeStallDiagnostic(input) {
5064
5095
  const context = [];
5065
- const lastActivityDetailKind = classifyApmRuntimeStallActivityDetail(input.lastActivityDetail);
5096
+ const lastActivityDetailKind = input.lastActivityDetail ? input.lastActivityDetailKind : void 0;
5066
5097
  if (input.lastActivityDetail) {
5067
5098
  context.push(`after ${input.lastActivityDetail}`);
5068
5099
  }
@@ -5094,7 +5125,7 @@ function projectApmRuntimeStallDiagnostic(input) {
5094
5125
  traceAttrs: {
5095
5126
  ageMs: input.staleForMs,
5096
5127
  staleForMinutes: input.staleForMinutes,
5097
- lastActivity: input.lastActivity,
5128
+ lastActivity: input.lastActivityKind,
5098
5129
  lastActivityDetailPresent: Boolean(input.lastActivityDetail),
5099
5130
  lastActivityDetailKind,
5100
5131
  runtime: input.runtime,
@@ -5118,20 +5149,6 @@ function projectApmRuntimeStallDiagnostic(input) {
5118
5149
  }
5119
5150
  };
5120
5151
  }
5121
- function classifyApmRuntimeStallActivityDetail(detail) {
5122
- if (!detail) return void 0;
5123
- if (detail === "Message received") return "message_received";
5124
- if (detail === "Starting\u2026") return "starting";
5125
- if (detail === "Running command\u2026") return "running_command";
5126
- if (detail === "Checking messages\u2026") return "checking_messages";
5127
- if (detail === "Compacting context") return "compacting_context";
5128
- if (detail === "Context compaction finished") return "compaction_finished";
5129
- if (detail === "Context compaction still running; no finish event observed") return "compaction_stale";
5130
- if (detail === "Idle" || detail === "Process idle") return "idle";
5131
- if (detail.startsWith("Restarting stalled ") && detail.endsWith(" runtime for queued message")) return "stalled_recovery";
5132
- if (detail.startsWith("Runtime stalled: no runtime events for ")) return "runtime_stalled";
5133
- return "other";
5134
- }
5135
5152
  function reduceApmGatedFlushReadiness(state, input) {
5136
5153
  if (!input.isGated) return { shouldNotify: false, blockedReason: "non_gated", effects: [] };
5137
5154
  if (!input.hasSession) return { shouldNotify: false, blockedReason: "missing_session", effects: [] };
@@ -6423,10 +6440,10 @@ function runtimeContextEnv(config) {
6423
6440
  return {
6424
6441
  ...ctx.agentId ? { SLOCK_CURRENT_AGENT_ID: ctx.agentId } : {},
6425
6442
  ...ctx.serverId ? { SLOCK_CURRENT_SERVER_ID: ctx.serverId } : {},
6426
- ...ctx.machineId ? { SLOCK_CURRENT_COMPUTER_ID: ctx.machineId } : {},
6427
- ...ctx.machineName ? { SLOCK_CURRENT_COMPUTER_NAME: ctx.machineName } : {},
6428
- ...ctx.machineHostname ? { SLOCK_CURRENT_COMPUTER_HOSTNAME: ctx.machineHostname } : {},
6429
- ...ctx.machineOs ? { SLOCK_CURRENT_COMPUTER_OS: ctx.machineOs } : {},
6443
+ ...ctx.machineId ? { RAFT_CURRENT_COMPUTER_ID: ctx.machineId } : {},
6444
+ ...ctx.machineName ? { RAFT_CURRENT_COMPUTER_NAME: ctx.machineName } : {},
6445
+ ...ctx.machineHostname ? { RAFT_CURRENT_COMPUTER_HOSTNAME: ctx.machineHostname } : {},
6446
+ ...ctx.machineOs ? { RAFT_CURRENT_COMPUTER_OS: ctx.machineOs } : {},
6430
6447
  ...ctx.daemonVersion ? { SLOCK_CURRENT_DAEMON_VERSION: ctx.daemonVersion } : {},
6431
6448
  ...ctx.workspacePath ? { SLOCK_CURRENT_WORKSPACE_PATH: ctx.workspacePath } : {}
6432
6449
  };
@@ -7567,7 +7584,7 @@ function codexNotificationDiagnosticEvent(message) {
7567
7584
  return null;
7568
7585
  }
7569
7586
  const sessionId = codexMessageThreadId(message);
7570
- const path19 = boundedString(params.path);
7587
+ const path20 = boundedString(params.path);
7571
7588
  return {
7572
7589
  kind: "runtime_diagnostic",
7573
7590
  severity: "warning",
@@ -7575,7 +7592,7 @@ function codexNotificationDiagnosticEvent(message) {
7575
7592
  itemType: message.method,
7576
7593
  message: diagnosticMessage,
7577
7594
  ...details ? { details } : {},
7578
- ...path19 ? { path: path19 } : {},
7595
+ ...path20 ? { path: path20 } : {},
7579
7596
  ...params.range !== void 0 ? { range: params.range } : {},
7580
7597
  payloadBytes: payloadBytes(params),
7581
7598
  ...sessionId ? { sessionId } : {}
@@ -10830,6 +10847,16 @@ function mapPiAssistantMessageEvent(assistantEvent, state) {
10830
10847
  }
10831
10848
  }
10832
10849
  }
10850
+ function mapPiMessageEndEvent(event) {
10851
+ const message = event.message;
10852
+ if (message?.role !== "assistant" || message.stopReason !== "error") {
10853
+ return [];
10854
+ }
10855
+ return [{
10856
+ kind: "error",
10857
+ message: typeof message.errorMessage === "string" && message.errorMessage.trim() ? message.errorMessage.trim() : "Pi SDK assistant turn ended with an unknown provider error"
10858
+ }];
10859
+ }
10833
10860
  function mapPiSdkEventToParsedEvents(event, state) {
10834
10861
  const events = [];
10835
10862
  pushSessionInitIfNeeded2(state, events);
@@ -10837,7 +10864,6 @@ function mapPiSdkEventToParsedEvents(event, state) {
10837
10864
  case "agent_start":
10838
10865
  case "turn_start":
10839
10866
  case "turn_end":
10840
- case "message_end":
10841
10867
  case "tool_execution_update":
10842
10868
  case "queue_update":
10843
10869
  case "session_info_changed":
@@ -10845,6 +10871,9 @@ function mapPiSdkEventToParsedEvents(event, state) {
10845
10871
  case "auto_retry_start":
10846
10872
  case "auto_retry_end":
10847
10873
  return events;
10874
+ case "message_end":
10875
+ events.push(...mapPiMessageEndEvent(event));
10876
+ return events;
10848
10877
  case "message_start":
10849
10878
  if (event.message.role === "assistant") {
10850
10879
  state.sawTextDelta = false;
@@ -12069,6 +12098,258 @@ var AgentNoProcessResidency = class {
12069
12098
  }
12070
12099
  };
12071
12100
 
12101
+ // src/agentLifecycleRecord.ts
12102
+ var AgentLifecycleRecords = class {
12103
+ idleRestartSnapshots = /* @__PURE__ */ new Map();
12104
+ terminalFailures = /* @__PURE__ */ new Map();
12105
+ activeSpawnFailBackoffs = /* @__PURE__ */ new Map();
12106
+ pendingStartRebinds = /* @__PURE__ */ new Map();
12107
+ pendingSpawnCauses = /* @__PURE__ */ new Map();
12108
+ runtimeErrorFingerprintFences = /* @__PURE__ */ new Map();
12109
+ activityClientSeqs = /* @__PURE__ */ new Map();
12110
+ nextActivityClientSeq(agentId) {
12111
+ const next = (this.activityClientSeqs.get(agentId) ?? 0) + 1;
12112
+ this.activityClientSeqs.set(agentId, next);
12113
+ return next;
12114
+ }
12115
+ deleteActivityClientSeq(agentId) {
12116
+ return this.activityClientSeqs.delete(agentId);
12117
+ }
12118
+ getRestartSnapshot(agentId) {
12119
+ return this.idleRestartSnapshots.get(agentId);
12120
+ }
12121
+ setRestartSnapshot(agentId, snapshot) {
12122
+ this.idleRestartSnapshots.set(agentId, snapshot);
12123
+ }
12124
+ deleteRestartSnapshot(agentId) {
12125
+ return this.idleRestartSnapshots.delete(agentId);
12126
+ }
12127
+ clearRestartSnapshots() {
12128
+ this.idleRestartSnapshots.clear();
12129
+ }
12130
+ restartSnapshotEntries() {
12131
+ return this.idleRestartSnapshots.entries();
12132
+ }
12133
+ restartSnapshotAgentIds() {
12134
+ return this.idleRestartSnapshots.keys();
12135
+ }
12136
+ getTerminalFailure(agentId) {
12137
+ return this.terminalFailures.get(agentId);
12138
+ }
12139
+ setTerminalFailure(agentId, failure) {
12140
+ this.terminalFailures.set(agentId, failure);
12141
+ }
12142
+ deleteTerminalFailure(agentId) {
12143
+ return this.terminalFailures.delete(agentId);
12144
+ }
12145
+ terminalFailureAgentIds() {
12146
+ return this.terminalFailures.keys();
12147
+ }
12148
+ getSpawnFailBackoff(agentId) {
12149
+ return this.activeSpawnFailBackoffs.get(agentId);
12150
+ }
12151
+ getOrCreateSpawnFailBackoff(agentId, create) {
12152
+ let state = this.activeSpawnFailBackoffs.get(agentId);
12153
+ if (!state) {
12154
+ state = create();
12155
+ this.activeSpawnFailBackoffs.set(agentId, state);
12156
+ }
12157
+ return state;
12158
+ }
12159
+ deleteSpawnFailBackoff(agentId) {
12160
+ return this.activeSpawnFailBackoffs.delete(agentId);
12161
+ }
12162
+ activeSpawnFailBackoffAgentIds(now, isActive) {
12163
+ return [...this.activeSpawnFailBackoffs.entries()].filter(([, state]) => isActive(state, now)).map(([agentId]) => agentId);
12164
+ }
12165
+ getPendingStartRebind(agentId) {
12166
+ return this.pendingStartRebinds.get(agentId);
12167
+ }
12168
+ setPendingStartRebind(agentId, start) {
12169
+ this.pendingStartRebinds.set(agentId, start);
12170
+ }
12171
+ deletePendingStartRebind(agentId) {
12172
+ return this.pendingStartRebinds.delete(agentId);
12173
+ }
12174
+ getPendingSpawnCause(agentId) {
12175
+ return this.pendingSpawnCauses.get(agentId);
12176
+ }
12177
+ setPendingSpawnCause(agentId, cause) {
12178
+ this.pendingSpawnCauses.set(agentId, cause);
12179
+ }
12180
+ deletePendingSpawnCause(agentId) {
12181
+ return this.pendingSpawnCauses.delete(agentId);
12182
+ }
12183
+ getRuntimeErrorFingerprintFence(agentId) {
12184
+ return this.runtimeErrorFingerprintFences.get(agentId);
12185
+ }
12186
+ setRuntimeErrorFingerprintFence(agentId, fence) {
12187
+ this.runtimeErrorFingerprintFences.set(agentId, fence);
12188
+ }
12189
+ deleteRuntimeErrorFingerprintFence(agentId) {
12190
+ return this.runtimeErrorFingerprintFences.delete(agentId);
12191
+ }
12192
+ runtimeErrorFingerprintFenceAgentIds() {
12193
+ return this.runtimeErrorFingerprintFences.keys();
12194
+ }
12195
+ snapshot(args) {
12196
+ return {
12197
+ runningAgentIds: args.runningAgentIds,
12198
+ queuedAgentIds: args.queuedAgentIds,
12199
+ startingAgentIds: args.startingAgentIds,
12200
+ idleRestartSnapshots: [...this.idleRestartSnapshots.entries()],
12201
+ terminalFailures: [...this.terminalFailures.entries()],
12202
+ activeSpawnFailBackoffs: [...this.activeSpawnFailBackoffs.entries()].filter(([, state]) => args.isSpawnFailBackoffActive(state, args.now)),
12203
+ pendingStartRebinds: [...this.pendingStartRebinds.entries()],
12204
+ pendingSpawnCauses: [...this.pendingSpawnCauses.entries()],
12205
+ runtimeErrorFingerprintFences: [...this.runtimeErrorFingerprintFences.entries()],
12206
+ activityClientSeqs: [...this.activityClientSeqs.entries()]
12207
+ };
12208
+ }
12209
+ assertInvariants(context, snapshot) {
12210
+ assertAgentLifecycleRecordInvariants(context, snapshot);
12211
+ }
12212
+ };
12213
+ function buildAgentLifecycleRecords(snapshot) {
12214
+ const running = new Set(snapshot.runningAgentIds);
12215
+ const queued = new Set(snapshot.queuedAgentIds);
12216
+ const starting = new Set(snapshot.startingAgentIds);
12217
+ const facts = /* @__PURE__ */ new Map();
12218
+ for (const agentId of snapshot.runningAgentIds) {
12219
+ factsFor(facts, agentId);
12220
+ }
12221
+ for (const agentId of snapshot.queuedAgentIds) {
12222
+ factsFor(facts, agentId);
12223
+ }
12224
+ for (const agentId of snapshot.startingAgentIds) {
12225
+ factsFor(facts, agentId);
12226
+ }
12227
+ for (const [agentId, restartSnapshot] of snapshot.idleRestartSnapshots) {
12228
+ factsFor(facts, agentId).restartSnapshot = restartSnapshot;
12229
+ }
12230
+ for (const [agentId, failure] of snapshot.terminalFailures) {
12231
+ factsFor(facts, agentId).terminalFailure = failure;
12232
+ }
12233
+ for (const [agentId, backoff] of snapshot.activeSpawnFailBackoffs) {
12234
+ factsFor(facts, agentId).activeSpawnFailBackoff = backoff;
12235
+ }
12236
+ for (const [agentId, pendingStartRebind] of snapshot.pendingStartRebinds) {
12237
+ factsFor(facts, agentId).pendingStartRebind = pendingStartRebind;
12238
+ }
12239
+ for (const [agentId, cause] of snapshot.pendingSpawnCauses) {
12240
+ factsFor(facts, agentId).pendingSpawnCause = cause;
12241
+ }
12242
+ for (const [agentId, fence] of snapshot.runtimeErrorFingerprintFences) {
12243
+ factsFor(facts, agentId).runtimeErrorFingerprintFence = fence;
12244
+ }
12245
+ for (const [agentId, seq] of snapshot.activityClientSeqs) {
12246
+ factsFor(facts, agentId).activityClientSeq = seq;
12247
+ }
12248
+ const records = /* @__PURE__ */ new Map();
12249
+ for (const [agentId, agentFacts] of facts) {
12250
+ if (queued.has(agentId) && starting.has(agentId)) {
12251
+ throw new Error(`queued and starting facts overlap for ${agentId}`);
12252
+ }
12253
+ if (agentFacts.terminalFailure) {
12254
+ assertTerminalRecordFacts(agentId, agentFacts, running.has(agentId));
12255
+ records.set(agentId, {
12256
+ kind: "terminal",
12257
+ agentId,
12258
+ terminalFailure: agentFacts.terminalFailure,
12259
+ fingerprintFence: agentFacts.runtimeErrorFingerprintFence,
12260
+ activityClientSeq: agentFacts.activityClientSeq
12261
+ });
12262
+ continue;
12263
+ }
12264
+ if (agentFacts.activeSpawnFailBackoff !== void 0) {
12265
+ if (running.has(agentId)) {
12266
+ throw new Error(`running process and active cooldown both present for ${agentId}`);
12267
+ }
12268
+ if (!agentFacts.restartSnapshot) {
12269
+ throw new Error(`active cooldown without restart config for ${agentId}`);
12270
+ }
12271
+ records.set(agentId, {
12272
+ kind: "cooldown",
12273
+ agentId,
12274
+ restartSnapshot: agentFacts.restartSnapshot,
12275
+ spawnFailBackoff: agentFacts.activeSpawnFailBackoff,
12276
+ fingerprintFence: agentFacts.runtimeErrorFingerprintFence,
12277
+ activityClientSeq: agentFacts.activityClientSeq
12278
+ });
12279
+ continue;
12280
+ }
12281
+ if (running.has(agentId)) {
12282
+ records.set(agentId, {
12283
+ kind: "running",
12284
+ agentId,
12285
+ restartSnapshot: agentFacts.restartSnapshot,
12286
+ pendingStartRebind: agentFacts.pendingStartRebind,
12287
+ pendingSpawnCause: agentFacts.pendingSpawnCause,
12288
+ fingerprintFence: agentFacts.runtimeErrorFingerprintFence,
12289
+ activityClientSeq: agentFacts.activityClientSeq
12290
+ });
12291
+ continue;
12292
+ }
12293
+ if (starting.has(agentId)) {
12294
+ records.set(agentId, {
12295
+ kind: "starting",
12296
+ agentId,
12297
+ restartSnapshot: agentFacts.restartSnapshot,
12298
+ pendingStartRebind: agentFacts.pendingStartRebind,
12299
+ activityClientSeq: agentFacts.activityClientSeq
12300
+ });
12301
+ continue;
12302
+ }
12303
+ if (queued.has(agentId)) {
12304
+ records.set(agentId, {
12305
+ kind: "queued",
12306
+ agentId,
12307
+ restartSnapshot: agentFacts.restartSnapshot,
12308
+ pendingStartRebind: agentFacts.pendingStartRebind,
12309
+ activityClientSeq: agentFacts.activityClientSeq
12310
+ });
12311
+ continue;
12312
+ }
12313
+ if (agentFacts.restartSnapshot) {
12314
+ records.set(agentId, {
12315
+ kind: "idle",
12316
+ agentId,
12317
+ restartSnapshot: agentFacts.restartSnapshot,
12318
+ fingerprintFence: agentFacts.runtimeErrorFingerprintFence,
12319
+ activityClientSeq: agentFacts.activityClientSeq
12320
+ });
12321
+ }
12322
+ }
12323
+ return records;
12324
+ }
12325
+ function assertAgentLifecycleRecordInvariants(context, snapshot) {
12326
+ try {
12327
+ buildAgentLifecycleRecords(snapshot);
12328
+ } catch (err) {
12329
+ const detail = err instanceof Error ? err.message : String(err);
12330
+ throw new Error(`Agent lifecycle record invariant violation after ${context}: ${detail}`);
12331
+ }
12332
+ }
12333
+ function factsFor(facts, agentId) {
12334
+ let value = facts.get(agentId);
12335
+ if (!value) {
12336
+ value = {};
12337
+ facts.set(agentId, value);
12338
+ }
12339
+ return value;
12340
+ }
12341
+ function assertTerminalRecordFacts(agentId, facts, isRunning) {
12342
+ if (isRunning) {
12343
+ throw new Error(`terminal failure while process is still registered for ${agentId}`);
12344
+ }
12345
+ if (facts.restartSnapshot) {
12346
+ throw new Error(`terminal failure and idle restart config both present for ${agentId}`);
12347
+ }
12348
+ if (facts.pendingStartRebind) {
12349
+ throw new Error(`terminal failure and pending start rebind both present for ${agentId}`);
12350
+ }
12351
+ }
12352
+
12072
12353
  // src/launchPhaseTransition.ts
12073
12354
  var LAUNCH_RUNTIME_READINESS_TRANSITION_SPAN = "launch_runtime_readiness_transition";
12074
12355
  function launchReadinessNegativeEvidence(identity) {
@@ -12342,7 +12623,7 @@ function buildRuntimeErrorDiagnosticEnvelope(message) {
12342
12623
  const httpStatus = extractHttpStatus(rawMessage);
12343
12624
  const runtimeErrorClass = classifyRuntimeError(rawMessage, httpStatus);
12344
12625
  const runtimeErrorReason = classifyRuntimeErrorReason(runtimeErrorClass);
12345
- const runtimeErrorAction = classifyRuntimeErrorAction(rawMessage, runtimeErrorClass);
12626
+ const runtimeErrorAction = classifyRuntimeErrorAction(runtimeErrorClass);
12346
12627
  const fingerprint = fingerprintRuntimeError(scrubbed);
12347
12628
  const spanAttrs = {
12348
12629
  turn_outcome: "failed",
@@ -12368,6 +12649,9 @@ function buildRuntimeErrorDiagnosticEnvelope(message) {
12368
12649
  };
12369
12650
  }
12370
12651
  function formatRuntimeLoginRequiredMessage(runtimeId) {
12652
+ if (runtimeId === "builtin") {
12653
+ return "Built-in provider authentication failed. Check this agent's provider API key and region/provider selection, then retry starting this agent.";
12654
+ }
12371
12655
  const runtimeLabel = runtimeDisplayName(runtimeId);
12372
12656
  return `${runtimeLabel} is not logged in on this machine. Please log in to ${runtimeLabel} locally, then retry starting this agent.`;
12373
12657
  }
@@ -12411,8 +12695,8 @@ function classifyRuntimeError(message, httpStatus) {
12411
12695
  if (/\bnot found\b/i.test(message)) return "NotFoundError";
12412
12696
  return "RuntimeError";
12413
12697
  }
12414
- function classifyRuntimeErrorAction(message, runtimeErrorClass) {
12415
- if (runtimeErrorClass === "AuthError" && isRuntimeAuthActionRequiredText(message)) {
12698
+ function classifyRuntimeErrorAction(runtimeErrorClass) {
12699
+ if (runtimeErrorClass === "AuthError") {
12416
12700
  return "user_reauth";
12417
12701
  }
12418
12702
  return "none";
@@ -12464,6 +12748,8 @@ function runtimeDisplayName(runtimeId) {
12464
12748
  return "OpenCode";
12465
12749
  case "pi":
12466
12750
  return "Pi";
12751
+ case "builtin":
12752
+ return "Built-in";
12467
12753
  default:
12468
12754
  return runtimeId || "This runtime";
12469
12755
  }
@@ -13578,6 +13864,49 @@ Success = user starts useful collaboration and setup progresses,
13578
13864
  not finishing a long onboarding conversation in one channel.
13579
13865
  `;
13580
13866
  }
13867
+ function createAgentProcessStartupState(context) {
13868
+ return { kind: "waiting", timer: null, ...context };
13869
+ }
13870
+ function agentProcessStartupContext(startup) {
13871
+ return {
13872
+ wakeMessage: startup.wakeMessage,
13873
+ unreadSummary: startup.unreadSummary,
13874
+ resumePrompt: startup.resumePrompt
13875
+ };
13876
+ }
13877
+ function agentProcessStartupReady(startup) {
13878
+ return { kind: "ready", ...agentProcessStartupContext(startup) };
13879
+ }
13880
+ var DecisionErrorWindow = class {
13881
+ progressEpoch = 0;
13882
+ stderrEpoch = 0;
13883
+ stderrLines = [];
13884
+ runtimeError = null;
13885
+ noteRuntimeProgress() {
13886
+ this.progressEpoch += 1;
13887
+ }
13888
+ recordStderr(text) {
13889
+ const base = this.stderrEpoch === this.progressEpoch ? this.stderrLines : [];
13890
+ this.stderrLines = pushRecentStderr(base, text);
13891
+ this.stderrEpoch = this.progressEpoch;
13892
+ }
13893
+ recordRuntimeError(message) {
13894
+ this.runtimeError = { epoch: this.progressEpoch, message };
13895
+ }
13896
+ currentStderrLines() {
13897
+ return this.stderrEpoch === this.progressEpoch ? this.stderrLines : [];
13898
+ }
13899
+ currentRuntimeError() {
13900
+ if (!this.runtimeError || this.runtimeError.epoch !== this.progressEpoch) return null;
13901
+ return this.runtimeError.message;
13902
+ }
13903
+ currentErrorCandidates() {
13904
+ return [
13905
+ this.currentRuntimeError(),
13906
+ ...this.currentStderrLines()
13907
+ ].filter((value) => !!value);
13908
+ }
13909
+ };
13581
13910
  function createRuntimeTraceCounters() {
13582
13911
  return {
13583
13912
  events: 0,
@@ -13591,6 +13920,7 @@ function createRuntimeTraceCounters() {
13591
13920
  }
13592
13921
  function createRuntimeErrorDeliveryBackoffState() {
13593
13922
  return {
13923
+ kind: "idle",
13594
13924
  attempts: 0,
13595
13925
  untilMs: 0,
13596
13926
  timer: null,
@@ -13767,10 +14097,7 @@ function runtimeRecoveryTraceAttrs(event) {
13767
14097
  };
13768
14098
  }
13769
14099
  function currentErrorCandidates(ap) {
13770
- return [
13771
- ap.runtimeErrorSinceProgress ? ap.lastRuntimeError : null,
13772
- ...ap.recentDecisionStderr
13773
- ].filter((value) => !!value);
14100
+ return ap.decisionErrorWindow.currentErrorCandidates();
13774
14101
  }
13775
14102
  function classifyTerminalFailure(ap) {
13776
14103
  const candidates = [
@@ -13860,8 +14187,10 @@ function buildRuntimeStallDiagnostic(ap, staleForMs, staleForMinutes) {
13860
14187
  return projectApmRuntimeStallDiagnostic({
13861
14188
  staleForMs,
13862
14189
  staleForMinutes,
14190
+ lastActivityKind: ap.lastActivityKind,
13863
14191
  lastActivity: ap.lastActivity,
13864
14192
  lastActivityDetail: ap.lastActivityDetail,
14193
+ lastActivityDetailKind: ap.lastActivityDetailKind,
13865
14194
  runtimeDescriptorBusyDelivery: ap.runtime.descriptor.busyDelivery,
13866
14195
  runtimeProgressLastEventKind: ap.runtimeProgress.lastEventKind,
13867
14196
  runtime: ap.config.runtime,
@@ -14047,39 +14376,16 @@ var NATIVE_STANDING_PROMPT_STARTUP_INPUT = (
14047
14376
  );
14048
14377
  var AgentProcessManager = class _AgentProcessManager {
14049
14378
  agents = /* @__PURE__ */ new Map();
14050
- /**
14051
- * Per-agent monotonic clientSeq for `agent:activity` upstream dedup.
14052
- * Server dedupes ingest by `(launchId, clientSeq)` (#engineering:72283cf7
14053
- * task #340 PR B). This counter is keyed by agentId at the MANAGER level —
14054
- * NOT on the per-process `AgentProcess` — so it SURVIVES process recreation
14055
- * (cold-start-resume / idle-auto-restart / queued-continuation /
14056
- * runtime-profile restart). Those daemon-internal restarts reuse the
14057
- * server-issued launchId but spawn a fresh process; if the counter reset to
14058
- * 0 (as the old per-`ap` field did) the reused launchId's `(launchId,
14059
- * clientSeq)` window would collide and the server would drop the
14060
- * post-restart activity as stale — the "activity log stops updating after
14061
- * error→restart" bug. Keeping it monotonic-per-agent and never resetting on
14062
- * respawn guarantees a fresh dedup key under the same launchId. launchId is
14063
- * decoupled: it stays the identity/gate token, this is the clock.
14064
- * (#proj-o11y:a1e54b59 — RS dedup-epoch ⊥ launchId-identity separation.)
14065
- */
14066
- activityClientSeqByAgent = /* @__PURE__ */ new Map();
14379
+ lifecycleRecords = new AgentLifecycleRecords();
14067
14380
  /** Next monotonic `agent:activity` clientSeq for this agent (never resets on respawn). */
14068
14381
  nextActivityClientSeq(agentId) {
14069
- const next = (this.activityClientSeqByAgent.get(agentId) ?? 0) + 1;
14070
- this.activityClientSeqByAgent.set(agentId, next);
14071
- return next;
14382
+ return this.lifecycleRecords.nextActivityClientSeq(agentId);
14072
14383
  }
14073
14384
  agentStarts;
14074
14385
  startingInboxes = new AgentStartPendingDeliveryBuffer();
14075
14386
  /** Monotonic ordering counter for launch phase-5/6 exported rows (audit only, not a pairing key). */
14076
14387
  launchTransitionSeq = 0;
14077
- terminalRuntimeFailures = /* @__PURE__ */ new Map();
14078
14388
  noProcessResidencyTransitions = new AgentNoProcessResidencyTransitions();
14079
- runtimeErrorFingerprintFences = /* @__PURE__ */ new Map();
14080
- pendingStartRebinds = /* @__PURE__ */ new Map();
14081
- /** Cached configs for agents whose process exited normally — enables auto-restart on next message */
14082
- idleAgentConfigs = /* @__PURE__ */ new Map();
14083
14389
  slockCliPath;
14084
14390
  sendToServer;
14085
14391
  daemonApiKey;
@@ -14099,12 +14405,16 @@ var AgentProcessManager = class _AgentProcessManager {
14099
14405
  deliveryTraceContexts = /* @__PURE__ */ new WeakMap();
14100
14406
  runtimeExitTraceAttrs = /* @__PURE__ */ new WeakMap();
14101
14407
  agentVisibleDelivery = new AgentVisibleDeliveryLedger();
14102
- // Spawn-fail backoff state per-agent (lifted outside AgentProcess because spawn fails
14103
- // BEFORE ap exists; rate-state must persist across stop/respawn so churn can't bypass).
14104
- // Explicit stop clears (fresh launch resets dedup clock — CC1 lifecycle pattern); silent
14105
- // stop preserves (same-launch respawn must keep counter or churn bypasses the cap).
14106
- pendingSpawnCause = /* @__PURE__ */ new Map();
14107
- agentSpawnFailBackoff = /* @__PURE__ */ new Map();
14408
+ /**
14409
+ * Per-agent lifecycle facts that outlive a single `AgentProcess`.
14410
+ *
14411
+ * The old implementation stored these as separate manager-level maps:
14412
+ * idle restart snapshots, terminal runtime failures, spawn-fail cooldown,
14413
+ * pending start rebinds, pending spawn causes, runtime-error fences, and the
14414
+ * activity client sequence. Keeping their storage under one owner makes the
14415
+ * lifecycle projection/invariants read the actual mutation boundary instead
14416
+ * of reconstructing it from unrelated fields.
14417
+ */
14108
14418
  daemonVersion;
14109
14419
  computerVersion;
14110
14420
  workerUrl;
@@ -14157,6 +14467,7 @@ var AgentProcessManager = class _AgentProcessManager {
14157
14467
  assertStartPendingDeliveryInvariants(context) {
14158
14468
  const residencySnapshot = this.noProcessResidencySnapshot();
14159
14469
  AgentNoProcessResidency.assertInvariants(context, residencySnapshot);
14470
+ this.lifecycleRecords.assertInvariants(context, this.agentLifecycleRecordSnapshot());
14160
14471
  this.startingInboxes.assertInvariants(
14161
14472
  context,
14162
14473
  AgentNoProcessResidency.allowedStartPendingSnapshot(residencySnapshot)
@@ -14169,13 +14480,30 @@ var AgentProcessManager = class _AgentProcessManager {
14169
14480
  runningAgentIds: [...this.agents.keys()],
14170
14481
  queuedAgentIds: startSnapshot.queuedAgentIds,
14171
14482
  startingAgentIds: startSnapshot.startingAgentIds,
14172
- idleAgentIds: [...this.idleAgentConfigs.keys()],
14173
- terminalFailureAgentIds: [...this.terminalRuntimeFailures.keys()],
14174
- activeCooldownAgentIds: [...this.agentSpawnFailBackoff.entries()].filter(([, state]) => state.untilMs > now).map(([agentId]) => agentId),
14175
- fingerprintFenceAgentIds: [...this.runtimeErrorFingerprintFences.keys()],
14483
+ idleAgentIds: [...this.lifecycleRecords.restartSnapshotAgentIds()],
14484
+ terminalFailureAgentIds: [...this.lifecycleRecords.terminalFailureAgentIds()],
14485
+ activeCooldownAgentIds: this.lifecycleRecords.activeSpawnFailBackoffAgentIds(
14486
+ now,
14487
+ (state, currentTime) => state.untilMs > currentTime
14488
+ ),
14489
+ fingerprintFenceAgentIds: [...this.lifecycleRecords.runtimeErrorFingerprintFenceAgentIds()],
14176
14490
  pendingDeliveryAgentIds: this.startingInboxes.agentIds()
14177
14491
  };
14178
14492
  }
14493
+ agentLifecycleRecordSnapshot() {
14494
+ const startSnapshot = this.agentStarts.snapshot();
14495
+ const now = this.clockNow();
14496
+ return this.lifecycleRecords.snapshot({
14497
+ runningAgentIds: [...this.agents.keys()],
14498
+ queuedAgentIds: startSnapshot.queuedAgentIds,
14499
+ startingAgentIds: startSnapshot.startingAgentIds,
14500
+ now,
14501
+ isSpawnFailBackoffActive: (state, currentTime) => state.untilMs > currentTime
14502
+ });
14503
+ }
14504
+ agentLifecycleRecord(agentId) {
14505
+ return buildAgentLifecycleRecords(this.agentLifecycleRecordSnapshot()).get(agentId);
14506
+ }
14179
14507
  getVisibleBoundary(agentId, target) {
14180
14508
  return this.agentVisibleDelivery.getBoundary(agentId, target);
14181
14509
  }
@@ -14196,15 +14524,10 @@ var AgentProcessManager = class _AgentProcessManager {
14196
14524
  // bypasses the cap — CC1 lifecycle pattern). Never advances any consume cursor or model-seen
14197
14525
  // state (3-cursor orthogonality with CC1/CC2).
14198
14526
  getOrCreateSpawnFailBackoff(agentId) {
14199
- let state = this.agentSpawnFailBackoff.get(agentId);
14200
- if (!state) {
14201
- state = createRuntimeErrorDeliveryBackoffState();
14202
- this.agentSpawnFailBackoff.set(agentId, state);
14203
- }
14204
- return state;
14527
+ return this.lifecycleRecords.getOrCreateSpawnFailBackoff(agentId, createRuntimeErrorDeliveryBackoffState);
14205
14528
  }
14206
14529
  isSpawnFailBackoffActive(agentId) {
14207
- const state = this.agentSpawnFailBackoff.get(agentId);
14530
+ const state = this.lifecycleRecords.getSpawnFailBackoff(agentId);
14208
14531
  if (!state) return false;
14209
14532
  return state.untilMs > 0 && this.clockNow() < state.untilMs;
14210
14533
  }
@@ -14228,7 +14551,7 @@ var AgentProcessManager = class _AgentProcessManager {
14228
14551
  state.untilMs = this.clockNow() + Math.floor(baseDelay);
14229
14552
  if (state.timer) clearTimeout(state.timer);
14230
14553
  state.timer = setTimeout(() => {
14231
- const s = this.agentSpawnFailBackoff.get(agentId);
14554
+ const s = this.lifecycleRecords.getSpawnFailBackoff(agentId);
14232
14555
  if (s) {
14233
14556
  s.timer = null;
14234
14557
  s.untilMs = 0;
@@ -14238,10 +14561,10 @@ var AgentProcessManager = class _AgentProcessManager {
14238
14561
  return { backoffActive: true, attempts: state.attempts, untilMs: state.untilMs };
14239
14562
  }
14240
14563
  resetSpawnFailBackoff(agentId, closeResult = "advanced") {
14241
- const state = this.agentSpawnFailBackoff.get(agentId);
14564
+ const state = this.lifecycleRecords.getSpawnFailBackoff(agentId);
14242
14565
  if (!state) return;
14243
14566
  if (state.timer) clearTimeout(state.timer);
14244
- this.agentSpawnFailBackoff.delete(agentId);
14567
+ this.lifecycleRecords.deleteSpawnFailBackoff(agentId);
14245
14568
  this.closeNoProcessResidency(agentId, closeResult, { negativeEvidenceBucket: "spawn_fail_cooldown_reset" });
14246
14569
  }
14247
14570
  // ----- RUNTIME-ERROR FINGERPRINT FENCE (per-agent) ---------------------
@@ -14266,9 +14589,9 @@ var AgentProcessManager = class _AgentProcessManager {
14266
14589
  }
14267
14590
  }
14268
14591
  resetRuntimeErrorFingerprintFence(agentId, resetSource, ap) {
14269
- const state = this.runtimeErrorFingerprintFences.get(agentId);
14592
+ const state = this.lifecycleRecords.getRuntimeErrorFingerprintFence(agentId);
14270
14593
  if (!state) return;
14271
- this.runtimeErrorFingerprintFences.delete(agentId);
14594
+ this.lifecycleRecords.deleteRuntimeErrorFingerprintFence(agentId);
14272
14595
  this.recordDaemonTrace("daemon.agent.runtime_error_fingerprint_fence.reset", {
14273
14596
  agentId,
14274
14597
  runtime: ap?.config.runtime,
@@ -14289,7 +14612,7 @@ var AgentProcessManager = class _AgentProcessManager {
14289
14612
  noteRuntimeErrorFingerprintFence(agentId, ap, message, fingerprint, terminalFailure, stickyTerminalFailure) {
14290
14613
  if (!fingerprint) return null;
14291
14614
  if (stickyTerminalFailure || terminalFailure?.actionRequired) return null;
14292
- let state = this.runtimeErrorFingerprintFences.get(agentId);
14615
+ let state = this.lifecycleRecords.getRuntimeErrorFingerprintFence(agentId);
14293
14616
  if (!state || state.fingerprint !== fingerprint) {
14294
14617
  state = {
14295
14618
  fingerprint,
@@ -14298,7 +14621,7 @@ var AgentProcessManager = class _AgentProcessManager {
14298
14621
  detail: "",
14299
14622
  launchId: ap.launchId
14300
14623
  };
14301
- this.runtimeErrorFingerprintFences.set(agentId, state);
14624
+ this.lifecycleRecords.setRuntimeErrorFingerprintFence(agentId, state);
14302
14625
  }
14303
14626
  state.attempts += 1;
14304
14627
  state.lastRuntimeError = message;
@@ -14328,7 +14651,7 @@ var AgentProcessManager = class _AgentProcessManager {
14328
14651
  attempts: state.attempts,
14329
14652
  threshold: RUNTIME_ERROR_FINGERPRINT_FENCE_THRESHOLD
14330
14653
  }, "error");
14331
- this.idleAgentConfigs.delete(agentId);
14654
+ this.lifecycleRecords.deleteRestartSnapshot(agentId);
14332
14655
  this.sendAgentStatus(agentId, "inactive", ap.launchId);
14333
14656
  this.cleanupTerminalRuntimeFailure(agentId, ap, state.detail);
14334
14657
  }
@@ -14380,7 +14703,7 @@ var AgentProcessManager = class _AgentProcessManager {
14380
14703
  }
14381
14704
  this.commitApmIdleState(agentId, ap, false);
14382
14705
  this.startRuntimeTrace(agentId, ap, "async-rejected-idle-delivery-retry", messages);
14383
- this.broadcastActivity(agentId, "working", "Message received");
14706
+ this.broadcastMessageReceivedActivity(agentId);
14384
14707
  const accepted = this.deliverInboxUpdateViaStdin(
14385
14708
  agentId,
14386
14709
  ap,
@@ -14426,11 +14749,46 @@ var AgentProcessManager = class _AgentProcessManager {
14426
14749
  return this.sendStdinNotification(agentId, { forceUnsupportedRetry: true });
14427
14750
  }
14428
14751
  clearRuntimeErrorDeliveryBackoff(ap) {
14429
- if (ap.runtimeErrorDeliveryBackoff.timer) {
14752
+ if (ap.runtimeErrorDeliveryBackoff.kind === "backing_off" && ap.runtimeErrorDeliveryBackoff.timer) {
14430
14753
  clearTimeout(ap.runtimeErrorDeliveryBackoff.timer);
14431
14754
  }
14432
14755
  ap.runtimeErrorDeliveryBackoff = createRuntimeErrorDeliveryBackoffState();
14433
14756
  }
14757
+ clearPendingTrajectoryTimer(ap) {
14758
+ if (ap.pendingTrajectory?.timer) {
14759
+ clearTimeout(ap.pendingTrajectory.timer);
14760
+ }
14761
+ ap.pendingTrajectory = null;
14762
+ }
14763
+ clearActivityHeartbeat(ap) {
14764
+ if (ap.activityHeartbeat.kind === "inactive") return;
14765
+ clearInterval(ap.activityHeartbeat.timer);
14766
+ ap.activityHeartbeat = { kind: "inactive" };
14767
+ }
14768
+ broadcastMessageReceivedActivity(agentId) {
14769
+ this.broadcastActivity(agentId, "working", "Message received", [], void 0, "message_received");
14770
+ }
14771
+ toolActivityDetailKind(toolName) {
14772
+ switch (toolName) {
14773
+ case "bash":
14774
+ return "running_command";
14775
+ case "check_messages":
14776
+ case "receive_message":
14777
+ return "checking_messages";
14778
+ default:
14779
+ return "other";
14780
+ }
14781
+ }
14782
+ disposeAgentProcessTimers(ap, options = {}) {
14783
+ this.clearRuntimeErrorDeliveryBackoff(ap);
14784
+ this.clearPendingTrajectoryTimer(ap);
14785
+ this.clearActivityHeartbeat(ap);
14786
+ this.clearRuntimeStartupTimeout(ap);
14787
+ if (options.includeCompactionWatchdog ?? true) {
14788
+ this.clearCompactionWatchdog(ap);
14789
+ }
14790
+ this.clearStalledRecoverySigtermWatchdog(ap);
14791
+ }
14434
14792
  clearRuntimeErrorDeliveryBackoffWithTrace(agentId, ap, resetSource) {
14435
14793
  if (ap.runtimeErrorDeliveryBackoff.attempts === 0 && ap.runtimeErrorDeliveryBackoff.untilMs === 0) return;
14436
14794
  const attempts = ap.runtimeErrorDeliveryBackoff.attempts;
@@ -14450,16 +14808,22 @@ var AgentProcessManager = class _AgentProcessManager {
14450
14808
  this.clearRuntimeErrorDeliveryBackoffWithTrace(agentId, ap, eventKind);
14451
14809
  }
14452
14810
  runtimeErrorDeliveryBackoffRemainingMs(ap) {
14811
+ if (ap.runtimeErrorDeliveryBackoff.kind === "idle") return 0;
14453
14812
  return Math.max(0, ap.runtimeErrorDeliveryBackoff.untilMs - Date.now());
14454
14813
  }
14814
+ runtimeErrorDeliveryBackoffTimerScheduled(ap) {
14815
+ return ap.runtimeErrorDeliveryBackoff.kind === "backing_off" && ap.runtimeErrorDeliveryBackoff.timer !== null;
14816
+ }
14455
14817
  scheduleRuntimeErrorDeliveryBackoffFlush(agentId, ap) {
14818
+ const state = ap.runtimeErrorDeliveryBackoff;
14819
+ if (state.kind === "idle") return false;
14456
14820
  const delayMs = this.runtimeErrorDeliveryBackoffRemainingMs(ap);
14457
- if (delayMs <= 0 || ap.runtimeErrorDeliveryBackoff.timer) return false;
14458
- ap.runtimeErrorDeliveryBackoff.timer = setTimeout(() => {
14459
- ap.runtimeErrorDeliveryBackoff.timer = null;
14821
+ if (delayMs <= 0 || state.timer) return false;
14822
+ state.timer = setTimeout(() => {
14823
+ if (ap.runtimeErrorDeliveryBackoff === state) state.timer = null;
14460
14824
  this.flushRuntimeErrorDeliveryBackoff(agentId);
14461
14825
  }, delayMs);
14462
- ap.runtimeErrorDeliveryBackoff.timer.unref?.();
14826
+ state.timer.unref?.();
14463
14827
  return true;
14464
14828
  }
14465
14829
  recoverableRuntimeDeliveryBackoffReason(message, terminalFailure, stickyTerminalFailure, reasonOverride) {
@@ -14490,13 +14854,16 @@ var AgentProcessManager = class _AgentProcessManager {
14490
14854
  const cappedDelayMs = Math.min(this.runtimeErrorDeliveryBackoffMaxMs, exponentialDelayMs);
14491
14855
  const jitterMs = Math.floor(cappedDelayMs * this.runtimeErrorDeliveryBackoffJitterRatio * Math.random());
14492
14856
  const delayMs = Math.min(this.runtimeErrorDeliveryBackoffMaxMs, cappedDelayMs + jitterMs);
14493
- if (ap.runtimeErrorDeliveryBackoff.timer) {
14857
+ if (ap.runtimeErrorDeliveryBackoff.kind === "backing_off" && ap.runtimeErrorDeliveryBackoff.timer) {
14494
14858
  clearTimeout(ap.runtimeErrorDeliveryBackoff.timer);
14495
- ap.runtimeErrorDeliveryBackoff.timer = null;
14496
14859
  }
14497
- ap.runtimeErrorDeliveryBackoff.attempts = attempts;
14498
- ap.runtimeErrorDeliveryBackoff.reason = reason;
14499
- ap.runtimeErrorDeliveryBackoff.untilMs = Date.now() + delayMs;
14860
+ ap.runtimeErrorDeliveryBackoff = {
14861
+ kind: "backing_off",
14862
+ attempts,
14863
+ reason,
14864
+ untilMs: Date.now() + delayMs,
14865
+ timer: null
14866
+ };
14500
14867
  if (ap.inbox.length > 0) {
14501
14868
  this.scheduleRuntimeErrorDeliveryBackoffFlush(agentId, ap);
14502
14869
  }
@@ -14536,7 +14903,7 @@ var AgentProcessManager = class _AgentProcessManager {
14536
14903
  runtime_error_backoff_remaining_ms: remainingMs,
14537
14904
  runtime_error_backoff_attempts: ap.runtimeErrorDeliveryBackoff.attempts,
14538
14905
  runtime_error_backoff_reason: ap.runtimeErrorDeliveryBackoff.reason || void 0,
14539
- runtime_error_backoff_timer_scheduled: scheduled || ap.runtimeErrorDeliveryBackoff.timer !== null
14906
+ runtime_error_backoff_timer_scheduled: scheduled || this.runtimeErrorDeliveryBackoffTimerScheduled(ap)
14540
14907
  }));
14541
14908
  return true;
14542
14909
  }
@@ -14571,7 +14938,7 @@ var AgentProcessManager = class _AgentProcessManager {
14571
14938
  }
14572
14939
  this.commitApmIdleState(agentId, ap, false);
14573
14940
  this.startRuntimeTrace(agentId, ap, "runtime-error-backoff-idle-delivery", messages);
14574
- this.broadcastActivity(agentId, "working", "Message received");
14941
+ this.broadcastMessageReceivedActivity(agentId);
14575
14942
  const accepted2 = this.deliverInboxUpdateViaStdin(
14576
14943
  agentId,
14577
14944
  ap,
@@ -14786,7 +15153,9 @@ var AgentProcessManager = class _AgentProcessManager {
14786
15153
  type: "agent:activity",
14787
15154
  agentId,
14788
15155
  activity: activity.statusEntry.activity,
15156
+ activityKind: activity.statusEntry.activityKind ?? activity.statusEntry.activity,
14789
15157
  detail: activity.statusEntry.detail,
15158
+ detailKind: activity.statusEntry.detailKind ?? "daemon_activity",
14790
15159
  entries: activity.entries,
14791
15160
  launchId: ap?.launchId || void 0,
14792
15161
  clientSeq: ap ? this.nextActivityClientSeq(agentId) : void 0
@@ -14796,8 +15165,10 @@ var AgentProcessManager = class _AgentProcessManager {
14796
15165
  this.sendToServer({
14797
15166
  type: "agent:activity",
14798
15167
  agentId,
14799
- activity: ap.lastActivity || "online",
15168
+ activity: ap.lastActivity || ap.lastActivityKind || "online",
15169
+ activityKind: ap.lastActivityKind || "online",
14800
15170
  detail: ap.lastActivityDetail || "",
15171
+ detailKind: ap.lastActivityDetailKind || "none",
14801
15172
  entries: [runtimeDiagnosticTrajectoryEntry(event)],
14802
15173
  launchId: ap.launchId || void 0,
14803
15174
  clientSeq: this.nextActivityClientSeq(agentId)
@@ -14813,8 +15184,10 @@ var AgentProcessManager = class _AgentProcessManager {
14813
15184
  this.sendToServer({
14814
15185
  type: "agent:activity",
14815
15186
  agentId,
14816
- activity: ap.lastActivity || "online",
15187
+ activity: ap.lastActivity || ap.lastActivityKind || "online",
15188
+ activityKind: ap.lastActivityKind || "online",
14817
15189
  detail: ap.lastActivityDetail || "",
15190
+ detailKind: ap.lastActivityDetailKind || "none",
14818
15191
  entries: [runtimeRecoveryTrajectoryEntry(event)],
14819
15192
  launchId: ap.launchId || void 0,
14820
15193
  clientSeq: this.nextActivityClientSeq(agentId)
@@ -14905,7 +15278,7 @@ var AgentProcessManager = class _AgentProcessManager {
14905
15278
  pid: typeof ap.runtime.pid === "number" ? ap.runtime.pid : void 0
14906
15279
  };
14907
15280
  }
14908
- startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient = false) {
15281
+ startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient = false, resumeMessages) {
14909
15282
  const startSnapshot = this.agentStarts.snapshot();
14910
15283
  return {
14911
15284
  agentId,
@@ -14916,6 +15289,7 @@ var AgentProcessManager = class _AgentProcessManager {
14916
15289
  launch_id_present: Boolean(launchId),
14917
15290
  wake_message_present: Boolean(wakeMessage),
14918
15291
  wake_message_transient: Boolean(wakeMessage && wakeMessageTransient),
15292
+ resume_messages_count: resumeMessages?.length ?? 0,
14919
15293
  unread_channels_count: unreadSummary ? Object.keys(unreadSummary).length : 0,
14920
15294
  resume_prompt_present: Boolean(resumePrompt),
14921
15295
  queue_depth: startSnapshot.queueDepth,
@@ -15042,7 +15416,7 @@ var AgentProcessManager = class _AgentProcessManager {
15042
15416
  rebindRunningStart(agentId, start, reason) {
15043
15417
  const ap = this.agents.get(agentId);
15044
15418
  if (!ap) {
15045
- this.pendingStartRebinds.set(agentId, start);
15419
+ this.lifecycleRecords.setPendingStartRebind(agentId, start);
15046
15420
  return false;
15047
15421
  }
15048
15422
  const previousLaunchId = ap.launchId;
@@ -15058,7 +15432,7 @@ var AgentProcessManager = class _AgentProcessManager {
15058
15432
  ...start.config,
15059
15433
  sessionId: nextConfigSessionId
15060
15434
  };
15061
- this.idleAgentConfigs.set(agentId, {
15435
+ this.lifecycleRecords.setRestartSnapshot(agentId, {
15062
15436
  config: this.buildRestartSafeConfig(ap.config, nextConfigSessionId),
15063
15437
  sessionId: nextConfigSessionId,
15064
15438
  launchId: nextLaunchId
@@ -15076,32 +15450,32 @@ var AgentProcessManager = class _AgentProcessManager {
15076
15450
  }
15077
15451
  return true;
15078
15452
  }
15079
- async startAgent(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient = false) {
15080
- this.recordDaemonTrace("daemon.agent.start.requested", this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient));
15453
+ async startAgent(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient = false, resumeMessages) {
15454
+ this.recordDaemonTrace("daemon.agent.start.requested", this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages));
15081
15455
  if (this.agents.has(agentId)) {
15082
15456
  this.recordDaemonTrace("daemon.agent.start.ignored", {
15083
- ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient),
15457
+ ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages),
15084
15458
  reason: "already_running"
15085
15459
  });
15086
- this.rebindRunningStart(agentId, { config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient }, "already_running");
15460
+ this.rebindRunningStart(agentId, { config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages }, "already_running");
15087
15461
  logger.info(`[Agent ${agentId}] Start rebound (already running)`);
15088
15462
  return;
15089
15463
  }
15090
15464
  if (this.agentStarts.hasStarting(agentId)) {
15091
15465
  this.recordDaemonTrace("daemon.agent.start.ignored", {
15092
- ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient),
15466
+ ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages),
15093
15467
  reason: "already_starting"
15094
15468
  });
15095
- this.pendingStartRebinds.set(agentId, { config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient });
15469
+ this.lifecycleRecords.setPendingStartRebind(agentId, { config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages });
15096
15470
  logger.info(`[Agent ${agentId}] Start rebind deferred (startup in progress)`);
15097
15471
  return;
15098
15472
  }
15099
15473
  if (this.agentStarts.hasQueued(agentId)) {
15100
15474
  this.recordDaemonTrace("daemon.agent.start.ignored", {
15101
- ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient),
15475
+ ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages),
15102
15476
  reason: "already_queued"
15103
15477
  });
15104
- this.rebindQueuedStart(agentId, { config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient }, "already_queued");
15478
+ this.rebindQueuedStart(agentId, { config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages }, "already_queued");
15105
15479
  logger.info(`[Agent ${agentId}] Queued start rebound (startup already queued)`);
15106
15480
  return;
15107
15481
  }
@@ -15111,6 +15485,7 @@ var AgentProcessManager = class _AgentProcessManager {
15111
15485
  config,
15112
15486
  wakeMessage,
15113
15487
  wakeMessageTransient,
15488
+ resumeMessages,
15114
15489
  unreadSummary,
15115
15490
  resumePrompt,
15116
15491
  launchId,
@@ -15118,7 +15493,7 @@ var AgentProcessManager = class _AgentProcessManager {
15118
15493
  reject
15119
15494
  };
15120
15495
  this.agentStarts.enqueue(item);
15121
- this.recordDaemonTrace("daemon.agent.start.queued", this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient));
15496
+ this.recordDaemonTrace("daemon.agent.start.queued", this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages));
15122
15497
  const startSnapshot = this.agentStarts.snapshot();
15123
15498
  this.enterNoProcessResidency(
15124
15499
  "queued_start",
@@ -15141,7 +15516,7 @@ var AgentProcessManager = class _AgentProcessManager {
15141
15516
  if (pumpState.kind === "rate_limited") {
15142
15517
  const { item: next, waitMs } = pumpState;
15143
15518
  this.recordDaemonTrace("daemon.agent.start.rate_limited", {
15144
- ...this.startQueueTraceAttrs(next.agentId, next.config, next.wakeMessage, next.unreadSummary, next.resumePrompt, next.launchId, next.wakeMessageTransient),
15519
+ ...this.startQueueTraceAttrs(next.agentId, next.config, next.wakeMessage, next.unreadSummary, next.resumePrompt, next.launchId, next.wakeMessageTransient, next.resumeMessages),
15145
15520
  wait_ms: waitMs
15146
15521
  });
15147
15522
  this.agentStarts.schedulePump(waitMs, () => this.pumpAgentStartQueue());
@@ -15153,7 +15528,7 @@ var AgentProcessManager = class _AgentProcessManager {
15153
15528
  const { item: item2 } = dequeued;
15154
15529
  this.closeNoProcessResidency(item2.agentId, "suppressed", { negativeEvidenceBucket: "stale_queue_item" });
15155
15530
  this.recordDaemonTrace("daemon.agent.start.skipped", {
15156
- ...this.startQueueTraceAttrs(item2.agentId, item2.config, item2.wakeMessage, item2.unreadSummary, item2.resumePrompt, item2.launchId, item2.wakeMessageTransient),
15531
+ ...this.startQueueTraceAttrs(item2.agentId, item2.config, item2.wakeMessage, item2.unreadSummary, item2.resumePrompt, item2.launchId, item2.wakeMessageTransient, item2.resumeMessages),
15157
15532
  reason: "stale_queue_item"
15158
15533
  });
15159
15534
  this.pumpAgentStartQueue();
@@ -15163,13 +15538,13 @@ var AgentProcessManager = class _AgentProcessManager {
15163
15538
  if (this.agents.has(item.agentId) || this.agentStarts.hasStarting(item.agentId)) {
15164
15539
  this.closeNoProcessResidency(item.agentId, "suppressed", { negativeEvidenceBucket: "already_running_or_starting" });
15165
15540
  this.recordDaemonTrace("daemon.agent.start.skipped", {
15166
- ...this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient),
15541
+ ...this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient, item.resumeMessages),
15167
15542
  reason: "already_running_or_starting"
15168
15543
  });
15169
15544
  if (this.agents.has(item.agentId)) {
15170
15545
  this.rebindRunningStart(item.agentId, item, "already_running_or_starting");
15171
15546
  } else {
15172
- this.pendingStartRebinds.set(item.agentId, item);
15547
+ this.lifecycleRecords.setPendingStartRebind(item.agentId, item);
15173
15548
  }
15174
15549
  logger.info(`[Agent ${item.agentId}] Queued start skipped (already running or starting)`);
15175
15550
  item.resolve();
@@ -15190,7 +15565,7 @@ var AgentProcessManager = class _AgentProcessManager {
15190
15565
  logger.info(
15191
15566
  `[Agent ${item.agentId}] Dequeued start (remaining=${startSnapshot.queueDepth}, active=${startSnapshot.activeStarts})`
15192
15567
  );
15193
- this.recordDaemonTrace("daemon.agent.start.dequeued", this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient));
15568
+ this.recordDaemonTrace("daemon.agent.start.dequeued", this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient, item.resumeMessages));
15194
15569
  this.startAgentNow(
15195
15570
  item.agentId,
15196
15571
  item.config,
@@ -15198,7 +15573,8 @@ var AgentProcessManager = class _AgentProcessManager {
15198
15573
  item.unreadSummary,
15199
15574
  item.resumePrompt,
15200
15575
  item.launchId,
15201
- item.wakeMessageTransient ?? false
15576
+ item.wakeMessageTransient ?? false,
15577
+ item.resumeMessages
15202
15578
  ).then(() => {
15203
15579
  this.releaseAgentStartSlot(item.agentId, "spawn attempted");
15204
15580
  item.resolve();
@@ -15229,7 +15605,7 @@ var AgentProcessManager = class _AgentProcessManager {
15229
15605
  this.startingInboxes.cancelStart(agentId);
15230
15606
  this.assertStartPendingDeliveryInvariants("cancel-queued-start");
15231
15607
  this.recordDaemonTrace("daemon.agent.start.cancelled", {
15232
- ...this.startQueueTraceAttrs(agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient),
15608
+ ...this.startQueueTraceAttrs(agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient, item.resumeMessages),
15233
15609
  reason
15234
15610
  }, "cancelled");
15235
15611
  logger.info(`[Agent ${agentId}] Queued start cancelled (${reason})`);
@@ -15240,7 +15616,7 @@ var AgentProcessManager = class _AgentProcessManager {
15240
15616
  const cancelled = this.agentStarts.cancelAllQueued((item) => {
15241
15617
  this.closeNoProcessResidency(item.agentId, "suppressed", { negativeEvidenceBucket: "start_cancelled" });
15242
15618
  this.recordDaemonTrace("daemon.agent.start.cancelled", {
15243
- ...this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient),
15619
+ ...this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient, item.resumeMessages),
15244
15620
  reason
15245
15621
  }, "cancelled");
15246
15622
  logger.info(`[Agent ${item.agentId}] Queued start cancelled (${reason})`);
@@ -15251,22 +15627,22 @@ var AgentProcessManager = class _AgentProcessManager {
15251
15627
  this.startingInboxes.cancelAllStarts();
15252
15628
  this.assertStartPendingDeliveryInvariants("cancel-all-queued-starts");
15253
15629
  }
15254
- async startAgentNow(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient = false) {
15630
+ async startAgentNow(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient = false, resumeMessages) {
15255
15631
  if (this.agents.has(agentId)) {
15256
15632
  this.recordDaemonTrace("daemon.agent.spawn.skipped", {
15257
- ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient),
15633
+ ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages),
15258
15634
  reason: "already_running"
15259
15635
  });
15260
- this.rebindRunningStart(agentId, { config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient }, "already_running");
15636
+ this.rebindRunningStart(agentId, { config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages }, "already_running");
15261
15637
  logger.info(`[Agent ${agentId}] Start rebound (already running)`);
15262
15638
  return;
15263
15639
  }
15264
15640
  if (this.agentStarts.hasStarting(agentId)) {
15265
15641
  this.recordDaemonTrace("daemon.agent.spawn.skipped", {
15266
- ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient),
15642
+ ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages),
15267
15643
  reason: "already_starting"
15268
15644
  });
15269
- this.pendingStartRebinds.set(agentId, { config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient });
15645
+ this.lifecycleRecords.setPendingStartRebind(agentId, { config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages });
15270
15646
  logger.info(`[Agent ${agentId}] Start rebind deferred (startup in progress)`);
15271
15647
  return;
15272
15648
  }
@@ -15299,9 +15675,9 @@ var AgentProcessManager = class _AgentProcessManager {
15299
15675
  }
15300
15676
  }
15301
15677
  }
15302
- pendingStartRebind = this.pendingStartRebinds.get(agentId);
15678
+ pendingStartRebind = this.lifecycleRecords.getPendingStartRebind(agentId);
15303
15679
  if (pendingStartRebind) {
15304
- this.pendingStartRebinds.delete(agentId);
15680
+ this.lifecycleRecords.deletePendingStartRebind(agentId);
15305
15681
  const previousWakeMessage = wakeMessage;
15306
15682
  this.startingInboxes.rebindWake(
15307
15683
  agentId,
@@ -15314,6 +15690,7 @@ var AgentProcessManager = class _AgentProcessManager {
15314
15690
  unreadSummary = pendingStartRebind.unreadSummary;
15315
15691
  resumePrompt = pendingStartRebind.resumePrompt;
15316
15692
  launchId = pendingStartRebind.launchId || launchId;
15693
+ resumeMessages = pendingStartRebind.resumeMessages;
15317
15694
  if (pendingStartRebind.wakeMessage) {
15318
15695
  wakeMessage = pendingStartRebind.wakeMessage;
15319
15696
  wakeMessageTransient = pendingStartRebind.wakeMessageTransient === true;
@@ -15328,7 +15705,7 @@ var AgentProcessManager = class _AgentProcessManager {
15328
15705
  deadlineUnixMs: this.clockNow() + runtimeStartTimeoutMs()
15329
15706
  }
15330
15707
  );
15331
- this.recordDaemonTrace("daemon.agent.spawn.started", this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient));
15708
+ this.recordDaemonTrace("daemon.agent.spawn.started", this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient, resumeMessages));
15332
15709
  const driver = this.driverResolver(config.runtime || "claude");
15333
15710
  const legacyWakeRuntimeProfile = wakeMessage ? runtimeProfileNotificationFromMessage(wakeMessage) : null;
15334
15711
  if (legacyWakeRuntimeProfile?.kind === "migration") {
@@ -15359,7 +15736,10 @@ var AgentProcessManager = class _AgentProcessManager {
15359
15736
  let promptSource;
15360
15737
  let wakeMessageDeliveredAsInboxUpdate = false;
15361
15738
  let startingInboxDeliveredAsInput = false;
15739
+ let resumeCatchupDeliveredAsInput = false;
15362
15740
  const startingInboxMessages = this.startingInboxes.values(agentId);
15741
+ const resumeCatchupMessages = isResume && !wakeMessage && !resumePrompt ? resumeMessages ?? [] : [];
15742
+ const resumeCatchupInputMessages = resumeCatchupMessages.length > 0 ? [...resumeCatchupMessages, ...startingInboxMessages] : [];
15363
15743
  if (runtimeConfig.runtimeProfileControl && !wakeMessage) {
15364
15744
  prompt = driver.supportsNativeStandingPrompt ? NATIVE_STANDING_PROMPT_STARTUP_INPUT : formatRuntimeProfileControlStartupInput(runtimeConfig.runtimeProfileControl, driver);
15365
15745
  promptSource = "runtime_profile_control";
@@ -15399,6 +15779,22 @@ You also have unread messages in other channels:`;
15399
15779
  Use the inbox/read commands at a natural breakpoint if you choose to inspect those targets.`;
15400
15780
  }
15401
15781
  }
15782
+ } else if (resumeCatchupInputMessages.length > 0) {
15783
+ resumeCatchupDeliveredAsInput = true;
15784
+ prompt = this.formatConcreteMessagesRuntimeInput(resumeCatchupInputMessages, driver);
15785
+ promptSource = "resume_catchup_inbox";
15786
+ if (unreadSummary && Object.keys(unreadSummary).length > 0) {
15787
+ prompt += `
15788
+
15789
+ Some unread channels may not be included in this bounded startup batch:`;
15790
+ for (const [ch, count] of Object.entries(unreadSummary)) {
15791
+ prompt += `
15792
+ - ${ch}: ${count} unread`;
15793
+ }
15794
+ prompt += `
15795
+
15796
+ Use the inbox/read commands at a natural breakpoint if you choose to inspect those targets.`;
15797
+ }
15402
15798
  } else if (startingInboxMessages.length > 0) {
15403
15799
  startingInboxDeliveredAsInput = true;
15404
15800
  prompt = this.formatInboxUpdateRuntimeInput(startingInboxMessages, driver);
@@ -15426,27 +15822,27 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15426
15822
  prompt,
15427
15823
  standingPrompt,
15428
15824
  resumePrompt,
15429
- messages: wakeMessage ? [wakeMessage] : void 0,
15825
+ messages: wakeMessage ? [wakeMessage] : resumeCatchupInputMessages.length > 0 ? resumeCatchupInputMessages : void 0,
15430
15826
  unreadSummary,
15431
15827
  sessionIdPresent: isResume,
15432
15828
  nativeStandingPrompt: Boolean(driver.supportsNativeStandingPrompt)
15433
15829
  });
15434
15830
  const effectiveLaunchId = launchId || null;
15435
- const canDeferEmptyStart = driver.deferSpawnUntilMessage === true && !wakeMessage && !runtimeConfig.runtimeProfileControl && (!unreadSummary || Object.keys(unreadSummary).length === 0);
15831
+ const canDeferEmptyStart = driver.deferSpawnUntilMessage === true && !wakeMessage && !runtimeConfig.runtimeProfileControl && resumeCatchupInputMessages.length === 0 && (!unreadSummary || Object.keys(unreadSummary).length === 0);
15436
15832
  if (canDeferEmptyStart) {
15437
15833
  const pendingMessages = this.startingInboxes.drainOnSpawn(agentId);
15438
15834
  this.agentStarts.clearStarting(agentId);
15439
15835
  this.closeNoProcessResidency(agentId, "suppressed", { negativeEvidenceBucket: "defer_until_concrete_message" });
15440
15836
  this.assertStartPendingDeliveryInvariants("defer-empty-start-drain");
15441
- this.idleAgentConfigs.set(agentId, {
15837
+ this.lifecycleRecords.setRestartSnapshot(agentId, {
15442
15838
  config: this.buildRestartSafeConfig(runtimeConfig, runtimeConfig.sessionId || null),
15443
15839
  sessionId: runtimeConfig.sessionId || null,
15444
15840
  launchId: effectiveLaunchId
15445
15841
  });
15446
15842
  this.sendAgentStatus(agentId, "active", effectiveLaunchId);
15447
- this.broadcastActivity(agentId, "online", "Process idle");
15843
+ this.broadcastActivity(agentId, "online", "Process idle", [], void 0, "idle");
15448
15844
  this.recordDaemonTrace("daemon.agent.spawn.deferred", {
15449
- ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, effectiveLaunchId || void 0, wakeMessageTransient),
15845
+ ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, effectiveLaunchId || void 0, wakeMessageTransient, resumeMessages),
15450
15846
  pending_messages_count: pendingMessages.length,
15451
15847
  reason: "defer_until_concrete_message"
15452
15848
  });
@@ -15481,51 +15877,49 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15481
15877
  const initialSessionId = this.initialAgentProcessSessionId(driver, liveProcessConfig);
15482
15878
  const restartSessionId = initialSessionId || (driver.requiresSessionInitForDelivery ? liveProcessConfig.sessionId || null : null);
15483
15879
  const processInstanceId = randomUUID6();
15880
+ const startupInputMessages = wakeMessageDeliveredAsInboxUpdate && wakeMessage ? [wakeMessage, ...startingInboxMessages] : resumeCatchupDeliveredAsInput ? resumeCatchupInputMessages : startingInboxMessages;
15484
15881
  agentProcess = {
15485
15882
  runtime,
15486
15883
  driver,
15487
- inbox: wakeMessageDeliveredAsInboxUpdate && wakeMessage ? [wakeMessage, ...startingInboxMessages] : startingInboxMessages,
15884
+ inbox: startupInputMessages,
15488
15885
  config: liveProcessConfig,
15489
15886
  sessionId: initialSessionId,
15490
15887
  sessionReadyForDelivery: this.initialSessionReadyForDelivery(driver, liveProcessConfig, initialSessionId),
15491
15888
  launchId: effectiveLaunchId,
15492
- startupWakeMessage: wakeMessage,
15493
- startupUnreadSummary: unreadSummary,
15494
- startupResumePrompt: resumePrompt,
15889
+ startup: createAgentProcessStartupState({
15890
+ wakeMessage,
15891
+ unreadSummary,
15892
+ resumePrompt
15893
+ }),
15495
15894
  notifications: new RuntimeNotificationState(),
15496
- activityHeartbeat: null,
15497
- startupTimeoutTimer: null,
15498
- startupReadinessSatisfied: false,
15895
+ activityHeartbeat: { kind: "inactive" },
15499
15896
  readinessTransition: null,
15500
- activationTransition: null,
15501
- initialActivationDelivered: false,
15502
- compactionWatchdog: null,
15503
- compactionStartedAt: null,
15897
+ activation: { kind: "idle" },
15898
+ compaction: { kind: "none" },
15504
15899
  runtimeProgress: new RuntimeProgressState(Date.now()),
15505
15900
  runtimeTraceSpan: null,
15506
15901
  runtimeTraceCounters: createRuntimeTraceCounters(),
15507
15902
  runtimeTelemetryResultSeq: 0,
15903
+ lastActivityKind: "offline",
15508
15904
  lastActivity: "",
15509
15905
  lastActivityDetail: "",
15906
+ lastActivityDetailKind: "none",
15510
15907
  recentStdout: [],
15511
15908
  recentStderr: [],
15512
15909
  lastRuntimeError: null,
15513
- recentDecisionStderr: [],
15514
- runtimeErrorSinceProgress: false,
15910
+ decisionErrorWindow: new DecisionErrorWindow(),
15515
15911
  runtimeErrorDeliveryBackoff: createRuntimeErrorDeliveryBackoffState(),
15516
15912
  spawnError: null,
15517
15913
  processInstanceId,
15518
15914
  spawnedAtMs: Date.now(),
15519
- exitCode: null,
15520
- exitSignal: null,
15521
- stalledRecoverySigtermTimer: null,
15915
+ exit: { kind: "live", stalledRecoverySigtermTimer: null },
15522
15916
  runtimeProfileTurnControl: liveProcessConfig.runtimeProfileControl ? runtimeProfileTurnControl(liveProcessConfig.runtimeProfileControl.kind, liveProcessConfig.runtimeProfileControl.key, "agent_config") : null,
15523
15917
  pendingTrajectory: null,
15524
15918
  gatedSteering: createGatedSteeringState()
15525
15919
  };
15526
15920
  this.startingInboxes.drainOnSpawn(agentId);
15527
15921
  this.agents.set(agentId, agentProcess);
15528
- this.idleAgentConfigs.set(agentId, {
15922
+ this.lifecycleRecords.setRestartSnapshot(agentId, {
15529
15923
  config: this.buildRestartSafeConfig(runtimeConfig, restartSessionId),
15530
15924
  sessionId: restartSessionId,
15531
15925
  launchId: effectiveLaunchId
@@ -15533,13 +15927,17 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15533
15927
  if (pendingStartRebind) {
15534
15928
  this.recordStartRebind(agentId, pendingStartRebind, "startup_registered", originalLaunchId, effectiveLaunchId, agentProcess.sessionId);
15535
15929
  }
15536
- this.startRuntimeTrace(agentId, agentProcess, "spawn", wakeMessage ? [wakeMessage] : void 0, runtimeInputTraceAttrs);
15930
+ this.startRuntimeTrace(agentId, agentProcess, "spawn", wakeMessage ? [wakeMessage] : resumeCatchupInputMessages.length > 0 ? resumeCatchupInputMessages : void 0, runtimeInputTraceAttrs);
15537
15931
  this.agentStarts.clearStarting(agentId);
15538
15932
  if (runtimeConfig.runtimeProfileControl) {
15539
15933
  this.ackInjectedRuntimeProfileControl(agentId, runtimeConfig.runtimeProfileControl, agentProcess.launchId);
15540
15934
  }
15541
15935
  if (wakeMessageDeliveredAsInboxUpdate) {
15542
15936
  this.recordInboxUpdateProjection(agentId, agentProcess, agentProcess.inbox, "spawn_wake_inbox_update", "wake", prompt);
15937
+ } else if (resumeCatchupDeliveredAsInput) {
15938
+ this.recordInboxUpdateProjection(agentId, agentProcess, resumeCatchupInputMessages, "spawn_resume_catchup_inbox", "wake", prompt);
15939
+ this.consumeVisibleMessages(agentId, { messages: resumeCatchupInputMessages, source: "spawn_resume_catchup_inbox" });
15940
+ this.ackInjectedRuntimeProfileMessages(agentId, resumeCatchupInputMessages, agentProcess.launchId);
15543
15941
  } else if (startingInboxDeliveredAsInput) {
15544
15942
  this.recordInboxUpdateProjection(agentId, agentProcess, startingInboxMessages, "spawn_starting_inbox_update", "wake", prompt);
15545
15943
  this.consumeVisibleMessages(agentId, { messages: startingInboxMessages, source: "spawn_starting_inbox_update" });
@@ -15564,7 +15962,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15564
15962
  if (driver.id === "codex" && isCodexProviderReconnectLog(text)) {
15565
15963
  if (current) {
15566
15964
  current.recentStderr = pushRecentStderr(current.recentStderr, text);
15567
- current.recentDecisionStderr = pushRecentStderr(current.recentDecisionStderr, text);
15965
+ current.decisionErrorWindow.recordStderr(text);
15568
15966
  }
15569
15967
  this.recordDaemonTrace("daemon.agent.provider_reconnect", {
15570
15968
  agentId,
@@ -15574,14 +15972,14 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15574
15972
  });
15575
15973
  this.broadcastActivity(agentId, "working", "Codex reconnecting to provider\u2026", [
15576
15974
  { kind: "text", text }
15577
- ]);
15975
+ ], void 0, "runtime_reconnecting");
15578
15976
  logger.info(`[Agent ${agentId} stderr]: ${text}`);
15579
15977
  return;
15580
15978
  }
15581
15979
  if (driver.id === "codex" && isCodexBenignTransportLog(text)) return;
15582
15980
  if (current) {
15583
15981
  current.recentStderr = pushRecentStderr(current.recentStderr, text);
15584
- current.recentDecisionStderr = pushRecentStderr(current.recentDecisionStderr, text);
15982
+ current.decisionErrorWindow.recordStderr(text);
15585
15983
  }
15586
15984
  logger.error(`[Agent ${agentId} stderr]: ${text}`);
15587
15985
  });
@@ -15603,8 +16001,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15603
16001
  runtime.on("exit", ({ code, signal }) => {
15604
16002
  const current = this.agents.get(agentId);
15605
16003
  if (current && current.runtime === runtime) {
15606
- current.exitCode = code;
15607
- current.exitSignal = signal;
16004
+ this.clearStalledRecoverySigtermWatchdog(current);
16005
+ current.exit = { kind: "exited", code, signal };
15608
16006
  }
15609
16007
  const exitTraceAttrs = this.runtimeExitTraceAttrs.get(runtime);
15610
16008
  this.recordDaemonTrace("daemon.agent.process.exited", {
@@ -15629,7 +16027,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15629
16027
  exit_code: code,
15630
16028
  exit_signal: signal,
15631
16029
  cause: exitCause,
15632
- last_event_kind: agentProcess.lastActivity || void 0,
16030
+ last_event_kind: agentProcess.lastActivityKind || void 0,
15633
16031
  last_event_age_ms_bucket: bucketMs(staleForMs),
15634
16032
  uptime_ms_bucket: bucketMs(Date.now() - agentProcess.spawnedAtMs)
15635
16033
  }, code === 0 ? "ok" : "error");
@@ -15641,19 +16039,11 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15641
16039
  const ap = this.agents.get(agentId);
15642
16040
  if (ap.runtime !== runtime) return;
15643
16041
  ap.notifications.clearTimer();
15644
- this.clearRuntimeErrorDeliveryBackoff(ap);
15645
- if (ap.pendingTrajectory?.timer) {
15646
- clearTimeout(ap.pendingTrajectory.timer);
15647
- }
15648
- if (ap.activityHeartbeat) {
15649
- clearInterval(ap.activityHeartbeat);
15650
- }
16042
+ this.disposeAgentProcessTimers(ap, { includeCompactionWatchdog: false });
15651
16043
  this.closeRuntimeReadinessTransition(ap, "terminal");
15652
16044
  this.closeActivationTransition(ap, "terminal");
15653
- this.clearRuntimeStartupTimeout(ap);
15654
- this.clearStalledRecoverySigtermWatchdog(ap);
15655
- const finalCode = ap.exitCode ?? code;
15656
- const finalSignal = ap.exitSignal ?? signal;
16045
+ const finalCode = ap.exit.kind === "exited" ? ap.exit.code ?? code : code;
16046
+ const finalSignal = ap.exit.kind === "exited" ? ap.exit.signal ?? signal : signal;
15657
16047
  const expectedTerminationReason = ap.gatedSteering.expectedTerminationReason;
15658
16048
  const startupTimeoutTermination = expectedTerminationReason === "startup_timeout";
15659
16049
  const startupRequestErrorTermination = expectedTerminationReason === "startup_request_error";
@@ -15697,21 +16087,23 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15697
16087
  [{
15698
16088
  kind: "text",
15699
16089
  text: `Stored ${runtimeLabel} session ${staleSessionId} ${reasonText}. Falling back to a cold start; earlier runtime context may not be restored.`
15700
- }]
16090
+ }],
16091
+ void 0,
16092
+ "runtime_unavailable"
15701
16093
  );
15702
- this.pendingSpawnCause.set(agentId, "restart_crash");
16094
+ this.lifecycleRecords.setPendingSpawnCause(agentId, "restart_crash");
15703
16095
  this.startAgent(
15704
16096
  agentId,
15705
16097
  restartConfig,
15706
- ap.startupWakeMessage,
15707
- ap.startupUnreadSummary,
15708
- ap.startupResumePrompt,
16098
+ ap.startup.wakeMessage,
16099
+ ap.startup.unreadSummary,
16100
+ ap.startup.resumePrompt,
15709
16101
  ap.launchId || void 0
15710
16102
  ).catch((err) => {
15711
16103
  logger.error(`[Agent ${agentId}] Cold start recovery failed`, err);
15712
- this.pendingSpawnCause.delete(agentId);
16104
+ this.lifecycleRecords.deletePendingSpawnCause(agentId);
15713
16105
  this.sendAgentStatus(agentId, "inactive", ap.launchId);
15714
- this.broadcastActivity(agentId, "offline", `Crashed (${summary})`, [], ap.launchId);
16106
+ this.broadcastActivity(agentId, "offline", `Crashed (${summary})`, [], ap.launchId, "runtime_crashed");
15715
16107
  });
15716
16108
  return;
15717
16109
  }
@@ -15729,20 +16121,20 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15729
16121
  if (queuedWakeMessage) {
15730
16122
  logger.info(`[Agent ${agentId}] Turn completed; restarting immediately for queued message`);
15731
16123
  const nextConfig = this.buildRestartSafeConfig(ap.config, ap.sessionId);
15732
- this.idleAgentConfigs.set(agentId, {
16124
+ this.lifecycleRecords.setRestartSnapshot(agentId, {
15733
16125
  config: nextConfig,
15734
16126
  sessionId: ap.sessionId,
15735
16127
  launchId: ap.launchId
15736
16128
  });
15737
- this.broadcastActivity(agentId, "working", "Message received");
15738
- this.idleAgentConfigs.delete(agentId);
16129
+ this.broadcastMessageReceivedActivity(agentId);
16130
+ this.lifecycleRecords.deleteRestartSnapshot(agentId);
15739
16131
  if (expectedTerminationReason === "stalled_recovery") {
15740
- this.pendingSpawnCause.set(agentId, "restart_stall");
16132
+ this.lifecycleRecords.setPendingSpawnCause(agentId, "restart_stall");
15741
16133
  }
15742
16134
  this.startAgent(agentId, nextConfig, queuedWakeMessage, unreadSummary2, void 0, ap.launchId || void 0).catch((err) => {
15743
16135
  logger.error(`[Agent ${agentId}] Failed to continue with queued message`, err);
15744
16136
  if (this.reportRunnerCredentialMintFailure(agentId, err, ap.launchId, "queued_continuation")) {
15745
- this.idleAgentConfigs.set(agentId, {
16137
+ this.lifecycleRecords.setRestartSnapshot(agentId, {
15746
16138
  config: nextConfig,
15747
16139
  sessionId: ap.sessionId,
15748
16140
  launchId: ap.launchId
@@ -15762,16 +16154,16 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15762
16154
  });
15763
16155
  return;
15764
16156
  }
15765
- this.idleAgentConfigs.set(agentId, {
16157
+ this.lifecycleRecords.setRestartSnapshot(agentId, {
15766
16158
  config: nextConfig,
15767
16159
  sessionId: ap.sessionId,
15768
16160
  launchId: ap.launchId
15769
16161
  });
15770
- this.broadcastActivity(agentId, "online", "Process idle");
16162
+ this.broadcastActivity(agentId, "online", "Process idle", [], void 0, "idle");
15771
16163
  });
15772
16164
  return;
15773
16165
  }
15774
- this.idleAgentConfigs.set(agentId, {
16166
+ this.lifecycleRecords.setRestartSnapshot(agentId, {
15775
16167
  config: this.buildRestartSafeConfig(ap.config, ap.sessionId),
15776
16168
  sessionId: ap.sessionId,
15777
16169
  launchId: ap.launchId
@@ -15779,11 +16171,11 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15779
16171
  if (!ap.driver.supportsStdinNotification) {
15780
16172
  logger.info(`[Agent ${agentId}] Turn completed; cached idle state for future restart`);
15781
16173
  }
15782
- this.broadcastActivity(agentId, "online", "Process idle");
16174
+ this.broadcastActivity(agentId, "online", "Process idle", [], void 0, "idle");
15783
16175
  } else {
15784
16176
  const reason = formatCrashReason(finalCode, finalSignal, ap);
15785
16177
  if (terminalFailureDetail && isProviderStreamFailureText(terminalFailureDetail.detail)) {
15786
- this.idleAgentConfigs.set(agentId, {
16178
+ this.lifecycleRecords.setRestartSnapshot(agentId, {
15787
16179
  config: this.buildRestartSafeConfig(ap.config, ap.sessionId),
15788
16180
  sessionId: ap.sessionId,
15789
16181
  launchId: ap.launchId
@@ -15794,10 +16186,10 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15794
16186
  this.cacheStartupTimeoutRetryConfig(agentId, ap);
15795
16187
  logger.warn(`[Agent ${agentId}] Startup timeout cleanup completed (${reason})`);
15796
16188
  } else if (startupRequestErrorTermination) {
15797
- this.idleAgentConfigs.delete(agentId);
16189
+ this.lifecycleRecords.deleteRestartSnapshot(agentId);
15798
16190
  logger.warn(`[Agent ${agentId}] Startup request failure cleanup completed (${reason})`);
15799
16191
  } else {
15800
- this.idleAgentConfigs.delete(agentId);
16192
+ this.lifecycleRecords.deleteRestartSnapshot(agentId);
15801
16193
  logger.error(`[Agent ${agentId}] Process crashed (${reason}) \u2014 marking inactive`);
15802
16194
  this.sendAgentStatus(agentId, "inactive", ap.launchId);
15803
16195
  }
@@ -15808,11 +16200,12 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15808
16200
  "error",
15809
16201
  terminalFailureDetail.detail,
15810
16202
  [{ kind: "text", text: `Error: ${terminalFailureDetail.detail}` }],
15811
- ap.launchId
16203
+ ap.launchId,
16204
+ "runtime_error"
15812
16205
  );
15813
16206
  }
15814
16207
  } else if (!startupRequestErrorTermination) {
15815
- this.broadcastActivity(agentId, "offline", `Crashed (${summary})`, [], ap.launchId);
16208
+ this.broadcastActivity(agentId, "offline", `Crashed (${summary})`, [], ap.launchId, "runtime_crashed");
15816
16209
  }
15817
16210
  }
15818
16211
  }
@@ -15832,10 +16225,20 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15832
16225
  error_present: Boolean(startResult.error),
15833
16226
  runtime_error_class: diagnostics?.spanAttrs.runtime_error_class
15834
16227
  }, "error");
16228
+ if (startResult.error) {
16229
+ agentProcess.lastRuntimeError = startResult.error;
16230
+ agentProcess.decisionErrorWindow.recordRuntimeError(startResult.error);
16231
+ }
16232
+ if (startResult.error && diagnostics?.spanAttrs.runtime_error_action_required === true) {
16233
+ const visibleErrorMessage = formatRuntimeLoginRequiredMessage(agentProcess.driver.id);
16234
+ this.broadcastActivity(agentId, "error", visibleErrorMessage, [
16235
+ { kind: "text", text: `Error: ${visibleErrorMessage}` }
16236
+ ], agentProcess.launchId, "runtime_error");
16237
+ }
15835
16238
  throw new Error(`Runtime session failed to start: ${startResult.reason}${startResult.error ? ` (${startResult.error})` : ""}`);
15836
16239
  }
15837
16240
  this.closeNoProcessResidency(agentId, "advanced");
15838
- if (this.terminalRuntimeFailures.delete(agentId)) {
16241
+ if (this.lifecycleRecords.deleteTerminalFailure(agentId)) {
15839
16242
  this.closeNoProcessResidency(agentId, "advanced", { negativeEvidenceBucket: "terminal_recovery_start_succeeded" });
15840
16243
  }
15841
16244
  this.assertStartPendingDeliveryInvariants("spawn-drain");
@@ -15845,8 +16248,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15845
16248
  new_session: false,
15846
16249
  process_pid_present: typeof runtime.pid === "number"
15847
16250
  });
15848
- const pendingCause = this.pendingSpawnCause.get(agentId);
15849
- this.pendingSpawnCause.delete(agentId);
16251
+ const pendingCause = this.lifecycleRecords.getPendingSpawnCause(agentId);
16252
+ this.lifecycleRecords.deletePendingSpawnCause(agentId);
15850
16253
  const startCause = pendingCause ?? (isResume ? "session_resume" : wakeMessage ? "wake_message" : "explicit_start");
15851
16254
  this.recordDaemonTrace("daemon.runtime.process.spawn", {
15852
16255
  ...this.processLifecycleIdentityAttrs(agentId, agentProcess),
@@ -15859,7 +16262,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15859
16262
  if (pendingStartRebind && agentProcess.sessionId) {
15860
16263
  this.sendToServer({ type: "agent:session", agentId, sessionId: agentProcess.sessionId, launchId: agentProcess.launchId || void 0 });
15861
16264
  }
15862
- this.broadcastActivity(agentId, "working", "Starting\u2026");
16265
+ this.broadcastActivity(agentId, "working", "Starting\u2026", [], void 0, "starting");
15863
16266
  this.startRuntimeStartupTimeout(agentId, agentProcess, startCause);
15864
16267
  if (wakeMessage || startingInboxMessages.length > 0) {
15865
16268
  this.openActivationTransition(agentId, agentProcess, startCause);
@@ -15870,7 +16273,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15870
16273
  } catch (err) {
15871
16274
  this.agentStarts.clearStarting(agentId);
15872
16275
  this.closeNoProcessResidency(agentId, "terminal", { negativeEvidenceBucket: "runtime_start_failed" });
15873
- this.pendingStartRebinds.delete(agentId);
16276
+ this.lifecycleRecords.deletePendingStartRebind(agentId);
15874
16277
  this.cleanupFailedRuntimeStart(agentId, agentProcess, err);
15875
16278
  throw err;
15876
16279
  }
@@ -15879,22 +16282,9 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15879
16282
  if (!ap) return;
15880
16283
  if (this.agents.get(agentId) !== ap) return;
15881
16284
  ap.notifications.clearTimer();
15882
- if (ap.pendingTrajectory?.timer) {
15883
- clearTimeout(ap.pendingTrajectory.timer);
15884
- ap.pendingTrajectory.timer = null;
15885
- }
15886
- if (ap.activityHeartbeat) {
15887
- clearInterval(ap.activityHeartbeat);
15888
- ap.activityHeartbeat = null;
15889
- }
15890
- if (ap.compactionWatchdog) {
15891
- clearTimeout(ap.compactionWatchdog);
15892
- ap.compactionWatchdog = null;
15893
- }
16285
+ this.disposeAgentProcessTimers(ap);
15894
16286
  this.closeRuntimeReadinessTransition(ap, "terminal");
15895
16287
  this.closeActivationTransition(ap, "terminal");
15896
- this.clearRuntimeStartupTimeout(ap);
15897
- this.clearStalledRecoverySigtermWatchdog(ap);
15898
16288
  this.endRuntimeTrace(ap, "error", {
15899
16289
  outcome: "runtime-start-failed",
15900
16290
  failure_detail: err instanceof Error ? err.message : String(err),
@@ -15904,36 +16294,25 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15904
16294
  cleanupAgentCredentialProxy(agentId, ap.launchId);
15905
16295
  this.revokeManagedRunnerCredential(agentId, ap.config, ap.launchId);
15906
16296
  this.agents.delete(agentId);
15907
- this.idleAgentConfigs.delete(agentId);
15908
- if (this.terminalRuntimeFailures.delete(agentId)) {
16297
+ this.lifecycleRecords.deleteRestartSnapshot(agentId);
16298
+ if (this.lifecycleRecords.deleteTerminalFailure(agentId)) {
15909
16299
  this.closeNoProcessResidency(agentId, "terminal", { negativeEvidenceBucket: "runtime_start_failed" });
15910
16300
  }
15911
16301
  }
15912
16302
  cleanupTerminalRuntimeFailure(agentId, ap, detail) {
15913
16303
  if (this.agents.get(agentId) !== ap) return;
15914
16304
  ap.notifications.clear();
15915
- this.clearRuntimeErrorDeliveryBackoff(ap);
15916
- if (ap.pendingTrajectory?.timer) {
15917
- clearTimeout(ap.pendingTrajectory.timer);
15918
- ap.pendingTrajectory.timer = null;
15919
- }
15920
- if (ap.activityHeartbeat) {
15921
- clearInterval(ap.activityHeartbeat);
15922
- ap.activityHeartbeat = null;
15923
- }
15924
- this.clearCompactionWatchdog(ap);
16305
+ this.disposeAgentProcessTimers(ap);
15925
16306
  this.closeRuntimeReadinessTransition(ap, "terminal");
15926
16307
  this.closeActivationTransition(ap, "terminal");
15927
- this.clearRuntimeStartupTimeout(ap);
15928
- this.clearStalledRecoverySigtermWatchdog(ap);
15929
16308
  cleanupAgentCredentialProxy(agentId, ap.launchId);
15930
16309
  this.revokeManagedRunnerCredential(agentId, ap.config, ap.launchId);
15931
- this.idleAgentConfigs.delete(agentId);
16310
+ this.lifecycleRecords.deleteRestartSnapshot(agentId);
15932
16311
  if (ap.inbox.length > 0) {
15933
16312
  this.startingInboxes.bufferMessagesDuringStart(agentId, ap.inbox);
15934
16313
  }
15935
16314
  this.agents.delete(agentId);
15936
- this.terminalRuntimeFailures.set(agentId, { detail, launchId: ap.launchId });
16315
+ this.lifecycleRecords.setTerminalFailure(agentId, { detail, launchId: ap.launchId });
15937
16316
  this.enterNoProcessResidency(
15938
16317
  "terminal_runtime_error",
15939
16318
  this.noProcessResidencyIdentity(agentId, ap.config, ap.launchId, "terminal_runtime_error", ap.driver.id),
@@ -15968,7 +16347,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
15968
16347
  cacheStartupTimeoutRetryConfig(agentId, ap) {
15969
16348
  const retrySessionId = this.restartSafeSessionId(ap);
15970
16349
  const retryConfig = this.buildRestartSafeConfig(ap.config, retrySessionId);
15971
- this.idleAgentConfigs.set(agentId, {
16350
+ this.lifecycleRecords.setRestartSnapshot(agentId, {
15972
16351
  config: retryConfig,
15973
16352
  sessionId: retrySessionId,
15974
16353
  launchId: ap.launchId
@@ -16205,9 +16584,9 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16205
16584
  }
16206
16585
  async stopAgent(agentId, { wait = false, silent = false } = {}) {
16207
16586
  this.cancelQueuedAgentStart(agentId, "stop requested");
16208
- this.pendingStartRebinds.delete(agentId);
16209
- this.idleAgentConfigs.delete(agentId);
16210
- if (this.terminalRuntimeFailures.delete(agentId)) {
16587
+ this.lifecycleRecords.deletePendingStartRebind(agentId);
16588
+ this.lifecycleRecords.deleteRestartSnapshot(agentId);
16589
+ if (this.lifecycleRecords.deleteTerminalFailure(agentId)) {
16211
16590
  this.closeNoProcessResidency(agentId, "suppressed", { negativeEvidenceBucket: "explicit_stop" });
16212
16591
  }
16213
16592
  const ap = this.agents.get(agentId);
@@ -16218,17 +16597,12 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16218
16597
  return;
16219
16598
  }
16220
16599
  ap.notifications.clearTimer();
16221
- this.clearRuntimeErrorDeliveryBackoff(ap);
16222
- if (ap.activityHeartbeat) {
16223
- clearInterval(ap.activityHeartbeat);
16224
- }
16225
- this.clearCompactionWatchdog(ap);
16226
- this.clearStalledRecoverySigtermWatchdog(ap);
16600
+ this.disposeAgentProcessTimers(ap);
16227
16601
  cleanupAgentCredentialProxy(agentId, ap.launchId);
16228
16602
  this.revokeManagedRunnerCredential(agentId, ap.config, ap.launchId);
16229
16603
  this.agents.delete(agentId);
16230
16604
  if (!silent) {
16231
- this.activityClientSeqByAgent.delete(agentId);
16605
+ this.lifecycleRecords.deleteActivityClientSeq(agentId);
16232
16606
  this.agentVisibleDelivery.clearAgent(agentId);
16233
16607
  this.resetSpawnFailBackoff(agentId, "suppressed");
16234
16608
  this.resetRuntimeErrorFingerprintFence(agentId, "explicit_stop", ap);
@@ -16246,7 +16620,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16246
16620
  if (!silent) {
16247
16621
  this.sendRuntimeProfileReportFor(agentId, ap.config, ap.sessionId, ap.launchId, "stop");
16248
16622
  this.sendAgentStatus(agentId, "inactive", ap.launchId);
16249
- this.broadcastActivity(agentId, "offline", "Stopped");
16623
+ this.broadcastActivity(agentId, "offline", "Stopped", [], void 0, "stopped");
16250
16624
  logger.info(`[Agent ${agentId}] Stopped by request`);
16251
16625
  }
16252
16626
  if (wait) {
@@ -16320,8 +16694,9 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16320
16694
  }));
16321
16695
  return true;
16322
16696
  }
16323
- const terminalRuntimeFailure = this.terminalRuntimeFailures.get(agentId);
16324
- if (terminalRuntimeFailure) {
16697
+ const lifecycleRecord = this.agentLifecycleRecord(agentId);
16698
+ if (lifecycleRecord?.kind === "terminal") {
16699
+ const { terminalFailure } = lifecycleRecord;
16325
16700
  if (transientDelivery) {
16326
16701
  this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
16327
16702
  outcome: "transient_dropped_terminal_runtime_error_no_process",
@@ -16329,7 +16704,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16329
16704
  process_present: false,
16330
16705
  cached_idle_config_present: false,
16331
16706
  terminal_runtime_failure: true,
16332
- launchId: terminalRuntimeFailure.launchId || void 0
16707
+ launchId: terminalFailure.launchId || void 0
16333
16708
  }));
16334
16709
  return true;
16335
16710
  }
@@ -16342,14 +16717,14 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16342
16717
  cached_idle_config_present: false,
16343
16718
  terminal_runtime_failure: true,
16344
16719
  starting_inbox_count: startingInboxCount,
16345
- launchId: terminalRuntimeFailure.launchId || void 0
16720
+ launchId: terminalFailure.launchId || void 0
16346
16721
  }));
16347
- this.sendAgentStatus(agentId, "inactive", terminalRuntimeFailure.launchId);
16348
- this.broadcastActivity(agentId, "error", terminalRuntimeFailure.detail, [], terminalRuntimeFailure.launchId);
16722
+ this.sendAgentStatus(agentId, "inactive", terminalFailure.launchId);
16723
+ this.broadcastActivity(agentId, "error", terminalFailure.detail, [], terminalFailure.launchId, "runtime_error");
16349
16724
  return true;
16350
16725
  }
16351
- const cached = this.idleAgentConfigs.get(agentId);
16352
- if (cached) {
16726
+ if (lifecycleRecord?.kind === "idle" || lifecycleRecord?.kind === "cooldown") {
16727
+ const cached = lifecycleRecord.restartSnapshot;
16353
16728
  const driver = this.driverResolver(cached.config.runtime || "claude");
16354
16729
  if (!transientDelivery && this.shouldDeferWakeMessage(agentId, driver, message)) {
16355
16730
  this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
@@ -16364,8 +16739,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16364
16739
  return true;
16365
16740
  }
16366
16741
  logger.info(`[Agent ${agentId}] Starting from idle state for new message`);
16367
- if (this.isSpawnFailBackoffActive(agentId)) {
16368
- const state = this.agentSpawnFailBackoff.get(agentId);
16742
+ if (lifecycleRecord.kind === "cooldown") {
16743
+ const state = lifecycleRecord.spawnFailBackoff;
16369
16744
  const startingInboxCount = this.startingInboxes.bufferDuringStart(agentId, message);
16370
16745
  this.assertStartPendingDeliveryInvariants("delivery-spawn-fail-cooldown");
16371
16746
  this.enterSpawnFailCooldownResidency(agentId, cached, state.untilMs, "idle_auto_restart", "spawn_fail_cooldown_active");
@@ -16383,7 +16758,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16383
16758
  }));
16384
16759
  return true;
16385
16760
  }
16386
- this.idleAgentConfigs.delete(agentId);
16761
+ this.lifecycleRecords.deleteRestartSnapshot(agentId);
16387
16762
  this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
16388
16763
  outcome: "auto_restart_from_idle",
16389
16764
  accepted: true,
@@ -16400,7 +16775,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16400
16775
  }, (err) => {
16401
16776
  logger.error(`[Agent ${agentId}] Failed to auto-restart`, err);
16402
16777
  if (this.reportRunnerCredentialMintFailure(agentId, err, cached.launchId, "idle_auto_restart")) {
16403
- this.idleAgentConfigs.set(agentId, cached);
16778
+ this.lifecycleRecords.setRestartSnapshot(agentId, cached);
16404
16779
  const report2 = this.recordSpawnFailure(agentId, "runner_credential_mint");
16405
16780
  this.assertStartPendingDeliveryInvariants("idle-auto-restart-runner-credential-mint-failure");
16406
16781
  if (report2.backoffActive) {
@@ -16416,7 +16791,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16416
16791
  });
16417
16792
  return false;
16418
16793
  }
16419
- this.idleAgentConfigs.set(agentId, cached);
16794
+ this.lifecycleRecords.setRestartSnapshot(agentId, cached);
16420
16795
  const report = this.recordSpawnFailure(agentId, "spawn_error");
16421
16796
  this.assertStartPendingDeliveryInvariants("idle-auto-restart-spawn-failure");
16422
16797
  if (report.backoffActive) {
@@ -16462,7 +16837,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16462
16837
  cached_idle_config_present: false
16463
16838
  }), "error");
16464
16839
  this.sendAgentStatus(agentId, "inactive", null);
16465
- this.broadcastActivity(agentId, "offline", "Process unavailable; restart required");
16840
+ this.broadcastActivity(agentId, "offline", "Process unavailable; restart required", [], void 0, "runtime_unavailable");
16466
16841
  return false;
16467
16842
  }
16468
16843
  const isIdle = this.isApmIdle(ap);
@@ -16522,7 +16897,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16522
16897
  inbox_count: ap.inbox.length
16523
16898
  }));
16524
16899
  this.sendAgentStatus(agentId, "inactive", ap.launchId);
16525
- this.broadcastActivity(agentId, "error", stickyTerminalFailure.detail);
16900
+ this.broadcastActivity(agentId, "error", stickyTerminalFailure.detail, [], void 0, "runtime_error");
16526
16901
  return true;
16527
16902
  }
16528
16903
  }
@@ -16533,7 +16908,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16533
16908
  if (transientDelivery) {
16534
16909
  this.commitApmIdleState(agentId, ap, false);
16535
16910
  this.startRuntimeTrace(agentId, ap, "stdin-idle-delivery", [message]);
16536
- this.broadcastActivity(agentId, "working", "Message received");
16911
+ this.broadcastMessageReceivedActivity(agentId);
16537
16912
  const stdinAccepted2 = this.deliverMessagesViaStdin(
16538
16913
  agentId,
16539
16914
  ap,
@@ -16579,7 +16954,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16579
16954
  const nextMessages = [...ap.inbox];
16580
16955
  this.commitApmIdleState(agentId, ap, false);
16581
16956
  this.startRuntimeTrace(agentId, ap, "stdin-idle-delivery", [message]);
16582
- this.broadcastActivity(agentId, "working", "Message received");
16957
+ this.broadcastMessageReceivedActivity(agentId);
16583
16958
  const stdinAccepted = this.deliverInboxUpdateViaStdin(
16584
16959
  agentId,
16585
16960
  ap,
@@ -16768,7 +17143,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16768
17143
  }
16769
17144
  async stopAll() {
16770
17145
  this.cancelAllQueuedAgentStarts("daemon shutdown");
16771
- this.idleAgentConfigs.clear();
17146
+ this.lifecycleRecords.clearRestartSnapshots();
16772
17147
  const pids = [];
16773
17148
  for (const ap of this.agents.values()) {
16774
17149
  if (typeof ap.runtime.pid === "number") pids.push(ap.runtime.pid);
@@ -16878,7 +17253,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16878
17253
  }
16879
17254
  getIdleAgentSessionIds() {
16880
17255
  const result = [];
16881
- for (const [agentId, { sessionId, launchId }] of this.idleAgentConfigs) {
17256
+ for (const [agentId, { sessionId, launchId }] of this.lifecycleRecords.restartSnapshotEntries()) {
16882
17257
  if (this.agents.has(agentId)) continue;
16883
17258
  if (sessionId) result.push({ agentId, sessionId, launchId });
16884
17259
  }
@@ -16915,7 +17290,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16915
17290
  running.runtime.currentRuntimeHomeDir
16916
17291
  );
16917
17292
  }
16918
- const idle = this.idleAgentConfigs.get(agentId);
17293
+ const idle = this.lifecycleRecords.getRestartSnapshot(agentId);
16919
17294
  if (idle) {
16920
17295
  return this.buildRuntimeProfileReport(agentId, idle.config, idle.sessionId, idle.launchId);
16921
17296
  }
@@ -16931,7 +17306,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
16931
17306
  seen.add(agentId);
16932
17307
  }
16933
17308
  }
16934
- for (const agentId of this.idleAgentConfigs.keys()) {
17309
+ for (const agentId of this.lifecycleRecords.restartSnapshotAgentIds()) {
16935
17310
  if (seen.has(agentId)) continue;
16936
17311
  const report = this.getAgentRuntimeProfileReport(agentId);
16937
17312
  if (report) reports.push(report);
@@ -17034,11 +17409,12 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17034
17409
  });
17035
17410
  return true;
17036
17411
  }
17037
- const cached = this.idleAgentConfigs.get(agentId);
17038
- if (cached) {
17412
+ const lifecycleRecord = this.agentLifecycleRecord(agentId);
17413
+ if (lifecycleRecord?.kind === "idle" || lifecycleRecord?.kind === "cooldown") {
17414
+ const cached = lifecycleRecord.restartSnapshot;
17039
17415
  logger.info(`[Agent ${agentId}] Starting from idle state for runtime profile ${kind} ${key}`);
17040
- if (this.isSpawnFailBackoffActive(agentId)) {
17041
- const state = this.agentSpawnFailBackoff.get(agentId);
17416
+ if (lifecycleRecord.kind === "cooldown") {
17417
+ const state = lifecycleRecord.spawnFailBackoff;
17042
17418
  this.enterSpawnFailCooldownResidency(agentId, cached, state.untilMs, "runtime_profile_auto_restart", "spawn_fail_cooldown_active");
17043
17419
  span.end("ok", {
17044
17420
  attrs: {
@@ -17051,7 +17427,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17051
17427
  });
17052
17428
  return true;
17053
17429
  }
17054
- this.idleAgentConfigs.delete(agentId);
17430
+ this.lifecycleRecords.deleteRestartSnapshot(agentId);
17055
17431
  return this.startAgent(agentId, cached.config, message, void 0, void 0, cached.launchId || void 0).then(() => {
17056
17432
  this.resetSpawnFailBackoff(agentId);
17057
17433
  this.assertStartPendingDeliveryInvariants("runtime-profile-auto-restart-success");
@@ -17059,7 +17435,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17059
17435
  }, (err) => {
17060
17436
  logger.error(`[Agent ${agentId}] Failed to auto-restart for runtime profile notification`, err);
17061
17437
  if (this.reportRunnerCredentialMintFailure(agentId, err, cached.launchId, "runtime_profile_auto_restart")) {
17062
- this.idleAgentConfigs.set(agentId, cached);
17438
+ this.lifecycleRecords.setRestartSnapshot(agentId, cached);
17063
17439
  const report2 = this.recordSpawnFailure(agentId, "runner_credential_mint");
17064
17440
  this.assertStartPendingDeliveryInvariants("runtime-profile-auto-restart-runner-credential-mint-failure");
17065
17441
  if (report2.backoffActive) {
@@ -17082,7 +17458,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17082
17458
  });
17083
17459
  return false;
17084
17460
  }
17085
- this.idleAgentConfigs.set(agentId, cached);
17461
+ this.lifecycleRecords.setRestartSnapshot(agentId, cached);
17086
17462
  const report = this.recordSpawnFailure(agentId, "spawn_error");
17087
17463
  this.assertStartPendingDeliveryInvariants("runtime-profile-auto-restart-spawn-failure");
17088
17464
  if (report.backoffActive) {
@@ -17119,7 +17495,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17119
17495
  continue;
17120
17496
  }
17121
17497
  const title = runtimeProfileNotificationTitle(notification.kind);
17122
- this.broadcastActivity(agentId, "working", title, [{ kind: "system", title, text: message.content }], launchId);
17498
+ this.broadcastActivity(agentId, "working", title, [{ kind: "system", title, text: message.content }], launchId, "system_message");
17123
17499
  this.sendToServer({
17124
17500
  type: "agent:runtime_profile:daemon_release_notice:ack",
17125
17501
  agentId,
@@ -17148,7 +17524,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17148
17524
  span.end("ok", { attrs: { outcome: "deprecated_noop_completed" } });
17149
17525
  return;
17150
17526
  }
17151
- this.broadcastActivity(agentId, "working", title, [{ kind: "system", title, text: control.message }], launchId);
17527
+ this.broadcastActivity(agentId, "working", title, [{ kind: "system", title, text: control.message }], launchId, "system_message");
17152
17528
  this.sendToServer({
17153
17529
  type: "agent:runtime_profile:daemon_release_notice:ack",
17154
17530
  agentId,
@@ -17256,7 +17632,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17256
17632
  };
17257
17633
  async getSessionTranscript(agentId) {
17258
17634
  const agent = this.agents.get(agentId);
17259
- const idle = this.idleAgentConfigs.get(agentId);
17635
+ const idle = this.lifecycleRecords.getRestartSnapshot(agentId);
17260
17636
  const config = agent?.config ?? idle?.config ?? null;
17261
17637
  const actualSessionId = agent?.sessionId || idle?.sessionId || null;
17262
17638
  if (!config) {
@@ -17433,7 +17809,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17433
17809
  }
17434
17810
  async listSkills(agentId, runtimeHint) {
17435
17811
  const agent = this.agents.get(agentId);
17436
- const idle = this.idleAgentConfigs.get(agentId);
17812
+ const idle = this.lifecycleRecords.getRestartSnapshot(agentId);
17437
17813
  const config = agent?.config ?? idle?.config ?? null;
17438
17814
  const runtime = runtimeHint || config?.runtime || "claude";
17439
17815
  const workspaceDir = path14.join(this.dataDir, agentId);
@@ -17533,12 +17909,12 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17533
17909
  * should carry explicit reason/correlation/window attrs so the server no
17534
17910
  * longer infers lifecycle semantics from generic activity strings.
17535
17911
  */
17536
- broadcastActivity(agentId, activity, detail, extraTrajectory = [], launchIdOverride) {
17912
+ broadcastActivity(agentId, activityKind, detail, extraTrajectory = [], launchIdOverride, detailKind = "other", activityDisplay = activityKind) {
17537
17913
  const ap = this.agents.get(agentId);
17538
17914
  const entries = [...extraTrajectory];
17539
17915
  const hasToolStart = entries.some((e) => e.kind === "tool_start");
17540
17916
  if (!hasToolStart) {
17541
- entries.push({ kind: "status", activity, detail });
17917
+ entries.push({ kind: "status", activity: activityKind, activityKind, detail, detailKind });
17542
17918
  }
17543
17919
  const launchId = launchIdOverride || ap?.launchId || void 0;
17544
17920
  const clientSeq = this.nextActivityClientSeq(agentId);
@@ -17546,23 +17922,28 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17546
17922
  this.sendToServer({
17547
17923
  type: "agent:activity",
17548
17924
  agentId,
17549
- activity,
17925
+ activity: activityDisplay,
17926
+ activityKind,
17550
17927
  detail,
17928
+ detailKind,
17551
17929
  entries,
17552
17930
  launchId,
17553
17931
  clientSeq,
17554
17932
  producerFactId
17555
17933
  });
17556
- this.recordActivityProducedTrace(agentId, activity, detail, entries, ap, launchId, clientSeq, producerFactId);
17934
+ this.recordActivityProducedTrace(agentId, activityKind, detail, detailKind, entries, ap, launchId, clientSeq, producerFactId);
17557
17935
  if (ap) {
17558
- ap.lastActivity = activity;
17936
+ ap.lastActivityKind = activityKind;
17937
+ ap.lastActivity = activityDisplay;
17559
17938
  ap.lastActivityDetail = detail;
17560
- if (activity === "working" || activity === "thinking") {
17561
- if (!ap.activityHeartbeat) {
17562
- ap.activityHeartbeat = setInterval(() => {
17939
+ ap.lastActivityDetailKind = detailKind;
17940
+ if (activityKind === "working" || activityKind === "thinking") {
17941
+ if (ap.activityHeartbeat.kind === "inactive") {
17942
+ const timer = setInterval(() => {
17563
17943
  if (this.markRuntimeProgressStaleIfNeeded(agentId, ap)) return;
17564
17944
  this.recordRuntimeTraceEvent(agentId, ap, "activity.heartbeat.sent", {
17565
- activity: ap.lastActivity
17945
+ activity: ap.lastActivityKind,
17946
+ detailKind: ap.lastActivityDetailKind
17566
17947
  });
17567
17948
  const heartbeatLaunchId = launchIdOverride || ap.launchId || void 0;
17568
17949
  const heartbeatClientSeq = this.nextActivityClientSeq(agentId);
@@ -17571,23 +17952,23 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17571
17952
  type: "agent:activity",
17572
17953
  agentId,
17573
17954
  activity: ap.lastActivity,
17955
+ activityKind: ap.lastActivityKind,
17574
17956
  detail: ap.lastActivityDetail,
17957
+ detailKind: ap.lastActivityDetailKind,
17575
17958
  launchId: heartbeatLaunchId,
17576
17959
  clientSeq: heartbeatClientSeq,
17577
17960
  producerFactId: heartbeatProducerFactId
17578
17961
  });
17579
- this.recordActivityProducedTrace(agentId, ap.lastActivity, ap.lastActivityDetail, [], ap, heartbeatLaunchId, heartbeatClientSeq, heartbeatProducerFactId);
17962
+ this.recordActivityProducedTrace(agentId, ap.lastActivityKind, ap.lastActivityDetail, ap.lastActivityDetailKind, [], ap, heartbeatLaunchId, heartbeatClientSeq, heartbeatProducerFactId);
17580
17963
  }, ACTIVITY_HEARTBEAT_MS);
17964
+ ap.activityHeartbeat = { kind: "active", timer };
17581
17965
  }
17582
17966
  } else {
17583
- if (ap.activityHeartbeat) {
17584
- clearInterval(ap.activityHeartbeat);
17585
- ap.activityHeartbeat = null;
17586
- }
17967
+ this.clearActivityHeartbeat(ap);
17587
17968
  }
17588
17969
  }
17589
17970
  }
17590
- recordActivityProducedTrace(agentId, activity, detail, entries, ap, launchId, clientSeq, producerFactId) {
17971
+ recordActivityProducedTrace(agentId, activityKind, detail, detailKind, entries, ap, launchId, clientSeq, producerFactId) {
17591
17972
  const runtimeContext = ap?.config.runtimeContext;
17592
17973
  this.recordDaemonTrace("daemon.agent.activity.produced", {
17593
17974
  agentId,
@@ -17595,8 +17976,10 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17595
17976
  server_id: runtimeContext?.serverId,
17596
17977
  machine_id: runtimeContext?.machineId,
17597
17978
  process_instance_id: ap?.processInstanceId,
17598
- activity,
17979
+ activity: activityKind,
17980
+ activity_kind: activityKind,
17599
17981
  detail_present: Boolean(detail),
17982
+ detail_kind: detailKind,
17600
17983
  entry_kinds: entries.map((e) => e.kind).join(","),
17601
17984
  ap_present: Boolean(ap),
17602
17985
  launchId,
@@ -17638,8 +18021,10 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17638
18021
  */
17639
18022
  respondToActivityProbe(agentId, probeId) {
17640
18023
  const ap = this.agents.get(agentId);
17641
- const activity = ap?.lastActivity || "offline";
18024
+ const activityKind = ap?.lastActivityKind || "offline";
18025
+ const activity = ap?.lastActivity || activityKind;
17642
18026
  const detail = ap?.lastActivityDetail || (ap ? "" : "Agent not running");
18027
+ const detailKind = ap?.lastActivityDetailKind || (ap ? "none" : "runtime_unavailable");
17643
18028
  const launchId = ap?.launchId || void 0;
17644
18029
  const clientSeq = this.nextActivityClientSeq(agentId);
17645
18030
  const producerFactId = this.buildActivityProducerFactId(agentId, launchId, clientSeq);
@@ -17647,26 +18032,28 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17647
18032
  type: "agent:activity",
17648
18033
  agentId,
17649
18034
  activity,
18035
+ activityKind,
17650
18036
  detail,
18037
+ detailKind,
17651
18038
  launchId,
17652
18039
  probeId,
17653
18040
  clientSeq,
17654
18041
  producerFactId
17655
18042
  });
17656
- this.recordActivityProducedTrace(agentId, activity, detail, [], ap, launchId, clientSeq, producerFactId);
18043
+ this.recordActivityProducedTrace(agentId, activityKind, detail, detailKind, [], ap, launchId, clientSeq, producerFactId);
17657
18044
  }
17658
18045
  flushPendingTrajectory(agentId) {
17659
18046
  const ap = this.agents.get(agentId);
17660
18047
  const pending = ap?.pendingTrajectory;
17661
18048
  if (!ap || !pending) return;
17662
- if (pending.timer) clearTimeout(pending.timer);
18049
+ clearTimeout(pending.timer);
17663
18050
  ap.pendingTrajectory = null;
17664
18051
  const text = pending.text.length > MAX_TRAJECTORY_TEXT ? pending.text.slice(0, MAX_TRAJECTORY_TEXT) + "\u2026" : pending.text;
17665
18052
  if (!text) return;
17666
18053
  if (pending.kind === "thinking") {
17667
- this.broadcastActivity(agentId, "thinking", "", [{ kind: "thinking", text }]);
18054
+ this.broadcastActivity(agentId, "thinking", "", [{ kind: "thinking", text }], void 0, "none");
17668
18055
  } else {
17669
- this.broadcastActivity(agentId, "thinking", "", [{ kind: "text", text }]);
18056
+ this.broadcastActivity(agentId, "thinking", "", [{ kind: "text", text }], void 0, "none");
17670
18057
  }
17671
18058
  }
17672
18059
  queueTrajectoryText(agentId, kind, text) {
@@ -17681,19 +18068,19 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17681
18068
  return;
17682
18069
  }
17683
18070
  if (!text) {
17684
- this.broadcastActivity(agentId, "thinking", "");
18071
+ this.broadcastActivity(agentId, "thinking", "", [], void 0, "none");
17685
18072
  return;
17686
18073
  }
17687
18074
  const pending = ap.pendingTrajectory;
17688
18075
  if (pending && pending.kind === kind) {
17689
18076
  pending.text += text;
17690
- if (pending.timer) clearTimeout(pending.timer);
18077
+ clearTimeout(pending.timer);
17691
18078
  pending.timer = setTimeout(() => this.flushPendingTrajectory(agentId), TRAJECTORY_COALESCE_MS);
17692
18079
  return;
17693
18080
  }
17694
18081
  this.flushPendingTrajectory(agentId);
17695
- if (ap.lastActivity !== "thinking" || ap.lastActivityDetail !== "") {
17696
- this.broadcastActivity(agentId, "thinking", "");
18082
+ if (ap.lastActivityKind !== "thinking" || ap.lastActivityDetailKind !== "none") {
18083
+ this.broadcastActivity(agentId, "thinking", "", [], void 0, "none");
17697
18084
  }
17698
18085
  ap.pendingTrajectory = {
17699
18086
  kind,
@@ -17702,16 +18089,15 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17702
18089
  };
17703
18090
  }
17704
18091
  clearCompactionWatchdog(ap) {
17705
- if (ap.compactionWatchdog) {
17706
- clearTimeout(ap.compactionWatchdog);
17707
- ap.compactionWatchdog = null;
18092
+ if (ap.compaction.kind === "active" && ap.compaction.watchdog) {
18093
+ clearTimeout(ap.compaction.watchdog);
17708
18094
  }
17709
- ap.compactionStartedAt = null;
18095
+ ap.compaction = { kind: "none" };
17710
18096
  }
17711
18097
  clearStalledRecoverySigtermWatchdog(ap) {
17712
- if (!ap.stalledRecoverySigtermTimer) return;
17713
- clearTimeout(ap.stalledRecoverySigtermTimer);
17714
- ap.stalledRecoverySigtermTimer = null;
18098
+ if (ap.exit.kind !== "live" || !ap.exit.stalledRecoverySigtermTimer) return;
18099
+ clearTimeout(ap.exit.stalledRecoverySigtermTimer);
18100
+ ap.exit = { ...ap.exit, stalledRecoverySigtermTimer: null };
17715
18101
  }
17716
18102
  mergeRuntimeExitTraceAttrs(runtime, attrs) {
17717
18103
  this.runtimeExitTraceAttrs.set(runtime, {
@@ -17723,8 +18109,10 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17723
18109
  this.clearStalledRecoverySigtermWatchdog(ap);
17724
18110
  const timeoutMs = stalledRecoverySigtermTimeoutMs();
17725
18111
  const runtimeAtSignal = ap.runtime;
17726
- ap.stalledRecoverySigtermTimer = setTimeout(() => {
17727
- ap.stalledRecoverySigtermTimer = null;
18112
+ const timer = setTimeout(() => {
18113
+ if (ap.exit.kind === "live" && ap.exit.stalledRecoverySigtermTimer === timer) {
18114
+ ap.exit = { ...ap.exit, stalledRecoverySigtermTimer: null };
18115
+ }
17728
18116
  const current = this.agents.get(agentId);
17729
18117
  if (!current || current !== ap || current.runtime !== runtimeAtSignal || current.gatedSteering.expectedTerminationReason !== "stalled_recovery") {
17730
18118
  return;
@@ -17781,26 +18169,29 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17781
18169
  logger.warn(`[Agent ${agentId}] Failed to force kill stalled ${runtimeLabel} process: ${reason}`);
17782
18170
  }
17783
18171
  }, timeoutMs);
18172
+ if (ap.exit.kind === "live") {
18173
+ ap.exit = { ...ap.exit, stalledRecoverySigtermTimer: timer };
18174
+ }
17784
18175
  }
17785
18176
  startCompactionWatchdog(agentId, ap) {
17786
18177
  this.clearCompactionWatchdog(ap);
17787
18178
  const startedAt = Date.now();
17788
- ap.compactionStartedAt = startedAt;
17789
- ap.compactionWatchdog = setTimeout(() => {
18179
+ const watchdog = setTimeout(() => {
17790
18180
  this.markCompactionStale(agentId, startedAt);
17791
18181
  }, COMPACTION_STALE_MS);
18182
+ ap.compaction = { kind: "active", startedAt, watchdog };
17792
18183
  }
17793
18184
  markCompactionStale(agentId, startedAt) {
17794
18185
  const ap = this.agents.get(agentId);
17795
- if (!ap || ap.compactionStartedAt !== startedAt) return;
17796
- ap.compactionWatchdog = null;
17797
- this.broadcastActivity(agentId, "working", "Context compaction still running; no finish event observed");
18186
+ if (!ap || ap.compaction.kind !== "active" || ap.compaction.startedAt !== startedAt) return;
18187
+ ap.compaction = { ...ap.compaction, watchdog: null };
18188
+ this.broadcastActivity(agentId, "working", "Context compaction still running; no finish event observed", [], void 0, "compaction_stale");
17798
18189
  }
17799
18190
  completeCompactionIfActive(agentId, detail = "Context compaction finished", options = {}) {
17800
18191
  const ap = this.agents.get(agentId);
17801
- if (!ap || !ap.compactionStartedAt) return;
18192
+ if (!ap || ap.compaction.kind !== "active") return;
17802
18193
  this.clearCompactionWatchdog(ap);
17803
- this.broadcastActivity(agentId, "working", detail, [{ kind: "compaction_finished" }]);
18194
+ this.broadcastActivity(agentId, "working", detail, [{ kind: "compaction_finished" }], void 0, "compaction_finished");
17804
18195
  const reduction = reduceApmGatedCompaction(ap.gatedSteering, { kind: "compaction_finished" });
17805
18196
  this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, {
17806
18197
  event: "compaction_finished",
@@ -17813,7 +18204,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
17813
18204
  }
17814
18205
  interruptCompactionIfActive(agentId) {
17815
18206
  const ap = this.agents.get(agentId);
17816
- if (!ap || !ap.compactionStartedAt && !ap.gatedSteering.compacting) return;
18207
+ if (!ap || ap.compaction.kind !== "active" && !ap.gatedSteering.compacting) return;
17817
18208
  this.clearCompactionWatchdog(ap);
17818
18209
  const reduction = reduceApmGatedCompaction(ap.gatedSteering, { kind: "compaction_interrupted" });
17819
18210
  this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState);
@@ -18016,8 +18407,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18016
18407
  * for diagnostics, user-facing reporting, and sticky terminal-failure gating.
18017
18408
  */
18018
18409
  invalidateRecoveryErrorView(ap) {
18019
- ap.recentDecisionStderr = [];
18020
- ap.runtimeErrorSinceProgress = false;
18410
+ ap.decisionErrorWindow.noteRuntimeProgress();
18021
18411
  }
18022
18412
  recordGatedSteeringEvent(agentId, ap, event, attrs = {}) {
18023
18413
  if (ap.runtime.descriptor.busyDelivery !== "gated") return;
@@ -18096,7 +18486,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18096
18486
  runtime_error_backoff_remaining_ms: runtimeErrorBackoffRemainingMs,
18097
18487
  runtime_error_backoff_attempts: ap.runtimeErrorDeliveryBackoff.attempts,
18098
18488
  runtime_error_backoff_reason: ap.runtimeErrorDeliveryBackoff.reason || void 0,
18099
- runtime_error_backoff_timer_scheduled: scheduled || ap.runtimeErrorDeliveryBackoff.timer !== null,
18489
+ runtime_error_backoff_timer_scheduled: scheduled || this.runtimeErrorDeliveryBackoffTimerScheduled(ap),
18100
18490
  delivered_messages_count: 0
18101
18491
  });
18102
18492
  return false;
@@ -18133,7 +18523,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18133
18523
  });
18134
18524
  return false;
18135
18525
  }
18136
- this.broadcastActivity(agentId, "working", "Message received");
18526
+ this.broadcastMessageReceivedActivity(agentId);
18137
18527
  let accepted = true;
18138
18528
  if (runtimeProfileMessages.length > 0) {
18139
18529
  ap.inbox.splice(0, ap.inbox.length, ...ordinaryMessageCandidates);
@@ -18226,7 +18616,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18226
18616
  * deliver, so explicit starts with no activation produce no phase-6 row.
18227
18617
  */
18228
18618
  openActivationTransition(agentId, ap, launchSource) {
18229
- if (ap.activationTransition || ap.initialActivationDelivered) return;
18619
+ if (ap.activation.kind !== "idle") return;
18230
18620
  const identity = this.launchIdentityAttrs(agentId, ap, launchSource);
18231
18621
  const state = {
18232
18622
  stateInstanceId: randomUUID6(),
@@ -18234,7 +18624,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18234
18624
  identity,
18235
18625
  negativeEvidenceBucket: launchReadinessNegativeEvidence(identity)
18236
18626
  };
18237
- ap.activationTransition = state;
18627
+ ap.activation = { kind: "open", transition: state };
18238
18628
  this.recordDaemonTrace(LAUNCH_ACTIVATION_DELIVERY_TRANSITION_SPAN, buildLaunchActivationEnterAttrs(state));
18239
18629
  }
18240
18630
  /**
@@ -18245,10 +18635,14 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18245
18635
  * delivered on `advanced` so later normal deliveries are not re-counted.
18246
18636
  */
18247
18637
  closeActivationTransition(ap, closeResult, deliveredVia) {
18248
- if (closeResult === "advanced") ap.initialActivationDelivered = true;
18249
- const state = ap.activationTransition;
18250
- if (!state) return;
18251
- ap.activationTransition = null;
18638
+ if (ap.activation.kind !== "open") {
18639
+ if (closeResult === "advanced" && ap.activation.kind === "idle") {
18640
+ ap.activation = { kind: "delivered" };
18641
+ }
18642
+ return;
18643
+ }
18644
+ const state = ap.activation.transition;
18645
+ ap.activation = closeResult === "advanced" ? { kind: "delivered" } : { kind: "closed" };
18252
18646
  this.recordDaemonTrace(
18253
18647
  LAUNCH_ACTIVATION_DELIVERY_TRANSITION_SPAN,
18254
18648
  buildLaunchActivationCloseAttrs(state, closeResult, this.launchTransitionSeq++, deliveredVia),
@@ -18266,15 +18660,22 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18266
18660
  fenced ? Date.now() + timeoutMs : null
18267
18661
  );
18268
18662
  if (!fenced) return;
18269
- ap.startupTimeoutTimer = setTimeout(() => {
18663
+ if (ap.startup.kind !== "waiting") return;
18664
+ const timer = setTimeout(() => {
18270
18665
  this.handleRuntimeStartupTimeout(agentId, ap, timeoutMs);
18271
18666
  }, timeoutMs);
18272
- ap.startupTimeoutTimer.unref?.();
18667
+ timer.unref?.();
18668
+ ap.startup = { ...ap.startup, timer };
18273
18669
  }
18274
18670
  clearRuntimeStartupTimeout(ap) {
18275
- if (!ap.startupTimeoutTimer) return;
18276
- clearTimeout(ap.startupTimeoutTimer);
18277
- ap.startupTimeoutTimer = null;
18671
+ if (ap.startup.kind !== "waiting" || !ap.startup.timer) return;
18672
+ clearTimeout(ap.startup.timer);
18673
+ ap.startup = { ...ap.startup, timer: null };
18674
+ }
18675
+ markRuntimeStartupReady(ap) {
18676
+ if (ap.startup.kind === "ready") return;
18677
+ this.clearRuntimeStartupTimeout(ap);
18678
+ ap.startup = agentProcessStartupReady(ap.startup);
18278
18679
  }
18279
18680
  runtimeStartupReadinessSatisfiedByEvent(ap, event) {
18280
18681
  if ((ap.driver.startupReadiness ?? "first_event") !== "initial_turn") {
@@ -18286,7 +18687,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18286
18687
  const current = this.agents.get(agentId);
18287
18688
  if (current !== ap) return;
18288
18689
  const reduction = reduceApmStartupTimeoutTermination(ap.gatedSteering, {
18289
- hasRuntimeProgressEvent: ap.startupReadinessSatisfied
18690
+ hasRuntimeProgressEvent: ap.startup.kind === "ready"
18290
18691
  });
18291
18692
  if (!reduction.shouldTerminate) {
18292
18693
  this.clearRuntimeStartupTimeout(ap);
@@ -18298,7 +18699,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18298
18699
  const terminalFailureDetail = classifyTerminalFailure(ap);
18299
18700
  const detail = terminalFailureDetail?.detail ?? formatRuntimeStartTimeoutMessage(ap.driver.id);
18300
18701
  ap.lastRuntimeError = detail;
18301
- ap.runtimeErrorSinceProgress = true;
18702
+ ap.decisionErrorWindow.recordRuntimeError(detail);
18302
18703
  ap.runtimeProgress.markStale();
18303
18704
  const staleForMs = Math.max(timeoutMs, ap.runtimeProgress.ageMs());
18304
18705
  const diagnostic = buildRuntimeStallDiagnostic(ap, staleForMs, Math.max(1, Math.floor(staleForMs / 6e4)));
@@ -18316,7 +18717,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18316
18717
  ...this.finalizeRuntimeProfileTurnControl(agentId, ap, "runtime_stalled")
18317
18718
  });
18318
18719
  logger.warn(`[Agent ${agentId}] ${ap.driver.id} did not reach startup readiness within ${timeoutMs}ms; terminating process`);
18319
- this.broadcastActivity(agentId, "error", detail, [{ kind: "text", text: `Error: ${detail}` }], ap.launchId);
18720
+ this.broadcastActivity(agentId, "error", detail, [{ kind: "text", text: `Error: ${detail}` }], ap.launchId, "runtime_error");
18320
18721
  this.sendAgentStatus(agentId, "inactive", ap.launchId);
18321
18722
  this.cacheStartupTimeoutRetryConfig(agentId, ap);
18322
18723
  try {
@@ -18339,7 +18740,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18339
18740
  const reduction = reduceApmStartupRequestErrorTermination(ap.gatedSteering);
18340
18741
  this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "startup_request_error" });
18341
18742
  ap.lastRuntimeError = event.message;
18342
- ap.runtimeErrorSinceProgress = true;
18743
+ ap.decisionErrorWindow.recordRuntimeError(event.message);
18343
18744
  ap.runtimeProgress.markStale();
18344
18745
  ap.notifications.clearPending();
18345
18746
  ap.notifications.clearTimer();
@@ -18370,9 +18771,9 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18370
18771
  );
18371
18772
  this.broadcastActivity(agentId, "error", visibleErrorMessage, [
18372
18773
  { kind: "text", text: `Error: ${visibleErrorMessage}` }
18373
- ], ap.launchId);
18774
+ ], ap.launchId, "runtime_error");
18374
18775
  this.sendAgentStatus(agentId, "inactive", ap.launchId);
18375
- this.idleAgentConfigs.delete(agentId);
18776
+ this.lifecycleRecords.deleteRestartSnapshot(agentId);
18376
18777
  try {
18377
18778
  this.runtimeExitTraceAttrs.set(ap.runtime, {
18378
18779
  stop_source: "startup_request_error",
@@ -18390,7 +18791,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18390
18791
  return /thinking.*redacted_thinking|redacted_thinking.*thinking/i.test(message) && /cannot be modified/i.test(message) || /messages\.\d+\.content\.\d+\.text\.start_timestamp:\s*Extra inputs are not permitted/i.test(message);
18391
18792
  }
18392
18793
  markRuntimeProgressStaleIfNeeded(agentId, ap) {
18393
- if (ap.lastActivity !== "working" && ap.lastActivity !== "thinking") return false;
18794
+ if (ap.lastActivityKind !== "working" && ap.lastActivityKind !== "thinking") return false;
18394
18795
  if (ap.runtimeProgress.isStale) return true;
18395
18796
  const staleForMs = ap.runtimeProgress.ageMs();
18396
18797
  if (staleForMs < RUNTIME_PROGRESS_STALE_MS) return false;
@@ -18400,7 +18801,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18400
18801
  const projection = projectApmRuntimeProgressStalledTrace({
18401
18802
  turnReason: diagnostic.turnReason,
18402
18803
  staleForMs,
18403
- lastActivity: ap.lastActivity,
18804
+ lastActivity: ap.lastActivityKind,
18404
18805
  lastActivityDetailPresent: diagnostic.lastActivityDetailPresent,
18405
18806
  lastActivityDetailKind: diagnostic.lastActivityDetailKind
18406
18807
  });
@@ -18424,13 +18825,13 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18424
18825
  }
18425
18826
  this.recordDaemonTrace("daemon.runtime.stall.detected", {
18426
18827
  ...this.processLifecycleIdentityAttrs(agentId, ap),
18427
- last_event_kind: ap.lastActivity || void 0,
18828
+ last_event_kind: ap.lastActivityKind || void 0,
18428
18829
  last_event_age_ms_bucket: bucketMs(staleForMs),
18429
18830
  subprocess_pid_alive: subprocessPidAlive,
18430
18831
  subprocess_socket_alive: !ap.runtime.closed,
18431
18832
  daemon_connected_to_server: this.serverConnected()
18432
18833
  }, "error");
18433
- this.broadcastActivity(agentId, "error", diagnostic.detail);
18834
+ this.broadcastActivity(agentId, "error", diagnostic.detail, [], void 0, "runtime_stalled");
18434
18835
  return true;
18435
18836
  }
18436
18837
  recoverStaleProcessForQueuedMessageIfNeeded(agentId, ap) {
@@ -18457,7 +18858,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18457
18858
  reason: "stalled_recovery",
18458
18859
  turnReason: diagnostic.turnReason,
18459
18860
  staleForMs,
18460
- lastActivity: ap.lastActivity,
18861
+ lastActivity: ap.lastActivityKind,
18461
18862
  lastActivityDetailPresent: diagnostic.lastActivityDetailPresent,
18462
18863
  lastActivityDetailKind: diagnostic.lastActivityDetailKind,
18463
18864
  pendingMessages: ap.inbox.length,
@@ -18476,7 +18877,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18476
18877
  logger.warn(
18477
18878
  `[Agent ${agentId}] ${runtimeLabel} process stalled for ${staleForMinutes}m with ${ap.inbox.length} queued message(s); terminating for restart`
18478
18879
  );
18479
- this.broadcastActivity(agentId, "working", `Restarting stalled ${runtimeLabel} runtime for queued message`);
18880
+ this.broadcastActivity(agentId, "working", `Restarting stalled ${runtimeLabel} runtime for queued message`, [], void 0, "stalled_recovery");
18480
18881
  try {
18481
18882
  this.runtimeExitTraceAttrs.set(ap.runtime, projection.processExitAttrs);
18482
18883
  this.startStalledRecoverySigtermWatchdog(agentId, ap, runtimeLabel, ap.inbox.length, staleForMs);
@@ -18534,9 +18935,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18534
18935
  if (ap) {
18535
18936
  const wasStalled = ap.runtimeProgress.isStale;
18536
18937
  if (this.runtimeStartupReadinessSatisfiedByEvent(ap, event)) {
18537
- ap.startupReadinessSatisfied = true;
18938
+ this.markRuntimeStartupReady(ap);
18538
18939
  this.closeRuntimeReadinessTransition(ap, "advanced");
18539
- this.clearRuntimeStartupTimeout(ap);
18540
18940
  }
18541
18941
  this.noteRuntimeTraceCounter(ap, event);
18542
18942
  const eventAttrs = event.kind === "internal_progress" ? {
@@ -18640,7 +19040,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18640
19040
  kind: "tool_start",
18641
19041
  toolName: invocation.toolName,
18642
19042
  toolInput: inputSummary
18643
- }]);
19043
+ }], void 0, this.toolActivityDetailKind(invocation.toolName));
18644
19044
  break;
18645
19045
  }
18646
19046
  case "tool_output": {
@@ -18664,7 +19064,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18664
19064
  this.flushPendingTrajectory(agentId);
18665
19065
  if (ap) this.recordRuntimeTraceEvent(agentId, ap, "runtime.context_compaction.started");
18666
19066
  if (ap) this.startCompactionWatchdog(agentId, ap);
18667
- this.broadcastActivity(agentId, "working", "Compacting context", [{ kind: "compaction_started" }]);
19067
+ this.broadcastActivity(agentId, "working", "Compacting context", [{ kind: "compaction_started" }], void 0, "compacting_context");
18668
19068
  if (ap) {
18669
19069
  const reduction = reduceApmGatedCompaction(ap.gatedSteering, { kind: "compaction_started" });
18670
19070
  this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "compaction_started" });
@@ -18674,7 +19074,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18674
19074
  this.flushPendingTrajectory(agentId);
18675
19075
  if (ap) this.recordRuntimeTraceEvent(agentId, ap, "runtime.context_compaction.finished");
18676
19076
  if (ap) this.clearCompactionWatchdog(ap);
18677
- this.broadcastActivity(agentId, "working", "Context compaction finished", [{ kind: "compaction_finished" }]);
19077
+ this.broadcastActivity(agentId, "working", "Context compaction finished", [{ kind: "compaction_finished" }], void 0, "compaction_finished");
18678
19078
  if (ap) {
18679
19079
  const reduction = reduceApmGatedCompaction(ap.gatedSteering, { kind: "compaction_finished" });
18680
19080
  this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "compaction_finished" });
@@ -18684,7 +19084,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18684
19084
  case "review_started":
18685
19085
  this.flushPendingTrajectory(agentId);
18686
19086
  if (ap) this.recordRuntimeTraceEvent(agentId, ap, "runtime.review_mode.started");
18687
- this.broadcastActivity(agentId, "working", "Reviewing changes");
19087
+ this.broadcastActivity(agentId, "working", "Reviewing changes", [], void 0, "reviewing_changes");
18688
19088
  if (ap) {
18689
19089
  const reduction = reduceApmGatedReview(ap.gatedSteering, { kind: "review_started" });
18690
19090
  this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "review_started" });
@@ -18693,7 +19093,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18693
19093
  case "review_finished":
18694
19094
  this.flushPendingTrajectory(agentId);
18695
19095
  if (ap) this.recordRuntimeTraceEvent(agentId, ap, "runtime.review_mode.finished");
18696
- this.broadcastActivity(agentId, "working", "Review finished");
19096
+ this.broadcastActivity(agentId, "working", "Review finished", [], void 0, "review_finished");
18697
19097
  if (ap) {
18698
19098
  const reduction = reduceApmGatedReview(ap.gatedSteering, { kind: "review_finished" });
18699
19099
  this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "review_finished" });
@@ -18730,20 +19130,20 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18730
19130
  if (!this.executeApmGatedSteeringEffect(agentId, ap, deliverStdinEffect)) {
18731
19131
  this.commitApmIdleState(agentId, ap, true);
18732
19132
  if (stickyTerminalFailure) {
18733
- this.broadcastActivity(agentId, "error", stickyTerminalFailure.detail);
19133
+ this.broadcastActivity(agentId, "error", stickyTerminalFailure.detail, [], void 0, "runtime_error");
18734
19134
  } else if (ap.lastRuntimeError && ap.runtimeErrorDeliveryBackoff.attempts > 0) {
18735
- this.broadcastActivity(agentId, "error", ap.lastRuntimeError);
19135
+ this.broadcastActivity(agentId, "error", ap.lastRuntimeError, [], void 0, "runtime_error");
18736
19136
  } else {
18737
- this.broadcastActivity(agentId, "online", "Idle");
19137
+ this.broadcastActivity(agentId, "online", "Idle", [], void 0, "idle");
18738
19138
  }
18739
19139
  }
18740
19140
  } else {
18741
19141
  if (stickyTerminalFailure) {
18742
- this.broadcastActivity(agentId, "error", stickyTerminalFailure.detail);
19142
+ this.broadcastActivity(agentId, "error", stickyTerminalFailure.detail, [], void 0, "runtime_error");
18743
19143
  } else if (ap.lastRuntimeError) {
18744
- this.broadcastActivity(agentId, "error", ap.lastRuntimeError);
19144
+ this.broadcastActivity(agentId, "error", ap.lastRuntimeError, [], void 0, "runtime_error");
18745
19145
  } else {
18746
- this.broadcastActivity(agentId, "online", "Idle");
19146
+ this.broadcastActivity(agentId, "online", "Idle", [], void 0, "idle");
18747
19147
  }
18748
19148
  }
18749
19149
  this.endRuntimeTrace(ap, stickyTerminalFailure ? "error" : "ok", {
@@ -18775,7 +19175,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18775
19175
  this.flushPendingTrajectory(agentId);
18776
19176
  if (ap) {
18777
19177
  ap.lastRuntimeError = event.message;
18778
- ap.runtimeErrorSinceProgress = true;
19178
+ ap.decisionErrorWindow.recordRuntimeError(event.message);
18779
19179
  }
18780
19180
  let visibleErrorMessage = event.message;
18781
19181
  if (ap) {
@@ -18856,7 +19256,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18856
19256
  }
18857
19257
  this.broadcastActivity(agentId, "error", visibleErrorMessage, [
18858
19258
  { kind: "text", text: `Error: ${visibleErrorMessage}` }
18859
- ]);
19259
+ ], void 0, "runtime_error");
18860
19260
  break;
18861
19261
  }
18862
19262
  }
@@ -18936,7 +19336,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
18936
19336
  "error",
18937
19337
  `Start failed: ${reason}`,
18938
19338
  [{ kind: "text", text: `Error: ${reason}` }],
18939
- launchId
19339
+ launchId,
19340
+ "runtime_error"
18940
19341
  );
18941
19342
  return true;
18942
19343
  }
@@ -19004,7 +19405,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
19004
19405
  runtime_error_backoff_remaining_ms: runtimeErrorBackoffRemainingMs,
19005
19406
  runtime_error_backoff_attempts: ap.runtimeErrorDeliveryBackoff.attempts,
19006
19407
  runtime_error_backoff_reason: ap.runtimeErrorDeliveryBackoff.reason || void 0,
19007
- runtime_error_backoff_timer_scheduled: scheduled || ap.runtimeErrorDeliveryBackoff.timer !== null
19408
+ runtime_error_backoff_timer_scheduled: scheduled || this.runtimeErrorDeliveryBackoffTimerScheduled(ap)
19008
19409
  });
19009
19410
  return false;
19010
19411
  }
@@ -19158,6 +19559,22 @@ ${formatAgentInboxDelta(inboxRows, { totalPendingMessages: inboxCount })}]`;
19158
19559
  "]"
19159
19560
  ].join("\n");
19160
19561
  }
19562
+ formatConcreteMessagesRuntimeInput(messages, driver) {
19563
+ if (messages.length === 1) {
19564
+ return `New message received:
19565
+
19566
+ ${formatIncomingMessage(messages[0], incomingMessageFormatOptionsForDriver(driver))}
19567
+
19568
+ Respond as appropriate. Complete all your work before stopping.
19569
+ ${RESPONSE_TARGET_HINT}`;
19570
+ }
19571
+ return `New messages received:
19572
+
19573
+ ${messages.map((message) => formatIncomingMessage(message, incomingMessageFormatOptionsForDriver(driver))).join("\n")}
19574
+
19575
+ Respond as appropriate. Complete all your work before stopping.
19576
+ ${RESPONSE_TARGET_HINT}`;
19577
+ }
19161
19578
  recordInboxUpdateProjection(agentId, ap, messages, source, mode, renderedInput, totalPendingMessages = messages.length) {
19162
19579
  const rows = projectAgentInboxSnapshot(messages);
19163
19580
  const projectionAttrs = this.inboxProjectionTraceAttrs(rows, totalPendingMessages);
@@ -19912,7 +20329,8 @@ var DIAGNOSTIC_ID_ATTRS = /* @__PURE__ */ new Set([
19912
20329
  "machine_id",
19913
20330
  "process_instance_id",
19914
20331
  "launch_id",
19915
- "correlation_id"
20332
+ "correlation_id",
20333
+ "migration_attempt_id"
19916
20334
  ]);
19917
20335
  var DIAGNOSTIC_ERROR_ATTRS = /* @__PURE__ */ new Set([
19918
20336
  "runtime_error_class",
@@ -20363,6 +20781,66 @@ function readPositiveIntegerEnv2(name, fallback) {
20363
20781
  return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
20364
20782
  }
20365
20783
 
20784
+ // src/computerMigrationGuard.ts
20785
+ import { existsSync as existsSync9, readdirSync as readdirSync6, readFileSync as readFileSync8 } from "fs";
20786
+ import path18 from "path";
20787
+ var LegacyDaemonKeyAdoptedByComputerError = class extends Error {
20788
+ code = "LEGACY_DAEMON_KEY_ADOPTED_BY_COMPUTER";
20789
+ attachmentPath;
20790
+ serverId;
20791
+ constructor(match) {
20792
+ const serverDisplay = match.serverSlug ? `/${match.serverSlug}` : match.serverId;
20793
+ const startCommand = match.serverSlug ? `raft-computer start /${match.serverSlug}` : "raft-computer start";
20794
+ super(
20795
+ `This legacy daemon key was already adopted by Raft Computer for ${serverDisplay}. Start the Computer supervisor instead: ${startCommand}. Legacy daemon startup is blocked to avoid relaunching a migrated machine key.`
20796
+ );
20797
+ this.name = "LegacyDaemonKeyAdoptedByComputerError";
20798
+ this.attachmentPath = match.attachmentPath;
20799
+ this.serverId = match.serverId;
20800
+ }
20801
+ };
20802
+ function daemonApiKeyFingerprint(apiKey) {
20803
+ return getDaemonMachineLockId(apiKey).slice("machine-".length);
20804
+ }
20805
+ function findAdoptedComputerForLegacyFingerprint(slockHome, legacyApiKeyFingerprint) {
20806
+ const serversDir = path18.join(slockHome, "computer", "servers");
20807
+ if (!existsSync9(serversDir)) return null;
20808
+ let serverDirs;
20809
+ try {
20810
+ serverDirs = readdirSync6(serversDir);
20811
+ } catch {
20812
+ return null;
20813
+ }
20814
+ for (const serverId of serverDirs) {
20815
+ const attachmentPath = path18.join(serversDir, serverId, "runner.state.json");
20816
+ let raw;
20817
+ try {
20818
+ raw = readFileSync8(attachmentPath, "utf8");
20819
+ } catch {
20820
+ continue;
20821
+ }
20822
+ try {
20823
+ const attachment = JSON.parse(raw);
20824
+ if (attachment.kind === "computer-attachment" && attachment.adoptedFromLegacy === true && attachment.legacyApiKeyFingerprint === legacyApiKeyFingerprint) {
20825
+ return {
20826
+ attachmentPath,
20827
+ serverId: typeof attachment.serverId === "string" && attachment.serverId.length > 0 ? attachment.serverId : serverId,
20828
+ serverSlug: typeof attachment.serverSlug === "string" && attachment.serverSlug.length > 0 ? attachment.serverSlug : void 0,
20829
+ serverMachineId: typeof attachment.serverMachineId === "string" && attachment.serverMachineId.length > 0 ? attachment.serverMachineId : void 0
20830
+ };
20831
+ }
20832
+ } catch {
20833
+ continue;
20834
+ }
20835
+ }
20836
+ return null;
20837
+ }
20838
+ function assertLegacyDaemonKeyNotAdoptedByComputer(options) {
20839
+ const legacyApiKeyFingerprint = daemonApiKeyFingerprint(options.apiKey);
20840
+ const match = findAdoptedComputerForLegacyFingerprint(options.slockHome, legacyApiKeyFingerprint);
20841
+ if (match) throw new LegacyDaemonKeyAdoptedByComputerError(match);
20842
+ }
20843
+
20366
20844
  // src/core.ts
20367
20845
  var DEFAULT_TRACE_UPLOAD_URL = "https://slock-trace-upload.botiverse.dev";
20368
20846
  var RUNNER_CREDENTIAL_SCOPES = ["send", "read", "mentions", "tasks", "reactions", "server", "channels", "knowledge"];
@@ -20534,13 +21012,13 @@ function readDaemonVersion(moduleUrl = import.meta.url) {
20534
21012
  }
20535
21013
  }
20536
21014
  function resolveSlockCliPath(moduleUrl = import.meta.url) {
20537
- const thisDir = path18.dirname(fileURLToPath(moduleUrl));
20538
- const bundledDistPath = path18.resolve(thisDir, "cli", "index.js");
21015
+ const thisDir = path19.dirname(fileURLToPath(moduleUrl));
21016
+ const bundledDistPath = path19.resolve(thisDir, "cli", "index.js");
20539
21017
  try {
20540
21018
  accessSync(bundledDistPath);
20541
21019
  return bundledDistPath;
20542
21020
  } catch {
20543
- const workspaceDistPath = path18.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
21021
+ const workspaceDistPath = path19.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
20544
21022
  accessSync(workspaceDistPath);
20545
21023
  return workspaceDistPath;
20546
21024
  }
@@ -20554,7 +21032,7 @@ function resolveSlockCliPathOrEmpty(moduleUrl = import.meta.url) {
20554
21032
  }
20555
21033
  async function runBundledSlockCli(argv) {
20556
21034
  process.argv = [process.execPath, "slock", ...argv];
20557
- await import("./dist-PCKZII47.js");
21035
+ await import("./dist-TGKVYIA7.js");
20558
21036
  }
20559
21037
  function detectRuntimes(tracer = noopTracer) {
20560
21038
  const ids = [];
@@ -20695,7 +21173,7 @@ var DaemonCore = class {
20695
21173
  options;
20696
21174
  daemonVersion;
20697
21175
  // When this runner is launched by a managed Computer service, the
20698
- // service exports SLOCK_COMPUTER_VERSION (the `@botiverse/raft-computer`
21176
+ // service exports RAFT_COMPUTER_VERSION (the `@botiverse/raft-computer`
20699
21177
  // bundle version). Reported in `ready` so the server can surface the
20700
21178
  // Computer's own version (distinct from the underlying daemonVersion).
20701
21179
  computerVersion;
@@ -20722,7 +21200,7 @@ var DaemonCore = class {
20722
21200
  constructor(options) {
20723
21201
  this.options = options;
20724
21202
  this.daemonVersion = options.daemonVersion ?? readDaemonVersion();
20725
- this.computerVersion = (process.env.SLOCK_COMPUTER_VERSION || "").trim() || null;
21203
+ this.computerVersion = (process.env.RAFT_COMPUTER_VERSION || "").trim() || null;
20726
21204
  this.slockCliPath = options.slockCliPath ?? resolveSlockCliPathOrEmpty();
20727
21205
  this.slockHome = resolveSlockHome();
20728
21206
  process.env[SLOCK_HOME_ENV] = this.slockHome;
@@ -20762,7 +21240,7 @@ var DaemonCore = class {
20762
21240
  }
20763
21241
  resolveMachineStateRoot() {
20764
21242
  if (this.options.machineStateDir) return this.options.machineStateDir;
20765
- if (this.options.dataDir) return path18.join(path18.dirname(this.options.dataDir), "machines");
21243
+ if (this.options.dataDir) return path19.join(path19.dirname(this.options.dataDir), "machines");
20766
21244
  return resolveDefaultMachineStateRoot();
20767
21245
  }
20768
21246
  shouldEnableLocalTrace() {
@@ -20790,7 +21268,7 @@ var DaemonCore = class {
20790
21268
  sinks: [this.localTraceSink]
20791
21269
  }));
20792
21270
  this.agentManager.setTracer(this.tracer);
20793
- this.agentManager.setCliTransportTraceDir(path18.join(machineDir, "traces"));
21271
+ this.agentManager.setCliTransportTraceDir(path19.join(machineDir, "traces"));
20794
21272
  }
20795
21273
  installTraceBundleUploader(machineDir) {
20796
21274
  if (!this.shouldEnableLocalTrace()) return;
@@ -20816,6 +21294,10 @@ var DaemonCore = class {
20816
21294
  `[Slock Daemon] Legacy Slock state exists outside ${SLOCK_HOME_ENV}: ${legacy.path}. This daemon will use ${legacy.destination}; migrate manually if that ${legacy.description} should move with this installation.`
20817
21295
  );
20818
21296
  }
21297
+ assertLegacyDaemonKeyNotAdoptedByComputer({
21298
+ slockHome: this.slockHome,
21299
+ apiKey: this.options.apiKey
21300
+ });
20819
21301
  if (!this.machineLock) {
20820
21302
  this.machineLock = acquireDaemonMachineLock({
20821
21303
  apiKey: this.options.apiKey,
@@ -21038,7 +21520,8 @@ var DaemonCore = class {
21038
21520
  msg.unreadSummary,
21039
21521
  msg.resumePrompt,
21040
21522
  msg.launchId,
21041
- wakeMessageTransient
21523
+ wakeMessageTransient,
21524
+ msg.resumeMessages
21042
21525
  );
21043
21526
  this.coreStartingAgentIds.delete(msg.agentId);
21044
21527
  if (wakeDeliveryAck) {