@jx-grxf/patchpilot 0.2.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 (95) hide show
  1. package/.env.example +13 -0
  2. package/LICENSE +21 -0
  3. package/README.md +314 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +71 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/core/agent.d.ts +21 -0
  8. package/dist/core/agent.js +346 -0
  9. package/dist/core/agent.js.map +1 -0
  10. package/dist/core/codex.d.ts +22 -0
  11. package/dist/core/codex.js +242 -0
  12. package/dist/core/codex.js.map +1 -0
  13. package/dist/core/compute.d.ts +9 -0
  14. package/dist/core/compute.js +18 -0
  15. package/dist/core/compute.js.map +1 -0
  16. package/dist/core/doctor.d.ts +7 -0
  17. package/dist/core/doctor.js +226 -0
  18. package/dist/core/doctor.js.map +1 -0
  19. package/dist/core/env.d.ts +6 -0
  20. package/dist/core/env.js +103 -0
  21. package/dist/core/env.js.map +1 -0
  22. package/dist/core/gemini.d.ts +20 -0
  23. package/dist/core/gemini.js +177 -0
  24. package/dist/core/gemini.js.map +1 -0
  25. package/dist/core/json.d.ts +3 -0
  26. package/dist/core/json.js +95 -0
  27. package/dist/core/json.js.map +1 -0
  28. package/dist/core/modelClient.d.ts +8 -0
  29. package/dist/core/modelClient.js +42 -0
  30. package/dist/core/modelClient.js.map +1 -0
  31. package/dist/core/nvidia.d.ts +19 -0
  32. package/dist/core/nvidia.js +160 -0
  33. package/dist/core/nvidia.js.map +1 -0
  34. package/dist/core/ollama.d.ts +31 -0
  35. package/dist/core/ollama.js +176 -0
  36. package/dist/core/ollama.js.map +1 -0
  37. package/dist/core/openrouter.d.ts +27 -0
  38. package/dist/core/openrouter.js +168 -0
  39. package/dist/core/openrouter.js.map +1 -0
  40. package/dist/core/subagents.d.ts +14 -0
  41. package/dist/core/subagents.js +89 -0
  42. package/dist/core/subagents.js.map +1 -0
  43. package/dist/core/tokenAccounting.d.ts +6 -0
  44. package/dist/core/tokenAccounting.js +134 -0
  45. package/dist/core/tokenAccounting.js.map +1 -0
  46. package/dist/core/types.d.ts +90 -0
  47. package/dist/core/types.js +2 -0
  48. package/dist/core/types.js.map +1 -0
  49. package/dist/core/workspace.d.ts +28 -0
  50. package/dist/core/workspace.js +616 -0
  51. package/dist/core/workspace.js.map +1 -0
  52. package/dist/tui/App.d.ts +6 -0
  53. package/dist/tui/App.js +1717 -0
  54. package/dist/tui/App.js.map +1 -0
  55. package/dist/tui/commands.d.ts +14 -0
  56. package/dist/tui/commands.js +210 -0
  57. package/dist/tui/commands.js.map +1 -0
  58. package/dist/tui/components/CommandSuggestions.d.ts +12 -0
  59. package/dist/tui/components/CommandSuggestions.js +12 -0
  60. package/dist/tui/components/CommandSuggestions.js.map +1 -0
  61. package/dist/tui/components/Composer.d.ts +13 -0
  62. package/dist/tui/components/Composer.js +29 -0
  63. package/dist/tui/components/Composer.js.map +1 -0
  64. package/dist/tui/components/Header.d.ts +25 -0
  65. package/dist/tui/components/Header.js +62 -0
  66. package/dist/tui/components/Header.js.map +1 -0
  67. package/dist/tui/components/OnboardingPanel.d.ts +38 -0
  68. package/dist/tui/components/OnboardingPanel.js +85 -0
  69. package/dist/tui/components/OnboardingPanel.js.map +1 -0
  70. package/dist/tui/components/Sidebar.d.ts +22 -0
  71. package/dist/tui/components/Sidebar.js +133 -0
  72. package/dist/tui/components/Sidebar.js.map +1 -0
  73. package/dist/tui/components/Transcript.d.ts +10 -0
  74. package/dist/tui/components/Transcript.js +111 -0
  75. package/dist/tui/components/Transcript.js.map +1 -0
  76. package/dist/tui/format.d.ts +29 -0
  77. package/dist/tui/format.js +202 -0
  78. package/dist/tui/format.js.map +1 -0
  79. package/dist/tui/hosts.d.ts +34 -0
  80. package/dist/tui/hosts.js +338 -0
  81. package/dist/tui/hosts.js.map +1 -0
  82. package/dist/tui/inputRouting.d.ts +8 -0
  83. package/dist/tui/inputRouting.js +94 -0
  84. package/dist/tui/inputRouting.js.map +1 -0
  85. package/dist/tui/platform.d.ts +2 -0
  86. package/dist/tui/platform.js +13 -0
  87. package/dist/tui/platform.js.map +1 -0
  88. package/dist/tui/systemStats.d.ts +25 -0
  89. package/dist/tui/systemStats.js +88 -0
  90. package/dist/tui/systemStats.js.map +1 -0
  91. package/dist/tui/types.d.ts +16 -0
  92. package/dist/tui/types.js +2 -0
  93. package/dist/tui/types.js.map +1 -0
  94. package/docs/showcase/patchpilot-showcase.svg +39 -0
  95. package/package.json +63 -0
@@ -0,0 +1,18 @@
1
+ import { normalizeOllamaBaseUrl } from "./ollama.js";
2
+ const localHosts = new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
3
+ export function describeComputeTarget(value) {
4
+ const url = normalizeOllamaBaseUrl(value);
5
+ const parsedUrl = new URL(url);
6
+ const host = parsedUrl.host;
7
+ const kind = localHosts.has(parsedUrl.hostname.toLowerCase()) ? "local" : "remote";
8
+ return {
9
+ kind,
10
+ url,
11
+ host,
12
+ label: kind === "local" ? "local Ollama" : `remote Ollama at ${host}`
13
+ };
14
+ }
15
+ export function isLocalComputeTarget(value) {
16
+ return describeComputeTarget(value).kind === "local";
17
+ }
18
+ //# sourceMappingURL=compute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute.js","sourceRoot":"","sources":["../../src/core/compute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAWrD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvE,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,MAAM,GAAG,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;IAC5B,MAAM,IAAI,GAAsB,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEtG,OAAO;QACL,IAAI;QACJ,GAAG;QACH,IAAI;QACJ,KAAK,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,oBAAoB,IAAI,EAAE;KACtE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC;AACvD,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ModelProvider } from "./types.js";
2
+ export type DoctorResult = {
3
+ name: string;
4
+ ok: boolean;
5
+ details: string;
6
+ };
7
+ export declare function runDoctor(provider: ModelProvider, ollamaUrl: string, model?: string): Promise<DoctorResult[]>;
@@ -0,0 +1,226 @@
1
+ import { spawn } from "node:child_process";
2
+ import { describeComputeTarget } from "./compute.js";
3
+ import { codexOAuthModels, hasCodexCliOAuth } from "./codex.js";
4
+ import { GeminiClient, readGeminiApiKey } from "./gemini.js";
5
+ import { NvidiaClient, readNvidiaApiKey } from "./nvidia.js";
6
+ import { OllamaClient } from "./ollama.js";
7
+ import { OpenRouterClient, readOpenRouterApiKey } from "./openrouter.js";
8
+ export async function runDoctor(provider, ollamaUrl, model) {
9
+ const results = [];
10
+ results.push(await checkCommand("node", ["--version"]));
11
+ results.push(await checkCommand("git", ["--version"]));
12
+ if (provider === "gemini") {
13
+ results.push(...(await checkGemini(model)));
14
+ return results;
15
+ }
16
+ if (provider === "codex") {
17
+ results.push(...(await checkCodex(model)));
18
+ return results;
19
+ }
20
+ if (provider === "openrouter") {
21
+ results.push(...(await checkOpenRouter(model)));
22
+ return results;
23
+ }
24
+ if (provider === "nvidia") {
25
+ results.push(...(await checkNvidia(model)));
26
+ return results;
27
+ }
28
+ const computeTarget = describeComputeTarget(ollamaUrl);
29
+ if (computeTarget.kind === "local") {
30
+ results.push(await checkCommand("ollama", ["--version"], "ollama-cli", "Install Ollama and ensure the ollama CLI is available on PATH."));
31
+ }
32
+ else {
33
+ results.push({
34
+ name: "ollama-cli",
35
+ ok: true,
36
+ details: `not required locally while using ${computeTarget.label}`
37
+ });
38
+ }
39
+ const ollama = new OllamaClient(ollamaUrl);
40
+ try {
41
+ const models = await ollama.listModels();
42
+ results.push({
43
+ name: "ollama",
44
+ ok: true,
45
+ details: models.length > 0 ? `available models: ${models.join(", ")}` : "server reachable, no models pulled"
46
+ });
47
+ if (model) {
48
+ results.push({
49
+ name: "ollama-model",
50
+ ok: models.includes(model),
51
+ details: models.includes(model) ? `${model} is available` : `${model} is missing. Run: ollama pull ${model}`
52
+ });
53
+ }
54
+ }
55
+ catch (error) {
56
+ results.push({
57
+ name: "ollama",
58
+ ok: false,
59
+ details: error instanceof Error ? error.message : String(error)
60
+ });
61
+ }
62
+ return results;
63
+ }
64
+ async function checkOpenRouter(model) {
65
+ const results = [
66
+ {
67
+ name: "openrouter-key",
68
+ ok: Boolean(readOpenRouterApiKey()),
69
+ details: readOpenRouterApiKey() ? "OPENROUTER_API_KEY is configured" : "missing. Add OPENROUTER_API_KEY to PatchPilot config"
70
+ }
71
+ ];
72
+ if (!readOpenRouterApiKey()) {
73
+ return results;
74
+ }
75
+ try {
76
+ const models = await new OpenRouterClient().listModels();
77
+ results.push({
78
+ name: "openrouter",
79
+ ok: true,
80
+ details: models.length > 0 ? `available models: ${models.slice(0, 12).join(", ")}` : "API reachable, no models listed"
81
+ });
82
+ if (model) {
83
+ results.push({
84
+ name: "openrouter-model",
85
+ ok: models.includes(model),
86
+ details: models.includes(model) ? `${model} is available` : `${model} is not listed by OpenRouter models API`
87
+ });
88
+ }
89
+ }
90
+ catch (error) {
91
+ results.push({
92
+ name: "openrouter",
93
+ ok: false,
94
+ details: error instanceof Error ? error.message : String(error)
95
+ });
96
+ }
97
+ return results;
98
+ }
99
+ async function checkNvidia(model) {
100
+ const results = [
101
+ {
102
+ name: "nvidia-key",
103
+ ok: Boolean(readNvidiaApiKey()),
104
+ details: readNvidiaApiKey() ? "NVIDIA_API_KEY is configured" : "missing. Add NVIDIA_API_KEY to PatchPilot config"
105
+ }
106
+ ];
107
+ if (!readNvidiaApiKey()) {
108
+ return results;
109
+ }
110
+ try {
111
+ const models = await new NvidiaClient().listModels();
112
+ results.push({
113
+ name: "nvidia",
114
+ ok: true,
115
+ details: models.length > 0 ? `available models: ${models.slice(0, 12).join(", ")}` : "API reachable, no models listed"
116
+ });
117
+ if (model) {
118
+ results.push({
119
+ name: "nvidia-model",
120
+ ok: models.includes(model),
121
+ details: models.includes(model) ? `${model} is available` : `${model} is not listed by NVIDIA models API`
122
+ });
123
+ }
124
+ }
125
+ catch (error) {
126
+ results.push({
127
+ name: "nvidia",
128
+ ok: false,
129
+ details: error instanceof Error ? error.message : String(error)
130
+ });
131
+ }
132
+ return results;
133
+ }
134
+ async function checkCodex(model) {
135
+ const cli = await checkCommand("codex", ["--version"], "codex-cli", "Install Codex CLI, then run codex login.");
136
+ const hasOAuth = hasCodexCliOAuth();
137
+ const results = [
138
+ cli,
139
+ {
140
+ name: "codex-auth",
141
+ ok: hasOAuth,
142
+ details: hasOAuth ? "Codex CLI OAuth tokens are present" : "missing. Run: codex login"
143
+ }
144
+ ];
145
+ if (!cli.ok || !hasOAuth) {
146
+ return results;
147
+ }
148
+ results.push({
149
+ name: "codex",
150
+ ok: true,
151
+ details: `OAuth backend ready. Models: ${codexOAuthModels.join(", ")}`
152
+ });
153
+ if (model) {
154
+ results.push({
155
+ name: "codex-model",
156
+ ok: codexOAuthModels.includes(model),
157
+ details: codexOAuthModels.includes(model) ? `${model} is available` : `${model} is not in the Codex OAuth model list`
158
+ });
159
+ }
160
+ return results;
161
+ }
162
+ async function checkGemini(model) {
163
+ const results = [
164
+ {
165
+ name: "gemini-key",
166
+ ok: Boolean(readGeminiApiKey()),
167
+ details: readGeminiApiKey() ? "GEMINI_API_KEY is configured" : "missing. Add GEMINI_API_KEY to .env"
168
+ }
169
+ ];
170
+ if (!readGeminiApiKey()) {
171
+ return results;
172
+ }
173
+ const gemini = new GeminiClient();
174
+ try {
175
+ const models = await gemini.listModels();
176
+ results.push({
177
+ name: "gemini",
178
+ ok: true,
179
+ details: models.length > 0 ? `available models: ${models.slice(0, 12).join(", ")}` : "API reachable, no generateContent models listed"
180
+ });
181
+ if (model) {
182
+ results.push({
183
+ name: "gemini-model",
184
+ ok: models.includes(model),
185
+ details: models.includes(model) ? `${model} is available` : `${model} is not listed by Gemini models API`
186
+ });
187
+ }
188
+ }
189
+ catch (error) {
190
+ results.push({
191
+ name: "gemini",
192
+ ok: false,
193
+ details: error instanceof Error ? error.message : String(error)
194
+ });
195
+ }
196
+ return results;
197
+ }
198
+ function checkCommand(command, args, name = command, missingHint) {
199
+ return new Promise((resolve) => {
200
+ const child = spawn(command, args, {
201
+ windowsHide: true
202
+ });
203
+ let output = "";
204
+ child.stdout.on("data", (chunk) => {
205
+ output += chunk.toString("utf8");
206
+ });
207
+ child.stderr.on("data", (chunk) => {
208
+ output += chunk.toString("utf8");
209
+ });
210
+ child.on("error", (error) => {
211
+ resolve({
212
+ name,
213
+ ok: false,
214
+ details: missingHint ? `${error.message}. ${missingHint}` : error.message
215
+ });
216
+ });
217
+ child.on("close", (exitCode) => {
218
+ resolve({
219
+ name,
220
+ ok: exitCode === 0,
221
+ details: output.trim()
222
+ });
223
+ });
224
+ });
225
+ }
226
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/core/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AASzE,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAuB,EAAE,SAAiB,EAAE,KAAc;IACxF,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,OAAO,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAEvD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,aAAa,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,aAAa,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,CACV,MAAM,YAAY,CAChB,QAAQ,EACR,CAAC,WAAW,CAAC,EACb,YAAY,EACZ,gEAAgE,CACjE,CACF,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,YAAY;YAClB,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,oCAAoC,aAAa,CAAC,KAAK,EAAE;SACnE,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,oCAAoC;SAC7G,CAAC,CAAC;QACH,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,cAAc;gBACpB,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAC1B,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,iCAAiC,KAAK,EAAE;aAC7G,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,KAAc;IAC3C,MAAM,OAAO,GAAmB;QAC9B;YACE,IAAI,EAAE,gBAAgB;YACtB,EAAE,EAAE,OAAO,CAAC,oBAAoB,EAAE,CAAC;YACnC,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,sDAAsD;SAC9H;KACF,CAAC;IAEF,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;QAC5B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,gBAAgB,EAAE,CAAC,UAAU,EAAE,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,YAAY;YAClB,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,iCAAiC;SACvH,CAAC,CAAC;QACH,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,kBAAkB;gBACxB,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAC1B,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,yCAAyC;aAC9G,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,YAAY;YAClB,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,KAAc;IACvC,MAAM,OAAO,GAAmB;QAC9B;YACE,IAAI,EAAE,YAAY;YAClB,EAAE,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC/B,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,kDAAkD;SAClH;KACF,CAAC;IAEF,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,iCAAiC;SACvH,CAAC,CAAC;QACH,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,cAAc;gBACpB,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAC1B,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,qCAAqC;aAC1G,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,KAAc;IACtC,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,WAAW,EAAE,0CAA0C,CAAC,CAAC;IAChH,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,MAAM,OAAO,GAAmB;QAC9B,GAAG;QACH;YACE,IAAI,EAAE,YAAY;YAClB,EAAE,EAAE,QAAQ;YACZ,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,2BAA2B;SACvF;KACF,CAAC;IAEF,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,IAAI;QACR,OAAO,EAAE,gCAAgC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;KACvE,CAAC,CAAC;IACH,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,aAAa;YACnB,EAAE,EAAE,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC;YACpC,OAAO,EAAE,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,uCAAuC;SACtH,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,KAAc;IACvC,MAAM,OAAO,GAAmB;QAC9B;YACE,IAAI,EAAE,YAAY;YAClB,EAAE,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC/B,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,qCAAqC;SACrG;KACF,CAAC;IAEF,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,iDAAiD;SACvI,CAAC,CAAC;QACH,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,cAAc;gBACpB,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAC1B,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,qCAAqC;aAC1G,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,OAAe,EAAE,IAAc,EAAE,IAAI,GAAG,OAAO,EAAE,WAAoB;IACzF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACjC,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,OAAO,CAAC;gBACN,IAAI;gBACJ,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO;aAC1E,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC7B,OAAO,CAAC;gBACN,IAAI;gBACJ,EAAE,EAAE,QAAQ,KAAK,CAAC;gBAClB,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE;aACvB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare function loadDotEnv(cwd?: string): void;
2
+ export declare function saveDotEnvValues(values: Record<string, string>, cwd?: string): void;
3
+ export declare function getPatchPilotConfigDir(env?: NodeJS.ProcessEnv): string;
4
+ export declare function getPatchPilotEnvPath(env?: NodeJS.ProcessEnv): string;
5
+ export declare function loadPatchPilotEnv(env?: NodeJS.ProcessEnv): void;
6
+ export declare function savePatchPilotEnvValues(values: Record<string, string>, env?: NodeJS.ProcessEnv): void;
@@ -0,0 +1,103 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import path from "node:path";
4
+ export function loadDotEnv(cwd = process.cwd()) {
5
+ const envPath = path.join(cwd, ".env");
6
+ if (!existsSync(envPath)) {
7
+ return;
8
+ }
9
+ const content = readFileSync(envPath, "utf8");
10
+ for (const line of content.split(/\r?\n/)) {
11
+ const entry = parseEnvLine(line);
12
+ if (!entry || process.env[entry.key] !== undefined) {
13
+ continue;
14
+ }
15
+ process.env[entry.key] = entry.value;
16
+ }
17
+ }
18
+ export function saveDotEnvValues(values, cwd = process.cwd()) {
19
+ const envPath = path.join(cwd, ".env");
20
+ const existingContent = existsSync(envPath) ? readFileSync(envPath, "utf8") : "";
21
+ const lines = existingContent ? existingContent.split(/\r?\n/) : [];
22
+ const remainingValues = new Map(Object.entries(values));
23
+ const nextLines = lines.map((line) => {
24
+ const parsedLine = parseEnvLine(line);
25
+ if (!parsedLine || !remainingValues.has(parsedLine.key)) {
26
+ return line;
27
+ }
28
+ const value = remainingValues.get(parsedLine.key) ?? "";
29
+ remainingValues.delete(parsedLine.key);
30
+ return `${parsedLine.key}=${quoteEnvValue(value)}`;
31
+ });
32
+ while (nextLines.at(-1) === "") {
33
+ nextLines.pop();
34
+ }
35
+ for (const [key, value] of remainingValues) {
36
+ nextLines.push(`${key}=${quoteEnvValue(value)}`);
37
+ }
38
+ writeFileSync(envPath, `${nextLines.join("\n").replace(/\n+$/, "")}\n`, {
39
+ encoding: "utf8",
40
+ mode: 0o600
41
+ });
42
+ tryChmod(envPath, 0o600);
43
+ }
44
+ export function getPatchPilotConfigDir(env = process.env) {
45
+ return env.PATCHPILOT_CONFIG_DIR?.trim() || path.join(homedir(), ".patchpilot");
46
+ }
47
+ export function getPatchPilotEnvPath(env = process.env) {
48
+ return path.join(getPatchPilotConfigDir(env), ".env");
49
+ }
50
+ export function loadPatchPilotEnv(env = process.env) {
51
+ const envPath = getPatchPilotEnvPath(env);
52
+ if (!existsSync(envPath)) {
53
+ return;
54
+ }
55
+ loadDotEnv(path.dirname(envPath));
56
+ }
57
+ export function savePatchPilotEnvValues(values, env = process.env) {
58
+ const configDir = getPatchPilotConfigDir(env);
59
+ mkdirSync(configDir, { recursive: true, mode: 0o700 });
60
+ tryChmod(configDir, 0o700);
61
+ saveDotEnvValues(values, configDir);
62
+ }
63
+ function tryChmod(filePath, mode) {
64
+ try {
65
+ chmodSync(filePath, mode);
66
+ }
67
+ catch {
68
+ // Best-effort hardening; chmod can be limited on some Windows filesystems.
69
+ }
70
+ }
71
+ function parseEnvLine(line) {
72
+ const trimmedLine = line.trim();
73
+ if (!trimmedLine || trimmedLine.startsWith("#")) {
74
+ return null;
75
+ }
76
+ const separatorIndex = trimmedLine.indexOf("=");
77
+ if (separatorIndex <= 0) {
78
+ return null;
79
+ }
80
+ const key = trimmedLine.slice(0, separatorIndex).trim();
81
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
82
+ return null;
83
+ }
84
+ return {
85
+ key,
86
+ value: unquoteEnvValue(trimmedLine.slice(separatorIndex + 1).trim())
87
+ };
88
+ }
89
+ function unquoteEnvValue(value) {
90
+ if ((value.startsWith('"') && value.endsWith('"')) ||
91
+ (value.startsWith("'") && value.endsWith("'"))) {
92
+ return value.slice(1, -1);
93
+ }
94
+ const commentIndex = value.indexOf(" #");
95
+ return commentIndex >= 0 ? value.slice(0, commentIndex).trimEnd() : value;
96
+ }
97
+ function quoteEnvValue(value) {
98
+ if (!value || /[\s#"']/.test(value)) {
99
+ return JSON.stringify(value);
100
+ }
101
+ return value;
102
+ }
103
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/core/env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ModelChatOptions, ModelChatResult } from "./types.js";
2
+ export declare const defaultGeminiModel = "gemini-2.5-flash";
3
+ export declare const defaultGeminiBaseUrl = "https://generativelanguage.googleapis.com/v1beta";
4
+ type GeminiRuntimeOptions = {
5
+ maxOutputTokens: number;
6
+ temperature: number;
7
+ };
8
+ export declare class GeminiClient {
9
+ private readonly apiKey;
10
+ private readonly baseUrl;
11
+ private readonly runtimeOptions;
12
+ constructor(apiKey?: string, baseUrl?: string, runtimeOptions?: GeminiRuntimeOptions);
13
+ chat(options: ModelChatOptions): Promise<ModelChatResult>;
14
+ listModels(): Promise<string[]>;
15
+ private fetchGemini;
16
+ private assertConfigured;
17
+ }
18
+ export declare function readGeminiApiKey(env?: NodeJS.ProcessEnv): string;
19
+ export declare function readGeminiRuntimeOptions(env?: NodeJS.ProcessEnv): GeminiRuntimeOptions;
20
+ export {};
@@ -0,0 +1,177 @@
1
+ import { attachTokenCost } from "./tokenAccounting.js";
2
+ export const defaultGeminiModel = "gemini-2.5-flash";
3
+ export const defaultGeminiBaseUrl = "https://generativelanguage.googleapis.com/v1beta";
4
+ export class GeminiClient {
5
+ apiKey;
6
+ baseUrl;
7
+ runtimeOptions;
8
+ constructor(apiKey = readGeminiApiKey(), baseUrl = process.env.PATCHPILOT_GEMINI_BASE_URL ?? defaultGeminiBaseUrl, runtimeOptions = readGeminiRuntimeOptions()) {
9
+ this.apiKey = apiKey;
10
+ this.baseUrl = baseUrl.replace(/\/$/, "");
11
+ this.runtimeOptions = runtimeOptions;
12
+ }
13
+ async chat(options) {
14
+ this.assertConfigured();
15
+ const startedAt = Date.now();
16
+ const response = await this.fetchGemini(`${modelPath(options.model)}:generateContent`, {
17
+ method: "POST",
18
+ headers: {
19
+ "Content-Type": "application/json",
20
+ "x-goog-api-key": this.apiKey
21
+ },
22
+ body: JSON.stringify(toGenerateContentRequest(options.model, options.messages, options.formatJson, this.runtimeOptions, options.reasoningEffort)),
23
+ signal: options.signal
24
+ });
25
+ const durationMs = Date.now() - startedAt;
26
+ const payload = (await readJsonSafely(response));
27
+ if (!response.ok || payload.error) {
28
+ const reason = payload.error?.message ? ` ${payload.error.message}` : "";
29
+ throw new Error(`Gemini chat failed for model "${options.model}": HTTP ${response.status}.${reason}`);
30
+ }
31
+ const content = payload.candidates?.[0]?.content?.parts?.map((part) => part.text ?? "").join("").trim() ?? "";
32
+ if (!content) {
33
+ const blockReason = payload.promptFeedback?.blockReason;
34
+ const finishReason = payload.candidates?.[0]?.finishReason;
35
+ const reason = blockReason ? ` Prompt blocked: ${blockReason}.` : finishReason ? ` Finish reason: ${finishReason}.` : "";
36
+ throw new Error(`Gemini returned an empty response.${reason}`);
37
+ }
38
+ return {
39
+ content,
40
+ telemetry: toTelemetry(payload, durationMs, options.model)
41
+ };
42
+ }
43
+ async listModels() {
44
+ this.assertConfigured();
45
+ const response = await this.fetchGemini("models");
46
+ const payload = (await readJsonSafely(response));
47
+ if (!response.ok || payload.error) {
48
+ const reason = payload.error?.message ? ` ${payload.error.message}` : "";
49
+ throw new Error(`Gemini models failed with HTTP ${response.status}.${reason}`);
50
+ }
51
+ return (payload.models
52
+ ?.filter((model) => model.supportedGenerationMethods?.includes("generateContent"))
53
+ .map((model) => stripModelPrefix(model.name))
54
+ .sort() ?? []);
55
+ }
56
+ async fetchGemini(path, init) {
57
+ try {
58
+ return await fetch(`${this.baseUrl}/${path}`, init);
59
+ }
60
+ catch (error) {
61
+ const suffix = error instanceof Error ? ` ${error.message}` : "";
62
+ throw new Error(`Cannot reach Gemini API at ${this.baseUrl}.${suffix}`);
63
+ }
64
+ }
65
+ assertConfigured() {
66
+ if (!this.apiKey) {
67
+ throw new Error("Gemini API key missing. Set GEMINI_API_KEY in .env or your shell.");
68
+ }
69
+ }
70
+ }
71
+ export function readGeminiApiKey(env = process.env) {
72
+ return env.GOOGLE_API_KEY?.trim() || env.GEMINI_API_KEY?.trim() || "";
73
+ }
74
+ export function readGeminiRuntimeOptions(env = process.env) {
75
+ return {
76
+ maxOutputTokens: readPositiveInteger(env.PATCHPILOT_NUM_PREDICT, 1024),
77
+ temperature: readTemperature(env.PATCHPILOT_TEMPERATURE, 0.1)
78
+ };
79
+ }
80
+ function toGenerateContentRequest(model, messages, formatJson, runtimeOptions, reasoningEffort) {
81
+ const systemText = messages
82
+ .filter((message) => message.role === "system")
83
+ .map((message) => message.content)
84
+ .join("\n\n")
85
+ .trim();
86
+ const contents = messages.filter((message) => message.role !== "system").map(toGeminiContent);
87
+ return {
88
+ systemInstruction: systemText
89
+ ? {
90
+ parts: [
91
+ {
92
+ text: systemText
93
+ }
94
+ ]
95
+ }
96
+ : undefined,
97
+ contents,
98
+ generationConfig: {
99
+ maxOutputTokens: runtimeOptions.maxOutputTokens,
100
+ temperature: runtimeOptions.temperature,
101
+ thinkingConfig: buildGeminiThinkingConfig(model, reasoningEffort),
102
+ responseMimeType: formatJson ? "application/json" : undefined
103
+ }
104
+ };
105
+ }
106
+ function buildGeminiThinkingConfig(model, reasoningEffort) {
107
+ if (!reasoningEffort) {
108
+ return undefined;
109
+ }
110
+ if (/gemini-2\.5/i.test(model)) {
111
+ return {
112
+ thinkingBudget: reasoningEffort === "low"
113
+ ? 512
114
+ : reasoningEffort === "medium"
115
+ ? 2048
116
+ : reasoningEffort === "high"
117
+ ? 8192
118
+ : 12_288
119
+ };
120
+ }
121
+ return {
122
+ thinkingLevel: reasoningEffort === "xhigh" ? "high" : reasoningEffort
123
+ };
124
+ }
125
+ function toGeminiContent(message) {
126
+ return {
127
+ role: message.role === "assistant" ? "model" : "user",
128
+ parts: [
129
+ {
130
+ text: message.content
131
+ }
132
+ ]
133
+ };
134
+ }
135
+ function modelPath(model) {
136
+ const normalizedModel = model.startsWith("models/") ? model : `models/${model}`;
137
+ return normalizedModel.split("/").map(encodeURIComponent).join("/");
138
+ }
139
+ function stripModelPrefix(model) {
140
+ return model.startsWith("models/") ? model.slice("models/".length) : model;
141
+ }
142
+ function toTelemetry(payload, durationMs, model) {
143
+ const promptTokens = payload.usageMetadata?.promptTokenCount ?? 0;
144
+ const responseTokens = payload.usageMetadata?.candidatesTokenCount ?? 0;
145
+ const cachedPromptTokens = payload.usageMetadata?.cachedContentTokenCount ?? 0;
146
+ const thoughtsTokens = payload.usageMetadata?.thoughtsTokenCount ?? 0;
147
+ const totalTokens = payload.usageMetadata?.totalTokenCount ?? promptTokens + responseTokens;
148
+ return attachTokenCost({
149
+ promptTokens,
150
+ cachedPromptTokens,
151
+ cacheWriteTokens: 0,
152
+ responseTokens: responseTokens + thoughtsTokens,
153
+ totalTokens,
154
+ evalTokensPerSecond: responseTokens > 0 && durationMs > 0 ? responseTokens / (durationMs / 1000) : null,
155
+ promptDurationMs: 0,
156
+ responseDurationMs: durationMs,
157
+ totalDurationMs: durationMs,
158
+ tokenSource: "provider"
159
+ }, "gemini", model);
160
+ }
161
+ async function readJsonSafely(response) {
162
+ try {
163
+ return await response.json();
164
+ }
165
+ catch {
166
+ return {};
167
+ }
168
+ }
169
+ function readPositiveInteger(value, fallback) {
170
+ const parsedValue = Number.parseInt(value ?? "", 10);
171
+ return Number.isFinite(parsedValue) && parsedValue > 0 ? parsedValue : fallback;
172
+ }
173
+ function readTemperature(value, fallback) {
174
+ const parsedValue = Number.parseFloat(value ?? "");
175
+ return Number.isFinite(parsedValue) && parsedValue >= 0 ? parsedValue : fallback;
176
+ }
177
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/core/gemini.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AgentResponse } from "./types.js";
2
+ export declare function parseAgentResponse(rawContent: string): AgentResponse;
3
+ export declare function formatParseError(error: unknown): string;