rubric-chat 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.
Files changed (41) hide show
  1. package/dist/commands/list.js +34 -0
  2. package/dist/commands/list.js.map +1 -0
  3. package/dist/commands/login.js +110 -0
  4. package/dist/commands/login.js.map +1 -0
  5. package/dist/commands/logout.js +7 -0
  6. package/dist/commands/logout.js.map +1 -0
  7. package/dist/commands/rate.js +116 -0
  8. package/dist/commands/rate.js.map +1 -0
  9. package/dist/commands/status.js +47 -0
  10. package/dist/commands/status.js.map +1 -0
  11. package/dist/commands/whoami.js +20 -0
  12. package/dist/commands/whoami.js.map +1 -0
  13. package/dist/commands/wizard.js +107 -0
  14. package/dist/commands/wizard.js.map +1 -0
  15. package/dist/index.js +70 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/lib/api.js +53 -0
  18. package/dist/lib/api.js.map +1 -0
  19. package/dist/lib/config.js +80 -0
  20. package/dist/lib/config.js.map +1 -0
  21. package/dist/lib/local-server.js +126 -0
  22. package/dist/lib/local-server.js.map +1 -0
  23. package/dist/lib/render.js +38 -0
  24. package/dist/lib/render.js.map +1 -0
  25. package/dist/sources/claudeCode.js +200 -0
  26. package/dist/sources/claudeCode.js.map +1 -0
  27. package/dist/sources/claudeCode.test.js +55 -0
  28. package/dist/sources/claudeCode.test.js.map +1 -0
  29. package/dist/sources/codex.js +200 -0
  30. package/dist/sources/codex.js.map +1 -0
  31. package/dist/sources/codex.test.js +64 -0
  32. package/dist/sources/codex.test.js.map +1 -0
  33. package/dist/sources/generic.js +169 -0
  34. package/dist/sources/generic.js.map +1 -0
  35. package/dist/sources/index.js +12 -0
  36. package/dist/sources/index.js.map +1 -0
  37. package/dist/sources/types.js +2 -0
  38. package/dist/sources/types.js.map +1 -0
  39. package/dist/types.js +4 -0
  40. package/dist/types.js.map +1 -0
  41. package/package.json +64 -0
@@ -0,0 +1,34 @@
1
+ import kleur from "kleur";
2
+ import { getSource, SOURCES } from "../sources/index.js";
3
+ export async function runList(options) {
4
+ const limit = options.limit ? Number(options.limit) : 20;
5
+ const toolNames = options.tool ? [options.tool] : Object.keys(SOURCES);
6
+ const results = [];
7
+ for (const name of toolNames) {
8
+ const source = getSource(name);
9
+ if (!source) {
10
+ console.error(kleur.red(`Unknown tool: ${name}. Available: ${Object.keys(SOURCES).join(", ")}`));
11
+ process.exitCode = 1;
12
+ return;
13
+ }
14
+ const stubs = await source.discover(limit);
15
+ results.push({ source: source.label, stubs });
16
+ }
17
+ if (options.json) {
18
+ console.log(JSON.stringify(results, null, 2));
19
+ return;
20
+ }
21
+ for (const { source, stubs } of results) {
22
+ console.log(kleur.bold(source));
23
+ if (stubs.length === 0) {
24
+ console.log(kleur.dim(" No sessions found."));
25
+ continue;
26
+ }
27
+ for (const stub of stubs) {
28
+ const when = stub.last_modified.slice(0, 16).replace("T", " ");
29
+ console.log(` ${kleur.cyan(stub.id.slice(0, 12))} ${kleur.dim(when)} ${kleur.dim(`(${stub.turn_count} turns)`)} ${stub.preview}`);
30
+ }
31
+ console.log();
32
+ }
33
+ }
34
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAQzD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAoB;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEvE,MAAM,OAAO,GAA2F,EAAE,CAAC;IAC3G,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,IAAI,gBAAgB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACjG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,KAAK,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,OAAO,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC;YAC/C,SAAS;QACX,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC/D,OAAO,CAAC,GAAG,CACT,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,SAAS,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CACzH,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -0,0 +1,110 @@
1
+ import kleur from "kleur";
2
+ import openBrowser from "open";
3
+ import prompts from "prompts";
4
+ import { fetchMe, requestMagicLink, verifyMagicLink } from "../lib/api.js";
5
+ import { getWebBaseUrl, storeToken } from "../lib/config.js";
6
+ import { startLocalCallback } from "../lib/local-server.js";
7
+ /**
8
+ * Runs the local-callback login flow with a manual paste-token fallback.
9
+ * Returns true if the user ends up signed in, false otherwise.
10
+ */
11
+ export async function runLogin(options = {}) {
12
+ const email = await ensureEmail(options.email);
13
+ if (!email) {
14
+ console.error(kleur.red("Email is required."));
15
+ process.exitCode = 1;
16
+ return false;
17
+ }
18
+ if (!options.noBrowser) {
19
+ try {
20
+ const ok = await loginViaBrowserCallback(email);
21
+ if (ok)
22
+ return true;
23
+ }
24
+ catch (err) {
25
+ console.error(kleur.yellow(`Browser flow couldn't complete: ${err.message}`));
26
+ console.error(kleur.dim("Falling back to manual token entry…"));
27
+ }
28
+ }
29
+ return loginViaManualToken(email);
30
+ }
31
+ async function ensureEmail(provided) {
32
+ if (provided)
33
+ return provided;
34
+ const response = await prompts({
35
+ type: "text",
36
+ name: "email",
37
+ message: "Email"
38
+ });
39
+ return response.email;
40
+ }
41
+ async function loginViaBrowserCallback(email) {
42
+ const callback = startLocalCallback();
43
+ try {
44
+ await requestMagicLink(email, {
45
+ callbackUrl: callback.callbackUrl,
46
+ callbackState: callback.state
47
+ });
48
+ }
49
+ catch (err) {
50
+ callback.close();
51
+ throw err;
52
+ }
53
+ console.log(kleur.cyan("\nOpening browser to ") +
54
+ kleur.bold(email) +
55
+ kleur.cyan("'s magic link…"));
56
+ console.log(kleur.dim(`Listening on ${callback.callbackUrl} (state ${callback.state.slice(0, 8)}…)`));
57
+ // The magic-link email is the actual entry point; we open the inbox-agnostic
58
+ // login page so the user knows what to expect while they wait for the email.
59
+ void openBrowser(`${getWebBaseUrl()}/auth/login`).catch(() => undefined);
60
+ try {
61
+ const result = await callback.wait();
62
+ await storeToken(result.jwt);
63
+ const me = await fetchMe();
64
+ console.log(kleur.green(`\nSigned in as ${me.email}.`));
65
+ return true;
66
+ }
67
+ catch (err) {
68
+ if (err.message.includes("Timed out")) {
69
+ console.error(kleur.yellow("\nBrowser sign-in timed out."));
70
+ return false;
71
+ }
72
+ throw err;
73
+ }
74
+ }
75
+ async function loginViaManualToken(email) {
76
+ console.log(kleur.cyan("\nWe'll send a magic link to ") + kleur.bold(email) + kleur.cyan("."));
77
+ try {
78
+ await requestMagicLink(email);
79
+ }
80
+ catch (err) {
81
+ console.error(kleur.red(`Could not request magic link: ${err.message}`));
82
+ process.exitCode = 1;
83
+ return false;
84
+ }
85
+ console.log(kleur.dim("Open it, then paste the `token:` value back here."));
86
+ const tokenAnswer = await prompts({
87
+ type: "text",
88
+ name: "token",
89
+ message: "Magic-link token"
90
+ });
91
+ const token = tokenAnswer.token?.trim();
92
+ if (!token) {
93
+ console.error(kleur.red("Token is required."));
94
+ process.exitCode = 1;
95
+ return false;
96
+ }
97
+ try {
98
+ const session = await verifyMagicLink(token);
99
+ await storeToken(session.jwt);
100
+ const me = await fetchMe();
101
+ console.log(kleur.green(`Signed in as ${me.email}.`));
102
+ return true;
103
+ }
104
+ catch (err) {
105
+ console.error(kleur.red(`Verification failed: ${err.message}`));
106
+ process.exitCode = 1;
107
+ return false;
108
+ }
109
+ }
110
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import kleur from "kleur";
2
+ import { clearToken } from "../lib/config.js";
3
+ export async function runLogout() {
4
+ await clearToken();
5
+ console.log(kleur.green("Signed out."));
6
+ }
7
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,UAAU,EAAE,CAAC;IACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,116 @@
1
+ import kleur from "kleur";
2
+ import prompts from "prompts";
3
+ import { analyzeSession } from "../lib/api.js";
4
+ import { getWebBaseUrl } from "../lib/config.js";
5
+ import { renderReport, renderTeaser } from "../lib/render.js";
6
+ import { loadGenericSession } from "../sources/generic.js";
7
+ import { getSource, SOURCES } from "../sources/index.js";
8
+ export async function runRate(target, options) {
9
+ let session;
10
+ let usedPath = options.file ?? target;
11
+ if (options.interactive) {
12
+ const stub = await pickInteractive(options.tool);
13
+ if (!stub) {
14
+ console.log(kleur.yellow("No selection. Exiting."));
15
+ return;
16
+ }
17
+ const source = getSource(stub.source);
18
+ if (!source)
19
+ throw new Error(`Unknown source ${stub.source}`);
20
+ session = await source.load(stub);
21
+ usedPath = stub.path;
22
+ }
23
+ else if (options.file) {
24
+ session = await loadGenericSession(options.file);
25
+ }
26
+ else if (target) {
27
+ if (target.includes("/") || target.endsWith(".json") || target.endsWith(".jsonl")) {
28
+ session = await loadGenericSession(target);
29
+ }
30
+ else {
31
+ const stub = await findStubById(target, options.tool);
32
+ if (!stub) {
33
+ console.error(kleur.red(`Could not find a session with id starting "${target}".`));
34
+ process.exitCode = 1;
35
+ return;
36
+ }
37
+ const source = getSource(stub.source);
38
+ if (!source)
39
+ throw new Error(`Unknown source ${stub.source}`);
40
+ session = await source.load(stub);
41
+ usedPath = stub.path;
42
+ }
43
+ }
44
+ else {
45
+ console.error(kleur.red("Provide a session id, --file <path>, or --interactive."));
46
+ process.exitCode = 1;
47
+ return;
48
+ }
49
+ if (session.turns.length === 0) {
50
+ console.error(kleur.red(`No user turns found in ${usedPath ?? "input"}.`));
51
+ process.exitCode = 1;
52
+ return;
53
+ }
54
+ if (!options.quiet) {
55
+ console.log(kleur.dim(`Analyzing ${session.turns.length} user turns…`));
56
+ }
57
+ const response = await analyzeSession(session);
58
+ const webBase = getWebBaseUrl();
59
+ if (options.json) {
60
+ console.log(JSON.stringify(response));
61
+ return;
62
+ }
63
+ if (response.kind === "teaser" && response.teaser) {
64
+ if (options.quiet) {
65
+ console.log(response.teaser.score);
66
+ }
67
+ else {
68
+ console.log(renderTeaser(response.teaser, webBase));
69
+ }
70
+ return;
71
+ }
72
+ if (response.kind === "full" && response.report) {
73
+ if (options.quiet) {
74
+ console.log(response.report.score);
75
+ }
76
+ else {
77
+ console.log(renderReport(response.report, webBase));
78
+ }
79
+ }
80
+ }
81
+ async function pickInteractive(toolFilter) {
82
+ const sources = toolFilter
83
+ ? [getSource(toolFilter)].filter((s) => Boolean(s))
84
+ : Object.values(SOURCES);
85
+ const all = [];
86
+ for (const source of sources) {
87
+ const stubs = await source.discover(20);
88
+ all.push(...stubs);
89
+ }
90
+ if (all.length === 0)
91
+ return null;
92
+ all.sort((a, b) => b.last_modified.localeCompare(a.last_modified));
93
+ const response = await prompts({
94
+ type: "select",
95
+ name: "stub",
96
+ message: "Pick a session",
97
+ choices: all.map((stub) => ({
98
+ title: `${stub.id.slice(0, 12)} ${stub.last_modified.slice(0, 16).replace("T", " ")} ${stub.preview}`,
99
+ value: stub
100
+ }))
101
+ });
102
+ return response.stub;
103
+ }
104
+ async function findStubById(prefix, toolFilter) {
105
+ const sources = toolFilter
106
+ ? [getSource(toolFilter)].filter((s) => Boolean(s))
107
+ : Object.values(SOURCES);
108
+ for (const source of sources) {
109
+ const stubs = await source.discover(100);
110
+ const match = stubs.find((stub) => stub.id.startsWith(prefix));
111
+ if (match)
112
+ return match;
113
+ }
114
+ return null;
115
+ }
116
+ //# sourceMappingURL=rate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate.js","sourceRoot":"","sources":["../../src/commands/rate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import kleur from "kleur";
2
+ import { fetchBillingStatus, fetchMe } from "../lib/api.js";
3
+ import { getApiBaseUrl, getWebBaseUrl, readToken } from "../lib/config.js";
4
+ export async function runStatus() {
5
+ const apiUrl = getApiBaseUrl();
6
+ const webUrl = getWebBaseUrl();
7
+ console.log("");
8
+ console.log(` ${kleur.bold("API")} ${kleur.cyan(apiUrl)}`);
9
+ console.log(` ${kleur.bold("Web")} ${kleur.cyan(webUrl)}`);
10
+ const token = await readToken();
11
+ if (!token) {
12
+ console.log(` ${kleur.bold("Auth")} ${kleur.yellow("Not signed in. Run `rubric-chat login`.")}`);
13
+ console.log("");
14
+ process.exitCode = 1;
15
+ return;
16
+ }
17
+ try {
18
+ const me = await fetchMe();
19
+ console.log(` ${kleur.bold("Auth")} ${kleur.green("Signed in")} as ${me.email}`);
20
+ }
21
+ catch (err) {
22
+ console.log(` ${kleur.bold("Auth")} ${kleur.yellow(`Token rejected: ${err.message}`)}`);
23
+ process.exitCode = 1;
24
+ return;
25
+ }
26
+ try {
27
+ const billing = await fetchBillingStatus();
28
+ if (billing.is_premium) {
29
+ const ends = billing.current_period_end
30
+ ? `, renews ${billing.current_period_end.slice(0, 10)}`
31
+ : "";
32
+ const cancelled = billing.cancel_at_period_end ? kleur.yellow(" (cancels at period end)") : "";
33
+ console.log(` ${kleur.bold("Plan")} ${kleur.magenta("Premium")}${ends}${cancelled}`);
34
+ }
35
+ else if (billing.upgrade_url) {
36
+ console.log(` ${kleur.bold("Plan")} ${kleur.dim("Free")} — upgrade at ${billing.upgrade_url}`);
37
+ }
38
+ else {
39
+ console.log(` ${kleur.bold("Plan")} ${kleur.dim("Free")}`);
40
+ }
41
+ }
42
+ catch (err) {
43
+ console.log(` ${kleur.bold("Plan")} ${kleur.dim(`Billing status unavailable: ${err.message}`)}`);
44
+ }
45
+ console.log("");
46
+ }
47
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import kleur from "kleur";
2
+ import { fetchMe } from "../lib/api.js";
3
+ import { readToken } from "../lib/config.js";
4
+ export async function runWhoami() {
5
+ const token = await readToken();
6
+ if (!token) {
7
+ console.log(kleur.yellow("Not signed in. Run `rubric-chat login`."));
8
+ process.exitCode = 1;
9
+ return;
10
+ }
11
+ try {
12
+ const me = await fetchMe();
13
+ console.log(`${me.email} (${me.id})`);
14
+ }
15
+ catch (err) {
16
+ console.error(kleur.red(`Could not verify session: ${err.message}`));
17
+ process.exitCode = 1;
18
+ }
19
+ }
20
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,OAAO,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,6BAA8B,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAChF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -0,0 +1,107 @@
1
+ import kleur from "kleur";
2
+ import openBrowser from "open";
3
+ import prompts from "prompts";
4
+ import { analyzeSession } from "../lib/api.js";
5
+ import { getWebBaseUrl, readToken } from "../lib/config.js";
6
+ import { renderReport, renderTeaser } from "../lib/render.js";
7
+ import { getSource, SOURCES } from "../sources/index.js";
8
+ import { runLogin } from "./login.js";
9
+ export async function runWizard() {
10
+ printBanner();
11
+ if (!(await readToken())) {
12
+ console.log(kleur.dim("Looks like this is your first run on this machine. Let's get you signed in.\n"));
13
+ const ok = await runLogin();
14
+ if (!ok)
15
+ return;
16
+ }
17
+ const stub = await pickSession();
18
+ if (!stub) {
19
+ console.log(kleur.dim("\nNo session selected. Run `rubric-chat list` to see what's discoverable, or `rubric-chat rate --file <path>` to score a file directly."));
20
+ return;
21
+ }
22
+ const source = getSource(stub.source);
23
+ if (!source) {
24
+ console.error(kleur.red(`Unknown source ${stub.source}.`));
25
+ process.exitCode = 1;
26
+ return;
27
+ }
28
+ console.log(kleur.dim(`\nLoading ${stub.path}…`));
29
+ const session = await source.load(stub);
30
+ if (session.turns.length === 0) {
31
+ console.error(kleur.red("No user turns found in this session."));
32
+ process.exitCode = 1;
33
+ return;
34
+ }
35
+ console.log(kleur.dim(`Analyzing ${session.turns.length} user turn${session.turns.length === 1 ? "" : "s"}…`));
36
+ const response = await analyzeSession(session);
37
+ const webBase = getWebBaseUrl();
38
+ if (response.kind === "teaser" && response.teaser) {
39
+ console.log(renderTeaser(response.teaser, webBase));
40
+ }
41
+ else if (response.kind === "full" && response.report) {
42
+ console.log(renderReport(response.report, webBase));
43
+ await afterReport(response.report.id);
44
+ }
45
+ }
46
+ async function pickSession() {
47
+ const stubs = [];
48
+ for (const source of Object.values(SOURCES)) {
49
+ try {
50
+ const found = await source.discover(10);
51
+ stubs.push(...found);
52
+ }
53
+ catch {
54
+ // Skip sources we can't enumerate (likely no directory on this machine).
55
+ }
56
+ }
57
+ if (stubs.length === 0)
58
+ return null;
59
+ stubs.sort((a, b) => b.last_modified.localeCompare(a.last_modified));
60
+ const response = await prompts({
61
+ type: "select",
62
+ name: "stub",
63
+ message: "Pick a session to score",
64
+ choices: stubs.map((stub) => ({
65
+ title: `${kleur.cyan(stub.id.slice(0, 12))} ${kleur.dim(stub.last_modified.slice(0, 16).replace("T", " "))} ${kleur.dim(`(${stub.turn_count} turns)`)} ${stub.preview}`,
66
+ value: stub
67
+ })),
68
+ hint: "↑↓ to move, Enter to choose"
69
+ });
70
+ return response.stub ?? null;
71
+ }
72
+ async function afterReport(reportId) {
73
+ const response = await prompts({
74
+ type: "select",
75
+ name: "next",
76
+ message: "What now?",
77
+ choices: [
78
+ { title: "Open this report in the browser", value: "open" },
79
+ { title: "Score another session", value: "again" },
80
+ { title: "Quit", value: "quit" }
81
+ ]
82
+ });
83
+ const choice = response.next;
84
+ if (choice === "open") {
85
+ const url = `${getWebBaseUrl()}/result/${reportId}`;
86
+ console.log(kleur.dim(`Opening ${url}`));
87
+ try {
88
+ await openBrowser(url);
89
+ }
90
+ catch {
91
+ console.log(kleur.yellow("Couldn't open browser automatically. Copy the URL above."));
92
+ }
93
+ }
94
+ else if (choice === "again") {
95
+ await runWizard();
96
+ }
97
+ }
98
+ function printBanner() {
99
+ const lines = [
100
+ "",
101
+ kleur.bold(" rubric-chat") + kleur.dim(" · score the way you prompt"),
102
+ kleur.dim(" ──────────────────────────────"),
103
+ ""
104
+ ];
105
+ console.log(lines.join("\n"));
106
+ }
107
+ //# sourceMappingURL=wizard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../src/commands/wizard.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { runList } from "./commands/list.js";
4
+ import { runLogin } from "./commands/login.js";
5
+ import { runLogout } from "./commands/logout.js";
6
+ import { runRate } from "./commands/rate.js";
7
+ import { runStatus } from "./commands/status.js";
8
+ import { runWhoami } from "./commands/whoami.js";
9
+ import { runWizard } from "./commands/wizard.js";
10
+ import { CLI_VERSION } from "./lib/config.js";
11
+ const program = new Command();
12
+ program
13
+ .name("rubric-chat")
14
+ .description("Score full AI chat sessions with Rubric.")
15
+ .version(CLI_VERSION);
16
+ program
17
+ .command("login")
18
+ .description("Sign in via magic link (opens browser by default).")
19
+ .option("--email <email>", "Email address to use")
20
+ .option("--no-browser", "Skip the browser flow and paste the token manually")
21
+ .action(async (opts) => {
22
+ await runLogin(opts);
23
+ });
24
+ program
25
+ .command("logout")
26
+ .description("Clear stored credentials.")
27
+ .action(async () => {
28
+ await runLogout();
29
+ });
30
+ program
31
+ .command("whoami")
32
+ .description("Show the signed-in account.")
33
+ .action(async () => {
34
+ await runWhoami();
35
+ });
36
+ program
37
+ .command("status")
38
+ .description("Show auth + plan + configured URLs.")
39
+ .action(async () => {
40
+ await runStatus();
41
+ });
42
+ program
43
+ .command("list")
44
+ .description("List sessions discovered on disk.")
45
+ .option("--tool <tool>", "Filter by source (claude-code | codex)")
46
+ .option("--limit <n>", "How many sessions to show per tool", "20")
47
+ .option("--json", "Output as JSON")
48
+ .action(async (opts) => {
49
+ await runList(opts);
50
+ });
51
+ program
52
+ .command("rate [sessionId]")
53
+ .description("Score a session and print the result.")
54
+ .option("--tool <tool>", "Limit lookup to a specific source (claude-code | codex)")
55
+ .option("--file <path>", "Path to a session file (JSON or .jsonl)")
56
+ .option("--json", "Print the analyze response as JSON")
57
+ .option("--quiet", "Print only the score")
58
+ .option("--interactive", "Pick a session from a list")
59
+ .action(async (sessionId, opts) => {
60
+ await runRate(sessionId, opts);
61
+ });
62
+ // Default action: when invoked with no subcommand, launch the interactive wizard.
63
+ program.action(async () => {
64
+ await runWizard();
65
+ });
66
+ program.parseAsync(process.argv).catch((err) => {
67
+ console.error(err instanceof Error ? err.message : err);
68
+ process.exit(1);
69
+ });
70
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { getApiBaseUrl, readToken } from "./config.js";
2
+ async function authHeaders() {
3
+ const jwt = await readToken();
4
+ return jwt ? { Authorization: `Bearer ${jwt}` } : {};
5
+ }
6
+ async function unwrap(response) {
7
+ if (!response.ok) {
8
+ const detail = await response.text().catch(() => "");
9
+ throw new Error(detail || `Request failed: ${response.status}`);
10
+ }
11
+ return (await response.json());
12
+ }
13
+ export async function requestMagicLink(email, opts = {}) {
14
+ const response = await fetch(`${getApiBaseUrl()}/auth/magic-link`, {
15
+ method: "POST",
16
+ headers: { "content-type": "application/json" },
17
+ body: JSON.stringify({
18
+ email,
19
+ callback_url: opts.callbackUrl ?? null,
20
+ callback_state: opts.callbackState ?? null
21
+ })
22
+ });
23
+ await unwrap(response);
24
+ }
25
+ export async function verifyMagicLink(token) {
26
+ const response = await fetch(`${getApiBaseUrl()}/auth/verify?token=${encodeURIComponent(token)}`);
27
+ return unwrap(response);
28
+ }
29
+ export async function fetchMe() {
30
+ const headers = await authHeaders();
31
+ const response = await fetch(`${getApiBaseUrl()}/auth/me`, { headers });
32
+ return unwrap(response);
33
+ }
34
+ export async function analyzeSession(session) {
35
+ const headers = await authHeaders();
36
+ const response = await fetch(`${getApiBaseUrl()}/analyze`, {
37
+ method: "POST",
38
+ headers: { "content-type": "application/json", ...headers },
39
+ body: JSON.stringify(session)
40
+ });
41
+ return unwrap(response);
42
+ }
43
+ export async function fetchReport(id) {
44
+ const headers = await authHeaders();
45
+ const response = await fetch(`${getApiBaseUrl()}/reports/${id}`, { headers });
46
+ return unwrap(response);
47
+ }
48
+ export async function fetchBillingStatus() {
49
+ const headers = await authHeaders();
50
+ const response = await fetch(`${getApiBaseUrl()}/billing/status`, { headers });
51
+ return unwrap(response);
52
+ }
53
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}