@archeagle087/costcrew 0.0.0-stage → 0.4.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.
- package/.github/workflows/ci.yml +21 -0
- package/.github/workflows/npm-release.yml +123 -0
- package/.github/workflows/prices-monthly.yml +58 -0
- package/.github/workflows/release.yml +45 -0
- package/Cargo.lock +980 -0
- package/Cargo.toml +22 -0
- package/LICENSE +21 -0
- package/README.md +255 -2
- package/assets/advise.png +0 -0
- package/assets/board.png +0 -0
- package/assets/catalog.png +0 -0
- package/assets/demo.png +0 -0
- package/assets/help.png +0 -0
- package/assets/mascot.png +0 -0
- package/assets/prices.png +0 -0
- package/assets/scan.png +0 -0
- package/assets/spend.png +0 -0
- package/assets/ui.png +0 -0
- package/bin.js +46 -0
- package/data/prices.json +1 -0
- package/dist/costcrew-linux-x86_64.tar.gz +0 -0
- package/dist/costcrew-macos-aarch64.tar.gz +0 -0
- package/dist/costcrew-macos-x86_64.tar.gz +0 -0
- package/dist/costcrew-windows-x86_64.zip +0 -0
- package/install.ps1 +38 -0
- package/install.sh +56 -0
- package/package.json +18 -4
- package/packaging/npm/bin.js +46 -0
- package/packaging/npm/package.json +20 -0
- package/packaging/winget/0.4.0/Arch087146.costcrew.installer.yaml +15 -0
- package/packaging/winget/0.4.0/Arch087146.costcrew.locale.en-US.yaml +28 -0
- package/packaging/winget/0.4.0/Arch087146.costcrew.yaml +5 -0
- package/packaging/winget/README.md +31 -0
- package/scripts/render_screen.py +221 -0
- package/src/advise.rs +154 -0
- package/src/args.rs +239 -0
- package/src/board.rs +227 -0
- package/src/catalog.rs +136 -0
- package/src/demo.rs +79 -0
- package/src/fetch.rs +155 -0
- package/src/main.rs +371 -0
- package/src/price.rs +218 -0
- package/src/prices.rs +182 -0
- package/src/report.rs +194 -0
- package/src/scan.rs +593 -0
- package/src/spend.rs +452 -0
- package/src/ui.rs +367 -0
- package/work/costcrew-darwin-arm64/costcrew +0 -0
- package/work/costcrew-darwin-arm64/package.json +9 -0
- package/work/costcrew-darwin-x64/costcrew +0 -0
- package/work/costcrew-darwin-x64/package.json +9 -0
- package/work/costcrew-linux-x64/costcrew +0 -0
- package/work/costcrew-linux-x64/package.json +9 -0
- package/work/costcrew-win32-x64/costcrew.exe +0 -0
- package/work/costcrew-win32-x64/package.json +9 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
check:
|
|
9
|
+
runs-on: ${{ matrix.os }}
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
16
|
+
with:
|
|
17
|
+
components: clippy, rustfmt
|
|
18
|
+
- run: cargo fmt --all -- --check
|
|
19
|
+
- run: cargo clippy --all-targets -- -D warnings
|
|
20
|
+
- run: cargo test
|
|
21
|
+
- run: cargo build --release
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
name: npm-release
|
|
2
|
+
# Publishes @archeagle087/costcrew plus one binary package per platform.
|
|
3
|
+
# Runs on every v* tag, after the Release workflow has uploaded assets.
|
|
4
|
+
# Without NPM_TOKEN set in repo secrets this publishes nothing — it exits
|
|
5
|
+
# with a notice so the run stays green and the steps are easy to find.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["v*"]
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
publish:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: 20
|
|
24
|
+
registry-url: https://registry.npmjs.org
|
|
25
|
+
|
|
26
|
+
- name: resolve version + tag
|
|
27
|
+
id: ver
|
|
28
|
+
env:
|
|
29
|
+
GH_TOKEN: ${{ github.token }}
|
|
30
|
+
run: |
|
|
31
|
+
if [[ "${GITHUB_REF_NAME}" == v* ]]; then
|
|
32
|
+
TAG="${GITHUB_REF_NAME}"
|
|
33
|
+
else
|
|
34
|
+
# manual dispatch from a branch: fall back to the latest release
|
|
35
|
+
TAG="$(gh api "repos/${GITHUB_REPOSITORY}/releases/latest" --jq .tag_name)"
|
|
36
|
+
fi
|
|
37
|
+
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
|
38
|
+
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
|
|
39
|
+
|
|
40
|
+
- name: check for NPM_TOKEN
|
|
41
|
+
id: tok
|
|
42
|
+
run: |
|
|
43
|
+
if [ -n "${NPM_TOKEN:-}" ]; then
|
|
44
|
+
echo "have_token=true" >> "$GITHUB_OUTPUT"
|
|
45
|
+
else
|
|
46
|
+
echo "have_token=false" >> "$GITHUB_OUTPUT"
|
|
47
|
+
echo "::notice::NPM_TOKEN secret not set — skipping npm publish. Add it in Settings → Secrets → Actions."
|
|
48
|
+
fi
|
|
49
|
+
env:
|
|
50
|
+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
51
|
+
|
|
52
|
+
- name: download release assets (waits for Release to finish)
|
|
53
|
+
if: steps.tok.outputs.have_token == 'true'
|
|
54
|
+
run: |
|
|
55
|
+
mkdir -p dist
|
|
56
|
+
assets="costcrew-linux-x86_64.tar.gz costcrew-macos-aarch64.tar.gz costcrew-macos-x86_64.tar.gz costcrew-windows-x86_64.zip"
|
|
57
|
+
TAG="${{ steps.ver.outputs.tag }}"
|
|
58
|
+
fetch() {
|
|
59
|
+
for a in $assets; do
|
|
60
|
+
if [ ! -s "dist/$a" ]; then
|
|
61
|
+
# 404 if Release hasn't uploaded yet — retry later, never
|
|
62
|
+
# leave a partial file behind
|
|
63
|
+
curl -fsSL "https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}/${a}" -o "dist/$a.part" \
|
|
64
|
+
&& mv "dist/$a.part" "dist/$a" || rm -f "dist/$a.part"
|
|
65
|
+
fi
|
|
66
|
+
done
|
|
67
|
+
for a in $assets; do [ -s "dist/$a" ] || return 1; done
|
|
68
|
+
}
|
|
69
|
+
fetch && exit 0
|
|
70
|
+
for i in $(seq 1 120); do # Release builds take a few minutes
|
|
71
|
+
sleep 10
|
|
72
|
+
fetch && exit 0
|
|
73
|
+
done
|
|
74
|
+
echo "::error::release assets for ${TAG} not found after 20 minutes"
|
|
75
|
+
exit 1
|
|
76
|
+
|
|
77
|
+
- name: assemble + publish platform packages
|
|
78
|
+
if: steps.tok.outputs.have_token == 'true'
|
|
79
|
+
env:
|
|
80
|
+
VERSION: ${{ steps.ver.outputs.version }}
|
|
81
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
82
|
+
run: |
|
|
83
|
+
set -euo pipefail
|
|
84
|
+
V="${VERSION}"
|
|
85
|
+
mkdir -p work
|
|
86
|
+
|
|
87
|
+
# platform package = one package.json + the naked binary
|
|
88
|
+
emit() { # name asset cmd
|
|
89
|
+
local name="$1" asset="$2" cmd="$3" dir="work/$1"
|
|
90
|
+
mkdir -p "$dir"
|
|
91
|
+
tar xzf "dist/$asset" -C "$dir" || true
|
|
92
|
+
unzip -qo "dist/$asset" -d "$dir" || true
|
|
93
|
+
[ -f "$dir/$cmd" ] || { echo "::error::binary $cmd missing from $asset"; exit 1; }
|
|
94
|
+
chmod +x "$dir/$cmd"
|
|
95
|
+
cat > "$dir/package.json" <<EOF
|
|
96
|
+
{
|
|
97
|
+
"name": "@archeagle087/$name",
|
|
98
|
+
"version": "$V",
|
|
99
|
+
"description": "costcrew native binary ($name) — do not install directly",
|
|
100
|
+
"os": ["$4"],
|
|
101
|
+
"cpu": ["$5"],
|
|
102
|
+
"license": "MIT",
|
|
103
|
+
"repository": "github:Arch087146/costcrew"
|
|
104
|
+
}
|
|
105
|
+
EOF
|
|
106
|
+
# files field: ship only what's needed
|
|
107
|
+
( cd "$dir" && npm publish --access public --non-interactive )
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
emit costcrew-linux-x64 costcrew-linux-x86_64.tar.gz costcrew linux x64
|
|
111
|
+
emit costcrew-darwin-arm64 costcrew-macos-aarch64.tar.gz costcrew darwin arm64
|
|
112
|
+
emit costcrew-darwin-x64 costcrew-macos-x86_64.tar.gz costcrew darwin x64
|
|
113
|
+
emit costcrew-win32-x64 costcrew-windows-x86_64.zip costcrew.exe win32 x64
|
|
114
|
+
|
|
115
|
+
- name: publish wrapper
|
|
116
|
+
if: steps.tok.outputs.have_token == 'true'
|
|
117
|
+
env:
|
|
118
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
119
|
+
run: |
|
|
120
|
+
cp packaging/npm/package.json .
|
|
121
|
+
sed -i "s/\"0\.4\.0\"/\"${{ steps.ver.outputs.version }}\"/g" package.json
|
|
122
|
+
cp packaging/npm/bin.js .
|
|
123
|
+
npm publish --access public --non-interactive
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Refresh data/prices.json monthly so the bundled price database
|
|
2
|
+
# ships fresh. Runs on the 3rd of each month + manual dispatch.
|
|
3
|
+
# If OpenRouter returned anything new, it commits directly to main.
|
|
4
|
+
name: prices-monthly
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: "17 5 3 * *" # 05:17 UTC, 3rd of the month
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
refresh:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Fetch live OpenRouter catalog
|
|
21
|
+
run: |
|
|
22
|
+
python3 - <<'EOF'
|
|
23
|
+
import json, time, urllib.request
|
|
24
|
+
url = "https://openrouter.ai/api/v1/models"
|
|
25
|
+
with urllib.request.urlopen(url, timeout=30) as r:
|
|
26
|
+
v = json.load(r)
|
|
27
|
+
models = []
|
|
28
|
+
for m in v.get("data", []):
|
|
29
|
+
p = m.get("pricing", {})
|
|
30
|
+
f = lambda k: float(p.get(k) or 0) * 1_000_000
|
|
31
|
+
models.append({
|
|
32
|
+
"id": m.get("id"),
|
|
33
|
+
"prompt": f("prompt"),
|
|
34
|
+
"completion": f("completion"),
|
|
35
|
+
"cache_read": f("input_cache_read"),
|
|
36
|
+
"cache_write": f("input_cache_write"),
|
|
37
|
+
})
|
|
38
|
+
doc = {
|
|
39
|
+
"version": 1,
|
|
40
|
+
"fetched_at_ms": int(time.time() * 1000),
|
|
41
|
+
"models": [m for m in models if m["id"]],
|
|
42
|
+
}
|
|
43
|
+
with open("data/prices.json", "w") as fh:
|
|
44
|
+
json.dump(doc, fh)
|
|
45
|
+
print("models:", len(doc["models"]))
|
|
46
|
+
EOF
|
|
47
|
+
|
|
48
|
+
- name: Commit if changed
|
|
49
|
+
run: |
|
|
50
|
+
git config user.name "costcrew-bot"
|
|
51
|
+
git config user.email "actions@users.noreply.github.com"
|
|
52
|
+
git add data/prices.json
|
|
53
|
+
if git diff --cached --quiet; then
|
|
54
|
+
echo "no price changes"
|
|
55
|
+
else
|
|
56
|
+
git commit -m "prices: monthly refresh from OpenRouter ($(date -u +%Y-%m-%d))"
|
|
57
|
+
git push
|
|
58
|
+
fi
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags: ["v*"]
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: write
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
include:
|
|
14
|
+
- os: ubuntu-latest
|
|
15
|
+
target: x86_64-unknown-linux-gnu
|
|
16
|
+
artifact: costcrew-linux-x86_64.tar.gz
|
|
17
|
+
- os: macos-latest
|
|
18
|
+
target: aarch64-apple-darwin
|
|
19
|
+
artifact: costcrew-macos-aarch64.tar.gz
|
|
20
|
+
- os: macos-latest
|
|
21
|
+
target: x86_64-apple-darwin
|
|
22
|
+
artifact: costcrew-macos-x86_64.tar.gz
|
|
23
|
+
- os: windows-latest
|
|
24
|
+
target: x86_64-pc-windows-msvc
|
|
25
|
+
artifact: costcrew-windows-x86_64.zip
|
|
26
|
+
runs-on: ${{ matrix.os }}
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
30
|
+
with:
|
|
31
|
+
targets: ${{ matrix.target }}
|
|
32
|
+
- run: cargo build --release --target ${{ matrix.target }}
|
|
33
|
+
- name: Package (unix)
|
|
34
|
+
if: runner.os != 'Windows'
|
|
35
|
+
run: |
|
|
36
|
+
cd target/${{ matrix.target }}/release
|
|
37
|
+
tar czf ../../../${{ matrix.artifact }} costcrew
|
|
38
|
+
- name: Package (windows)
|
|
39
|
+
if: runner.os == 'Windows'
|
|
40
|
+
shell: pwsh
|
|
41
|
+
run: |
|
|
42
|
+
Compress-Archive target/${{ matrix.target }}/release/costcrew.exe ${{ matrix.artifact }}
|
|
43
|
+
- uses: softprops/action-gh-release@v2
|
|
44
|
+
with:
|
|
45
|
+
files: ${{ matrix.artifact }}
|