@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.
- package/CHANGELOG.md +8 -1
- package/dist/git/cache.d.ts +12 -6
- package/dist/git/cache.d.ts.map +1 -1
- package/dist/git/cache.js +40 -39
- package/dist/git/cache.js.map +1 -1
- package/dist/git/context.d.ts +19 -0
- package/dist/git/context.d.ts.map +1 -1
- package/dist/git/context.js.map +1 -1
- package/dist/git/features.d.ts +1 -1
- package/dist/git/features.d.ts.map +1 -1
- package/dist/git/features.js +1 -0
- package/dist/git/features.js.map +1 -1
- package/dist/git/models/graph.d.ts +96 -0
- package/dist/git/models/graph.d.ts.map +1 -1
- package/dist/git/models/graph.js +24 -1
- package/dist/git/models/graph.js.map +1 -1
- package/dist/git/models/remoteProvider.d.ts +1 -0
- package/dist/git/models/remoteProvider.d.ts.map +1 -1
- package/dist/git/models/remoteProvider.js.map +1 -1
- package/dist/git/models/repository.d.ts +21 -12
- package/dist/git/models/repository.d.ts.map +1 -1
- package/dist/git/models/repository.js +70 -84
- package/dist/git/models/repository.js.map +1 -1
- package/dist/git/models/statusFile.d.ts +9 -0
- package/dist/git/models/statusFile.d.ts.map +1 -1
- package/dist/git/models/statusFile.js +11 -0
- package/dist/git/models/statusFile.js.map +1 -1
- package/dist/git/providers/commits.d.ts +4 -0
- package/dist/git/providers/commits.d.ts.map +1 -1
- package/dist/git/providers/config.d.ts +1 -3
- package/dist/git/providers/config.d.ts.map +1 -1
- package/dist/git/providers/operations.d.ts +39 -13
- package/dist/git/providers/operations.d.ts.map +1 -1
- package/dist/git/remotes/custom.d.ts +2 -0
- package/dist/git/remotes/custom.d.ts.map +1 -1
- package/dist/git/remotes/custom.js +20 -0
- package/dist/git/remotes/custom.js.map +1 -1
- package/dist/git/utils/contributor.utils.d.ts +3 -0
- package/dist/git/utils/contributor.utils.d.ts.map +1 -1
- package/dist/git/utils/contributor.utils.js +22 -0
- package/dist/git/utils/contributor.utils.js.map +1 -1
- package/dist/git/utils/reachability.utils.d.ts +37 -0
- package/dist/git/utils/reachability.utils.d.ts.map +1 -0
- package/dist/git/utils/reachability.utils.js +96 -0
- package/dist/git/utils/reachability.utils.js.map +1 -0
- package/dist/git/watching/watchService.d.ts +4 -2
- package/dist/git/watching/watchService.d.ts.map +1 -1
- package/dist/git/watching/watchService.js +8 -3
- package/dist/git/watching/watchService.js.map +1 -1
- package/dist/git/watching/watchSession.d.ts +14 -12
- package/dist/git/watching/watchSession.d.ts.map +1 -1
- package/dist/git/watching/watchSession.js +56 -55
- package/dist/git/watching/watchSession.js.map +1 -1
- package/dist/git-cli/providers/branches.d.ts.map +1 -1
- package/dist/git-cli/providers/branches.js +1 -0
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.d.ts +1 -0
- package/dist/git-cli/providers/commits.d.ts.map +1 -1
- package/dist/git-cli/providers/commits.js +12 -0
- package/dist/git-cli/providers/commits.js.map +1 -1
- package/dist/git-cli/providers/config.d.ts +8 -4
- package/dist/git-cli/providers/config.d.ts.map +1 -1
- package/dist/git-cli/providers/config.js +62 -39
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/git-cli/providers/diff.d.ts.map +1 -1
- package/dist/git-cli/providers/diff.js +1 -1
- package/dist/git-cli/providers/diff.js.map +1 -1
- package/dist/git-cli/providers/graph.d.ts.map +1 -1
- package/dist/git-cli/providers/graph.js +132 -14
- package/dist/git-cli/providers/graph.js.map +1 -1
- package/dist/git-cli/providers/operations.d.ts +6 -5
- package/dist/git-cli/providers/operations.d.ts.map +1 -1
- package/dist/git-cli/providers/operations.js +97 -95
- package/dist/git-cli/providers/operations.js.map +1 -1
- package/dist/git-cli/providers/stash.d.ts.map +1 -1
- package/dist/git-cli/providers/stash.js +20 -2
- package/dist/git-cli/providers/stash.js.map +1 -1
- package/dist/git-cli/providers/status.d.ts.map +1 -1
- package/dist/git-cli/providers/status.js +5 -2
- package/dist/git-cli/providers/status.js.map +1 -1
- package/dist/ipc/discovery.d.ts +22 -0
- package/dist/ipc/discovery.d.ts.map +1 -1
- package/dist/ipc/discovery.js +111 -2
- package/dist/ipc/discovery.js.map +1 -1
- package/dist/plus/agents/providers/claudeCodeProvider.d.ts +73 -20
- package/dist/plus/agents/providers/claudeCodeProvider.d.ts.map +1 -1
- package/dist/plus/agents/providers/claudeCodeProvider.js +394 -88
- package/dist/plus/agents/providers/claudeCodeProvider.js.map +1 -1
- package/dist/plus/agents/types.d.ts +62 -11
- package/dist/plus/agents/types.d.ts.map +1 -1
- package/dist/plus/ai/models/model.d.ts +1 -1
- package/dist/plus/ai/models/model.d.ts.map +1 -1
- package/dist/plus/ai/models/model.js.map +1 -1
- package/dist/plus/ai/models/provider.d.ts +3 -0
- package/dist/plus/ai/models/provider.d.ts.map +1 -1
- package/dist/plus/ai/providers/gitkrakenProvider.d.ts +1 -1
- package/dist/plus/ai/providers/gitkrakenProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/gitkrakenProvider.js +4 -1
- package/dist/plus/ai/providers/gitkrakenProvider.js.map +1 -1
- package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts +4 -3
- package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts.map +1 -1
- package/dist/plus/ai/providers/openAICompatibleProviderBase.js +9 -6
- package/dist/plus/ai/providers/openAICompatibleProviderBase.js.map +1 -1
- package/dist/plus/ai/utils/ai.utils.d.ts.map +1 -1
- package/dist/plus/ai/utils/ai.utils.js +2 -0
- package/dist/plus/ai/utils/ai.utils.js.map +1 -1
- package/dist/plus/git-github/api/github.d.ts +2 -0
- package/dist/plus/git-github/api/github.d.ts.map +1 -1
- package/dist/plus/git-github/api/github.js +93 -6
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/providers/github/refs.js +1 -1
- package/dist/utils/date.d.ts.map +1 -1
- package/dist/utils/date.js +6 -0
- package/dist/utils/date.js.map +1 -1
- package/dist/utils/debounce.js +1 -1
- package/dist/utils/iterable.d.ts +7 -1
- package/dist/utils/iterable.d.ts.map +1 -1
- package/dist/utils/iterable.js +12 -4
- package/dist/utils/iterable.js.map +1 -1
- package/dist/utils/object.d.ts +22 -1
- package/dist/utils/object.d.ts.map +1 -1
- package/dist/utils/object.js +56 -3
- package/dist/utils/object.js.map +1 -1
- package/dist/utils/paging.js +14 -15
- package/dist/utils/paging.js.map +1 -1
- package/dist/utils/promiseCache.d.ts.map +1 -1
- package/dist/utils/promiseCache.js +12 -4
- package/dist/utils/promiseCache.js.map +1 -1
- package/dist/utils/string.js +1 -1
- package/package.json +1 -1
- package/src/git/cache.ts +58 -70
- package/src/git/context.ts +21 -0
- package/src/git/features.ts +2 -0
- package/src/git/models/graph.ts +97 -0
- package/src/git/models/remoteProvider.ts +1 -0
- package/src/git/models/repository.ts +84 -93
- package/src/git/models/statusFile.ts +12 -0
- package/src/git/providers/commits.ts +4 -0
- package/src/git/providers/config.ts +1 -5
- package/src/git/providers/operations.ts +42 -22
- package/src/git/remotes/custom.ts +23 -0
- package/src/git/utils/contributor.utils.ts +24 -0
- package/src/git/utils/reachability.utils.ts +109 -0
- package/src/git/watching/watchService.ts +9 -4
- package/src/git/watching/watchSession.ts +61 -55
- package/src/git-cli/providers/branches.ts +1 -0
- package/src/git-cli/providers/commits.ts +24 -0
- package/src/git-cli/providers/config.ts +63 -49
- package/src/git-cli/providers/diff.ts +2 -1
- package/src/git-cli/providers/graph.ts +145 -14
- package/src/git-cli/providers/operations.ts +118 -130
- package/src/git-cli/providers/stash.ts +20 -2
- package/src/git-cli/providers/status.ts +11 -3
- package/src/ipc/discovery.ts +132 -2
- package/src/plus/agents/providers/claudeCodeProvider.ts +430 -90
- package/src/plus/agents/types.ts +59 -11
- package/src/plus/ai/models/model.ts +1 -0
- package/src/plus/ai/models/provider.ts +7 -1
- package/src/plus/ai/providers/gitkrakenProvider.ts +4 -0
- package/src/plus/ai/providers/openAICompatibleProviderBase.ts +21 -4
- package/src/plus/ai/utils/ai.utils.ts +2 -0
- package/src/plus/git-github/api/github.ts +120 -8
- package/src/plus/git-github/providers/github/refs.ts +1 -1
- package/src/utils/date.ts +5 -0
- package/src/utils/debounce.ts +1 -1
- package/src/utils/iterable.ts +14 -3
- package/src/utils/object.ts +55 -4
- package/src/utils/paging.ts +14 -14
- package/src/utils/promiseCache.ts +24 -16
- 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(
|
|
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> {
|
package/src/ipc/discovery.ts
CHANGED
|
@@ -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
|
+
}
|