@gitkraken/core-gitlens 0.1.0 → 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.
- package/CHANGELOG.md +22 -1
- package/dist/git/cache.d.ts +21 -5
- package/dist/git/cache.d.ts.map +1 -1
- package/dist/git/cache.js +102 -6
- package/dist/git/cache.js.map +1 -1
- package/dist/git/context.d.ts +11 -2
- package/dist/git/context.d.ts.map +1 -1
- package/dist/git/context.js.map +1 -1
- package/dist/git/models/branch.d.ts +1 -0
- package/dist/git/models/branch.d.ts.map +1 -1
- package/dist/git/models/branch.js.map +1 -1
- package/dist/git/models/commit.d.ts +1 -9
- package/dist/git/models/commit.d.ts.map +1 -1
- package/dist/git/models/commit.js +4 -9
- package/dist/git/models/commit.js.map +1 -1
- package/dist/git/models/graph.d.ts +2 -4
- package/dist/git/models/graph.d.ts.map +1 -1
- package/dist/git/models/repository.d.ts +12 -3
- package/dist/git/models/repository.d.ts.map +1 -1
- package/dist/git/models/repository.js +25 -4
- package/dist/git/models/repository.js.map +1 -1
- package/dist/git/models/worktree.d.ts +1 -1
- package/dist/git/models/worktree.d.ts.map +1 -1
- package/dist/git/models/worktree.js +2 -2
- package/dist/git/models/worktree.js.map +1 -1
- package/dist/git/parsers/diffParser.d.ts +0 -1
- package/dist/git/parsers/diffParser.d.ts.map +1 -1
- package/dist/git/parsers/diffParser.js +22 -61
- package/dist/git/parsers/diffParser.js.map +1 -1
- package/dist/git/providers/branches.d.ts +3 -0
- package/dist/git/providers/branches.d.ts.map +1 -1
- package/dist/git/providers/commits.d.ts +6 -0
- package/dist/git/providers/commits.d.ts.map +1 -1
- package/dist/git/providers/config.d.ts +2 -0
- package/dist/git/providers/config.d.ts.map +1 -1
- package/dist/git/providers/diff.d.ts +2 -0
- package/dist/git/providers/diff.d.ts.map +1 -1
- package/dist/git/providers/operations.d.ts +6 -0
- package/dist/git/providers/operations.d.ts.map +1 -1
- package/dist/git/providers/revision.d.ts +1 -1
- package/dist/git/providers/revision.d.ts.map +1 -1
- package/dist/git/providers/staging.d.ts +2 -0
- package/dist/git/providers/staging.d.ts.map +1 -1
- package/dist/git/utils/sorting.d.ts +6 -0
- package/dist/git/utils/sorting.d.ts.map +1 -1
- package/dist/git/utils/sorting.js +19 -0
- package/dist/git/utils/sorting.js.map +1 -1
- package/dist/git-cli/cliGitProvider.js +1 -1
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/exec/git.d.ts +29 -4
- package/dist/git-cli/exec/git.d.ts.map +1 -1
- package/dist/git-cli/exec/git.js +70 -9
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/exec/gitQueue.d.ts +12 -4
- package/dist/git-cli/exec/gitQueue.d.ts.map +1 -1
- package/dist/git-cli/exec/gitQueue.js +49 -12
- package/dist/git-cli/exec/gitQueue.js.map +1 -1
- package/dist/git-cli/parsers/logParser.d.ts +1 -0
- package/dist/git-cli/parsers/logParser.d.ts.map +1 -1
- package/dist/git-cli/parsers/logParser.js +4 -0
- package/dist/git-cli/parsers/logParser.js.map +1 -1
- package/dist/git-cli/providers/blame.js +1 -1
- package/dist/git-cli/providers/blame.js.map +1 -1
- package/dist/git-cli/providers/branches.d.ts +2 -0
- package/dist/git-cli/providers/branches.d.ts.map +1 -1
- package/dist/git-cli/providers/branches.js +176 -123
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.d.ts +4 -0
- package/dist/git-cli/providers/commits.d.ts.map +1 -1
- package/dist/git-cli/providers/commits.js +58 -17
- package/dist/git-cli/providers/commits.js.map +1 -1
- package/dist/git-cli/providers/config.d.ts.map +1 -1
- package/dist/git-cli/providers/config.js +9 -9
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/git-cli/providers/contributors.d.ts.map +1 -1
- package/dist/git-cli/providers/contributors.js +7 -4
- package/dist/git-cli/providers/contributors.js.map +1 -1
- package/dist/git-cli/providers/diff.d.ts +2 -0
- package/dist/git-cli/providers/diff.d.ts.map +1 -1
- package/dist/git-cli/providers/diff.js +89 -19
- 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 +43 -27
- package/dist/git-cli/providers/graph.js.map +1 -1
- package/dist/git-cli/providers/operations.d.ts +17 -0
- package/dist/git-cli/providers/operations.d.ts.map +1 -1
- package/dist/git-cli/providers/operations.js +47 -14
- package/dist/git-cli/providers/operations.js.map +1 -1
- package/dist/git-cli/providers/patch.d.ts.map +1 -1
- package/dist/git-cli/providers/patch.js +15 -30
- package/dist/git-cli/providers/patch.js.map +1 -1
- package/dist/git-cli/providers/pausedOperations.js +6 -6
- package/dist/git-cli/providers/pausedOperations.js.map +1 -1
- package/dist/git-cli/providers/refs.d.ts.map +1 -1
- package/dist/git-cli/providers/refs.js +26 -7
- package/dist/git-cli/providers/refs.js.map +1 -1
- package/dist/git-cli/providers/remotes.js +4 -4
- package/dist/git-cli/providers/remotes.js.map +1 -1
- package/dist/git-cli/providers/revision.d.ts +1 -1
- package/dist/git-cli/providers/revision.d.ts.map +1 -1
- package/dist/git-cli/providers/revision.js +15 -11
- package/dist/git-cli/providers/revision.js.map +1 -1
- package/dist/git-cli/providers/staging.d.ts +2 -0
- package/dist/git-cli/providers/staging.d.ts.map +1 -1
- package/dist/git-cli/providers/staging.js +20 -8
- package/dist/git-cli/providers/staging.js.map +1 -1
- package/dist/git-cli/providers/stash.d.ts +0 -8
- package/dist/git-cli/providers/stash.d.ts.map +1 -1
- package/dist/git-cli/providers/stash.js +63 -119
- package/dist/git-cli/providers/stash.js.map +1 -1
- package/dist/git-cli/providers/status.js +6 -6
- package/dist/git-cli/providers/status.js.map +1 -1
- package/dist/git-cli/providers/tags.js +4 -4
- package/dist/git-cli/providers/tags.js.map +1 -1
- package/dist/git-cli/providers/worktrees.js +3 -3
- package/dist/git-cli/providers/worktrees.js.map +1 -1
- package/dist/plus/ai/constants.d.ts +2 -1
- package/dist/plus/ai/constants.d.ts.map +1 -1
- package/dist/plus/ai/constants.js +7 -0
- package/dist/plus/ai/constants.js.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/promptTemplates.d.ts +19 -2
- package/dist/plus/ai/models/promptTemplates.d.ts.map +1 -1
- package/dist/plus/ai/models/results.d.ts +28 -0
- package/dist/plus/ai/models/results.d.ts.map +1 -1
- package/dist/plus/ai/prompts.d.ts +3 -0
- package/dist/plus/ai/prompts.d.ts.map +1 -1
- package/dist/plus/ai/prompts.js +126 -0
- package/dist/plus/ai/prompts.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/ai/utils/results.utils.d.ts +3 -0
- package/dist/plus/ai/utils/results.utils.d.ts.map +1 -1
- package/dist/plus/ai/utils/results.utils.js +75 -0
- package/dist/plus/ai/utils/results.utils.js.map +1 -1
- package/dist/plus/ai/utils/truncation.utils.d.ts +1 -1
- package/dist/plus/ai/utils/truncation.utils.d.ts.map +1 -1
- package/dist/plus/ai/utils/truncation.utils.js.map +1 -1
- package/dist/plus/git-github/providers/github/branches.d.ts.map +1 -1
- package/dist/plus/git-github/providers/github/branches.js +16 -1
- package/dist/plus/git-github/providers/github/branches.js.map +1 -1
- package/dist/plus/git-github/providers/github/diff.d.ts +2 -0
- package/dist/plus/git-github/providers/github/diff.d.ts.map +1 -1
- package/dist/plus/git-github/providers/github/diff.js.map +1 -1
- package/dist/utils/decorators/log.js +1 -1
- package/dist/utils/decorators/log.js.map +1 -1
- package/dist/utils/decorators/sequentialize.d.ts.map +1 -1
- package/dist/utils/decorators/sequentialize.js +4 -2
- package/dist/utils/decorators/sequentialize.js.map +1 -1
- package/dist/utils/env/node/base64.js.map +1 -1
- package/dist/utils/env/node/exec.js.map +1 -1
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +4 -10
- package/dist/utils/formatter.js.map +1 -1
- package/dist/utils/iterable.js.map +1 -1
- package/dist/utils/lruMap.d.ts +40 -0
- package/dist/utils/lruMap.d.ts.map +1 -0
- package/dist/utils/lruMap.js +81 -0
- package/dist/utils/lruMap.js.map +1 -0
- package/dist/utils/version.d.ts +14 -0
- package/dist/utils/version.d.ts.map +1 -1
- package/dist/utils/version.js +48 -0
- package/dist/utils/version.js.map +1 -1
- package/package.json +1 -1
- package/src/git/cache.ts +179 -13
- package/src/git/context.ts +11 -2
- package/src/git/models/branch.ts +1 -0
- package/src/git/models/commit.ts +1 -17
- package/src/git/models/graph.ts +2 -4
- package/src/git/models/repository.ts +26 -6
- package/src/git/models/worktree.ts +2 -2
- package/src/git/parsers/diffParser.ts +7 -44
- package/src/git/providers/branches.ts +3 -0
- package/src/git/providers/commits.ts +7 -0
- package/src/git/providers/config.ts +2 -0
- package/src/git/providers/diff.ts +8 -2
- package/src/git/providers/operations.ts +10 -3
- package/src/git/providers/revision.ts +5 -1
- package/src/git/providers/staging.ts +2 -0
- package/src/git/utils/sorting.ts +21 -0
- package/src/git-cli/cliGitProvider.ts +1 -1
- package/src/git-cli/exec/git.ts +70 -18
- package/src/git-cli/exec/gitQueue.ts +57 -13
- package/src/git-cli/parsers/logParser.ts +5 -1
- package/src/git-cli/providers/blame.ts +1 -1
- package/src/git-cli/providers/branches.ts +207 -133
- package/src/git-cli/providers/commits.ts +71 -18
- package/src/git-cli/providers/config.ts +9 -14
- package/src/git-cli/providers/contributors.ts +7 -12
- package/src/git-cli/providers/diff.ts +100 -19
- package/src/git-cli/providers/graph.ts +47 -27
- package/src/git-cli/providers/operations.ts +77 -18
- package/src/git-cli/providers/patch.ts +15 -37
- package/src/git-cli/providers/pausedOperations.ts +6 -6
- package/src/git-cli/providers/refs.ts +27 -8
- package/src/git-cli/providers/remotes.ts +4 -4
- package/src/git-cli/providers/revision.ts +20 -13
- package/src/git-cli/providers/staging.ts +18 -8
- package/src/git-cli/providers/stash.ts +67 -134
- package/src/git-cli/providers/status.ts +6 -6
- package/src/git-cli/providers/tags.ts +4 -4
- package/src/git-cli/providers/worktrees.ts +3 -3
- package/src/plus/ai/constants.ts +8 -0
- package/src/plus/ai/models/model.ts +1 -0
- package/src/plus/ai/models/promptTemplates.ts +29 -0
- package/src/plus/ai/models/results.ts +30 -0
- package/src/plus/ai/prompts.ts +129 -0
- package/src/plus/ai/utils/ai.utils.ts +2 -0
- package/src/plus/ai/utils/results.utils.ts +99 -0
- package/src/plus/ai/utils/truncation.utils.ts +3 -1
- package/src/plus/git-github/providers/github/branches.ts +17 -5
- package/src/plus/git-github/providers/github/diff.ts +8 -2
- package/src/utils/decorators/log.ts +1 -1
- package/src/utils/decorators/sequentialize.ts +8 -6
- package/src/utils/env/node/base64.ts +1 -1
- package/src/utils/env/node/exec.ts +2 -2
- package/src/utils/formatter.ts +4 -11
- package/src/utils/iterable.ts +1 -1
- package/src/utils/lruMap.ts +87 -0
- package/src/utils/version.ts +48 -0
|
@@ -142,7 +142,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
|
|
|
142
142
|
);
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
return this.git.
|
|
145
|
+
return this.git.run(
|
|
146
146
|
{
|
|
147
147
|
cwd: repoPath,
|
|
148
148
|
cancellation: cancellation,
|
|
@@ -168,7 +168,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
|
|
|
168
168
|
const staged = options?.staged ?? true;
|
|
169
169
|
const unstaged = options?.unstaged ?? true;
|
|
170
170
|
if (staged || unstaged) {
|
|
171
|
-
const result = await this.git.
|
|
171
|
+
const result = await this.git.run(
|
|
172
172
|
{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },
|
|
173
173
|
'diff',
|
|
174
174
|
'--quiet',
|
|
@@ -218,14 +218,14 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
|
|
|
218
218
|
try {
|
|
219
219
|
const [stagedResult, unstagedResult, untrackedResult] = await Promise.allSettled([
|
|
220
220
|
// Check for staged changes
|
|
221
|
-
this.git.
|
|
221
|
+
this.git.run(
|
|
222
222
|
{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },
|
|
223
223
|
'diff',
|
|
224
224
|
'--quiet',
|
|
225
225
|
'--staged',
|
|
226
226
|
),
|
|
227
227
|
// Check for unstaged changes
|
|
228
|
-
this.git.
|
|
228
|
+
this.git.run({ cwd: repoPath, cancellation: cancellation, errors: 'ignore' }, 'diff', '--quiet'),
|
|
229
229
|
// Check for untracked files
|
|
230
230
|
this.hasUntrackedFiles(repoPath, cancellation),
|
|
231
231
|
]);
|
|
@@ -279,7 +279,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
|
|
|
279
279
|
const scope = getScopedLogger();
|
|
280
280
|
|
|
281
281
|
try {
|
|
282
|
-
const result = await this.git.
|
|
282
|
+
const result = await this.git.run(
|
|
283
283
|
{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },
|
|
284
284
|
'ls-files',
|
|
285
285
|
'-z',
|
|
@@ -337,7 +337,7 @@ export class StatusGitSubProvider implements GitStatusSubProvider {
|
|
|
337
337
|
const scope = getScopedLogger();
|
|
338
338
|
|
|
339
339
|
try {
|
|
340
|
-
const result = await this.git.
|
|
340
|
+
const result = await this.git.run(
|
|
341
341
|
{ cwd: repoPath, cancellation: cancellation, errors: 'ignore' },
|
|
342
342
|
'ls-files',
|
|
343
343
|
'-z',
|
|
@@ -56,7 +56,7 @@ export class TagsGitSubProvider implements GitTagsSubProvider {
|
|
|
56
56
|
try {
|
|
57
57
|
const parser = getTagParser();
|
|
58
58
|
|
|
59
|
-
const result = await this.git.
|
|
59
|
+
const result = await this.git.run(
|
|
60
60
|
{ cwd: repoPath, cancellation: signal },
|
|
61
61
|
'for-each-ref',
|
|
62
62
|
...parser.arguments,
|
|
@@ -130,7 +130,7 @@ export class TagsGitSubProvider implements GitTagsSubProvider {
|
|
|
130
130
|
const params: string[] = ['tag', '--format=%(refname:short)'];
|
|
131
131
|
params.push(options?.mode === 'pointsAt' ? `--points-at=${sha}` : `--contains=${sha}`);
|
|
132
132
|
|
|
133
|
-
return this.git.
|
|
133
|
+
return this.git.run(
|
|
134
134
|
{
|
|
135
135
|
cwd: repoPath,
|
|
136
136
|
cancellation: cancellation,
|
|
@@ -149,7 +149,7 @@ export class TagsGitSubProvider implements GitTagsSubProvider {
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
try {
|
|
152
|
-
await this.git.
|
|
152
|
+
await this.git.run({ cwd: repoPath }, ...args);
|
|
153
153
|
this.context.hooks?.cache?.onReset?.(repoPath, 'tags');
|
|
154
154
|
this.context.hooks?.repository?.onChanged?.(repoPath, ['tags']);
|
|
155
155
|
} catch (ex) {
|
|
@@ -170,7 +170,7 @@ export class TagsGitSubProvider implements GitTagsSubProvider {
|
|
|
170
170
|
const args = ['tag', '-d', name];
|
|
171
171
|
|
|
172
172
|
try {
|
|
173
|
-
await this.git.
|
|
173
|
+
await this.git.run({ cwd: repoPath }, ...args);
|
|
174
174
|
this.context.hooks?.cache?.onReset?.(repoPath, 'tags');
|
|
175
175
|
this.context.hooks?.repository?.onChanged?.(repoPath, ['tags']);
|
|
176
176
|
} catch (ex) {
|
|
@@ -49,7 +49,7 @@ export class WorktreesGitSubProvider implements GitWorktreesSubProvider {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
try {
|
|
52
|
-
await this.git.
|
|
52
|
+
await this.git.run({ cwd: repoPath }, ...args);
|
|
53
53
|
|
|
54
54
|
this.context.hooks?.cache?.onReset?.(
|
|
55
55
|
repoPath,
|
|
@@ -106,7 +106,7 @@ export class WorktreesGitSubProvider implements GitWorktreesSubProvider {
|
|
|
106
106
|
// Prefer the aggregate signal from the cache; fall back to the caller's cancellation.
|
|
107
107
|
signal ??= cancellation;
|
|
108
108
|
const [dataResult, branchesResult] = await Promise.allSettled([
|
|
109
|
-
this.git.
|
|
109
|
+
this.git.run({ cwd: commonPath, cancellation: signal }, 'worktree', 'list', '--porcelain'),
|
|
110
110
|
this.provider.branches.getBranches(commonPath, undefined, signal),
|
|
111
111
|
]);
|
|
112
112
|
|
|
@@ -154,7 +154,7 @@ export class WorktreesGitSubProvider implements GitWorktreesSubProvider {
|
|
|
154
154
|
|
|
155
155
|
let deleted = false;
|
|
156
156
|
try {
|
|
157
|
-
await this.git.
|
|
157
|
+
await this.git.run({ cwd: repoPath, errors: 'throw' }, ...args);
|
|
158
158
|
deleted = true;
|
|
159
159
|
} catch (ex) {
|
|
160
160
|
scope?.error(ex);
|
package/src/plus/ai/constants.ts
CHANGED
|
@@ -13,6 +13,7 @@ export type AIProviders =
|
|
|
13
13
|
| 'openai'
|
|
14
14
|
| 'openaicompatible'
|
|
15
15
|
| 'openrouter'
|
|
16
|
+
| 'simulator'
|
|
16
17
|
| 'vscode'
|
|
17
18
|
| 'xai';
|
|
18
19
|
export type AIPrimaryProviders = Extract<AIProviders, 'gitkraken' | 'vscode'>;
|
|
@@ -119,3 +120,10 @@ export const ollamaProviderDescriptor: AIProviderDescriptor<'ollama'> = {
|
|
|
119
120
|
requiresAccount: true,
|
|
120
121
|
requiresUserKey: false,
|
|
121
122
|
} as const;
|
|
123
|
+
export const simulatorProviderDescriptor: AIProviderDescriptor<'simulator'> = {
|
|
124
|
+
id: 'simulator',
|
|
125
|
+
name: 'Simulator (Debugging)',
|
|
126
|
+
primary: false,
|
|
127
|
+
requiresAccount: false,
|
|
128
|
+
requiresUserKey: false,
|
|
129
|
+
} as const;
|
|
@@ -78,6 +78,26 @@ interface ReviewPullRequestPromptTemplateContext {
|
|
|
78
78
|
instructions?: string;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
interface ReviewChangesPromptTemplateContext {
|
|
82
|
+
diff: string;
|
|
83
|
+
message: string;
|
|
84
|
+
instructions?: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface ReviewOverviewPromptTemplateContext {
|
|
88
|
+
files: string;
|
|
89
|
+
message: string;
|
|
90
|
+
instructions?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
interface ReviewDetailPromptTemplateContext {
|
|
94
|
+
diff: string;
|
|
95
|
+
overview: string;
|
|
96
|
+
message: string;
|
|
97
|
+
focusArea: string;
|
|
98
|
+
instructions?: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
81
101
|
interface StartWorkIssuePromptTemplateContext {
|
|
82
102
|
issue: string;
|
|
83
103
|
instructions?: string;
|
|
@@ -91,6 +111,9 @@ export type PromptTemplateType =
|
|
|
91
111
|
| 'generate-commits'
|
|
92
112
|
| 'generate-searchQuery'
|
|
93
113
|
| 'explain-changes'
|
|
114
|
+
| 'review-changes'
|
|
115
|
+
| 'review-overview'
|
|
116
|
+
| 'review-detail'
|
|
94
117
|
| 'start-review-pullRequest'
|
|
95
118
|
| 'start-work-issue';
|
|
96
119
|
|
|
@@ -115,6 +138,12 @@ export type PromptTemplateContext<T extends PromptTemplateType> = T extends 'gen
|
|
|
115
138
|
? SearchQueryPromptTemplateContext
|
|
116
139
|
: T extends 'explain-changes'
|
|
117
140
|
? ExplainChangesPromptTemplateContext
|
|
141
|
+
: T extends 'review-changes'
|
|
142
|
+
? ReviewChangesPromptTemplateContext
|
|
143
|
+
: T extends 'review-overview'
|
|
144
|
+
? ReviewOverviewPromptTemplateContext
|
|
145
|
+
: T extends 'review-detail'
|
|
146
|
+
? ReviewDetailPromptTemplateContext
|
|
118
147
|
: T extends 'start-review-pullRequest'
|
|
119
148
|
? ReviewPullRequestPromptTemplateContext
|
|
120
149
|
: T extends 'start-work-issue'
|
|
@@ -1 +1,31 @@
|
|
|
1
1
|
export type AISummarizedResult = { summary: string; body: string };
|
|
2
|
+
|
|
3
|
+
export type AIReviewSeverity = 'critical' | 'warning' | 'suggestion';
|
|
4
|
+
|
|
5
|
+
export interface AIReviewFinding {
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly severity: AIReviewSeverity;
|
|
8
|
+
readonly title: string;
|
|
9
|
+
readonly description: string;
|
|
10
|
+
readonly filePath?: string;
|
|
11
|
+
readonly lineRange?: { readonly start: number; readonly end: number };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface AIReviewFocusArea {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly label: string;
|
|
17
|
+
readonly rationale: string;
|
|
18
|
+
readonly severity: AIReviewSeverity;
|
|
19
|
+
readonly files: readonly string[];
|
|
20
|
+
readonly findings?: readonly AIReviewFinding[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AIReviewResult {
|
|
24
|
+
readonly overview: string;
|
|
25
|
+
readonly focusAreas: readonly AIReviewFocusArea[];
|
|
26
|
+
readonly mode: 'single-pass' | 'two-pass';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface AIReviewDetailResult {
|
|
30
|
+
readonly findings: readonly AIReviewFinding[];
|
|
31
|
+
}
|
package/src/plus/ai/prompts.ts
CHANGED
|
@@ -526,3 +526,132 @@ You can use GitKraken MCP tools to gather additional context about the repositor
|
|
|
526
526
|
|
|
527
527
|
Now, proceed with your analysis and provide a comprehensive review of the PR. Return only the relevant information without any additional text.`,
|
|
528
528
|
};
|
|
529
|
+
|
|
530
|
+
export const reviewChanges: PromptTemplate<'review-changes'> = {
|
|
531
|
+
id: 'review-changes',
|
|
532
|
+
variables: ['diff', 'message', 'instructions'],
|
|
533
|
+
template: `You are an expert code reviewer analyzing a set of code changes. Your goal is to identify meaningful issues — bugs, logic errors, security vulnerabilities, missing error handling, and potential regressions — while ignoring style preferences and linter-level concerns. Focus on problems a careful human reviewer would catch.
|
|
534
|
+
|
|
535
|
+
Examine the following code changes in Git diff format:
|
|
536
|
+
<~~diff~~>
|
|
537
|
+
\${diff}
|
|
538
|
+
</~~diff~~>
|
|
539
|
+
|
|
540
|
+
Author's description of the changes:
|
|
541
|
+
<~~message~~>
|
|
542
|
+
\${message}
|
|
543
|
+
</~~message~~>
|
|
544
|
+
|
|
545
|
+
Produce a structured review in the following XML format. Include ONLY the XML tags described — no other text:
|
|
546
|
+
|
|
547
|
+
<overview>
|
|
548
|
+
A concise 1-3 sentence summary of what these changes do and their overall quality. Note any systemic concerns.
|
|
549
|
+
</overview>
|
|
550
|
+
<focus-areas>
|
|
551
|
+
<area severity="critical|warning|suggestion" files="comma-separated file paths">
|
|
552
|
+
<label>Short title of the concern (under 60 chars)</label>
|
|
553
|
+
<rationale>Why this matters — what could go wrong or what is suboptimal</rationale>
|
|
554
|
+
<findings>
|
|
555
|
+
<finding severity="critical|warning|suggestion" file="path/to/file.ts" lines="start-end">
|
|
556
|
+
<title>Specific issue title</title>
|
|
557
|
+
<description>Clear explanation of the problem and how to address it</description>
|
|
558
|
+
</finding>
|
|
559
|
+
</findings>
|
|
560
|
+
</area>
|
|
561
|
+
</focus-areas>
|
|
562
|
+
|
|
563
|
+
Guidelines:
|
|
564
|
+
- Severity levels: "critical" = bugs, security issues, data loss risks; "warning" = logic concerns, missing error handling, potential regressions; "suggestion" = improvements, maintainability, performance
|
|
565
|
+
- Group related findings into focus areas by theme, not by file
|
|
566
|
+
- If changes look correct and well-structured, say so in the overview and include zero focus areas
|
|
567
|
+
- 3-5 high-quality findings are better than 15 low-quality ones
|
|
568
|
+
- Reference specific lines from the diff when possible
|
|
569
|
+
- Do not flag style issues, naming preferences, or things a linter would catch
|
|
570
|
+
- Base conclusions only on the code shown — do not speculate about unseen code
|
|
571
|
+
|
|
572
|
+
\${instructions}
|
|
573
|
+
|
|
574
|
+
Review the changes and produce the structured XML output above.`,
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
export const reviewOverview: PromptTemplate<'review-overview'> = {
|
|
578
|
+
id: 'review-overview',
|
|
579
|
+
variables: ['files', 'message', 'instructions'],
|
|
580
|
+
template: `You are an expert code reviewer performing an initial assessment of a set of code changes. You are given a file manifest (not full diffs) — use the file paths, change types, and line counts to identify which areas deserve closer inspection.
|
|
581
|
+
|
|
582
|
+
File manifest (JSON array of changed files):
|
|
583
|
+
<~~files~~>
|
|
584
|
+
\${files}
|
|
585
|
+
</~~files~~>
|
|
586
|
+
|
|
587
|
+
Author's description of the changes:
|
|
588
|
+
<~~message~~>
|
|
589
|
+
\${message}
|
|
590
|
+
</~~message~~>
|
|
591
|
+
|
|
592
|
+
Produce a structured assessment in the following XML format. Include ONLY the XML tags described — no other text:
|
|
593
|
+
|
|
594
|
+
<overview>
|
|
595
|
+
A concise 1-3 sentence summary of the scope and nature of these changes based on the file manifest and description.
|
|
596
|
+
</overview>
|
|
597
|
+
<focus-areas>
|
|
598
|
+
<area severity="critical|warning|suggestion" files="comma-separated file paths">
|
|
599
|
+
<label>Short title of the area to inspect (under 60 chars)</label>
|
|
600
|
+
<rationale>Why this area deserves closer review — based on the types of files changed, the volume of changes, and potential risk</rationale>
|
|
601
|
+
</area>
|
|
602
|
+
</focus-areas>
|
|
603
|
+
|
|
604
|
+
Guidelines:
|
|
605
|
+
- Severity reflects potential risk: "critical" = security-sensitive files, auth/crypto/payment paths, database migrations; "warning" = core logic changes, API changes, large modifications; "suggestion" = refactoring, config changes, documentation
|
|
606
|
+
- Rank focus areas from highest to lowest risk
|
|
607
|
+
- Group related files into focus areas by theme
|
|
608
|
+
- Include 2-6 focus areas. If changes are very simple, fewer is fine
|
|
609
|
+
- Do NOT include <findings> — those come in a later pass when full diffs are available
|
|
610
|
+
|
|
611
|
+
\${instructions}
|
|
612
|
+
|
|
613
|
+
Assess the changes and produce the structured XML output above.`,
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
export const reviewDetail: PromptTemplate<'review-detail'> = {
|
|
617
|
+
id: 'review-detail',
|
|
618
|
+
variables: ['diff', 'overview', 'message', 'focusArea', 'instructions'],
|
|
619
|
+
template: `You are an expert code reviewer performing a detailed inspection of specific files that were flagged for closer review. You have the context from an initial overview assessment.
|
|
620
|
+
|
|
621
|
+
Initial overview of the full changeset:
|
|
622
|
+
<~~overview~~>
|
|
623
|
+
\${overview}
|
|
624
|
+
</~~overview~~>
|
|
625
|
+
|
|
626
|
+
Focus area being inspected: \${focusArea}
|
|
627
|
+
|
|
628
|
+
Author's description of the changes:
|
|
629
|
+
<~~message~~>
|
|
630
|
+
\${message}
|
|
631
|
+
</~~message~~>
|
|
632
|
+
|
|
633
|
+
Code changes for the files in this focus area (Git diff format):
|
|
634
|
+
<~~diff~~>
|
|
635
|
+
\${diff}
|
|
636
|
+
</~~diff~~>
|
|
637
|
+
|
|
638
|
+
Produce detailed findings in the following XML format. Include ONLY the XML tags — no other text:
|
|
639
|
+
|
|
640
|
+
<findings>
|
|
641
|
+
<finding severity="critical|warning|suggestion" file="path/to/file.ts" lines="start-end">
|
|
642
|
+
<title>Specific issue title</title>
|
|
643
|
+
<description>Clear explanation of the problem and how to address it</description>
|
|
644
|
+
</finding>
|
|
645
|
+
</findings>
|
|
646
|
+
|
|
647
|
+
Guidelines:
|
|
648
|
+
- Severity: "critical" = bugs, security, data loss; "warning" = logic concerns, error handling, regressions; "suggestion" = improvements, maintainability
|
|
649
|
+
- Reference specific line numbers from the diff
|
|
650
|
+
- Be concrete — explain what the problem is and how to fix it
|
|
651
|
+
- If the code in this area looks correct, return an empty <findings></findings> block
|
|
652
|
+
- Do not flag style issues or things a linter would catch
|
|
653
|
+
|
|
654
|
+
\${instructions}
|
|
655
|
+
|
|
656
|
+
Inspect the diff for this focus area and produce the structured XML findings above.`,
|
|
657
|
+
};
|
|
@@ -4,6 +4,8 @@ export function getActionName(action: AIActionType): string {
|
|
|
4
4
|
switch (action) {
|
|
5
5
|
case 'explain-changes':
|
|
6
6
|
return 'Explain Changes';
|
|
7
|
+
case 'review-changes':
|
|
8
|
+
return 'Review Changes';
|
|
7
9
|
case 'generate-commitMessage':
|
|
8
10
|
return 'Generate Commit Message';
|
|
9
11
|
case 'generate-stashMessage':
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AIReviewDetailResult,
|
|
3
|
+
AIReviewFinding,
|
|
4
|
+
AIReviewFocusArea,
|
|
5
|
+
AIReviewResult,
|
|
6
|
+
AIReviewSeverity,
|
|
7
|
+
} from '../models/results.js';
|
|
8
|
+
|
|
1
9
|
const summaryTagRegex = /<summary>([\s\S]*?)(?:<\/summary>|$)/;
|
|
2
10
|
const bodyTagRegex = /<body>([\s\S]*?)(?:<\/body>|$)/;
|
|
3
11
|
const codeBlockRegex = /```([\s\S]*?)```/;
|
|
@@ -48,3 +56,94 @@ export function splitMessageIntoSummaryAndBody(message: string): { readonly summ
|
|
|
48
56
|
body: message.substring(index + 1).trim(),
|
|
49
57
|
};
|
|
50
58
|
}
|
|
59
|
+
|
|
60
|
+
const overviewTagRegex = /<overview>([\s\S]*?)(?:<\/overview>|$)/;
|
|
61
|
+
const areaTagRegex = /<area\s+([^>]*)>([\s\S]*?)(?:<\/area>|$)/g;
|
|
62
|
+
const findingTagRegex = /<finding\s+([^>]*)>([\s\S]*?)(?:<\/finding>|$)/g;
|
|
63
|
+
const labelTagRegex = /<label>([\s\S]*?)(?:<\/label>|$)/;
|
|
64
|
+
const rationaleTagRegex = /<rationale>([\s\S]*?)(?:<\/rationale>|$)/;
|
|
65
|
+
const titleTagRegex = /<title>([\s\S]*?)(?:<\/title>|$)/;
|
|
66
|
+
const descriptionTagRegex = /<description>([\s\S]*?)(?:<\/description>|$)/;
|
|
67
|
+
const findingsBlockRegex = /<findings>([\s\S]*?)(?:<\/findings>|$)/;
|
|
68
|
+
|
|
69
|
+
function parseAttr(attrs: string, name: string): string | undefined {
|
|
70
|
+
const match = new RegExp(`${name}="([^"]*)"`, 'i').exec(attrs);
|
|
71
|
+
return match?.[1]?.trim() || undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function parseSeverity(value: string | undefined): AIReviewSeverity {
|
|
75
|
+
if (value === 'critical' || value === 'warning' || value === 'suggestion') return value;
|
|
76
|
+
return 'suggestion';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function parseLineRange(value: string | undefined): { start: number; end: number } | undefined {
|
|
80
|
+
if (!value) return undefined;
|
|
81
|
+
const parts = value.split('-');
|
|
82
|
+
const start = parseInt(parts[0], 10);
|
|
83
|
+
if (isNaN(start)) return undefined;
|
|
84
|
+
const end = parts.length > 1 ? parseInt(parts[1], 10) : start;
|
|
85
|
+
return { start: start, end: isNaN(end) ? start : end };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function parseFindings(content: string, idPrefix: string): AIReviewFinding[] {
|
|
89
|
+
const findings: AIReviewFinding[] = [];
|
|
90
|
+
let findingIndex = 0;
|
|
91
|
+
|
|
92
|
+
for (const match of content.matchAll(findingTagRegex)) {
|
|
93
|
+
const attrs = match[1];
|
|
94
|
+
const inner = match[2];
|
|
95
|
+
findingIndex++;
|
|
96
|
+
|
|
97
|
+
findings.push({
|
|
98
|
+
id: `${idPrefix}-f${findingIndex}`,
|
|
99
|
+
severity: parseSeverity(parseAttr(attrs, 'severity')),
|
|
100
|
+
title: inner.match(titleTagRegex)?.[1]?.trim() ?? 'Untitled finding',
|
|
101
|
+
description: inner.match(descriptionTagRegex)?.[1]?.trim() ?? '',
|
|
102
|
+
filePath: parseAttr(attrs, 'file'),
|
|
103
|
+
lineRange: parseLineRange(parseAttr(attrs, 'lines')),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return findings;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function parseReviewResult(result: string, mode: 'single-pass' | 'two-pass'): AIReviewResult {
|
|
111
|
+
result = result.trim();
|
|
112
|
+
|
|
113
|
+
const overview = result.match(overviewTagRegex)?.[1]?.trim() ?? '';
|
|
114
|
+
|
|
115
|
+
const focusAreas: AIReviewFocusArea[] = [];
|
|
116
|
+
let areaIndex = 0;
|
|
117
|
+
|
|
118
|
+
for (const match of result.matchAll(areaTagRegex)) {
|
|
119
|
+
const attrs = match[1];
|
|
120
|
+
const inner = match[2];
|
|
121
|
+
areaIndex++;
|
|
122
|
+
|
|
123
|
+
const id = `area-${areaIndex}`;
|
|
124
|
+
const filesAttr = parseAttr(attrs, 'files');
|
|
125
|
+
|
|
126
|
+
const findingsBlock = inner.match(findingsBlockRegex)?.[1];
|
|
127
|
+
const findings = findingsBlock ? parseFindings(findingsBlock, id) : undefined;
|
|
128
|
+
|
|
129
|
+
focusAreas.push({
|
|
130
|
+
id: id,
|
|
131
|
+
label: inner.match(labelTagRegex)?.[1]?.trim() ?? 'Untitled area',
|
|
132
|
+
rationale: inner.match(rationaleTagRegex)?.[1]?.trim() ?? '',
|
|
133
|
+
severity: parseSeverity(parseAttr(attrs, 'severity')),
|
|
134
|
+
files: filesAttr?.split(',').map(f => f.trim()) ?? [],
|
|
135
|
+
findings: findings,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return { overview: overview, focusAreas: focusAreas, mode: mode };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function parseReviewDetailResult(result: string, focusAreaId: string): AIReviewDetailResult {
|
|
143
|
+
result = result.trim();
|
|
144
|
+
|
|
145
|
+
const findingsBlock = result.match(findingsBlockRegex)?.[1] ?? result;
|
|
146
|
+
const findings = parseFindings(findingsBlock, focusAreaId);
|
|
147
|
+
|
|
148
|
+
return { findings: findings };
|
|
149
|
+
}
|
|
@@ -52,7 +52,9 @@ type DiffTemplateType =
|
|
|
52
52
|
| 'generate-create-cloudPatch'
|
|
53
53
|
| 'generate-create-codeSuggestion'
|
|
54
54
|
| 'generate-create-pullRequest'
|
|
55
|
-
| 'explain-changes'
|
|
55
|
+
| 'explain-changes'
|
|
56
|
+
| 'review-changes'
|
|
57
|
+
| 'review-detail';
|
|
56
58
|
|
|
57
59
|
/** File type base scores (0-100, higher = more important) */
|
|
58
60
|
const fileTypeScores: Record<string, number> = {
|
|
@@ -8,6 +8,7 @@ import { debug } from '../../../../utils/decorators/log.js';
|
|
|
8
8
|
import { getScopedLogger } from '../../../../utils/logger.scoped.js';
|
|
9
9
|
import type { PagedResult, PagingOptions } from '../../../../utils/paging.js';
|
|
10
10
|
import { emptyPagedResult } from '../../../../utils/paging.js';
|
|
11
|
+
import { getSettledValue } from '../../../../utils/promise.js';
|
|
11
12
|
import type { CacheController } from '../../../../utils/promiseCache.js';
|
|
12
13
|
import { toTokenInfo } from '../../api/tokenUtils.js';
|
|
13
14
|
import { HeadType } from '../../context.js';
|
|
@@ -206,6 +207,9 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
206
207
|
): Promise<BranchContributionsOverview | undefined> {
|
|
207
208
|
const scope = getScopedLogger();
|
|
208
209
|
|
|
210
|
+
// No outer cache here — GitHub provider has no stored-target safety net (no Tier 1
|
|
211
|
+
// equivalent), so the result is purely PR-resolution-dependent and a `ref`-keyed cache
|
|
212
|
+
// would serve stale data when the PR is later retargeted.
|
|
209
213
|
try {
|
|
210
214
|
let mergeTarget: string | undefined;
|
|
211
215
|
|
|
@@ -223,11 +227,18 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
223
227
|
const mergeBase = await this.provider.refs.getMergeBase(repoPath, ref, mergeTarget);
|
|
224
228
|
if (mergeBase == null) return undefined;
|
|
225
229
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
230
|
+
// Fetch the merge-base commit's committer date in parallel with contributors so consumers
|
|
231
|
+
// that just need the date for the scope window don't pay a separate round-trip.
|
|
232
|
+
// `allSettled` so a transient failure in one side doesn't drop the overview entirely.
|
|
233
|
+
const [contributorsSettled, mergeBaseCommitSettled] = await Promise.allSettled([
|
|
234
|
+
this.provider.contributors.getContributors(repoPath, createRevisionRange(mergeBase, ref, '..'), {
|
|
235
|
+
stats: true,
|
|
236
|
+
}),
|
|
237
|
+
this.provider.commits.getCommit(repoPath, mergeBase),
|
|
238
|
+
]);
|
|
239
|
+
|
|
240
|
+
const result = getSettledValue(contributorsSettled) ?? { contributors: [] };
|
|
241
|
+
const mergeBaseCommit = getSettledValue(mergeBaseCommitSettled);
|
|
231
242
|
|
|
232
243
|
sortContributors(result.contributors, { orderBy: 'score:desc' });
|
|
233
244
|
|
|
@@ -265,6 +276,7 @@ export class BranchesGitSubProvider implements GitBranchesSubProvider {
|
|
|
265
276
|
branch: ref,
|
|
266
277
|
mergeTarget: mergeTarget,
|
|
267
278
|
mergeBase: mergeBase,
|
|
279
|
+
mergeBaseDate: mergeBaseCommit?.committer?.date ?? mergeBaseCommit?.author?.date,
|
|
268
280
|
|
|
269
281
|
commits: totalCommits,
|
|
270
282
|
files: totalFiles,
|
|
@@ -59,7 +59,7 @@ export class DiffGitSubProvider implements GitDiffSubProvider {
|
|
|
59
59
|
repoPath: string,
|
|
60
60
|
to?: string,
|
|
61
61
|
_from?: string,
|
|
62
|
-
_options?: { uris?: (string | Uri)[] },
|
|
62
|
+
_options?: { uris?: (string | Uri)[]; includeUntracked?: boolean },
|
|
63
63
|
_cancellation?: AbortSignal,
|
|
64
64
|
): Promise<GitDiffShortStat | undefined> {
|
|
65
65
|
// TODO@eamodio if there is no ref we can't return anything, until we can get at the change store from RemoteHub
|
|
@@ -79,7 +79,13 @@ export class DiffGitSubProvider implements GitDiffSubProvider {
|
|
|
79
79
|
repoPath: string,
|
|
80
80
|
ref1OrRange: string | GitRevisionRange,
|
|
81
81
|
ref2?: string,
|
|
82
|
-
_options?: {
|
|
82
|
+
_options?: {
|
|
83
|
+
filters?: GitDiffFilter[];
|
|
84
|
+
includeUntracked?: boolean;
|
|
85
|
+
path?: string;
|
|
86
|
+
renameLimit?: number;
|
|
87
|
+
similarityThreshold?: number;
|
|
88
|
+
},
|
|
83
89
|
): Promise<GitFile[] | undefined> {
|
|
84
90
|
if (repoPath == null) return undefined;
|
|
85
91
|
|
|
@@ -103,12 +103,14 @@ export function sequentialize<T extends (...args: any[]) => any>(
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
// Cleanup when done
|
|
106
|
-
void promise
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
void promise
|
|
107
|
+
.finally(() => {
|
|
108
|
+
const s = this[prop];
|
|
109
|
+
if (s?.promise === promise && s.waiting == null) {
|
|
110
|
+
this[prop] = undefined;
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
.catch(() => {});
|
|
112
114
|
|
|
113
115
|
return promise;
|
|
114
116
|
};
|
|
@@ -373,8 +373,8 @@ export function runSpawn<T extends string | Buffer>(
|
|
|
373
373
|
function getStdio<T>(
|
|
374
374
|
encoding: BufferEncoding | 'buffer' | string,
|
|
375
375
|
): { stdout: T; stderr: T } | Promise<{ stdout: T; stderr: T }> {
|
|
376
|
-
const stdout = Buffer.concat(stdoutBuffers
|
|
377
|
-
const stderr = Buffer.concat(stderrBuffers
|
|
376
|
+
const stdout = Buffer.concat(stdoutBuffers);
|
|
377
|
+
const stderr = Buffer.concat(stderrBuffers);
|
|
378
378
|
if (encoding === 'utf8' || encoding === 'binary') {
|
|
379
379
|
return { stdout: stdout.toString(encoding) as T, stderr: stderr.toString(encoding) as T };
|
|
380
380
|
}
|
package/src/utils/formatter.ts
CHANGED
|
@@ -176,23 +176,16 @@ export abstract class Formatter<Item = any, Options extends FormatOptions = Form
|
|
|
176
176
|
options.tokenOptions = tokenOptions;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
this._formatter.reset(item, options);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return interpolateAsync(template, this._formatter);
|
|
179
|
+
// Always allocate a fresh formatter: `interpolateAsync` awaits between tokens, so a
|
|
180
|
+
// concurrent call that reset a shared instance would poison in-flight token resolution.
|
|
181
|
+
return interpolateAsync(template, new formatter(item, options));
|
|
186
182
|
}
|
|
187
183
|
|
|
188
184
|
static has<TOptions extends FormatOptions>(
|
|
189
185
|
template: string,
|
|
190
186
|
...tokens: (keyof NonNullable<TOptions['tokenOptions']>)[]
|
|
191
187
|
): boolean {
|
|
192
|
-
const token =
|
|
193
|
-
tokens.length === 1
|
|
194
|
-
? (tokens[0] as string)
|
|
195
|
-
: (`(${tokens.join('|')})` as keyof NonNullable<TOptions['tokenOptions']> as string);
|
|
188
|
+
const token = tokens.length === 1 ? (tokens[0] as string) : `(${tokens.join('|')})`;
|
|
196
189
|
|
|
197
190
|
let regex = hasTokenRegexMap.get(token);
|
|
198
191
|
if (regex == null) {
|
package/src/utils/iterable.ts
CHANGED
|
@@ -179,7 +179,7 @@ class FilterIterator<T, U extends T = T> implements IterableIterator<T | U> {
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
if (this.predicate === undefined ? result.value != null : this.predicate(result.value)) {
|
|
182
|
-
return { done: false, value: result.value
|
|
182
|
+
return { done: false, value: result.value };
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
}
|