awarts 0.3.0 → 0.3.2
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/CODE_OF_CONDUCT.md +27 -0
- package/CONTRIBUTING.md +66 -0
- package/SECURITY.md +9 -0
- package/dist/index.js +51 -9
- package/package.json +5 -2
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
|
6
|
+
|
|
7
|
+
## Our Standards
|
|
8
|
+
|
|
9
|
+
**Positive behavior includes:**
|
|
10
|
+
- Using welcoming and inclusive language
|
|
11
|
+
- Being respectful of differing viewpoints
|
|
12
|
+
- Gracefully accepting constructive criticism
|
|
13
|
+
- Focusing on what is best for the community
|
|
14
|
+
|
|
15
|
+
**Unacceptable behavior includes:**
|
|
16
|
+
- Trolling, insulting comments, and personal attacks
|
|
17
|
+
- Harassment in any form
|
|
18
|
+
- Publishing others' private information without permission
|
|
19
|
+
- Other conduct which could reasonably be considered inappropriate
|
|
20
|
+
|
|
21
|
+
## Enforcement
|
|
22
|
+
|
|
23
|
+
Instances of abusive or unacceptable behavior may be reported by opening an issue or contacting the maintainer. All complaints will be reviewed and investigated.
|
|
24
|
+
|
|
25
|
+
## Attribution
|
|
26
|
+
|
|
27
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Contributing to AWARTS CLI
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing to AWARTS! Here's how to get started.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
1. Clone the repo:
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/HarshalJain-cs/AWARTS.git
|
|
10
|
+
cd AWARTS/cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Install dependencies:
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
3. Run in dev mode:
|
|
19
|
+
```bash
|
|
20
|
+
npm run dev
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Project Structure
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
cli/
|
|
27
|
+
src/
|
|
28
|
+
index.ts # CLI entry point (commander setup)
|
|
29
|
+
types.ts # Shared TypeScript types
|
|
30
|
+
adapters/ # Provider adapters (claude, codex, gemini, antigravity)
|
|
31
|
+
commands/ # Command implementations
|
|
32
|
+
lib/ # Core libraries (auth, daemon, api, output)
|
|
33
|
+
dist/ # Built output
|
|
34
|
+
package.json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Adding a New Provider Adapter
|
|
38
|
+
|
|
39
|
+
1. Create `src/adapters/<provider>.ts` implementing the `Adapter` interface:
|
|
40
|
+
```typescript
|
|
41
|
+
interface Adapter {
|
|
42
|
+
name: ProviderKey;
|
|
43
|
+
displayName: string;
|
|
44
|
+
detect(): Promise<boolean>;
|
|
45
|
+
read(): Promise<UsageEntry[]>;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
2. Register it in `src/lib/detect.ts`
|
|
50
|
+
|
|
51
|
+
3. Test with `awarts push --provider <name> --dry-run`
|
|
52
|
+
|
|
53
|
+
## Guidelines
|
|
54
|
+
|
|
55
|
+
- Write clear commit messages
|
|
56
|
+
- Keep PRs focused on a single change
|
|
57
|
+
- Test your changes locally before submitting
|
|
58
|
+
- Don't commit API keys or credentials
|
|
59
|
+
|
|
60
|
+
## Reporting Issues
|
|
61
|
+
|
|
62
|
+
Open an issue at [github.com/HarshalJain-cs/AWARTS/issues](https://github.com/HarshalJain-cs/AWARTS/issues) with:
|
|
63
|
+
- Node.js version (`node --version`)
|
|
64
|
+
- OS and version
|
|
65
|
+
- Steps to reproduce
|
|
66
|
+
- Expected vs actual behavior
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a Vulnerability
|
|
4
|
+
|
|
5
|
+
If you discover a security vulnerability, please email **harshaljaincs@gmail.com**.
|
|
6
|
+
|
|
7
|
+
**Do NOT open a public GitHub issue for security vulnerabilities.**
|
|
8
|
+
|
|
9
|
+
See the full security policy at [github.com/HarshalJain-cs/AWARTS/SECURITY.md](https://github.com/HarshalJain-cs/AWARTS/blob/main/SECURITY.md).
|
package/dist/index.js
CHANGED
|
@@ -4710,26 +4710,61 @@ var open_default = open;
|
|
|
4710
4710
|
import fs7 from "node:fs/promises";
|
|
4711
4711
|
import path3 from "node:path";
|
|
4712
4712
|
import os4 from "node:os";
|
|
4713
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4713
4714
|
|
|
4714
4715
|
// src/lib/auth-store.ts
|
|
4715
4716
|
import fs6 from "node:fs/promises";
|
|
4716
4717
|
import path2 from "node:path";
|
|
4717
4718
|
import os3 from "node:os";
|
|
4719
|
+
import crypto from "node:crypto";
|
|
4718
4720
|
var AWARTS_DIR = path2.join(os3.homedir(), ".awarts");
|
|
4719
4721
|
var AUTH_FILE = path2.join(AWARTS_DIR, "auth.json");
|
|
4722
|
+
function deriveKey() {
|
|
4723
|
+
const material = `awarts-cli:${os3.hostname()}:${os3.userInfo().username}`;
|
|
4724
|
+
return crypto.createHash("sha256").update(material).digest();
|
|
4725
|
+
}
|
|
4726
|
+
function encrypt(plaintext) {
|
|
4727
|
+
const key = deriveKey();
|
|
4728
|
+
const iv = crypto.randomBytes(12);
|
|
4729
|
+
const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
|
|
4730
|
+
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
4731
|
+
const tag = cipher.getAuthTag();
|
|
4732
|
+
return {
|
|
4733
|
+
version: 2,
|
|
4734
|
+
iv: iv.toString("hex"),
|
|
4735
|
+
tag: tag.toString("hex"),
|
|
4736
|
+
ciphertext: encrypted.toString("hex")
|
|
4737
|
+
};
|
|
4738
|
+
}
|
|
4739
|
+
function decrypt(file) {
|
|
4740
|
+
const key = deriveKey();
|
|
4741
|
+
const decipher = crypto.createDecipheriv("aes-256-gcm", key, Buffer.from(file.iv, "hex"));
|
|
4742
|
+
decipher.setAuthTag(Buffer.from(file.tag, "hex"));
|
|
4743
|
+
return decipher.update(file.ciphertext, "hex", "utf8") + decipher.final("utf8");
|
|
4744
|
+
}
|
|
4720
4745
|
async function ensureDir() {
|
|
4721
4746
|
await fs6.mkdir(AWARTS_DIR, { recursive: true, mode: 448 });
|
|
4722
4747
|
}
|
|
4723
4748
|
async function saveAuth(data) {
|
|
4724
4749
|
await ensureDir();
|
|
4725
|
-
|
|
4750
|
+
const encrypted = encrypt(JSON.stringify(data));
|
|
4751
|
+
await fs6.writeFile(AUTH_FILE, JSON.stringify(encrypted, null, 2), { encoding: "utf-8", mode: 384 });
|
|
4726
4752
|
}
|
|
4727
4753
|
async function loadAuth() {
|
|
4728
4754
|
try {
|
|
4729
4755
|
const raw = await fs6.readFile(AUTH_FILE, "utf-8");
|
|
4730
4756
|
const parsed = JSON.parse(raw);
|
|
4757
|
+
if (parsed.version === 2 && parsed.ciphertext) {
|
|
4758
|
+
const decrypted = JSON.parse(decrypt(parsed));
|
|
4759
|
+
if (typeof decrypted.token === "string" && typeof decrypted.user_id === "string") {
|
|
4760
|
+
return decrypted;
|
|
4761
|
+
}
|
|
4762
|
+
return null;
|
|
4763
|
+
}
|
|
4731
4764
|
if (typeof parsed.token === "string" && typeof parsed.user_id === "string") {
|
|
4732
|
-
|
|
4765
|
+
const data = parsed;
|
|
4766
|
+
await saveAuth(data);
|
|
4767
|
+
return data;
|
|
4733
4768
|
}
|
|
4734
4769
|
return null;
|
|
4735
4770
|
} catch {
|
|
@@ -4747,6 +4782,13 @@ async function getToken() {
|
|
|
4747
4782
|
}
|
|
4748
4783
|
|
|
4749
4784
|
// src/lib/api.ts
|
|
4785
|
+
var __dirname3 = path3.dirname(fileURLToPath2(import.meta.url));
|
|
4786
|
+
var _cliVersion = "0.0.0";
|
|
4787
|
+
try {
|
|
4788
|
+
const pkgPath = path3.resolve(__dirname3, "..", "package.json");
|
|
4789
|
+
const pkg = JSON.parse(await fs7.readFile(pkgPath, "utf-8"));
|
|
4790
|
+
_cliVersion = pkg.version ?? "0.0.0";
|
|
4791
|
+
} catch {}
|
|
4750
4792
|
var DEFAULT_API_URL = "https://honorable-bee-242.convex.site";
|
|
4751
4793
|
async function readConfigUrl() {
|
|
4752
4794
|
try {
|
|
@@ -4781,7 +4823,7 @@ async function apiRequest(method, endpoint, body) {
|
|
|
4781
4823
|
const token = await getToken();
|
|
4782
4824
|
const headers = {
|
|
4783
4825
|
"Content-Type": "application/json",
|
|
4784
|
-
"User-Agent":
|
|
4826
|
+
"User-Agent": `awarts-cli/${_cliVersion}`
|
|
4785
4827
|
};
|
|
4786
4828
|
if (token) {
|
|
4787
4829
|
headers["Authorization"] = `Bearer ${token}`;
|
|
@@ -4808,7 +4850,7 @@ async function postUnauthenticated(endpoint, body) {
|
|
|
4808
4850
|
method: "POST",
|
|
4809
4851
|
headers: {
|
|
4810
4852
|
"Content-Type": "application/json",
|
|
4811
|
-
"User-Agent":
|
|
4853
|
+
"User-Agent": `awarts-cli/${_cliVersion}`
|
|
4812
4854
|
},
|
|
4813
4855
|
body: body != null ? JSON.stringify(body) : undefined
|
|
4814
4856
|
});
|
|
@@ -5990,7 +6032,7 @@ import os7 from "node:os";
|
|
|
5990
6032
|
var KEYS_PATH = path6.join(os7.homedir(), ".awarts", "keys.json");
|
|
5991
6033
|
async function ensureDir3() {
|
|
5992
6034
|
const dir = path6.dirname(KEYS_PATH);
|
|
5993
|
-
await fs10.mkdir(dir, { recursive: true });
|
|
6035
|
+
await fs10.mkdir(dir, { recursive: true, mode: 448 });
|
|
5994
6036
|
}
|
|
5995
6037
|
async function loadKeys() {
|
|
5996
6038
|
try {
|
|
@@ -7376,12 +7418,12 @@ async function daemonRunLoop(intervalMs) {
|
|
|
7376
7418
|
|
|
7377
7419
|
// src/lib/version-check.ts
|
|
7378
7420
|
import { readFileSync } from "node:fs";
|
|
7379
|
-
import { fileURLToPath as
|
|
7421
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
7380
7422
|
import { dirname, join } from "node:path";
|
|
7381
|
-
var
|
|
7423
|
+
var __dirname4 = dirname(fileURLToPath3(import.meta.url));
|
|
7382
7424
|
function getLocalVersion() {
|
|
7383
7425
|
try {
|
|
7384
|
-
const pkg = JSON.parse(readFileSync(join(
|
|
7426
|
+
const pkg = JSON.parse(readFileSync(join(__dirname4, "..", "package.json"), "utf-8"));
|
|
7385
7427
|
return pkg.version ?? "0.0.0";
|
|
7386
7428
|
} catch {
|
|
7387
7429
|
return "0.0.0";
|
|
@@ -7408,7 +7450,7 @@ async function checkForUpdates() {
|
|
|
7408
7450
|
|
|
7409
7451
|
// src/index.ts
|
|
7410
7452
|
var program2 = new Command;
|
|
7411
|
-
program2.name("awarts").description("Track your AI coding spend across Claude, Codex, Gemini & Antigravity").version("0.3.
|
|
7453
|
+
program2.name("awarts").description("Track your AI coding spend across Claude, Codex, Gemini & Antigravity").version("0.3.1").hook("preAction", () => checkForUpdates());
|
|
7412
7454
|
program2.command("login").description("Authenticate with your AWARTS account via device auth").option("--force", "Re-authenticate even if already logged in").action(async (opts) => {
|
|
7413
7455
|
try {
|
|
7414
7456
|
if (opts.force) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "awarts",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Track your AI coding across Claude, Codex, Gemini & Antigravity",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,10 @@
|
|
|
34
34
|
"files": [
|
|
35
35
|
"dist",
|
|
36
36
|
"README.md",
|
|
37
|
-
"LICENSE"
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"CONTRIBUTING.md",
|
|
39
|
+
"CODE_OF_CONDUCT.md",
|
|
40
|
+
"SECURITY.md"
|
|
38
41
|
],
|
|
39
42
|
"sideEffects": false,
|
|
40
43
|
"scripts": {
|