@jpkme/diff-review 0.1.12 → 0.1.13
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 +1 -1
- package/lib/acp-policy.mjs +99 -12
- package/lib/acp-policy.test.mjs +56 -3
- package/lib/acp-shell.mjs +38 -8
- package/lib/acp-shell.test.mjs +32 -1
- package/lib/agent-login.mjs +105 -105
- package/lib/check-report.mjs +1 -0
- package/lib/check-report.test.mjs +1 -0
- package/lib/extract-cache.test.mjs +162 -162
- package/lib/model-label.mjs +263 -263
- package/lib/model-label.test.mjs +77 -77
- package/lib/models-cache.mjs +75 -75
- package/lib/models-cache.test.mjs +50 -50
- package/lib/review-prep.mjs +63 -63
- package/package.json +1 -1
- package/web/build/client/_app/immutable/assets/{0.CLQiq3Ed.css → 0.BKRG1f36.css} +1 -1
- package/web/build/client/_app/immutable/assets/0.BKRG1f36.css.br +0 -0
- package/web/build/client/_app/immutable/assets/{0.CLQiq3Ed.css.gz → 0.BKRG1f36.css.gz} +0 -0
- package/web/build/client/_app/immutable/assets/2.tqrMRTM0.css +1 -0
- package/web/build/client/_app/immutable/assets/2.tqrMRTM0.css.br +0 -0
- package/web/build/client/_app/immutable/assets/2.tqrMRTM0.css.gz +0 -0
- package/web/build/client/_app/immutable/assets/3.BT54aVKb.css +1 -0
- package/web/build/client/_app/immutable/assets/3.BT54aVKb.css.br +0 -0
- package/web/build/client/_app/immutable/assets/3.BT54aVKb.css.gz +0 -0
- package/web/build/client/_app/immutable/assets/storage.DqYH0w6R.css +1 -0
- package/web/build/client/_app/immutable/assets/storage.DqYH0w6R.css.br +0 -0
- package/web/build/client/_app/immutable/assets/storage.DqYH0w6R.css.gz +0 -0
- package/web/build/client/_app/immutable/chunks/BXUWMim4.js +213 -0
- package/web/build/client/_app/immutable/chunks/BXUWMim4.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/BXUWMim4.js.gz +0 -0
- package/web/build/client/_app/immutable/chunks/{CPyWH418.js → Bu1mm6Oz.js} +1 -1
- package/web/build/client/_app/immutable/chunks/Bu1mm6Oz.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/Bu1mm6Oz.js.gz +0 -0
- package/web/build/client/_app/immutable/chunks/{B5ByWcPE.js → DPfXzQnm.js} +2 -2
- package/web/build/client/_app/immutable/chunks/DPfXzQnm.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/DPfXzQnm.js.gz +0 -0
- package/web/build/client/_app/immutable/entry/{app.BiBohpyO.js → app.CTgiuiU1.js} +2 -2
- package/web/build/client/_app/immutable/entry/app.CTgiuiU1.js.br +0 -0
- package/web/build/client/_app/immutable/entry/app.CTgiuiU1.js.gz +0 -0
- package/web/build/client/_app/immutable/entry/start.CFSl0kht.js +1 -0
- package/web/build/client/_app/immutable/entry/start.CFSl0kht.js.br +0 -0
- package/web/build/client/_app/immutable/entry/start.CFSl0kht.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/{1.BzPXaJJj.js → 1.0PQZpSbJ.js} +1 -1
- package/web/build/client/_app/immutable/nodes/1.0PQZpSbJ.js.br +2 -0
- package/web/build/client/_app/immutable/nodes/1.0PQZpSbJ.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/2.DQaoQoy4.js +10 -0
- package/web/build/client/_app/immutable/nodes/2.DQaoQoy4.js.br +0 -0
- package/web/build/client/_app/immutable/nodes/2.DQaoQoy4.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/3.AciugOtL.js +171 -0
- package/web/build/client/_app/immutable/nodes/3.AciugOtL.js.br +0 -0
- package/web/build/client/_app/immutable/nodes/3.AciugOtL.js.gz +0 -0
- package/web/build/client/_app/version.json +1 -1
- package/web/build/client/_app/version.json.br +0 -0
- package/web/build/client/_app/version.json.gz +0 -0
- package/web/build/handler.js +3 -3
- package/web/build/index.js +3 -3
- package/web/build/server/chunks/{0-BYok4D0n.js → 0-DUStDOsr.js} +3 -3
- package/web/build/server/chunks/{0-BYok4D0n.js.map → 0-DUStDOsr.js.map} +1 -1
- package/web/build/server/chunks/1-C2qlInYk.js +7 -0
- package/web/build/server/chunks/{1-C7zcB0q0.js.map → 1-C2qlInYk.js.map} +1 -1
- package/web/build/server/chunks/2-DyE177MK.js +7 -0
- package/web/build/server/chunks/2-DyE177MK.js.map +1 -0
- package/web/build/server/chunks/3-SO3atuWO.js +7 -0
- package/web/build/server/chunks/{3-DAAmG6VX.js.map → 3-SO3atuWO.js.map} +1 -1
- package/web/build/server/chunks/{_server.ts-qYVrMYPB.js → _server.ts-CRNhzL2a.js} +3 -3
- package/web/build/server/chunks/{_server.ts-qYVrMYPB.js.map → _server.ts-CRNhzL2a.js.map} +1 -1
- package/web/build/server/chunks/{agent-sessions-DSqGavSn.js → agent-sessions-kcUaLhK5.js} +171 -40
- package/web/build/server/chunks/agent-sessions-kcUaLhK5.js.map +1 -0
- package/web/build/server/chunks/{git-review-CpO_G8z8.js → git-review-CXKcjYgZ.js} +2 -2
- package/web/build/server/chunks/{git-review-CpO_G8z8.js.map → git-review-CXKcjYgZ.js.map} +1 -1
- package/web/build/server/chunks/{handler-Di1wJQuU.js → handler-_E0NucKN.js} +3 -3
- package/web/build/server/chunks/{handler-Di1wJQuU.js.map → handler-_E0NucKN.js.map} +1 -1
- package/web/build/server/chunks/{hooks.server-BLOHobEK.js → hooks.server-D7yPODoc.js} +2 -2
- package/web/build/server/chunks/{hooks.server-BLOHobEK.js.map → hooks.server-D7yPODoc.js.map} +1 -1
- package/web/build/server/chunks/{index.js-yLYmrAWy.js → index.js-lMtDM8ZQ.js} +3 -3
- package/web/build/server/chunks/{index.js-yLYmrAWy.js.map → index.js-lMtDM8ZQ.js.map} +1 -1
- package/web/build/server/chunks/{manifest.js-CXj8IIo3.js → manifest.js-BIm6jot5.js} +9 -9
- package/web/build/server/chunks/{manifest.js-CXj8IIo3.js.map → manifest.js-BIm6jot5.js.map} +1 -1
- package/web/build/server/chunks/{remote-1g4ayag-BiJeU0Pk.js → remote-1g4ayag-DmqxwUIz.js} +3 -3
- package/web/build/server/chunks/{remote-1g4ayag-BiJeU0Pk.js.map → remote-1g4ayag-DmqxwUIz.js.map} +1 -1
- package/web/build/server/chunks/{remote-wh6t6j-CHanXurm.js → remote-wh6t6j-DZk0W9Pp.js} +4 -4
- package/web/build/server/chunks/{remote-wh6t6j-CHanXurm.js.map → remote-wh6t6j-DZk0W9Pp.js.map} +1 -1
- package/web/build/client/_app/immutable/assets/0.CLQiq3Ed.css.br +0 -0
- package/web/build/client/_app/immutable/assets/2.CKE12GwZ.css +0 -1
- package/web/build/client/_app/immutable/assets/2.CKE12GwZ.css.br +0 -0
- package/web/build/client/_app/immutable/assets/2.CKE12GwZ.css.gz +0 -0
- package/web/build/client/_app/immutable/assets/3.Dx3c_e7d.css +0 -1
- package/web/build/client/_app/immutable/assets/3.Dx3c_e7d.css.br +0 -0
- package/web/build/client/_app/immutable/assets/3.Dx3c_e7d.css.gz +0 -0
- package/web/build/client/_app/immutable/assets/storage.gDV-BhtT.css +0 -1
- package/web/build/client/_app/immutable/assets/storage.gDV-BhtT.css.br +0 -0
- package/web/build/client/_app/immutable/assets/storage.gDV-BhtT.css.gz +0 -0
- package/web/build/client/_app/immutable/chunks/B5ByWcPE.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/B5ByWcPE.js.gz +0 -0
- package/web/build/client/_app/immutable/chunks/CPyWH418.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/CPyWH418.js.gz +0 -0
- package/web/build/client/_app/immutable/chunks/NwkMsx0h.js +0 -210
- package/web/build/client/_app/immutable/chunks/NwkMsx0h.js.br +0 -0
- package/web/build/client/_app/immutable/chunks/NwkMsx0h.js.gz +0 -0
- package/web/build/client/_app/immutable/entry/app.BiBohpyO.js.br +0 -0
- package/web/build/client/_app/immutable/entry/app.BiBohpyO.js.gz +0 -0
- package/web/build/client/_app/immutable/entry/start.CjWbsiSO.js +0 -1
- package/web/build/client/_app/immutable/entry/start.CjWbsiSO.js.br +0 -0
- package/web/build/client/_app/immutable/entry/start.CjWbsiSO.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/1.BzPXaJJj.js.br +0 -2
- package/web/build/client/_app/immutable/nodes/1.BzPXaJJj.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/2.Cp6Ttd_9.js +0 -10
- package/web/build/client/_app/immutable/nodes/2.Cp6Ttd_9.js.br +0 -0
- package/web/build/client/_app/immutable/nodes/2.Cp6Ttd_9.js.gz +0 -0
- package/web/build/client/_app/immutable/nodes/3.DLiDQm__.js +0 -171
- package/web/build/client/_app/immutable/nodes/3.DLiDQm__.js.br +0 -0
- package/web/build/client/_app/immutable/nodes/3.DLiDQm__.js.gz +0 -0
- package/web/build/server/chunks/1-C7zcB0q0.js +0 -7
- package/web/build/server/chunks/2-v6ejI_0-.js +0 -7
- package/web/build/server/chunks/2-v6ejI_0-.js.map +0 -1
- package/web/build/server/chunks/3-DAAmG6VX.js +0 -7
- package/web/build/server/chunks/agent-sessions-DSqGavSn.js.map +0 -1
- /package/web/build/client/_app/immutable/nodes/{0.Cak4ehiE.js → 0.Dj97JW46.js} +0 -0
- /package/web/build/client/_app/immutable/nodes/{0.Cak4ehiE.js.br → 0.Dj97JW46.js.br} +0 -0
- /package/web/build/client/_app/immutable/nodes/{0.Cak4ehiE.js.gz → 0.Dj97JW46.js.gz} +0 -0
package/lib/model-label.test.mjs
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { test } from "node:test";
|
|
3
|
-
import {
|
|
4
|
-
buildAcpModelSelectOptions,
|
|
5
|
-
compactModelMeta,
|
|
6
|
-
formatModelOption,
|
|
7
|
-
humanizeModelId,
|
|
8
|
-
modelOptionLabel,
|
|
9
|
-
} from "./model-label.mjs";
|
|
10
|
-
|
|
11
|
-
test("humanizeModelId", () => {
|
|
12
|
-
assert.equal(humanizeModelId("claude-opus-5-5"), "Claude Opus 5.5");
|
|
13
|
-
assert.equal(humanizeModelId("claude-sonnet-5.5"), "Claude Sonnet 5.5");
|
|
14
|
-
assert.equal(humanizeModelId("gemini-3.8-flash"), "Gemini 3.8 Flash");
|
|
15
|
-
assert.equal(humanizeModelId("gpt-5.6-sol"), "GPT 5.6 Sol");
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test("compactModelMeta", () => {
|
|
19
|
-
assert.deepEqual(compactModelMeta("context=300k,effort=medium,fast=false"), ["300k", "medium"]);
|
|
20
|
-
assert.deepEqual(compactModelMeta("thinking=true,context=300k,effort=high,fast=false"), [
|
|
21
|
-
"thinking",
|
|
22
|
-
"300k",
|
|
23
|
-
"high",
|
|
24
|
-
]);
|
|
25
|
-
assert.deepEqual(compactModelMeta("1m"), ["1m"]);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test("formatModelOption compacto y amigable", () => {
|
|
29
|
-
const a = formatModelOption("claude-opus-5-5", "claude-opus-5-5[context=300k,effort=medium,fast=false]");
|
|
30
|
-
assert.equal(a.title, "Claude Opus 5.5");
|
|
31
|
-
assert.deepEqual(a.badges, ["300k", "medium"]);
|
|
32
|
-
assert.equal(a.label, "Claude Opus 5.5 · [ 300k, medium ]");
|
|
33
|
-
assert.equal(a.hint, "[ 300k, medium ]");
|
|
34
|
-
|
|
35
|
-
const b = formatModelOption("Claude Sonnet 5.5", "claude-sonnet-5.5");
|
|
36
|
-
assert.equal(b.title, "Claude Sonnet 5.5");
|
|
37
|
-
assert.deepEqual(b.badges, []);
|
|
38
|
-
assert.equal(b.label, "Claude Sonnet 5.5");
|
|
39
|
-
|
|
40
|
-
const c = formatModelOption("Sonnet (1M context)", "sonnet[1m]");
|
|
41
|
-
assert.equal(c.title, "Sonnet (1M context)");
|
|
42
|
-
assert.deepEqual(c.badges, []);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test("buildAcpModelSelectOptions fusiona aliases y formatea ACP", () => {
|
|
46
|
-
const { options } = buildAcpModelSelectOptions(
|
|
47
|
-
{
|
|
48
|
-
currentModel: "default",
|
|
49
|
-
models: [
|
|
50
|
-
{ value: "default", name: "Default (recommended)" },
|
|
51
|
-
{
|
|
52
|
-
value: "claude-opus-5-5[context=300k,effort=medium,fast=false]",
|
|
53
|
-
name: "claude-opus-5-5",
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
options: [
|
|
59
|
-
{ value: "", label: "Por defecto (opus)" },
|
|
60
|
-
{ value: "opus", label: "opus", hint: "el más capaz" },
|
|
61
|
-
],
|
|
62
|
-
}
|
|
63
|
-
);
|
|
64
|
-
assert.equal(options[0].label, "Por defecto (opus)");
|
|
65
|
-
assert.ok(options.some((o) => o.value === "opus"));
|
|
66
|
-
const opusAcp = options.find((o) => o.value.startsWith("claude-opus-5-5"));
|
|
67
|
-
assert.equal(opusAcp?.title, "Claude Opus 5.5");
|
|
68
|
-
assert.deepEqual(opusAcp?.badges, ["300k", "medium"]);
|
|
69
|
-
assert.equal(opusAcp?.hint, "[ 300k, medium ]");
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test("modelOptionLabel compat", () => {
|
|
73
|
-
assert.equal(
|
|
74
|
-
modelOptionLabel("grok-4.7", "grok-4.7[context=256k,fast=true]"),
|
|
75
|
-
"Grok 4.7 · [ 256k, fast ]"
|
|
76
|
-
);
|
|
77
|
-
});
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import {
|
|
4
|
+
buildAcpModelSelectOptions,
|
|
5
|
+
compactModelMeta,
|
|
6
|
+
formatModelOption,
|
|
7
|
+
humanizeModelId,
|
|
8
|
+
modelOptionLabel,
|
|
9
|
+
} from "./model-label.mjs";
|
|
10
|
+
|
|
11
|
+
test("humanizeModelId", () => {
|
|
12
|
+
assert.equal(humanizeModelId("claude-opus-5-5"), "Claude Opus 5.5");
|
|
13
|
+
assert.equal(humanizeModelId("claude-sonnet-5.5"), "Claude Sonnet 5.5");
|
|
14
|
+
assert.equal(humanizeModelId("gemini-3.8-flash"), "Gemini 3.8 Flash");
|
|
15
|
+
assert.equal(humanizeModelId("gpt-5.6-sol"), "GPT 5.6 Sol");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("compactModelMeta", () => {
|
|
19
|
+
assert.deepEqual(compactModelMeta("context=300k,effort=medium,fast=false"), ["300k", "medium"]);
|
|
20
|
+
assert.deepEqual(compactModelMeta("thinking=true,context=300k,effort=high,fast=false"), [
|
|
21
|
+
"thinking",
|
|
22
|
+
"300k",
|
|
23
|
+
"high",
|
|
24
|
+
]);
|
|
25
|
+
assert.deepEqual(compactModelMeta("1m"), ["1m"]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("formatModelOption compacto y amigable", () => {
|
|
29
|
+
const a = formatModelOption("claude-opus-5-5", "claude-opus-5-5[context=300k,effort=medium,fast=false]");
|
|
30
|
+
assert.equal(a.title, "Claude Opus 5.5");
|
|
31
|
+
assert.deepEqual(a.badges, ["300k", "medium"]);
|
|
32
|
+
assert.equal(a.label, "Claude Opus 5.5 · [ 300k, medium ]");
|
|
33
|
+
assert.equal(a.hint, "[ 300k, medium ]");
|
|
34
|
+
|
|
35
|
+
const b = formatModelOption("Claude Sonnet 5.5", "claude-sonnet-5.5");
|
|
36
|
+
assert.equal(b.title, "Claude Sonnet 5.5");
|
|
37
|
+
assert.deepEqual(b.badges, []);
|
|
38
|
+
assert.equal(b.label, "Claude Sonnet 5.5");
|
|
39
|
+
|
|
40
|
+
const c = formatModelOption("Sonnet (1M context)", "sonnet[1m]");
|
|
41
|
+
assert.equal(c.title, "Sonnet (1M context)");
|
|
42
|
+
assert.deepEqual(c.badges, []);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("buildAcpModelSelectOptions fusiona aliases y formatea ACP", () => {
|
|
46
|
+
const { options } = buildAcpModelSelectOptions(
|
|
47
|
+
{
|
|
48
|
+
currentModel: "default",
|
|
49
|
+
models: [
|
|
50
|
+
{ value: "default", name: "Default (recommended)" },
|
|
51
|
+
{
|
|
52
|
+
value: "claude-opus-5-5[context=300k,effort=medium,fast=false]",
|
|
53
|
+
name: "claude-opus-5-5",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
options: [
|
|
59
|
+
{ value: "", label: "Por defecto (opus)" },
|
|
60
|
+
{ value: "opus", label: "opus", hint: "el más capaz" },
|
|
61
|
+
],
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
assert.equal(options[0].label, "Por defecto (opus)");
|
|
65
|
+
assert.ok(options.some((o) => o.value === "opus"));
|
|
66
|
+
const opusAcp = options.find((o) => o.value.startsWith("claude-opus-5-5"));
|
|
67
|
+
assert.equal(opusAcp?.title, "Claude Opus 5.5");
|
|
68
|
+
assert.deepEqual(opusAcp?.badges, ["300k", "medium"]);
|
|
69
|
+
assert.equal(opusAcp?.hint, "[ 300k, medium ]");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("modelOptionLabel compat", () => {
|
|
73
|
+
assert.equal(
|
|
74
|
+
modelOptionLabel("grok-4.7", "grok-4.7[context=256k,fast=true]"),
|
|
75
|
+
"Grok 4.7 · [ 256k, fast ]"
|
|
76
|
+
);
|
|
77
|
+
});
|
package/lib/models-cache.mjs
CHANGED
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Caché en disco de las listas de modelos ACP por agente.
|
|
3
|
-
* TTL 24h: los catálogos cambian de a poco (semanas); un día evita spawnear el CLI en cada review
|
|
4
|
-
* y sigue fresco si aparece un modelo nuevo.
|
|
5
|
-
*/
|
|
6
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
|
-
import { homedir } from "node:os";
|
|
8
|
-
import { dirname, join } from "node:path";
|
|
9
|
-
|
|
10
|
-
/** 24 horas. */
|
|
11
|
-
export const MODELS_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
12
|
-
|
|
13
|
-
/** @returns {string} */
|
|
14
|
-
export function modelsCachePath(home = homedir()) {
|
|
15
|
-
return join(home, ".diff-review", "models-cache.json");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @param {string} agentId
|
|
20
|
-
* @param {{ home?: string, now?: number, ttlMs?: number }} [opts]
|
|
21
|
-
* @returns {{ models: { value: string, name: string }[], currentModel: string, fetchedAt: string } | null}
|
|
22
|
-
*/
|
|
23
|
-
export function readModelsCache(agentId, opts = {}) {
|
|
24
|
-
const id = String(agentId || "").trim();
|
|
25
|
-
if (!id) return null;
|
|
26
|
-
const path = modelsCachePath(opts.home);
|
|
27
|
-
let root;
|
|
28
|
-
try {
|
|
29
|
-
root = JSON.parse(readFileSync(path, "utf8"));
|
|
30
|
-
} catch {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
const entry = root?.agents?.[id];
|
|
34
|
-
if (!entry || !Array.isArray(entry.models)) return null;
|
|
35
|
-
const fetchedAt = Date.parse(String(entry.fetchedAt || ""));
|
|
36
|
-
if (!Number.isFinite(fetchedAt)) return null;
|
|
37
|
-
const ttl = opts.ttlMs ?? MODELS_CACHE_TTL_MS;
|
|
38
|
-
const now = opts.now ?? Date.now();
|
|
39
|
-
if (now - fetchedAt > ttl) return null;
|
|
40
|
-
return {
|
|
41
|
-
models: entry.models
|
|
42
|
-
.filter((m) => m && typeof m.value === "string")
|
|
43
|
-
.map((m) => ({ value: m.value, name: String(m.name ?? m.value) })),
|
|
44
|
-
currentModel: String(entry.currentModel ?? ""),
|
|
45
|
-
fetchedAt: new Date(fetchedAt).toISOString(),
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @param {string} agentId
|
|
51
|
-
* @param {{ models: { value: string, name: string }[], currentModel?: string }} data
|
|
52
|
-
* @param {{ home?: string, now?: number }} [opts]
|
|
53
|
-
*/
|
|
54
|
-
export function writeModelsCache(agentId, data, opts = {}) {
|
|
55
|
-
const id = String(agentId || "").trim();
|
|
56
|
-
if (!id || !Array.isArray(data?.models) || !data.models.length) return;
|
|
57
|
-
const path = modelsCachePath(opts.home);
|
|
58
|
-
let root = { version: 1, agents: {} };
|
|
59
|
-
try {
|
|
60
|
-
if (existsSync(path)) root = { ...root, ...JSON.parse(readFileSync(path, "utf8")) };
|
|
61
|
-
} catch {
|
|
62
|
-
/* archivo nuevo */
|
|
63
|
-
}
|
|
64
|
-
if (!root.agents || typeof root.agents !== "object") root.agents = {};
|
|
65
|
-
root.agents[id] = {
|
|
66
|
-
fetchedAt: new Date(opts.now ?? Date.now()).toISOString(),
|
|
67
|
-
currentModel: String(data.currentModel ?? ""),
|
|
68
|
-
models: data.models.map((m) => ({
|
|
69
|
-
value: String(m.value),
|
|
70
|
-
name: String(m.name ?? m.value),
|
|
71
|
-
})),
|
|
72
|
-
};
|
|
73
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
74
|
-
writeFileSync(path, `${JSON.stringify(root, null, 2)}\n`);
|
|
75
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Caché en disco de las listas de modelos ACP por agente.
|
|
3
|
+
* TTL 24h: los catálogos cambian de a poco (semanas); un día evita spawnear el CLI en cada review
|
|
4
|
+
* y sigue fresco si aparece un modelo nuevo.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
|
|
10
|
+
/** 24 horas. */
|
|
11
|
+
export const MODELS_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
12
|
+
|
|
13
|
+
/** @returns {string} */
|
|
14
|
+
export function modelsCachePath(home = homedir()) {
|
|
15
|
+
return join(home, ".diff-review", "models-cache.json");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {string} agentId
|
|
20
|
+
* @param {{ home?: string, now?: number, ttlMs?: number }} [opts]
|
|
21
|
+
* @returns {{ models: { value: string, name: string }[], currentModel: string, fetchedAt: string } | null}
|
|
22
|
+
*/
|
|
23
|
+
export function readModelsCache(agentId, opts = {}) {
|
|
24
|
+
const id = String(agentId || "").trim();
|
|
25
|
+
if (!id) return null;
|
|
26
|
+
const path = modelsCachePath(opts.home);
|
|
27
|
+
let root;
|
|
28
|
+
try {
|
|
29
|
+
root = JSON.parse(readFileSync(path, "utf8"));
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const entry = root?.agents?.[id];
|
|
34
|
+
if (!entry || !Array.isArray(entry.models)) return null;
|
|
35
|
+
const fetchedAt = Date.parse(String(entry.fetchedAt || ""));
|
|
36
|
+
if (!Number.isFinite(fetchedAt)) return null;
|
|
37
|
+
const ttl = opts.ttlMs ?? MODELS_CACHE_TTL_MS;
|
|
38
|
+
const now = opts.now ?? Date.now();
|
|
39
|
+
if (now - fetchedAt > ttl) return null;
|
|
40
|
+
return {
|
|
41
|
+
models: entry.models
|
|
42
|
+
.filter((m) => m && typeof m.value === "string")
|
|
43
|
+
.map((m) => ({ value: m.value, name: String(m.name ?? m.value) })),
|
|
44
|
+
currentModel: String(entry.currentModel ?? ""),
|
|
45
|
+
fetchedAt: new Date(fetchedAt).toISOString(),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {string} agentId
|
|
51
|
+
* @param {{ models: { value: string, name: string }[], currentModel?: string }} data
|
|
52
|
+
* @param {{ home?: string, now?: number }} [opts]
|
|
53
|
+
*/
|
|
54
|
+
export function writeModelsCache(agentId, data, opts = {}) {
|
|
55
|
+
const id = String(agentId || "").trim();
|
|
56
|
+
if (!id || !Array.isArray(data?.models) || !data.models.length) return;
|
|
57
|
+
const path = modelsCachePath(opts.home);
|
|
58
|
+
let root = { version: 1, agents: {} };
|
|
59
|
+
try {
|
|
60
|
+
if (existsSync(path)) root = { ...root, ...JSON.parse(readFileSync(path, "utf8")) };
|
|
61
|
+
} catch {
|
|
62
|
+
/* archivo nuevo */
|
|
63
|
+
}
|
|
64
|
+
if (!root.agents || typeof root.agents !== "object") root.agents = {};
|
|
65
|
+
root.agents[id] = {
|
|
66
|
+
fetchedAt: new Date(opts.now ?? Date.now()).toISOString(),
|
|
67
|
+
currentModel: String(data.currentModel ?? ""),
|
|
68
|
+
models: data.models.map((m) => ({
|
|
69
|
+
value: String(m.value),
|
|
70
|
+
name: String(m.name ?? m.value),
|
|
71
|
+
})),
|
|
72
|
+
};
|
|
73
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
74
|
+
writeFileSync(path, `${JSON.stringify(root, null, 2)}\n`);
|
|
75
|
+
}
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdtempSync, readFileSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { test } from "node:test";
|
|
6
|
-
import {
|
|
7
|
-
MODELS_CACHE_TTL_MS,
|
|
8
|
-
modelsCachePath,
|
|
9
|
-
readModelsCache,
|
|
10
|
-
writeModelsCache,
|
|
11
|
-
} from "./models-cache.mjs";
|
|
12
|
-
import { sortModelSelectOptions } from "./model-label.mjs";
|
|
13
|
-
|
|
14
|
-
test("sortModelSelectOptions: default y auto primero, resto lexico", () => {
|
|
15
|
-
const sorted = sortModelSelectOptions([
|
|
16
|
-
{ value: "zulu", label: "Zulu" },
|
|
17
|
-
{ value: "auto", label: "Auto" },
|
|
18
|
-
{ value: "alpha", label: "Alpha" },
|
|
19
|
-
{ value: "", label: "Por defecto" },
|
|
20
|
-
{ value: "bravo", label: "Bravo" },
|
|
21
|
-
]);
|
|
22
|
-
assert.deepEqual(
|
|
23
|
-
sorted.map((o) => o.value),
|
|
24
|
-
["", "auto", "alpha", "bravo", "zulu"]
|
|
25
|
-
);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test("models cache roundtrip + TTL", () => {
|
|
29
|
-
const home = mkdtempSync(join(tmpdir(), "diff-review-mc-"));
|
|
30
|
-
const now = Date.parse("2026-01-01T12:00:00.000Z");
|
|
31
|
-
writeModelsCache(
|
|
32
|
-
"claude",
|
|
33
|
-
{
|
|
34
|
-
models: [{ value: "opus", name: "Opus" }],
|
|
35
|
-
currentModel: "default",
|
|
36
|
-
},
|
|
37
|
-
{ home, now }
|
|
38
|
-
);
|
|
39
|
-
assert.ok(readFileSync(modelsCachePath(home), "utf8").includes("opus"));
|
|
40
|
-
|
|
41
|
-
const hit = readModelsCache("claude", { home, now: now + 1000 });
|
|
42
|
-
assert.equal(hit?.currentModel, "default");
|
|
43
|
-
assert.equal(hit?.models[0].value, "opus");
|
|
44
|
-
|
|
45
|
-
const expired = readModelsCache("claude", {
|
|
46
|
-
home,
|
|
47
|
-
now: now + MODELS_CACHE_TTL_MS + 1,
|
|
48
|
-
});
|
|
49
|
-
assert.equal(expired, null);
|
|
50
|
-
});
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtempSync, readFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { test } from "node:test";
|
|
6
|
+
import {
|
|
7
|
+
MODELS_CACHE_TTL_MS,
|
|
8
|
+
modelsCachePath,
|
|
9
|
+
readModelsCache,
|
|
10
|
+
writeModelsCache,
|
|
11
|
+
} from "./models-cache.mjs";
|
|
12
|
+
import { sortModelSelectOptions } from "./model-label.mjs";
|
|
13
|
+
|
|
14
|
+
test("sortModelSelectOptions: default y auto primero, resto lexico", () => {
|
|
15
|
+
const sorted = sortModelSelectOptions([
|
|
16
|
+
{ value: "zulu", label: "Zulu" },
|
|
17
|
+
{ value: "auto", label: "Auto" },
|
|
18
|
+
{ value: "alpha", label: "Alpha" },
|
|
19
|
+
{ value: "", label: "Por defecto" },
|
|
20
|
+
{ value: "bravo", label: "Bravo" },
|
|
21
|
+
]);
|
|
22
|
+
assert.deepEqual(
|
|
23
|
+
sorted.map((o) => o.value),
|
|
24
|
+
["", "auto", "alpha", "bravo", "zulu"]
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("models cache roundtrip + TTL", () => {
|
|
29
|
+
const home = mkdtempSync(join(tmpdir(), "diff-review-mc-"));
|
|
30
|
+
const now = Date.parse("2026-01-01T12:00:00.000Z");
|
|
31
|
+
writeModelsCache(
|
|
32
|
+
"claude",
|
|
33
|
+
{
|
|
34
|
+
models: [{ value: "opus", name: "Opus" }],
|
|
35
|
+
currentModel: "default",
|
|
36
|
+
},
|
|
37
|
+
{ home, now }
|
|
38
|
+
);
|
|
39
|
+
assert.ok(readFileSync(modelsCachePath(home), "utf8").includes("opus"));
|
|
40
|
+
|
|
41
|
+
const hit = readModelsCache("claude", { home, now: now + 1000 });
|
|
42
|
+
assert.equal(hit?.currentModel, "default");
|
|
43
|
+
assert.equal(hit?.models[0].value, "opus");
|
|
44
|
+
|
|
45
|
+
const expired = readModelsCache("claude", {
|
|
46
|
+
home,
|
|
47
|
+
now: now + MODELS_CACHE_TTL_MS + 1,
|
|
48
|
+
});
|
|
49
|
+
assert.equal(expired, null);
|
|
50
|
+
});
|
package/lib/review-prep.mjs
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Precomputa contexto git para el prompt de review (diff cache + lista de archivos).
|
|
3
|
-
*/
|
|
4
|
-
import { loadReviewConfig } from "./config.mjs";
|
|
5
|
-
import { extractBranchDiff } from "./extract.mjs";
|
|
6
|
-
import { outputRelPath } from "./output-name.mjs";
|
|
7
|
-
import { ensureReviewDir, readDiffCache, writeDiffCache } from "./review-dir.mjs";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Cachea el three-dot diff y arma las opciones de `buildPrompt` (tips, files, ignores).
|
|
11
|
-
* @param {{
|
|
12
|
-
* repo: string,
|
|
13
|
-
* branch: string,
|
|
14
|
-
* base?: string,
|
|
15
|
-
* outputFilename: string,
|
|
16
|
-
* acp?: boolean,
|
|
17
|
-
* }} input
|
|
18
|
-
*/
|
|
19
|
-
export function prepareReviewPromptOpts(input) {
|
|
20
|
-
const repo = String(input.repo || "").trim();
|
|
21
|
-
const branch = String(input.branch || "").trim();
|
|
22
|
-
const base = String(input.base || "develop").trim() || "develop";
|
|
23
|
-
const outputFilename = String(input.outputFilename || "").trim();
|
|
24
|
-
if (!repo || !branch || !outputFilename) {
|
|
25
|
-
throw new Error("prepareReviewPromptOpts requiere repo, branch y outputFilename.");
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
ensureReviewDir(repo);
|
|
29
|
-
writeDiffCache(repo, outputFilename, { branch, base });
|
|
30
|
-
const cached = readDiffCache(repo, outputFilename);
|
|
31
|
-
|
|
32
|
-
let extracted;
|
|
33
|
-
try {
|
|
34
|
-
extracted = extractBranchDiff({
|
|
35
|
-
repo,
|
|
36
|
-
branch,
|
|
37
|
-
base,
|
|
38
|
-
...(cached ? { cachedDiff: cached } : {}),
|
|
39
|
-
});
|
|
40
|
-
} catch {
|
|
41
|
-
extracted = extractBranchDiff({ repo, branch, base });
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const config = loadReviewConfig(repo);
|
|
45
|
-
const diffRelPath = cached
|
|
46
|
-
? outputRelPath(outputFilename).replace(/\.json$/i, ".diff")
|
|
47
|
-
: null;
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
outputFilename,
|
|
51
|
-
acp: Boolean(input.acp),
|
|
52
|
-
diffRelPath,
|
|
53
|
-
mergeBase: extracted.mergeBase || undefined,
|
|
54
|
-
branchSha: extracted.branchSha || undefined,
|
|
55
|
-
baseSha: extracted.baseSha || undefined,
|
|
56
|
-
files: (extracted.files || []).map((f) => ({
|
|
57
|
-
path: f.path,
|
|
58
|
-
changeType: f.changeType,
|
|
59
|
-
})),
|
|
60
|
-
ignored: extracted.context?.ignored || [],
|
|
61
|
-
ignoreGlobs: config.ignore,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Precomputa contexto git para el prompt de review (diff cache + lista de archivos).
|
|
3
|
+
*/
|
|
4
|
+
import { loadReviewConfig } from "./config.mjs";
|
|
5
|
+
import { extractBranchDiff } from "./extract.mjs";
|
|
6
|
+
import { outputRelPath } from "./output-name.mjs";
|
|
7
|
+
import { ensureReviewDir, readDiffCache, writeDiffCache } from "./review-dir.mjs";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Cachea el three-dot diff y arma las opciones de `buildPrompt` (tips, files, ignores).
|
|
11
|
+
* @param {{
|
|
12
|
+
* repo: string,
|
|
13
|
+
* branch: string,
|
|
14
|
+
* base?: string,
|
|
15
|
+
* outputFilename: string,
|
|
16
|
+
* acp?: boolean,
|
|
17
|
+
* }} input
|
|
18
|
+
*/
|
|
19
|
+
export function prepareReviewPromptOpts(input) {
|
|
20
|
+
const repo = String(input.repo || "").trim();
|
|
21
|
+
const branch = String(input.branch || "").trim();
|
|
22
|
+
const base = String(input.base || "develop").trim() || "develop";
|
|
23
|
+
const outputFilename = String(input.outputFilename || "").trim();
|
|
24
|
+
if (!repo || !branch || !outputFilename) {
|
|
25
|
+
throw new Error("prepareReviewPromptOpts requiere repo, branch y outputFilename.");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
ensureReviewDir(repo);
|
|
29
|
+
writeDiffCache(repo, outputFilename, { branch, base });
|
|
30
|
+
const cached = readDiffCache(repo, outputFilename);
|
|
31
|
+
|
|
32
|
+
let extracted;
|
|
33
|
+
try {
|
|
34
|
+
extracted = extractBranchDiff({
|
|
35
|
+
repo,
|
|
36
|
+
branch,
|
|
37
|
+
base,
|
|
38
|
+
...(cached ? { cachedDiff: cached } : {}),
|
|
39
|
+
});
|
|
40
|
+
} catch {
|
|
41
|
+
extracted = extractBranchDiff({ repo, branch, base });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const config = loadReviewConfig(repo);
|
|
45
|
+
const diffRelPath = cached
|
|
46
|
+
? outputRelPath(outputFilename).replace(/\.json$/i, ".diff")
|
|
47
|
+
: null;
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
outputFilename,
|
|
51
|
+
acp: Boolean(input.acp),
|
|
52
|
+
diffRelPath,
|
|
53
|
+
mergeBase: extracted.mergeBase || undefined,
|
|
54
|
+
branchSha: extracted.branchSha || undefined,
|
|
55
|
+
baseSha: extracted.baseSha || undefined,
|
|
56
|
+
files: (extracted.files || []).map((f) => ({
|
|
57
|
+
path: f.path,
|
|
58
|
+
changeType: f.changeType,
|
|
59
|
+
})),
|
|
60
|
+
ignored: extracted.context?.ignored || [],
|
|
61
|
+
ignoreGlobs: config.ignore,
|
|
62
|
+
};
|
|
63
|
+
}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--bg:#0b0e14;--bg-elev:#11151d;--bg-card:#151a24;--bg-card-hover:#1a2130;--border:#242b3a;--border-soft:#1c2230;--text:#e6e9ef;--text-dim:#9aa4b8;--text-faint:#5f6b82;--accent:#6ea8fe;--accent-soft:#1c2b45;--ok:#7ee2a8;--ok-bg:#0d2a1c;--warn:#e2c67e;--danger:#ff9a9a;--danger-bg:#2a1414;--danger-border:#4a1e1e;--mono:ui-monospace, "JetBrains Mono", "Fira Code", Consolas, "SFMono-Regular", Menlo, monospace;--sans:-apple-system, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;--btn-primary-bg:#1c2b45;--btn-primary-border:#3a5a8f;--btn-primary-text:#cfe0ff;--kind-feat:#7ee2a8;--kind-fix:#ff9a9a;--kind-refactor:#c9a5ff;--kind-perf:#e2c67e;--kind-test:#6ea8fe;--kind-chore:#9aa4b8;--kind-docs:#7fd6e0;--kind-infra:#f0a868;--sev-high:#ff9a9a;--sev-med:#f08a5a;--sev-low:#c4b86a;--sev-nit:#7f8aa3;--diff-add-bg:#0f2419;--diff-add-fg:#7ee2a8;--diff-del-bg:#2a1418;--diff-del-fg:#ff9a9a;--diff-hunk-bg:#141924;--diff-gutter:#46516a;--diff-mark:#2b3f63;--diff-mark-edge:#6ea8fe;--diff-add-strong:#1f6b3c;--diff-del-strong:#6d2530;--diff-blank-bg:repeating-linear-gradient(135deg, #11151d 0 6px, #151a24 6px 12px);--fix-bg:#0e1a13;--fix-border:#2f6b46;--fix-text:#7ee2a8;--publish-bg:#0e1622;--publish-border:#3a5a8f;--publish-text:#7db8ff;--scrollbar-thumb:#2a3348;--scrollbar-thumb-hover:#3a4660;--selection-bg:#33507a;--header-bg:#0b0e14eb}:root[data-theme=light]{--bg:#fff;--bg-elev:#f6f7f9;--bg-card:#eef0f3;--bg-card-hover:#e4e7ec;--border:#d7dbe2;--border-soft:#e4e7ec;--text:#16181d;--text-dim:#4b5563;--text-faint:#6b7280;--accent:#2f6fe0;--accent-soft:#dce8ff;--ok:#1f9d55;--ok-bg:#e3f8ea;--warn:#a5720a;--danger:#c92a2a;--danger-bg:#fbe4e4;--danger-border:#f3b4b4;--btn-primary-bg:#2f6fe0;--btn-primary-border:#2358b8;--btn-primary-text:#fff;--kind-feat:#1f9d55;--kind-fix:#c92a2a;--kind-refactor:#7c4dd6;--kind-perf:#a5720a;--kind-test:#2f6fe0;--kind-chore:#5b6472;--kind-docs:#0f8fa3;--kind-infra:#c1690f;--sev-high:#c92a2a;--sev-med:#c44d1a;--sev-low:#8b7d2e;--sev-nit:#6b7280;--diff-add-bg:#e6f7ec;--diff-add-fg:#1f9d55;--diff-del-bg:#fbe9e9;--diff-del-fg:#c92a2a;--diff-hunk-bg:#eef1f5;--diff-gutter:#9aa3b2;--diff-mark:#cfe0ff;--diff-mark-edge:#2f6fe0;--diff-add-strong:#a7ebbd;--diff-del-strong:#f9b8b8;--diff-blank-bg:repeating-linear-gradient(135deg, #f6f7f9 0 6px, #eef0f3 6px 12px);--fix-bg:#e6f7ec;--fix-border:#1f9d55;--fix-text:#157a41;--publish-bg:#e8f0fe;--publish-border:#2f6fe0;--publish-text:#1d4fa8;--scrollbar-thumb:#c7cbd4;--scrollbar-thumb-hover:#aab0bb;--selection-bg:#cfe0ff;--header-bg:#ffffffeb}.code .chg{border-radius:2px}.code.del .chg{background:var(--diff-del-strong)}.code.add .chg{background:var(--diff-add-strong)}.hljs-comment,.hljs-quote{color:#6b7689;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-doctag,.hljs-formula{color:#c9a5ff}.hljs-string,.hljs-regexp,.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string{color:#a5d6a7}.hljs-number,.hljs-variable,.hljs-template-variable,.hljs-type,.hljs-selector-class,.hljs-selector-attr,.hljs-selector-pseudo{color:#f0a868}.hljs-title,.hljs-section,.hljs-title.class_,.hljs-title.function_{color:#7fd6e0}.hljs-attr,.hljs-property,.hljs-symbol,.hljs-bullet,.hljs-link{color:#6ea8fe}.hljs-built_in,.hljs-class,.hljs-params{color:#e6e9ef}.hljs-meta,.hljs-tag{color:#9aa4b8}:root[data-theme=light] .hljs-comment,:root[data-theme=light] .hljs-quote{color:#6b7280}:root[data-theme=light] .hljs-keyword,:root[data-theme=light] .hljs-selector-tag,:root[data-theme=light] .hljs-literal,:root[data-theme=light] .hljs-doctag,:root[data-theme=light] .hljs-formula{color:#7c4dd6}:root[data-theme=light] .hljs-string,:root[data-theme=light] .hljs-regexp,:root[data-theme=light] .hljs-addition,:root[data-theme=light] .hljs-attribute,:root[data-theme=light] .hljs-meta .hljs-string{color:#1f9d55}:root[data-theme=light] .hljs-number,:root[data-theme=light] .hljs-variable,:root[data-theme=light] .hljs-template-variable,:root[data-theme=light] .hljs-type,:root[data-theme=light] .hljs-selector-class,:root[data-theme=light] .hljs-selector-attr,:root[data-theme=light] .hljs-selector-pseudo{color:#b5650f}:root[data-theme=light] .hljs-title,:root[data-theme=light] .hljs-section,:root[data-theme=light] .hljs-title.class_,:root[data-theme=light] .hljs-title.function_{color:#0f8fa3}:root[data-theme=light] .hljs-attr,:root[data-theme=light] .hljs-property,:root[data-theme=light] .hljs-symbol,:root[data-theme=light] .hljs-bullet,:root[data-theme=light] .hljs-link{color:#2f6fe0}:root[data-theme=light] .hljs-built_in,:root[data-theme=light] .hljs-class,:root[data-theme=light] .hljs-params{color:#16181d}:root[data-theme=light] .hljs-meta,:root[data-theme=light] .hljs-tag{color:#5b6472}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.anchor-flash{animation:1.4s ease-out anchor-flash}@keyframes anchor-flash{0%{box-shadow:0 0 0 2px var(--accent)}to{box-shadow:0 0 0 2px #0000}}*{box-sizing:border-box}html,body{background:var(--bg);color:var(--text);font-family:var(--sans);min-height:100%;margin:0;padding:0}body{-webkit-font-smoothing:antialiased}button,input,select{font:inherit;color:inherit}button{cursor:pointer}::selection{background:var(--selection-bg)}html,body,*{scrollbar-width:thin;scrollbar-color:var(--scrollbar-thumb) transparent}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);background-clip:padding-box;border:2px solid #0000;border-radius:999px}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover);background-clip:padding-box;border:2px solid #0000}::-webkit-scrollbar-corner{background:0 0}.boot.svelte-12qhfyh{color:var(--text-dim);font-family:var(--mono);padding:48px 28px;font-size:13px}.boot.svelte-12qhfyh button:where(.svelte-12qhfyh){background:var(--btn-primary-bg);border:1px solid var(--btn-primary-border);color:var(--btn-primary-text);border-radius:
|
|
1
|
+
:root{--bg:#0b0e14;--bg-elev:#11151d;--bg-card:#151a24;--bg-card-hover:#1a2130;--border:#242b3a;--border-soft:#1c2230;--text:#e6e9ef;--text-dim:#9aa4b8;--text-faint:#5f6b82;--accent:#6ea8fe;--accent-soft:#1c2b45;--ok:#7ee2a8;--ok-bg:#0d2a1c;--warn:#e2c67e;--danger:#ff9a9a;--danger-bg:#2a1414;--danger-border:#4a1e1e;--mono:ui-monospace, "JetBrains Mono", "Fira Code", Consolas, "SFMono-Regular", Menlo, monospace;--sans:-apple-system, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;--btn-primary-bg:#1c2b45;--btn-primary-border:#3a5a8f;--btn-primary-text:#cfe0ff;--kind-feat:#7ee2a8;--kind-fix:#ff9a9a;--kind-refactor:#c9a5ff;--kind-perf:#e2c67e;--kind-test:#6ea8fe;--kind-chore:#9aa4b8;--kind-docs:#7fd6e0;--kind-infra:#f0a868;--sev-high:#ff9a9a;--sev-med:#f08a5a;--sev-low:#c4b86a;--sev-nit:#7f8aa3;--diff-add-bg:#0f2419;--diff-add-fg:#7ee2a8;--diff-del-bg:#2a1418;--diff-del-fg:#ff9a9a;--diff-hunk-bg:#141924;--diff-gutter:#46516a;--diff-mark:#2b3f63;--diff-mark-edge:#6ea8fe;--diff-add-strong:#1f6b3c;--diff-del-strong:#6d2530;--diff-blank-bg:repeating-linear-gradient(135deg, #11151d 0 6px, #151a24 6px 12px);--fix-bg:#0e1a13;--fix-border:#2f6b46;--fix-text:#7ee2a8;--publish-bg:#0e1622;--publish-border:#3a5a8f;--publish-text:#7db8ff;--scrollbar-thumb:#2a3348;--scrollbar-thumb-hover:#3a4660;--selection-bg:#33507a;--header-bg:#0b0e14eb}:root[data-theme=light]{--bg:#fff;--bg-elev:#f6f7f9;--bg-card:#eef0f3;--bg-card-hover:#e4e7ec;--border:#d7dbe2;--border-soft:#e4e7ec;--text:#16181d;--text-dim:#4b5563;--text-faint:#6b7280;--accent:#2f6fe0;--accent-soft:#dce8ff;--ok:#1f9d55;--ok-bg:#e3f8ea;--warn:#a5720a;--danger:#c92a2a;--danger-bg:#fbe4e4;--danger-border:#f3b4b4;--btn-primary-bg:#2f6fe0;--btn-primary-border:#2358b8;--btn-primary-text:#fff;--kind-feat:#1f9d55;--kind-fix:#c92a2a;--kind-refactor:#7c4dd6;--kind-perf:#a5720a;--kind-test:#2f6fe0;--kind-chore:#5b6472;--kind-docs:#0f8fa3;--kind-infra:#c1690f;--sev-high:#c92a2a;--sev-med:#c44d1a;--sev-low:#8b7d2e;--sev-nit:#6b7280;--diff-add-bg:#e6f7ec;--diff-add-fg:#1f9d55;--diff-del-bg:#fbe9e9;--diff-del-fg:#c92a2a;--diff-hunk-bg:#eef1f5;--diff-gutter:#9aa3b2;--diff-mark:#cfe0ff;--diff-mark-edge:#2f6fe0;--diff-add-strong:#a7ebbd;--diff-del-strong:#f9b8b8;--diff-blank-bg:repeating-linear-gradient(135deg, #f6f7f9 0 6px, #eef0f3 6px 12px);--fix-bg:#e6f7ec;--fix-border:#1f9d55;--fix-text:#157a41;--publish-bg:#e8f0fe;--publish-border:#2f6fe0;--publish-text:#1d4fa8;--scrollbar-thumb:#c7cbd4;--scrollbar-thumb-hover:#aab0bb;--selection-bg:#cfe0ff;--header-bg:#ffffffeb}.code .chg{border-radius:2px}.code.del .chg{background:var(--diff-del-strong)}.code.add .chg{background:var(--diff-add-strong)}.hljs-comment,.hljs-quote{color:#6b7689;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-doctag,.hljs-formula{color:#c9a5ff}.hljs-string,.hljs-regexp,.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string{color:#a5d6a7}.hljs-number,.hljs-variable,.hljs-template-variable,.hljs-type,.hljs-selector-class,.hljs-selector-attr,.hljs-selector-pseudo{color:#f0a868}.hljs-title,.hljs-section,.hljs-title.class_,.hljs-title.function_{color:#7fd6e0}.hljs-attr,.hljs-property,.hljs-symbol,.hljs-bullet,.hljs-link{color:#6ea8fe}.hljs-built_in,.hljs-class,.hljs-params{color:#e6e9ef}.hljs-meta,.hljs-tag{color:#9aa4b8}:root[data-theme=light] .hljs-comment,:root[data-theme=light] .hljs-quote{color:#6b7280}:root[data-theme=light] .hljs-keyword,:root[data-theme=light] .hljs-selector-tag,:root[data-theme=light] .hljs-literal,:root[data-theme=light] .hljs-doctag,:root[data-theme=light] .hljs-formula{color:#7c4dd6}:root[data-theme=light] .hljs-string,:root[data-theme=light] .hljs-regexp,:root[data-theme=light] .hljs-addition,:root[data-theme=light] .hljs-attribute,:root[data-theme=light] .hljs-meta .hljs-string{color:#1f9d55}:root[data-theme=light] .hljs-number,:root[data-theme=light] .hljs-variable,:root[data-theme=light] .hljs-template-variable,:root[data-theme=light] .hljs-type,:root[data-theme=light] .hljs-selector-class,:root[data-theme=light] .hljs-selector-attr,:root[data-theme=light] .hljs-selector-pseudo{color:#b5650f}:root[data-theme=light] .hljs-title,:root[data-theme=light] .hljs-section,:root[data-theme=light] .hljs-title.class_,:root[data-theme=light] .hljs-title.function_{color:#0f8fa3}:root[data-theme=light] .hljs-attr,:root[data-theme=light] .hljs-property,:root[data-theme=light] .hljs-symbol,:root[data-theme=light] .hljs-bullet,:root[data-theme=light] .hljs-link{color:#2f6fe0}:root[data-theme=light] .hljs-built_in,:root[data-theme=light] .hljs-class,:root[data-theme=light] .hljs-params{color:#16181d}:root[data-theme=light] .hljs-meta,:root[data-theme=light] .hljs-tag{color:#5b6472}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.anchor-flash{animation:1.4s ease-out anchor-flash}@keyframes anchor-flash{0%{box-shadow:0 0 0 2px var(--accent)}to{box-shadow:0 0 0 2px #0000}}*{box-sizing:border-box}html,body{background:var(--bg);color:var(--text);font-family:var(--sans);min-height:100%;margin:0;padding:0}body{-webkit-font-smoothing:antialiased}button,input,select{font:inherit;color:inherit}button{cursor:pointer}::selection{background:var(--selection-bg)}html,body,*{scrollbar-width:thin;scrollbar-color:var(--scrollbar-thumb) transparent}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);background-clip:padding-box;border:2px solid #0000;border-radius:999px}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover);background-clip:padding-box;border:2px solid #0000}::-webkit-scrollbar-corner{background:0 0}.boot.svelte-12qhfyh{color:var(--text-dim);font-family:var(--mono);padding:48px 28px;font-size:13px}.boot.svelte-12qhfyh button:where(.svelte-12qhfyh){background:var(--btn-primary-bg);border:1px solid var(--btn-primary-border);color:var(--btn-primary-text);border-radius:0;margin-top:12px;padding:8px 14px}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.live.svelte-18urbyr{background:radial-gradient(900px 420px at 8% -8%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 70%), var(--bg);flex-direction:column;flex:1;min-height:0;display:flex}.bar.svelte-18urbyr{border-bottom:1px solid var(--border);background:color-mix(in srgb, var(--bg-elev) 90%, transparent);justify-content:space-between;align-items:center;gap:12px;padding:12px 20px;display:flex}.brand.svelte-18urbyr{align-items:center;gap:10px;min-width:0;font-size:14px;display:flex}.dot.svelte-18urbyr{background:var(--accent);width:8px;height:8px;box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);border-radius:50%;flex:none}.pill.svelte-18urbyr{letter-spacing:.02em;border:1px solid var(--border);color:var(--text-dim);background:var(--bg-card);text-transform:lowercase;border-radius:0;padding:3px 9px;font-size:11px;font-weight:500}.pill.busy.svelte-18urbyr{border-color:color-mix(in srgb, var(--accent) 45%, var(--border));color:var(--accent);background:var(--accent-soft)}.pill.error.svelte-18urbyr{border-color:var(--danger-border,var(--danger));color:var(--danger);background:var(--danger-bg,transparent)}.pill.gone.svelte-18urbyr{color:var(--text-faint)}.actions.svelte-18urbyr{flex:none;align-items:center;gap:8px;display:flex}.ghost.svelte-18urbyr{border:1px solid var(--border);color:var(--text);font:inherit;cursor:pointer;background:0 0;padding:6px 11px;font-size:13px}.ghost.svelte-18urbyr:hover{border-color:var(--accent)}.body.svelte-18urbyr{flex:1;grid-template-columns:minmax(280px,320px) 1fr;gap:20px;min-height:0;padding:20px 24px 24px;display:grid}.card.svelte-18urbyr{border:1px solid var(--border);background:var(--bg-elev);border-radius:0;align-self:start;padding:16px 16px 14px}.fields.svelte-18urbyr{flex-direction:column;gap:14px;margin:0;display:flex}.fields.svelte-18urbyr dt:where(.svelte-18urbyr){text-transform:uppercase;letter-spacing:.04em;color:var(--text-faint);margin:0 0 3px;font-size:11px}.fields.svelte-18urbyr dd:where(.svelte-18urbyr){font-size:13px;font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap;color:var(--text);margin:0;overflow:hidden}.branch.svelte-18urbyr{color:var(--accent);font-weight:600}.arrow.svelte-18urbyr{color:var(--text-faint);margin:0 2px}.card-note.svelte-18urbyr{border-top:1px solid var(--border-soft,var(--border));color:var(--text-faint);margin:16px 0 0;padding-top:12px;font-size:12.5px;line-height:1.4}.stage.svelte-18urbyr{border:1px solid var(--border);background:var(--bg-elev);border-radius:0;flex-direction:column;min-width:0;min-height:0;display:flex;overflow:hidden}.center.svelte-18urbyr{text-align:center;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;padding:40px 24px;display:flex}.center.fail.svelte-18urbyr .title:where(.svelte-18urbyr){color:var(--danger)}.auth-actions.svelte-18urbyr{flex-wrap:wrap;justify-content:center;gap:8px;margin-top:12px;display:flex}.primary.svelte-18urbyr{border:1px solid color-mix(in srgb, var(--accent) 55%, var(--border));background:var(--accent-soft);color:var(--accent);font:inherit;cursor:pointer;border-radius:0;padding:7px 14px;font-size:13px;font-weight:600}.primary.svelte-18urbyr:hover:not(:disabled){border-color:var(--accent)}.primary.svelte-18urbyr:disabled{opacity:.6;cursor:default}.auth-note.svelte-18urbyr{max-width:28rem;color:var(--text-dim);margin:10px 0 0;font-size:13px}.auth-err.svelte-18urbyr{max-width:28rem;color:var(--danger);margin:8px 0 0;font-size:13px}.spinner.svelte-18urbyr{border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;width:34px;height:34px;margin-bottom:6px;animation:.8s linear infinite svelte-18urbyr-spin}@keyframes svelte-18urbyr-spin{to{transform:rotate(360deg)}}.title.svelte-18urbyr{margin:0;font-size:17px;font-weight:600}.detail.svelte-18urbyr{color:var(--text-dim);max-width:28rem;margin:0;font-size:14px}.hint.svelte-18urbyr{max-width:32rem;color:var(--text-faint);margin:6px 0 0;font-size:13px}.stage-header.svelte-18urbyr{border-bottom:1px solid var(--border);border-radius:0;flex:none;align-items:center;gap:8px;min-width:0;padding:10px 14px;display:flex}.stage-header.svelte-18urbyr strong:where(.svelte-18urbyr){font-size:13.5px;font-weight:650}.stage-header.svelte-18urbyr small:where(.svelte-18urbyr){font-family:var(--mono);color:var(--text-faint);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:11.5px;overflow:hidden}.log-wrap.svelte-18urbyr{border-radius:0;flex-direction:column;flex:1;gap:10px;min-height:0;padding:12px 14px;display:flex}.log-wrap.svelte-18urbyr .log{flex:1;min-height:0}.stage-footer.svelte-18urbyr{border-top:1px solid var(--border);border-radius:0;flex:none;align-items:center;gap:10px;margin-top:auto;padding-top:10px;display:flex}.footer-spacer.svelte-18urbyr{flex:1}.launch-banner.svelte-18urbyr{border:1px solid var(--border);background:color-mix(in srgb, var(--accent-soft) 70%, var(--bg-card));border-radius:0;align-items:flex-start;gap:12px;padding:10px 12px;display:flex}.launch-banner.svelte-18urbyr .title:where(.svelte-18urbyr){font-size:14px}.launch-banner.svelte-18urbyr .detail:where(.svelte-18urbyr){margin-top:2px;font-size:12.5px}.spinner.sm.svelte-18urbyr{flex:none;width:18px;height:18px;margin:2px 0 0}@media (width<=800px){.body.svelte-18urbyr{grid-template-rows:auto 1fr;grid-template-columns:1fr;gap:14px;padding:16px}.card.svelte-18urbyr{align-self:stretch}.stage.svelte-18urbyr{min-height:280px}}@media (width<=480px){.bar.svelte-18urbyr{flex-wrap:wrap;padding:10px 14px}.pill.svelte-18urbyr{font-size:10px}}.page.svelte-1uha8ag{flex-direction:column;min-height:100vh;display:flex}.page.live.svelte-1uha8ag{height:100vh;min-height:100vh;overflow:hidden}.diff-spinner.svelte-1uha8ag{border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;width:28px;height:28px;margin:0 auto;animation:.7s linear infinite svelte-1uha8ag-diff-spin}.cli-wait.svelte-1uha8ag{text-align:center;background:var(--bg);flex-direction:column;flex:1;justify-content:center;align-items:center;gap:12px;min-height:0;padding:32px 24px;display:flex}.cli-wait-title.svelte-1uha8ag{color:var(--text);margin:0;font-size:15px}.cli-wait-detail.svelte-1uha8ag{color:var(--text-faint);margin:0;font-size:13px}.cli-wait.svelte-1uha8ag .ghost:where(.svelte-1uha8ag){border:1px solid var(--border);color:var(--text-dim);cursor:pointer;background:0 0;margin-top:8px;padding:6px 12px;font-size:13px}@keyframes svelte-1uha8ag-diff-spin{to{transform:rotate(360deg)}}.toast.svelte-1uha8ag{z-index:50;border:1px solid var(--border);background:var(--bg-card);color:var(--text);padding:10px 16px;font-size:13px;position:fixed;top:16px;left:50%;transform:translate(-50%);box-shadow:0 8px 24px #00000029}.topbar.svelte-1uha8ag{border-bottom:1px solid var(--border);background:var(--header-bg);z-index:5;justify-content:space-between;align-items:center;gap:12px;padding:16px 28px;display:flex;position:sticky;top:0}.brand.svelte-1uha8ag{color:var(--text);align-items:center;gap:10px;text-decoration:none;display:flex}.brand-dot.svelte-1uha8ag{background:linear-gradient(135deg,#6ea8fe,#c9a5ff);border-radius:50%;flex-shrink:0;width:9px;height:9px;box-shadow:0 0 12px #6ea8fe88}.title-block.svelte-1uha8ag{text-align:left;flex-direction:column;line-height:1.25;display:flex}.title-block.svelte-1uha8ag span:where(.svelte-1uha8ag):first-child{font-size:15px;font-weight:700}.title-block.svelte-1uha8ag small:where(.svelte-1uha8ag){color:var(--text-faint);font-size:11.5px;font-weight:400}.workspace.svelte-1uha8ag{flex:1;grid-template-columns:minmax(0,1fr) minmax(300px,380px);align-items:start;gap:28px;width:100%;max-width:1280px;margin:0 auto;padding:22px 28px 40px;display:grid;overflow:auto}.setup.svelte-1uha8ag{min-width:0}h2.svelte-1uha8ag{letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);margin:0 0 4px;font-size:13px;font-weight:600}.result-head.svelte-1uha8ag{margin-top:24px}.section-head.svelte-1uha8ag{justify-content:space-between;align-items:baseline;margin-top:22px;display:flex}.hint-text.svelte-1uha8ag{color:var(--text-dim);margin:0 0 12px;font-size:12.5px;line-height:1.5}.hint-text.svelte-1uha8ag code:where(.svelte-1uha8ag){font-family:var(--mono);color:var(--text);font-size:12px}.detect-banner.svelte-1uha8ag,.detect-wait.svelte-1uha8ag{color:var(--text-dim);margin:0 0 10px;font-size:13px}button.file-link.svelte-1uha8ag{color:var(--accent);font:inherit;cursor:pointer;background:0 0;border:0;padding:0;text-decoration:underline}.error-line.svelte-1uha8ag{color:var(--danger);margin:0 0 10px;font-size:12px}.ok-line.svelte-1uha8ag{color:var(--ok);margin:0 0 10px;font-size:12px}.row.svelte-1uha8ag{flex-wrap:wrap;gap:8px;display:flex}.repo-setup.svelte-1uha8ag{flex-direction:column;gap:10px;display:flex}.field.svelte-1uha8ag{flex-direction:column;flex:1;gap:4px;min-width:180px;display:flex}.repo-field.svelte-1uha8ag{flex:none;width:100%;min-width:0}.branches-row.svelte-1uha8ag .field:where(.svelte-1uha8ag){flex:1;min-width:160px}.field.svelte-1uha8ag span:where(.svelte-1uha8ag){color:var(--text-faint);font-size:11px}.repo-row.svelte-1uha8ag{gap:6px;min-width:0;display:flex}.repo-row.svelte-1uha8ag input[type=text]:where(.svelte-1uha8ag){flex:1;min-width:0}.repo-row.svelte-1uha8ag button:where(.svelte-1uha8ag){flex-shrink:0}.source-toggle.svelte-1uha8ag{margin-bottom:10px}input[type=text].svelte-1uha8ag,select.svelte-1uha8ag{background:var(--bg-card);border:1px solid var(--border);flex:1;min-width:0;padding:9px 12px}button.svelte-1uha8ag{background:var(--bg-card);border:1px solid var(--border);color:var(--text);padding:9px 12px;font-size:12.5px}button.svelte-1uha8ag:hover:not(:disabled){border-color:var(--accent)}button.svelte-1uha8ag:disabled{opacity:.5;cursor:not-allowed}.mode-toggle.svelte-1uha8ag{border:1px solid var(--border);width:fit-content;margin-bottom:10px;display:flex;overflow:hidden}.mode-toggle.svelte-1uha8ag button:where(.svelte-1uha8ag){background:0 0;border:0;padding:6px 12px;font-size:12px}.mode-toggle.svelte-1uha8ag button:where(.svelte-1uha8ag)+button:where(.svelte-1uha8ag){border-left:1px solid var(--border)}.mode-toggle.svelte-1uha8ag button.on:where(.svelte-1uha8ag){background:var(--accent-soft)}textarea.svelte-1uha8ag{resize:vertical;background:var(--bg);border:1px solid var(--border);width:100%;height:220px;font-family:var(--mono);color:var(--text);padding:12px;font-size:12px;line-height:1.5}.loading-models.svelte-1uha8ag{color:var(--text-faint);font-weight:400}.models-error.svelte-1uha8ag{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}button.linkish.svelte-1uha8ag{color:var(--accent,#3b82f6);cursor:pointer;font:inherit;background:0 0;border:none;padding:0;text-decoration:underline}.actions.svelte-1uha8ag{gap:8px;margin-top:10px;display:flex}button.primary.svelte-1uha8ag{background:var(--btn-primary-bg);border-color:var(--btn-primary-border);color:var(--btn-primary-text);font-weight:600}.coverage-box.svelte-1uha8ag{border:1px solid var(--border);border-left:3px solid var(--sev-med);background:var(--bg-card);flex-direction:column;gap:10px;margin-top:12px;padding:12px 14px;display:flex}.coverage-head.svelte-1uha8ag{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}.coverage-head.svelte-1uha8ag strong:where(.svelte-1uha8ag){color:var(--sev-med);font-size:13px}.coverage-head.svelte-1uha8ag span:where(.svelte-1uha8ag){color:var(--text-faint);font-size:11.5px}.coverage-box.svelte-1uha8ag summary:where(.svelte-1uha8ag){color:var(--text-dim);cursor:pointer;font-size:12px}.coverage-list.svelte-1uha8ag{max-height:180px;font-family:var(--mono);color:var(--text-faint);margin:8px 0 0;padding-left:18px;font-size:11px;overflow:auto}.coverage-box.svelte-1uha8ag textarea:where(.svelte-1uha8ag){resize:vertical;background:var(--bg);border:1px solid var(--border);width:100%;font-family:var(--mono);color:var(--text);padding:10px;font-size:11.5px;line-height:1.5}.coverage-actions.svelte-1uha8ag{flex-wrap:wrap;gap:8px;display:flex}.dropzone.svelte-1uha8ag{border:1.5px dashed var(--border);text-align:center;background:var(--bg-elev);padding:26px;transition:background .15s,border-color .15s}.dropzone.drag.svelte-1uha8ag{border-color:var(--accent);background:var(--accent-soft)}.dropzone.busy.svelte-1uha8ag{opacity:.7}.dropzone.svelte-1uha8ag p:where(.svelte-1uha8ag){color:var(--text-dim);margin:0 0 6px;font-size:14px}.visually-hidden.svelte-1uha8ag{clip:rect(0 0 0 0);width:1px;height:1px;position:absolute;overflow:hidden}.drop-errors.svelte-1uha8ag{background:var(--danger-bg);color:var(--danger);margin-top:10px;padding:10px 12px;font-size:12.5px}.drop-errors.svelte-1uha8ag strong:where(.svelte-1uha8ag){margin-bottom:4px;display:block}.drop-errors.svelte-1uha8ag ul:where(.svelte-1uha8ag){margin:0;padding-left:18px;line-height:1.6}.reports-col.svelte-1uha8ag{min-width:0;max-height:calc(100vh - 110px);position:sticky;top:88px;overflow:auto}.report-list.svelte-1uha8ag{flex-direction:column;gap:8px;margin:0;padding:0;list-style:none;display:flex}.report-item.svelte-1uha8ag{border:1px solid var(--border);background:var(--bg-card);align-items:stretch;display:flex;position:relative;overflow:visible}.report-item.svelte-1uha8ag:hover{background:var(--bg-card-hover);border-color:#33507a}.report-card.svelte-1uha8ag{min-width:0;color:var(--text);flex:1;padding:12px 8px 12px 14px;text-decoration:none;display:block}.report-actions.svelte-1uha8ag{flex-shrink:0;padding:8px 8px 0 0;position:relative}.kebab.svelte-1uha8ag{width:26px;height:26px;color:var(--text-faint);cursor:pointer;background:0 0;border:1px solid #0000;justify-content:center;align-items:center;padding:0;display:inline-flex}.kebab.svelte-1uha8ag:hover{border-color:var(--border);color:var(--text);background:var(--bg)}.report-menu.svelte-1uha8ag{z-index:40;border:1px solid var(--border);background:var(--bg-card);width:148px;padding:4px;position:fixed;box-shadow:0 8px 24px #0000002e}.report-menu.svelte-1uha8ag .menu-item:where(.svelte-1uha8ag){width:100%;color:var(--text);text-align:left;cursor:pointer;background:0 0;border:0;padding:8px 10px;font-size:12.5px;display:block}.report-menu.svelte-1uha8ag .menu-item:where(.svelte-1uha8ag):hover{background:var(--accent-soft)}.report-menu.svelte-1uha8ag .menu-item.danger:where(.svelte-1uha8ag){color:var(--danger)}.report-top.svelte-1uha8ag{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.report-top.svelte-1uha8ag strong:where(.svelte-1uha8ag){font-size:14px}.report-prov.svelte-1uha8ag{min-width:0;color:var(--text-dim);align-items:center;gap:6px;margin-top:4px;font-size:12px;display:flex}.report-prov.svelte-1uha8ag .prov-agent:where(.svelte-1uha8ag){text-overflow:ellipsis;white-space:nowrap;flex:0 auto;min-width:0;overflow:hidden}.report-prov.svelte-1uha8ag .prov-sep:where(.svelte-1uha8ag){color:var(--text-faint);flex-shrink:0}.report-prov.svelte-1uha8ag .prov-model:where(.svelte-1uha8ag){min-width:0;font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:11.5px;overflow:hidden}.when.svelte-1uha8ag{color:var(--text-dim);font-size:12px}.report-meta.svelte-1uha8ag{color:var(--text-dim);justify-content:space-between;align-items:baseline;gap:12px;margin-top:6px;font-size:12px;display:flex}.report-base.svelte-1uha8ag{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.base-arrow.svelte-1uha8ag{color:var(--text-faint)}.report-counts.svelte-1uha8ag{flex-shrink:0;align-items:baseline;gap:8px;display:flex}.pill.svelte-1uha8ag{font-family:var(--mono);font-size:11px}.pill.bad.svelte-1uha8ag{color:var(--danger)}.report-intent.svelte-1uha8ag{color:var(--text-dim);-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;margin:8px 0 0;font-size:12.5px;line-height:1.45;display:-webkit-box;overflow:hidden}@media (width<=960px){.workspace.svelte-1uha8ag{grid-template-columns:1fr}.reports-col.svelte-1uha8ag{max-height:none;position:static}}
|
|
Binary file
|
|
Binary file
|