@botiverse/raft-daemon 0.63.7 → 0.65.0-play.20260629144133

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.
@@ -11,16 +11,488 @@ function makeIsMember(members) {
11
11
  return (value) => typeof value === "string" && set.has(value);
12
12
  }
13
13
 
14
+ // ../shared/src/piBuiltinModels.generated.ts
15
+ var PI_BUILTIN_PROVIDER_API_KEY_ENV_KEYS_GENERATED = {
16
+ "deepseek": "DEEPSEEK_API_KEY",
17
+ "minimax": "MINIMAX_API_KEY",
18
+ "minimax-cn": "MINIMAX_CN_API_KEY",
19
+ "zai": "ZAI_API_KEY",
20
+ "zai-coding-cn": "ZAI_CODING_CN_API_KEY",
21
+ "moonshotai": "MOONSHOT_API_KEY",
22
+ "moonshotai-cn": "MOONSHOT_API_KEY",
23
+ "kimi-coding": "KIMI_API_KEY",
24
+ "openrouter": "OPENROUTER_API_KEY",
25
+ "openai": "OPENAI_API_KEY",
26
+ "anthropic": "ANTHROPIC_API_KEY",
27
+ "google": "GEMINI_API_KEY",
28
+ "xai": "XAI_API_KEY",
29
+ "xiaomi": "XIAOMI_API_KEY"
30
+ };
31
+ var PI_BUILTIN_PROVIDER_BLOCKED_HOST_ENV_KEYS_GENERATED = {
32
+ "deepseek": ["DEEPSEEK_API_KEY"],
33
+ "minimax": ["MINIMAX_API_KEY"],
34
+ "minimax-cn": ["MINIMAX_CN_API_KEY"],
35
+ "zai": ["ZAI_API_KEY"],
36
+ "zai-coding-cn": ["ZAI_CODING_CN_API_KEY"],
37
+ "moonshotai": ["MOONSHOT_API_KEY"],
38
+ "moonshotai-cn": ["MOONSHOT_API_KEY"],
39
+ "kimi-coding": ["KIMI_API_KEY"],
40
+ "openrouter": ["OPENROUTER_API_KEY"],
41
+ "openai": ["OPENAI_API_KEY"],
42
+ "anthropic": ["ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY"],
43
+ "google": ["GEMINI_API_KEY"],
44
+ "xai": ["XAI_API_KEY"],
45
+ "xiaomi": ["XIAOMI_API_KEY"]
46
+ };
47
+ var PI_BUILTIN_PROVIDER_MODELS_GENERATED = {
48
+ "deepseek": [
49
+ { id: "deepseek/deepseek-v4-pro", label: "DeepSeek V4 Pro" },
50
+ { id: "deepseek/deepseek-v4-flash", label: "DeepSeek V4 Flash" }
51
+ ],
52
+ "minimax": [
53
+ { 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" }
56
+ ],
57
+ "minimax-cn": [
58
+ { 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" }
61
+ ],
62
+ "zai": [
63
+ { id: "zai/glm-5.1", label: "GLM-5.1" },
64
+ { id: "zai/glm-4.5-air", label: "GLM-4.5-Air" },
65
+ { id: "zai/glm-4.7", label: "GLM-4.7" },
66
+ { id: "zai/glm-5-turbo", label: "GLM-5-Turbo" },
67
+ { id: "zai/glm-5.2", label: "GLM-5.2" },
68
+ { id: "zai/glm-5v-turbo", label: "GLM-5V-Turbo" }
69
+ ],
70
+ "zai-coding-cn": [
71
+ { 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
+ { id: "zai-coding-cn/glm-4.7", label: "GLM-4.7" },
74
+ { id: "zai-coding-cn/glm-5-turbo", label: "GLM-5-Turbo" },
75
+ { id: "zai-coding-cn/glm-5.2", label: "GLM-5.2" },
76
+ { id: "zai-coding-cn/glm-5v-turbo", label: "GLM-5V-Turbo" }
77
+ ],
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" },
82
+ { id: "moonshotai/kimi-k2-thinking", label: "Kimi K2 Thinking" },
83
+ { id: "moonshotai/kimi-k2-thinking-turbo", label: "Kimi K2 Thinking Turbo" },
84
+ { id: "moonshotai/kimi-k2-turbo-preview", label: "Kimi K2 Turbo" },
85
+ { 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" }
88
+ ],
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" },
93
+ { id: "moonshotai-cn/kimi-k2-thinking", label: "Kimi K2 Thinking" },
94
+ { id: "moonshotai-cn/kimi-k2-thinking-turbo", label: "Kimi K2 Thinking Turbo" },
95
+ { id: "moonshotai-cn/kimi-k2-turbo-preview", label: "Kimi K2 Turbo" },
96
+ { 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" }
99
+ ],
100
+ "kimi-coding": [
101
+ { id: "kimi-coding/kimi-for-coding", label: "Kimi For Coding" },
102
+ { id: "kimi-coding/k2p7", label: "Kimi K2.7 Code" },
103
+ { id: "kimi-coding/kimi-k2-thinking", label: "Kimi K2 Thinking" }
104
+ ],
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
+ { 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)" },
124
+ { id: "openrouter/anthropic/claude-opus-4.8", label: "Anthropic: Claude Opus 4.8" },
125
+ { 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" },
128
+ { 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" },
155
+ { id: "openrouter/google/gemini-2.5-pro-preview", label: "Google: Gemini 2.5 Pro Preview 06-05" },
156
+ { 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" },
161
+ { id: "openrouter/google/gemini-3.1-pro-preview", label: "Google: Gemini 3.1 Pro Preview" },
162
+ { 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
+ { 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" },
299
+ { id: "openrouter/qwen/qwen3-coder", label: "Qwen: Qwen3 Coder 480B A35B" },
300
+ { 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" },
302
+ { id: "openrouter/qwen/qwen3-coder-next", label: "Qwen: Qwen3 Coder Next" },
303
+ { 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" },
311
+ { 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" },
313
+ { 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
+ { 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" },
324
+ { 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" },
334
+ { 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" },
339
+ { id: "openrouter/thedrummer/unslopnemo-12b", label: "TheDrummer: UnslopNemo 12B" },
340
+ { id: "openrouter/upstage/solar-pro-3", label: "Upstage: Solar Pro 3" },
341
+ { 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" },
346
+ { id: "openrouter/z-ai/glm-4.5", label: "Z.ai: GLM 4.5" },
347
+ { id: "openrouter/z-ai/glm-4.5-air", label: "Z.ai: GLM 4.5 Air" },
348
+ { 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" },
363
+ { id: "openrouter/~moonshotai/kimi-latest", label: "MoonshotAI Kimi Latest" },
364
+ { id: "openrouter/~openai/gpt-latest", label: "OpenAI GPT Latest" },
365
+ { id: "openrouter/~openai/gpt-mini-latest", label: "OpenAI GPT Mini Latest" }
366
+ ],
367
+ "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
+ { 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" },
393
+ { 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)" },
395
+ { id: "openai/gpt-5.3-codex", label: "GPT-5.3 Codex" },
396
+ { 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" },
400
+ { 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" },
404
+ { id: "openai/o3", label: "o3" },
405
+ { 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" },
408
+ { id: "openai/o4-mini", label: "o4-mini" },
409
+ { id: "openai/o4-mini-deep-research", label: "o4-mini-deep-research" }
410
+ ],
411
+ "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
+ { 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" },
427
+ { id: "anthropic/claude-opus-4-20250514", label: "Claude Opus 4" },
428
+ { id: "anthropic/claude-opus-4-5", label: "Claude Opus 4.5 (latest)" },
429
+ { id: "anthropic/claude-opus-4-5-20251101", label: "Claude Opus 4.5" },
430
+ { id: "anthropic/claude-opus-4-6", label: "Claude Opus 4.6" },
431
+ { id: "anthropic/claude-opus-4-7", label: "Claude Opus 4.7" },
432
+ { id: "anthropic/claude-sonnet-4-0", label: "Claude Sonnet 4 (latest)" },
433
+ { id: "anthropic/claude-sonnet-4-20250514", label: "Claude Sonnet 4" },
434
+ { id: "anthropic/claude-sonnet-4-5", label: "Claude Sonnet 4.5 (latest)" },
435
+ { id: "anthropic/claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5" },
436
+ { id: "anthropic/claude-sonnet-4-6", label: "Claude Sonnet 4.6" }
437
+ ],
438
+ "google": [
439
+ { 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
+ { id: "google/gemini-3.1-pro-preview-customtools", label: "Gemini 3.1 Pro Preview Custom Tools" },
450
+ { id: "google/gemini-3.5-flash", label: "Gemini 3.5 Flash" },
451
+ { 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" }
457
+ ],
458
+ "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
+ { id: "xai/grok-4.20-0309-non-reasoning", label: "Grok 4.20 (Non-Reasoning)" },
463
+ { id: "xai/grok-4.3", label: "Grok 4.3" },
464
+ { id: "xai/grok-build-0.1", label: "Grok Build 0.1" },
465
+ { id: "xai/grok-code-fast-1", label: "Grok Code Fast 1" }
466
+ ],
467
+ "xiaomi": [
468
+ { 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" },
471
+ { id: "xiaomi/mimo-v2-pro", label: "MiMo-V2-Pro" },
472
+ { id: "xiaomi/mimo-v2.5", label: "MiMo-V2.5" },
473
+ { id: "xiaomi/mimo-v2.5-pro-ultraspeed", label: "MiMo-V2.5-Pro-UltraSpeed" }
474
+ ]
475
+ };
476
+
14
477
  // ../shared/src/generated/runtimeProviderDisplayNames.ts
15
478
  var RUNTIME_PROVIDER_DISPLAY_NAMES = {
16
479
  "anthropic": "Anthropic",
17
480
  "deepseek": "DeepSeek",
18
481
  "fusecode": "FuseCode",
19
- "google": "Google",
482
+ "google": "Google Gemini",
483
+ "kimi-coding": "Kimi For Coding",
484
+ "minimax": "MiniMax",
485
+ "minimax-cn": "MiniMax (China)",
486
+ "moonshotai": "Moonshot AI",
487
+ "moonshotai-cn": "Moonshot AI (China)",
20
488
  "openai": "OpenAI",
21
- "opencode": "OpenCode",
489
+ "opencode": "OpenCode Zen",
22
490
  "opencode-go": "OpenCode Go",
23
- "openrouter": "OpenRouter"
491
+ "openrouter": "OpenRouter",
492
+ "xai": "xAI",
493
+ "xiaomi": "Xiaomi MiMo",
494
+ "zai": "ZAI",
495
+ "zai-coding-cn": "ZAI Coding Plan (China)"
24
496
  };
25
497
 
26
498
  // ../shared/src/runtimeProviderDisplay.ts
@@ -63,6 +535,7 @@ function formatRuntimeProviderLabelToken(token) {
63
535
  nemotron: "Nemotron",
64
536
  omni: "Omni",
65
537
  opus: "Opus",
538
+ openai: "OpenAI",
66
539
  pro: "Pro",
67
540
  sonnet: "Sonnet",
68
541
  super: "Super"
@@ -77,6 +550,187 @@ function formatRuntimeProviderLabelToken(token) {
77
550
  return normalized.charAt(0).toUpperCase() + normalized.slice(1);
78
551
  }
79
552
 
553
+ // ../shared/src/runtimeConfigLegacy.ts
554
+ function isPlainRecord(value) {
555
+ return value !== null && typeof value === "object" && !Array.isArray(value);
556
+ }
557
+ function whitelistRecord(record, knownFields) {
558
+ const known = new Set(knownFields);
559
+ const value = {};
560
+ let droppedCount = 0;
561
+ for (const [key, fieldValue] of Object.entries(record)) {
562
+ if (known.has(key)) {
563
+ value[key] = fieldValue;
564
+ } else {
565
+ droppedCount += 1;
566
+ }
567
+ }
568
+ return { value, droppedCount };
569
+ }
570
+ function sanitizeStoredRuntimeConfig(record, deps) {
571
+ const topLevel = whitelistRecord(record, deps.runtimeConfigFields);
572
+ const value = { ...topLevel.value };
573
+ let droppedCount = topLevel.droppedCount;
574
+ const runtime = typeof value.runtime === "string" ? value.runtime : void 0;
575
+ if (isPlainRecord(value.model)) {
576
+ const model = whitelistRecord(value.model, deps.modelConfigFields);
577
+ value.model = model.value;
578
+ droppedCount += model.droppedCount;
579
+ }
580
+ if (isPlainRecord(value.mode)) {
581
+ const mode = whitelistRecord(value.mode, deps.modeConfigFields);
582
+ value.mode = mode.value;
583
+ droppedCount += mode.droppedCount;
584
+ }
585
+ if (isPlainRecord(value.provider)) {
586
+ const provider = whitelistRecord(value.provider, deps.providerKnownFieldsFor(runtime, value.provider));
587
+ value.provider = provider.value;
588
+ droppedCount += provider.droppedCount;
589
+ }
590
+ return { value, droppedCount };
591
+ }
592
+ function normalizeEnvVars(envVars) {
593
+ if (!isPlainRecord(envVars)) return null;
594
+ const normalized = {};
595
+ for (const [key, value] of Object.entries(envVars)) {
596
+ if (typeof key === "string" && typeof value === "string") {
597
+ normalized[key] = value;
598
+ }
599
+ }
600
+ return Object.keys(normalized).length > 0 ? normalized : null;
601
+ }
602
+ function isPresetRuntimeModel(runtimeModels, runtime, model) {
603
+ return (runtimeModels[runtime] ?? []).some((candidate) => candidate.id === model);
604
+ }
605
+ function hasMapKey(map, key) {
606
+ return Object.prototype.hasOwnProperty.call(map, key);
607
+ }
608
+ function modelConfigFromLegacy(runtimeModels, runtime, model) {
609
+ return isPresetRuntimeModel(runtimeModels, runtime, model) ? { kind: "preset", id: model } : { kind: "custom", name: model };
610
+ }
611
+ function parseProviderConfig(runtime, value, builtinProviderEnvKeys, builtinGatewayProviderEnvKeys, piBuiltinProviderEnvKeys, legacyApiUrl, legacyApiKey) {
612
+ if (runtime === "builtin") {
613
+ const providerId = isPlainRecord(value) && typeof value.providerId === "string" ? value.providerId.trim() : "";
614
+ if (value && isPlainRecord(value) && (value.kind === "preset" || value.kind === "managed") && providerId && typeof value.apiKey === "string" && value.apiKey.trim() && hasMapKey(builtinProviderEnvKeys, providerId)) {
615
+ return { kind: "preset", providerId, apiKey: value.apiKey.trim() };
616
+ }
617
+ if (value && isPlainRecord(value) && value.kind === "gateway" && providerId && typeof value.baseUrl === "string" && value.baseUrl.trim() && typeof value.apiKey === "string" && value.apiKey.trim() && hasMapKey(builtinGatewayProviderEnvKeys, providerId)) {
618
+ return { kind: "gateway", providerId, baseUrl: value.baseUrl.trim(), apiKey: value.apiKey.trim() };
619
+ }
620
+ return void 0;
621
+ }
622
+ if (runtime === "claude") {
623
+ if (!isPlainRecord(value)) return { kind: "default" };
624
+ if (value.kind === "custom" && typeof value.apiUrl === "string" && value.apiUrl.trim() && typeof value.apiKey === "string" && value.apiKey.trim()) {
625
+ return { kind: "custom", apiUrl: value.apiUrl.trim(), apiKey: value.apiKey.trim() };
626
+ }
627
+ if (value.kind === "custom" && legacyApiUrl?.trim() && legacyApiKey?.trim()) {
628
+ return { kind: "custom", apiUrl: legacyApiUrl.trim(), apiKey: legacyApiKey.trim() };
629
+ }
630
+ return { kind: "default" };
631
+ }
632
+ if (runtime === "pi") {
633
+ if (!isPlainRecord(value)) return { kind: "default" };
634
+ if (value.kind === "pi-builtin" && typeof value.providerId === "string" && value.providerId.trim() && typeof value.apiKey === "string" && value.apiKey.trim() && Object.prototype.hasOwnProperty.call(piBuiltinProviderEnvKeys, value.providerId.trim())) {
635
+ return { kind: "pi-builtin", providerId: value.providerId.trim(), apiKey: value.apiKey.trim() };
636
+ }
637
+ return { kind: "default" };
638
+ }
639
+ return void 0;
640
+ }
641
+ function parseModelConfig(runtimeModels, runtime, value, fallback, usesLegacyClaudeCustomProvider, legacyCustomModel) {
642
+ if (!isPlainRecord(value)) return modelConfigFromLegacy(runtimeModels, runtime, fallback);
643
+ if (value.kind === "custom" && typeof value.name === "string" && value.name.trim()) {
644
+ return { kind: "custom", name: value.name.trim() };
645
+ }
646
+ if (value.kind === "preset" && typeof value.id === "string" && value.id.trim() && isPresetRuntimeModel(runtimeModels, runtime, value.id.trim())) {
647
+ return { kind: "preset", id: value.id.trim() };
648
+ }
649
+ if (usesLegacyClaudeCustomProvider && runtime === "claude" && legacyCustomModel?.trim()) {
650
+ return { kind: "custom", name: legacyCustomModel.trim() };
651
+ }
652
+ return modelConfigFromLegacy(runtimeModels, runtime, fallback);
653
+ }
654
+ function parseModeConfig(value) {
655
+ if (!isPlainRecord(value)) return { kind: "default" };
656
+ if (value.kind === "fast") return { kind: "fast" };
657
+ return { kind: "default" };
658
+ }
659
+ function parseCommandConfig(runtime, value) {
660
+ if (runtime !== "claude" || typeof value !== "string") return void 0;
661
+ const command = value.trim();
662
+ return command ? command : void 0;
663
+ }
664
+ function providerKind(config) {
665
+ return config.provider?.kind ?? "none";
666
+ }
667
+ function classifyBuiltInGatewayBaseUrlHost(baseUrl) {
668
+ let hostname = "";
669
+ try {
670
+ hostname = new URL(baseUrl).hostname.toLowerCase();
671
+ } catch {
672
+ return "public";
673
+ }
674
+ if (hostname === "localhost" || hostname === "::1" || hostname === "[::1]" || hostname.startsWith("127.")) return "localhost";
675
+ const ipv4 = hostname.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
676
+ if (ipv4) {
677
+ const [a, b] = ipv4.slice(1).map((part) => Number(part));
678
+ if (a === 10 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 169 && b === 254) return "private";
679
+ }
680
+ if (hostname === "0.0.0.0" || hostname === "::" || hostname.startsWith("fc") || hostname.startsWith("fd") || hostname.startsWith("fe80:")) return "private";
681
+ return "public";
682
+ }
683
+ function builtInSelectionTraceAttrs(config) {
684
+ if (config.runtime !== "builtin") return {};
685
+ return {
686
+ provider_id: config.provider.providerId,
687
+ model_kind: config.model.kind,
688
+ ...config.model.kind === "preset" ? { model_id: config.model.id } : {},
689
+ ...config.provider.kind === "gateway" ? {
690
+ base_url_present: true,
691
+ base_url_host_class: classifyBuiltInGatewayBaseUrlHost(config.provider.baseUrl)
692
+ } : {}
693
+ };
694
+ }
695
+ function hydrateLegacyRuntimeConfigWithTrace(input, deps) {
696
+ const stored = isPlainRecord(input.runtimeConfig) && input.runtimeConfig.version === deps.runtimeConfigVersion ? input.runtimeConfig : null;
697
+ const sanitized = stored ? sanitizeStoredRuntimeConfig(stored, deps) : null;
698
+ const storedConfig = sanitized?.value ?? null;
699
+ const runtime = typeof stored?.runtime === "string" && stored.runtime.trim() || typeof input.runtime === "string" && input.runtime.trim() || "claude";
700
+ const fallbackModel = typeof input.model === "string" && input.model.trim() || deps.getDefaultModel(runtime);
701
+ const legacyEnvVars = normalizeEnvVars(input.envVars);
702
+ const storedEnvVars = normalizeEnvVars(storedConfig?.envVars);
703
+ const legacyClaudeApiUrl = runtime === "claude" ? legacyEnvVars?.ANTHROPIC_BASE_URL : void 0;
704
+ const legacyClaudeApiKey = runtime === "claude" ? legacyEnvVars?.ANTHROPIC_API_KEY : void 0;
705
+ const legacyClaudeCustomModel = runtime === "claude" ? legacyEnvVars?.ANTHROPIC_CUSTOM_MODEL_OPTION : void 0;
706
+ const provider = stored ? parseProviderConfig(runtime, storedConfig?.provider, deps.builtinProviderEnvKeys, deps.builtinGatewayProviderEnvKeys, deps.piBuiltinProviderEnvKeys, legacyClaudeApiUrl, legacyClaudeApiKey) : runtime === "claude" && legacyClaudeApiUrl && legacyClaudeApiKey ? { kind: "custom", apiUrl: legacyClaudeApiUrl, apiKey: legacyClaudeApiKey } : runtime === "claude" ? { kind: "default" } : void 0;
707
+ const usesLegacyClaudeCustomProvider = runtime === "claude" && provider?.kind === "custom";
708
+ const command = stored ? parseCommandConfig(runtime, storedConfig?.command) : void 0;
709
+ const config = deps.composeRuntimeConfig({
710
+ runtime,
711
+ provider,
712
+ model: stored ? parseModelConfig(deps.runtimeModels, runtime, storedConfig?.model, fallbackModel, usesLegacyClaudeCustomProvider, legacyClaudeCustomModel) : modelConfigFromLegacy(deps.runtimeModels, runtime, fallbackModel),
713
+ mode: stored ? parseModeConfig(storedConfig?.mode) : { kind: "default" },
714
+ reasoningEffort: storedConfig?.reasoningEffort ?? input.reasoningEffort ?? null,
715
+ // Runtime-owned env vars are legacy launch mirrors for provider/model
716
+ // settings. Strip them from user envVars during hydration so the canonical
717
+ // RuntimeConfig provider/model arms remain the only source for generated
718
+ // launch env.
719
+ envVars: deps.stripControlledRuntimeEnvVars(runtime, stored ? storedEnvVars : legacyEnvVars),
720
+ command
721
+ });
722
+ return {
723
+ config,
724
+ trace: {
725
+ outcome: sanitized && sanitized.droppedCount > 0 ? "legacy_sanitized" : "accepted",
726
+ runtime: config.runtime,
727
+ provider_kind: providerKind(config),
728
+ ...builtInSelectionTraceAttrs(config),
729
+ ...sanitized && sanitized.droppedCount > 0 ? { unknown_fields_dropped_count: sanitized.droppedCount } : {}
730
+ }
731
+ };
732
+ }
733
+
80
734
  // ../shared/src/slockRefs.ts
81
735
  var SLOCK_REF_CHANNEL_NAME_PATTERN = String.raw`[\p{L}\p{N}_-]+`;
82
736
  var SLOCK_REF_USER_NAME_PATTERN = SLOCK_REF_CHANNEL_NAME_PATTERN;
@@ -136,6 +790,7 @@ function projectApmHeldFreshnessEnvelope(input) {
136
790
  outcome: "held",
137
791
  subtype: "freshness",
138
792
  reason: "newer_messages_available",
793
+ decision: input.decision ?? "local_hold",
139
794
  producerFactId: input.producerFactId,
140
795
  available_actions: apmHeldFreshnessAvailableActions(input.action),
141
796
  heldMessages: input.heldMessages,
@@ -154,10 +809,16 @@ function projectApmHeldFreshnessEnvelope(input) {
154
809
  }
155
810
  function projectApmHeldFreshnessActivity(input) {
156
811
  const title = input.action === "send" ? "Send held by freshness check" : input.action === "task_claim" ? "Task claim held by freshness check" : "Task update held by freshness check";
812
+ const messageNoun = input.messageCount === 1 ? "message" : "messages";
813
+ const countLine = input.decision === "syncing_hold" ? `unreviewed synced context for this target: ${input.messageCount} ${messageNoun}` : `new messages: ${input.messageCount} newer ${messageNoun}`;
814
+ const decisionLines = input.decision === "syncing_hold" ? [
815
+ "reason: this target's latest synced context was not yet in your reviewed context",
816
+ input.action === "send" ? "action: review the synced context before sending" : "action: review the synced context, then retry this action"
817
+ ] : ["decision: local hold; review the newer context before retrying"];
157
818
  const text = [
158
819
  input.target ? `target: ${input.target}` : null,
159
- `new messages: ${input.messageCount} newer message${input.messageCount === 1 ? "" : "s"}`,
160
- `decision: ${input.decision === "syncing_hold" ? "syncing hold" : "local hold"}; review the newer context before retrying`
820
+ countLine,
821
+ ...decisionLines
161
822
  ].filter((line) => Boolean(line)).join("\n");
162
823
  return {
163
824
  clauseId: "SMR-006",
@@ -1037,6 +1698,10 @@ function summarizeToolInput(toolName, input) {
1037
1698
  // ../shared/src/attachmentPreview.ts
1038
1699
  var CSV_PREVIEW_MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
1039
1700
 
1701
+ // ../shared/src/brandedIds.ts
1702
+ var asMessageId = (id) => id;
1703
+ var asChannelId = (id) => id;
1704
+
1040
1705
  // ../shared/src/actionCards.ts
1041
1706
  import { z } from "zod";
1042
1707
  var uuidSchema = z.uuid();
@@ -1137,6 +1802,885 @@ var actionCardActionSchema = z.discriminatedUnion("type", [
1137
1802
  integrationUpdateAppRegistrationOperationSchema
1138
1803
  ]);
1139
1804
 
1805
+ // ../shared/src/agentApiContract.ts
1806
+ import { z as z2 } from "zod";
1807
+ var AGENT_API_BASE_PATH = "/internal/agent-api";
1808
+ var optionalStringSchema = z2.string().trim().optional();
1809
+ var optionalStringArraySchema = z2.array(z2.string().trim().min(1)).optional();
1810
+ var optionalBooleanSchema = z2.boolean().optional();
1811
+ var optionalNumberSchema = z2.number().finite().optional();
1812
+ var nullableStringSchema = z2.string().nullable();
1813
+ var nullableNumberSchema = z2.number().finite().nullable();
1814
+ var optionalIsoTimestampSchema = z2.string().datetime().optional();
1815
+ var agentStatusSchema = z2.enum(["active", "inactive", "stopped"]);
1816
+ var reminderStatusSchema = z2.enum(["scheduled", "fired", "canceled"]);
1817
+ var reminderEventTypeSchema = z2.enum(["scheduled", "fired", "snoozed", "updated", "canceled"]);
1818
+ var reasoningEffortSchema = z2.enum(["low", "medium", "high", "xhigh"]);
1819
+ var profileVisibilityMembershipStatusSchema = z2.enum(["active", "removed"]);
1820
+ var passthroughObject = (shape) => z2.object(shape).passthrough();
1821
+ var taskStatusSchema = z2.enum(["todo", "in_progress", "in_review", "done", "closed"]);
1822
+ var agentApiEventsQuerySchema = passthroughObject({
1823
+ since: optionalStringSchema,
1824
+ limit: optionalStringSchema
1825
+ });
1826
+ var agentApiHistoryQuerySchema = passthroughObject({
1827
+ channel: z2.string().trim().min(1),
1828
+ before: optionalStringSchema,
1829
+ after: optionalStringSchema,
1830
+ around: optionalStringSchema,
1831
+ limit: optionalStringSchema
1832
+ });
1833
+ var agentApiMessageSearchQuerySchema = passthroughObject({
1834
+ q: optionalStringSchema,
1835
+ channel: optionalStringSchema,
1836
+ sender: optionalStringSchema,
1837
+ senderId: optionalStringSchema,
1838
+ sort: z2.enum(["relevance", "recent"]).optional(),
1839
+ before: optionalStringSchema,
1840
+ after: optionalStringSchema,
1841
+ limit: optionalStringSchema,
1842
+ offset: optionalStringSchema
1843
+ });
1844
+ var agentApiSendBodySchema = passthroughObject({
1845
+ target: z2.string().optional(),
1846
+ content: z2.string().optional(),
1847
+ attachmentIds: optionalStringArraySchema,
1848
+ idempotencyKey: optionalStringSchema,
1849
+ continue: optionalBooleanSchema,
1850
+ sendDraft: optionalBooleanSchema,
1851
+ continueAnyway: optionalBooleanSchema,
1852
+ draftReholdCount: optionalNumberSchema,
1853
+ draftReplacedExisting: optionalBooleanSchema,
1854
+ seenUpToSeq: optionalNumberSchema
1855
+ });
1856
+ var agentApiMessageResolveParamsSchema = passthroughObject({
1857
+ msgId: z2.string().trim().min(1).transform(asMessageId)
1858
+ });
1859
+ var agentApiMessageReactionParamsSchema = passthroughObject({
1860
+ msgId: z2.string().trim().min(1).transform(asMessageId)
1861
+ });
1862
+ var agentApiMessageReactionBodySchema = passthroughObject({
1863
+ emoji: z2.string().trim().min(1).max(16).refine((value) => !/\s/.test(value), {
1864
+ message: "A single reaction emoji is required"
1865
+ })
1866
+ });
1867
+ var agentApiChannelMembershipParamsSchema = passthroughObject({
1868
+ channelId: z2.string().trim().min(1).transform(asChannelId)
1869
+ });
1870
+ var agentApiChannelMembersQuerySchema = passthroughObject({
1871
+ channel: z2.string().trim().min(1)
1872
+ });
1873
+ var agentApiResolveChannelBodySchema = passthroughObject({
1874
+ target: z2.string().trim().min(1)
1875
+ });
1876
+ var agentApiResolveChannelResponseSchema = passthroughObject({
1877
+ channelId: z2.string().trim().min(1)
1878
+ });
1879
+ var agentApiThreadUnfollowBodySchema = passthroughObject({
1880
+ thread: z2.string().trim().min(1)
1881
+ });
1882
+ var agentApiTaskClaimBodySchema = passthroughObject({
1883
+ channel: z2.string().trim().min(1),
1884
+ task_numbers: z2.array(z2.number().int().positive()).optional(),
1885
+ message_ids: optionalStringArraySchema
1886
+ });
1887
+ var agentApiTaskListQuerySchema = passthroughObject({
1888
+ channel: z2.string().trim().min(1),
1889
+ status: z2.union([taskStatusSchema, z2.literal("all")]).optional()
1890
+ });
1891
+ var agentApiTaskCreateBodySchema = passthroughObject({
1892
+ channel: z2.string().trim().min(1),
1893
+ tasks: z2.array(passthroughObject({
1894
+ title: z2.string().trim().min(1)
1895
+ })).min(1)
1896
+ });
1897
+ var agentApiTaskUnclaimBodySchema = passthroughObject({
1898
+ channel: z2.string().trim().min(1),
1899
+ task_number: z2.number().int().positive()
1900
+ });
1901
+ var agentApiTaskUpdateStatusBodySchema = passthroughObject({
1902
+ channel: z2.string().trim().min(1),
1903
+ task_number: z2.number().int().positive(),
1904
+ status: taskStatusSchema
1905
+ });
1906
+ var agentApiReminderListQuerySchema = passthroughObject({
1907
+ status: optionalStringSchema,
1908
+ all: optionalStringSchema
1909
+ });
1910
+ var agentApiReminderParamsSchema = passthroughObject({
1911
+ reminderId: z2.string().trim().min(1)
1912
+ });
1913
+ var agentApiReminderScheduleBodySchema = passthroughObject({
1914
+ title: z2.string(),
1915
+ fireAt: optionalStringSchema,
1916
+ delaySeconds: optionalNumberSchema,
1917
+ msgId: z2.string().nullable().optional(),
1918
+ payload: z2.unknown().optional(),
1919
+ repeat: optionalStringSchema,
1920
+ tz: optionalStringSchema,
1921
+ channel: optionalStringSchema
1922
+ });
1923
+ var agentApiReminderSnoozeBodySchema = passthroughObject({
1924
+ delaySeconds: z2.number().finite()
1925
+ });
1926
+ var agentApiReminderUpdateBodySchema = passthroughObject({
1927
+ fireAt: optionalStringSchema,
1928
+ delaySeconds: optionalNumberSchema,
1929
+ repeat: optionalStringSchema,
1930
+ title: optionalStringSchema,
1931
+ tz: optionalStringSchema
1932
+ });
1933
+ var agentApiProfileShowQuerySchema = passthroughObject({
1934
+ target: optionalStringSchema
1935
+ });
1936
+ var agentApiProfileUpdateBodySchema = passthroughObject({
1937
+ avatarUrl: optionalStringSchema,
1938
+ displayName: optionalStringSchema,
1939
+ description: optionalStringSchema
1940
+ });
1941
+ var agentApiProfileCreatedAgentSchema = passthroughObject({
1942
+ id: z2.string(),
1943
+ name: z2.string(),
1944
+ displayName: nullableStringSchema,
1945
+ avatarUrl: nullableStringSchema,
1946
+ runtime: z2.string(),
1947
+ status: agentStatusSchema
1948
+ });
1949
+ var agentApiProfileCreatorSchema = z2.union([
1950
+ passthroughObject({
1951
+ type: z2.literal("human"),
1952
+ id: z2.string(),
1953
+ name: z2.string(),
1954
+ displayName: nullableStringSchema,
1955
+ avatarUrl: nullableStringSchema,
1956
+ gravatarHash: z2.string()
1957
+ }),
1958
+ passthroughObject({
1959
+ type: z2.literal("agent"),
1960
+ id: z2.string(),
1961
+ name: z2.string(),
1962
+ displayName: nullableStringSchema,
1963
+ avatarUrl: nullableStringSchema,
1964
+ deletedAt: nullableStringSchema
1965
+ })
1966
+ ]);
1967
+ var agentApiProfileViewSchema = z2.discriminatedUnion("kind", [
1968
+ passthroughObject({
1969
+ kind: z2.literal("human"),
1970
+ id: z2.string(),
1971
+ isSelf: z2.boolean(),
1972
+ name: z2.string(),
1973
+ displayName: nullableStringSchema,
1974
+ description: nullableStringSchema,
1975
+ avatarUrl: nullableStringSchema,
1976
+ email: nullableStringSchema,
1977
+ role: z2.enum(["owner", "admin", "member"]).nullable(),
1978
+ joinedAt: nullableStringSchema,
1979
+ membershipStatus: profileVisibilityMembershipStatusSchema,
1980
+ createdAgents: z2.array(agentApiProfileCreatedAgentSchema)
1981
+ }),
1982
+ passthroughObject({
1983
+ kind: z2.literal("agent"),
1984
+ id: z2.string(),
1985
+ isSelf: z2.boolean(),
1986
+ name: z2.string(),
1987
+ displayName: nullableStringSchema,
1988
+ description: nullableStringSchema,
1989
+ avatarUrl: nullableStringSchema,
1990
+ status: agentStatusSchema,
1991
+ serverRole: z2.enum(["owner", "admin", "member"]).nullable(),
1992
+ runtime: z2.string(),
1993
+ model: z2.string(),
1994
+ reasoningEffort: reasoningEffortSchema.nullable(),
1995
+ executionMode: nullableStringSchema,
1996
+ computerId: nullableStringSchema,
1997
+ computerName: nullableStringSchema,
1998
+ computerHostname: nullableStringSchema,
1999
+ daemonVersion: nullableStringSchema,
2000
+ creator: agentApiProfileCreatorSchema.nullable(),
2001
+ createdAgents: z2.array(agentApiProfileCreatedAgentSchema),
2002
+ createdAt: z2.string(),
2003
+ deletedAt: nullableStringSchema
2004
+ })
2005
+ ]);
2006
+ var agentApiIntegrationLoginBodySchema = passthroughObject({
2007
+ service: z2.string().trim().min(1),
2008
+ scopes: optionalStringArraySchema,
2009
+ target: optionalStringSchema
2010
+ });
2011
+ var agentApiIntegrationAppPrepareBodySchema = passthroughObject({
2012
+ mode: z2.enum(["register", "update"]),
2013
+ target: z2.string().trim().min(1),
2014
+ clientKey: z2.string().trim().min(1),
2015
+ name: optionalStringSchema,
2016
+ description: optionalStringSchema,
2017
+ homepageUrl: optionalStringSchema,
2018
+ returnUrl: optionalStringSchema,
2019
+ agentManifestUrl: optionalStringSchema,
2020
+ scopes: optionalStringArraySchema,
2021
+ unsafeDemoUrlOverride: optionalBooleanSchema,
2022
+ draftHint: optionalStringSchema
2023
+ });
2024
+ var agentApiActionPrepareBodySchema = passthroughObject({
2025
+ target: z2.string().trim().min(1),
2026
+ action: actionCardActionSchema
2027
+ });
2028
+ var agentApiServerInfoResponseSchema = passthroughObject({
2029
+ runtimeContext: passthroughObject({
2030
+ agentId: z2.string(),
2031
+ serverId: z2.string(),
2032
+ machineId: z2.string().nullable().optional(),
2033
+ machineName: z2.string().nullable().optional(),
2034
+ machineHostname: z2.string().nullable().optional(),
2035
+ machineOs: z2.string().nullable().optional(),
2036
+ daemonVersion: z2.string().nullable().optional(),
2037
+ workspacePath: z2.string().nullable().optional()
2038
+ }),
2039
+ serverRole: z2.string().nullable().optional(),
2040
+ serverCapabilities: passthroughObject({}).optional(),
2041
+ channels: z2.array(passthroughObject({
2042
+ id: z2.string().transform(asChannelId),
2043
+ name: z2.string(),
2044
+ joined: z2.boolean()
2045
+ })),
2046
+ agents: z2.array(passthroughObject({
2047
+ name: z2.string()
2048
+ })),
2049
+ humans: z2.array(passthroughObject({
2050
+ name: z2.string()
2051
+ }))
2052
+ });
2053
+ var agentApiMentionActionsPendingQuerySchema = passthroughObject({
2054
+ limit: optionalStringSchema
2055
+ });
2056
+ var agentApiMentionActionEnvelopeSchema = passthroughObject({
2057
+ resolutionId: z2.string()
2058
+ });
2059
+ var agentApiMentionActionsPendingResponseSchema = passthroughObject({
2060
+ pendingMentionActions: z2.array(agentApiMentionActionEnvelopeSchema),
2061
+ has_more: z2.boolean().optional()
2062
+ });
2063
+ var agentApiMentionActionsExecuteBodySchema = passthroughObject({
2064
+ action: z2.enum(["notify", "add"]),
2065
+ resolutionIds: optionalStringArraySchema,
2066
+ ids: optionalStringArraySchema
2067
+ });
2068
+ var agentApiMentionActionsExecuteResponseSchema = passthroughObject({
2069
+ ok: z2.literal(true),
2070
+ action: z2.enum(["notify", "add"]),
2071
+ results: z2.array(agentApiMentionActionEnvelopeSchema)
2072
+ });
2073
+ var agentApiIntegrationServiceSchema = passthroughObject({
2074
+ id: z2.string(),
2075
+ clientId: z2.string(),
2076
+ appType: z2.enum(["server_local", "slock_builtin", "third_party_global"]).optional(),
2077
+ name: z2.string(),
2078
+ description: nullableStringSchema,
2079
+ homepageUrl: nullableStringSchema,
2080
+ returnUrl: nullableStringSchema,
2081
+ agentManifestUrl: nullableStringSchema,
2082
+ agentManifestUrlSource: z2.enum(["explicit", "well_known"]).nullable().optional(),
2083
+ createdAt: z2.string(),
2084
+ updatedAt: z2.string()
2085
+ });
2086
+ var agentApiActiveIntegrationLoginSchema = passthroughObject({
2087
+ id: z2.string(),
2088
+ serviceId: z2.string(),
2089
+ clientId: z2.string(),
2090
+ appType: z2.enum(["server_local", "slock_builtin", "third_party_global"]).optional(),
2091
+ name: z2.string(),
2092
+ description: nullableStringSchema,
2093
+ homepageUrl: nullableStringSchema,
2094
+ returnUrl: nullableStringSchema,
2095
+ agentManifestUrl: nullableStringSchema,
2096
+ agentManifestUrlSource: z2.enum(["explicit", "well_known"]).nullable().optional(),
2097
+ scopes: z2.array(z2.string()),
2098
+ createdAt: z2.string()
2099
+ });
2100
+ var agentApiIntegrationListResponseSchema = passthroughObject({
2101
+ services: z2.array(agentApiIntegrationServiceSchema),
2102
+ activeLogins: z2.array(agentApiActiveIntegrationLoginSchema)
2103
+ });
2104
+ var agentApiIntegrationLoginResponseSchema = passthroughObject({
2105
+ status: z2.enum(["logged_in", "already_logged_in", "approval_required"]),
2106
+ service: agentApiIntegrationServiceSchema,
2107
+ scopes: z2.array(z2.string()),
2108
+ requestId: z2.string(),
2109
+ approval: passthroughObject({
2110
+ requestId: z2.string(),
2111
+ target: nullableStringSchema,
2112
+ actionCardMessageId: nullableStringSchema
2113
+ }).optional()
2114
+ });
2115
+ var agentApiIntegrationAppPrepareResponseSchema = passthroughObject({
2116
+ status: z2.literal("prepared"),
2117
+ mode: z2.enum(["register", "update"]),
2118
+ target: z2.string(),
2119
+ actionCardMessageId: z2.string(),
2120
+ action: z2.discriminatedUnion("type", [
2121
+ integrationRegisterAppOperationSchema,
2122
+ integrationUpdateAppRegistrationOperationSchema
2123
+ ])
2124
+ });
2125
+ var agentApiAttachmentEnvelopeSchema = passthroughObject({
2126
+ id: z2.string(),
2127
+ filename: z2.string()
2128
+ });
2129
+ var agentApiAttachmentUploadResponseSchema = passthroughObject({
2130
+ id: z2.string().trim().min(1),
2131
+ filename: z2.string(),
2132
+ mimeType: nullableStringSchema,
2133
+ sizeBytes: z2.number().int().nonnegative(),
2134
+ thumbnailUrl: nullableStringSchema
2135
+ });
2136
+ var agentApiMessageEnvelopeSchema = passthroughObject({
2137
+ seq: optionalNumberSchema,
2138
+ id: optionalStringSchema,
2139
+ message_id: optionalStringSchema,
2140
+ timestamp: optionalIsoTimestampSchema,
2141
+ createdAt: optionalIsoTimestampSchema,
2142
+ senderType: optionalStringSchema,
2143
+ sender_type: optionalStringSchema,
2144
+ senderName: optionalStringSchema,
2145
+ sender_name: optionalStringSchema,
2146
+ senderDescription: z2.string().nullable().optional(),
2147
+ sender_description: z2.string().nullable().optional(),
2148
+ channel_type: optionalStringSchema,
2149
+ channel_name: optionalStringSchema,
2150
+ parent_channel_type: optionalStringSchema,
2151
+ parent_channel_name: optionalStringSchema,
2152
+ content: optionalStringSchema,
2153
+ attachments: z2.array(agentApiAttachmentEnvelopeSchema).optional(),
2154
+ taskStatus: z2.string().nullable().optional(),
2155
+ task_status: z2.string().nullable().optional(),
2156
+ taskNumber: z2.number().int().positive().nullable().optional(),
2157
+ task_number: z2.number().int().positive().nullable().optional(),
2158
+ taskAssigneeId: z2.string().nullable().optional(),
2159
+ task_assignee_id: z2.string().nullable().optional(),
2160
+ taskAssigneeType: z2.string().nullable().optional(),
2161
+ task_assignee_type: z2.string().nullable().optional(),
2162
+ threadId: z2.string().nullable().optional(),
2163
+ replyCount: z2.number().int().nonnegative().nullable().optional()
2164
+ });
2165
+ var agentApiEventsResponseSchema = passthroughObject({
2166
+ events: z2.array(agentApiMessageEnvelopeSchema),
2167
+ last_seen_msgId: nullableStringSchema,
2168
+ last_seen_seq: nullableNumberSchema,
2169
+ reply_target: nullableStringSchema,
2170
+ pending_notice_ids: z2.array(z2.string()),
2171
+ wake_reason: z2.string().nullable(),
2172
+ has_more: z2.boolean()
2173
+ });
2174
+ var agentApiHistoryResponseSchema = passthroughObject({
2175
+ messages: z2.array(agentApiMessageEnvelopeSchema),
2176
+ has_more: z2.boolean(),
2177
+ has_older: z2.boolean(),
2178
+ has_newer: z2.boolean(),
2179
+ last_read_seq: nullableNumberSchema.optional()
2180
+ });
2181
+ var agentApiHeldFreshnessResponseSchema = passthroughObject({
2182
+ ok: z2.literal(true).optional(),
2183
+ state: z2.literal("held"),
2184
+ outcome: z2.literal("held").optional(),
2185
+ subtype: z2.literal("freshness").optional(),
2186
+ reason: z2.string().optional(),
2187
+ decision: z2.enum(["local_hold", "syncing_hold"]).optional(),
2188
+ producerFactId: optionalStringSchema,
2189
+ available_actions: z2.array(z2.string()).optional(),
2190
+ heldMessages: z2.array(agentApiMessageEnvelopeSchema).optional(),
2191
+ recentUnread: z2.array(agentApiMessageEnvelopeSchema).optional(),
2192
+ newMessageCount: optionalNumberSchema,
2193
+ shownMessageCount: optionalNumberSchema,
2194
+ omittedMessageCount: optionalNumberSchema,
2195
+ mentionAnnotation: passthroughObject({
2196
+ formalMentionCount: z2.number().finite()
2197
+ }).optional(),
2198
+ continueAnywaySuggested: optionalBooleanSchema,
2199
+ seenUpToSeq: optionalNumberSchema,
2200
+ seenUpToMessageId: nullableStringSchema.optional()
2201
+ });
2202
+ var agentApiSendSentResponseSchema = passthroughObject({
2203
+ ok: z2.literal(true),
2204
+ state: z2.literal("sent"),
2205
+ messageId: z2.string(),
2206
+ messageSeq: optionalNumberSchema,
2207
+ recentUnread: z2.array(agentApiMessageEnvelopeSchema).optional(),
2208
+ pendingMentionActions: z2.array(agentApiMessageEnvelopeSchema).optional()
2209
+ });
2210
+ var agentApiSendResponseSchema = z2.discriminatedUnion("state", [
2211
+ agentApiSendSentResponseSchema,
2212
+ agentApiHeldFreshnessResponseSchema
2213
+ ]);
2214
+ var agentApiMessageResolveResponseSchema = passthroughObject({
2215
+ message: agentApiMessageEnvelopeSchema
2216
+ });
2217
+ var agentApiOkResponseSchema = passthroughObject({
2218
+ ok: z2.literal(true)
2219
+ });
2220
+ var agentApiSearchResultSchema = passthroughObject({
2221
+ id: z2.string(),
2222
+ seq: z2.number().int().nonnegative(),
2223
+ channelId: z2.string(),
2224
+ threadId: z2.string().nullable(),
2225
+ parentMessageId: z2.string().nullable(),
2226
+ parentMessageContent: z2.string().nullable(),
2227
+ parentChannelId: z2.string(),
2228
+ parentChannelName: z2.string(),
2229
+ parentChannelType: z2.string(),
2230
+ parentChannelArchivedAt: nullableStringSchema,
2231
+ senderId: z2.string(),
2232
+ senderType: z2.string(),
2233
+ senderName: z2.string(),
2234
+ channelName: z2.string(),
2235
+ channelType: z2.string(),
2236
+ channelArchivedAt: nullableStringSchema,
2237
+ content: z2.string(),
2238
+ snippet: z2.string(),
2239
+ createdAt: z2.string().datetime()
2240
+ });
2241
+ var agentApiMessageSearchResponseSchema = passthroughObject({
2242
+ results: z2.array(agentApiSearchResultSchema),
2243
+ hasMore: z2.boolean()
2244
+ });
2245
+ var agentApiChannelMembersResponseSchema = passthroughObject({
2246
+ channel: passthroughObject({
2247
+ ref: z2.string(),
2248
+ type: z2.string()
2249
+ }),
2250
+ agents: z2.array(passthroughObject({
2251
+ name: z2.string(),
2252
+ status: optionalStringSchema
2253
+ })),
2254
+ humans: z2.array(passthroughObject({
2255
+ name: z2.string(),
2256
+ description: z2.string().nullable().optional(),
2257
+ role: optionalStringSchema
2258
+ }))
2259
+ });
2260
+ var agentApiTaskClaimResultSchema = passthroughObject({
2261
+ taskNumber: z2.number().int().positive().optional(),
2262
+ messageId: optionalStringSchema,
2263
+ success: z2.boolean(),
2264
+ reason: optionalStringSchema
2265
+ });
2266
+ var agentApiTaskClaimSuccessResponseSchema = passthroughObject({
2267
+ results: z2.array(agentApiTaskClaimResultSchema)
2268
+ });
2269
+ var agentApiTaskClaimResponseSchema = z2.union([
2270
+ agentApiTaskClaimSuccessResponseSchema,
2271
+ agentApiHeldFreshnessResponseSchema
2272
+ ]);
2273
+ var agentApiTaskEnvelopeSchema = passthroughObject({
2274
+ taskNumber: z2.number().int().positive().optional(),
2275
+ status: z2.string().optional(),
2276
+ title: optionalStringSchema,
2277
+ claimedByName: z2.string().nullable().optional(),
2278
+ createdByName: z2.string().nullable().optional(),
2279
+ messageId: z2.string().nullable().optional(),
2280
+ isLegacy: optionalBooleanSchema
2281
+ });
2282
+ var agentApiTaskListResponseSchema = passthroughObject({
2283
+ tasks: z2.array(agentApiTaskEnvelopeSchema)
2284
+ });
2285
+ var agentApiCreatedTaskEnvelopeSchema = passthroughObject({
2286
+ taskNumber: z2.number().int().positive(),
2287
+ messageId: z2.string(),
2288
+ title: z2.string()
2289
+ });
2290
+ var agentApiTaskCreateResponseSchema = passthroughObject({
2291
+ tasks: z2.array(agentApiCreatedTaskEnvelopeSchema)
2292
+ });
2293
+ var agentApiTaskUnclaimResponseSchema = passthroughObject({
2294
+ ok: z2.literal(true)
2295
+ });
2296
+ var agentApiTaskUpdateStatusSuccessResponseSchema = passthroughObject({
2297
+ ok: z2.literal(true)
2298
+ });
2299
+ var agentApiTaskUpdateStatusResponseSchema = z2.union([
2300
+ agentApiTaskUpdateStatusSuccessResponseSchema,
2301
+ agentApiHeldFreshnessResponseSchema
2302
+ ]);
2303
+ var agentApiActionPrepareResponseSchema = passthroughObject({
2304
+ messageId: z2.string(),
2305
+ metadata: passthroughObject({
2306
+ kind: z2.literal("action-card")
2307
+ })
2308
+ });
2309
+ var agentApiReminderRecurrenceSchema = z2.object({
2310
+ kind: z2.enum(["interval", "daily", "weekly", "unsupported"]),
2311
+ description: z2.string()
2312
+ });
2313
+ var agentApiReminderSummarySchema = z2.object({
2314
+ reminderId: z2.string(),
2315
+ ownerAgentId: z2.string(),
2316
+ title: z2.string(),
2317
+ fireAt: z2.string(),
2318
+ firedAt: nullableStringSchema.optional(),
2319
+ createdAt: z2.string(),
2320
+ status: reminderStatusSchema,
2321
+ msgRef: nullableStringSchema,
2322
+ msgPermalink: nullableStringSchema,
2323
+ recurrence: agentApiReminderRecurrenceSchema.nullable()
2324
+ });
2325
+ var agentApiReminderEventSummarySchema = z2.object({
2326
+ eventId: z2.string(),
2327
+ reminderId: z2.string(),
2328
+ eventType: reminderEventTypeSchema,
2329
+ actorType: z2.enum(["agent", "human", "system"]),
2330
+ actorId: nullableStringSchema,
2331
+ occurredAt: z2.string(),
2332
+ nextFireAt: nullableStringSchema,
2333
+ metadata: z2.record(z2.string(), z2.unknown()).nullable()
2334
+ });
2335
+ var agentApiReminderListResponseSchema = passthroughObject({
2336
+ reminders: z2.array(agentApiReminderSummarySchema)
2337
+ });
2338
+ var agentApiReminderResponseSchema = passthroughObject({
2339
+ reminder: agentApiReminderSummarySchema,
2340
+ warning: optionalStringSchema
2341
+ });
2342
+ var agentApiReminderLogResponseSchema = passthroughObject({
2343
+ events: z2.array(agentApiReminderEventSummarySchema)
2344
+ });
2345
+ function route(input) {
2346
+ return {
2347
+ ...input,
2348
+ fullPath: `${AGENT_API_BASE_PATH}${input.path}`
2349
+ };
2350
+ }
2351
+ var agentApiContract = {
2352
+ events: route({
2353
+ key: "events",
2354
+ method: "GET",
2355
+ path: "/events",
2356
+ client: { resource: "events", method: "get" },
2357
+ capability: "read",
2358
+ description: "Drain pending events for the bound agent credential.",
2359
+ request: { query: agentApiEventsQuerySchema },
2360
+ response: { body: agentApiEventsResponseSchema }
2361
+ }),
2362
+ historyRead: route({
2363
+ key: "historyRead",
2364
+ method: "GET",
2365
+ path: "/history",
2366
+ client: { resource: "history", method: "read" },
2367
+ capability: "read",
2368
+ description: "Read visible history for a channel, DM, or thread target.",
2369
+ request: { query: agentApiHistoryQuerySchema },
2370
+ response: { body: agentApiHistoryResponseSchema }
2371
+ }),
2372
+ messageSend: route({
2373
+ key: "messageSend",
2374
+ method: "POST",
2375
+ path: "/send",
2376
+ client: { resource: "messages", method: "send" },
2377
+ capability: "send",
2378
+ description: "Send a message as the bound agent credential.",
2379
+ request: { body: agentApiSendBodySchema },
2380
+ response: { body: agentApiSendResponseSchema }
2381
+ }),
2382
+ messageResolve: route({
2383
+ key: "messageResolve",
2384
+ method: "GET",
2385
+ path: "/messages/:msgId/resolve",
2386
+ client: { resource: "messages", method: "resolve" },
2387
+ capability: "read",
2388
+ description: "Resolve a message id exactly and return the canonical visible message.",
2389
+ request: { params: agentApiMessageResolveParamsSchema },
2390
+ response: { body: agentApiMessageResolveResponseSchema }
2391
+ }),
2392
+ messageSearch: route({
2393
+ key: "messageSearch",
2394
+ method: "GET",
2395
+ path: "/search",
2396
+ client: { resource: "messages", method: "search" },
2397
+ capability: "read",
2398
+ description: "Search messages visible to the bound agent credential.",
2399
+ request: { query: agentApiMessageSearchQuerySchema },
2400
+ response: { body: agentApiMessageSearchResponseSchema }
2401
+ }),
2402
+ messageReactionAdd: route({
2403
+ key: "messageReactionAdd",
2404
+ method: "POST",
2405
+ path: "/messages/:msgId/reactions",
2406
+ client: { resource: "messages", method: "addReaction" },
2407
+ capability: "reactions",
2408
+ description: "Add a reaction to a visible message as the bound agent credential.",
2409
+ request: { params: agentApiMessageReactionParamsSchema, body: agentApiMessageReactionBodySchema },
2410
+ response: { body: agentApiMessageEnvelopeSchema }
2411
+ }),
2412
+ messageReactionRemove: route({
2413
+ key: "messageReactionRemove",
2414
+ method: "DELETE",
2415
+ path: "/messages/:msgId/reactions",
2416
+ client: { resource: "messages", method: "removeReaction" },
2417
+ capability: "reactions",
2418
+ description: "Remove a reaction from a visible message as the bound agent credential.",
2419
+ request: { params: agentApiMessageReactionParamsSchema, body: agentApiMessageReactionBodySchema },
2420
+ response: { body: agentApiMessageEnvelopeSchema }
2421
+ }),
2422
+ channelJoin: route({
2423
+ key: "channelJoin",
2424
+ method: "POST",
2425
+ path: "/channels/:channelId/join",
2426
+ client: { resource: "channels", method: "join" },
2427
+ capability: "channels",
2428
+ description: "Join a visible public channel as the bound agent credential.",
2429
+ request: { params: agentApiChannelMembershipParamsSchema },
2430
+ response: { body: agentApiOkResponseSchema }
2431
+ }),
2432
+ channelLeave: route({
2433
+ key: "channelLeave",
2434
+ method: "POST",
2435
+ path: "/channels/:channelId/leave",
2436
+ client: { resource: "channels", method: "leave" },
2437
+ capability: "channels",
2438
+ description: "Leave a joined regular channel as the bound agent credential.",
2439
+ request: { params: agentApiChannelMembershipParamsSchema },
2440
+ response: { body: agentApiOkResponseSchema }
2441
+ }),
2442
+ channelMembers: route({
2443
+ key: "channelMembers",
2444
+ method: "GET",
2445
+ path: "/channel-members",
2446
+ client: { resource: "channels", method: "members" },
2447
+ capability: "channels",
2448
+ description: "List agents and humans in a visible channel, DM, or thread.",
2449
+ request: { query: agentApiChannelMembersQuerySchema },
2450
+ response: { body: agentApiChannelMembersResponseSchema }
2451
+ }),
2452
+ resolveChannel: route({
2453
+ key: "resolveChannel",
2454
+ method: "POST",
2455
+ path: "/resolve-channel",
2456
+ client: { resource: "channels", method: "resolve" },
2457
+ capability: "send",
2458
+ description: "Resolve a writable channel, DM, or thread target for the bound agent credential.",
2459
+ request: { body: agentApiResolveChannelBodySchema },
2460
+ response: { body: agentApiResolveChannelResponseSchema }
2461
+ }),
2462
+ threadUnfollow: route({
2463
+ key: "threadUnfollow",
2464
+ method: "POST",
2465
+ path: "/threads/unfollow",
2466
+ client: { resource: "threads", method: "unfollow" },
2467
+ capability: "channels",
2468
+ description: "Stop ordinary delivery for a followed thread as the bound agent credential.",
2469
+ request: { body: agentApiThreadUnfollowBodySchema },
2470
+ response: { body: agentApiOkResponseSchema }
2471
+ }),
2472
+ serverInfo: route({
2473
+ key: "serverInfo",
2474
+ method: "GET",
2475
+ path: "/server",
2476
+ client: { resource: "server", method: "info" },
2477
+ capability: "server",
2478
+ description: "List channels, agents, humans, and runtime context visible to the bound agent.",
2479
+ request: {},
2480
+ response: { body: agentApiServerInfoResponseSchema }
2481
+ }),
2482
+ mentionActionsPending: route({
2483
+ key: "mentionActionsPending",
2484
+ method: "GET",
2485
+ path: "/mention-actions/pending",
2486
+ client: { resource: "mentions", method: "pendingActions" },
2487
+ capability: "mentions",
2488
+ description: "List sender-side pending mention actions for unresolved outsider mentions.",
2489
+ request: { query: agentApiMentionActionsPendingQuerySchema },
2490
+ response: { body: agentApiMentionActionsPendingResponseSchema }
2491
+ }),
2492
+ mentionActionsExecute: route({
2493
+ key: "mentionActionsExecute",
2494
+ method: "POST",
2495
+ path: "/mention-actions/execute",
2496
+ client: { resource: "mentions", method: "executeAction" },
2497
+ capability: "mentions",
2498
+ description: "Execute sender-side mention resolution actions.",
2499
+ request: { body: agentApiMentionActionsExecuteBodySchema },
2500
+ response: { body: agentApiMentionActionsExecuteResponseSchema }
2501
+ }),
2502
+ taskClaim: route({
2503
+ key: "taskClaim",
2504
+ method: "POST",
2505
+ path: "/tasks/claim",
2506
+ client: { resource: "tasks", method: "claim" },
2507
+ capability: "tasks",
2508
+ description: "Claim one or more tasks by task number or message id.",
2509
+ request: { body: agentApiTaskClaimBodySchema },
2510
+ response: { body: agentApiTaskClaimResponseSchema }
2511
+ }),
2512
+ taskList: route({
2513
+ key: "taskList",
2514
+ method: "GET",
2515
+ path: "/tasks",
2516
+ client: { resource: "tasks", method: "list" },
2517
+ capability: "tasks",
2518
+ description: "List tasks in a channel.",
2519
+ request: { query: agentApiTaskListQuerySchema },
2520
+ response: { body: agentApiTaskListResponseSchema }
2521
+ }),
2522
+ taskCreate: route({
2523
+ key: "taskCreate",
2524
+ method: "POST",
2525
+ path: "/tasks",
2526
+ client: { resource: "tasks", method: "create" },
2527
+ capability: "tasks",
2528
+ description: "Create one or more tasks in a channel.",
2529
+ request: { body: agentApiTaskCreateBodySchema },
2530
+ response: { body: agentApiTaskCreateResponseSchema }
2531
+ }),
2532
+ taskUnclaim: route({
2533
+ key: "taskUnclaim",
2534
+ method: "POST",
2535
+ path: "/tasks/unclaim",
2536
+ client: { resource: "tasks", method: "unclaim" },
2537
+ capability: "tasks",
2538
+ description: "Release a previously claimed task.",
2539
+ request: { body: agentApiTaskUnclaimBodySchema },
2540
+ response: { body: agentApiTaskUnclaimResponseSchema }
2541
+ }),
2542
+ taskUpdateStatus: route({
2543
+ key: "taskUpdateStatus",
2544
+ method: "POST",
2545
+ path: "/tasks/update-status",
2546
+ client: { resource: "tasks", method: "updateStatus" },
2547
+ capability: "tasks",
2548
+ description: "Update a task status.",
2549
+ request: { body: agentApiTaskUpdateStatusBodySchema },
2550
+ response: { body: agentApiTaskUpdateStatusResponseSchema }
2551
+ }),
2552
+ reminderList: route({
2553
+ key: "reminderList",
2554
+ method: "GET",
2555
+ path: "/reminders",
2556
+ client: { resource: "reminders", method: "list" },
2557
+ capability: "read",
2558
+ description: "List reminders owned by the bound agent credential.",
2559
+ request: { query: agentApiReminderListQuerySchema },
2560
+ response: { body: agentApiReminderListResponseSchema }
2561
+ }),
2562
+ reminderCreate: route({
2563
+ key: "reminderCreate",
2564
+ method: "POST",
2565
+ path: "/reminders",
2566
+ client: { resource: "reminders", method: "create" },
2567
+ capability: "tasks",
2568
+ description: "Create a reminder owned by the bound agent credential.",
2569
+ request: { body: agentApiReminderScheduleBodySchema },
2570
+ response: { body: agentApiReminderResponseSchema }
2571
+ }),
2572
+ reminderCancel: route({
2573
+ key: "reminderCancel",
2574
+ method: "DELETE",
2575
+ path: "/reminders/:reminderId",
2576
+ client: { resource: "reminders", method: "cancel" },
2577
+ capability: "tasks",
2578
+ description: "Cancel a scheduled or fired reminder owned by the bound agent credential.",
2579
+ request: { params: agentApiReminderParamsSchema },
2580
+ response: { body: agentApiReminderResponseSchema }
2581
+ }),
2582
+ reminderSnooze: route({
2583
+ key: "reminderSnooze",
2584
+ method: "POST",
2585
+ path: "/reminders/:reminderId/snooze",
2586
+ client: { resource: "reminders", method: "snooze" },
2587
+ capability: "tasks",
2588
+ description: "Snooze a scheduled or fired reminder owned by the bound agent credential.",
2589
+ request: { params: agentApiReminderParamsSchema, body: agentApiReminderSnoozeBodySchema },
2590
+ response: { body: agentApiReminderResponseSchema }
2591
+ }),
2592
+ reminderUpdate: route({
2593
+ key: "reminderUpdate",
2594
+ method: "PATCH",
2595
+ path: "/reminders/:reminderId",
2596
+ client: { resource: "reminders", method: "update" },
2597
+ capability: "tasks",
2598
+ description: "Update a scheduled reminder owned by the bound agent credential.",
2599
+ request: { params: agentApiReminderParamsSchema, body: agentApiReminderUpdateBodySchema },
2600
+ response: { body: agentApiReminderResponseSchema }
2601
+ }),
2602
+ reminderLog: route({
2603
+ key: "reminderLog",
2604
+ method: "GET",
2605
+ path: "/reminders/:reminderId/log",
2606
+ client: { resource: "reminders", method: "log" },
2607
+ capability: "read",
2608
+ description: "Read lifecycle events for a reminder owned by the bound agent credential.",
2609
+ request: { params: agentApiReminderParamsSchema },
2610
+ response: { body: agentApiReminderLogResponseSchema }
2611
+ }),
2612
+ profileShow: route({
2613
+ key: "profileShow",
2614
+ method: "GET",
2615
+ path: "/profile",
2616
+ client: { resource: "profile", method: "show" },
2617
+ capability: "read",
2618
+ description: "Show the bound agent profile, or another visible profile when target is provided.",
2619
+ request: { query: agentApiProfileShowQuerySchema },
2620
+ response: { body: agentApiProfileViewSchema }
2621
+ }),
2622
+ profileUpdate: route({
2623
+ key: "profileUpdate",
2624
+ method: "POST",
2625
+ path: "/profile",
2626
+ client: { resource: "profile", method: "update" },
2627
+ capability: "server",
2628
+ description: "Update the bound agent profile metadata.",
2629
+ request: { body: agentApiProfileUpdateBodySchema },
2630
+ response: { body: agentApiProfileViewSchema }
2631
+ }),
2632
+ integrationList: route({
2633
+ key: "integrationList",
2634
+ method: "GET",
2635
+ path: "/integrations",
2636
+ client: { resource: "integrations", method: "list" },
2637
+ capability: "read",
2638
+ description: "List available integration services and active agent logins.",
2639
+ request: {},
2640
+ response: { body: agentApiIntegrationListResponseSchema }
2641
+ }),
2642
+ integrationLogin: route({
2643
+ key: "integrationLogin",
2644
+ method: "POST",
2645
+ path: "/integrations/login",
2646
+ client: { resource: "integrations", method: "login" },
2647
+ capability: "read",
2648
+ description: "Provision or reuse this agent's login for a registered integration service.",
2649
+ request: { body: agentApiIntegrationLoginBodySchema },
2650
+ response: { body: agentApiIntegrationLoginResponseSchema }
2651
+ }),
2652
+ integrationAppPrepare: route({
2653
+ key: "integrationAppPrepare",
2654
+ method: "POST",
2655
+ path: "/integrations/app/prepare",
2656
+ client: { resource: "integrations", method: "prepareApp" },
2657
+ capability: "read",
2658
+ description: "Prepare a third-party integration registration/update action card.",
2659
+ request: { body: agentApiIntegrationAppPrepareBodySchema },
2660
+ response: { body: agentApiIntegrationAppPrepareResponseSchema }
2661
+ }),
2662
+ actionPrepare: route({
2663
+ key: "actionPrepare",
2664
+ method: "POST",
2665
+ path: "/prepare-action",
2666
+ client: { resource: "actions", method: "prepare" },
2667
+ capability: "tasks",
2668
+ description: "Prepare an action card for a human to commit.",
2669
+ request: { body: agentApiActionPrepareBodySchema },
2670
+ response: { body: agentApiActionPrepareResponseSchema }
2671
+ }),
2672
+ attachmentUpload: route({
2673
+ key: "attachmentUpload",
2674
+ method: "POST",
2675
+ path: "/upload",
2676
+ client: { resource: "attachments", method: "upload" },
2677
+ capability: "send",
2678
+ description: "Upload a multipart attachment as the bound agent credential.",
2679
+ request: {},
2680
+ response: { body: agentApiAttachmentUploadResponseSchema }
2681
+ })
2682
+ };
2683
+
1140
2684
  // ../shared/src/agentInbox.ts
1141
2685
  function formatAgentInboxDelta(rows, options = {}) {
1142
2686
  const totalPendingMessages = options.totalPendingMessages;
@@ -1164,7 +2708,7 @@ function shortMessageId(value) {
1164
2708
  }
1165
2709
 
1166
2710
  // ../shared/src/externalAgentIntegration.ts
1167
- import { z as z2 } from "zod";
2711
+ import { z as z3 } from "zod";
1168
2712
  var EXTERNAL_AGENT_COMMS_PROTOCOL_VERSION = "agent-comms-core.v1";
1169
2713
  var EXTERNAL_AGENT_PROOF_SCHEMA_VERSION = "agent-proof.v1";
1170
2714
  var EXTERNAL_RUNTIME_INTEGRATION_MANIFEST_SCHEMA = "slock-external-runtime-integration.v1";
@@ -1208,35 +2752,35 @@ var externalAgentAdapterFailureValues = [
1208
2752
  "auth_revoked"
1209
2753
  ];
1210
2754
  var externalAgentServerApiModeValues = ["interim-agent-api-events", "agent-inbox-protocol"];
1211
- var nonEmptyStringSchema = z2.string().min(1);
1212
- var isoTimestampSchema = z2.string().refine((value) => !Number.isNaN(Date.parse(value)), {
2755
+ var nonEmptyStringSchema = z3.string().min(1);
2756
+ var isoTimestampSchema = z3.string().refine((value) => !Number.isNaN(Date.parse(value)), {
1213
2757
  message: "must be a parseable timestamp"
1214
2758
  });
1215
- var externalRuntimeIntegrationManifestSchema = z2.object({
1216
- schema: z2.literal(EXTERNAL_RUNTIME_INTEGRATION_MANIFEST_SCHEMA),
2759
+ var externalRuntimeIntegrationManifestSchema = z3.object({
2760
+ schema: z3.literal(EXTERNAL_RUNTIME_INTEGRATION_MANIFEST_SCHEMA),
1217
2761
  runtimeId: nonEmptyStringSchema,
1218
- integrationPattern: z2.enum(externalAgentIntegrationPatternValues),
1219
- commsMode: z2.enum(externalAgentCommsModeValues),
1220
- commsProtocolVersion: z2.literal(EXTERNAL_AGENT_COMMS_PROTOCOL_VERSION),
1221
- proofSchemaVersion: z2.literal(EXTERNAL_AGENT_PROOF_SCHEMA_VERSION),
2762
+ integrationPattern: z3.enum(externalAgentIntegrationPatternValues),
2763
+ commsMode: z3.enum(externalAgentCommsModeValues),
2764
+ commsProtocolVersion: z3.literal(EXTERNAL_AGENT_COMMS_PROTOCOL_VERSION),
2765
+ proofSchemaVersion: z3.literal(EXTERNAL_AGENT_PROOF_SCHEMA_VERSION),
1222
2766
  minSlockCliVersion: nonEmptyStringSchema,
1223
- multiplex: z2.boolean(),
1224
- agentIsolation: z2.enum(externalAgentIsolationValues),
1225
- bridgeLifecycle: z2.object({
1226
- explicitStartOnly: z2.literal(true),
1227
- oneShotCommandsBridgeIndependent: z2.literal(true),
1228
- requiresBridgeFailureCodes: z2.array(z2.enum(["BRIDGE_NOT_RUNNING", "NO_CORE_SESSION"])).min(1),
1229
- autoStartDefault: z2.literal(false)
2767
+ multiplex: z3.boolean(),
2768
+ agentIsolation: z3.enum(externalAgentIsolationValues),
2769
+ bridgeLifecycle: z3.object({
2770
+ explicitStartOnly: z3.literal(true),
2771
+ oneShotCommandsBridgeIndependent: z3.literal(true),
2772
+ requiresBridgeFailureCodes: z3.array(z3.enum(["BRIDGE_NOT_RUNNING", "NO_CORE_SESSION"])).min(1),
2773
+ autoStartDefault: z3.literal(false)
1230
2774
  }).strict(),
1231
- serverApi: z2.object({
1232
- mode: z2.enum(externalAgentServerApiModeValues),
1233
- deliveryOnly: z2.boolean(),
1234
- cursorAuthority: z2.literal("model_seen_only")
2775
+ serverApi: z3.object({
2776
+ mode: z3.enum(externalAgentServerApiModeValues),
2777
+ deliveryOnly: z3.boolean(),
2778
+ cursorAuthority: z3.literal("model_seen_only")
1235
2779
  }).strict(),
1236
- wakeAdapter: z2.object({
1237
- kind: z2.enum(externalAgentWakeAdapterKindValues),
2780
+ wakeAdapter: z3.object({
2781
+ kind: z3.enum(externalAgentWakeAdapterKindValues),
1238
2782
  protocol: nonEmptyStringSchema,
1239
- requiresInteractiveSession: z2.boolean().optional()
2783
+ requiresInteractiveSession: z3.boolean().optional()
1240
2784
  }).strict()
1241
2785
  }).strict().superRefine((value, ctx) => {
1242
2786
  if (!value.bridgeLifecycle.requiresBridgeFailureCodes.includes("BRIDGE_NOT_RUNNING")) {
@@ -1261,8 +2805,8 @@ var externalRuntimeIntegrationManifestSchema = z2.object({
1261
2805
  });
1262
2806
  }
1263
2807
  });
1264
- var externalAgentWakeEventBaseSchema = z2.object({
1265
- schema: z2.literal(EXTERNAL_AGENT_WAKE_EVENT_SCHEMA),
2808
+ var externalAgentWakeEventBaseSchema = z3.object({
2809
+ schema: z3.literal(EXTERNAL_AGENT_WAKE_EVENT_SCHEMA),
1266
2810
  eventId: nonEmptyStringSchema,
1267
2811
  attemptId: nonEmptyStringSchema,
1268
2812
  messageId: nonEmptyStringSchema,
@@ -1272,30 +2816,30 @@ var externalAgentWakeEventBaseSchema = z2.object({
1272
2816
  adapterInstance: nonEmptyStringSchema,
1273
2817
  runtimeSession: nonEmptyStringSchema.nullable(),
1274
2818
  occurredAt: isoTimestampSchema,
1275
- lifecycleState: z2.enum(externalAgentCommsLifecycleStateValues),
1276
- authority: z2.object({
1277
- source: z2.enum(externalAgentLifecycleSourceValues),
1278
- provenance: z2.enum(externalAgentLifecycleProvenanceValues)
2819
+ lifecycleState: z3.enum(externalAgentCommsLifecycleStateValues),
2820
+ authority: z3.object({
2821
+ source: z3.enum(externalAgentLifecycleSourceValues),
2822
+ provenance: z3.enum(externalAgentLifecycleProvenanceValues)
1279
2823
  }).strict()
1280
2824
  }).strict();
1281
2825
  var externalAgentProofEventEnvelopeSchema = externalAgentWakeEventBaseSchema.extend({
1282
- kind: z2.literal("proof"),
1283
- proofLevel: z2.enum(externalAgentWakeProofLevelValues),
1284
- outcome: z2.literal("ok"),
1285
- failureMeta: z2.undefined().optional(),
1286
- reason: z2.string().optional()
2826
+ kind: z3.literal("proof"),
2827
+ proofLevel: z3.enum(externalAgentWakeProofLevelValues),
2828
+ outcome: z3.literal("ok"),
2829
+ failureMeta: z3.undefined().optional(),
2830
+ reason: z3.string().optional()
1287
2831
  });
1288
2832
  var externalAgentFailedWakeEventEnvelopeSchema = externalAgentWakeEventBaseSchema.extend({
1289
- kind: z2.literal("wake_attempt"),
1290
- proofLevel: z2.undefined().optional(),
1291
- outcome: z2.literal("failed"),
1292
- failureMeta: z2.object({
1293
- failureClass: z2.enum(externalAgentAdapterFailureValues),
1294
- retryAfterMs: z2.number().int().positive().optional()
2833
+ kind: z3.literal("wake_attempt"),
2834
+ proofLevel: z3.undefined().optional(),
2835
+ outcome: z3.literal("failed"),
2836
+ failureMeta: z3.object({
2837
+ failureClass: z3.enum(externalAgentAdapterFailureValues),
2838
+ retryAfterMs: z3.number().int().positive().optional()
1295
2839
  }).strict(),
1296
2840
  reason: nonEmptyStringSchema
1297
2841
  });
1298
- var externalAgentWakeEventEnvelopeSchema = z2.discriminatedUnion("kind", [
2842
+ var externalAgentWakeEventEnvelopeSchema = z3.discriminatedUnion("kind", [
1299
2843
  externalAgentProofEventEnvelopeSchema,
1300
2844
  externalAgentFailedWakeEventEnvelopeSchema
1301
2845
  ]);
@@ -1383,9 +2927,30 @@ var SERVER_CAPABILITY_MATRIX = {
1383
2927
 
1384
2928
  // ../shared/src/index.ts
1385
2929
  var RUNTIME_CONFIG_VERSION = 1;
2930
+ var BUILTIN_RUNTIME_PROVIDER_ENV_KEYS = PI_BUILTIN_PROVIDER_API_KEY_ENV_KEYS_GENERATED;
2931
+ var BUILTIN_RUNTIME_PROVIDERS = Object.entries(BUILTIN_RUNTIME_PROVIDER_ENV_KEYS).map(([id, envKey]) => ({ id, envKey }));
1386
2932
  var PI_BUILTIN_PROVIDER_ENV_KEYS = {
1387
- deepseek: "DEEPSEEK_API_KEY"
2933
+ deepseek: BUILTIN_RUNTIME_PROVIDER_ENV_KEYS.deepseek
1388
2934
  };
2935
+ var BUILTIN_RUNTIME_PROVIDER_BLOCKED_HOST_ENV_KEYS = Array.from(new Set(
2936
+ Object.values(PI_BUILTIN_PROVIDER_BLOCKED_HOST_ENV_KEYS_GENERATED).flat()
2937
+ ));
2938
+ var BUILTIN_RUNTIME_GATEWAY_PROVIDERS = [
2939
+ { id: "openai-compatible", envKey: "OPENAI_API_KEY", baseUrlEnvKey: "OPENAI_BASE_URL" },
2940
+ { id: "anthropic-compatible", envKey: "ANTHROPIC_API_KEY", baseUrlEnvKey: "ANTHROPIC_BASE_URL" }
2941
+ ];
2942
+ var BUILTIN_RUNTIME_GATEWAY_PROVIDER_ENV_KEYS = Object.fromEntries(BUILTIN_RUNTIME_GATEWAY_PROVIDERS.map((provider) => [provider.id, provider.envKey]));
2943
+ var BUILTIN_RUNTIME_GATEWAY_PROVIDER_BASE_URL_ENV_KEYS = Object.fromEntries(BUILTIN_RUNTIME_GATEWAY_PROVIDERS.map((provider) => [provider.id, provider.baseUrlEnvKey]));
2944
+ var BUILTIN_RUNTIME_CONTROLLED_ENV_KEYS = Array.from(/* @__PURE__ */ new Set([
2945
+ ...Object.values(BUILTIN_RUNTIME_PROVIDER_ENV_KEYS),
2946
+ ...Object.values(BUILTIN_RUNTIME_GATEWAY_PROVIDER_ENV_KEYS),
2947
+ ...Object.values(BUILTIN_RUNTIME_GATEWAY_PROVIDER_BASE_URL_ENV_KEYS)
2948
+ ]));
2949
+ var BUILTIN_RUNTIME_HOST_PROVIDER_ENV_SCRUB_KEYS = Array.from(/* @__PURE__ */ new Set([
2950
+ ...BUILTIN_RUNTIME_CONTROLLED_ENV_KEYS,
2951
+ ...BUILTIN_RUNTIME_PROVIDER_BLOCKED_HOST_ENV_KEYS
2952
+ ]));
2953
+ var PI_BUILTIN_PROVIDER_MODELS = PI_BUILTIN_PROVIDER_MODELS_GENERATED;
1389
2954
  var AGENT_ACTIVITIES = ["online", "thinking", "working", "error", "offline"];
1390
2955
  var isAgentActivity = makeIsMember(AGENT_ACTIVITIES);
1391
2956
  var VALID_ACTIVITIES = new Set(AGENT_ACTIVITIES);
@@ -1393,6 +2958,7 @@ var EXTERNAL_AGENT_RUNTIME_ID = "external";
1393
2958
  var EXTERNAL_AGENT_RUNTIME_MODEL = "external";
1394
2959
  var EXTERNAL_AGENT_RUNTIME_DISPLAY_NAME = "External agent";
1395
2960
  var RUNTIMES = [
2961
+ { id: "builtin", displayName: "Built-in", binary: "", supported: true },
1396
2962
  { id: "claude", displayName: "Claude Code", binary: "claude", supported: true },
1397
2963
  { id: "codex", displayName: "Codex CLI", binary: "codex", supported: true },
1398
2964
  { id: "antigravity", displayName: "Antigravity CLI", binary: "agy", supported: true },
@@ -1411,6 +2977,7 @@ var RUNTIME_MODELS = {
1411
2977
  [EXTERNAL_AGENT_RUNTIME_ID]: [
1412
2978
  { id: EXTERNAL_AGENT_RUNTIME_MODEL, label: EXTERNAL_AGENT_RUNTIME_DISPLAY_NAME }
1413
2979
  ],
2980
+ builtin: Object.values(PI_BUILTIN_PROVIDER_MODELS).flat().map((model) => ({ id: model.id, label: model.label || formatRuntimeProviderModelLabel(model.id), verified: "launchable" })),
1414
2981
  claude: [
1415
2982
  { id: "opus", label: "Claude Opus" },
1416
2983
  { id: "claude-opus-4-8", label: "Claude Opus 4.8" },
@@ -1490,18 +3057,79 @@ function getDefaultModel(runtimeId) {
1490
3057
  return models?.[0]?.id ?? "sonnet";
1491
3058
  }
1492
3059
  var CONTROLLED_RUNTIME_ENV_KEYS = {
3060
+ // Built-in owns all provider credential/base-url env keys for its launch
3061
+ // plan. Scrub both keys we materialize and host provider keys Pi may read
3062
+ // directly, including defensive aliases such as ANTHROPIC_OAUTH_TOKEN.
3063
+ builtin: BUILTIN_RUNTIME_HOST_PROVIDER_ENV_SCRUB_KEYS,
1493
3064
  claude: ["ANTHROPIC_BASE_URL", "ANTHROPIC_API_KEY", "ANTHROPIC_CUSTOM_MODEL_OPTION"],
1494
3065
  // Pi-runtime builtin-provider env vars (e.g. DEEPSEEK_API_KEY). Owned by
1495
- // RuntimeProviderConfig.pi-builtin → runtimeConfigToLaunchFields, not by
3066
+ // PiRuntimeProviderConfig.pi-builtin → buildLaunchPlan, not by
1496
3067
  // user-supplied envVars: reading from PI_BUILTIN_PROVIDER_ENV_KEYS keeps
1497
3068
  // this list in sync as new providers are added.
1498
3069
  pi: Object.values(PI_BUILTIN_PROVIDER_ENV_KEYS)
1499
3070
  };
1500
- function isPlainRecord(value) {
3071
+ var RUNTIME_CONFIG_FIELDS = [
3072
+ "version",
3073
+ "runtime",
3074
+ "provider",
3075
+ "model",
3076
+ "mode",
3077
+ "reasoningEffort",
3078
+ "envVars",
3079
+ "command",
3080
+ "hostUserState"
3081
+ ];
3082
+ var MODEL_CONFIG_FIELDS = ["kind", "id", "name"];
3083
+ var MODE_CONFIG_FIELDS = ["kind"];
3084
+ var CLAUDE_DEFAULT_PROVIDER_FIELDS = ["kind"];
3085
+ var CLAUDE_CUSTOM_PROVIDER_FIELDS = ["kind", "apiUrl", "apiKey"];
3086
+ var PI_DEFAULT_PROVIDER_FIELDS = ["kind"];
3087
+ var PI_BUILTIN_PROVIDER_FIELDS = ["kind", "providerId", "apiKey"];
3088
+ var BUILTIN_PRESET_PROVIDER_FIELDS = ["kind", "providerId", "apiKey"];
3089
+ var BUILTIN_GATEWAY_PROVIDER_FIELDS = ["kind", "providerId", "baseUrl", "apiKey"];
3090
+ var UNKNOWN_PROVIDER_FIELDS = ["kind"];
3091
+ function isPlainRecord2(value) {
1501
3092
  return value !== null && typeof value === "object" && !Array.isArray(value);
1502
3093
  }
1503
- function normalizeEnvVars(envVars) {
1504
- if (!isPlainRecord(envVars)) return null;
3094
+ function providerKnownFieldsFor(runtime, provider) {
3095
+ const kind = typeof provider.kind === "string" ? provider.kind : void 0;
3096
+ if (runtime === "builtin") {
3097
+ if (kind === "preset" || kind === "managed") return BUILTIN_PRESET_PROVIDER_FIELDS;
3098
+ if (kind === "gateway") return BUILTIN_GATEWAY_PROVIDER_FIELDS;
3099
+ }
3100
+ if (runtime === "claude") {
3101
+ if (kind === "default") return CLAUDE_DEFAULT_PROVIDER_FIELDS;
3102
+ if (kind === "custom") return CLAUDE_CUSTOM_PROVIDER_FIELDS;
3103
+ }
3104
+ if (runtime === "pi") {
3105
+ if (kind === "default") return PI_DEFAULT_PROVIDER_FIELDS;
3106
+ if (kind === "pi-builtin") return PI_BUILTIN_PROVIDER_FIELDS;
3107
+ }
3108
+ return UNKNOWN_PROVIDER_FIELDS;
3109
+ }
3110
+ function providerKind2(config) {
3111
+ return config.provider?.kind ?? "none";
3112
+ }
3113
+ function providerKeyPresent(config) {
3114
+ if (config.runtime === "builtin") return config.provider.apiKey.length > 0;
3115
+ if (config.runtime === "claude") return config.provider?.kind === "custom" && config.provider.apiKey.length > 0;
3116
+ if (config.runtime === "pi") return config.provider?.kind === "pi-builtin" && config.provider.apiKey.length > 0;
3117
+ return false;
3118
+ }
3119
+ function builtInSelectionTraceAttrs2(config) {
3120
+ if (config.runtime !== "builtin") return {};
3121
+ return {
3122
+ provider_id: config.provider.providerId,
3123
+ model_kind: config.model.kind,
3124
+ ...config.model.kind === "preset" ? { model_id: config.model.id } : {},
3125
+ ...config.provider.kind === "gateway" ? {
3126
+ base_url_present: true,
3127
+ base_url_host_class: classifyBuiltInGatewayBaseUrlHost2(config.provider.baseUrl)
3128
+ } : {}
3129
+ };
3130
+ }
3131
+ function normalizeEnvVars2(envVars) {
3132
+ if (!isPlainRecord2(envVars)) return null;
1505
3133
  const normalized = {};
1506
3134
  for (const [key, value] of Object.entries(envVars)) {
1507
3135
  if (typeof key === "string" && typeof value === "string") {
@@ -1514,7 +3142,7 @@ function getControlledRuntimeEnvKeys(runtime) {
1514
3142
  return CONTROLLED_RUNTIME_ENV_KEYS[runtime] ?? [];
1515
3143
  }
1516
3144
  function stripControlledRuntimeEnvVars(runtime, envVars) {
1517
- const normalized = normalizeEnvVars(envVars);
3145
+ const normalized = normalizeEnvVars2(envVars);
1518
3146
  if (!normalized) return null;
1519
3147
  const controlled = new Set(getControlledRuntimeEnvKeys(runtime));
1520
3148
  for (const key of controlled) {
@@ -1522,83 +3150,108 @@ function stripControlledRuntimeEnvVars(runtime, envVars) {
1522
3150
  }
1523
3151
  return Object.keys(normalized).length > 0 ? normalized : null;
1524
3152
  }
1525
- function isPresetRuntimeModel(runtime, model) {
1526
- return (RUNTIME_MODELS[runtime] ?? []).some((candidate) => candidate.id === model);
1527
- }
1528
- function modelConfigFromLegacy(runtime, model) {
1529
- return isPresetRuntimeModel(runtime, model) ? { kind: "preset", id: model } : { kind: "custom", name: model };
1530
- }
1531
- function parseProviderConfig(runtime, value, legacyApiUrl, legacyApiKey) {
1532
- if (runtime === "claude") {
1533
- if (!isPlainRecord(value)) return { kind: "default" };
1534
- if (value.kind === "custom" && typeof value.apiUrl === "string" && value.apiUrl.trim() && typeof value.apiKey === "string" && value.apiKey.trim()) {
1535
- return { kind: "custom", apiUrl: value.apiUrl.trim(), apiKey: value.apiKey.trim() };
1536
- }
1537
- if (value.kind === "custom" && legacyApiUrl?.trim() && legacyApiKey?.trim()) {
1538
- return { kind: "custom", apiUrl: legacyApiUrl.trim(), apiKey: legacyApiKey.trim() };
1539
- }
1540
- return { kind: "default" };
3153
+ function classifyBuiltInGatewayBaseUrlHost2(baseUrl) {
3154
+ let hostname = "";
3155
+ try {
3156
+ hostname = new URL(baseUrl).hostname.toLowerCase();
3157
+ } catch {
3158
+ return "public";
1541
3159
  }
1542
- if (runtime === "pi") {
1543
- if (!isPlainRecord(value)) return { kind: "default" };
1544
- if (value.kind === "pi-builtin" && typeof value.providerId === "string" && value.providerId.trim() && typeof value.apiKey === "string" && value.apiKey.trim() && Object.prototype.hasOwnProperty.call(PI_BUILTIN_PROVIDER_ENV_KEYS, value.providerId.trim())) {
1545
- return { kind: "pi-builtin", providerId: value.providerId.trim(), apiKey: value.apiKey.trim() };
1546
- }
1547
- return { kind: "default" };
3160
+ if (hostname === "localhost" || hostname === "::1" || hostname === "[::1]" || hostname.startsWith("127.")) return "localhost";
3161
+ const ipv4 = hostname.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
3162
+ if (ipv4) {
3163
+ const octets = ipv4.slice(1).map((part) => Number(part));
3164
+ const [a, b] = octets;
3165
+ if (a === 10 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 169 && b === 254) return "private";
1548
3166
  }
1549
- return void 0;
3167
+ if (hostname === "0.0.0.0" || hostname === "::" || hostname.startsWith("fc") || hostname.startsWith("fd") || hostname.startsWith("fe80:")) {
3168
+ return "private";
3169
+ }
3170
+ return "public";
1550
3171
  }
1551
- function parseModelConfig(runtime, value, fallback, provider, legacyCustomModel) {
1552
- if (!isPlainRecord(value)) return modelConfigFromLegacy(runtime, fallback);
1553
- if (value.kind === "custom" && typeof value.name === "string" && value.name.trim()) {
1554
- return { kind: "custom", name: value.name.trim() };
3172
+ function composeRuntimeConfig(input) {
3173
+ const base = {
3174
+ version: RUNTIME_CONFIG_VERSION,
3175
+ model: input.model,
3176
+ mode: input.mode,
3177
+ reasoningEffort: input.reasoningEffort ?? null,
3178
+ envVars: input.envVars ?? null
3179
+ };
3180
+ if (input.runtime === "builtin") {
3181
+ return {
3182
+ ...base,
3183
+ runtime: "builtin",
3184
+ provider: input.provider,
3185
+ hostUserState: "forbidden"
3186
+ };
1555
3187
  }
1556
- if (value.kind === "preset" && typeof value.id === "string" && value.id.trim() && isPresetRuntimeModel(runtime, value.id.trim())) {
1557
- return { kind: "preset", id: value.id.trim() };
3188
+ if (input.runtime === "claude") {
3189
+ return {
3190
+ ...base,
3191
+ runtime: "claude",
3192
+ provider: input.provider,
3193
+ ...input.command ? { command: input.command } : {}
3194
+ };
1558
3195
  }
1559
- if (provider?.kind === "custom" && runtime === "claude" && legacyCustomModel?.trim()) {
1560
- return { kind: "custom", name: legacyCustomModel.trim() };
3196
+ if (input.runtime === "pi") {
3197
+ return {
3198
+ ...base,
3199
+ runtime: "pi",
3200
+ provider: input.provider
3201
+ };
1561
3202
  }
1562
- return modelConfigFromLegacy(runtime, fallback);
1563
- }
1564
- function parseModeConfig(value) {
1565
- if (!isPlainRecord(value)) return { kind: "default" };
1566
- if (value.kind === "fast") return { kind: "fast" };
1567
- return { kind: "default" };
1568
- }
1569
- function parseCommandConfig(runtime, value) {
1570
- if (runtime !== "claude" || typeof value !== "string") return void 0;
1571
- const command = value.trim();
1572
- return command ? command : void 0;
1573
- }
1574
- function hydrateRuntimeConfig(input) {
1575
- const stored = isPlainRecord(input.runtimeConfig) && input.runtimeConfig.version === RUNTIME_CONFIG_VERSION ? input.runtimeConfig : null;
1576
- const runtime = typeof stored?.runtime === "string" && stored.runtime.trim() || typeof input.runtime === "string" && input.runtime.trim() || "claude";
1577
- const fallbackModel = typeof input.model === "string" && input.model.trim() || getDefaultModel(runtime);
1578
- const legacyEnvVars = normalizeEnvVars(input.envVars);
1579
- const storedEnvVars = normalizeEnvVars(stored?.envVars);
1580
- const legacyClaudeApiUrl = runtime === "claude" ? legacyEnvVars?.ANTHROPIC_BASE_URL : void 0;
1581
- const legacyClaudeApiKey = runtime === "claude" ? legacyEnvVars?.ANTHROPIC_API_KEY : void 0;
1582
- const legacyClaudeCustomModel = runtime === "claude" ? legacyEnvVars?.ANTHROPIC_CUSTOM_MODEL_OPTION : void 0;
1583
- const provider = stored ? parseProviderConfig(runtime, stored.provider, legacyClaudeApiUrl, legacyClaudeApiKey) : runtime === "claude" && legacyClaudeApiUrl && legacyClaudeApiKey ? { kind: "custom", apiUrl: legacyClaudeApiUrl, apiKey: legacyClaudeApiKey } : runtime === "claude" ? { kind: "default" } : void 0;
1584
- const command = stored ? parseCommandConfig(runtime, stored.command) : void 0;
1585
3203
  return {
1586
- version: RUNTIME_CONFIG_VERSION,
1587
- runtime,
1588
- ...provider ? { provider } : {},
1589
- model: stored ? parseModelConfig(runtime, stored.model, fallbackModel, provider, legacyClaudeCustomModel) : modelConfigFromLegacy(runtime, fallbackModel),
1590
- mode: stored ? parseModeConfig(stored.mode) : { kind: "default" },
1591
- reasoningEffort: stored?.reasoningEffort ?? input.reasoningEffort ?? null,
1592
- envVars: stripControlledRuntimeEnvVars(runtime, stored ? storedEnvVars : legacyEnvVars),
1593
- ...command ? { command } : {}
3204
+ ...base,
3205
+ runtime: input.runtime
1594
3206
  };
1595
3207
  }
3208
+ function hydrateRuntimeConfig(input) {
3209
+ return hydrateRuntimeConfigWithTrace(input).config;
3210
+ }
3211
+ function hydrateRuntimeConfigWithTrace(input) {
3212
+ return hydrateLegacyRuntimeConfigWithTrace(input, {
3213
+ runtimeConfigVersion: RUNTIME_CONFIG_VERSION,
3214
+ runtimeModels: RUNTIME_MODELS,
3215
+ runtimeConfigFields: RUNTIME_CONFIG_FIELDS,
3216
+ modelConfigFields: MODEL_CONFIG_FIELDS,
3217
+ modeConfigFields: MODE_CONFIG_FIELDS,
3218
+ getDefaultModel,
3219
+ builtinProviderEnvKeys: BUILTIN_RUNTIME_PROVIDER_ENV_KEYS,
3220
+ builtinGatewayProviderEnvKeys: BUILTIN_RUNTIME_GATEWAY_PROVIDER_ENV_KEYS,
3221
+ piBuiltinProviderEnvKeys: PI_BUILTIN_PROVIDER_ENV_KEYS,
3222
+ providerKnownFieldsFor,
3223
+ stripControlledRuntimeEnvVars,
3224
+ composeRuntimeConfig
3225
+ });
3226
+ }
1596
3227
  function runtimeConfigModelValue(config) {
1597
3228
  return config.model.kind === "custom" ? config.model.name : config.model.id;
1598
3229
  }
1599
- function runtimeConfigToLaunchFields(config) {
1600
- const normalized = isPlainRecord(config) && config.version === RUNTIME_CONFIG_VERSION ? hydrateRuntimeConfig({ runtimeConfig: config }) : hydrateRuntimeConfig(config);
3230
+ function runtimeConfigSource(config) {
3231
+ if (config.runtime === "builtin") return "agent_config";
3232
+ if (config.runtime === "claude") {
3233
+ return config.provider?.kind === "custom" ? "agent_config" : "host_claude_config";
3234
+ }
3235
+ if (config.runtime === "pi") {
3236
+ return config.provider?.kind === "pi-builtin" ? "agent_config" : "local_pi_config";
3237
+ }
3238
+ return config.provider ? "agent_config" : "host_runtime_config";
3239
+ }
3240
+ function buildLaunchPlan(config) {
3241
+ const normalized = config;
1601
3242
  const generatedEnvVars = {};
3243
+ if (normalized.runtime === "builtin") {
3244
+ if (normalized.provider.kind === "preset") {
3245
+ const envKey = BUILTIN_RUNTIME_PROVIDER_ENV_KEYS[normalized.provider.providerId];
3246
+ if (envKey) generatedEnvVars[envKey] = normalized.provider.apiKey;
3247
+ }
3248
+ if (normalized.provider.kind === "gateway") {
3249
+ const apiKeyEnvKey = BUILTIN_RUNTIME_GATEWAY_PROVIDER_ENV_KEYS[normalized.provider.providerId];
3250
+ const baseUrlEnvKey = BUILTIN_RUNTIME_GATEWAY_PROVIDER_BASE_URL_ENV_KEYS[normalized.provider.providerId];
3251
+ if (apiKeyEnvKey) generatedEnvVars[apiKeyEnvKey] = normalized.provider.apiKey;
3252
+ if (baseUrlEnvKey) generatedEnvVars[baseUrlEnvKey] = normalized.provider.baseUrl;
3253
+ }
3254
+ }
1602
3255
  if (normalized.runtime === "claude") {
1603
3256
  if (normalized.provider?.kind === "custom") {
1604
3257
  generatedEnvVars.ANTHROPIC_BASE_URL = normalized.provider.apiUrl;
@@ -1617,14 +3270,30 @@ function runtimeConfigToLaunchFields(config) {
1617
3270
  ...generatedEnvVars
1618
3271
  };
1619
3272
  return {
3273
+ // Compatibility output for launch paths only; persist/re-parse RuntimeConfig for decisions instead of inferring config semantics back from env vars.
1620
3274
  runtime: normalized.runtime,
1621
3275
  model: runtimeConfigModelValue(normalized),
1622
3276
  mode: normalized.mode,
3277
+ configSource: runtimeConfigSource(normalized),
1623
3278
  reasoningEffort: normalized.reasoningEffort ?? null,
1624
3279
  envVars: Object.keys(envVars).length > 0 ? envVars : null,
1625
- ...normalized.command ? { command: normalized.command } : {}
3280
+ ...normalized.command ? { command: normalized.command } : {},
3281
+ trace: {
3282
+ outcome: "materialized",
3283
+ runtime: normalized.runtime,
3284
+ provider_kind: providerKind2(normalized),
3285
+ ...builtInSelectionTraceAttrs2(normalized),
3286
+ config_source: runtimeConfigSource(normalized),
3287
+ provider_key_present: providerKeyPresent(normalized),
3288
+ ...providerKeyPresent(normalized) ? { provider_key_source: "runtime_config_plaintext" } : {},
3289
+ env_key_count: Object.keys(envVars).length
3290
+ }
1626
3291
  };
1627
3292
  }
3293
+ function runtimeConfigToLaunchFields(config) {
3294
+ const { trace: _, configSource: _configSource, ...launchFields } = buildLaunchPlan(config);
3295
+ return launchFields;
3296
+ }
1628
3297
  var PRO_SEAT_MONTHLY_USD = 10;
1629
3298
  var PRO_AGENT_SEAT_BLOCK_SIZE = 10;
1630
3299
  var PRO_AGENT_SEAT_FRACTION = 1 / PRO_AGENT_SEAT_BLOCK_SIZE;
@@ -2136,30 +3805,32 @@ Use the \`raft\` CLI for chat / task / attachment operations (\`slock\` remains
2136
3805
  4. **\`raft channel members\`** \u2014 List the members (agents and humans) of a specific channel, DM, or thread target.
2137
3806
  5. **\`raft channel join\`** \u2014 Join a visible public channel. This only affects your own agent membership.
2138
3807
  6. **\`raft channel leave\`** \u2014 Leave a regular channel you have joined. This only affects your own agent membership.
2139
- 7. **\`raft thread unfollow\`** \u2014 Stop receiving ordinary delivery for a thread you no longer need to follow. This only affects your own agent attention state.
2140
- 8. **\`raft message read\`** \u2014 Read past messages from a channel, DM, or thread. Supports \`before\` / \`after\` anchors and \`around\` for centered context.
2141
- 9. **\`raft message search\`** \u2014 Search messages visible to you, then inspect a hit with \`raft message read\`.
2142
- 10. **\`raft message resolve\`** \u2014 Verify that a cited message id exists exactly and print its canonical message row. Use this when checking whether a referenced id is real; \`read --around\` is for context, not proof.
2143
- 11. **\`raft message react\`** \u2014 Add or remove your reaction on a message. Use sparingly: prefer acknowledgement/follow-up signals like \u{1F440}, and do not auto-react to every merge, deploy, or task completion with celebratory emoji.
2144
- 12. **\`raft task list\`** \u2014 View a channel's task board.
2145
- 13. **\`raft task create\`** \u2014 Create new task-messages in a channel (supports batch titles; equivalent to sending a new message and publishing it as a task-message, not claiming it for yourself).
2146
- 14. **\`raft task claim\`** \u2014 Claim tasks by number or message ID using repeatable flags; examples: \`raft task claim --channel "#channel" --number 1 --number 2\`, or \`raft task claim --channel "#channel" --message-id abc12345\`.
2147
- 15. **\`raft task unclaim\`** \u2014 Release your claim on a task.
2148
- 16. **\`raft task update\`** \u2014 Change a task's status (e.g. to in_review or done).
2149
- 17. **\`raft attachment upload\`** \u2014 Upload a file to attach to a message. Uses content sniffing for image previews; pass \`--mime-type\` only when you know the exact type. Returns an attachment ID to pass to \`raft message send\`.
2150
- 18. **\`raft attachment view\`** \u2014 Download an attached file by its attachment ID so you can inspect it locally.
2151
- 19. **\`raft profile show\`** \u2014 Show your own profile, or another visible profile via \`@handle\`. Mirrors the canonical Slock profile view.
2152
- 20. **\`raft profile update\`** \u2014 Update your own profile. Supports \`--avatar-file <path>\`, \`--avatar-url pixel:random:<seed>\`, \`--display-name <name>\`, and \`--description <text>\`. Use \`--avatar-url pixel:random:<seed>\` when you want a new pixel avatar but do not have a local image file. Values must be non-empty. Provide at least one flag per call; multiple flags can be combined.
2153
- 21. **\`raft integration list\`** \u2014 List built-in Slock apps, registered third-party services, and this agent's active Slock Agent Logins.
2154
- 22. **\`raft integration login\`** \u2014 Provision or reuse this agent's login for a built-in Slock app or registered third-party service.
2155
- 23. **\`raft integration env\`** \u2014 Print per-agent local CLI environment for a manifest-backed service that requires isolated HOME/XDG state.
2156
- 24. **\`raft reminder schedule\`** \u2014 Schedule a reminder for yourself later, at a specific time, or on a recurring cadence.
2157
- 25. **\`raft reminder list\`** \u2014 List your reminders, including lifecycle history for each reminder.
2158
- 26. **\`raft reminder snooze\`** \u2014 Push a reminder later without replacing it.
2159
- 27. **\`raft reminder update\`** \u2014 Change a reminder's title, schedule, or recurrence without creating a new reminder.
2160
- 28. **\`raft reminder cancel\`** \u2014 Cancel one of your reminders by ID.
2161
- 29. **\`raft reminder log\`** \u2014 Show the event log for a reminder, including fires, dismissals, and reschedules.
2162
- 30. **\`raft action prepare\`** \u2014 Prepare an action card for a human to commit (B-mode quick-commit shortcut). Posts a card the human can click to execute the action under their own identity. Pass \`--target <ch>\` and pipe the action JSON on stdin (variants: \`channel:create\`, \`agent:create\`).
3808
+ 7. **\`raft channel mute\`** \u2014 Mute ordinary Activity delivery for a regular channel for your agent. Personal @mentions, DMs, and tasks still pierce.
3809
+ 8. **\`raft channel unmute\`** \u2014 Unmute ordinary Activity delivery for a regular channel for your agent. Muted-window messages are not retroactively promoted.
3810
+ 9. **\`raft thread unfollow\`** \u2014 Stop receiving ordinary delivery for a thread you no longer need to follow. This only affects your own agent attention state.
3811
+ 10. **\`raft message read\`** \u2014 Read past messages from a channel, DM, or thread. Supports \`before\` / \`after\` anchors and \`around\` for centered context.
3812
+ 11. **\`raft message search\`** \u2014 Search messages visible to you, then inspect a hit with \`raft message read\`.
3813
+ 12. **\`raft message resolve\`** \u2014 Verify that a cited message id exists exactly and print its canonical message row. Use this when checking whether a referenced id is real; \`read --around\` is for context, not proof.
3814
+ 13. **\`raft message react\`** \u2014 Add or remove your reaction on a message. Use sparingly: prefer acknowledgement/follow-up signals like \u{1F440}, and do not auto-react to every merge, deploy, or task completion with celebratory emoji.
3815
+ 14. **\`raft task list\`** \u2014 View a channel's task board.
3816
+ 15. **\`raft task create\`** \u2014 Create new task-messages in a channel (supports batch titles; equivalent to sending a new message and publishing it as a task-message, not claiming it for yourself).
3817
+ 16. **\`raft task claim\`** \u2014 Claim tasks by number or message ID using repeatable flags; examples: \`raft task claim --channel "#channel" --number 1 --number 2\`, or \`raft task claim --channel "#channel" --message-id abc12345\`.
3818
+ 17. **\`raft task unclaim\`** \u2014 Release your claim on a task.
3819
+ 18. **\`raft task update\`** \u2014 Change a task's status (e.g. to in_review or done).
3820
+ 19. **\`raft attachment upload\`** \u2014 Upload a file to attach to a message. Uses content sniffing for image previews; pass \`--mime-type\` only when you know the exact type. Returns an attachment ID to pass to \`raft message send\`.
3821
+ 20. **\`raft attachment view\`** \u2014 Download an attached file by its attachment ID so you can inspect it locally.
3822
+ 21. **\`raft profile show\`** \u2014 Show your own profile, or another visible profile via \`@handle\`. Mirrors the canonical Slock profile view.
3823
+ 22. **\`raft profile update\`** \u2014 Update your own profile. Supports \`--avatar-file <path>\`, \`--avatar-url pixel:random:<seed>\`, \`--display-name <name>\`, and \`--description <text>\`. Use \`--avatar-url pixel:random:<seed>\` when you want a new pixel avatar but do not have a local image file. Values must be non-empty. Provide at least one flag per call; multiple flags can be combined.
3824
+ 23. **\`raft integration list\`** \u2014 List built-in Slock apps, registered third-party services, and this agent's active Slock Agent Logins.
3825
+ 24. **\`raft integration login\`** \u2014 Provision or reuse this agent's login for a built-in Slock app or registered third-party service.
3826
+ 25. **\`raft integration env\`** \u2014 Print per-agent local CLI environment for a manifest-backed service that requires isolated HOME/XDG state.
3827
+ 26. **\`raft reminder schedule\`** \u2014 Schedule a reminder for yourself later, at a specific time, or on a recurring cadence.
3828
+ 27. **\`raft reminder list\`** \u2014 List your reminders, including lifecycle history for each reminder.
3829
+ 28. **\`raft reminder snooze\`** \u2014 Push a reminder later without replacing it.
3830
+ 29. **\`raft reminder update\`** \u2014 Change a reminder's title, schedule, or recurrence without creating a new reminder.
3831
+ 30. **\`raft reminder cancel\`** \u2014 Cancel one of your reminders by ID.
3832
+ 31. **\`raft reminder log\`** \u2014 Show the event log for a reminder, including fires, dismissals, and reschedules.
3833
+ 32. **\`raft action prepare\`** \u2014 Prepare an action card for a human to commit (B-mode quick-commit shortcut). Posts a card the human can click to execute the action under their own identity. Pass \`--target <ch>\` and pipe the action JSON on stdin (variants: \`channel:create\`, \`agent:create\`).
2163
3834
 
2164
3835
  The CLI prints human-readable canonical text on success (matching the format you see in received messages and history). On failure it prints canonical labeled text to stderr:
2165
3836
  - \`Error:\` human-readable error summary
@@ -2230,7 +3901,7 @@ function buildDiscoverySection() {
2230
3901
  return `### Discovering people and channels
2231
3902
 
2232
3903
  Call \`raft server info\` to see all channels in this server, which ones you have joined, other agents, and humans.
2233
- Visible public channels may appear even when \`joined=false\`. In that state you can still inspect them with \`raft message read\` and \`raft channel members\`, but you cannot send messages there or receive ordinary channel delivery until you join with \`raft channel join --target "#channel-name"\`. Private channels require a human with access to add you. To leave a regular channel you have joined, use \`raft channel leave --target "#channel-name"\`. To stop following a thread without leaving its parent channel, use \`raft thread unfollow --target "#channel-name:shortid"\`.
3904
+ Visible public channels may appear even when \`joined=false\`. In that state you can still inspect them with \`raft message read\` and \`raft channel members\`, but you cannot send messages there or receive ordinary channel delivery until you join with \`raft channel join --target "#channel-name"\`. Private channels require a human with access to add you. To leave a regular channel you have joined, use \`raft channel leave --target "#channel-name"\`. To mute ordinary Activity delivery without leaving a regular channel, use \`raft channel mute "#channel-name"\`; personal @mentions, DMs, and tasks still pierce, and thread following is separate. To reverse that setting, use \`raft channel unmute "#channel-name"\`. To stop following a thread without leaving its parent channel, use \`raft thread unfollow --target "#channel-name:shortid"\`.
2234
3905
  Private channels are membership-gated. If \`raft server info\` shows a channel as private, treat its name, members, and content as private to that channel; do not disclose that information in other channels, DMs, summaries, or task reports unless a human explicitly asks within an authorized context. In \`raft channel members\`, human role labels such as owner/admin show server-level authority; no role label means ordinary member.`;
2235
3906
  }
2236
3907
  function buildChannelAwarenessSection() {
@@ -2506,7 +4177,7 @@ function buildPrompt(config, opts) {
2506
4177
  const channelAwarenessSection = cliGuideSections.channelAwareness;
2507
4178
  const thirdPartyIntegrationsSection = `### Third-party integrations
2508
4179
 
2509
- If a built-in Slock app or registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app or built-in Slock app, first run \`raft integration list\` and match the app to a listed service before browsing the app. Use \`raft integration login --service <service>\` to provision or reuse your agent login for that service. If the service exposes an agent behavior manifest and you need to run its local CLI, run \`raft integration env --service <service>\` before invoking that CLI; if it prints exports, apply them first so service credentials stay under a per-agent profile HOME/XDG tree instead of the host user's global HOME. If it reports that no local env is required, do not invent HOME/XDG overrides. If it fails, do not run that local CLI with the host user's HOME; report that the service manifest is unsupported. Slock does not execute commands from remote manifests automatically. If the CLI reports that the \`integration\` command is unknown, the local daemon/CLI is too old for Slock Agent Login; report that the machine must be upgraded/restarted instead of calling internal HTTP endpoints yourself. When the command returns \`Agent login ready\` or \`Already logged in\`, the agent-side login is ready. If the output includes an app URL, open that URL as the service-provided app surface; it should look like the service's normal Login with Slock callback and not require you to understand Slock's internal grant/request protocol. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow, use internal request IDs as OAuth callback codes, call internal Slock integration endpoints directly, or call third-party exchange endpoints unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use \`raft profile show\`. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the listed service / Slock Agent Login path.`;
4180
+ If a built-in Slock app or registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app or built-in Slock app, first run \`raft integration list\` and match the app to a listed service before browsing the app. Use \`raft integration login --service <service>\` to provision or reuse your agent login for that service. If the service exposes an agent behavior manifest and you need to run its local CLI, run \`raft integration env --service <service>\` before invoking that CLI; if it prints exports, apply them first so service credentials stay under a per-agent profile HOME/XDG tree instead of the host user's global HOME. If it reports that no local env is required, do not invent HOME/XDG overrides. If it fails, do not run that local CLI with the host user's HOME; report that the service manifest is unsupported. Slock does not execute commands from remote manifests automatically. If the CLI reports that the \`integration\` command is unknown, the local daemon/CLI is too old for Slock Agent Login; report that the machine must be upgraded/restarted instead of calling internal HTTP endpoints yourself. When the command returns \`Agent login ready\` or \`Already logged in\`, the agent-side login is ready. If the output includes a service callback handoff URL, treat it as the registered OAuth callback carrying an Agent Login request code, not as a normal browser app URL; open it only when the service documents a stateless Agent Login callback that accepts that URL directly. Otherwise use the service docs, API, or manifest entry point. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow, use internal request IDs as OAuth callback codes, call internal Slock integration endpoints directly, or call third-party exchange endpoints unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use \`raft profile show\`. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the listed service / Slock Agent Login path.`;
2510
4181
  const readingHistorySection = cliGuideSections.readingHistory;
2511
4182
  const historicalReferenceSection = cliGuideSections.historicalReferences;
2512
4183
  const tasksSection = cliGuideSections.tasks;
@@ -2694,6 +4365,19 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
2694
4365
  return candidates.filter((candidate) => existsSync(candidate.path));
2695
4366
  }
2696
4367
 
4368
+ // src/authEnv.ts
4369
+ var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
4370
+ var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
4371
+ function scrubDaemonAuthEnv(env) {
4372
+ delete env[DAEMON_API_KEY_ENV];
4373
+ return env;
4374
+ }
4375
+ function scrubDaemonChildEnv(env) {
4376
+ delete env[DAEMON_API_KEY_ENV];
4377
+ delete env[SLOCK_AGENT_TOKEN_ENV];
4378
+ return env;
4379
+ }
4380
+
2697
4381
  // src/agentCredentialProxy.ts
2698
4382
  import { randomBytes } from "crypto";
2699
4383
  import http from "http";
@@ -3486,6 +5170,7 @@ function heldPlan(input, held, trace) {
3486
5170
  localResponse: projectApmHeldFreshnessEnvelope({
3487
5171
  producerFactId,
3488
5172
  action: input.action,
5173
+ decision: held.decision.decision,
3489
5174
  heldMessages: held.context.heldMessages,
3490
5175
  newMessageCount: held.context.newMessageCount,
3491
5176
  omittedMessageCount: held.context.omittedMessageCount,
@@ -4261,7 +5946,9 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
4261
5946
  var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
4262
5947
  var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
4263
5948
  var RAW_CREDENTIAL_ENV_DENYLIST = [
4264
- "SLOCK_AGENT_CREDENTIAL_KEY"
5949
+ "SLOCK_AGENT_TOKEN",
5950
+ "SLOCK_AGENT_CREDENTIAL_KEY",
5951
+ "SLOCK_AGENT_CREDENTIAL_KEY_FILE"
4265
5952
  ];
4266
5953
  var WORKSPACE_CLI_TRANSPORT_FILENAMES = [
4267
5954
  "agent-token",
@@ -4601,7 +6288,7 @@ set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
4601
6288
  writeOpencliWrapper(slockDir, opencliBinPath, platform, execIsElectron);
4602
6289
  }
4603
6290
  const wrapperPath = platform === "win32" ? path2.join(slockDir, "slock.cmd") : posixWrapper;
4604
- const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
6291
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config));
4605
6292
  const spawnEnv = {
4606
6293
  ...process.env,
4607
6294
  FORCE_COLOR: "0",
@@ -4616,7 +6303,7 @@ set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
4616
6303
  SLOCK_SERVER_URL: ctx.config.serverUrl,
4617
6304
  PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
4618
6305
  };
4619
- delete spawnEnv.SLOCK_AGENT_TOKEN;
6306
+ scrubDaemonChildEnv(spawnEnv);
4620
6307
  for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
4621
6308
  delete spawnEnv[key];
4622
6309
  }
@@ -4928,7 +6615,7 @@ var CLAUDE_CUSTOM_PROVIDER_HOST_ENV_KEYS = [
4928
6615
  "CLAUDE_CODE_USE_CCR_V2"
4929
6616
  ];
4930
6617
  function isClaudeCustomProviderConfig(config) {
4931
- const launchRuntimeFields = runtimeConfigToLaunchFields(config);
6618
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(config));
4932
6619
  return launchRuntimeFields.runtime === "claude" && Boolean(launchRuntimeFields.envVars?.ANTHROPIC_BASE_URL) && Boolean(launchRuntimeFields.envVars?.ANTHROPIC_API_KEY);
4933
6620
  }
4934
6621
  function clearInheritedClaudeProviderEnv(explicitEnv) {
@@ -4970,7 +6657,7 @@ function buildClaudeProviderIsolationEnv(ctx) {
4970
6657
  if (!isClaudeCustomProviderConfig(ctx.config)) {
4971
6658
  return {};
4972
6659
  }
4973
- const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
6660
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config));
4974
6661
  return {
4975
6662
  ...clearInheritedClaudeProviderEnv(launchRuntimeFields.envVars)
4976
6663
  };
@@ -5138,7 +6825,7 @@ function requiresWindowsShell(command, platform = process.platform) {
5138
6825
  }
5139
6826
  function resolveCommandOnPath(command, deps = {}) {
5140
6827
  const platform = deps.platform ?? process.platform;
5141
- const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
6828
+ const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
5142
6829
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
5143
6830
  const existsSyncFn = deps.existsSyncFn ?? existsSync3;
5144
6831
  if (platform === "win32") {
@@ -5164,7 +6851,7 @@ function firstExistingPath(candidates, deps = {}) {
5164
6851
  return null;
5165
6852
  }
5166
6853
  function readCommandVersion(command, args = [], deps = {}) {
5167
- const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
6854
+ const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
5168
6855
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
5169
6856
  try {
5170
6857
  const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
@@ -5204,7 +6891,7 @@ function resolveClaudeCommand(deps = {}) {
5204
6891
  ], deps);
5205
6892
  }
5206
6893
  function resolveClaudeLaunchCommand(config, deps = {}) {
5207
- const launchRuntimeFields = runtimeConfigToLaunchFields(config);
6894
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(config));
5208
6895
  return launchRuntimeFields.command?.trim() || resolveClaudeCommand(deps);
5209
6896
  }
5210
6897
  function probeClaude(deps = {}) {
@@ -5216,7 +6903,7 @@ function probeClaude(deps = {}) {
5216
6903
  };
5217
6904
  }
5218
6905
  function buildClaudeArgs(config, opts) {
5219
- const launchRuntimeFields = runtimeConfigToLaunchFields(config);
6906
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(config));
5220
6907
  const args = [
5221
6908
  "--allow-dangerously-skip-permissions",
5222
6909
  "--dangerously-skip-permissions",
@@ -5387,14 +7074,14 @@ function resolveCodexHomeRootFromEnv(env = process.env, opts = {}) {
5387
7074
  return path6.join(opts.defaultHomeDir ?? os2.homedir(), ".codex");
5388
7075
  }
5389
7076
  function hasConfiguredCodexHome(config, baseEnv = process.env) {
5390
- const launchRuntimeFields = config ? runtimeConfigToLaunchFields(config) : null;
7077
+ const launchRuntimeFields = config ? runtimeConfigToLaunchFields(hydrateRuntimeConfig(config)) : null;
5391
7078
  return Boolean(readConfiguredCodexHome({
5392
7079
  ...baseEnv,
5393
7080
  ...launchRuntimeFields?.envVars || {}
5394
7081
  }));
5395
7082
  }
5396
7083
  function resolveCodexHomeRootFromConfig(config, defaultHomeDir, cwd, baseEnv = process.env, _opts = {}) {
5397
- const launchRuntimeFields = runtimeConfigToLaunchFields(config);
7084
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(config));
5398
7085
  const env = {
5399
7086
  ...baseEnv,
5400
7087
  ...launchRuntimeFields.envVars || {}
@@ -6306,7 +7993,7 @@ var CodexDriver = class {
6306
7993
  // the daemon. They replace the previous transcript-mtime heuristic.
6307
7994
  experimentalRawEvents: true
6308
7995
  };
6309
- const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
7996
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config));
6310
7997
  if (launchRuntimeFields.model) {
6311
7998
  threadParams.model = launchRuntimeFields.model;
6312
7999
  }
@@ -6847,7 +8534,7 @@ function buildAntigravityArgs(ctx) {
6847
8534
  const args = [
6848
8535
  "--print",
6849
8536
  "--print-timeout",
6850
- runtimeConfigToLaunchFields(ctx.config).envVars?.ANTIGRAVITY_PRINT_TIMEOUT || DEFAULT_PRINT_TIMEOUT,
8537
+ runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config)).envVars?.ANTIGRAVITY_PRINT_TIMEOUT || DEFAULT_PRINT_TIMEOUT,
6851
8538
  "--dangerously-skip-permissions"
6852
8539
  ];
6853
8540
  if (ctx.config.sessionId) {
@@ -6990,7 +8677,7 @@ var CopilotDriver = class {
6990
8677
  "-p",
6991
8678
  ctx.prompt
6992
8679
  ];
6993
- const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
8680
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config));
6994
8681
  if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
6995
8682
  args.push("--model", launchRuntimeFields.model);
6996
8683
  }
@@ -7128,7 +8815,7 @@ var CursorDriver = class {
7128
8815
  "--approve-mcps",
7129
8816
  "--trust"
7130
8817
  ];
7131
- const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
8818
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config));
7132
8819
  if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
7133
8820
  args.push("--model", launchRuntimeFields.model);
7134
8821
  }
@@ -7248,11 +8935,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
7248
8935
  return parseCursorModelsOutput(String(result.stdout || ""));
7249
8936
  }
7250
8937
  function buildCursorModelProbeEnv(deps = {}) {
7251
- return withWindowsUserEnvironment({
8938
+ return scrubDaemonChildEnv(withWindowsUserEnvironment({
7252
8939
  ...deps.env ?? process.env,
7253
8940
  FORCE_COLOR: "0",
7254
8941
  NO_COLOR: "1"
7255
- }, deps);
8942
+ }, deps));
7256
8943
  }
7257
8944
  function runCursorModelsCommand() {
7258
8945
  return spawnSync("cursor-agent", ["models"], {
@@ -7268,7 +8955,7 @@ import { existsSync as existsSync5 } from "fs";
7268
8955
  import path8 from "path";
7269
8956
  async function buildGeminiSpawnEnv(ctx, platform = process.platform) {
7270
8957
  const { spawnEnv } = await prepareCliTransport(ctx, { NO_COLOR: "1" }, platform);
7271
- const launchEnvVars = runtimeConfigToLaunchFields(ctx.config).envVars;
8958
+ const launchEnvVars = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config)).envVars;
7272
8959
  if (!Object.prototype.hasOwnProperty.call(launchEnvVars ?? {}, "GEMINI_CLI_TRUST_WORKSPACE")) {
7273
8960
  spawnEnv.GEMINI_CLI_TRUST_WORKSPACE = "true";
7274
8961
  }
@@ -7292,7 +8979,7 @@ function buildGeminiArgs(config) {
7292
8979
  "-p",
7293
8980
  ""
7294
8981
  ];
7295
- const launchRuntimeFields = runtimeConfigToLaunchFields(config);
8982
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(config));
7296
8983
  if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
7297
8984
  args.push("--model", launchRuntimeFields.model);
7298
8985
  }
@@ -7308,7 +8995,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
7308
8995
  }
7309
8996
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
7310
8997
  const existsSyncFn = deps.existsSyncFn ?? existsSync5;
7311
- const env = deps.env ?? process.env;
8998
+ const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
7312
8999
  const winPath = path8.win32;
7313
9000
  let geminiEntry = null;
7314
9001
  try {
@@ -7445,12 +9132,15 @@ var GeminiDriver = class {
7445
9132
  // src/drivers/kimi.ts
7446
9133
  import { randomUUID as randomUUID2 } from "crypto";
7447
9134
  import { spawn as spawn7 } from "child_process";
7448
- import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
9135
+ import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
7449
9136
  import os4 from "os";
7450
9137
  import path9 from "path";
7451
9138
  var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
7452
9139
  var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
7453
9140
  var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
9141
+ var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
9142
+ var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
9143
+ var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
7454
9144
  function parseToolArguments(raw) {
7455
9145
  if (typeof raw !== "string") return raw;
7456
9146
  try {
@@ -7459,6 +9149,73 @@ function parseToolArguments(raw) {
7459
9149
  return raw;
7460
9150
  }
7461
9151
  }
9152
+ function readKimiConfigSource(home = os4.homedir(), env = process.env) {
9153
+ const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
9154
+ if (inlineConfig && inlineConfig.trim()) {
9155
+ return {
9156
+ raw: inlineConfig,
9157
+ explicitPath: null,
9158
+ sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
9159
+ };
9160
+ }
9161
+ const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
9162
+ const configPath = explicitPath && explicitPath.trim() ? explicitPath : path9.join(home, ".kimi", "config.toml");
9163
+ try {
9164
+ return {
9165
+ raw: readFileSync3(configPath, "utf8"),
9166
+ explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
9167
+ sourcePath: configPath
9168
+ };
9169
+ } catch {
9170
+ return {
9171
+ raw: null,
9172
+ explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
9173
+ sourcePath: configPath
9174
+ };
9175
+ }
9176
+ }
9177
+ function buildKimiSpawnEnv(env = process.env) {
9178
+ const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
9179
+ delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
9180
+ delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
9181
+ return scrubDaemonChildEnv(spawnEnv);
9182
+ }
9183
+ function buildKimiEffectiveEnv(ctx, overrideEnv) {
9184
+ return {
9185
+ ...process.env,
9186
+ ...ctx.config.envVars || {},
9187
+ ...overrideEnv || {}
9188
+ };
9189
+ }
9190
+ function buildKimiLaunchOptions(ctx, opts = {}) {
9191
+ const env = buildKimiEffectiveEnv(ctx, opts.env);
9192
+ const source = readKimiConfigSource(opts.home ?? os4.homedir(), env);
9193
+ const args = [];
9194
+ let configFilePath = null;
9195
+ let configContent = null;
9196
+ if (source.explicitPath) {
9197
+ configFilePath = source.explicitPath;
9198
+ } else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
9199
+ configFilePath = path9.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
9200
+ configContent = source.raw;
9201
+ if (opts.writeGeneratedConfig !== false) {
9202
+ writeFileSync3(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
9203
+ chmodSync(configFilePath, 384);
9204
+ }
9205
+ }
9206
+ if (configFilePath) {
9207
+ args.push("--config-file", configFilePath);
9208
+ }
9209
+ if (ctx.config.model && ctx.config.model !== "default") {
9210
+ args.push("--model", ctx.config.model);
9211
+ }
9212
+ return {
9213
+ args,
9214
+ env: buildKimiSpawnEnv(env),
9215
+ configFilePath,
9216
+ configContent
9217
+ };
9218
+ }
7462
9219
  function resolveKimiSpawn(commandArgs, deps = {}) {
7463
9220
  return {
7464
9221
  command: resolveCommandOnPath("kimi", deps) ?? "kimi",
@@ -7482,7 +9239,25 @@ var KimiDriver = class {
7482
9239
  };
7483
9240
  model = {
7484
9241
  detectedModelsVerifiedAs: "launchable",
7485
- toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
9242
+ toLaunchSpec: (modelId, ctx, opts) => {
9243
+ if (!ctx) return { args: ["--model", modelId] };
9244
+ const launchCtx = {
9245
+ ...ctx,
9246
+ config: {
9247
+ ...ctx.config,
9248
+ model: modelId
9249
+ }
9250
+ };
9251
+ const launch = buildKimiLaunchOptions(launchCtx, {
9252
+ home: opts?.home,
9253
+ writeGeneratedConfig: false
9254
+ });
9255
+ return {
9256
+ args: launch.args,
9257
+ env: launch.env,
9258
+ configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
9259
+ };
9260
+ }
7486
9261
  };
7487
9262
  supportsStdinNotification = true;
7488
9263
  busyDeliveryMode = "direct";
@@ -7506,21 +9281,23 @@ var KimiDriver = class {
7506
9281
  ` system_prompt_path: ./${KIMI_SYSTEM_PROMPT_FILE}`,
7507
9282
  ""
7508
9283
  ].join("\n"), "utf8");
9284
+ const launch = buildKimiLaunchOptions(ctx);
7509
9285
  const args = [
7510
9286
  "--wire",
7511
9287
  "--yolo",
7512
9288
  "--agent-file",
7513
9289
  agentFilePath,
7514
9290
  "--session",
7515
- this.sessionId
9291
+ this.sessionId,
9292
+ ...launch.args
7516
9293
  ];
7517
- const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
9294
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config));
7518
9295
  if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
7519
9296
  args.push("--model", launchRuntimeFields.model);
7520
9297
  }
7521
9298
  const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
7522
- const launch = resolveKimiSpawn(args);
7523
- const proc = spawn7(launch.command, launch.args, {
9299
+ const spawnTarget = resolveKimiSpawn(args);
9300
+ const proc = spawn7(spawnTarget.command, spawnTarget.args, {
7524
9301
  cwd: ctx.workingDirectory,
7525
9302
  stdio: ["pipe", "pipe", "pipe"],
7526
9303
  env: spawnEnv,
@@ -7528,7 +9305,7 @@ var KimiDriver = class {
7528
9305
  // and has an 8191-character command-line limit. Kimi's official
7529
9306
  // installer/uv entrypoint is an executable, so launch it directly and
7530
9307
  // keep prompts on stdin / files instead of routing through cmd.exe.
7531
- shell: launch.shell
9308
+ shell: spawnTarget.shell
7532
9309
  });
7533
9310
  proc.stdin?.write(JSON.stringify({
7534
9311
  jsonrpc: "2.0",
@@ -7641,14 +9418,9 @@ var KimiDriver = class {
7641
9418
  return detectKimiModels();
7642
9419
  }
7643
9420
  };
7644
- function detectKimiModels(home = os4.homedir()) {
7645
- const configPath = path9.join(home, ".kimi", "config.toml");
7646
- let raw;
7647
- try {
7648
- raw = readFileSync3(configPath, "utf8");
7649
- } catch {
7650
- return null;
7651
- }
9421
+ function detectKimiModels(home = os4.homedir(), opts = {}) {
9422
+ const raw = readKimiConfigSource(home, opts.env).raw;
9423
+ if (raw === null) return null;
7652
9424
  const models = [];
7653
9425
  const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
7654
9426
  const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
@@ -7833,7 +9605,7 @@ async function createKimiAgentSessionForContext(ctx, sessionId) {
7833
9605
  userAgentSuffix: `slock-daemon/${getDaemonVersion()}`
7834
9606
  }
7835
9607
  });
7836
- const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
9608
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config));
7837
9609
  const sessionFields = {
7838
9610
  workDir: ctx.workingDirectory,
7839
9611
  ...launchRuntimeFields.model && launchRuntimeFields.model !== "default" ? { model: launchRuntimeFields.model } : {}
@@ -8174,7 +9946,7 @@ function parseOpenCodeConfigContent(raw) {
8174
9946
  return {};
8175
9947
  }
8176
9948
  function parseUserOpenCodeConfig(ctx) {
8177
- const raw = runtimeConfigToLaunchFields(ctx.config).envVars?.OPENCODE_CONFIG_CONTENT;
9949
+ const raw = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config)).envVars?.OPENCODE_CONFIG_CONTENT;
8178
9950
  return parseOpenCodeConfigContent(raw);
8179
9951
  }
8180
9952
  function readLocalOpenCodeConfig(home = os5.homedir()) {
@@ -8272,7 +10044,7 @@ async function buildOpenCodeLaunchOptions(ctx, home = os5.homedir(), version = n
8272
10044
  "--dir",
8273
10045
  ctx.workingDirectory
8274
10046
  ];
8275
- const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
10047
+ const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config));
8276
10048
  if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
8277
10049
  args.push("--model", launchRuntimeFields.model);
8278
10050
  }
@@ -8314,7 +10086,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
8314
10086
  const platform = deps.platform ?? process.platform;
8315
10087
  const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
8316
10088
  const result = spawnSyncFn("opencode", ["models"], {
8317
- env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
10089
+ env: scrubDaemonChildEnv({ ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" }),
8318
10090
  encoding: "utf8",
8319
10091
  timeout: 5e3,
8320
10092
  shell: platform === "win32"
@@ -8586,7 +10358,25 @@ import {
8586
10358
  VERSION as PI_SDK_VERSION
8587
10359
  } from "@earendil-works/pi-coding-agent";
8588
10360
  var PI_SESSION_DIR = ".pi-sessions";
10361
+ var BUILTIN_SESSION_DIR = ".builtin-sessions";
10362
+ var BUILTIN_AGENT_DIR = ".builtin-runtime";
8589
10363
  var PI_SDK_COMPACTION_ENABLED = true;
10364
+ var BUILTIN_BLOCKED_HOST_AMBIENT_CREDENTIAL_ENV_KEYS = [
10365
+ "AZURE_OPENAI_BASE_URL",
10366
+ "AZURE_OPENAI_RESOURCE_NAME",
10367
+ "AZURE_OPENAI_API_VERSION",
10368
+ "AZURE_OPENAI_DEPLOYMENT_NAME_MAP",
10369
+ "CLOUDFLARE_ACCOUNT_ID",
10370
+ "AWS_PROFILE",
10371
+ "AWS_ACCESS_KEY_ID",
10372
+ "AWS_SECRET_ACCESS_KEY",
10373
+ "AWS_BEARER_TOKEN_BEDROCK",
10374
+ "AWS_REGION"
10375
+ ];
10376
+ var BUILTIN_BLOCKED_HOST_PROVIDER_ENV_KEYS = Array.from(/* @__PURE__ */ new Set([
10377
+ ...BUILTIN_RUNTIME_HOST_PROVIDER_ENV_SCRUB_KEYS,
10378
+ ...BUILTIN_BLOCKED_HOST_AMBIENT_CREDENTIAL_ENV_KEYS
10379
+ ]));
8590
10380
  function createPiSdkEventMappingState(sessionId = null) {
8591
10381
  return {
8592
10382
  sessionId,
@@ -8597,9 +10387,77 @@ function createPiSdkEventMappingState(sessionId = null) {
8597
10387
  function buildPiSessionDir(workingDirectory) {
8598
10388
  return path12.join(workingDirectory, PI_SESSION_DIR);
8599
10389
  }
10390
+ function buildBuiltInSessionDir(workingDirectory) {
10391
+ return path12.join(workingDirectory, BUILTIN_SESSION_DIR);
10392
+ }
10393
+ function buildBuiltInAgentDir(workingDirectory) {
10394
+ return path12.join(workingDirectory, BUILTIN_AGENT_DIR);
10395
+ }
8600
10396
  async function buildPiSpawnEnv(ctx) {
8601
10397
  return (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
8602
10398
  }
10399
+ function seedBuiltInAuthStorage(authStorage, runtimeConfig) {
10400
+ if (runtimeConfig.runtime !== "builtin") return;
10401
+ if (runtimeConfig.provider.kind === "preset") {
10402
+ authStorage.setRuntimeApiKey(runtimeConfig.provider.providerId, runtimeConfig.provider.apiKey);
10403
+ return;
10404
+ }
10405
+ if (runtimeConfig.provider.providerId === "openai-compatible") {
10406
+ authStorage.setRuntimeApiKey("openai", runtimeConfig.provider.apiKey);
10407
+ } else if (runtimeConfig.provider.providerId === "anthropic-compatible") {
10408
+ authStorage.setRuntimeApiKey("anthropic", runtimeConfig.provider.apiKey);
10409
+ }
10410
+ }
10411
+ function buildPiSessionCreateEnvPatch(runtimeConfig, envVars) {
10412
+ if (runtimeConfig.runtime !== "builtin" || !envVars) return envVars;
10413
+ const providerApiKeyEnvNames = /* @__PURE__ */ new Set([
10414
+ ...Object.values(BUILTIN_RUNTIME_PROVIDER_ENV_KEYS),
10415
+ ...Object.values(BUILTIN_RUNTIME_GATEWAY_PROVIDER_ENV_KEYS)
10416
+ ]);
10417
+ const filtered = Object.fromEntries(
10418
+ Object.entries(envVars).filter(([key]) => !providerApiKeyEnvNames.has(key))
10419
+ );
10420
+ return Object.keys(filtered).length > 0 ? filtered : null;
10421
+ }
10422
+ var processEnvPatchTail = Promise.resolve();
10423
+ async function runWithProcessEnvPatchLock(fn) {
10424
+ const previous = processEnvPatchTail;
10425
+ let release;
10426
+ processEnvPatchTail = new Promise((resolve) => {
10427
+ release = resolve;
10428
+ });
10429
+ await previous;
10430
+ try {
10431
+ return await fn();
10432
+ } finally {
10433
+ release();
10434
+ }
10435
+ }
10436
+ async function withProcessEnvPatch(patch, fn, opts = {}) {
10437
+ const keys = /* @__PURE__ */ new Set([...opts.removeFirst ?? [], ...Object.keys(patch ?? {})]);
10438
+ if (keys.size === 0) return fn();
10439
+ return runWithProcessEnvPatchLock(async () => {
10440
+ const previous = {};
10441
+ for (const key of keys) {
10442
+ previous[key] = process.env[key];
10443
+ delete process.env[key];
10444
+ }
10445
+ for (const [key, value] of Object.entries(patch ?? {})) {
10446
+ process.env[key] = value;
10447
+ }
10448
+ try {
10449
+ return await fn();
10450
+ } finally {
10451
+ for (const [key, value] of Object.entries(previous)) {
10452
+ if (value === void 0) {
10453
+ delete process.env[key];
10454
+ } else {
10455
+ process.env[key] = value;
10456
+ }
10457
+ }
10458
+ }
10459
+ });
10460
+ }
8603
10461
  function resolvePiModelFromRegistry(modelId, modelRegistry) {
8604
10462
  if (!modelId || modelId === "default") return void 0;
8605
10463
  const [provider, ...modelParts] = modelId.split("/");
@@ -8608,6 +10466,27 @@ function resolvePiModelFromRegistry(modelId, modelRegistry) {
8608
10466
  }
8609
10467
  return modelRegistry.getAll().find((model) => model.id === modelId);
8610
10468
  }
10469
+ function configureBuiltInGatewayCustomModel(modelRegistry, runtimeConfig) {
10470
+ if (runtimeConfig.runtime !== "builtin") return;
10471
+ if (runtimeConfig.provider.kind !== "gateway") return;
10472
+ if (runtimeConfig.model.kind !== "custom") return;
10473
+ const provider = runtimeConfig.provider.providerId === "openai-compatible" ? { id: "openai", api: "openai-completions", apiKeyEnv: "OPENAI_API_KEY" } : { id: "anthropic", api: "anthropic-messages", apiKeyEnv: "ANTHROPIC_API_KEY" };
10474
+ modelRegistry.registerProvider(provider.id, {
10475
+ name: getRuntimeProviderDisplayName(runtimeConfig.provider.providerId),
10476
+ baseUrl: runtimeConfig.provider.baseUrl,
10477
+ apiKey: `$${provider.apiKeyEnv}`,
10478
+ api: provider.api,
10479
+ models: [{
10480
+ id: runtimeConfig.model.name,
10481
+ name: runtimeConfig.model.name,
10482
+ reasoning: true,
10483
+ input: ["text"],
10484
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
10485
+ contextWindow: 2e5,
10486
+ maxTokens: 8192
10487
+ }]
10488
+ });
10489
+ }
8611
10490
  function findPiSessionFile(sessionDir, sessionId) {
8612
10491
  let entries;
8613
10492
  try {
@@ -8814,12 +10693,25 @@ var PI_RUNTIME_SESSION_DESCRIPTOR = {
8814
10693
  };
8815
10694
  var PI_IDLE_PROMPT_RETRY_MS = 25;
8816
10695
  var PI_IDLE_PROMPT_MAX_WAIT_MS = 1e3;
8817
- async function createPiAgentSessionForContext(ctx, sessionId) {
8818
- const sessionDir = buildPiSessionDir(ctx.workingDirectory);
10696
+ async function createPiAgentSessionForContext(ctx, sessionId, opts = {}) {
10697
+ const sessionDir = opts.sessionDir ?? buildPiSessionDir(ctx.workingDirectory);
8819
10698
  mkdirSync3(sessionDir, { recursive: true });
8820
- const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
10699
+ const runtimeConfig = hydrateRuntimeConfig(ctx.config);
10700
+ const launchPlan = buildLaunchPlan(runtimeConfig);
10701
+ const { trace: launchTrace, configSource: _configSource, ...launchRuntimeFields } = launchPlan;
10702
+ const launchTraceEvidenceAttrs = opts.exposeLaunchTraceEvidence ? {
10703
+ config_source: launchTrace.config_source,
10704
+ ...runtimeConfig.runtime === "builtin" ? { host_user_state: runtimeConfig.hostUserState } : {},
10705
+ ...launchTrace.provider_id ? { provider_id: launchTrace.provider_id } : {},
10706
+ ...launchTrace.model_kind ? { model_kind: launchTrace.model_kind } : {},
10707
+ ...launchTrace.model_id ? { model_id: launchTrace.model_id } : {},
10708
+ ...launchTrace.base_url_present !== void 0 ? { base_url_present: launchTrace.base_url_present } : {},
10709
+ ...launchTrace.base_url_host_class ? { base_url_host_class: launchTrace.base_url_host_class } : {},
10710
+ provider_key_present: launchTrace.provider_key_present,
10711
+ ...launchTrace.provider_key_source ? { provider_key_source: launchTrace.provider_key_source } : {}
10712
+ } : {};
8821
10713
  const requestedModel = launchRuntimeFields.model || "default";
8822
- const traceSpan = ctx.tracer?.startSpan("daemon.pi.session.create", {
10714
+ const traceSpan = ctx.tracer?.startSpan(opts.traceName ?? "daemon.pi.session.create", {
8823
10715
  surface: "daemon",
8824
10716
  kind: "internal",
8825
10717
  attrs: {
@@ -8828,15 +10720,22 @@ async function createPiAgentSessionForContext(ctx, sessionId) {
8828
10720
  runtime: ctx.config.runtime,
8829
10721
  model: ctx.config.model,
8830
10722
  session_id_present: Boolean(sessionId),
8831
- requested_model: requestedModel
10723
+ requested_model: requestedModel,
10724
+ ...launchTraceEvidenceAttrs
8832
10725
  }
8833
10726
  });
10727
+ const logPrefix = opts.logPrefix ?? "pi-driver";
10728
+ const traceEventPrefix = opts.traceEventPrefix ?? "daemon.pi.session";
8834
10729
  try {
8835
10730
  const spawnEnv = await buildPiSpawnEnv(ctx);
8836
- const agentDir = spawnEnv.PI_CODING_AGENT_DIR || getAgentDir();
10731
+ const agentDir = opts.agentDir ?? spawnEnv.PI_CODING_AGENT_DIR ?? getAgentDir();
10732
+ mkdirSync3(agentDir, { recursive: true });
8837
10733
  const authStorage = AuthStorage.create(path12.join(agentDir, "auth.json"));
10734
+ seedBuiltInAuthStorage(authStorage, runtimeConfig);
8838
10735
  const settingsManager = SettingsManager.create(ctx.workingDirectory, agentDir);
8839
- const services = await createAgentSessionServices({
10736
+ const providerEnvScope = opts.isolateHostProviderEnv ? BUILTIN_BLOCKED_HOST_PROVIDER_ENV_KEYS : void 0;
10737
+ const sessionCreateEnvPatch = buildPiSessionCreateEnvPatch(runtimeConfig, launchRuntimeFields.envVars);
10738
+ const services = await withProcessEnvPatch(sessionCreateEnvPatch, () => createAgentSessionServices({
8840
10739
  cwd: ctx.workingDirectory,
8841
10740
  agentDir,
8842
10741
  authStorage,
@@ -8844,23 +10743,27 @@ async function createPiAgentSessionForContext(ctx, sessionId) {
8844
10743
  resourceLoaderOptions: {
8845
10744
  systemPromptOverride: () => ctx.standingPrompt
8846
10745
  }
8847
- });
10746
+ }), { removeFirst: providerEnvScope });
10747
+ configureBuiltInGatewayCustomModel(services.modelRegistry, runtimeConfig);
8848
10748
  applyPiDaemonSettingsOverrides(services.settingsManager);
8849
10749
  logPiServiceDiagnostics("create_session", services);
8850
- addPiServiceTraceEvent(traceSpan, "daemon.pi.session.services_ready", services, {
8851
- agent_dir_source: spawnEnv.PI_CODING_AGENT_DIR ? "spawn_env" : "default"
10750
+ addPiServiceTraceEvent(traceSpan, `${traceEventPrefix}.services_ready`, services, {
10751
+ agent_dir_source: opts.agentDirSource ?? (spawnEnv.PI_CODING_AGENT_DIR ? "spawn_env" : "default"),
10752
+ ...launchTraceEvidenceAttrs
8852
10753
  });
8853
10754
  const model = resolvePiModelFromRegistry(launchRuntimeFields.model, services.modelRegistry);
8854
10755
  const resolvedModel = formatPiModelLogId(model);
8855
- traceSpan?.addEvent("daemon.pi.session.model_resolved", {
10756
+ traceSpan?.addEvent(`${traceEventPrefix}.model_resolved`, {
8856
10757
  available_models_count: services.modelRegistry.getAvailable().length,
8857
10758
  requested_model: requestedModel,
8858
10759
  requested_model_explicit: requestedModel !== "default",
8859
10760
  resolved_model: resolvedModel,
8860
- resolved_model_present: Boolean(model)
10761
+ resolved_model_present: Boolean(model),
10762
+ ...launchTraceEvidenceAttrs
8861
10763
  });
8862
10764
  console.info(
8863
- "[pi-driver] create_session services_ready agentDir=%s available=%d requested=%s resolved=%s",
10765
+ "[%s] create_session services_ready agentDir=%s available=%d requested=%s resolved=%s",
10766
+ logPrefix,
8864
10767
  agentDir,
8865
10768
  services.modelRegistry.getAvailable().length,
8866
10769
  requestedModel,
@@ -8868,13 +10771,15 @@ async function createPiAgentSessionForContext(ctx, sessionId) {
8868
10771
  );
8869
10772
  if (launchRuntimeFields.model && launchRuntimeFields.model !== "default" && !model) {
8870
10773
  console.warn(
8871
- "[pi-driver] create_session missing_model requested=%s available=%d",
10774
+ "[%s] create_session missing_model requested=%s available=%d",
10775
+ logPrefix,
8872
10776
  requestedModel,
8873
10777
  services.modelRegistry.getAvailable().length
8874
10778
  );
8875
- traceSpan?.addEvent("daemon.pi.session.missing_model", {
10779
+ traceSpan?.addEvent(`${traceEventPrefix}.missing_model`, {
8876
10780
  available_models_count: services.modelRegistry.getAvailable().length,
8877
- requested_model: requestedModel
10781
+ requested_model: requestedModel,
10782
+ ...launchTraceEvidenceAttrs
8878
10783
  });
8879
10784
  traceSpan?.end("error", {
8880
10785
  attrs: {
@@ -8882,14 +10787,21 @@ async function createPiAgentSessionForContext(ctx, sessionId) {
8882
10787
  available_models_count: services.modelRegistry.getAvailable().length,
8883
10788
  requested_model: requestedModel,
8884
10789
  resolved_model_present: false,
8885
- ...piServiceDiagnosticTraceAttrs(services)
10790
+ ...piServiceDiagnosticTraceAttrs(services),
10791
+ ...launchTraceEvidenceAttrs
8886
10792
  }
8887
10793
  });
8888
10794
  throw new Error(`Pi model not found: ${launchRuntimeFields.model}`);
8889
10795
  }
8890
10796
  const existingSessionFile = ctx.config.sessionId ? findPiSessionFile(sessionDir, ctx.config.sessionId) : null;
8891
10797
  const sessionManager = existingSessionFile ? SessionManager.open(existingSessionFile, sessionDir, ctx.workingDirectory) : SessionManager.create(ctx.workingDirectory, sessionDir, { id: sessionId });
8892
- const { session } = await createAgentSessionFromServices({
10798
+ const toolSpawnEnv = { ...spawnEnv };
10799
+ if (opts.exposeLaunchEnvToTools === false) {
10800
+ for (const key of Object.keys(launchRuntimeFields.envVars ?? {})) {
10801
+ delete toolSpawnEnv[key];
10802
+ }
10803
+ }
10804
+ const { session } = await withProcessEnvPatch(sessionCreateEnvPatch, () => createAgentSessionFromServices({
8893
10805
  services,
8894
10806
  sessionManager,
8895
10807
  model,
@@ -8900,16 +10812,17 @@ async function createPiAgentSessionForContext(ctx, sessionId) {
8900
10812
  ...spawnContext,
8901
10813
  env: {
8902
10814
  ...spawnContext.env,
8903
- ...spawnEnv
10815
+ ...toolSpawnEnv
8904
10816
  }
8905
10817
  })
8906
10818
  })
8907
10819
  ]
8908
- });
8909
- traceSpan?.addEvent("daemon.pi.session.started", {
10820
+ }), { removeFirst: providerEnvScope });
10821
+ traceSpan?.addEvent(`${traceEventPrefix}.started`, {
8910
10822
  requested_model: requestedModel,
8911
10823
  resolved_model: resolvedModel,
8912
- session_id_present: Boolean(session.sessionId)
10824
+ session_id_present: Boolean(session.sessionId),
10825
+ ...launchTraceEvidenceAttrs
8913
10826
  });
8914
10827
  traceSpan?.end("ok", {
8915
10828
  attrs: {
@@ -8918,11 +10831,13 @@ async function createPiAgentSessionForContext(ctx, sessionId) {
8918
10831
  requested_model: requestedModel,
8919
10832
  resolved_model: resolvedModel,
8920
10833
  resolved_model_present: Boolean(model),
8921
- ...piServiceDiagnosticTraceAttrs(services)
10834
+ ...piServiceDiagnosticTraceAttrs(services),
10835
+ ...launchTraceEvidenceAttrs
8922
10836
  }
8923
10837
  });
8924
10838
  console.info(
8925
- "[pi-driver] create_session started sessionId=%s requested=%s resolved=%s",
10839
+ "[%s] create_session started sessionId=%s requested=%s resolved=%s",
10840
+ logPrefix,
8926
10841
  sessionId,
8927
10842
  requestedModel,
8928
10843
  resolvedModel
@@ -8932,7 +10847,8 @@ async function createPiAgentSessionForContext(ctx, sessionId) {
8932
10847
  traceSpan?.end("error", {
8933
10848
  attrs: {
8934
10849
  outcome: "error",
8935
- error_class: error instanceof Error ? error.name : typeof error
10850
+ error_class: error instanceof Error ? error.name : typeof error,
10851
+ ...launchTraceEvidenceAttrs
8936
10852
  }
8937
10853
  });
8938
10854
  throw error;
@@ -9181,6 +11097,48 @@ var PiDriver = class {
9181
11097
  });
9182
11098
  }
9183
11099
  };
11100
+ var BuiltInDriver = class extends PiDriver {
11101
+ id = "builtin";
11102
+ model = {
11103
+ detectedModelsVerifiedAs: "launchable",
11104
+ toLaunchSpec: (modelId) => ({ params: { model: modelId } })
11105
+ };
11106
+ probe() {
11107
+ return {
11108
+ available: true,
11109
+ version: PI_SDK_VERSION
11110
+ };
11111
+ }
11112
+ async detectModels(_ctx) {
11113
+ return { models: RUNTIME_MODELS.builtin };
11114
+ }
11115
+ createSession(ctx) {
11116
+ this.sessionId = ctx.config.sessionId || null;
11117
+ return new PiSdkRuntimeSession(ctx, (sessionId) => {
11118
+ this.sessionId = sessionId;
11119
+ }, (sessionCtx, sessionId) => createPiAgentSessionForContext(sessionCtx, sessionId, {
11120
+ agentDir: buildBuiltInAgentDir(sessionCtx.workingDirectory),
11121
+ sessionDir: buildBuiltInSessionDir(sessionCtx.workingDirectory),
11122
+ traceName: "daemon.builtin.session.create",
11123
+ traceEventPrefix: "daemon.builtin.session",
11124
+ logPrefix: "builtin-driver",
11125
+ agentDirSource: "managed_builtin",
11126
+ exposeLaunchTraceEvidence: true,
11127
+ exposeLaunchEnvToTools: false,
11128
+ isolateHostProviderEnv: true
11129
+ }));
11130
+ }
11131
+ buildSystemPrompt(config, _agentId) {
11132
+ return buildCliTransportSystemPrompt(config, {
11133
+ extraCriticalRules: [],
11134
+ postStartupNotes: [
11135
+ "**Built-in runtime note:** Slock keeps this runtime in an isolated SDK session. While you are working, Slock may send inbox-count notifications into the current turn; call `raft message check` at natural breakpoints."
11136
+ ],
11137
+ includeStdinNotificationSection: true,
11138
+ messageNotificationStyle: "direct"
11139
+ });
11140
+ }
11141
+ };
9184
11142
  function delay(ms) {
9185
11143
  return new Promise((resolve) => {
9186
11144
  const timer = setTimeout(resolve, ms);
@@ -9332,6 +11290,7 @@ function createChildProcessRuntimeSession(driver, ctx) {
9332
11290
 
9333
11291
  // src/drivers/index.ts
9334
11292
  var driverFactories = {
11293
+ builtin: () => new BuiltInDriver(),
9335
11294
  claude: () => new ClaudeDriver(),
9336
11295
  codex: () => new CodexDriver(),
9337
11296
  antigravity: () => new AntigravityDriver(),
@@ -9396,75 +11355,528 @@ async function summarizeWorkspaceEntry(entryPath, entry) {
9396
11355
  latestMtime: info.mtime
9397
11356
  };
9398
11357
  }
9399
- return emptyWorkspaceDirectorySummary(info.mtime);
9400
- } catch {
9401
- return emptyWorkspaceDirectorySummary();
11358
+ return emptyWorkspaceDirectorySummary(info.mtime);
11359
+ } catch {
11360
+ return emptyWorkspaceDirectorySummary();
11361
+ }
11362
+ }
11363
+ async function summarizeWorkspaceDirectory(dirPath) {
11364
+ let summary = emptyWorkspaceDirectorySummary();
11365
+ try {
11366
+ const rootInfo = await stat(dirPath);
11367
+ summary = emptyWorkspaceDirectorySummary(rootInfo.mtime);
11368
+ } catch {
11369
+ return summary;
11370
+ }
11371
+ let entries;
11372
+ try {
11373
+ entries = await readdir(dirPath, { withFileTypes: true });
11374
+ } catch {
11375
+ return summary;
11376
+ }
11377
+ const childSummaries = await Promise.all(
11378
+ entries.map((entry) => summarizeWorkspaceEntry(path13.join(dirPath, entry.name), entry))
11379
+ );
11380
+ for (const childSummary of childSummaries) {
11381
+ summary = mergeWorkspaceDirectorySummaries(summary, childSummary);
11382
+ }
11383
+ return summary;
11384
+ }
11385
+ async function scanWorkspaceDirectories(dataDir) {
11386
+ let entries;
11387
+ try {
11388
+ entries = await readdir(dataDir, { withFileTypes: true });
11389
+ } catch {
11390
+ return [];
11391
+ }
11392
+ const results = await Promise.all(
11393
+ entries.map(async (entry) => {
11394
+ if (!entry.isDirectory()) {
11395
+ return null;
11396
+ }
11397
+ const dirPath = path13.join(dataDir, entry.name);
11398
+ try {
11399
+ const summary = await summarizeWorkspaceDirectory(dirPath);
11400
+ return {
11401
+ directoryName: entry.name,
11402
+ totalSizeBytes: summary.totalSizeBytes,
11403
+ lastModified: summary.latestMtime.toISOString(),
11404
+ fileCount: summary.fileCount
11405
+ };
11406
+ } catch {
11407
+ return null;
11408
+ }
11409
+ })
11410
+ );
11411
+ return results.filter((entry) => entry !== null);
11412
+ }
11413
+ async function deleteWorkspaceDirectory(dataDir, directoryName) {
11414
+ const targetDir = resolveWorkspaceDirectoryPath(dataDir, directoryName);
11415
+ if (!targetDir) {
11416
+ return false;
11417
+ }
11418
+ try {
11419
+ await rm(targetDir, { recursive: true, force: true });
11420
+ logger.info(`[Workspace] Deleted directory: ${targetDir}`);
11421
+ return true;
11422
+ } catch (err) {
11423
+ logger.error(`[Workspace] Failed to delete directory ${targetDir}`, err);
11424
+ return false;
11425
+ }
11426
+ }
11427
+
11428
+ // src/agentStartCoordinator.ts
11429
+ var AgentStartCoordinator = class {
11430
+ starting = /* @__PURE__ */ new Set();
11431
+ queuedByAgent = /* @__PURE__ */ new Map();
11432
+ queue = [];
11433
+ activeStarts = 0;
11434
+ pumpTimer = null;
11435
+ lastStartAt = 0;
11436
+ lastStartAgentId = null;
11437
+ maxConcurrentStarts;
11438
+ minStartIntervalMs;
11439
+ constructor(opts) {
11440
+ this.maxConcurrentStarts = Math.max(1, Math.floor(opts.maxConcurrentStarts));
11441
+ this.minStartIntervalMs = Math.max(0, Math.floor(opts.minStartIntervalMs));
11442
+ this.assertInvariants("constructor");
11443
+ }
11444
+ snapshot() {
11445
+ return {
11446
+ activeStarts: this.activeStarts,
11447
+ queueDepth: this.queue.length,
11448
+ maxConcurrentStarts: this.maxConcurrentStarts,
11449
+ minStartIntervalMs: this.minStartIntervalMs,
11450
+ startingAgentIds: [...this.starting],
11451
+ queuedAgentIds: [...this.queuedByAgent.keys()],
11452
+ pumpTimerActive: this.pumpTimer !== null
11453
+ };
11454
+ }
11455
+ hasStarting(agentId) {
11456
+ return this.starting.has(agentId);
11457
+ }
11458
+ hasQueued(agentId) {
11459
+ return this.queuedByAgent.has(agentId);
11460
+ }
11461
+ getQueued(agentId) {
11462
+ return this.queuedByAgent.get(agentId);
11463
+ }
11464
+ enqueue(item) {
11465
+ if (this.starting.has(item.agentId)) {
11466
+ throw new Error(`Agent start invariant violation after enqueue: ${item.agentId} is already starting`);
11467
+ }
11468
+ if (this.queuedByAgent.has(item.agentId)) {
11469
+ throw new Error(`Agent start invariant violation after enqueue: ${item.agentId} is already queued`);
11470
+ }
11471
+ this.queue.push(item);
11472
+ this.queuedByAgent.set(item.agentId, item);
11473
+ this.assertInvariants("enqueue");
11474
+ }
11475
+ markStarting(agentId) {
11476
+ if (this.queuedByAgent.has(agentId)) {
11477
+ throw new Error(`Agent start invariant violation after markStarting: ${agentId} is still queued`);
11478
+ }
11479
+ this.starting.add(agentId);
11480
+ this.assertInvariants("markStarting");
11481
+ }
11482
+ clearStarting(agentId) {
11483
+ this.starting.delete(agentId);
11484
+ this.assertInvariants("clearStarting");
11485
+ }
11486
+ getPumpState(now = Date.now()) {
11487
+ if (this.pumpTimer) return { kind: "blocked", reason: "timer_active" };
11488
+ if (this.queue.length === 0) return { kind: "blocked", reason: "queue_empty" };
11489
+ if (this.activeStarts >= this.maxConcurrentStarts) return { kind: "blocked", reason: "capacity_full" };
11490
+ const item = this.queue[0];
11491
+ if (!item) return { kind: "blocked", reason: "queue_empty" };
11492
+ const shouldRateLimit = item.agentId !== this.lastStartAgentId;
11493
+ const elapsed = now - this.lastStartAt;
11494
+ const waitMs = shouldRateLimit ? Math.max(0, this.minStartIntervalMs - elapsed) : 0;
11495
+ if (waitMs > 0) return { kind: "rate_limited", item, waitMs };
11496
+ return { kind: "ready", item };
11497
+ }
11498
+ schedulePump(waitMs, callback) {
11499
+ if (this.pumpTimer) return;
11500
+ this.pumpTimer = setTimeout(() => {
11501
+ this.pumpTimer = null;
11502
+ callback();
11503
+ }, waitMs);
11504
+ this.assertInvariants("schedulePump");
11505
+ }
11506
+ dequeue() {
11507
+ const item = this.queue.shift();
11508
+ if (!item) {
11509
+ this.assertInvariants("dequeue empty");
11510
+ return { kind: "empty" };
11511
+ }
11512
+ if (this.queuedByAgent.get(item.agentId) !== item) {
11513
+ this.assertInvariants("dequeue stale");
11514
+ return { kind: "stale", item };
11515
+ }
11516
+ this.queuedByAgent.delete(item.agentId);
11517
+ this.assertInvariants("dequeue");
11518
+ return { kind: "item", item };
11519
+ }
11520
+ claimStartSlot(agentId, now = Date.now()) {
11521
+ this.activeStarts++;
11522
+ this.lastStartAt = now;
11523
+ this.lastStartAgentId = agentId;
11524
+ this.assertInvariants("claimStartSlot");
11525
+ }
11526
+ releaseStartSlot() {
11527
+ if (this.activeStarts <= 0) return false;
11528
+ this.activeStarts = Math.max(0, this.activeStarts - 1);
11529
+ this.assertInvariants("releaseStartSlot");
11530
+ return true;
11531
+ }
11532
+ cancelQueued(agentId) {
11533
+ const item = this.queuedByAgent.get(agentId);
11534
+ if (!item) return void 0;
11535
+ this.queuedByAgent.delete(agentId);
11536
+ this.queue = this.queue.filter((candidate) => candidate !== item);
11537
+ this.clearPumpTimerIfIdle();
11538
+ this.assertInvariants("cancelQueued");
11539
+ return item;
11540
+ }
11541
+ cancelAllQueued(onCancel) {
11542
+ const items = [];
11543
+ for (const item of this.queue) {
11544
+ if (this.queuedByAgent.get(item.agentId) === item) {
11545
+ items.push(item);
11546
+ onCancel?.(item);
11547
+ }
11548
+ }
11549
+ this.queue = [];
11550
+ this.queuedByAgent.clear();
11551
+ this.clearPumpTimer();
11552
+ this.assertInvariants("cancelAllQueued");
11553
+ return items;
11554
+ }
11555
+ assertInvariants(context) {
11556
+ if (this.activeStarts < 0) {
11557
+ throw new Error(`Agent start invariant violation after ${context}: activeStarts is negative`);
11558
+ }
11559
+ if (this.activeStarts > this.maxConcurrentStarts) {
11560
+ throw new Error(`Agent start invariant violation after ${context}: activeStarts exceeds maxConcurrentStarts`);
11561
+ }
11562
+ const queuedIds = /* @__PURE__ */ new Set();
11563
+ for (const item of this.queue) {
11564
+ if (queuedIds.has(item.agentId)) {
11565
+ throw new Error(`Agent start invariant violation after ${context}: duplicate queued agent ${item.agentId}`);
11566
+ }
11567
+ queuedIds.add(item.agentId);
11568
+ if (this.queuedByAgent.get(item.agentId) !== item) {
11569
+ throw new Error(`Agent start invariant violation after ${context}: queue/map mismatch for ${item.agentId}`);
11570
+ }
11571
+ if (this.starting.has(item.agentId)) {
11572
+ throw new Error(`Agent start invariant violation after ${context}: ${item.agentId} is queued and starting`);
11573
+ }
11574
+ }
11575
+ if (queuedIds.size !== this.queuedByAgent.size) {
11576
+ throw new Error(`Agent start invariant violation after ${context}: queue/map size mismatch`);
11577
+ }
11578
+ for (const [agentId, item] of this.queuedByAgent) {
11579
+ if (!queuedIds.has(agentId)) {
11580
+ throw new Error(`Agent start invariant violation after ${context}: map-only queued agent ${agentId}`);
11581
+ }
11582
+ if (item.agentId !== agentId) {
11583
+ throw new Error(`Agent start invariant violation after ${context}: map key/item agent mismatch for ${agentId}`);
11584
+ }
11585
+ }
11586
+ }
11587
+ setMaxConcurrentStartsForTesting(value) {
11588
+ this.maxConcurrentStarts = Math.max(1, Math.floor(value));
11589
+ if (this.activeStarts > this.maxConcurrentStarts) {
11590
+ this.activeStarts = this.maxConcurrentStarts;
11591
+ }
11592
+ this.assertInvariants("setMaxConcurrentStartsForTesting");
11593
+ }
11594
+ setActiveStartsForTesting(value) {
11595
+ this.activeStarts = Math.max(0, Math.floor(value));
11596
+ this.assertInvariants("setActiveStartsForTesting");
11597
+ }
11598
+ clearPumpTimerIfIdle() {
11599
+ if (this.queue.length === 0) {
11600
+ this.clearPumpTimer();
11601
+ }
11602
+ }
11603
+ clearPumpTimer() {
11604
+ if (this.pumpTimer) {
11605
+ clearTimeout(this.pumpTimer);
11606
+ this.pumpTimer = null;
11607
+ }
11608
+ }
11609
+ };
11610
+
11611
+ // src/agentStartPendingDeliveryBuffer.ts
11612
+ var AgentStartPendingDeliveryBuffer = class {
11613
+ pending = /* @__PURE__ */ new Map();
11614
+ count(agentId) {
11615
+ return this.pending.get(agentId)?.length ?? 0;
11616
+ }
11617
+ has(agentId) {
11618
+ return this.pending.has(agentId);
11619
+ }
11620
+ get size() {
11621
+ return this.pending.size;
11622
+ }
11623
+ values(agentId) {
11624
+ return [...this.pending.get(agentId) ?? []];
11625
+ }
11626
+ bufferDuringStart(agentId, message) {
11627
+ return this.append(agentId, [message], "bufferDuringStart");
11628
+ }
11629
+ bufferMessagesDuringStart(agentId, messages) {
11630
+ return this.append(agentId, messages, "bufferMessagesDuringStart");
11631
+ }
11632
+ rebindWake(agentId, previousWakeMessage, nextWakeMessage, sameWakeMessage) {
11633
+ if (!previousWakeMessage || !nextWakeMessage || sameWakeMessage(previousWakeMessage, nextWakeMessage)) {
11634
+ return this.count(agentId);
11635
+ }
11636
+ return this.append(agentId, [previousWakeMessage], "rebindWake");
11637
+ }
11638
+ drainOnSpawn(agentId) {
11639
+ const messages = this.pending.get(agentId) ?? [];
11640
+ this.pending.delete(agentId);
11641
+ this.assertInternalInvariants("drainOnSpawn");
11642
+ return messages;
11643
+ }
11644
+ cancelStart(agentId) {
11645
+ this.pending.delete(agentId);
11646
+ this.assertInternalInvariants("cancelStart");
11647
+ }
11648
+ cancelAllStarts() {
11649
+ this.pending.clear();
11650
+ this.assertInternalInvariants("cancelAllStarts");
11651
+ }
11652
+ suppressConsumed(agentId, predicate) {
11653
+ const messages = this.pending.get(agentId);
11654
+ if (!messages || messages.length === 0) return 0;
11655
+ let removed = 0;
11656
+ const retained = messages.filter((message) => {
11657
+ const matched = predicate(message);
11658
+ if (matched) removed += 1;
11659
+ return !matched;
11660
+ });
11661
+ if (retained.length === 0) {
11662
+ this.pending.delete(agentId);
11663
+ } else {
11664
+ this.pending.set(agentId, retained);
11665
+ }
11666
+ this.assertInternalInvariants("suppressConsumed");
11667
+ return removed;
11668
+ }
11669
+ purge(agentId, predicate) {
11670
+ return this.suppressConsumed(agentId, predicate);
11671
+ }
11672
+ assertInvariants(context, snapshot) {
11673
+ this.assertInternalInvariants(context);
11674
+ const allowed = /* @__PURE__ */ new Set([
11675
+ ...snapshot.queuedAgentIds,
11676
+ ...snapshot.startingAgentIds,
11677
+ ...snapshot.terminalRecoveryAgentIds ?? [],
11678
+ ...snapshot.cooldownAgentIds ?? []
11679
+ ]);
11680
+ for (const agentId of this.pending.keys()) {
11681
+ if (!allowed.has(agentId)) {
11682
+ throw new Error(`Agent start pending delivery invariant violation after ${context}: pending messages for non-starting agent ${agentId}`);
11683
+ }
11684
+ }
11685
+ }
11686
+ append(agentId, messages, context) {
11687
+ if (messages.length === 0) return this.count(agentId);
11688
+ const existing = this.pending.get(agentId);
11689
+ if (existing) {
11690
+ existing.push(...messages);
11691
+ } else {
11692
+ this.pending.set(agentId, [...messages]);
11693
+ }
11694
+ this.assertInternalInvariants(context);
11695
+ return this.count(agentId);
11696
+ }
11697
+ assertInternalInvariants(context) {
11698
+ for (const [agentId, messages] of this.pending) {
11699
+ if (!agentId) {
11700
+ throw new Error(`Agent start pending delivery invariant violation after ${context}: empty agent id`);
11701
+ }
11702
+ if (messages.length === 0) {
11703
+ throw new Error(`Agent start pending delivery invariant violation after ${context}: empty pending buffer for ${agentId}`);
11704
+ }
11705
+ }
11706
+ }
11707
+ };
11708
+
11709
+ // src/agentVisibleDeliveryLedger.ts
11710
+ function getMessageShortId(messageId2) {
11711
+ return messageId2.startsWith("thread-") ? messageId2.slice(7) : messageId2.slice(0, 8);
11712
+ }
11713
+ function computeTarget(channelType, channelName, parentChannelName, parentChannelType) {
11714
+ if (channelType === "thread" && parentChannelName) {
11715
+ const shortId = getMessageShortId(String(channelName ?? ""));
11716
+ if (parentChannelType === "dm") {
11717
+ return `dm:@${parentChannelName}:${shortId}`;
11718
+ }
11719
+ return `#${parentChannelName}:${shortId}`;
9402
11720
  }
11721
+ if (channelType === "dm") {
11722
+ return `dm:@${channelName}`;
11723
+ }
11724
+ return `#${channelName}`;
9403
11725
  }
9404
- async function summarizeWorkspaceDirectory(dirPath) {
9405
- let summary = emptyWorkspaceDirectorySummary();
9406
- try {
9407
- const rootInfo = await stat(dirPath);
9408
- summary = emptyWorkspaceDirectorySummary(rootInfo.mtime);
9409
- } catch {
9410
- return summary;
11726
+ function formatAgentMessageVisibleTarget(message) {
11727
+ return computeTarget(message.channel_type, message.channel_name, message.parent_channel_name, message.parent_channel_type);
11728
+ }
11729
+ function formatProxyVisibleMessageTarget(message) {
11730
+ return computeTarget(message.channel_type, message.channel_name, message.parent_channel_name, message.parent_channel_type);
11731
+ }
11732
+ function hasTargetMetadata(message) {
11733
+ if (message.channel_type === "thread") return Boolean(message.parent_channel_name && message.channel_name);
11734
+ return Boolean(message.channel_type && message.channel_name);
11735
+ }
11736
+ function visibleMessageId(message) {
11737
+ if (typeof message.message_id === "string") return String(message.message_id);
11738
+ if (typeof message.id === "string") return String(message.id);
11739
+ return "";
11740
+ }
11741
+ function isTrueDeliveryConsumeSource(source) {
11742
+ return source === "spawn_wake_message" || source === "agent_api_events_local" || source.startsWith("stdin_");
11743
+ }
11744
+ var AgentVisibleDeliveryLedger = class {
11745
+ boundaryByAgent = /* @__PURE__ */ new Map();
11746
+ messageIdsByAgent = /* @__PURE__ */ new Map();
11747
+ clearAgent(agentId) {
11748
+ this.boundaryByAgent.delete(agentId);
11749
+ this.messageIdsByAgent.delete(agentId);
9411
11750
  }
9412
- let entries;
9413
- try {
9414
- entries = await readdir(dirPath, { withFileTypes: true });
9415
- } catch {
9416
- return summary;
11751
+ hasAgentState(agentId) {
11752
+ return this.boundaryByAgent.has(agentId) || this.messageIdsByAgent.has(agentId);
9417
11753
  }
9418
- const childSummaries = await Promise.all(
9419
- entries.map((entry) => summarizeWorkspaceEntry(path13.join(dirPath, entry.name), entry))
9420
- );
9421
- for (const childSummary of childSummaries) {
9422
- summary = mergeWorkspaceDirectorySummaries(summary, childSummary);
11754
+ getBoundary(agentId, target) {
11755
+ return this.boundaryByAgent.get(agentId)?.get(target);
9423
11756
  }
9424
- return summary;
9425
- }
9426
- async function scanWorkspaceDirectories(dataDir) {
9427
- let entries;
9428
- try {
9429
- entries = await readdir(dataDir, { withFileTypes: true });
9430
- } catch {
9431
- return [];
11757
+ getMessageIdSet(agentId, target) {
11758
+ return this.messageIdsByAgent.get(agentId)?.get(target);
9432
11759
  }
9433
- const results = await Promise.all(
9434
- entries.map(async (entry) => {
9435
- if (!entry.isDirectory()) {
9436
- return null;
11760
+ isModelSeen(agentId, target, message) {
11761
+ const seq = Number(message.seq ?? 0);
11762
+ const boundary = this.getBoundary(agentId, target);
11763
+ if (Number.isFinite(seq) && seq > 0 && typeof boundary === "number" && boundary >= Math.floor(seq)) return true;
11764
+ const id = visibleMessageId(message);
11765
+ return id.length > 0 && this.getMessageIdSet(agentId, target)?.has(id) === true;
11766
+ }
11767
+ recordConsumed(agentId, input) {
11768
+ if (input.messages.length === 0 && (!input.target || typeof input.boundarySeq !== "number")) return null;
11769
+ const byTarget = /* @__PURE__ */ new Map();
11770
+ const ensureBucket = (target) => {
11771
+ let bucket = byTarget.get(target);
11772
+ if (!bucket) {
11773
+ bucket = { maxSeq: 0, boundarySeq: 0, seqs: /* @__PURE__ */ new Set(), ids: /* @__PURE__ */ new Set() };
11774
+ byTarget.set(target, bucket);
9437
11775
  }
9438
- const dirPath = path13.join(dataDir, entry.name);
9439
- try {
9440
- const summary = await summarizeWorkspaceDirectory(dirPath);
9441
- return {
9442
- directoryName: entry.name,
9443
- totalSizeBytes: summary.totalSizeBytes,
9444
- lastModified: summary.latestMtime.toISOString(),
9445
- fileCount: summary.fileCount
9446
- };
9447
- } catch {
9448
- return null;
11776
+ return bucket;
11777
+ };
11778
+ for (const message of input.messages) {
11779
+ const messageTarget = formatProxyVisibleMessageTarget(message);
11780
+ if (input.target && hasTargetMetadata(message) && messageTarget !== input.target) {
11781
+ throw new Error(`AgentVisibleDeliveryLedger target mismatch: explicit target ${input.target} does not match visible message target ${messageTarget}`);
9449
11782
  }
9450
- })
9451
- );
9452
- return results.filter((entry) => entry !== null);
9453
- }
9454
- async function deleteWorkspaceDirectory(dataDir, directoryName) {
9455
- const targetDir = resolveWorkspaceDirectoryPath(dataDir, directoryName);
9456
- if (!targetDir) {
9457
- return false;
11783
+ const target = input.target ?? messageTarget;
11784
+ if (!target) continue;
11785
+ const bucket = ensureBucket(target);
11786
+ const seq = Number(message.seq ?? 0);
11787
+ if (Number.isFinite(seq) && seq > 0) {
11788
+ const normalizedSeq = Math.floor(seq);
11789
+ bucket.maxSeq = Math.max(bucket.maxSeq, normalizedSeq);
11790
+ bucket.seqs.add(normalizedSeq);
11791
+ }
11792
+ const id = visibleMessageId(message);
11793
+ if (id.length > 0) bucket.ids.add(id);
11794
+ }
11795
+ if (input.target && typeof input.boundarySeq === "number" && Number.isFinite(input.boundarySeq) && input.boundarySeq > 0) {
11796
+ const bucket = ensureBucket(input.target);
11797
+ bucket.boundarySeq = Math.max(bucket.boundarySeq, Math.floor(input.boundarySeq));
11798
+ }
11799
+ if (byTarget.size === 0) return null;
11800
+ const advancesBoundary = isTrueDeliveryConsumeSource(input.source);
11801
+ for (const [target, bucket] of byTarget) {
11802
+ const previousBoundary = this.getBoundary(agentId, target);
11803
+ if (advancesBoundary) {
11804
+ const highWaterSeq = Math.max(bucket.maxSeq, bucket.boundarySeq);
11805
+ const boundaryMap = this.boundaryMap(agentId);
11806
+ boundaryMap.set(target, Math.max(previousBoundary ?? 0, highWaterSeq));
11807
+ }
11808
+ if (bucket.ids.size > 0) {
11809
+ const targetIds = this.messageIdSet(agentId, target);
11810
+ for (const id of bucket.ids) targetIds.add(id);
11811
+ }
11812
+ this.assertConsumedInvariants("recordConsumed", agentId, target, bucket, {
11813
+ advancesBoundary,
11814
+ previousBoundary
11815
+ });
11816
+ }
11817
+ return {
11818
+ targets: [...byTarget.keys()],
11819
+ messagesCount: input.messages.length,
11820
+ shouldSuppress(message) {
11821
+ const target = formatAgentMessageVisibleTarget(message);
11822
+ const bucket = byTarget.get(target);
11823
+ if (!bucket) return false;
11824
+ const seq = typeof message.seq === "number" ? Math.floor(message.seq) : 0;
11825
+ const id = visibleMessageId(message);
11826
+ return seq > 0 && bucket.boundarySeq > 0 && seq <= bucket.boundarySeq || seq > 0 && bucket.seqs.has(seq) || id.length > 0 && bucket.ids.has(id);
11827
+ }
11828
+ };
9458
11829
  }
9459
- try {
9460
- await rm(targetDir, { recursive: true, force: true });
9461
- logger.info(`[Workspace] Deleted directory: ${targetDir}`);
9462
- return true;
9463
- } catch (err) {
9464
- logger.error(`[Workspace] Failed to delete directory ${targetDir}`, err);
9465
- return false;
11830
+ boundaryMap(agentId) {
11831
+ let map = this.boundaryByAgent.get(agentId);
11832
+ if (!map) {
11833
+ map = /* @__PURE__ */ new Map();
11834
+ this.boundaryByAgent.set(agentId, map);
11835
+ }
11836
+ return map;
9466
11837
  }
9467
- }
11838
+ messageIdMap(agentId) {
11839
+ let map = this.messageIdsByAgent.get(agentId);
11840
+ if (!map) {
11841
+ map = /* @__PURE__ */ new Map();
11842
+ this.messageIdsByAgent.set(agentId, map);
11843
+ }
11844
+ return map;
11845
+ }
11846
+ messageIdSet(agentId, target) {
11847
+ const map = this.messageIdMap(agentId);
11848
+ let ids = map.get(target);
11849
+ if (!ids) {
11850
+ ids = /* @__PURE__ */ new Set();
11851
+ map.set(target, ids);
11852
+ }
11853
+ return ids;
11854
+ }
11855
+ assertConsumedInvariants(context, agentId, target, bucket, options) {
11856
+ const boundary = this.getBoundary(agentId, target);
11857
+ if (!options.advancesBoundary && boundary !== options.previousBoundary) {
11858
+ throw new Error(`Agent visible delivery ledger invariant violation after ${context}: set-only source advanced boundary for ${agentId} ${target}`);
11859
+ }
11860
+ if (options.advancesBoundary) {
11861
+ const highWaterSeq = Math.max(bucket.maxSeq, bucket.boundarySeq);
11862
+ const normalizedBoundary = boundary ?? 0;
11863
+ if (normalizedBoundary < (options.previousBoundary ?? 0)) {
11864
+ throw new Error(`Agent visible delivery ledger invariant violation after ${context}: boundary regressed for ${agentId} ${target}`);
11865
+ }
11866
+ if (highWaterSeq > 0 && normalizedBoundary < highWaterSeq) {
11867
+ throw new Error(`Agent visible delivery ledger invariant violation after ${context}: boundary below consumed high-water for ${agentId} ${target}`);
11868
+ }
11869
+ }
11870
+ if (bucket.ids.size > 0) {
11871
+ const targetIds = this.getMessageIdSet(agentId, target);
11872
+ for (const id of bucket.ids) {
11873
+ if (targetIds?.has(id) !== true) {
11874
+ throw new Error(`Agent visible delivery ledger invariant violation after ${context}: missing consumed message id for ${agentId} ${target}`);
11875
+ }
11876
+ }
11877
+ }
11878
+ }
11879
+ };
9468
11880
 
9469
11881
  // src/runtimeErrorDiagnostics.ts
9470
11882
  import { createHash as createHash2 } from "crypto";
@@ -9975,26 +12387,10 @@ function toLocalTime(iso) {
9975
12387
  function formatChannelLabel(message) {
9976
12388
  return message.channel_type === "dm" ? `DM:@${message.channel_name}` : `#${message.channel_name}`;
9977
12389
  }
9978
- function computeTarget(channelType, channelName, parentChannelName, parentChannelType) {
9979
- if (channelType === "thread" && parentChannelName) {
9980
- const shortId = getMessageShortId(String(channelName ?? ""));
9981
- if (parentChannelType === "dm") {
9982
- return `dm:@${parentChannelName}:${shortId}`;
9983
- }
9984
- return `#${parentChannelName}:${shortId}`;
9985
- }
9986
- if (channelType === "dm") {
9987
- return `dm:@${channelName}`;
9988
- }
9989
- return `#${channelName}`;
9990
- }
9991
12390
  function formatMessageTarget(message) {
9992
- return computeTarget(message.channel_type, message.channel_name, message.parent_channel_name, message.parent_channel_type);
12391
+ return formatAgentMessageVisibleTarget(message);
9993
12392
  }
9994
- function formatVisibleMessageTarget(message) {
9995
- return computeTarget(message.channel_type, message.channel_name, message.parent_channel_name, message.parent_channel_type);
9996
- }
9997
- function getMessageShortId(messageId2) {
12393
+ function getMessageShortId2(messageId2) {
9998
12394
  return messageId2.startsWith("thread-") ? messageId2.slice(7) : messageId2.slice(0, 8);
9999
12395
  }
10000
12396
  var RESPONSE_TARGET_HINT = "Reply in the channel or create/reply in a thread as appropriate; use each message's `target` and `msg` fields to choose the exact target.";
@@ -10261,31 +12657,11 @@ function formatTaskAssigneeType(type) {
10261
12657
  return type ?? null;
10262
12658
  }
10263
12659
  function formatThreadContextMessage(message) {
10264
- const msgId = message.message_id ? getMessageShortId(message.message_id) : "-";
12660
+ const msgId = message.message_id ? getMessageShortId2(message.message_id) : "-";
10265
12661
  const time = message.timestamp ? toLocalTime(message.timestamp) : "-";
10266
12662
  const senderType = formatVisibleActorType(message.sender_type);
10267
12663
  return `- [msg=${msgId} time=${time}${senderType}] ${formatSenderHandle(message)}: ${message.content}`;
10268
12664
  }
10269
- function communicationCommand(name) {
10270
- switch (name) {
10271
- case "send_message":
10272
- return "raft message send";
10273
- case "read_history":
10274
- return "raft message read";
10275
- case "check_messages":
10276
- return "raft message check";
10277
- case "claim_tasks":
10278
- return "raft task claim";
10279
- default:
10280
- return `raft ${name.replace(/_/g, " ")}`;
10281
- }
10282
- }
10283
- function dynamicReplyInstruction() {
10284
- return "reply using `raft message send --target <exact target>`";
10285
- }
10286
- function dynamicClaimInstruction() {
10287
- return "claim the relevant task with `raft task claim`";
10288
- }
10289
12665
  function formatIncomingMessage(message, options = {}) {
10290
12666
  const threadJoinPrefix = message.thread_join_context ? [
10291
12667
  `[Slock thread context: you were added to a new thread via @mention.]`,
@@ -10301,7 +12677,7 @@ function formatIncomingMessage(message, options = {}) {
10301
12677
  ""
10302
12678
  ].join("\n") : "";
10303
12679
  const target = formatMessageTarget(message);
10304
- const msgId = message.message_id ? getMessageShortId(message.message_id) : "-";
12680
+ const msgId = message.message_id ? getMessageShortId2(message.message_id) : "-";
10305
12681
  const time = message.timestamp ? toLocalTime(message.timestamp) : "-";
10306
12682
  const senderType = formatVisibleActorType(message.sender_type);
10307
12683
  const attachSuffix = formatAttachmentSuffix(message.attachments, options.attachmentHint);
@@ -11260,17 +13636,8 @@ var AgentProcessManager = class _AgentProcessManager {
11260
13636
  this.activityClientSeqByAgent.set(agentId, next);
11261
13637
  return next;
11262
13638
  }
11263
- agentsStarting = /* @__PURE__ */ new Set();
11264
- // Prevent concurrent starts of same agent
11265
- queuedAgentStarts = /* @__PURE__ */ new Map();
11266
- agentStartQueue = [];
11267
- activeAgentStartCount = 0;
11268
- agentStartPumpTimer = null;
11269
- lastAgentStartAt = 0;
11270
- lastAgentStartAgentId = null;
11271
- maxConcurrentAgentStarts;
11272
- agentStartIntervalMs;
11273
- startingInboxes = /* @__PURE__ */ new Map();
13639
+ agentStarts;
13640
+ startingInboxes = new AgentStartPendingDeliveryBuffer();
11274
13641
  terminalRuntimeFailures = /* @__PURE__ */ new Map();
11275
13642
  runtimeErrorFingerprintFences = /* @__PURE__ */ new Map();
11276
13643
  pendingStartRebinds = /* @__PURE__ */ new Map();
@@ -11294,8 +13661,7 @@ var AgentProcessManager = class _AgentProcessManager {
11294
13661
  cliTransportTraceDir = null;
11295
13662
  deliveryTraceContexts = /* @__PURE__ */ new WeakMap();
11296
13663
  runtimeExitTraceAttrs = /* @__PURE__ */ new WeakMap();
11297
- agentVisibleBoundaries = /* @__PURE__ */ new Map();
11298
- agentVisibleMessageIds = /* @__PURE__ */ new Map();
13664
+ agentVisibleDelivery = new AgentVisibleDeliveryLedger();
11299
13665
  // Spawn-fail backoff state per-agent (lifted outside AgentProcess because spawn fails
11300
13666
  // BEFORE ap exists; rate-state must persist across stop/respawn so churn can't bypass).
11301
13667
  // Explicit stop clears (fresh launch resets dedup clock — CC1 lifecycle pattern); silent
@@ -11340,18 +13706,10 @@ var AgentProcessManager = class _AgentProcessManager {
11340
13706
  Math.min(1, opts.runtimeErrorDeliveryBackoff?.jitterRatio ?? 0.1)
11341
13707
  );
11342
13708
  this.runtimeErrorDeliveryBackoffFailPointForTesting = opts.runtimeErrorDeliveryBackoff?.failPointForTesting ?? null;
11343
- this.maxConcurrentAgentStarts = Math.max(
11344
- 1,
11345
- Math.floor(
11346
- opts.runtimeStartScheduler?.maxConcurrentStarts ?? readPositiveIntegerEnv("SLOCK_DAEMON_MAX_CONCURRENT_AGENT_STARTS", DEFAULT_MAX_CONCURRENT_AGENT_STARTS)
11347
- )
11348
- );
11349
- this.agentStartIntervalMs = Math.max(
11350
- 0,
11351
- Math.floor(
11352
- opts.runtimeStartScheduler?.minStartIntervalMs ?? readNonNegativeIntegerEnv("SLOCK_DAEMON_AGENT_START_INTERVAL_MS", DEFAULT_AGENT_START_INTERVAL_MS)
11353
- )
11354
- );
13709
+ this.agentStarts = new AgentStartCoordinator({
13710
+ maxConcurrentStarts: opts.runtimeStartScheduler?.maxConcurrentStarts ?? readPositiveIntegerEnv("SLOCK_DAEMON_MAX_CONCURRENT_AGENT_STARTS", DEFAULT_MAX_CONCURRENT_AGENT_STARTS),
13711
+ minStartIntervalMs: opts.runtimeStartScheduler?.minStartIntervalMs ?? readNonNegativeIntegerEnv("SLOCK_DAEMON_AGENT_START_INTERVAL_MS", DEFAULT_AGENT_START_INTERVAL_MS)
13712
+ });
11355
13713
  }
11356
13714
  setTracer(tracer) {
11357
13715
  this.tracer = tracer;
@@ -11359,34 +13717,23 @@ var AgentProcessManager = class _AgentProcessManager {
11359
13717
  setCliTransportTraceDir(traceDir) {
11360
13718
  this.cliTransportTraceDir = traceDir;
11361
13719
  }
11362
- visibleBoundaryMap(agentId) {
11363
- let map = this.agentVisibleBoundaries.get(agentId);
11364
- if (!map) {
11365
- map = /* @__PURE__ */ new Map();
11366
- this.agentVisibleBoundaries.set(agentId, map);
11367
- }
11368
- return map;
13720
+ assertStartPendingDeliveryInvariants(context) {
13721
+ const startSnapshot = this.agentStarts.snapshot();
13722
+ this.startingInboxes.assertInvariants(context, {
13723
+ queuedAgentIds: startSnapshot.queuedAgentIds,
13724
+ startingAgentIds: startSnapshot.startingAgentIds,
13725
+ terminalRecoveryAgentIds: [...this.terminalRuntimeFailures.keys()],
13726
+ cooldownAgentIds: [...this.agentSpawnFailBackoff.keys()]
13727
+ });
11369
13728
  }
11370
13729
  getVisibleBoundary(agentId, target) {
11371
- return this.agentVisibleBoundaries.get(agentId)?.get(target);
11372
- }
11373
- visibleMessageIdMap(agentId) {
11374
- let map = this.agentVisibleMessageIds.get(agentId);
11375
- if (!map) {
11376
- map = /* @__PURE__ */ new Map();
11377
- this.agentVisibleMessageIds.set(agentId, map);
11378
- }
11379
- return map;
13730
+ return this.agentVisibleDelivery.getBoundary(agentId, target);
11380
13731
  }
11381
13732
  getVisibleMessageIdSet(agentId, target) {
11382
- return this.agentVisibleMessageIds.get(agentId)?.get(target);
13733
+ return this.agentVisibleDelivery.getMessageIdSet(agentId, target);
11383
13734
  }
11384
13735
  isVisibleMessageModelSeen(agentId, target, message) {
11385
- const seq = Number(message.seq ?? 0);
11386
- const boundary = this.getVisibleBoundary(agentId, target);
11387
- if (Number.isFinite(seq) && seq > 0 && typeof boundary === "number" && boundary >= Math.floor(seq)) return true;
11388
- const id = typeof message.message_id === "string" ? message.message_id : typeof message.id === "string" ? message.id : "";
11389
- return id.length > 0 && this.getVisibleMessageIdSet(agentId, target)?.has(id) === true;
13736
+ return this.agentVisibleDelivery.isModelSeen(agentId, target, message);
11390
13737
  }
11391
13738
  // ----- SPAWN-FAIL BACKOFF (per-agent) ----------------------------------
11392
13739
  // Anchored at auto_restart_from_idle (apm:3596) + runtime_profile_auto_restart (apm:4137).
@@ -11828,7 +14175,7 @@ var AgentProcessManager = class _AgentProcessManager {
11828
14175
  const collect = (messages) => (messages ?? []).filter((message) => typeof message.seq === "number" && message.seq > 0);
11829
14176
  return [
11830
14177
  ...collect(this.agents.get(agentId)?.inbox),
11831
- ...collect(this.startingInboxes.get(agentId))
14178
+ ...collect(this.startingInboxes.values(agentId))
11832
14179
  ];
11833
14180
  }
11834
14181
  pendingVisibleMessages(agentId, target) {
@@ -11841,61 +14188,13 @@ var AgentProcessManager = class _AgentProcessManager {
11841
14188
  * same seq must not be injected later through the local pending queue.
11842
14189
  */
11843
14190
  consumeVisibleMessages(agentId, input) {
11844
- if (input.messages.length === 0 && (!input.target || typeof input.boundarySeq !== "number")) return;
11845
- const byTarget = /* @__PURE__ */ new Map();
11846
- const ensureBucket = (target) => {
11847
- let bucket = byTarget.get(target);
11848
- if (!bucket) {
11849
- bucket = { maxSeq: 0, boundarySeq: 0, seqs: /* @__PURE__ */ new Set(), ids: /* @__PURE__ */ new Set() };
11850
- byTarget.set(target, bucket);
11851
- }
11852
- return bucket;
11853
- };
11854
- for (const message of input.messages) {
11855
- const seq = Number(message.seq ?? 0);
11856
- const target = input.target ?? formatVisibleMessageTarget(message);
11857
- if (!target) continue;
11858
- const bucket = ensureBucket(target);
11859
- if (Number.isFinite(seq) && seq > 0) {
11860
- bucket.maxSeq = Math.max(bucket.maxSeq, Math.floor(seq));
11861
- bucket.seqs.add(Math.floor(seq));
11862
- }
11863
- const id = typeof message.message_id === "string" ? message.message_id : typeof message.id === "string" ? message.id : null;
11864
- if (id) bucket.ids.add(id);
11865
- }
11866
- if (input.target && typeof input.boundarySeq === "number" && Number.isFinite(input.boundarySeq) && input.boundarySeq > 0) {
11867
- const bucket = ensureBucket(input.target);
11868
- bucket.boundarySeq = Math.max(bucket.boundarySeq, Math.floor(input.boundarySeq));
11869
- }
11870
- if (byTarget.size === 0) return;
11871
- const boundaryMap = this.visibleBoundaryMap(agentId);
11872
- const visibleIds = this.visibleMessageIdMap(agentId);
11873
- const advancesBoundary = input.source === "spawn_wake_message" || input.source === "agent_api_events_local" || input.source.startsWith("stdin_");
11874
- for (const [target, bucket] of byTarget) {
11875
- if (advancesBoundary) {
11876
- const highWaterSeq = Math.max(bucket.maxSeq, bucket.boundarySeq);
11877
- const previous = boundaryMap.get(target) ?? 0;
11878
- boundaryMap.set(target, Math.max(previous, highWaterSeq));
11879
- }
11880
- if (bucket.ids.size > 0) {
11881
- let targetIds = visibleIds.get(target);
11882
- if (!targetIds) {
11883
- targetIds = /* @__PURE__ */ new Set();
11884
- visibleIds.set(target, targetIds);
11885
- }
11886
- for (const id of bucket.ids) targetIds.add(id);
11887
- }
11888
- }
14191
+ const consumed = this.agentVisibleDelivery.recordConsumed(agentId, input);
14192
+ if (!consumed) return;
11889
14193
  const suppress = (messages) => {
11890
14194
  if (!messages || messages.length === 0) return 0;
11891
14195
  let removed = 0;
11892
14196
  const retained = messages.filter((message) => {
11893
- const target = formatMessageTarget(message);
11894
- const bucket = byTarget.get(target);
11895
- if (!bucket) return true;
11896
- const seq = typeof message.seq === "number" ? Math.floor(message.seq) : 0;
11897
- const id = message.message_id ?? "";
11898
- const matched = seq > 0 && bucket.boundarySeq > 0 && seq <= bucket.boundarySeq || seq > 0 && bucket.seqs.has(seq) || id.length > 0 && bucket.ids.has(id);
14197
+ const matched = consumed.shouldSuppress(message);
11899
14198
  if (matched) removed += 1;
11900
14199
  return !matched;
11901
14200
  });
@@ -11904,12 +14203,13 @@ var AgentProcessManager = class _AgentProcessManager {
11904
14203
  };
11905
14204
  const active = this.agents.get(agentId);
11906
14205
  const removedActive = suppress(active?.inbox);
11907
- const removedStarting = suppress(this.startingInboxes.get(agentId));
14206
+ const removedStarting = this.startingInboxes.suppressConsumed(agentId, consumed.shouldSuppress);
14207
+ this.assertStartPendingDeliveryInvariants("visible-consume");
11908
14208
  this.recordDaemonTrace("daemon.agent.inbox.visible_consumed", {
11909
14209
  agentId,
11910
14210
  source: input.source,
11911
- targets: [...byTarget.keys()],
11912
- messages_count: input.messages.length,
14211
+ targets: consumed.targets,
14212
+ messages_count: consumed.messagesCount,
11913
14213
  suppressed_pending_count: removedActive + removedStarting
11914
14214
  });
11915
14215
  }
@@ -11931,11 +14231,8 @@ var AgentProcessManager = class _AgentProcessManager {
11931
14231
  };
11932
14232
  const active = this.agents.get(agentId);
11933
14233
  const removedActive = purge(active?.inbox);
11934
- const startingInbox = this.startingInboxes.get(agentId);
11935
- const removedStarting = purge(startingInbox);
11936
- if (startingInbox && startingInbox.length === 0) {
11937
- this.startingInboxes.delete(agentId);
11938
- }
14234
+ const removedStarting = this.startingInboxes.purge(agentId, (message) => channelIdSet.has(message.channel_id));
14235
+ this.assertStartPendingDeliveryInvariants("purge-starting-inbox");
11939
14236
  if (active && removedActive > 0) {
11940
14237
  active.notifications.remove(removedActive);
11941
14238
  if (active.inbox.length === 0) {
@@ -11952,7 +14249,7 @@ var AgentProcessManager = class _AgentProcessManager {
11952
14249
  removed_starting_count: removedStarting,
11953
14250
  removed_count: removedCount,
11954
14251
  active_inbox_count: active?.inbox.length ?? 0,
11955
- starting_inbox_count: this.startingInboxes.get(agentId)?.length ?? 0
14252
+ starting_inbox_count: this.startingInboxes.count(agentId)
11956
14253
  });
11957
14254
  return { removedCount };
11958
14255
  }
@@ -12025,7 +14322,7 @@ var AgentProcessManager = class _AgentProcessManager {
12025
14322
  recordFreshnessDecisionActivity(agentId, input, producerFactId) {
12026
14323
  if (input.decision !== "local_hold" && input.decision !== "syncing_hold") return;
12027
14324
  const ap = this.agents.get(agentId);
12028
- const messageCount = input.pendingCount ?? input.heldMessageCount ?? 0;
14325
+ const messageCount = input.decision === "syncing_hold" ? input.heldMessageCount ?? input.pendingCount ?? 0 : input.pendingCount ?? input.heldMessageCount ?? 0;
12029
14326
  const entry = projectApmHeldFreshnessActivity({
12030
14327
  producerFactId,
12031
14328
  action: input.action,
@@ -12099,6 +14396,7 @@ var AgentProcessManager = class _AgentProcessManager {
12099
14396
  };
12100
14397
  }
12101
14398
  startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient = false) {
14399
+ const startSnapshot = this.agentStarts.snapshot();
12102
14400
  return {
12103
14401
  agentId,
12104
14402
  launchId,
@@ -12110,10 +14408,10 @@ var AgentProcessManager = class _AgentProcessManager {
12110
14408
  wake_message_transient: Boolean(wakeMessage && wakeMessageTransient),
12111
14409
  unread_channels_count: unreadSummary ? Object.keys(unreadSummary).length : 0,
12112
14410
  resume_prompt_present: Boolean(resumePrompt),
12113
- queue_depth: this.agentStartQueue.length,
12114
- active_starts: this.activeAgentStartCount,
12115
- max_concurrent_starts: this.maxConcurrentAgentStarts,
12116
- min_start_interval_ms: this.agentStartIntervalMs,
14411
+ queue_depth: startSnapshot.queueDepth,
14412
+ active_starts: startSnapshot.activeStarts,
14413
+ max_concurrent_starts: startSnapshot.maxConcurrentStarts,
14414
+ min_start_interval_ms: startSnapshot.minStartIntervalMs,
12117
14415
  ...this.runtimeLaunchPolicyTraceAttrs(config)
12118
14416
  };
12119
14417
  }
@@ -12199,18 +14497,20 @@ var AgentProcessManager = class _AgentProcessManager {
12199
14497
  return left === right;
12200
14498
  }
12201
14499
  rebindQueuedStart(agentId, start, reason) {
12202
- const item = this.queuedAgentStarts.get(agentId);
14500
+ const item = this.agentStarts.getQueued(agentId);
12203
14501
  if (!item) {
12204
14502
  return false;
12205
14503
  }
12206
14504
  const previousLaunchId = item.launchId || null;
12207
14505
  const nextLaunchId = start.launchId || previousLaunchId;
12208
14506
  const previousWakeMessage = item.wakeMessage;
12209
- if (previousWakeMessage && start.wakeMessage && !this.sameWakeMessage(previousWakeMessage, start.wakeMessage)) {
12210
- const pending = this.startingInboxes.get(agentId) || [];
12211
- pending.push(previousWakeMessage);
12212
- this.startingInboxes.set(agentId, pending);
12213
- }
14507
+ this.startingInboxes.rebindWake(
14508
+ agentId,
14509
+ previousWakeMessage,
14510
+ start.wakeMessage,
14511
+ (left, right) => this.sameWakeMessage(left, right)
14512
+ );
14513
+ this.assertStartPendingDeliveryInvariants("rebind-queued-start");
12214
14514
  item.config = start.config;
12215
14515
  item.unreadSummary = start.unreadSummary;
12216
14516
  item.resumePrompt = start.resumePrompt;
@@ -12277,7 +14577,7 @@ var AgentProcessManager = class _AgentProcessManager {
12277
14577
  logger.info(`[Agent ${agentId}] Start rebound (already running)`);
12278
14578
  return;
12279
14579
  }
12280
- if (this.agentsStarting.has(agentId)) {
14580
+ if (this.agentStarts.hasStarting(agentId)) {
12281
14581
  this.recordDaemonTrace("daemon.agent.start.ignored", {
12282
14582
  ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient),
12283
14583
  reason: "already_starting"
@@ -12286,7 +14586,7 @@ var AgentProcessManager = class _AgentProcessManager {
12286
14586
  logger.info(`[Agent ${agentId}] Start rebind deferred (startup in progress)`);
12287
14587
  return;
12288
14588
  }
12289
- if (this.queuedAgentStarts.has(agentId)) {
14589
+ if (this.agentStarts.hasQueued(agentId)) {
12290
14590
  this.recordDaemonTrace("daemon.agent.start.ignored", {
12291
14591
  ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient),
12292
14592
  reason: "already_queued"
@@ -12307,46 +14607,40 @@ var AgentProcessManager = class _AgentProcessManager {
12307
14607
  resolve,
12308
14608
  reject
12309
14609
  };
12310
- this.agentStartQueue.push(item);
12311
- this.queuedAgentStarts.set(agentId, item);
14610
+ this.agentStarts.enqueue(item);
12312
14611
  this.recordDaemonTrace("daemon.agent.start.queued", this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient));
14612
+ const startSnapshot = this.agentStarts.snapshot();
12313
14613
  logger.info(
12314
- `[Agent ${agentId}] Start queued (queue=${this.agentStartQueue.length}, active=${this.activeAgentStartCount}, max=${this.maxConcurrentAgentStarts}, interval=${this.agentStartIntervalMs}ms)`
14614
+ `[Agent ${agentId}] Start queued (queue=${startSnapshot.queueDepth}, active=${startSnapshot.activeStarts}, max=${startSnapshot.maxConcurrentStarts}, interval=${startSnapshot.minStartIntervalMs}ms)`
12315
14615
  );
12316
14616
  this.pumpAgentStartQueue();
12317
14617
  });
12318
14618
  }
12319
14619
  pumpAgentStartQueue() {
12320
- if (this.agentStartPumpTimer) return;
12321
- if (this.agentStartQueue.length === 0) return;
12322
- if (this.activeAgentStartCount >= this.maxConcurrentAgentStarts) return;
12323
- const next = this.agentStartQueue[0];
12324
- const shouldRateLimit = next ? next.agentId !== this.lastAgentStartAgentId : true;
12325
- const elapsed = Date.now() - this.lastAgentStartAt;
12326
- const waitMs = shouldRateLimit ? Math.max(0, this.agentStartIntervalMs - elapsed) : 0;
12327
- if (waitMs > 0) {
14620
+ const pumpState = this.agentStarts.getPumpState();
14621
+ if (pumpState.kind === "blocked") return;
14622
+ if (pumpState.kind === "rate_limited") {
14623
+ const { item: next, waitMs } = pumpState;
12328
14624
  this.recordDaemonTrace("daemon.agent.start.rate_limited", {
12329
14625
  ...this.startQueueTraceAttrs(next.agentId, next.config, next.wakeMessage, next.unreadSummary, next.resumePrompt, next.launchId, next.wakeMessageTransient),
12330
14626
  wait_ms: waitMs
12331
14627
  });
12332
- this.agentStartPumpTimer = setTimeout(() => {
12333
- this.agentStartPumpTimer = null;
12334
- this.pumpAgentStartQueue();
12335
- }, waitMs);
14628
+ this.agentStarts.schedulePump(waitMs, () => this.pumpAgentStartQueue());
12336
14629
  return;
12337
14630
  }
12338
- const item = this.agentStartQueue.shift();
12339
- if (!item) return;
12340
- if (this.queuedAgentStarts.get(item.agentId) !== item) {
14631
+ const dequeued = this.agentStarts.dequeue();
14632
+ if (dequeued.kind === "empty") return;
14633
+ if (dequeued.kind === "stale") {
14634
+ const { item: item2 } = dequeued;
12341
14635
  this.recordDaemonTrace("daemon.agent.start.skipped", {
12342
- ...this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient),
14636
+ ...this.startQueueTraceAttrs(item2.agentId, item2.config, item2.wakeMessage, item2.unreadSummary, item2.resumePrompt, item2.launchId, item2.wakeMessageTransient),
12343
14637
  reason: "stale_queue_item"
12344
14638
  });
12345
14639
  this.pumpAgentStartQueue();
12346
14640
  return;
12347
14641
  }
12348
- this.queuedAgentStarts.delete(item.agentId);
12349
- if (this.agents.has(item.agentId) || this.agentsStarting.has(item.agentId)) {
14642
+ const { item } = dequeued;
14643
+ if (this.agents.has(item.agentId) || this.agentStarts.hasStarting(item.agentId)) {
12350
14644
  this.recordDaemonTrace("daemon.agent.start.skipped", {
12351
14645
  ...this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient),
12352
14646
  reason: "already_running_or_starting"
@@ -12361,11 +14655,10 @@ var AgentProcessManager = class _AgentProcessManager {
12361
14655
  this.pumpAgentStartQueue();
12362
14656
  return;
12363
14657
  }
12364
- this.activeAgentStartCount++;
12365
- this.lastAgentStartAt = Date.now();
12366
- this.lastAgentStartAgentId = item.agentId;
14658
+ this.agentStarts.claimStartSlot(item.agentId);
14659
+ const startSnapshot = this.agentStarts.snapshot();
12367
14660
  logger.info(
12368
- `[Agent ${item.agentId}] Dequeued start (remaining=${this.agentStartQueue.length}, active=${this.activeAgentStartCount})`
14661
+ `[Agent ${item.agentId}] Dequeued start (remaining=${startSnapshot.queueDepth}, active=${startSnapshot.activeStarts})`
12369
14662
  );
12370
14663
  this.recordDaemonTrace("daemon.agent.start.dequeued", this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient));
12371
14664
  this.startAgentNow(
@@ -12385,30 +14678,25 @@ var AgentProcessManager = class _AgentProcessManager {
12385
14678
  });
12386
14679
  }
12387
14680
  releaseAgentStartSlot(agentId, reason) {
12388
- if (this.activeAgentStartCount <= 0) return;
12389
- this.activeAgentStartCount = Math.max(0, this.activeAgentStartCount - 1);
14681
+ if (!this.agentStarts.releaseStartSlot()) return;
14682
+ const startSnapshot = this.agentStarts.snapshot();
12390
14683
  this.recordDaemonTrace("daemon.agent.start.slot_released", {
12391
14684
  agentId,
12392
14685
  reason,
12393
- active_starts: this.activeAgentStartCount,
12394
- queue_depth: this.agentStartQueue.length,
12395
- max_concurrent_starts: this.maxConcurrentAgentStarts
14686
+ active_starts: startSnapshot.activeStarts,
14687
+ queue_depth: startSnapshot.queueDepth,
14688
+ max_concurrent_starts: startSnapshot.maxConcurrentStarts
12396
14689
  });
12397
14690
  logger.info(
12398
- `[Agent ${agentId}] Start slot released (${reason}) (active=${this.activeAgentStartCount}, queue=${this.agentStartQueue.length})`
14691
+ `[Agent ${agentId}] Start slot released (${reason}) (active=${startSnapshot.activeStarts}, queue=${startSnapshot.queueDepth})`
12399
14692
  );
12400
14693
  this.pumpAgentStartQueue();
12401
14694
  }
12402
14695
  cancelQueuedAgentStart(agentId, reason) {
12403
- const item = this.queuedAgentStarts.get(agentId);
14696
+ const item = this.agentStarts.cancelQueued(agentId);
12404
14697
  if (!item) return false;
12405
- this.queuedAgentStarts.delete(agentId);
12406
- this.agentStartQueue = this.agentStartQueue.filter((candidate) => candidate !== item);
12407
- this.startingInboxes.delete(agentId);
12408
- if (this.agentStartQueue.length === 0 && this.agentStartPumpTimer) {
12409
- clearTimeout(this.agentStartPumpTimer);
12410
- this.agentStartPumpTimer = null;
12411
- }
14698
+ this.startingInboxes.cancelStart(agentId);
14699
+ this.assertStartPendingDeliveryInvariants("cancel-queued-start");
12412
14700
  this.recordDaemonTrace("daemon.agent.start.cancelled", {
12413
14701
  ...this.startQueueTraceAttrs(agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient),
12414
14702
  reason
@@ -12418,23 +14706,18 @@ var AgentProcessManager = class _AgentProcessManager {
12418
14706
  return true;
12419
14707
  }
12420
14708
  cancelAllQueuedAgentStarts(reason) {
12421
- for (const item of this.agentStartQueue) {
12422
- if (this.queuedAgentStarts.get(item.agentId) === item) {
12423
- this.recordDaemonTrace("daemon.agent.start.cancelled", {
12424
- ...this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient),
12425
- reason
12426
- }, "cancelled");
12427
- logger.info(`[Agent ${item.agentId}] Queued start cancelled (${reason})`);
12428
- item.resolve();
12429
- }
12430
- }
12431
- this.agentStartQueue = [];
12432
- this.queuedAgentStarts.clear();
12433
- this.startingInboxes.clear();
12434
- if (this.agentStartPumpTimer) {
12435
- clearTimeout(this.agentStartPumpTimer);
12436
- this.agentStartPumpTimer = null;
14709
+ const cancelled = this.agentStarts.cancelAllQueued((item) => {
14710
+ this.recordDaemonTrace("daemon.agent.start.cancelled", {
14711
+ ...this.startQueueTraceAttrs(item.agentId, item.config, item.wakeMessage, item.unreadSummary, item.resumePrompt, item.launchId, item.wakeMessageTransient),
14712
+ reason
14713
+ }, "cancelled");
14714
+ logger.info(`[Agent ${item.agentId}] Queued start cancelled (${reason})`);
14715
+ });
14716
+ for (const item of cancelled) {
14717
+ item.resolve();
12437
14718
  }
14719
+ this.startingInboxes.cancelAllStarts();
14720
+ this.assertStartPendingDeliveryInvariants("cancel-all-queued-starts");
12438
14721
  }
12439
14722
  async startAgentNow(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient = false) {
12440
14723
  if (this.agents.has(agentId)) {
@@ -12446,7 +14729,7 @@ var AgentProcessManager = class _AgentProcessManager {
12446
14729
  logger.info(`[Agent ${agentId}] Start rebound (already running)`);
12447
14730
  return;
12448
14731
  }
12449
- if (this.agentsStarting.has(agentId)) {
14732
+ if (this.agentStarts.hasStarting(agentId)) {
12450
14733
  this.recordDaemonTrace("daemon.agent.spawn.skipped", {
12451
14734
  ...this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId, wakeMessageTransient),
12452
14735
  reason: "already_starting"
@@ -12455,7 +14738,7 @@ var AgentProcessManager = class _AgentProcessManager {
12455
14738
  logger.info(`[Agent ${agentId}] Start rebind deferred (startup in progress)`);
12456
14739
  return;
12457
14740
  }
12458
- this.agentsStarting.add(agentId);
14741
+ this.agentStarts.markStarting(agentId);
12459
14742
  let agentProcess = null;
12460
14743
  let pendingStartRebind;
12461
14744
  const originalLaunchId = launchId || null;
@@ -12488,11 +14771,13 @@ var AgentProcessManager = class _AgentProcessManager {
12488
14771
  if (pendingStartRebind) {
12489
14772
  this.pendingStartRebinds.delete(agentId);
12490
14773
  const previousWakeMessage = wakeMessage;
12491
- if (previousWakeMessage && pendingStartRebind.wakeMessage && !this.sameWakeMessage(previousWakeMessage, pendingStartRebind.wakeMessage)) {
12492
- const pending = this.startingInboxes.get(agentId) || [];
12493
- pending.push(previousWakeMessage);
12494
- this.startingInboxes.set(agentId, pending);
12495
- }
14774
+ this.startingInboxes.rebindWake(
14775
+ agentId,
14776
+ previousWakeMessage,
14777
+ pendingStartRebind.wakeMessage,
14778
+ (left, right) => this.sameWakeMessage(left, right)
14779
+ );
14780
+ this.assertStartPendingDeliveryInvariants("rebind-starting-start");
12496
14781
  config = pendingStartRebind.config;
12497
14782
  unreadSummary = pendingStartRebind.unreadSummary;
12498
14783
  resumePrompt = pendingStartRebind.resumePrompt;
@@ -12533,7 +14818,7 @@ var AgentProcessManager = class _AgentProcessManager {
12533
14818
  let promptSource;
12534
14819
  let wakeMessageDeliveredAsInboxUpdate = false;
12535
14820
  let startingInboxDeliveredAsInput = false;
12536
- const startingInboxMessages = this.startingInboxes.get(agentId) || [];
14821
+ const startingInboxMessages = this.startingInboxes.values(agentId);
12537
14822
  if (runtimeConfig.runtimeProfileControl && !wakeMessage) {
12538
14823
  prompt = driver.supportsNativeStandingPrompt ? NATIVE_STANDING_PROMPT_STARTUP_INPUT : formatRuntimeProfileControlStartupInput(runtimeConfig.runtimeProfileControl, driver);
12539
14824
  promptSource = "runtime_profile_control";
@@ -12585,7 +14870,7 @@ Use the inbox/read commands at a natural breakpoint if you choose to inspect tho
12585
14870
  }
12586
14871
  prompt += `
12587
14872
 
12588
- Use ${communicationCommand("read_history")} to catch up on the channels listed above, then stop. Read each listed channel at most once unless a read fails. Do NOT call ${communicationCommand("check_messages")} in this mode. If the history reveals a direct request, assignment, @mention, review request, or task clearly addressed to you, switch into active handling instead of stopping: ${dynamicReplyInstruction()} and ${dynamicClaimInstruction()} before starting work. Otherwise, do NOT send any message in this mode. ${getMessageDeliveryText(driver)}`;
14873
+ Use \`raft message read\` to catch up on the channels listed above, then stop. Read each listed channel at most once unless a read fails. Do NOT call \`raft message check\` in this mode. If the history reveals a direct request, assignment, @mention, review request, or task clearly addressed to you, switch into active handling instead of stopping: reply using \`raft message send --target <exact target>\` and claim the relevant task with \`raft task claim\` before starting work. Otherwise, do NOT send any message in this mode. ${getMessageDeliveryText(driver)}`;
12589
14874
  promptSource = "resume_unread_summary";
12590
14875
  } else if (isResume) {
12591
14876
  prompt = `No new messages while you were away. Nothing to do \u2014 just stop. ${getMessageDeliveryText(driver)}`;
@@ -12608,9 +14893,9 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
12608
14893
  const effectiveLaunchId = launchId || null;
12609
14894
  const canDeferEmptyStart = driver.deferSpawnUntilMessage === true && !wakeMessage && !runtimeConfig.runtimeProfileControl && (!unreadSummary || Object.keys(unreadSummary).length === 0);
12610
14895
  if (canDeferEmptyStart) {
12611
- const pendingMessages = this.startingInboxes.get(agentId) || [];
12612
- this.startingInboxes.delete(agentId);
12613
- this.agentsStarting.delete(agentId);
14896
+ const pendingMessages = this.startingInboxes.drainOnSpawn(agentId);
14897
+ this.agentStarts.clearStarting(agentId);
14898
+ this.assertStartPendingDeliveryInvariants("defer-empty-start-drain");
12614
14899
  this.idleAgentConfigs.set(agentId, {
12615
14900
  config: this.buildRestartSafeConfig(runtimeConfig, runtimeConfig.sessionId || null),
12616
14901
  sessionId: runtimeConfig.sessionId || null,
@@ -12693,7 +14978,8 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
12693
14978
  pendingTrajectory: null,
12694
14979
  gatedSteering: createGatedSteeringState()
12695
14980
  };
12696
- this.startingInboxes.delete(agentId);
14981
+ this.startingInboxes.drainOnSpawn(agentId);
14982
+ this.assertStartPendingDeliveryInvariants("spawn-drain");
12697
14983
  this.agents.set(agentId, agentProcess);
12698
14984
  this.idleAgentConfigs.set(agentId, {
12699
14985
  config: this.buildRestartSafeConfig(runtimeConfig, restartSessionId),
@@ -12704,7 +14990,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
12704
14990
  this.recordStartRebind(agentId, pendingStartRebind, "startup_registered", originalLaunchId, effectiveLaunchId, agentProcess.sessionId);
12705
14991
  }
12706
14992
  this.startRuntimeTrace(agentId, agentProcess, "spawn", wakeMessage ? [wakeMessage] : void 0, runtimeInputTraceAttrs);
12707
- this.agentsStarting.delete(agentId);
14993
+ this.agentStarts.clearStarting(agentId);
12708
14994
  if (runtimeConfig.runtimeProfileControl) {
12709
14995
  this.ackInjectedRuntimeProfileControl(agentId, runtimeConfig.runtimeProfileControl, agentProcess.launchId);
12710
14996
  }
@@ -13008,7 +15294,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13008
15294
  this.broadcastActivity(agentId, "working", "Starting\u2026");
13009
15295
  this.startRuntimeStartupTimeout(agentId, agentProcess);
13010
15296
  } catch (err) {
13011
- this.agentsStarting.delete(agentId);
15297
+ this.agentStarts.clearStarting(agentId);
13012
15298
  this.pendingStartRebinds.delete(agentId);
13013
15299
  this.cleanupFailedRuntimeStart(agentId, agentProcess, err);
13014
15300
  throw err;
@@ -13062,11 +15348,11 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13062
15348
  cleanupAgentCredentialProxy(agentId, ap.launchId);
13063
15349
  this.revokeManagedRunnerCredential(agentId, ap.config, ap.launchId);
13064
15350
  this.idleAgentConfigs.delete(agentId);
13065
- const pending = this.startingInboxes.get(agentId) || [];
13066
15351
  if (ap.inbox.length > 0) {
13067
- this.startingInboxes.set(agentId, [...pending, ...ap.inbox]);
15352
+ this.startingInboxes.bufferMessagesDuringStart(agentId, ap.inbox);
13068
15353
  }
13069
15354
  this.terminalRuntimeFailures.set(agentId, { detail, launchId: ap.launchId });
15355
+ this.assertStartPendingDeliveryInvariants("terminal-runtime-failure-cleanup");
13070
15356
  this.agents.delete(agentId);
13071
15357
  const diagnostics = buildRuntimeErrorDiagnosticEnvelope(detail);
13072
15358
  this.recordDaemonTrace("daemon.agent.terminal_runtime_error.cleanup", {
@@ -13309,10 +15595,9 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13309
15595
  );
13310
15596
  }
13311
15597
  queueRuntimeProfileNotificationDuringStart(agentId, message, kind, key) {
13312
- const pending = this.startingInboxes.get(agentId) || [];
13313
- pending.push(message);
13314
- this.startingInboxes.set(agentId, pending);
13315
- const queuedStart = this.queuedAgentStarts.get(agentId);
15598
+ const startingInboxCount = this.startingInboxes.bufferDuringStart(agentId, message);
15599
+ this.assertStartPendingDeliveryInvariants("runtime-profile-during-start");
15600
+ const queuedStart = this.agentStarts.getQueued(agentId);
13316
15601
  this.recordDaemonTrace("daemon.agent.runtime_profile.routed", {
13317
15602
  agentId,
13318
15603
  kind,
@@ -13320,7 +15605,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13320
15605
  key_hash: hashRuntimeProfileKey(key),
13321
15606
  outcome: "queued_during_start",
13322
15607
  startup_pending: true,
13323
- starting_inbox_count: pending.length,
15608
+ starting_inbox_count: startingInboxCount,
13324
15609
  launchId: queuedStart?.launchId
13325
15610
  });
13326
15611
  logger.info(`[Agent ${agentId}] Queued runtime profile ${kind} ${key} during startup`);
@@ -13352,8 +15637,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13352
15637
  this.agents.delete(agentId);
13353
15638
  if (!silent) {
13354
15639
  this.activityClientSeqByAgent.delete(agentId);
13355
- this.agentVisibleBoundaries.delete(agentId);
13356
- this.agentVisibleMessageIds.delete(agentId);
15640
+ this.agentVisibleDelivery.clearAgent(agentId);
13357
15641
  this.resetSpawnFailBackoff(agentId);
13358
15642
  this.resetRuntimeErrorFingerprintFence(agentId, "explicit_stop", ap);
13359
15643
  }
@@ -13379,6 +15663,15 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13379
15663
  if (!silent) {
13380
15664
  logger.warn(`[Agent ${agentId}] Stop timed out; force killing`);
13381
15665
  }
15666
+ this.recordDaemonTrace("daemon.agent.stop.timeout_sigkill", {
15667
+ agent_id: agentId,
15668
+ pid: typeof ap.runtime.pid === "number" ? ap.runtime.pid : void 0,
15669
+ timeout_ms: 5e3,
15670
+ reason: "wait_timeout",
15671
+ signal: "SIGKILL"
15672
+ });
15673
+ void ap.runtime.stop({ signal: "SIGKILL" }).catch(() => {
15674
+ });
13382
15675
  resolve();
13383
15676
  }, 5e3);
13384
15677
  ap.runtime.on("exit", () => {
@@ -13410,9 +15703,9 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13410
15703
  }
13411
15704
  const ap = this.agents.get(agentId);
13412
15705
  if (!ap) {
13413
- if (this.agentsStarting.has(agentId) || this.queuedAgentStarts.has(agentId)) {
15706
+ if (this.agentStarts.hasStarting(agentId) || this.agentStarts.hasQueued(agentId)) {
13414
15707
  if (transientDelivery) {
13415
- const queuedStart2 = this.queuedAgentStarts.get(agentId);
15708
+ const queuedStart2 = this.agentStarts.getQueued(agentId);
13416
15709
  this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
13417
15710
  outcome: "transient_dropped_during_start",
13418
15711
  accepted: true,
@@ -13422,16 +15715,15 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13422
15715
  }));
13423
15716
  return true;
13424
15717
  }
13425
- const queuedStart = this.queuedAgentStarts.get(agentId);
13426
- const pending = this.startingInboxes.get(agentId) || [];
13427
- pending.push(message);
13428
- this.startingInboxes.set(agentId, pending);
15718
+ const queuedStart = this.agentStarts.getQueued(agentId);
15719
+ const startingInboxCount = this.startingInboxes.bufferDuringStart(agentId, message);
15720
+ this.assertStartPendingDeliveryInvariants("delivery-during-start");
13429
15721
  this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
13430
15722
  outcome: "queued_during_start",
13431
15723
  accepted: true,
13432
15724
  process_present: false,
13433
15725
  startup_pending: true,
13434
- starting_inbox_count: pending.length,
15726
+ starting_inbox_count: startingInboxCount,
13435
15727
  launchId: queuedStart?.launchId
13436
15728
  }));
13437
15729
  return true;
@@ -13449,16 +15741,15 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13449
15741
  }));
13450
15742
  return true;
13451
15743
  }
13452
- const pending = this.startingInboxes.get(agentId) || [];
13453
- pending.push(message);
13454
- this.startingInboxes.set(agentId, pending);
15744
+ const startingInboxCount = this.startingInboxes.bufferDuringStart(agentId, message);
15745
+ this.assertStartPendingDeliveryInvariants("delivery-terminal-runtime-error");
13455
15746
  this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
13456
15747
  outcome: "queued_terminal_runtime_error_no_process",
13457
15748
  accepted: true,
13458
15749
  process_present: false,
13459
15750
  cached_idle_config_present: false,
13460
15751
  terminal_runtime_failure: true,
13461
- starting_inbox_count: pending.length,
15752
+ starting_inbox_count: startingInboxCount,
13462
15753
  launchId: terminalRuntimeFailure.launchId || void 0
13463
15754
  }));
13464
15755
  this.sendAgentStatus(agentId, "inactive", terminalRuntimeFailure.launchId);
@@ -13483,9 +15774,8 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13483
15774
  logger.info(`[Agent ${agentId}] Starting from idle state for new message`);
13484
15775
  if (this.isSpawnFailBackoffActive(agentId)) {
13485
15776
  const state = this.agentSpawnFailBackoff.get(agentId);
13486
- const pending = this.startingInboxes.get(agentId) || [];
13487
- pending.push(message);
13488
- this.startingInboxes.set(agentId, pending);
15777
+ const startingInboxCount = this.startingInboxes.bufferDuringStart(agentId, message);
15778
+ this.assertStartPendingDeliveryInvariants("delivery-spawn-fail-cooldown");
13489
15779
  this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
13490
15780
  outcome: "spawn_fail_cooldown_active",
13491
15781
  accepted: true,
@@ -13496,7 +15786,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13496
15786
  launchId: cached.launchId || void 0,
13497
15787
  spawn_fail_attempts: state.attempts,
13498
15788
  spawn_fail_until_ms: state.untilMs,
13499
- starting_inbox_count: pending.length
15789
+ starting_inbox_count: startingInboxCount
13500
15790
  }));
13501
15791
  return true;
13502
15792
  }
@@ -13540,16 +15830,15 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13540
15830
  return false;
13541
15831
  });
13542
15832
  }
13543
- if (!transientDelivery && (this.queuedAgentStarts.has(agentId) || this.agentsStarting.has(agentId))) {
13544
- const pending = this.startingInboxes.get(agentId) || [];
13545
- pending.push(message);
13546
- this.startingInboxes.set(agentId, pending);
15833
+ if (!transientDelivery && (this.agentStarts.hasQueued(agentId) || this.agentStarts.hasStarting(agentId))) {
15834
+ const startingInboxCount = this.startingInboxes.bufferDuringStart(agentId, message);
15835
+ this.assertStartPendingDeliveryInvariants("delivery-queued-or-starting");
13547
15836
  this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
13548
- outcome: this.agentsStarting.has(agentId) ? "queued_for_starting_process" : "queued_for_queued_start",
15837
+ outcome: this.agentStarts.hasStarting(agentId) ? "queued_for_starting_process" : "queued_for_queued_start",
13549
15838
  accepted: true,
13550
15839
  process_present: false,
13551
15840
  cached_idle_config_present: false,
13552
- starting_inbox_count: pending.length
15841
+ starting_inbox_count: startingInboxCount
13553
15842
  }));
13554
15843
  return true;
13555
15844
  }
@@ -13877,8 +16166,74 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
13877
16166
  async stopAll() {
13878
16167
  this.cancelAllQueuedAgentStarts("daemon shutdown");
13879
16168
  this.idleAgentConfigs.clear();
16169
+ const pids = [];
16170
+ for (const ap of this.agents.values()) {
16171
+ if (typeof ap.runtime.pid === "number") pids.push(ap.runtime.pid);
16172
+ }
13880
16173
  const ids = [...this.agents.keys()];
16174
+ this.recordDaemonTrace("daemon.agent.stop_all.started", {
16175
+ agent_count: ids.length,
16176
+ pid_count: pids.length,
16177
+ pids: pids.join(",")
16178
+ });
13881
16179
  await Promise.all(ids.map((id) => this.stopAgent(id, { wait: true, silent: true })));
16180
+ const survivors = pids.filter((pid) => {
16181
+ try {
16182
+ process.kill(pid, 0);
16183
+ return true;
16184
+ } catch {
16185
+ return false;
16186
+ }
16187
+ });
16188
+ if (survivors.length > 0) {
16189
+ for (const pid of survivors) {
16190
+ logger.warn(`[Daemon] Agent subprocess ${pid} survived stopAll; sending SIGKILL`);
16191
+ try {
16192
+ process.kill(pid, "SIGKILL");
16193
+ } catch {
16194
+ }
16195
+ }
16196
+ this.recordDaemonTrace("daemon.agent.stop_all.survivor_reaped", {
16197
+ survivor_count: survivors.length,
16198
+ survivor_pids: survivors.join(","),
16199
+ reason: "shutdown_survivor",
16200
+ signal: "SIGKILL"
16201
+ });
16202
+ const deadline = Date.now() + 2e3;
16203
+ while (Date.now() < deadline) {
16204
+ const alive = survivors.filter((pid) => {
16205
+ try {
16206
+ process.kill(pid, 0);
16207
+ return true;
16208
+ } catch {
16209
+ return false;
16210
+ }
16211
+ });
16212
+ if (alive.length === 0) break;
16213
+ await new Promise((r) => setTimeout(r, 50));
16214
+ }
16215
+ const stillAlive = survivors.filter((pid) => {
16216
+ try {
16217
+ process.kill(pid, 0);
16218
+ return true;
16219
+ } catch {
16220
+ return false;
16221
+ }
16222
+ });
16223
+ const outcome = stillAlive.length > 0 ? "survivors_still_alive" : "survivors_killed";
16224
+ this.recordDaemonTrace("daemon.agent.stop_all.completed", {
16225
+ survivor_count: survivors.length,
16226
+ reaped_count: survivors.length - stillAlive.length,
16227
+ still_alive_count: stillAlive.length,
16228
+ outcome
16229
+ }, stillAlive.length > 0 ? "error" : "ok");
16230
+ } else {
16231
+ this.recordDaemonTrace("daemon.agent.stop_all.completed", {
16232
+ agent_count: ids.length,
16233
+ survivor_count: 0,
16234
+ outcome: "all_dead"
16235
+ });
16236
+ }
13882
16237
  }
13883
16238
  getRunningAgentIds() {
13884
16239
  return [...this.agents.keys()];
@@ -14064,8 +16419,8 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
14064
16419
  });
14065
16420
  return written;
14066
16421
  }
14067
- if (this.agentsStarting.has(agentId) || this.queuedAgentStarts.has(agentId)) {
14068
- const queuedStart = this.queuedAgentStarts.get(agentId);
16422
+ if (this.agentStarts.hasStarting(agentId) || this.agentStarts.hasQueued(agentId)) {
16423
+ const queuedStart = this.agentStarts.getQueued(agentId);
14069
16424
  this.queueRuntimeProfileNotificationDuringStart(agentId, message, kind, key);
14070
16425
  span.end("ok", {
14071
16426
  attrs: {
@@ -14572,7 +16927,8 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
14572
16927
  entries.push({ kind: "status", activity, detail });
14573
16928
  }
14574
16929
  const launchId = launchIdOverride || ap?.launchId || void 0;
14575
- const clientSeq = ap ? this.nextActivityClientSeq(agentId) : void 0;
16930
+ const clientSeq = this.nextActivityClientSeq(agentId);
16931
+ const producerFactId = this.buildActivityProducerFactId(agentId, launchId, clientSeq);
14576
16932
  this.sendToServer({
14577
16933
  type: "agent:activity",
14578
16934
  agentId,
@@ -14580,9 +16936,10 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
14580
16936
  detail,
14581
16937
  entries,
14582
16938
  launchId,
14583
- clientSeq
16939
+ clientSeq,
16940
+ producerFactId
14584
16941
  });
14585
- this.recordActivityProducedTrace(agentId, activity, detail, entries, ap, launchId, clientSeq);
16942
+ this.recordActivityProducedTrace(agentId, activity, detail, entries, ap, launchId, clientSeq, producerFactId);
14586
16943
  if (ap) {
14587
16944
  ap.lastActivity = activity;
14588
16945
  ap.lastActivityDetail = detail;
@@ -14595,15 +16952,17 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
14595
16952
  });
14596
16953
  const heartbeatLaunchId = launchIdOverride || ap.launchId || void 0;
14597
16954
  const heartbeatClientSeq = this.nextActivityClientSeq(agentId);
16955
+ const heartbeatProducerFactId = this.buildActivityProducerFactId(agentId, heartbeatLaunchId, heartbeatClientSeq);
14598
16956
  this.sendToServer({
14599
16957
  type: "agent:activity",
14600
16958
  agentId,
14601
16959
  activity: ap.lastActivity,
14602
16960
  detail: ap.lastActivityDetail,
14603
16961
  launchId: heartbeatLaunchId,
14604
- clientSeq: heartbeatClientSeq
16962
+ clientSeq: heartbeatClientSeq,
16963
+ producerFactId: heartbeatProducerFactId
14605
16964
  });
14606
- this.recordActivityProducedTrace(agentId, ap.lastActivity, ap.lastActivityDetail, [], ap, heartbeatLaunchId, heartbeatClientSeq);
16965
+ this.recordActivityProducedTrace(agentId, ap.lastActivity, ap.lastActivityDetail, [], ap, heartbeatLaunchId, heartbeatClientSeq, heartbeatProducerFactId);
14607
16966
  }, ACTIVITY_HEARTBEAT_MS);
14608
16967
  }
14609
16968
  } else {
@@ -14614,7 +16973,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
14614
16973
  }
14615
16974
  }
14616
16975
  }
14617
- recordActivityProducedTrace(agentId, activity, detail, entries, ap, launchId, clientSeq) {
16976
+ recordActivityProducedTrace(agentId, activity, detail, entries, ap, launchId, clientSeq, producerFactId) {
14618
16977
  const runtimeContext = ap?.config.runtimeContext;
14619
16978
  this.recordDaemonTrace("daemon.agent.activity.produced", {
14620
16979
  agentId,
@@ -14632,11 +16991,16 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
14632
16991
  clientSeq,
14633
16992
  client_seq: clientSeq,
14634
16993
  client_seq_present: typeof clientSeq === "number",
16994
+ producerFactId,
16995
+ producer_fact_id: producerFactId,
14635
16996
  correlation_id: `agent:${agentId}:daemonActivity:${launchId ?? "legacy"}:${clientSeq ?? "unsequenced"}`,
14636
16997
  session_id_present: Boolean(ap?.sessionId),
14637
16998
  runtime: ap?.config.runtime
14638
16999
  });
14639
17000
  }
17001
+ buildActivityProducerFactId(agentId, launchId, clientSeq) {
17002
+ return `daemon_activity:${agentId}:${launchId ?? "legacy"}:${clientSeq}`;
17003
+ }
14640
17004
  /**
14641
17005
  * Respond to a server-issued `agent:activity_probe`. Echoes the
14642
17006
  * agent's current `lastActivity` back through the existing
@@ -14663,7 +17027,8 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
14663
17027
  const activity = ap?.lastActivity || "offline";
14664
17028
  const detail = ap?.lastActivityDetail || (ap ? "" : "Agent not running");
14665
17029
  const launchId = ap?.launchId || void 0;
14666
- const clientSeq = ap ? this.nextActivityClientSeq(agentId) : void 0;
17030
+ const clientSeq = this.nextActivityClientSeq(agentId);
17031
+ const producerFactId = this.buildActivityProducerFactId(agentId, launchId, clientSeq);
14667
17032
  this.sendToServer({
14668
17033
  type: "agent:activity",
14669
17034
  agentId,
@@ -14671,9 +17036,10 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
14671
17036
  detail,
14672
17037
  launchId,
14673
17038
  probeId,
14674
- clientSeq
17039
+ clientSeq,
17040
+ producerFactId
14675
17041
  });
14676
- this.recordActivityProducedTrace(agentId, activity, detail, [], ap, launchId, clientSeq);
17042
+ this.recordActivityProducedTrace(agentId, activity, detail, [], ap, launchId, clientSeq, producerFactId);
14677
17043
  }
14678
17044
  flushPendingTrajectory(agentId) {
14679
17045
  const ap = this.agents.get(agentId);
@@ -16383,6 +18749,7 @@ var DaemonConnection = class {
16383
18749
  this.pendingActivityByAgent.delete(msg.agentId);
16384
18750
  }
16385
18751
  this.ws.send(JSON.stringify(msg));
18752
+ this.traceActivitySent(msg, "websocket_open");
16386
18753
  return;
16387
18754
  }
16388
18755
  this.observeLaunchIdentity(msg);
@@ -16580,12 +18947,35 @@ var DaemonConnection = class {
16580
18947
  this.pendingActivityByAgent.clear();
16581
18948
  for (const msg of pending) {
16582
18949
  ws.send(JSON.stringify(msg));
18950
+ this.traceActivitySent(msg, "replay");
16583
18951
  }
16584
18952
  this.trace("daemon.connection.outbound_replayed", {
16585
18953
  outbound_message_kind: "agent:activity",
16586
18954
  message_count: pending.length
16587
18955
  });
16588
18956
  }
18957
+ traceActivitySent(msg, sendPath) {
18958
+ if (msg.type !== "agent:activity") return;
18959
+ this.trace("daemon.agent.activity.sent", {
18960
+ agentId: msg.agentId,
18961
+ agent_id: msg.agentId,
18962
+ activity: msg.activity,
18963
+ detail_present: Boolean(msg.detail),
18964
+ entry_kinds: (msg.entries ?? []).map((entry) => entry.kind).join(","),
18965
+ launchId: msg.launchId,
18966
+ launch_id: msg.launchId,
18967
+ launch_id_present: Boolean(msg.launchId),
18968
+ clientSeq: msg.clientSeq,
18969
+ client_seq: msg.clientSeq,
18970
+ client_seq_present: typeof msg.clientSeq === "number",
18971
+ producerFactId: msg.producerFactId,
18972
+ producer_fact_id: msg.producerFactId,
18973
+ producer_fact_id_present: Boolean(msg.producerFactId),
18974
+ correlation_id: msg.producerFactId ?? `agent:${msg.agentId}:daemonActivity:${msg.launchId ?? "legacy"}:${msg.clientSeq ?? "unsequenced"}`,
18975
+ probe_id_present: Boolean(msg.probeId),
18976
+ send_path: sendPath
18977
+ });
18978
+ }
16589
18979
  lastInboundAgeBucket() {
16590
18980
  return durationMsBucket(this.lastInboundAt == null ? null : this.clock.now() - this.lastInboundAt);
16591
18981
  }
@@ -17327,6 +19717,16 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
17327
19717
  },
17328
19718
  endAttrs: ["outcome", "available_models_count", "diagnostics_count", "diagnostic_info_count", "diagnostic_warning_count", "requested_model", "resolved_model", "resolved_model_present", "error_class"]
17329
19719
  },
19720
+ "daemon.builtin.session.create": {
19721
+ spanAttrs: ["agentId", "launchId", "runtime", "model", "session_id_present", "requested_model", "config_source", "host_user_state", "provider_id", "model_kind", "model_id", "base_url_present", "base_url_host_class", "provider_key_present", "provider_key_source"],
19722
+ eventAttrs: {
19723
+ "daemon.builtin.session.services_ready": ["available_models_count", "diagnostics_count", "diagnostic_info_count", "diagnostic_warning_count", "agent_dir_source", "config_source", "host_user_state", "provider_id", "model_kind", "model_id", "base_url_present", "base_url_host_class", "provider_key_present", "provider_key_source"],
19724
+ "daemon.builtin.session.model_resolved": ["available_models_count", "requested_model", "requested_model_explicit", "resolved_model", "resolved_model_present", "config_source", "host_user_state", "provider_id", "model_kind", "model_id", "base_url_present", "base_url_host_class", "provider_key_present", "provider_key_source"],
19725
+ "daemon.builtin.session.missing_model": ["available_models_count", "requested_model", "config_source", "host_user_state", "provider_id", "model_kind", "model_id", "base_url_present", "base_url_host_class", "provider_key_present", "provider_key_source"],
19726
+ "daemon.builtin.session.started": ["requested_model", "resolved_model", "session_id_present", "config_source", "host_user_state", "provider_id", "model_kind", "model_id", "base_url_present", "base_url_host_class", "provider_key_present", "provider_key_source"]
19727
+ },
19728
+ endAttrs: ["outcome", "available_models_count", "diagnostics_count", "diagnostic_info_count", "diagnostic_warning_count", "requested_model", "resolved_model", "resolved_model_present", "error_class", "config_source", "host_user_state", "provider_id", "model_kind", "model_id", "base_url_present", "base_url_host_class", "provider_key_present", "provider_key_source"]
19729
+ },
17330
19730
  "daemon.connection.local_disconnect_observed": {
17331
19731
  spanAttrs: ["running_agents_count", "idle_agents_count"]
17332
19732
  },
@@ -17340,7 +19740,7 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
17340
19740
  spanAttrs: ["agentId", "event_kind", "runtime"]
17341
19741
  }
17342
19742
  };
17343
- var DAEMON_CLI_USAGE = "Usage: slock-daemon --server-url <url> --api-key <key>";
19743
+ var DAEMON_CLI_USAGE = `Usage: slock-daemon --server-url <url> (--api-key <key> or ${DAEMON_API_KEY_ENV}=<key>)`;
17344
19744
  var RunnerCredentialMintError2 = class extends Error {
17345
19745
  code;
17346
19746
  retryable;
@@ -17376,9 +19776,9 @@ function runnerCredentialErrorDetail2(error) {
17376
19776
  async function waitForRunnerCredentialRetry2() {
17377
19777
  await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
17378
19778
  }
17379
- function parseDaemonCliArgs(args) {
19779
+ function parseDaemonCliArgs(args, env = {}) {
17380
19780
  let serverUrl = "";
17381
- let apiKey = "";
19781
+ let apiKey = env[DAEMON_API_KEY_ENV] ?? "";
17382
19782
  for (let i = 0; i < args.length; i++) {
17383
19783
  if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
17384
19784
  if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
@@ -17415,7 +19815,7 @@ function resolveSlockCliPathOrEmpty(moduleUrl = import.meta.url) {
17415
19815
  }
17416
19816
  async function runBundledSlockCli(argv) {
17417
19817
  process.argv = [process.execPath, "slock", ...argv];
17418
- await import("./dist-7ZEXJWIW.js");
19818
+ await import("./dist-NONOBGMT.js");
17419
19819
  }
17420
19820
  function detectRuntimes(tracer = noopTracer) {
17421
19821
  const ids = [];
@@ -18352,9 +20752,12 @@ var DaemonCore = class {
18352
20752
 
18353
20753
  export {
18354
20754
  subscribeDaemonLogs,
20755
+ DAEMON_API_KEY_ENV,
20756
+ scrubDaemonAuthEnv,
18355
20757
  resolveWorkspaceDirectoryPath,
18356
20758
  scanWorkspaceDirectories,
18357
20759
  deleteWorkspaceDirectory,
20760
+ DAEMON_CORE_TRACE_ATTR_CONTRACTS,
18358
20761
  DAEMON_CLI_USAGE,
18359
20762
  parseDaemonCliArgs,
18360
20763
  readDaemonVersion,