longer-agent 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +227 -0
  3. package/README.zh-CN.md +227 -0
  4. package/agent_templates/executor/agent.yaml +22 -0
  5. package/agent_templates/executor/system_prompt.md +17 -0
  6. package/agent_templates/explorer/agent.yaml +13 -0
  7. package/agent_templates/explorer/system_prompt.md +19 -0
  8. package/agent_templates/main/agent.yaml +7 -0
  9. package/agent_templates/main/system_prompt.md +45 -0
  10. package/configExample.yaml +83 -0
  11. package/dist/agents/agent.d.ts +79 -0
  12. package/dist/agents/agent.d.ts.map +1 -0
  13. package/dist/agents/agent.js +156 -0
  14. package/dist/agents/agent.js.map +1 -0
  15. package/dist/agents/tool-loop.d.ts +140 -0
  16. package/dist/agents/tool-loop.d.ts.map +1 -0
  17. package/dist/agents/tool-loop.js +465 -0
  18. package/dist/agents/tool-loop.js.map +1 -0
  19. package/dist/ask.d.ts +81 -0
  20. package/dist/ask.d.ts.map +1 -0
  21. package/dist/ask.js +34 -0
  22. package/dist/ask.js.map +1 -0
  23. package/dist/auth/openai-oauth.d.ts +66 -0
  24. package/dist/auth/openai-oauth.d.ts.map +1 -0
  25. package/dist/auth/openai-oauth.js +640 -0
  26. package/dist/auth/openai-oauth.js.map +1 -0
  27. package/dist/cli.d.ts +14 -0
  28. package/dist/cli.d.ts.map +1 -0
  29. package/dist/cli.js +254 -0
  30. package/dist/cli.js.map +1 -0
  31. package/dist/commands.d.ts +118 -0
  32. package/dist/commands.d.ts.map +1 -0
  33. package/dist/commands.js +862 -0
  34. package/dist/commands.js.map +1 -0
  35. package/dist/config.d.ts +130 -0
  36. package/dist/config.d.ts.map +1 -0
  37. package/dist/config.js +648 -0
  38. package/dist/config.js.map +1 -0
  39. package/dist/context-rendering.d.ts +69 -0
  40. package/dist/context-rendering.d.ts.map +1 -0
  41. package/dist/context-rendering.js +250 -0
  42. package/dist/context-rendering.js.map +1 -0
  43. package/dist/document-projection.d.ts +12 -0
  44. package/dist/document-projection.d.ts.map +1 -0
  45. package/dist/document-projection.js +75 -0
  46. package/dist/document-projection.js.map +1 -0
  47. package/dist/ephemeral-log.d.ts +15 -0
  48. package/dist/ephemeral-log.d.ts.map +1 -0
  49. package/dist/ephemeral-log.js +173 -0
  50. package/dist/ephemeral-log.js.map +1 -0
  51. package/dist/file-attach.d.ts +89 -0
  52. package/dist/file-attach.d.ts.map +1 -0
  53. package/dist/file-attach.js +571 -0
  54. package/dist/file-attach.js.map +1 -0
  55. package/dist/index.d.ts +29 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +43 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/init-wizard.d.ts +13 -0
  60. package/dist/init-wizard.d.ts.map +1 -0
  61. package/dist/init-wizard.js +328 -0
  62. package/dist/init-wizard.js.map +1 -0
  63. package/dist/log-entry.d.ts +104 -0
  64. package/dist/log-entry.d.ts.map +1 -0
  65. package/dist/log-entry.js +292 -0
  66. package/dist/log-entry.js.map +1 -0
  67. package/dist/log-projection.d.ts +73 -0
  68. package/dist/log-projection.d.ts.map +1 -0
  69. package/dist/log-projection.js +651 -0
  70. package/dist/log-projection.js.map +1 -0
  71. package/dist/mcp-client.d.ts +55 -0
  72. package/dist/mcp-client.d.ts.map +1 -0
  73. package/dist/mcp-client.js +402 -0
  74. package/dist/mcp-client.js.map +1 -0
  75. package/dist/model-selection.d.ts +16 -0
  76. package/dist/model-selection.d.ts.map +1 -0
  77. package/dist/model-selection.js +181 -0
  78. package/dist/model-selection.js.map +1 -0
  79. package/dist/network-retry.d.ts +38 -0
  80. package/dist/network-retry.d.ts.map +1 -0
  81. package/dist/network-retry.js +140 -0
  82. package/dist/network-retry.js.map +1 -0
  83. package/dist/persistence.d.ts +104 -0
  84. package/dist/persistence.d.ts.map +1 -0
  85. package/dist/persistence.js +644 -0
  86. package/dist/persistence.js.map +1 -0
  87. package/dist/primitives/context.d.ts +29 -0
  88. package/dist/primitives/context.d.ts.map +1 -0
  89. package/dist/primitives/context.js +85 -0
  90. package/dist/primitives/context.js.map +1 -0
  91. package/dist/progress.d.ts +51 -0
  92. package/dist/progress.d.ts.map +1 -0
  93. package/dist/progress.js +229 -0
  94. package/dist/progress.js.map +1 -0
  95. package/dist/provider-presets.d.ts +34 -0
  96. package/dist/provider-presets.d.ts.map +1 -0
  97. package/dist/provider-presets.js +181 -0
  98. package/dist/provider-presets.js.map +1 -0
  99. package/dist/providers/anthropic.d.ts +32 -0
  100. package/dist/providers/anthropic.d.ts.map +1 -0
  101. package/dist/providers/anthropic.js +450 -0
  102. package/dist/providers/anthropic.js.map +1 -0
  103. package/dist/providers/base.d.ts +135 -0
  104. package/dist/providers/base.d.ts.map +1 -0
  105. package/dist/providers/base.js +104 -0
  106. package/dist/providers/base.js.map +1 -0
  107. package/dist/providers/glm.d.ts +18 -0
  108. package/dist/providers/glm.d.ts.map +1 -0
  109. package/dist/providers/glm.js +59 -0
  110. package/dist/providers/glm.js.map +1 -0
  111. package/dist/providers/kimi.d.ts +23 -0
  112. package/dist/providers/kimi.d.ts.map +1 -0
  113. package/dist/providers/kimi.js +89 -0
  114. package/dist/providers/kimi.js.map +1 -0
  115. package/dist/providers/minimax.d.ts +20 -0
  116. package/dist/providers/minimax.d.ts.map +1 -0
  117. package/dist/providers/minimax.js +192 -0
  118. package/dist/providers/minimax.js.map +1 -0
  119. package/dist/providers/openai-chat.d.ts +33 -0
  120. package/dist/providers/openai-chat.d.ts.map +1 -0
  121. package/dist/providers/openai-chat.js +543 -0
  122. package/dist/providers/openai-chat.js.map +1 -0
  123. package/dist/providers/openai-responses.d.ts +26 -0
  124. package/dist/providers/openai-responses.d.ts.map +1 -0
  125. package/dist/providers/openai-responses.js +443 -0
  126. package/dist/providers/openai-responses.js.map +1 -0
  127. package/dist/providers/openrouter.d.ts +24 -0
  128. package/dist/providers/openrouter.d.ts.map +1 -0
  129. package/dist/providers/openrouter.js +177 -0
  130. package/dist/providers/openrouter.js.map +1 -0
  131. package/dist/providers/registry.d.ts +7 -0
  132. package/dist/providers/registry.d.ts.map +1 -0
  133. package/dist/providers/registry.js +38 -0
  134. package/dist/providers/registry.js.map +1 -0
  135. package/dist/security/path.d.ts +51 -0
  136. package/dist/security/path.d.ts.map +1 -0
  137. package/dist/security/path.js +187 -0
  138. package/dist/security/path.js.map +1 -0
  139. package/dist/security/sensitive-files.d.ts +3 -0
  140. package/dist/security/sensitive-files.d.ts.map +1 -0
  141. package/dist/security/sensitive-files.js +41 -0
  142. package/dist/security/sensitive-files.js.map +1 -0
  143. package/dist/session.d.ts +446 -0
  144. package/dist/session.d.ts.map +1 -0
  145. package/dist/session.js +4595 -0
  146. package/dist/session.js.map +1 -0
  147. package/dist/settings.d.ts +46 -0
  148. package/dist/settings.d.ts.map +1 -0
  149. package/dist/settings.js +134 -0
  150. package/dist/settings.js.map +1 -0
  151. package/dist/show-context.d.ts +35 -0
  152. package/dist/show-context.d.ts.map +1 -0
  153. package/dist/show-context.js +320 -0
  154. package/dist/show-context.js.map +1 -0
  155. package/dist/skills/loader.d.ts +49 -0
  156. package/dist/skills/loader.d.ts.map +1 -0
  157. package/dist/skills/loader.js +166 -0
  158. package/dist/skills/loader.js.map +1 -0
  159. package/dist/summarize-context.d.ts +29 -0
  160. package/dist/summarize-context.d.ts.map +1 -0
  161. package/dist/summarize-context.js +247 -0
  162. package/dist/summarize-context.js.map +1 -0
  163. package/dist/templates/loader.d.ts +104 -0
  164. package/dist/templates/loader.d.ts.map +1 -0
  165. package/dist/templates/loader.js +514 -0
  166. package/dist/templates/loader.js.map +1 -0
  167. package/dist/tools/basic.d.ts +29 -0
  168. package/dist/tools/basic.d.ts.map +1 -0
  169. package/dist/tools/basic.js +2079 -0
  170. package/dist/tools/basic.js.map +1 -0
  171. package/dist/tools/comm.d.ts +17 -0
  172. package/dist/tools/comm.d.ts.map +1 -0
  173. package/dist/tools/comm.js +192 -0
  174. package/dist/tools/comm.js.map +1 -0
  175. package/dist/tools/web-fetch.d.ts +11 -0
  176. package/dist/tools/web-fetch.d.ts.map +1 -0
  177. package/dist/tools/web-fetch.js +237 -0
  178. package/dist/tools/web-fetch.js.map +1 -0
  179. package/dist/tools/web-search.d.ts +24 -0
  180. package/dist/tools/web-search.d.ts.map +1 -0
  181. package/dist/tools/web-search.js +51 -0
  182. package/dist/tools/web-search.js.map +1 -0
  183. package/dist/tui/app.d.ts +35 -0
  184. package/dist/tui/app.d.ts.map +1 -0
  185. package/dist/tui/app.js +1042 -0
  186. package/dist/tui/app.js.map +1 -0
  187. package/dist/tui/checkbox-picker.d.ts +35 -0
  188. package/dist/tui/checkbox-picker.d.ts.map +1 -0
  189. package/dist/tui/checkbox-picker.js +85 -0
  190. package/dist/tui/checkbox-picker.js.map +1 -0
  191. package/dist/tui/command-picker.d.ts +31 -0
  192. package/dist/tui/command-picker.d.ts.map +1 -0
  193. package/dist/tui/command-picker.js +113 -0
  194. package/dist/tui/command-picker.js.map +1 -0
  195. package/dist/tui/components/ask-panel.d.ts +21 -0
  196. package/dist/tui/components/ask-panel.d.ts.map +1 -0
  197. package/dist/tui/components/ask-panel.js +81 -0
  198. package/dist/tui/components/ask-panel.js.map +1 -0
  199. package/dist/tui/components/conversation-panel.d.ts +68 -0
  200. package/dist/tui/components/conversation-panel.d.ts.map +1 -0
  201. package/dist/tui/components/conversation-panel.js +611 -0
  202. package/dist/tui/components/conversation-panel.js.map +1 -0
  203. package/dist/tui/components/input-panel.d.ts +27 -0
  204. package/dist/tui/components/input-panel.d.ts.map +1 -0
  205. package/dist/tui/components/input-panel.js +725 -0
  206. package/dist/tui/components/input-panel.js.map +1 -0
  207. package/dist/tui/components/logo-panel.d.ts +14 -0
  208. package/dist/tui/components/logo-panel.d.ts.map +1 -0
  209. package/dist/tui/components/logo-panel.js +37 -0
  210. package/dist/tui/components/logo-panel.js.map +1 -0
  211. package/dist/tui/components/plan-panel.d.ts +10 -0
  212. package/dist/tui/components/plan-panel.d.ts.map +1 -0
  213. package/dist/tui/components/plan-panel.js +8 -0
  214. package/dist/tui/components/plan-panel.js.map +1 -0
  215. package/dist/tui/components/status-bar.d.ts +24 -0
  216. package/dist/tui/components/status-bar.d.ts.map +1 -0
  217. package/dist/tui/components/status-bar.js +80 -0
  218. package/dist/tui/components/status-bar.js.map +1 -0
  219. package/dist/tui/input/editor-state.d.ts +22 -0
  220. package/dist/tui/input/editor-state.d.ts.map +1 -0
  221. package/dist/tui/input/editor-state.js +157 -0
  222. package/dist/tui/input/editor-state.js.map +1 -0
  223. package/dist/tui/input/keymap.d.ts +3 -0
  224. package/dist/tui/input/keymap.d.ts.map +1 -0
  225. package/dist/tui/input/keymap.js +72 -0
  226. package/dist/tui/input/keymap.js.map +1 -0
  227. package/dist/tui/input/paste-slots.d.ts +17 -0
  228. package/dist/tui/input/paste-slots.d.ts.map +1 -0
  229. package/dist/tui/input/paste-slots.js +46 -0
  230. package/dist/tui/input/paste-slots.js.map +1 -0
  231. package/dist/tui/input/paste.d.ts +15 -0
  232. package/dist/tui/input/paste.d.ts.map +1 -0
  233. package/dist/tui/input/paste.js +35 -0
  234. package/dist/tui/input/paste.js.map +1 -0
  235. package/dist/tui/input/protocol.d.ts +9 -0
  236. package/dist/tui/input/protocol.d.ts.map +1 -0
  237. package/dist/tui/input/protocol.js +387 -0
  238. package/dist/tui/input/protocol.js.map +1 -0
  239. package/dist/tui/input/sanitize.d.ts +6 -0
  240. package/dist/tui/input/sanitize.d.ts.map +1 -0
  241. package/dist/tui/input/sanitize.js +20 -0
  242. package/dist/tui/input/sanitize.js.map +1 -0
  243. package/dist/tui/input/types.d.ts +18 -0
  244. package/dist/tui/input/types.d.ts.map +1 -0
  245. package/dist/tui/input/types.js +2 -0
  246. package/dist/tui/input/types.js.map +1 -0
  247. package/dist/tui/launch.d.ts +23 -0
  248. package/dist/tui/launch.d.ts.map +1 -0
  249. package/dist/tui/launch.js +104 -0
  250. package/dist/tui/launch.js.map +1 -0
  251. package/dist/tui/theme.d.ts +20 -0
  252. package/dist/tui/theme.d.ts.map +1 -0
  253. package/dist/tui/theme.js +29 -0
  254. package/dist/tui/theme.js.map +1 -0
  255. package/dist/tui/types.d.ts +136 -0
  256. package/dist/tui/types.d.ts.map +1 -0
  257. package/dist/tui/types.js +9 -0
  258. package/dist/tui/types.js.map +1 -0
  259. package/package.json +76 -0
  260. package/prompts/sections/agents_md.md +23 -0
  261. package/prompts/sections/important_log.md +16 -0
  262. package/prompts/sections/system_mechanisms.md +18 -0
  263. package/prompts/tools/apply_patch.md +31 -0
  264. package/prompts/tools/ask.md +18 -0
  265. package/prompts/tools/bash.md +13 -0
  266. package/prompts/tools/bash_background.md +9 -0
  267. package/prompts/tools/bash_output.md +9 -0
  268. package/prompts/tools/check_status.md +3 -0
  269. package/prompts/tools/diff.md +5 -0
  270. package/prompts/tools/edit_file.md +11 -0
  271. package/prompts/tools/glob.md +7 -0
  272. package/prompts/tools/grep.md +20 -0
  273. package/prompts/tools/kill_agent.md +3 -0
  274. package/prompts/tools/kill_shell.md +5 -0
  275. package/prompts/tools/list_dir.md +5 -0
  276. package/prompts/tools/plan.md +252 -0
  277. package/prompts/tools/read_file.md +9 -0
  278. package/prompts/tools/show_context.md +12 -0
  279. package/prompts/tools/skill.md +7 -0
  280. package/prompts/tools/spawn_agent.md +195 -0
  281. package/prompts/tools/summarize_context.md +122 -0
  282. package/prompts/tools/test.md +5 -0
  283. package/prompts/tools/wait.md +17 -0
  284. package/prompts/tools/web_fetch.md +9 -0
  285. package/prompts/tools/web_search.md +5 -0
  286. package/prompts/tools/write_file.md +11 -0
  287. package/skills/.staging/.gitkeep +0 -0
  288. package/skills/explain-code/SKILL.md +15 -0
  289. package/skills/skill-manager/SKILL.md +83 -0
@@ -0,0 +1,177 @@
1
+ /**
2
+ * OpenRouter provider adapter.
3
+ *
4
+ * Extends OpenAIChatProvider with:
5
+ * - Automatic base_url defaulting and HTTP-Referer / X-Title headers
6
+ * - OpenRouter-style reasoning params (reasoning: { effort } in extra_body)
7
+ * - reasoning_details extraction from non-streaming responses
8
+ * - reasoning_details round-trip on assistant messages
9
+ */
10
+ import OpenAI from "openai";
11
+ import { OpenAIChatProvider } from "./openai-chat.js";
12
+ const OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
13
+ /** Map LongerAgent thinking levels to OpenRouter reasoning effort values. */
14
+ const EFFORT_MAP = {
15
+ minimal: "minimal",
16
+ low: "low",
17
+ medium: "medium",
18
+ high: "high",
19
+ xhigh: "xhigh",
20
+ max: "xhigh", // Anthropic "max" → OpenRouter's highest effort
21
+ on: "high", // binary on/off models → default to high
22
+ };
23
+ export class OpenRouterProvider extends OpenAIChatProvider {
24
+ constructor(config) {
25
+ const headerExtra = config.extra ?? {};
26
+ const sanitizedExtra = Object.fromEntries(Object.entries(headerExtra).filter(([k]) => k !== "http_referer" && k !== "x_title"));
27
+ super({
28
+ ...config,
29
+ extra: sanitizedExtra,
30
+ });
31
+ // Rebuild client with OpenRouter-specific settings
32
+ const baseUrl = config.baseUrl || OPENROUTER_BASE_URL;
33
+ const headers = {};
34
+ if (config.extra?.["http_referer"]) {
35
+ headers["HTTP-Referer"] = config.extra["http_referer"];
36
+ }
37
+ if (config.extra?.["x_title"]) {
38
+ headers["X-Title"] = config.extra["x_title"];
39
+ }
40
+ this._client = new OpenAI({
41
+ apiKey: config.apiKey,
42
+ baseURL: baseUrl,
43
+ defaultHeaders: Object.keys(headers).length > 0 ? headers : undefined,
44
+ });
45
+ }
46
+ // ------------------------------------------------------------------
47
+ // Thinking / reasoning params — OpenRouter unified format
48
+ // ------------------------------------------------------------------
49
+ _applyThinkingParams(kwargs, options) {
50
+ if (!this._config.supportsThinking)
51
+ return;
52
+ const level = options?.thinkingLevel;
53
+ // Explicitly disable reasoning
54
+ if (level === "off" || level === "none") {
55
+ const extraBody = kwargs["extra_body"] || {};
56
+ extraBody["reasoning"] = { effort: "none" };
57
+ kwargs["extra_body"] = extraBody;
58
+ return;
59
+ }
60
+ // Build reasoning config
61
+ const reasoningConfig = {};
62
+ if (this._config.thinkingBudget > 0) {
63
+ // Use max_tokens for reasoning when thinkingBudget is explicitly set
64
+ reasoningConfig["max_tokens"] = this._config.thinkingBudget;
65
+ }
66
+ else {
67
+ // Map thinking level to effort
68
+ const effort = (level && level !== "default")
69
+ ? (EFFORT_MAP[level] ?? "high")
70
+ : "high";
71
+ reasoningConfig["effort"] = effort;
72
+ }
73
+ const extraBody = kwargs["extra_body"] || {};
74
+ extraBody["reasoning"] = reasoningConfig;
75
+ kwargs["extra_body"] = extraBody;
76
+ // Do NOT delete temperature or swap max_tokens → max_completion_tokens.
77
+ // OpenRouter normalizes these per-model internally.
78
+ }
79
+ _augmentRequestKwargs(kwargs, ctx) {
80
+ if (!ctx.hasNativeWebSearch)
81
+ return;
82
+ const existing = Array.isArray(kwargs["plugins"])
83
+ ? [...kwargs["plugins"]]
84
+ : [];
85
+ const hasWebPlugin = existing.some((plugin) => plugin && typeof plugin === "object" && plugin["id"] === "web");
86
+ if (!hasWebPlugin) {
87
+ existing.push({ id: "web" });
88
+ }
89
+ kwargs["plugins"] = existing;
90
+ }
91
+ // ------------------------------------------------------------------
92
+ // Response post-processing — extract reasoning_details
93
+ // ------------------------------------------------------------------
94
+ async sendMessage(messages, tools, options) {
95
+ const result = await super.sendMessage(messages, tools, options);
96
+ // Non-streaming: the base class _parseResponse (private) only extracts
97
+ // reasoning_content (string). OpenRouter also returns reasoning_details
98
+ // (structured array) which we want for faithful round-tripping.
99
+ // Streaming already handles reasoning_details via _callStream.
100
+ if (result.raw && (!result.reasoningContent || result.reasoningState === result.reasoningContent)) {
101
+ try {
102
+ const raw = result.raw;
103
+ const choices = raw["choices"] || [];
104
+ if (choices.length > 0) {
105
+ const message = choices[0]["message"];
106
+ if (message) {
107
+ const details = message["reasoning_details"];
108
+ if (Array.isArray(details) && details.length > 0) {
109
+ const texts = [];
110
+ for (const item of details) {
111
+ if (typeof item === "string") {
112
+ texts.push(item);
113
+ continue;
114
+ }
115
+ if (item && typeof item === "object") {
116
+ const obj = item;
117
+ const text = obj["content"]
118
+ || obj["text"]
119
+ || "";
120
+ if (text)
121
+ texts.push(text);
122
+ // Extract from summary arrays
123
+ if (Array.isArray(obj["summary"])) {
124
+ for (const s of obj["summary"]) {
125
+ const st = s["text"] || "";
126
+ if (st)
127
+ texts.push(st);
128
+ }
129
+ }
130
+ }
131
+ }
132
+ if (texts.length > 0) {
133
+ result.reasoningContent = texts.join("\n");
134
+ result.reasoningState = details; // Preserve structured data for round-trip
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+ catch {
141
+ // Ignore extraction errors — reasoning_content from base class is still usable
142
+ }
143
+ }
144
+ return result;
145
+ }
146
+ // ------------------------------------------------------------------
147
+ // Message conversion — reasoning_details round-trip
148
+ // ------------------------------------------------------------------
149
+ _convertMessages(messages) {
150
+ const converted = super._convertMessages(messages);
151
+ // Enrich assistant messages with reasoning_details from _reasoning_state
152
+ // for faithful round-tripping through OpenRouter.
153
+ // Use simple ordinal mapping: base class preserves assistant message order.
154
+ const originals = messages;
155
+ const origAssistantIndices = [];
156
+ const convAssistantIndices = [];
157
+ for (let i = 0; i < originals.length; i++) {
158
+ if (originals[i]["role"] === "assistant")
159
+ origAssistantIndices.push(i);
160
+ }
161
+ for (let i = 0; i < converted.length; i++) {
162
+ if (converted[i]["role"] === "assistant")
163
+ convAssistantIndices.push(i);
164
+ }
165
+ const count = Math.min(origAssistantIndices.length, convAssistantIndices.length);
166
+ for (let i = 0; i < count; i++) {
167
+ const orig = originals[origAssistantIndices[i]];
168
+ const conv = converted[convAssistantIndices[i]];
169
+ const state = orig["_reasoning_state"];
170
+ if (state && Array.isArray(state)) {
171
+ conv["reasoning_details"] = state;
172
+ }
173
+ }
174
+ return converted;
175
+ }
176
+ }
177
+ //# sourceMappingURL=openrouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../src/providers/openrouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Provider factory — maps provider identifiers to concrete provider classes.
3
+ */
4
+ import type { ModelConfig } from "../config.js";
5
+ import type { BaseProvider } from "./base.js";
6
+ export declare function createProvider(config: ModelConfig): BaseProvider;
7
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAS9C,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAoChE"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Provider factory — maps provider identifiers to concrete provider classes.
3
+ */
4
+ import { AnthropicProvider } from "./anthropic.js";
5
+ import { OpenAIResponsesProvider } from "./openai-responses.js";
6
+ import { OpenAIChatProvider } from "./openai-chat.js";
7
+ import { KimiProvider } from "./kimi.js";
8
+ import { GLMProvider } from "./glm.js";
9
+ import { MiniMaxProvider } from "./minimax.js";
10
+ import { OpenRouterProvider } from "./openrouter.js";
11
+ export function createProvider(config) {
12
+ const provider = config.provider.toLowerCase();
13
+ if (provider === "anthropic") {
14
+ return new AnthropicProvider(config);
15
+ }
16
+ if (provider === "openai" || provider === "openai-codex") {
17
+ return new OpenAIResponsesProvider(config);
18
+ }
19
+ if (provider === "openai-chat") {
20
+ return new OpenAIChatProvider(config);
21
+ }
22
+ if (provider === "kimi-cn" || provider === "kimi-ai" || provider === "kimi" || provider === "kimi-code") {
23
+ return new KimiProvider(config);
24
+ }
25
+ if (provider === "glm" || provider === "glm-intl" || provider === "glm-code" || provider === "glm-intl-code") {
26
+ return new GLMProvider(config);
27
+ }
28
+ if (provider === "minimax" || provider === "minimax-cn") {
29
+ return new MiniMaxProvider(config);
30
+ }
31
+ if (provider === "openrouter") {
32
+ return new OpenRouterProvider(config);
33
+ }
34
+ throw new Error(`Unknown provider '${config.provider}'. ` +
35
+ "Supported: anthropic, openai, openai-codex, openai-chat, kimi, kimi-cn, kimi-ai, kimi-code, " +
36
+ "glm, glm-intl, glm-code, glm-intl-code, minimax, minimax-cn, openrouter");
37
+ }
38
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,UAAU,cAAc,CAAC,MAAmB;IAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAE/C,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC7B,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;QACzD,OAAO,IAAI,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC/B,OAAO,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;QACxG,OAAO,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,UAAU,IAAI,QAAQ,KAAK,UAAU,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;QAC7G,OAAO,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAED,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;QACxD,OAAO,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC9B,OAAO,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,IAAI,KAAK,CACb,qBAAqB,MAAM,CAAC,QAAQ,KAAK;QACvC,8FAA8F;QAC9F,yEAAyE,CAC5E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Unified path safety checks for file-accessing features.
3
+ *
4
+ * Phase 1 scope:
5
+ * - Enforce a directory boundary (project root / session artifacts)
6
+ * - Prevent lexical traversal (`..`) and prefix-collision mistakes
7
+ * - Reject symlink escapes via canonical (realpath) checks
8
+ * - Support create paths by validating the nearest existing ancestor
9
+ */
10
+ export type PathAccessKind = "read" | "write" | "list" | "search" | "attach" | "template" | "spawn_call_file" | "diff";
11
+ export type PathDecision = "allow" | "deny_external" | "deny_symlink";
12
+ export interface SafePathOptions {
13
+ baseDir: string;
14
+ requestedPath: string;
15
+ cwd?: string;
16
+ mustExist?: boolean;
17
+ allowCreate?: boolean;
18
+ expectDirectory?: boolean;
19
+ expectFile?: boolean;
20
+ accessKind: PathAccessKind;
21
+ followSymlinks?: boolean;
22
+ }
23
+ export interface SafePathResult {
24
+ requestedPath: string;
25
+ resolvedPath: string;
26
+ canonicalPath?: string;
27
+ baseDirResolved: string;
28
+ baseDirCanonical?: string;
29
+ decision: PathDecision;
30
+ safePath?: string;
31
+ reason?: string;
32
+ isOutsideByLexical?: boolean;
33
+ isOutsideByCanonical?: boolean;
34
+ crossedSymlinkBoundary?: boolean;
35
+ }
36
+ type SafePathErrorCode = "PATH_OUTSIDE_SCOPE" | "PATH_SYMLINK_ESCAPES_SCOPE" | "PATH_NOT_FOUND" | "PATH_NOT_FILE" | "PATH_NOT_DIRECTORY" | "PATH_INVALID_INPUT";
37
+ export declare class SafePathError extends Error {
38
+ code: SafePathErrorCode;
39
+ details: SafePathResult;
40
+ constructor(code: SafePathErrorCode, message: string, details: SafePathResult);
41
+ }
42
+ /**
43
+ * Resolve and validate a path against a single allowed base directory.
44
+ *
45
+ * Phase 1 behavior:
46
+ * - Paths outside the base are denied
47
+ * - Symlink escapes are denied (future phases may map this to an `ask`)
48
+ */
49
+ export declare function safePath(opts: SafePathOptions): SafePathResult;
50
+ export {};
51
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/security/path.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,OAAO,GACP,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,iBAAiB,GACjB,MAAM,CAAC;AAEX,MAAM,MAAM,YAAY,GACpB,OAAO,GACP,eAAe,GACf,cAAc,CAAC;AAEnB,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,cAAc,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,KAAK,iBAAiB,GAClB,oBAAoB,GACpB,4BAA4B,GAC5B,gBAAgB,GAChB,eAAe,GACf,oBAAoB,GACpB,oBAAoB,CAAC;AAEzB,qBAAa,aAAc,SAAQ,KAAK;IACtC,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,cAAc,CAAC;gBAGtB,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,cAAc;CAO1B;AAwCD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,cAAc,CAkI9D"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Unified path safety checks for file-accessing features.
3
+ *
4
+ * Phase 1 scope:
5
+ * - Enforce a directory boundary (project root / session artifacts)
6
+ * - Prevent lexical traversal (`..`) and prefix-collision mistakes
7
+ * - Reject symlink escapes via canonical (realpath) checks
8
+ * - Support create paths by validating the nearest existing ancestor
9
+ */
10
+ import { existsSync, realpathSync, statSync } from "node:fs";
11
+ import path from "node:path";
12
+ export class SafePathError extends Error {
13
+ code;
14
+ details;
15
+ constructor(code, message, details) {
16
+ super(message);
17
+ this.name = "SafePathError";
18
+ this.code = code;
19
+ this.details = details;
20
+ }
21
+ }
22
+ function isWithinBase(baseAbs, candidateAbs) {
23
+ const rel = path.relative(baseAbs, candidateAbs);
24
+ if (rel === "")
25
+ return true;
26
+ if (path.isAbsolute(rel))
27
+ return false; // Windows cross-drive safety
28
+ return !rel.startsWith("..");
29
+ }
30
+ function nearestExistingAncestor(targetAbs) {
31
+ let current = targetAbs;
32
+ while (true) {
33
+ if (existsSync(current))
34
+ return current;
35
+ const parent = path.dirname(current);
36
+ if (parent === current)
37
+ return null;
38
+ current = parent;
39
+ }
40
+ }
41
+ function makeBaseResult(opts, baseDirResolved, resolvedPath) {
42
+ return {
43
+ requestedPath: opts.requestedPath,
44
+ resolvedPath,
45
+ baseDirResolved,
46
+ decision: "deny_external",
47
+ };
48
+ }
49
+ function fail(code, message, result) {
50
+ throw new SafePathError(code, message, result);
51
+ }
52
+ /**
53
+ * Resolve and validate a path against a single allowed base directory.
54
+ *
55
+ * Phase 1 behavior:
56
+ * - Paths outside the base are denied
57
+ * - Symlink escapes are denied (future phases may map this to an `ask`)
58
+ */
59
+ export function safePath(opts) {
60
+ const requested = String(opts.requestedPath ?? "");
61
+ const baseRaw = String(opts.baseDir ?? "");
62
+ if (!requested.trim()) {
63
+ const result = {
64
+ requestedPath: requested,
65
+ resolvedPath: "",
66
+ baseDirResolved: path.resolve(baseRaw || "."),
67
+ decision: "deny_external",
68
+ reason: "Empty path.",
69
+ };
70
+ fail("PATH_INVALID_INPUT", "Path cannot be empty.", result);
71
+ }
72
+ if (!baseRaw.trim()) {
73
+ const result = {
74
+ requestedPath: requested,
75
+ resolvedPath: path.resolve(requested),
76
+ baseDirResolved: path.resolve("."),
77
+ decision: "deny_external",
78
+ reason: "Invalid base directory.",
79
+ };
80
+ fail("PATH_INVALID_INPUT", "Base directory cannot be empty.", result);
81
+ }
82
+ const baseDirResolved = path.resolve(baseRaw);
83
+ const cwd = opts.cwd ? path.resolve(opts.cwd) : process.cwd();
84
+ const resolvedPath = path.isAbsolute(requested)
85
+ ? path.resolve(requested)
86
+ : path.resolve(cwd, requested);
87
+ const result = makeBaseResult(opts, baseDirResolved, resolvedPath);
88
+ // 1) Lexical boundary check
89
+ const outsideLexical = !isWithinBase(baseDirResolved, resolvedPath);
90
+ result.isOutsideByLexical = outsideLexical;
91
+ if (outsideLexical) {
92
+ result.reason = "Path is outside the allowed directory boundary.";
93
+ fail("PATH_OUTSIDE_SCOPE", result.reason, result);
94
+ }
95
+ // 2) Existence / type checks
96
+ const mustExist = opts.mustExist === true;
97
+ const allowCreate = opts.allowCreate === true;
98
+ const exists = existsSync(resolvedPath);
99
+ if (mustExist && !exists) {
100
+ result.reason = `Path does not exist: ${resolvedPath}`;
101
+ fail("PATH_NOT_FOUND", result.reason, result);
102
+ }
103
+ if (!exists && !mustExist && !allowCreate) {
104
+ result.reason = `Path does not exist: ${resolvedPath}`;
105
+ fail("PATH_NOT_FOUND", result.reason, result);
106
+ }
107
+ // 3) Canonical (realpath) boundary check to prevent symlink escapes
108
+ const followSymlinks = opts.followSymlinks !== false;
109
+ if (followSymlinks) {
110
+ let baseCanonical;
111
+ try {
112
+ if (existsSync(baseDirResolved)) {
113
+ baseCanonical = realpathSync(baseDirResolved);
114
+ result.baseDirCanonical = baseCanonical;
115
+ }
116
+ }
117
+ catch {
118
+ // If the base cannot be canonicalized, fall back to lexical checks.
119
+ }
120
+ if (baseCanonical) {
121
+ if (exists) {
122
+ try {
123
+ const candidateCanonical = realpathSync(resolvedPath);
124
+ result.canonicalPath = candidateCanonical;
125
+ const outsideCanonical = !isWithinBase(baseCanonical, candidateCanonical);
126
+ result.isOutsideByCanonical = outsideCanonical;
127
+ if (outsideCanonical) {
128
+ result.canonicalPath = candidateCanonical;
129
+ result.crossedSymlinkBoundary = true;
130
+ result.decision = "deny_symlink";
131
+ result.reason = "Path escapes the allowed directory via a symbolic link.";
132
+ fail("PATH_SYMLINK_ESCAPES_SCOPE", result.reason, result);
133
+ }
134
+ }
135
+ catch (e) {
136
+ if (e instanceof SafePathError)
137
+ throw e;
138
+ // If canonicalization fails for an existing path, rely on lexical + stat checks.
139
+ }
140
+ }
141
+ else if (allowCreate) {
142
+ const ancestor = nearestExistingAncestor(resolvedPath);
143
+ if (ancestor) {
144
+ try {
145
+ const ancestorCanonical = realpathSync(ancestor);
146
+ const outsideCanonical = !isWithinBase(baseCanonical, ancestorCanonical);
147
+ result.canonicalPath = ancestorCanonical;
148
+ result.isOutsideByCanonical = outsideCanonical;
149
+ if (outsideCanonical) {
150
+ result.crossedSymlinkBoundary = true;
151
+ result.decision = "deny_symlink";
152
+ result.reason = "Path escapes the allowed directory via a symbolic link in its parent path.";
153
+ fail("PATH_SYMLINK_ESCAPES_SCOPE", result.reason, result);
154
+ }
155
+ }
156
+ catch (e) {
157
+ if (e instanceof SafePathError)
158
+ throw e;
159
+ // ignore canonical failure; lexical check already passed
160
+ }
161
+ }
162
+ }
163
+ }
164
+ }
165
+ if (exists) {
166
+ let st;
167
+ try {
168
+ st = statSync(resolvedPath);
169
+ }
170
+ catch (e) {
171
+ result.reason = `Failed to stat path: ${e instanceof Error ? e.message : String(e)}`;
172
+ fail("PATH_INVALID_INPUT", result.reason, result);
173
+ }
174
+ if (opts.expectFile && !st.isFile()) {
175
+ result.reason = `Expected a file: ${resolvedPath}`;
176
+ fail("PATH_NOT_FILE", result.reason, result);
177
+ }
178
+ if (opts.expectDirectory && !st.isDirectory()) {
179
+ result.reason = `Expected a directory: ${resolvedPath}`;
180
+ fail("PATH_NOT_DIRECTORY", result.reason, result);
181
+ }
182
+ }
183
+ result.decision = "allow";
184
+ result.safePath = resolvedPath;
185
+ return result;
186
+ }
187
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/security/path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function getSensitiveFileReadReason(filePath: string): string | null;
2
+ export declare function isSensitiveFileForRead(filePath: string): boolean;
3
+ //# sourceMappingURL=sensitive-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitive-files.d.ts","sourceRoot":"","sources":["../../src/security/sensitive-files.ts"],"names":[],"mappings":"AAoBA,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAwB1E;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEhE"}
@@ -0,0 +1,41 @@
1
+ import * as path from "node:path";
2
+ function normalizeBasename(filePath) {
3
+ return path.basename(filePath).toLowerCase();
4
+ }
5
+ function isEnvSecretFile(base) {
6
+ if (base === ".env")
7
+ return true;
8
+ if (!base.startsWith(".env."))
9
+ return false;
10
+ if (base === ".env.example" ||
11
+ base === ".env.sample" ||
12
+ base === ".env.template" ||
13
+ base === ".env.schema") {
14
+ return false;
15
+ }
16
+ return true;
17
+ }
18
+ export function getSensitiveFileReadReason(filePath) {
19
+ const base = normalizeBasename(filePath);
20
+ if (isEnvSecretFile(base)) {
21
+ return "environment secret files (.env*) are blocked by default";
22
+ }
23
+ if (base === ".npmrc" || base === ".pypirc" || base === ".netrc") {
24
+ return `${base} may contain credentials`;
25
+ }
26
+ if (base === "credentials.json" || base === "application_default_credentials.json") {
27
+ return `${base} commonly stores cloud credentials`;
28
+ }
29
+ if (base === "id_rsa" || base === "id_dsa" || base === "id_ecdsa" || base === "id_ed25519") {
30
+ return `${base} is a private key file`;
31
+ }
32
+ if (base.endsWith(".pem") || base.endsWith(".key") || base.endsWith(".p12") ||
33
+ base.endsWith(".pfx") || base.endsWith(".p8")) {
34
+ return "certificate/private-key material is blocked by default";
35
+ }
36
+ return null;
37
+ }
38
+ export function isSensitiveFileForRead(filePath) {
39
+ return getSensitiveFileReadReason(filePath) !== null;
40
+ }
41
+ //# sourceMappingURL=sensitive-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitive-files.js","sourceRoot":"","sources":["../../src/security/sensitive-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,SAAS,iBAAiB,CAAC,QAAgB;IACzC,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,IACE,IAAI,KAAK,cAAc;QACvB,IAAI,KAAK,aAAa;QACtB,IAAI,KAAK,eAAe;QACxB,IAAI,KAAK,aAAa,EACtB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,QAAgB;IACzD,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,yDAAyD,CAAC;IACnE,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACjE,OAAO,GAAG,IAAI,0BAA0B,CAAC;IAC3C,CAAC;IAED,IAAI,IAAI,KAAK,kBAAkB,IAAI,IAAI,KAAK,sCAAsC,EAAE,CAAC;QACnF,OAAO,GAAG,IAAI,oCAAoC,CAAC;IACrD,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QAC3F,OAAO,GAAG,IAAI,wBAAwB,CAAC;IACzC,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACvE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,wDAAwD,CAAC;IAClE,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,OAAO,0BAA0B,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;AACvD,CAAC"}