@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 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/tui/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { type OllamaRunningModel } from "../core/ollama.js";
2
+ export type OllamaHostKind = "local" | "lan" | "tailscale" | "manual";
3
+ export type OllamaHostSource = "default" | "env" | "current" | "discovered" | "tailscale" | "manual";
4
+ export type OllamaHost = {
5
+ label: string;
6
+ deviceName: string;
7
+ hostname: string;
8
+ url: string;
9
+ source: OllamaHostSource;
10
+ kind: OllamaHostKind;
11
+ version?: string;
12
+ os?: string;
13
+ tailscaleName?: string;
14
+ address?: string;
15
+ };
16
+ export type OllamaHostDetails = {
17
+ host: OllamaHost;
18
+ models: string[];
19
+ runningModels: OllamaRunningModel[];
20
+ fetchedAt: number;
21
+ };
22
+ export declare function getOllamaHostCandidates(currentUrl: string): OllamaHost[];
23
+ export declare function discoverOllamaHosts(currentUrl: string, options?: {
24
+ refresh?: boolean;
25
+ }): Promise<OllamaHost[]>;
26
+ export declare function normalizeOllamaUrl(value: string): string;
27
+ export declare function checkOllamaHost(value: string, options?: Partial<OllamaHost> & {
28
+ timeoutMs?: number;
29
+ }): Promise<OllamaHost | null>;
30
+ export declare function startLocalOllamaAppAndWait(options?: {
31
+ timeoutMs?: number;
32
+ }): Promise<OllamaHost | null>;
33
+ export declare function readOllamaHostDetails(host: OllamaHost, refresh?: boolean): Promise<OllamaHostDetails>;
34
+ export declare function classifyOllamaHost(value: string): OllamaHostKind;
@@ -0,0 +1,338 @@
1
+ import { execFile } from "node:child_process";
2
+ import { networkInterfaces } from "node:os";
3
+ import { promisify } from "node:util";
4
+ import { OllamaClient, defaultOllamaPort, defaultOllamaUrl, normalizeOllamaBaseUrl } from "../core/ollama.js";
5
+ const execFileAsync = promisify(execFile);
6
+ const hostDiscoveryCacheTtlMs = 20_000;
7
+ const hostDetailsCacheTtlMs = 15_000;
8
+ let lastDiscoveryCache = null;
9
+ const hostDetailsCache = new Map();
10
+ export function getOllamaHostCandidates(currentUrl) {
11
+ const hosts = [];
12
+ hosts.push(buildHostCandidate(defaultOllamaUrl, { label: "local", source: "default" }));
13
+ const envHost = process.env.PATCHPILOT_OLLAMA_URL || process.env.OLLAMA_HOST;
14
+ if (envHost) {
15
+ hosts.push(buildHostCandidate(envHost, { label: "env", source: "env" }));
16
+ }
17
+ if (currentUrl && normalizeOllamaUrl(currentUrl) !== defaultOllamaUrl) {
18
+ hosts.push(buildHostCandidate(currentUrl, { label: "current", source: "current" }));
19
+ }
20
+ return dedupeHosts(hosts);
21
+ }
22
+ export async function discoverOllamaHosts(currentUrl, options = {}) {
23
+ const normalizedCurrentUrl = normalizeOllamaUrl(currentUrl || defaultOllamaUrl);
24
+ if (!options.refresh && lastDiscoveryCache && lastDiscoveryCache.currentUrl === normalizedCurrentUrl && lastDiscoveryCache.expiresAt > Date.now()) {
25
+ return lastDiscoveryCache.hosts;
26
+ }
27
+ const candidates = getOllamaHostCandidates(normalizedCurrentUrl);
28
+ const [verifiedCandidates, discoveredLanHosts, discoveredTailscaleHosts] = await Promise.all([
29
+ runPool(candidates, 8, (candidate) => checkOllamaHost(candidate.url, {
30
+ ...candidate,
31
+ timeoutMs: 350
32
+ })),
33
+ scanLanOllamaHosts(),
34
+ discoverTailscaleOllamaHosts()
35
+ ]);
36
+ const hosts = dedupeHosts([
37
+ ...verifiedCandidates.filter((host) => host !== null),
38
+ ...discoveredTailscaleHosts,
39
+ ...discoveredLanHosts
40
+ ]);
41
+ lastDiscoveryCache = {
42
+ currentUrl: normalizedCurrentUrl,
43
+ expiresAt: Date.now() + hostDiscoveryCacheTtlMs,
44
+ hosts
45
+ };
46
+ return hosts;
47
+ }
48
+ export function normalizeOllamaUrl(value) {
49
+ return normalizeOllamaBaseUrl(value);
50
+ }
51
+ export async function checkOllamaHost(value, options = {}) {
52
+ const url = normalizeOllamaUrl(value);
53
+ const controller = new AbortController();
54
+ const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 500);
55
+ try {
56
+ const response = await fetch(`${url}/api/version`, {
57
+ signal: controller.signal,
58
+ headers: {
59
+ accept: "application/json"
60
+ }
61
+ });
62
+ if (!response.ok) {
63
+ return null;
64
+ }
65
+ const body = (await response.json());
66
+ if (typeof body.version !== "string" || body.version.length === 0) {
67
+ return null;
68
+ }
69
+ const parsedUrl = new URL(url);
70
+ const kind = options.kind ?? classifyOllamaHost(url);
71
+ const hostname = parsedUrl.hostname;
72
+ const deviceName = options.deviceName ?? formatDeviceName(hostname, options.tailscaleName);
73
+ const label = options.label ?? deviceName;
74
+ return {
75
+ label,
76
+ deviceName,
77
+ hostname,
78
+ url,
79
+ source: options.source ?? (kind === "tailscale" ? "tailscale" : "discovered"),
80
+ kind,
81
+ version: body.version,
82
+ os: options.os,
83
+ tailscaleName: options.tailscaleName,
84
+ address: options.address ?? (isIpAddress(hostname) ? hostname : undefined)
85
+ };
86
+ }
87
+ catch {
88
+ return null;
89
+ }
90
+ finally {
91
+ clearTimeout(timeout);
92
+ }
93
+ }
94
+ export async function startLocalOllamaAppAndWait(options = {}) {
95
+ if (process.platform !== "darwin") {
96
+ return null;
97
+ }
98
+ await execFileAsync("open", ["-a", "Ollama"], {
99
+ timeout: 1200,
100
+ windowsHide: true
101
+ }).catch(() => undefined);
102
+ const deadline = Date.now() + (options.timeoutMs ?? 5000);
103
+ while (Date.now() < deadline) {
104
+ const host = await checkOllamaHost("local", {
105
+ label: "local",
106
+ source: "default",
107
+ kind: "local",
108
+ timeoutMs: 500
109
+ });
110
+ if (host) {
111
+ return host;
112
+ }
113
+ await delay(350);
114
+ }
115
+ return null;
116
+ }
117
+ export async function readOllamaHostDetails(host, refresh = false) {
118
+ const cacheKey = host.url;
119
+ const cachedEntry = hostDetailsCache.get(cacheKey);
120
+ if (!refresh && cachedEntry && cachedEntry.expiresAt > Date.now()) {
121
+ return cachedEntry.details;
122
+ }
123
+ const client = new OllamaClient(host.url);
124
+ const [models, runningModels] = await Promise.all([
125
+ client.listModels(),
126
+ client.listRunningModels().catch(() => [])
127
+ ]);
128
+ const details = {
129
+ host,
130
+ models,
131
+ runningModels,
132
+ fetchedAt: Date.now()
133
+ };
134
+ hostDetailsCache.set(cacheKey, {
135
+ expiresAt: Date.now() + hostDetailsCacheTtlMs,
136
+ details
137
+ });
138
+ return details;
139
+ }
140
+ function delay(durationMs) {
141
+ return new Promise((resolve) => {
142
+ setTimeout(resolve, durationMs);
143
+ });
144
+ }
145
+ export function classifyOllamaHost(value) {
146
+ const normalizedUrl = normalizeOllamaUrl(value);
147
+ const hostname = new URL(normalizedUrl).hostname.toLowerCase();
148
+ if (hostname === "127.0.0.1" || hostname === "localhost" || hostname === "::1" || hostname === "[::1]") {
149
+ return "local";
150
+ }
151
+ if (isTailscaleHostname(hostname) || isTailscaleIpAddress(hostname)) {
152
+ return "tailscale";
153
+ }
154
+ if (isPrivateIpAddress(hostname)) {
155
+ return "lan";
156
+ }
157
+ return "manual";
158
+ }
159
+ function buildHostCandidate(value, options) {
160
+ const url = normalizeOllamaUrl(value);
161
+ const parsedUrl = new URL(url);
162
+ const kind = classifyOllamaHost(url);
163
+ return {
164
+ label: options.label,
165
+ deviceName: options.deviceName ?? formatDeviceName(parsedUrl.hostname, options.tailscaleName),
166
+ hostname: parsedUrl.hostname,
167
+ url,
168
+ source: options.source,
169
+ kind,
170
+ os: options.os,
171
+ tailscaleName: options.tailscaleName,
172
+ address: options.address ?? (isIpAddress(parsedUrl.hostname) ? parsedUrl.hostname : undefined)
173
+ };
174
+ }
175
+ function getPrivateNetworkAddresses() {
176
+ return Object.values(networkInterfaces())
177
+ .flatMap((interfaces) => interfaces ?? [])
178
+ .filter((networkInterface) => networkInterface.family === "IPv4" && !networkInterface.internal)
179
+ .map((networkInterface) => networkInterface.address)
180
+ .filter((address) => isPrivateIpAddress(address) && !isTailscaleIpAddress(address));
181
+ }
182
+ function getPrivateNetworkPrefixes() {
183
+ const prefixes = getPrivateNetworkAddresses()
184
+ .map((address) => address.split(".").slice(0, 3).join("."))
185
+ .filter((prefix, index, prefixes) => prefixes.indexOf(prefix) === index);
186
+ return prefixes.sort((left, right) => scoreNetworkPrefix(right) - scoreNetworkPrefix(left));
187
+ }
188
+ async function scanLanOllamaHosts() {
189
+ const prefixes = getPrivateNetworkPrefixes();
190
+ const discoveredHosts = [];
191
+ for (const prefix of prefixes.filter(shouldScanPrefix).slice(0, 1)) {
192
+ const urls = Array.from({ length: 254 }, (_, index) => `http://${prefix}.${index + 1}:${defaultOllamaPort}`);
193
+ const results = await runPool(urls, 96, (url) => checkOllamaHost(url, {
194
+ label: `lan-${new URL(url).hostname}`,
195
+ source: "discovered",
196
+ kind: "lan",
197
+ timeoutMs: 180
198
+ }));
199
+ for (const host of results.filter((result) => result !== null)) {
200
+ discoveredHosts.push(host);
201
+ }
202
+ }
203
+ return discoveredHosts;
204
+ }
205
+ async function discoverTailscaleOllamaHosts() {
206
+ const peerCandidates = await getTailscalePeerCandidates();
207
+ if (peerCandidates.length === 0) {
208
+ return [];
209
+ }
210
+ const results = await runPool(peerCandidates, 16, (candidate) => checkOllamaHost(candidate.url, {
211
+ ...candidate,
212
+ timeoutMs: 350
213
+ }));
214
+ return dedupeHosts(results.filter((host) => host !== null));
215
+ }
216
+ async function getTailscalePeerCandidates() {
217
+ try {
218
+ const { stdout } = await execFileAsync("tailscale", ["status", "--json"], {
219
+ timeout: 1200,
220
+ maxBuffer: 1_000_000,
221
+ windowsHide: true
222
+ });
223
+ const payload = JSON.parse(stdout);
224
+ const peers = Object.values(payload.Peer ?? {});
225
+ return dedupeHosts(peers.flatMap((peer) => {
226
+ if (peer.Online === false) {
227
+ return [];
228
+ }
229
+ const tailscaleName = trimTailscaleName(asString(peer.DNSName));
230
+ const deviceName = formatDeviceName(asString(peer.HostName), tailscaleName);
231
+ const os = asString(peer.OS) ?? undefined;
232
+ const tailscaleIps = asStringArray(peer.TailscaleIPs).filter(isTailscaleIpAddress);
233
+ const candidates = [];
234
+ if (tailscaleName) {
235
+ candidates.push(buildHostCandidate(`http://${tailscaleName}:${defaultOllamaPort}`, {
236
+ label: deviceName,
237
+ source: "tailscale",
238
+ deviceName,
239
+ os,
240
+ tailscaleName,
241
+ address: tailscaleIps[0]
242
+ }));
243
+ }
244
+ for (const address of tailscaleIps) {
245
+ candidates.push(buildHostCandidate(`http://${address}:${defaultOllamaPort}`, {
246
+ label: deviceName,
247
+ source: "tailscale",
248
+ deviceName,
249
+ os,
250
+ tailscaleName,
251
+ address
252
+ }));
253
+ }
254
+ return candidates;
255
+ }));
256
+ }
257
+ catch {
258
+ return [];
259
+ }
260
+ }
261
+ function shouldScanPrefix(prefix) {
262
+ return prefix !== "192.168.56" && !prefix.startsWith("172.");
263
+ }
264
+ function scoreNetworkPrefix(prefix) {
265
+ if (prefix.startsWith("192.168.") && prefix !== "192.168.56") {
266
+ return 30;
267
+ }
268
+ if (prefix.startsWith("10.")) {
269
+ return 20;
270
+ }
271
+ if (prefix.startsWith("172.")) {
272
+ return 10;
273
+ }
274
+ return 0;
275
+ }
276
+ async function runPool(inputs, concurrency, worker) {
277
+ const results = [];
278
+ let nextIndex = 0;
279
+ async function runWorker() {
280
+ while (nextIndex < inputs.length) {
281
+ const input = inputs[nextIndex];
282
+ nextIndex += 1;
283
+ results.push(await worker(input));
284
+ }
285
+ }
286
+ await Promise.all(Array.from({ length: Math.min(concurrency, inputs.length) }, () => runWorker()));
287
+ return results;
288
+ }
289
+ function isPrivateIpAddress(address) {
290
+ return /^(10\.|192\.168\.|172\.(1[6-9]|2\d|3[0-1])\.)/.test(address);
291
+ }
292
+ function isTailscaleIpAddress(address) {
293
+ const parts = address.split(".").map((part) => Number.parseInt(part, 10));
294
+ return parts.length === 4 && parts.every((part) => Number.isInteger(part) && part >= 0 && part <= 255) && parts[0] === 100 && parts[1] >= 64 && parts[1] <= 127;
295
+ }
296
+ function isTailscaleHostname(hostname) {
297
+ return hostname.endsWith(".ts.net");
298
+ }
299
+ function isIpAddress(hostname) {
300
+ return /^\d{1,3}(\.\d{1,3}){3}$/.test(hostname);
301
+ }
302
+ function formatDeviceName(hostname, tailscaleName) {
303
+ const candidate = (hostname || tailscaleName || "").trim();
304
+ if (!candidate) {
305
+ return "host";
306
+ }
307
+ const normalizedCandidate = trimTailscaleName(candidate) ?? candidate;
308
+ if (normalizedCandidate === "127.0.0.1" || normalizedCandidate === "localhost") {
309
+ return "local";
310
+ }
311
+ if (isIpAddress(normalizedCandidate)) {
312
+ return normalizedCandidate;
313
+ }
314
+ return normalizedCandidate.split(".")[0] || normalizedCandidate;
315
+ }
316
+ function trimTailscaleName(value) {
317
+ if (!value) {
318
+ return undefined;
319
+ }
320
+ return value.replace(/\.$/, "");
321
+ }
322
+ function asString(value) {
323
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
324
+ }
325
+ function asStringArray(value) {
326
+ return Array.isArray(value) ? value.map(asString).filter((entry) => entry !== null) : [];
327
+ }
328
+ function dedupeHosts(hosts) {
329
+ const seenUrls = new Set();
330
+ return hosts.filter((host) => {
331
+ if (seenUrls.has(host.url)) {
332
+ return false;
333
+ }
334
+ seenUrls.add(host.url);
335
+ return true;
336
+ });
337
+ }
338
+ //# sourceMappingURL=hosts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosts.js","sourceRoot":"","sources":["../../src/tui/hosts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type LocalConversationResult = {
2
+ handled: true;
3
+ tone: "accent" | "warning";
4
+ message: string;
5
+ } | {
6
+ handled: false;
7
+ };
8
+ export declare function routeLocalConversation(task: string, now?: Date): LocalConversationResult;
@@ -0,0 +1,94 @@
1
+ export function routeLocalConversation(task, now = new Date()) {
2
+ const normalizedTask = task.trim().toLowerCase();
3
+ const plainTask = normalizedTask.replace(/[!?.\s]/g, "");
4
+ if (["hi", "hey", "hello", "hallo", "servus", "yo", "moin"].includes(plainTask)) {
5
+ return {
6
+ handled: true,
7
+ tone: "accent",
8
+ message: "Bereit. Sag kurz, welches Projektziel ich anfassen soll."
9
+ };
10
+ }
11
+ if (asksForCurrentTime(normalizedTask)) {
12
+ return {
13
+ handled: true,
14
+ tone: "accent",
15
+ message: `Es ist ${formatLocalTime(now)}.`
16
+ };
17
+ }
18
+ if (asksHowAreYou(normalizedTask)) {
19
+ return {
20
+ handled: true,
21
+ tone: "accent",
22
+ message: "Läuft. Ich bin bereit für den nächsten PatchPilot-Task."
23
+ };
24
+ }
25
+ if (["ok", "okay", "nice", "cool", "danke", "thanks", "thx"].includes(plainTask)) {
26
+ return {
27
+ handled: true,
28
+ tone: "accent",
29
+ message: "Passt."
30
+ };
31
+ }
32
+ const wordCount = task.trim().split(/\s+/).filter(Boolean).length;
33
+ if (wordCount === 1 && looksLikeAmbiguousCodingVerb(plainTask)) {
34
+ return {
35
+ handled: true,
36
+ tone: "warning",
37
+ message: "Was genau soll ich damit machen? Beispiel: `summarize this repository` oder `summarize README.md`."
38
+ };
39
+ }
40
+ if (wordCount <= 2 && !looksLikeCodingTask(normalizedTask)) {
41
+ return {
42
+ handled: true,
43
+ tone: "warning",
44
+ message: "Zu wenig Kontext für den Agenten. Beispiel: `summarize this repository`, `run tests`, oder `add a diff preview`."
45
+ };
46
+ }
47
+ return {
48
+ handled: false
49
+ };
50
+ }
51
+ function looksLikeCodingTask(value) {
52
+ return /\b(add|build|fix|test|run|read|summarize|explain|refactor|implement|create|update|debug|commit|status|diff|search|find|install|rename|remove|write|edit)\b/.test(value);
53
+ }
54
+ function looksLikeAmbiguousCodingVerb(value) {
55
+ return [
56
+ "add",
57
+ "build",
58
+ "fix",
59
+ "test",
60
+ "run",
61
+ "read",
62
+ "summarize",
63
+ "explain",
64
+ "refactor",
65
+ "implement",
66
+ "create",
67
+ "update",
68
+ "debug",
69
+ "commit",
70
+ "diff",
71
+ "search",
72
+ "find",
73
+ "install",
74
+ "rename",
75
+ "remove",
76
+ "write",
77
+ "edit"
78
+ ].includes(value);
79
+ }
80
+ function asksForCurrentTime(value) {
81
+ return /\b(wie spät|uhrzeit|welche uhrzeit|what time|current time|time is it)\b/.test(value);
82
+ }
83
+ function asksHowAreYou(value) {
84
+ return /\b(wie gehts|wie geht es dir|how are you)\b/.test(value);
85
+ }
86
+ function formatLocalTime(value) {
87
+ return new Intl.DateTimeFormat("de-DE", {
88
+ hour: "2-digit",
89
+ minute: "2-digit",
90
+ second: "2-digit",
91
+ timeZoneName: "short"
92
+ }).format(value);
93
+ }
94
+ //# sourceMappingURL=inputRouting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputRouting.js","sourceRoot":"","sources":["../../src/tui/inputRouting.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE;IACnE,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACjD,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAEzD,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAChF,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,0DAA0D;SACpE,CAAC;IACJ,CAAC;IAED,IAAI,kBAAkB,CAAC,cAAc,CAAC,EAAE,CAAC;QACvC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,UAAU,eAAe,CAAC,GAAG,CAAC,GAAG;SAC3C,CAAC;IACJ,CAAC;IAED,IAAI,aAAa,CAAC,cAAc,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,yDAAyD;SACnE,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACjF,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,QAAQ;SAClB,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IAClE,IAAI,SAAS,KAAK,CAAC,IAAI,4BAA4B,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/D,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,oGAAoG;SAC9G,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,cAAc,CAAC,EAAE,CAAC;QAC3D,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,kHAAkH;SAC5H,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,4JAA4J,CAAC,IAAI,CACtK,KAAK,CACN,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B,CAAC,KAAa;IACjD,OAAO;QACL,KAAK;QACL,OAAO;QACP,KAAK;QACL,MAAM;QACN,KAAK;QACL,MAAM;QACN,WAAW;QACX,SAAS;QACT,UAAU;QACV,WAAW;QACX,QAAQ;QACR,QAAQ;QACR,OAAO;QACP,QAAQ;QACR,MAAM;QACN,QAAQ;QACR,MAAM;QACN,SAAS;QACT,QAAQ;QACR,QAAQ;QACR,OAAO;QACP,MAAM;KACP,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACvC,OAAO,yEAAyE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC/F,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,6CAA6C,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,eAAe,CAAC,KAAW;IAClC,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QACtC,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,OAAO;KACtB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function isMacOS(): boolean;
2
+ export declare function isLocalOllamaUrl(url: string): boolean;
@@ -0,0 +1,13 @@
1
+ export function isMacOS() {
2
+ return process.platform === "darwin";
3
+ }
4
+ export function isLocalOllamaUrl(url) {
5
+ try {
6
+ const parsedUrl = new URL(url);
7
+ return ["127.0.0.1", "localhost", "::1"].includes(parsedUrl.hostname);
8
+ }
9
+ catch {
10
+ return false;
11
+ }
12
+ }
13
+ //# sourceMappingURL=platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/tui/platform.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,OAAO;IACrB,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ export type SystemStats = {
2
+ cpuPercent: number | null;
3
+ memoryPercent: number;
4
+ usedMemoryGb: number;
5
+ totalMemoryGb: number;
6
+ };
7
+ export type GpuStats = {
8
+ name: string;
9
+ utilizationPercent: number;
10
+ usedMemoryGb: number;
11
+ totalMemoryGb: number;
12
+ temperatureCelsius: number | null;
13
+ powerDrawWatts: number | null;
14
+ powerLimitWatts: number | null;
15
+ };
16
+ type CpuSnapshot = {
17
+ idle: number;
18
+ total: number;
19
+ };
20
+ export declare function readSystemStats(previousSnapshot?: CpuSnapshot): {
21
+ stats: SystemStats;
22
+ snapshot: CpuSnapshot;
23
+ };
24
+ export declare function readGpuStats(): Promise<GpuStats | null>;
25
+ export {};
@@ -0,0 +1,88 @@
1
+ import { cpus, freemem, totalmem } from "node:os";
2
+ import { execFile } from "node:child_process";
3
+ import { promisify } from "node:util";
4
+ const execFileAsync = promisify(execFile);
5
+ const gpuStatsRetryDelayMs = 60_000;
6
+ let gpuProbeDisabledUntil = 0;
7
+ export function readSystemStats(previousSnapshot) {
8
+ const snapshot = readCpuSnapshot();
9
+ const totalMemory = totalmem();
10
+ const freeMemory = freemem();
11
+ const usedMemory = totalMemory - freeMemory;
12
+ return {
13
+ snapshot,
14
+ stats: {
15
+ cpuPercent: previousSnapshot ? calculateCpuPercent(previousSnapshot, snapshot) : null,
16
+ memoryPercent: Math.round((usedMemory / totalMemory) * 100),
17
+ usedMemoryGb: bytesToGb(usedMemory),
18
+ totalMemoryGb: bytesToGb(totalMemory)
19
+ }
20
+ };
21
+ }
22
+ function readCpuSnapshot() {
23
+ return cpus().reduce((snapshot, cpu) => {
24
+ const idle = cpu.times.idle;
25
+ const total = Object.values(cpu.times).reduce((sum, value) => sum + value, 0);
26
+ return {
27
+ idle: snapshot.idle + idle,
28
+ total: snapshot.total + total
29
+ };
30
+ }, {
31
+ idle: 0,
32
+ total: 0
33
+ });
34
+ }
35
+ function calculateCpuPercent(previousSnapshot, currentSnapshot) {
36
+ const idleDelta = currentSnapshot.idle - previousSnapshot.idle;
37
+ const totalDelta = currentSnapshot.total - previousSnapshot.total;
38
+ if (totalDelta <= 0) {
39
+ return 0;
40
+ }
41
+ return Math.max(0, Math.min(100, Math.round((1 - idleDelta / totalDelta) * 100)));
42
+ }
43
+ function bytesToGb(value) {
44
+ return Math.round((value / 1024 ** 3) * 10) / 10;
45
+ }
46
+ export async function readGpuStats() {
47
+ if (Date.now() < gpuProbeDisabledUntil) {
48
+ return null;
49
+ }
50
+ try {
51
+ const { stdout } = await execFileAsync("nvidia-smi", [
52
+ "--query-gpu=name,utilization.gpu,memory.used,memory.total,temperature.gpu,power.draw,power.limit",
53
+ "--format=csv,noheader,nounits"
54
+ ]);
55
+ const firstGpuLine = stdout.trim().split(/\r?\n/)[0];
56
+ if (!firstGpuLine) {
57
+ return null;
58
+ }
59
+ const [name, utilization, memoryUsed, memoryTotal, temperature, powerDraw, powerLimit] = firstGpuLine
60
+ .split(",")
61
+ .map((value) => value.trim());
62
+ return {
63
+ name,
64
+ utilizationPercent: readNumber(utilization),
65
+ usedMemoryGb: mibToGb(readNumber(memoryUsed)),
66
+ totalMemoryGb: mibToGb(readNumber(memoryTotal)),
67
+ temperatureCelsius: readNullableNumber(temperature),
68
+ powerDrawWatts: readNullableNumber(powerDraw),
69
+ powerLimitWatts: readNullableNumber(powerLimit)
70
+ };
71
+ }
72
+ catch {
73
+ gpuProbeDisabledUntil = Date.now() + gpuStatsRetryDelayMs;
74
+ return null;
75
+ }
76
+ }
77
+ function mibToGb(value) {
78
+ return Math.round((value / 1024) * 10) / 10;
79
+ }
80
+ function readNumber(value) {
81
+ const parsedValue = Number.parseFloat(value ?? "0");
82
+ return Number.isFinite(parsedValue) ? parsedValue : 0;
83
+ }
84
+ function readNullableNumber(value) {
85
+ const parsedValue = Number.parseFloat(value ?? "");
86
+ return Number.isFinite(parsedValue) ? parsedValue : null;
87
+ }
88
+ //# sourceMappingURL=systemStats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemStats.js","sourceRoot":"","sources":["../../src/tui/systemStats.ts"],"names":[],"mappings":"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"}