@gitkraken/core-gitlens 0.3.0 → 0.3.1

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 (170) hide show
  1. package/CHANGELOG.md +8 -1
  2. package/dist/git/cache.d.ts +12 -6
  3. package/dist/git/cache.d.ts.map +1 -1
  4. package/dist/git/cache.js +40 -39
  5. package/dist/git/cache.js.map +1 -1
  6. package/dist/git/context.d.ts +19 -0
  7. package/dist/git/context.d.ts.map +1 -1
  8. package/dist/git/context.js.map +1 -1
  9. package/dist/git/features.d.ts +1 -1
  10. package/dist/git/features.d.ts.map +1 -1
  11. package/dist/git/features.js +1 -0
  12. package/dist/git/features.js.map +1 -1
  13. package/dist/git/models/graph.d.ts +96 -0
  14. package/dist/git/models/graph.d.ts.map +1 -1
  15. package/dist/git/models/graph.js +24 -1
  16. package/dist/git/models/graph.js.map +1 -1
  17. package/dist/git/models/remoteProvider.d.ts +1 -0
  18. package/dist/git/models/remoteProvider.d.ts.map +1 -1
  19. package/dist/git/models/remoteProvider.js.map +1 -1
  20. package/dist/git/models/repository.d.ts +21 -12
  21. package/dist/git/models/repository.d.ts.map +1 -1
  22. package/dist/git/models/repository.js +70 -84
  23. package/dist/git/models/repository.js.map +1 -1
  24. package/dist/git/models/statusFile.d.ts +9 -0
  25. package/dist/git/models/statusFile.d.ts.map +1 -1
  26. package/dist/git/models/statusFile.js +11 -0
  27. package/dist/git/models/statusFile.js.map +1 -1
  28. package/dist/git/providers/commits.d.ts +4 -0
  29. package/dist/git/providers/commits.d.ts.map +1 -1
  30. package/dist/git/providers/config.d.ts +1 -3
  31. package/dist/git/providers/config.d.ts.map +1 -1
  32. package/dist/git/providers/operations.d.ts +39 -13
  33. package/dist/git/providers/operations.d.ts.map +1 -1
  34. package/dist/git/remotes/custom.d.ts +2 -0
  35. package/dist/git/remotes/custom.d.ts.map +1 -1
  36. package/dist/git/remotes/custom.js +20 -0
  37. package/dist/git/remotes/custom.js.map +1 -1
  38. package/dist/git/utils/contributor.utils.d.ts +3 -0
  39. package/dist/git/utils/contributor.utils.d.ts.map +1 -1
  40. package/dist/git/utils/contributor.utils.js +22 -0
  41. package/dist/git/utils/contributor.utils.js.map +1 -1
  42. package/dist/git/utils/reachability.utils.d.ts +37 -0
  43. package/dist/git/utils/reachability.utils.d.ts.map +1 -0
  44. package/dist/git/utils/reachability.utils.js +96 -0
  45. package/dist/git/utils/reachability.utils.js.map +1 -0
  46. package/dist/git/watching/watchService.d.ts +4 -2
  47. package/dist/git/watching/watchService.d.ts.map +1 -1
  48. package/dist/git/watching/watchService.js +8 -3
  49. package/dist/git/watching/watchService.js.map +1 -1
  50. package/dist/git/watching/watchSession.d.ts +14 -12
  51. package/dist/git/watching/watchSession.d.ts.map +1 -1
  52. package/dist/git/watching/watchSession.js +56 -55
  53. package/dist/git/watching/watchSession.js.map +1 -1
  54. package/dist/git-cli/providers/branches.d.ts.map +1 -1
  55. package/dist/git-cli/providers/branches.js +1 -0
  56. package/dist/git-cli/providers/branches.js.map +1 -1
  57. package/dist/git-cli/providers/commits.d.ts +1 -0
  58. package/dist/git-cli/providers/commits.d.ts.map +1 -1
  59. package/dist/git-cli/providers/commits.js +12 -0
  60. package/dist/git-cli/providers/commits.js.map +1 -1
  61. package/dist/git-cli/providers/config.d.ts +8 -4
  62. package/dist/git-cli/providers/config.d.ts.map +1 -1
  63. package/dist/git-cli/providers/config.js +62 -39
  64. package/dist/git-cli/providers/config.js.map +1 -1
  65. package/dist/git-cli/providers/diff.d.ts.map +1 -1
  66. package/dist/git-cli/providers/diff.js +1 -1
  67. package/dist/git-cli/providers/diff.js.map +1 -1
  68. package/dist/git-cli/providers/graph.d.ts.map +1 -1
  69. package/dist/git-cli/providers/graph.js +132 -14
  70. package/dist/git-cli/providers/graph.js.map +1 -1
  71. package/dist/git-cli/providers/operations.d.ts +6 -5
  72. package/dist/git-cli/providers/operations.d.ts.map +1 -1
  73. package/dist/git-cli/providers/operations.js +97 -95
  74. package/dist/git-cli/providers/operations.js.map +1 -1
  75. package/dist/git-cli/providers/stash.d.ts.map +1 -1
  76. package/dist/git-cli/providers/stash.js +20 -2
  77. package/dist/git-cli/providers/stash.js.map +1 -1
  78. package/dist/git-cli/providers/status.d.ts.map +1 -1
  79. package/dist/git-cli/providers/status.js +5 -2
  80. package/dist/git-cli/providers/status.js.map +1 -1
  81. package/dist/ipc/discovery.d.ts +22 -0
  82. package/dist/ipc/discovery.d.ts.map +1 -1
  83. package/dist/ipc/discovery.js +111 -2
  84. package/dist/ipc/discovery.js.map +1 -1
  85. package/dist/plus/agents/providers/claudeCodeProvider.d.ts +73 -20
  86. package/dist/plus/agents/providers/claudeCodeProvider.d.ts.map +1 -1
  87. package/dist/plus/agents/providers/claudeCodeProvider.js +394 -88
  88. package/dist/plus/agents/providers/claudeCodeProvider.js.map +1 -1
  89. package/dist/plus/agents/types.d.ts +62 -11
  90. package/dist/plus/agents/types.d.ts.map +1 -1
  91. package/dist/plus/ai/models/model.d.ts +1 -1
  92. package/dist/plus/ai/models/model.d.ts.map +1 -1
  93. package/dist/plus/ai/models/model.js.map +1 -1
  94. package/dist/plus/ai/models/provider.d.ts +3 -0
  95. package/dist/plus/ai/models/provider.d.ts.map +1 -1
  96. package/dist/plus/ai/providers/gitkrakenProvider.d.ts +1 -1
  97. package/dist/plus/ai/providers/gitkrakenProvider.d.ts.map +1 -1
  98. package/dist/plus/ai/providers/gitkrakenProvider.js +4 -1
  99. package/dist/plus/ai/providers/gitkrakenProvider.js.map +1 -1
  100. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts +4 -3
  101. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts.map +1 -1
  102. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +9 -6
  103. package/dist/plus/ai/providers/openAICompatibleProviderBase.js.map +1 -1
  104. package/dist/plus/ai/utils/ai.utils.d.ts.map +1 -1
  105. package/dist/plus/ai/utils/ai.utils.js +2 -0
  106. package/dist/plus/ai/utils/ai.utils.js.map +1 -1
  107. package/dist/plus/git-github/api/github.d.ts +2 -0
  108. package/dist/plus/git-github/api/github.d.ts.map +1 -1
  109. package/dist/plus/git-github/api/github.js +93 -6
  110. package/dist/plus/git-github/api/github.js.map +1 -1
  111. package/dist/plus/git-github/providers/github/refs.js +1 -1
  112. package/dist/utils/date.d.ts.map +1 -1
  113. package/dist/utils/date.js +6 -0
  114. package/dist/utils/date.js.map +1 -1
  115. package/dist/utils/debounce.js +1 -1
  116. package/dist/utils/iterable.d.ts +7 -1
  117. package/dist/utils/iterable.d.ts.map +1 -1
  118. package/dist/utils/iterable.js +12 -4
  119. package/dist/utils/iterable.js.map +1 -1
  120. package/dist/utils/object.d.ts +22 -1
  121. package/dist/utils/object.d.ts.map +1 -1
  122. package/dist/utils/object.js +56 -3
  123. package/dist/utils/object.js.map +1 -1
  124. package/dist/utils/paging.js +14 -15
  125. package/dist/utils/paging.js.map +1 -1
  126. package/dist/utils/promiseCache.d.ts.map +1 -1
  127. package/dist/utils/promiseCache.js +12 -4
  128. package/dist/utils/promiseCache.js.map +1 -1
  129. package/dist/utils/string.js +1 -1
  130. package/package.json +1 -1
  131. package/src/git/cache.ts +58 -70
  132. package/src/git/context.ts +21 -0
  133. package/src/git/features.ts +2 -0
  134. package/src/git/models/graph.ts +97 -0
  135. package/src/git/models/remoteProvider.ts +1 -0
  136. package/src/git/models/repository.ts +84 -93
  137. package/src/git/models/statusFile.ts +12 -0
  138. package/src/git/providers/commits.ts +4 -0
  139. package/src/git/providers/config.ts +1 -5
  140. package/src/git/providers/operations.ts +42 -22
  141. package/src/git/remotes/custom.ts +23 -0
  142. package/src/git/utils/contributor.utils.ts +24 -0
  143. package/src/git/utils/reachability.utils.ts +109 -0
  144. package/src/git/watching/watchService.ts +9 -4
  145. package/src/git/watching/watchSession.ts +61 -55
  146. package/src/git-cli/providers/branches.ts +1 -0
  147. package/src/git-cli/providers/commits.ts +24 -0
  148. package/src/git-cli/providers/config.ts +63 -49
  149. package/src/git-cli/providers/diff.ts +2 -1
  150. package/src/git-cli/providers/graph.ts +145 -14
  151. package/src/git-cli/providers/operations.ts +118 -130
  152. package/src/git-cli/providers/stash.ts +20 -2
  153. package/src/git-cli/providers/status.ts +11 -3
  154. package/src/ipc/discovery.ts +132 -2
  155. package/src/plus/agents/providers/claudeCodeProvider.ts +430 -90
  156. package/src/plus/agents/types.ts +59 -11
  157. package/src/plus/ai/models/model.ts +1 -0
  158. package/src/plus/ai/models/provider.ts +7 -1
  159. package/src/plus/ai/providers/gitkrakenProvider.ts +4 -0
  160. package/src/plus/ai/providers/openAICompatibleProviderBase.ts +21 -4
  161. package/src/plus/ai/utils/ai.utils.ts +2 -0
  162. package/src/plus/git-github/api/github.ts +120 -8
  163. package/src/plus/git-github/providers/github/refs.ts +1 -1
  164. package/src/utils/date.ts +5 -0
  165. package/src/utils/debounce.ts +1 -1
  166. package/src/utils/iterable.ts +14 -3
  167. package/src/utils/object.ts +55 -4
  168. package/src/utils/paging.ts +14 -14
  169. package/src/utils/promiseCache.ts +24 -16
  170. package/src/utils/string.ts +1 -1
@@ -43,7 +43,15 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
43
43
 
44
44
  const porcelainVersion = (await this.git.supports('git:status:porcelain-v2')) ? 2 : 1;
45
45
 
46
- const result = await this.statusCore(repoPath, porcelainVersion, { priority: options?.priority }, cancellation);
46
+ const result = await this.statusCore(
47
+ repoPath,
48
+ porcelainVersion,
49
+ {
50
+ similarityThreshold: this.context.config?.commits.similarityThreshold,
51
+ priority: options?.priority,
52
+ },
53
+ cancellation,
54
+ );
47
55
  const repoUri = fileUri(normalizePath(repoPath));
48
56
  const status = parseGitStatus(result.stdout, repoPath, porcelainVersion, p =>
49
57
  joinUriPath(repoUri, normalizePath(p)),
@@ -111,7 +119,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
111
119
  const result = await this.statusCore(
112
120
  repoPath,
113
121
  porcelainVersion,
114
- {},
122
+ { similarityThreshold: this.context.config?.commits.similarityThreshold },
115
123
  cancellation,
116
124
  // If we want renames, don't include the path as Git won't do rename detection
117
125
  ...(renames ? [] : [relativePath]),
@@ -135,7 +143,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
135
143
  private async statusCore(
136
144
  repoPath: string,
137
145
  porcelainVersion: number = 1,
138
- options?: { similarityThreshold?: number; priority?: GitCommandPriority },
146
+ options?: { similarityThreshold?: number | null; priority?: GitCommandPriority },
139
147
  cancellation?: AbortSignal,
140
148
  ...pathspecs: string[]
141
149
  ): Promise<GitResult> {
@@ -1,7 +1,7 @@
1
- import { mkdir, unlink, writeFile } from 'fs/promises';
1
+ import { mkdir, readdir, readFile, unlink, writeFile } from 'fs/promises';
2
2
  import { tmpdir } from 'os';
3
3
  import { join } from 'path';
4
- import { ppid } from 'process';
4
+ import { kill, ppid } from 'process';
5
5
 
6
6
  /**
7
7
  * Directory scanned by `gk` binaries (and `@gitkraken/core-gitlens` consumers) for the
@@ -34,6 +34,16 @@ export function getDiscoveryFileName(port: number): string {
34
34
  return `gitlens-ipc-server-${ppid}-${port}.json`;
35
35
  }
36
36
 
37
+ const discoveryFileNameRegex = /^gitlens-ipc-server-(\d+)-(\d+)\.json$/;
38
+
39
+ /** Parses a discovery file name back into its `ppid`/`port` parts; returns `undefined` if it doesn't match. */
40
+ export function parseDiscoveryFileName(name: string): { ppid: number; port: number } | undefined {
41
+ const match = discoveryFileNameRegex.exec(name);
42
+ if (match == null) return undefined;
43
+
44
+ return { ppid: Number(match[1]), port: Number(match[2]) };
45
+ }
46
+
37
47
  export function getDiscoveryFilePath(dir: string, port: number): string {
38
48
  return join(dir, getDiscoveryFileName(port));
39
49
  }
@@ -54,3 +64,123 @@ export async function cleanupDiscoveryFile(filePath: string | undefined): Promis
54
64
  // Ignore cleanup errors
55
65
  }
56
66
  }
67
+
68
+ export interface SweepDiscoveryFilesOptions {
69
+ /** Ports to never touch (e.g. our own live server). */
70
+ excludePorts?: number[];
71
+ /** Absolute file paths to never touch (e.g. our own files). */
72
+ excludePaths?: string[];
73
+ }
74
+
75
+ /**
76
+ * Best-effort sweep of orphaned discovery files left by processes that crashed or were
77
+ * hard-killed without cleaning up. Reachability is the source of truth: a file is removed
78
+ * only when its owning process is provably gone (pid reports `ESRCH`) or its server is
79
+ * unreachable (the probe fails with anything other than a timeout). Anything reachable — or
80
+ * ambiguous (timeouts, parse errors) — is kept, so a live peer's file is never deleted.
81
+ */
82
+ export async function sweepStaleDiscoveryFiles(
83
+ dirs: string[],
84
+ options?: SweepDiscoveryFilesOptions,
85
+ ): Promise<{ scanned: number; pruned: number }> {
86
+ const excludePorts = options?.excludePorts;
87
+ const excludePaths = options?.excludePaths;
88
+
89
+ let scanned = 0;
90
+ let pruned = 0;
91
+
92
+ for (const dir of dirs) {
93
+ let names: string[];
94
+ try {
95
+ names = await readdir(dir);
96
+ } catch {
97
+ // Dir doesn't exist yet (nothing ever published here) — nothing to sweep.
98
+ continue;
99
+ }
100
+
101
+ const candidates: string[] = [];
102
+ for (const name of names) {
103
+ const parsed = parseDiscoveryFileName(name);
104
+ if (parsed == null) continue;
105
+ if (excludePorts?.includes(parsed.port)) continue;
106
+
107
+ const filePath = join(dir, name);
108
+ if (excludePaths?.includes(filePath)) continue;
109
+
110
+ candidates.push(filePath);
111
+ }
112
+
113
+ scanned += candidates.length;
114
+
115
+ const results = await Promise.allSettled(
116
+ candidates.map(async filePath => {
117
+ if (await isDiscoveryFileStale(filePath)) {
118
+ await cleanupDiscoveryFile(filePath);
119
+ return true;
120
+ }
121
+ return false;
122
+ }),
123
+ );
124
+
125
+ for (const r of results) {
126
+ if (r.status === 'fulfilled' && r.value) {
127
+ pruned++;
128
+ }
129
+ }
130
+ }
131
+
132
+ return { scanned: scanned, pruned: pruned };
133
+ }
134
+
135
+ /** Returns true only when the file's server is provably gone (dead pid or unreachable server). */
136
+ async function isDiscoveryFileStale(filePath: string): Promise<boolean> {
137
+ let data: IpcDiscoveryData;
138
+ try {
139
+ data = JSON.parse(await readFile(filePath, 'utf8')) as IpcDiscoveryData;
140
+ } catch {
141
+ // Can't read/parse — don't delete files we don't understand.
142
+ return false;
143
+ }
144
+
145
+ // Cheap short-circuit: if the owning process is gone, the file is orphaned.
146
+ if (data.pid != null && !isProcessAlive(data.pid)) return true;
147
+
148
+ // Otherwise reachability is the source of truth.
149
+ if (!data.address) return false;
150
+
151
+ try {
152
+ await fetch(`${data.address}/ping`, { signal: AbortSignal.timeout(1000) });
153
+ // Any HTTP response (even 401/404) means a server is listening — keep.
154
+ return false;
155
+ } catch (ex) {
156
+ // A timeout is ambiguous — the server may be alive but slow to answer — so keep. Any other
157
+ // failure (connection refused, reset, host unreachable, bad address) means nothing is
158
+ // serving on that localhost port, so the file is stale. A healthy local server always
159
+ // answers near-instantly, so this never deletes a reachable peer.
160
+ return !isTimeoutError(ex);
161
+ }
162
+ }
163
+
164
+ function isProcessAlive(pid: number): boolean {
165
+ // `kill(0, ...)` / `kill(<negative>, ...)` have process-group semantics and don't probe a
166
+ // specific pid, so a malformed pid (from a foreign or corrupt file) can't prove death — treat
167
+ // it as inconclusive so the sweep falls through to the reachability probe rather than deleting
168
+ // on a bad pid. (Note: the agents session-card tracker's `isProcessAlive` biases the opposite
169
+ // way — toward dead — because expiring a live card there is harmless; deleting a live file is
170
+ // not, so this copy intentionally keeps on uncertainty.)
171
+ if (!Number.isInteger(pid) || pid <= 0) return true;
172
+
173
+ try {
174
+ kill(pid, 0);
175
+ return true;
176
+ } catch (ex) {
177
+ // ESRCH → no such process (dead). EPERM/EACCES → exists but not ours (alive). Anything
178
+ // else is inconclusive → treat as alive so we never delete a file on uncertainty.
179
+ return (ex as NodeJS.ErrnoException | null)?.code !== 'ESRCH';
180
+ }
181
+ }
182
+
183
+ function isTimeoutError(ex: unknown): boolean {
184
+ // `AbortSignal.timeout` rejects with a `TimeoutError`; a bare abort yields an `AbortError`.
185
+ return ex instanceof Error && (ex.name === 'TimeoutError' || ex.name === 'AbortError');
186
+ }