@markbrutx/promptbook-viewer 0.1.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/LICENSE +21 -0
- package/README.md +38 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/server/annotations.d.ts +30 -0
- package/dist/server/annotations.d.ts.map +1 -0
- package/dist/server/annotations.js +62 -0
- package/dist/server/annotations.js.map +1 -0
- package/dist/server/api.d.ts +16 -0
- package/dist/server/api.d.ts.map +1 -0
- package/dist/server/api.js +134 -0
- package/dist/server/api.js.map +1 -0
- package/dist/server/book-source.d.ts +20 -0
- package/dist/server/book-source.d.ts.map +1 -0
- package/dist/server/book-source.js +32 -0
- package/dist/server/book-source.js.map +1 -0
- package/dist/server/responses.d.ts +12 -0
- package/dist/server/responses.d.ts.map +1 -0
- package/dist/server/responses.js +106 -0
- package/dist/server/responses.js.map +1 -0
- package/dist/server/segments.d.ts +12 -0
- package/dist/server/segments.d.ts.map +1 -0
- package/dist/server/segments.js +24 -0
- package/dist/server/segments.js.map +1 -0
- package/dist/server/server.d.ts +24 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +71 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/static.d.ts +8 -0
- package/dist/server/static.d.ts.map +1 -0
- package/dist/server/static.js +55 -0
- package/dist/server/static.js.map +1 -0
- package/dist/server/used-in.d.ts +9 -0
- package/dist/server/used-in.d.ts.map +1 -0
- package/dist/server/used-in.js +19 -0
- package/dist/server/used-in.js.map +1 -0
- package/dist/shared/types.d.ts +113 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +2 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/web/assets/index-B2Wxtb-f.css +1 -0
- package/dist/web/assets/index-C8f_6lr_.js +51 -0
- package/dist/web/index.html +13 -0
- package/package.json +47 -0
- package/src/index.ts +19 -0
- package/src/server/annotations.ts +96 -0
- package/src/server/api.ts +164 -0
- package/src/server/book-source.ts +54 -0
- package/src/server/responses.ts +127 -0
- package/src/server/segments.ts +26 -0
- package/src/server/server.ts +96 -0
- package/src/server/static.ts +60 -0
- package/src/server/used-in.ts +23 -0
- package/src/shared/types.ts +137 -0
- package/src/web/App.tsx +307 -0
- package/src/web/annotations.ts +58 -0
- package/src/web/api.ts +44 -0
- package/src/web/colors.ts +21 -0
- package/src/web/components/Addons.tsx +109 -0
- package/src/web/components/Canvas.tsx +180 -0
- package/src/web/components/CodePromptView.tsx +87 -0
- package/src/web/components/Controls.tsx +71 -0
- package/src/web/components/Diff.tsx +30 -0
- package/src/web/components/FragmentView.tsx +54 -0
- package/src/web/components/Sidebar.tsx +178 -0
- package/src/web/diff.ts +51 -0
- package/src/web/env.d.ts +3 -0
- package/src/web/format.ts +8 -0
- package/src/web/index.html +12 -0
- package/src/web/main.tsx +15 -0
- package/src/web/selection.ts +5 -0
- package/src/web/styles.css +484 -0
- package/src/web/tree.ts +134 -0
- package/src/web/types.ts +17 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { watch } from "node:fs";
|
|
3
|
+
import { createServer } from "node:http";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { createRequestHandler } from "./api.js";
|
|
6
|
+
import { createBookSource } from "./book-source.js";
|
|
7
|
+
/** Best-effort: open `url` in the OS default browser; never throws. */
|
|
8
|
+
function openBrowser(url) {
|
|
9
|
+
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
10
|
+
try {
|
|
11
|
+
const child = spawn(command, [url], {
|
|
12
|
+
stdio: "ignore",
|
|
13
|
+
detached: true,
|
|
14
|
+
shell: process.platform === "win32",
|
|
15
|
+
});
|
|
16
|
+
child.on("error", () => { });
|
|
17
|
+
child.unref();
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// opening a browser is a convenience, not a requirement
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Watch the prompts folder and call `onChange` (debounced) on any edit. */
|
|
24
|
+
function watchFolder(promptsDir, onChange) {
|
|
25
|
+
try {
|
|
26
|
+
let timer;
|
|
27
|
+
const watcher = watch(promptsDir, { recursive: true }, () => {
|
|
28
|
+
if (timer !== undefined) {
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
}
|
|
31
|
+
timer = setTimeout(onChange, 50);
|
|
32
|
+
});
|
|
33
|
+
watcher.on("error", () => { });
|
|
34
|
+
return watcher;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Start the viewer server: serves the built web bundle and the `/api/*` routes
|
|
42
|
+
* over a prompts folder, hot-reloading on folder edits. Render-only; no model
|
|
43
|
+
* calls. Resolves once the server is listening.
|
|
44
|
+
*/
|
|
45
|
+
export async function startViewer(options) {
|
|
46
|
+
const { promptsDir, port = 0, open = false, fs } = options;
|
|
47
|
+
const webRoot = fileURLToPath(new URL("../web", import.meta.url));
|
|
48
|
+
const source = createBookSource(promptsDir, fs);
|
|
49
|
+
const handler = createRequestHandler({ source, promptsDir, webRoot });
|
|
50
|
+
const server = createServer((req, res) => handler.handle(req, res));
|
|
51
|
+
await new Promise((resolve, reject) => {
|
|
52
|
+
server.once("error", reject);
|
|
53
|
+
server.listen(port, "127.0.0.1", resolve);
|
|
54
|
+
});
|
|
55
|
+
const address = server.address();
|
|
56
|
+
const boundPort = typeof address === "object" && address !== null ? address.port : port;
|
|
57
|
+
const url = `http://localhost:${boundPort}`;
|
|
58
|
+
const watcher = watchFolder(promptsDir, () => handler.notifyReload());
|
|
59
|
+
if (open) {
|
|
60
|
+
openBrowser(url);
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
url,
|
|
64
|
+
port: boundPort,
|
|
65
|
+
close() {
|
|
66
|
+
watcher?.close();
|
|
67
|
+
return new Promise((resolve) => server.close(() => resolve()));
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ServerResponse } from "node:http";
|
|
2
|
+
/**
|
|
3
|
+
* Serve a static asset from the built web bundle. Unknown paths fall back to
|
|
4
|
+
* `index.html` (single-page app), and a missing bundle yields a friendly page
|
|
5
|
+
* pointing at the build command rather than a bare 404.
|
|
6
|
+
*/
|
|
7
|
+
export declare function serveStatic(res: ServerResponse, webRoot: string, urlPath: string): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=static.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAyChD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYtG"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { extname, join, normalize } from "node:path";
|
|
3
|
+
const MIME = {
|
|
4
|
+
".html": "text/html; charset=utf-8",
|
|
5
|
+
".js": "text/javascript; charset=utf-8",
|
|
6
|
+
".mjs": "text/javascript; charset=utf-8",
|
|
7
|
+
".css": "text/css; charset=utf-8",
|
|
8
|
+
".json": "application/json; charset=utf-8",
|
|
9
|
+
".svg": "image/svg+xml",
|
|
10
|
+
".png": "image/png",
|
|
11
|
+
".ico": "image/x-icon",
|
|
12
|
+
".woff2": "font/woff2",
|
|
13
|
+
};
|
|
14
|
+
/** Placeholder shown when the web bundle is missing (folder not built yet). */
|
|
15
|
+
const NOT_BUILT = `<!doctype html><meta charset="utf-8"><title>promptbook viewer</title>
|
|
16
|
+
<body style="font-family:system-ui;padding:2rem;line-height:1.5">
|
|
17
|
+
<h1>promptbook viewer</h1>
|
|
18
|
+
<p>The web bundle was not found. Build it with:</p>
|
|
19
|
+
<pre>npm -w @markbrutx/promptbook-viewer run build</pre>
|
|
20
|
+
<p>The API is live at <code>/api/book</code>.</p>`;
|
|
21
|
+
/** Resolve a request path to a file inside the web root, blocking traversal. */
|
|
22
|
+
function resolveAsset(webRoot, urlPath) {
|
|
23
|
+
const clean = normalize(urlPath).replace(/^(\.\.[/\\])+/, "");
|
|
24
|
+
const rel = clean === "/" || clean === "" ? "index.html" : clean.replace(/^\/+/, "");
|
|
25
|
+
return join(webRoot, rel);
|
|
26
|
+
}
|
|
27
|
+
async function readIfFile(path) {
|
|
28
|
+
try {
|
|
29
|
+
if ((await stat(path)).isFile()) {
|
|
30
|
+
return await readFile(path);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// fall through
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Serve a static asset from the built web bundle. Unknown paths fall back to
|
|
40
|
+
* `index.html` (single-page app), and a missing bundle yields a friendly page
|
|
41
|
+
* pointing at the build command rather than a bare 404.
|
|
42
|
+
*/
|
|
43
|
+
export async function serveStatic(res, webRoot, urlPath) {
|
|
44
|
+
const asset = resolveAsset(webRoot, urlPath);
|
|
45
|
+
const direct = await readIfFile(asset);
|
|
46
|
+
if (direct !== undefined) {
|
|
47
|
+
res.writeHead(200, { "content-type": MIME[extname(asset)] ?? "application/octet-stream" });
|
|
48
|
+
res.end(direct);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const index = await readIfFile(join(webRoot, "index.html"));
|
|
52
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
53
|
+
res.end(index ?? NOT_BUILT);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=static.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAErD,MAAM,IAAI,GAA2B;IACnC,OAAO,EAAE,0BAA0B;IACnC,KAAK,EAAE,gCAAgC;IACvC,MAAM,EAAE,gCAAgC;IACxC,MAAM,EAAE,yBAAyB;IACjC,OAAO,EAAE,iCAAiC;IAC1C,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,cAAc;IACtB,QAAQ,EAAE,YAAY;CACvB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,SAAS,GAAG;;;;;kDAKgC,CAAC;AAEnD,gFAAgF;AAChF,SAAS,YAAY,CAAC,OAAe,EAAE,OAAe;IACpD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,GAAG,GAAG,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACrF,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;YAChC,OAAO,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAmB,EAAE,OAAe,EAAE,OAAe;IACrF,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,0BAA0B,EAAE,CAAC,CAAC;QAC3F,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5D,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;IACnE,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PromptBook } from "@markbrutx/promptbook-core";
|
|
2
|
+
import type { UsedInReference } from "../shared/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* All references to `fragmentId` across compositions (base/order + each rule's
|
|
5
|
+
* add/after/replace/forbid/order), reported per-composition for the used-in
|
|
6
|
+
* panel. Reuses core's reference walk so the viewer can't drift from lint.
|
|
7
|
+
*/
|
|
8
|
+
export declare function usedIn(book: PromptBook, fragmentId: string): UsedInReference[];
|
|
9
|
+
//# sourceMappingURL=used-in.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"used-in.d.ts","sourceRoot":"","sources":["../../src/server/used-in.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,eAAe,EAAE,CAa9E"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { iterateReferences } from "@markbrutx/promptbook-core";
|
|
2
|
+
/**
|
|
3
|
+
* All references to `fragmentId` across compositions (base/order + each rule's
|
|
4
|
+
* add/after/replace/forbid/order), reported per-composition for the used-in
|
|
5
|
+
* panel. Reuses core's reference walk so the viewer can't drift from lint.
|
|
6
|
+
*/
|
|
7
|
+
export function usedIn(book, fragmentId) {
|
|
8
|
+
const references = [];
|
|
9
|
+
for (const ref of iterateReferences(book)) {
|
|
10
|
+
if (ref.id !== fragmentId) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
references.push(ref.ruleIndex === undefined
|
|
14
|
+
? { composition: ref.composition, role: ref.role }
|
|
15
|
+
: { composition: ref.composition, role: ref.role, ruleIndex: ref.ruleIndex });
|
|
16
|
+
}
|
|
17
|
+
return references;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=used-in.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"used-in.js","sourceRoot":"","sources":["../../src/server/used-in.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAG/D;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,IAAgB,EAAE,UAAkB;IACzD,MAAM,UAAU,GAAsB,EAAE,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,IAAI,GAAG,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,UAAU,CAAC,IAAI,CACb,GAAG,CAAC,SAAS,KAAK,SAAS;YACzB,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE;YAClD,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAC/E,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire types shared by the server and the web app. These are the JSON shapes
|
|
3
|
+
* the `/api/*` routes speak; importing them on both sides keeps the contract
|
|
4
|
+
* in one place. Only type-only imports from `@markbrutx/promptbook-core` are used so the
|
|
5
|
+
* file carries no runtime dependency.
|
|
6
|
+
*/
|
|
7
|
+
import type { Annotation, Context, FragmentReference, LintFinding, RuleAction, Trace, When } from "@markbrutx/promptbook-core";
|
|
8
|
+
export type { Annotation } from "@markbrutx/promptbook-core";
|
|
9
|
+
/** A rule reduced to what the viewer renders (no behavior, just the shape). */
|
|
10
|
+
export interface RuleSummary {
|
|
11
|
+
index: number;
|
|
12
|
+
when: When;
|
|
13
|
+
action: RuleAction;
|
|
14
|
+
add?: string[];
|
|
15
|
+
after?: string;
|
|
16
|
+
replace?: Record<string, string>;
|
|
17
|
+
forbid?: string[];
|
|
18
|
+
order?: string[];
|
|
19
|
+
}
|
|
20
|
+
/** A named context preset for a composition, sourced from `fixtures/`. */
|
|
21
|
+
export interface VariantSummary {
|
|
22
|
+
name: string;
|
|
23
|
+
context: Context;
|
|
24
|
+
}
|
|
25
|
+
/** A composition as the sidebar/canvas needs it. */
|
|
26
|
+
export interface CompositionSummary {
|
|
27
|
+
name: string;
|
|
28
|
+
base: string[];
|
|
29
|
+
order?: string[];
|
|
30
|
+
rules: RuleSummary[];
|
|
31
|
+
sourceFile: string;
|
|
32
|
+
variants: VariantSummary[];
|
|
33
|
+
}
|
|
34
|
+
/** A fragment as the inspector/used-in panels need it. */
|
|
35
|
+
export interface FragmentSummary {
|
|
36
|
+
id: string;
|
|
37
|
+
kind?: string;
|
|
38
|
+
tags: string[];
|
|
39
|
+
body: string;
|
|
40
|
+
sourceFile: string;
|
|
41
|
+
}
|
|
42
|
+
/** One captured snapshot of a code-prompt's output (the builder is never run). */
|
|
43
|
+
interface CodePromptSampleSummary {
|
|
44
|
+
label: string;
|
|
45
|
+
context?: Context;
|
|
46
|
+
output: string;
|
|
47
|
+
}
|
|
48
|
+
/** A builder-backed prompt as the unified menu/canvas needs it. */
|
|
49
|
+
export interface CodePromptSummary {
|
|
50
|
+
name: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
samples: CodePromptSampleSummary[];
|
|
53
|
+
sourceFile: string;
|
|
54
|
+
}
|
|
55
|
+
/** Response of `GET /api/book`. */
|
|
56
|
+
export interface BookResponse {
|
|
57
|
+
compositions: CompositionSummary[];
|
|
58
|
+
codePrompts: CodePromptSummary[];
|
|
59
|
+
fragments: FragmentSummary[];
|
|
60
|
+
warnings: string[];
|
|
61
|
+
}
|
|
62
|
+
/** One colored slice of the assembled prompt, mapped to its source fragment. */
|
|
63
|
+
export interface Segment {
|
|
64
|
+
fragmentId: string;
|
|
65
|
+
text: string;
|
|
66
|
+
}
|
|
67
|
+
/** Request body for `POST /api/resolve` and `POST /api/lint`. */
|
|
68
|
+
export interface ResolveRequest {
|
|
69
|
+
prompt: string;
|
|
70
|
+
context?: Context;
|
|
71
|
+
}
|
|
72
|
+
/** Response of `POST /api/resolve`. */
|
|
73
|
+
export interface ResolveResponse {
|
|
74
|
+
text: string;
|
|
75
|
+
trace: Trace;
|
|
76
|
+
segments: Segment[];
|
|
77
|
+
}
|
|
78
|
+
/** Response of `POST /api/lint`. */
|
|
79
|
+
export interface LintResponse {
|
|
80
|
+
findings: LintFinding[];
|
|
81
|
+
errorCount: number;
|
|
82
|
+
warningCount: number;
|
|
83
|
+
tokens: number;
|
|
84
|
+
}
|
|
85
|
+
/** Where a fragment id is referenced inside a composition (core's role union). */
|
|
86
|
+
type UsedInRole = FragmentReference["role"];
|
|
87
|
+
/** One reference to a fragment, as `GET /api/used-in/:id` reports it. */
|
|
88
|
+
export interface UsedInReference {
|
|
89
|
+
composition: string;
|
|
90
|
+
role: UsedInRole;
|
|
91
|
+
ruleIndex?: number;
|
|
92
|
+
}
|
|
93
|
+
/** Response of `GET /api/used-in/:id`. */
|
|
94
|
+
export interface UsedInResponse {
|
|
95
|
+
fragmentId: string;
|
|
96
|
+
references: UsedInReference[];
|
|
97
|
+
}
|
|
98
|
+
/** Request body for `POST /api/annotate`. */
|
|
99
|
+
export interface AnnotateRequest {
|
|
100
|
+
/** Composition of the annotated variant (omit when targeting a fragment). */
|
|
101
|
+
prompt?: string;
|
|
102
|
+
context?: Context;
|
|
103
|
+
fragmentId: string;
|
|
104
|
+
anchorText: string;
|
|
105
|
+
comment: string;
|
|
106
|
+
offset?: number;
|
|
107
|
+
sourceFile?: string;
|
|
108
|
+
}
|
|
109
|
+
/** Response of `GET /api/annotations`. */
|
|
110
|
+
export interface AnnotationsResponse {
|
|
111
|
+
annotations: Annotation[];
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--bg: #fff;--panel: #f6f8fa;--border: #e1e4e8;--text: #1f2328;--muted: #6e7781;--accent: #4f46e5;--warn: #b35900;font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:14px;color:var(--text)}*{box-sizing:border-box}body{margin:0;background:var(--bg)}.layout{display:grid;grid-template-columns:260px minmax(0,1fr) 380px;height:100vh}.sidebar{border-right:1px solid var(--border);overflow-y:auto;padding:12px;background:var(--panel)}.sidebar-title{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin:16px 0 6px}.tree{list-style:none;margin:0;padding-left:12px}.tree-folder,.tree-composition{cursor:pointer;font-weight:600;padding:2px 0}.tree-item,.link{display:inline-flex;align-items:center;gap:6px;width:100%;text-align:left;background:none;border:none;padding:3px 6px;border-radius:5px;color:var(--text);cursor:pointer;font:inherit}.tree-item:hover{background:#eaeef2}.tree-item.active{background:var(--accent);color:#fff}.link{width:auto;color:var(--accent);padding:0;text-decoration:underline}.swatch{width:10px;height:10px;border-radius:2px;flex:none}.canvas{overflow-y:auto;padding:20px 24px}.canvas-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:12px}.canvas-title{font-size:18px;margin:0;display:flex;align-items:center;gap:8px}.legend{list-style:none;display:flex;flex-wrap:wrap;gap:10px;padding:0;margin:0 0 14px;font-size:12px;color:var(--muted)}.legend li{display:inline-flex;align-items:center;gap:5px}.prompt{display:flex;flex-direction:column;gap:14px}.segment{position:relative;margin:0;padding:16px 12px 12px;border-radius:6px;border:1px solid var(--border);white-space:pre-wrap;word-break:break-word;font-family:ui-monospace,SF Mono,Menlo,monospace;font-size:13px;line-height:1.5}.segment-tag{position:absolute;top:0;right:0;font-size:10px;padding:1px 6px;background:#0000000f;border-bottom-left-radius:6px;font-family:system-ui,sans-serif;color:var(--muted)}.rail{border-left:1px solid var(--border);overflow-y:auto;padding:16px;background:var(--panel)}.rail section,.addons section{margin-bottom:18px}.rail h3,.addons h3{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin:0 0 8px}.rail h4{margin:12px 0 4px;font-size:12px}select,input{width:100%;padding:4px 6px;border:1px solid var(--border);border-radius:5px;font:inherit;background:#fff}.control-row{display:grid;grid-template-columns:90px 1fr;align-items:center;gap:8px;margin-bottom:6px}.control-key{font-family:ui-monospace,monospace;font-size:12px;color:var(--muted)}.control-add{display:grid;grid-template-columns:1fr auto;gap:6px;margin-top:6px}.control-add button{border:1px solid var(--border);border-radius:5px;background:#fff;cursor:pointer;padding:0 10px}.rules,.findings,.warnings,.used-list{list-style:none;margin:0;padding:0}.rules li{padding:4px 0;border-bottom:1px solid var(--border);font-size:12px}.rules li.skipped{color:var(--muted)}.rule-mark{margin-right:6px}.rule-action{font-weight:600;margin-right:6px}.rule-effect{font-family:ui-monospace,monospace;margin-top:2px}.rule-reason{color:var(--muted);margin-top:2px}.order{font-family:ui-monospace,monospace;font-size:12px;word-break:break-word}.finding{display:flex;flex-wrap:wrap;gap:6px;align-items:baseline;padding:5px 0;border-bottom:1px solid var(--border);font-size:12px}.finding-sev{text-transform:uppercase;font-size:10px;font-weight:700;padding:1px 5px;border-radius:4px;background:#eaeef2}.finding.error .finding-sev{background:#ffd7d5;color:#a40e26}.finding.warning .finding-sev{background:#fff1c2;color:var(--warn)}.finding-rule{font-family:ui-monospace,monospace;color:var(--muted)}.diff-body{margin:8px 0 0;font-family:ui-monospace,monospace;font-size:12px;border:1px solid var(--border);border-radius:6px;overflow-x:auto;background:#fff}.diff-row{padding:0 8px;white-space:pre-wrap}.diff-row.add{background:#e6ffec}.diff-row.remove{background:#ffebe9}.diff-mark{display:inline-block;width:12px;color:var(--muted)}.annot-mark{background:#fff3b0;border-bottom:2px solid var(--warn);border-radius:2px;padding:0 1px}.annot-popover{position:fixed;z-index:20;width:280px;padding:10px;background:#fff;border:1px solid var(--border);border-radius:8px;box-shadow:0 8px 24px #00000029}.annot-popover textarea{width:100%;min-height:64px;resize:vertical;margin:6px 0}.annot-actions{display:flex;justify-content:flex-end;gap:10px;align-items:center}.annot-actions button[type=button]:last-child{border:1px solid var(--border);border-radius:5px;background:var(--accent);color:#fff;padding:4px 12px;cursor:pointer}.annot-actions button[disabled]{opacity:.5;cursor:default}.annot-quote{margin:0;font-style:italic;color:var(--muted);font-size:12px;word-break:break-word}.annot-list{list-style:none;margin:0;padding:0}.annot-list li{padding:8px 0;border-bottom:1px solid var(--border)}.annot-comment{margin:4px 0;font-size:13px;word-break:break-word}.annot-meta{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:12px}.badge{font-size:12px;padding:2px 8px;border-radius:999px;background:#eaeef2;white-space:nowrap}.badge-code{font-size:10px;text-transform:uppercase;letter-spacing:.06em;background:#2b2b40;color:#fff}.code-tabs{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}.code-tab{font:inherit;font-size:12px;padding:3px 10px;border-radius:999px;border:1px solid var(--border);background:var(--panel);color:var(--text);cursor:pointer}.code-tab.active{background:var(--accent);border-color:var(--accent)}.code-diff{margin-top:18px}.tokens{font-size:20px;font-weight:600;margin:0}.muted{color:var(--muted)}.warn{color:var(--warn)}.used-list li{padding:3px 0}
|