@mrclrchtr/supi-review 1.4.0 → 1.6.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/README.md +53 -59
- package/package.json +2 -9
- package/src/git.ts +107 -1
- package/src/history/collect.ts +210 -0
- package/src/history/synthesize.ts +109 -0
- package/src/model.ts +100 -0
- package/src/review.ts +204 -342
- package/src/target/packet.ts +216 -0
- package/src/tool/brief-runner.ts +269 -0
- package/src/tool/review-runner.ts +434 -0
- package/src/tool/runner-types.ts +29 -12
- package/src/tool/schemas.ts +31 -0
- package/src/types.ts +87 -48
- package/src/ui/flow.ts +302 -0
- package/src/ui/format-content.ts +22 -16
- package/src/ui/progress-widget.ts +40 -40
- package/src/ui/renderer.ts +38 -21
- package/src/ui/theme-type.ts +16 -0
- package/node_modules/@mrclrchtr/supi-core/README.md +0 -107
- package/node_modules/@mrclrchtr/supi-core/package.json +0 -44
- package/node_modules/@mrclrchtr/supi-core/src/api.ts +0 -83
- package/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -76
- package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +0 -186
- package/node_modules/@mrclrchtr/supi-core/src/context/context-messages.ts +0 -119
- package/node_modules/@mrclrchtr/supi-core/src/context/context-provider-registry.ts +0 -36
- package/node_modules/@mrclrchtr/supi-core/src/context/context-tag.ts +0 -31
- package/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -255
- package/node_modules/@mrclrchtr/supi-core/src/extension.ts +0 -1
- package/node_modules/@mrclrchtr/supi-core/src/index.ts +0 -83
- package/node_modules/@mrclrchtr/supi-core/src/project-roots.ts +0 -170
- package/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +0 -54
- package/node_modules/@mrclrchtr/supi-core/src/session-utils.ts +0 -29
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-command.ts +0 -15
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +0 -41
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +0 -226
- package/node_modules/@mrclrchtr/supi-core/src/terminal.ts +0 -60
- package/src/briefs.ts +0 -101
- package/src/profiles.ts +0 -52
- package/src/prompts.ts +0 -116
- package/src/settings.ts +0 -246
- package/src/tool/runner.ts +0 -432
- package/src/tool/target-resolution.ts +0 -102
- package/src/ui/ui.ts +0 -208
package/src/model.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { Model } from "@earendil-works/pi-ai";
|
|
2
|
+
import { type ExtensionContext, SettingsManager } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import type { ReviewModelSelection } from "./types.ts";
|
|
4
|
+
|
|
5
|
+
/** Build the canonical `provider/modelId` string used throughout the review flow. */
|
|
6
|
+
export function toCanonicalModelId(
|
|
7
|
+
model: Pick<NonNullable<ExtensionContext["model"]>, "provider" | "id">,
|
|
8
|
+
): string {
|
|
9
|
+
return `${model.provider}/${model.id}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* List review models using Pi's scoped model configuration only.
|
|
14
|
+
*
|
|
15
|
+
* If no scoped model patterns are configured, the review picker is intentionally empty.
|
|
16
|
+
*/
|
|
17
|
+
export function getSelectableReviewModels(
|
|
18
|
+
ctx: Pick<ExtensionContext, "cwd" | "modelRegistry" | "model">,
|
|
19
|
+
enabledModelPatterns = SettingsManager.create(ctx.cwd).getEnabledModels(),
|
|
20
|
+
): ReviewModelSelection[] {
|
|
21
|
+
if (!enabledModelPatterns || enabledModelPatterns.length === 0) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const byCanonicalId = new Map<string, ReviewModelSelection>();
|
|
26
|
+
const availableModels = filterByEnabledModels(
|
|
27
|
+
enabledModelPatterns,
|
|
28
|
+
ctx.modelRegistry.getAvailable(),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const addModel = (
|
|
32
|
+
// biome-ignore lint/suspicious/noExplicitAny: Model<any> is pi's canonical type
|
|
33
|
+
model: Model<any>,
|
|
34
|
+
isCurrent: boolean,
|
|
35
|
+
) => {
|
|
36
|
+
const canonicalId = toCanonicalModelId(model);
|
|
37
|
+
const existing = byCanonicalId.get(canonicalId);
|
|
38
|
+
if (existing) {
|
|
39
|
+
if (isCurrent) existing.isCurrent = true;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
byCanonicalId.set(canonicalId, {
|
|
44
|
+
canonicalId,
|
|
45
|
+
provider: model.provider,
|
|
46
|
+
id: model.id,
|
|
47
|
+
model,
|
|
48
|
+
label: model.name ?? canonicalId,
|
|
49
|
+
description: canonicalId,
|
|
50
|
+
isCurrent,
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (ctx.model && matchModelPatterns(ctx.model, enabledModelPatterns)) {
|
|
55
|
+
addModel(ctx.model, true);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (const model of availableModels) {
|
|
59
|
+
addModel(
|
|
60
|
+
model,
|
|
61
|
+
ctx.model ? toCanonicalModelId(model) === toCanonicalModelId(ctx.model) : false,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return Array.from(byCanonicalId.values()).sort((a, b) => {
|
|
66
|
+
if (a.isCurrent !== b.isCurrent) return a.isCurrent ? -1 : 1;
|
|
67
|
+
return a.canonicalId.localeCompare(b.canonicalId);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function filterByEnabledModels<T extends { provider: string; id: string }>(
|
|
72
|
+
patterns: string[],
|
|
73
|
+
models: T[],
|
|
74
|
+
): T[] {
|
|
75
|
+
return models.filter((model) => matchModelPatterns(model, patterns));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function matchModelPatterns(model: { provider: string; id: string }, patterns: string[]): boolean {
|
|
79
|
+
return patterns.some((pattern) => matchModelPattern(model, pattern));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function matchModelPattern(model: { provider: string; id: string }, pattern: string): boolean {
|
|
83
|
+
const canonicalId = `${model.provider}/${model.id}`;
|
|
84
|
+
if (pattern.includes("/")) {
|
|
85
|
+
return simpleGlobMatch(canonicalId, pattern);
|
|
86
|
+
}
|
|
87
|
+
return simpleGlobMatch(model.id, pattern) || simpleGlobMatch(canonicalId, pattern);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function simpleGlobMatch(text: string, pattern: string): boolean {
|
|
91
|
+
if (!pattern.includes("*") && !pattern.includes("?")) {
|
|
92
|
+
return text.toLowerCase() === pattern.toLowerCase();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const regex = pattern
|
|
96
|
+
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
|
97
|
+
.replace(/\*/g, ".*")
|
|
98
|
+
.replace(/\?/g, ".");
|
|
99
|
+
return new RegExp(`^${regex}$`, "i").test(text);
|
|
100
|
+
}
|