@earntori/cli 0.2.0 → 0.2.1

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 (2) hide show
  1. package/dist/index.js +12 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import { readFileSync, writeFileSync, mkdirSync, existsSync, appendFileSync, unl
4
4
  import { homedir } from "node:os";
5
5
  import { join, resolve, relative, isAbsolute, dirname } from "node:path";
6
6
  import { execSync } from "node:child_process";
7
+ import { createHash } from "node:crypto";
7
8
  const CONFIG_DIR = join(homedir(), ".tori");
8
9
  const CONFIG = join(CONFIG_DIR, "config.json");
9
10
  const args = process.argv.slice(2);
@@ -22,7 +23,7 @@ function out(o, human) { console.log(json ? JSON.stringify(o, null, 2) : human);
22
23
  function die(msg) { console.error(json ? JSON.stringify({ error: msg }) : `\u2717 ${msg}`); process.exit(1); }
23
24
  const usd = (c) => `$${(c / 100).toFixed(2)}`;
24
25
  async function api(cfg, method, path, body) {
25
- const r = await fetch(`${cfg.base}${path}`, { method, headers: { Authorization: `Bearer ${cfg.token}`, "Content-Type": "application/json", "User-Agent": "@earntori/cli/0.2.0" }, body: body ? JSON.stringify(body) : undefined });
26
+ const r = await fetch(`${cfg.base}${path}`, { method, headers: { Authorization: `Bearer ${cfg.token}`, "Content-Type": "application/json", "User-Agent": "@earntori/cli/0.2.1" }, body: body ? JSON.stringify(body) : undefined });
26
27
  const t = await r.text();
27
28
  let j = null;
28
29
  try {
@@ -154,6 +155,15 @@ function init() {
154
155
  `\n\nClaude Code: restart the session (hooks and .mcp.json load at start). Cursor: reload the window.\nTori's checks now run when the agent finishes a turn; findings are shown to the agent before it stops.`);
155
156
  }
156
157
  const CODE_EXT = /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rb|php|java|kt|cs)$/i;
158
+ function projectId() {
159
+ try {
160
+ const url = execSync("git config --get remote.origin.url", { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
161
+ if (url)
162
+ return url.replace(/^https?:\/\/[^@]*@/, "https://").replace(/\.git$/, "").toLowerCase();
163
+ }
164
+ catch { }
165
+ return "local:" + createHash("sha256").update(process.cwd()).digest("hex").slice(0, 12);
166
+ }
157
167
  function gitChanged() {
158
168
  try {
159
169
  const o = execSync("git status --porcelain --untracked-files=all", { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
@@ -220,7 +230,7 @@ async function check() {
220
230
  }
221
231
  let r;
222
232
  try {
223
- const res = await fetch(`${cfg.base}/api/v1/checks/run`, { method: "POST", headers: { Authorization: `Bearer ${cfg.token}`, "Content-Type": "application/json", "User-Agent": "@earntori/cli/check" }, body: JSON.stringify({ files }) });
233
+ const res = await fetch(`${cfg.base}/api/v1/checks/run`, { method: "POST", headers: { Authorization: `Bearer ${cfg.token}`, "Content-Type": "application/json", "User-Agent": "@earntori/cli/check" }, body: JSON.stringify({ files, project: projectId() }) });
224
234
  const t = await res.text();
225
235
  if (!res.ok)
226
236
  throw new Error(`Tori API ${res.status}${t ? ": " + t.slice(0, 200) : ""}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earntori/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Tori CLI \u2014 sign in with GitHub, check your credits, mint a capped AI key into your tools.",
5
5
  "license": "MIT",
6
6
  "type": "module",