agentfit 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/.claude/settings.local.json +26 -0
- package/.prettierignore +7 -0
- package/.prettierrc +11 -0
- package/CONTRIBUTING.md +209 -0
- package/LICENSE +21 -0
- package/README.md +109 -0
- package/app/(dashboard)/coach/page.tsx +11 -0
- package/app/(dashboard)/commands/page.tsx +7 -0
- package/app/(dashboard)/community/[slug]/page.tsx +23 -0
- package/app/(dashboard)/community/page.tsx +71 -0
- package/app/(dashboard)/daily/page.tsx +19 -0
- package/app/(dashboard)/images/page.tsx +5 -0
- package/app/(dashboard)/layout.tsx +12 -0
- package/app/(dashboard)/page.tsx +23 -0
- package/app/(dashboard)/personality/page.tsx +11 -0
- package/app/(dashboard)/projects/page.tsx +11 -0
- package/app/(dashboard)/sessions/page.tsx +11 -0
- package/app/(dashboard)/tokens/page.tsx +11 -0
- package/app/(dashboard)/tools/page.tsx +11 -0
- package/app/api/check/route.ts +13 -0
- package/app/api/commands/route.ts +16 -0
- package/app/api/images/[...path]/route.ts +33 -0
- package/app/api/images-analysis/route.ts +177 -0
- package/app/api/sync/route.ts +14 -0
- package/app/api/usage/route.ts +117 -0
- package/app/favicon.ico +0 -0
- package/app/globals.css +144 -0
- package/app/icon.svg +3 -0
- package/app/layout.tsx +35 -0
- package/bin/agentfit.mjs +69 -0
- package/components/.gitkeep +0 -0
- package/components/agent-coach.tsx +248 -0
- package/components/app-sidebar.tsx +161 -0
- package/components/command-usage.tsx +294 -0
- package/components/daily-chart.tsx +118 -0
- package/components/daily-table.tsx +115 -0
- package/components/dashboard-shell.tsx +149 -0
- package/components/data-provider.tsx +213 -0
- package/components/fitness-score.tsx +95 -0
- package/components/overview-cards.tsx +198 -0
- package/components/pagination-controls.tsx +104 -0
- package/components/personality-fit.tsx +446 -0
- package/components/projects-table.tsx +70 -0
- package/components/screenshots-analysis.tsx +359 -0
- package/components/sessions-table.tsx +97 -0
- package/components/theme-provider.tsx +71 -0
- package/components/token-breakdown.tsx +179 -0
- package/components/tool-usage-chart.tsx +63 -0
- package/components/ui/badge.tsx +52 -0
- package/components/ui/button.tsx +60 -0
- package/components/ui/card.tsx +103 -0
- package/components/ui/chart.tsx +373 -0
- package/components/ui/dialog.tsx +160 -0
- package/components/ui/input.tsx +20 -0
- package/components/ui/scroll-area.tsx +55 -0
- package/components/ui/select.tsx +201 -0
- package/components/ui/separator.tsx +25 -0
- package/components/ui/sheet.tsx +138 -0
- package/components/ui/sidebar.tsx +723 -0
- package/components/ui/skeleton.tsx +13 -0
- package/components/ui/table.tsx +116 -0
- package/components/ui/tabs.tsx +82 -0
- package/components/ui/tooltip.tsx +66 -0
- package/components.json +25 -0
- package/generated/prisma/browser.ts +34 -0
- package/generated/prisma/client.ts +58 -0
- package/generated/prisma/commonInputTypes.ts +237 -0
- package/generated/prisma/enums.ts +15 -0
- package/generated/prisma/internal/class.ts +224 -0
- package/generated/prisma/internal/prismaNamespace.ts +920 -0
- package/generated/prisma/internal/prismaNamespaceBrowser.ts +130 -0
- package/generated/prisma/models/Image.ts +1310 -0
- package/generated/prisma/models/Session.ts +1695 -0
- package/generated/prisma/models/SyncLog.ts +1203 -0
- package/generated/prisma/models.ts +14 -0
- package/hooks/.gitkeep +0 -0
- package/hooks/use-mobile.ts +19 -0
- package/hooks/use-pagination.ts +60 -0
- package/lib/.gitkeep +0 -0
- package/lib/coach.ts +425 -0
- package/lib/commands.ts +239 -0
- package/lib/db.ts +15 -0
- package/lib/format.ts +26 -0
- package/lib/parse-codex.ts +201 -0
- package/lib/parse-logs.ts +369 -0
- package/lib/personality.ts +481 -0
- package/lib/plugins.ts +107 -0
- package/lib/pricing.ts +112 -0
- package/lib/queries-codex.ts +130 -0
- package/lib/queries.ts +154 -0
- package/lib/resolve-icon.ts +12 -0
- package/lib/sync.ts +335 -0
- package/lib/utils.ts +6 -0
- package/next.config.mjs +4 -0
- package/package.json +73 -0
- package/plugins/cost-heatmap/component.test.tsx +52 -0
- package/plugins/cost-heatmap/component.tsx +227 -0
- package/plugins/cost-heatmap/manifest.ts +13 -0
- package/plugins/index.ts +18 -0
- package/prisma/migrations/20260328152517_init/migration.sql +41 -0
- package/prisma/migrations/20260328153801_add_image_model/migration.sql +18 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +57 -0
- package/prisma.config.ts +14 -0
- package/public/.gitkeep +0 -0
- package/public/logo.svg +3 -0
- package/setup.sh +73 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PluginManifest } from '@/lib/plugins'
|
|
2
|
+
|
|
3
|
+
const manifest: PluginManifest = {
|
|
4
|
+
slug: 'cost-heatmap',
|
|
5
|
+
name: 'Cost Heatmap',
|
|
6
|
+
description: 'Visualize daily spending intensity as a calendar heatmap',
|
|
7
|
+
author: 'AgentFit Team',
|
|
8
|
+
icon: 'Flame',
|
|
9
|
+
version: '1.0.0',
|
|
10
|
+
tags: ['cost', 'calendar', 'heatmap'],
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default manifest
|
package/plugins/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin registration entrypoint.
|
|
3
|
+
*
|
|
4
|
+
* Community contributors: import your plugin's manifest and component here,
|
|
5
|
+
* then call registerPlugin(). See CONTRIBUTING.md for the full guide.
|
|
6
|
+
*/
|
|
7
|
+
import { registerPlugin } from '@/lib/plugins'
|
|
8
|
+
|
|
9
|
+
// ─── Built-in example ───────────────────────────────────────────────
|
|
10
|
+
import costHeatmapManifest from './cost-heatmap/manifest'
|
|
11
|
+
import CostHeatmap from './cost-heatmap/component'
|
|
12
|
+
|
|
13
|
+
registerPlugin(costHeatmapManifest, CostHeatmap)
|
|
14
|
+
|
|
15
|
+
// ─── Community plugins (add yours below this line) ──────────────────
|
|
16
|
+
// import myManifest from './my-plugin/manifest'
|
|
17
|
+
// import MyComponent from './my-plugin/component'
|
|
18
|
+
// registerPlugin(myManifest, MyComponent)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE "Session" (
|
|
3
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
4
|
+
"sessionId" TEXT NOT NULL,
|
|
5
|
+
"project" TEXT NOT NULL,
|
|
6
|
+
"projectPath" TEXT NOT NULL,
|
|
7
|
+
"startTime" DATETIME NOT NULL,
|
|
8
|
+
"endTime" DATETIME NOT NULL,
|
|
9
|
+
"durationMinutes" REAL NOT NULL,
|
|
10
|
+
"userMessages" INTEGER NOT NULL,
|
|
11
|
+
"assistantMessages" INTEGER NOT NULL,
|
|
12
|
+
"totalMessages" INTEGER NOT NULL,
|
|
13
|
+
"inputTokens" INTEGER NOT NULL,
|
|
14
|
+
"outputTokens" INTEGER NOT NULL,
|
|
15
|
+
"cacheCreationTokens" INTEGER NOT NULL,
|
|
16
|
+
"cacheReadTokens" INTEGER NOT NULL,
|
|
17
|
+
"totalTokens" INTEGER NOT NULL,
|
|
18
|
+
"costUSD" REAL NOT NULL,
|
|
19
|
+
"model" TEXT NOT NULL,
|
|
20
|
+
"toolCallsTotal" INTEGER NOT NULL,
|
|
21
|
+
"toolCallsJson" TEXT NOT NULL,
|
|
22
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
-- CreateTable
|
|
26
|
+
CREATE TABLE "SyncLog" (
|
|
27
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
28
|
+
"syncedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
29
|
+
"filesProcessed" INTEGER NOT NULL,
|
|
30
|
+
"sessionsAdded" INTEGER NOT NULL,
|
|
31
|
+
"sessionsSkipped" INTEGER NOT NULL
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
-- CreateIndex
|
|
35
|
+
CREATE UNIQUE INDEX "Session_sessionId_key" ON "Session"("sessionId");
|
|
36
|
+
|
|
37
|
+
-- CreateIndex
|
|
38
|
+
CREATE INDEX "Session_project_idx" ON "Session"("project");
|
|
39
|
+
|
|
40
|
+
-- CreateIndex
|
|
41
|
+
CREATE INDEX "Session_startTime_idx" ON "Session"("startTime");
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE "Image" (
|
|
3
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
4
|
+
"sessionId" TEXT NOT NULL,
|
|
5
|
+
"messageId" TEXT NOT NULL,
|
|
6
|
+
"filename" TEXT NOT NULL,
|
|
7
|
+
"mediaType" TEXT NOT NULL,
|
|
8
|
+
"sizeBytes" INTEGER NOT NULL,
|
|
9
|
+
"timestamp" DATETIME NOT NULL,
|
|
10
|
+
"role" TEXT NOT NULL,
|
|
11
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
-- CreateIndex
|
|
15
|
+
CREATE INDEX "Image_sessionId_idx" ON "Image"("sessionId");
|
|
16
|
+
|
|
17
|
+
-- CreateIndex
|
|
18
|
+
CREATE UNIQUE INDEX "Image_sessionId_messageId_filename_key" ON "Image"("sessionId", "messageId", "filename");
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
generator client {
|
|
2
|
+
provider = "prisma-client"
|
|
3
|
+
output = "../generated/prisma"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
datasource db {
|
|
7
|
+
provider = "sqlite"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
model Session {
|
|
11
|
+
id String @id @default(cuid())
|
|
12
|
+
sessionId String @unique
|
|
13
|
+
project String
|
|
14
|
+
projectPath String
|
|
15
|
+
startTime DateTime
|
|
16
|
+
endTime DateTime
|
|
17
|
+
durationMinutes Float
|
|
18
|
+
userMessages Int
|
|
19
|
+
assistantMessages Int
|
|
20
|
+
totalMessages Int
|
|
21
|
+
inputTokens Int
|
|
22
|
+
outputTokens Int
|
|
23
|
+
cacheCreationTokens Int
|
|
24
|
+
cacheReadTokens Int
|
|
25
|
+
totalTokens Int
|
|
26
|
+
costUSD Float
|
|
27
|
+
model String
|
|
28
|
+
toolCallsTotal Int
|
|
29
|
+
toolCallsJson String // JSON string of Record<string, number>
|
|
30
|
+
createdAt DateTime @default(now())
|
|
31
|
+
|
|
32
|
+
@@index([project])
|
|
33
|
+
@@index([startTime])
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
model Image {
|
|
37
|
+
id String @id @default(cuid())
|
|
38
|
+
sessionId String
|
|
39
|
+
messageId String // uuid of the message containing the image
|
|
40
|
+
filename String // relative path under data/images/
|
|
41
|
+
mediaType String // e.g. image/png
|
|
42
|
+
sizeBytes Int
|
|
43
|
+
timestamp DateTime
|
|
44
|
+
role String // user or assistant
|
|
45
|
+
createdAt DateTime @default(now())
|
|
46
|
+
|
|
47
|
+
@@index([sessionId])
|
|
48
|
+
@@unique([sessionId, messageId, filename])
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
model SyncLog {
|
|
52
|
+
id String @id @default(cuid())
|
|
53
|
+
syncedAt DateTime @default(now())
|
|
54
|
+
filesProcessed Int
|
|
55
|
+
sessionsAdded Int
|
|
56
|
+
sessionsSkipped Int
|
|
57
|
+
}
|
package/prisma.config.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// This file was generated by Prisma, and assumes you have installed the following:
|
|
2
|
+
// npm install --save-dev prisma dotenv
|
|
3
|
+
import "dotenv/config";
|
|
4
|
+
import { defineConfig } from "prisma/config";
|
|
5
|
+
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
schema: "prisma/schema.prisma",
|
|
8
|
+
migrations: {
|
|
9
|
+
path: "prisma/migrations",
|
|
10
|
+
},
|
|
11
|
+
datasource: {
|
|
12
|
+
url: process.env["DATABASE_URL"],
|
|
13
|
+
},
|
|
14
|
+
});
|
package/public/.gitkeep
ADDED
|
File without changes
|
package/public/logo.svg
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
+
<svg width="800px" height="800px" viewBox="0 -77.5 1179 1179" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M597.215632 994.574713h403.714943s43.549425-8.945287 43.549425-114.64092 94.16092-577.677241-459.976092-577.677241-457.151264 541.425287-457.151264 541.425287-25.423448 160.77977 54.848735 157.013333 415.014253-6.12046 415.014253-6.120459z" fill="#FFFFFF" /><path d="M1071.786667 712.798161h72.503908v136.297931h-72.503908zM36.016552 712.798161h72.503908v136.297931H36.016552z" fill="#EA5D5C" /><path d="M305.68366 559.40926l556.254412-1.165018 0.398364 190.20464-556.254412 1.165018-0.398364-190.20464Z" fill="#4C66AF" /><path d="M1129.931034 680.312644h-59.556781c-3.295632-152.069885-67.56046-258.942529-172.079081-324.384368l115.347127-238.462529a47.08046 47.08046 0 1 0-42.372414-20.48l-114.640919 236.57931a625.934713 625.934713 0 0 0-269.30023-53.200919 625.228506 625.228506 0 0 0-270.006437 54.848736l-115.817931-235.402299a47.08046 47.08046 0 1 0-42.372414 20.715402l117.701149 238.462529c-103.812414 65.441839-167.135632 173.02069-169.960459 324.61977H47.786667a47.08046 47.08046 0 0 0-47.08046 47.08046v117.701149a47.08046 47.08046 0 0 0 47.08046 47.08046h58.615172v57.908965a70.62069 70.62069 0 0 0 70.62069 70.62069l823.908046-1.647816a70.62069 70.62069 0 0 0 70.620689-70.62069v-57.908965h59.085977a47.08046 47.08046 0 0 0 47.08046-47.08046v-117.701149A47.08046 47.08046 0 0 0 1129.931034 680.312644zM94.16092 847.212874H47.08046v-117.70115h47.08046v117.70115z m929.83908 103.106206a23.54023 23.54023 0 0 1-23.54023 23.54023l-823.908046 1.647816a23.54023 23.54023 0 0 1-23.54023-23.540229v-258.942529c0-329.563218 303.668966-365.57977 434.788046-365.815173s435.494253 34.604138 436.20046 363.931954z m105.46023-105.224827h-47.08046v-117.70115h47.08046v117.70115z" fill="#3F4651" /><path d="M464.684138 135.827126l22.363218-19.53839 40.018391 62.381609a30.131494 30.131494 0 0 0 25.423448 13.888735h2.824828a30.131494 30.131494 0 0 0 25.188046-19.067586l20.715402-79.095172 21.186207 74.387126v2.118621a30.366897 30.366897 0 0 0 52.494713 6.826667l30.366896-57.202759 13.182529 12.947126a30.131494 30.131494 0 0 0 21.186207 8.709886h57.673563a23.54023 23.54023 0 0 0 23.54023-23.54023 23.54023 23.54023 0 0 0-23.54023-23.54023h-50.140689l-23.54023-23.54023a30.366897 30.366897 0 0 0-45.668046 3.766437l-21.42161 40.01839L629.465747 19.302989a30.131494 30.131494 0 0 0-28.012873-19.067587 30.131494 30.131494 0 0 0-28.012874 19.067587l-26.60046 101.693793-29.660689-47.08046a30.366897 30.366897 0 0 0-20.48-13.653333 30.837701 30.837701 0 0 0-23.54023 6.826666l-32.250115 28.248276h-60.027586a23.54023 23.54023 0 0 0-23.54023 23.54023 23.54023 23.54023 0 0 0 23.54023 23.54023h66.148046a31.308506 31.308506 0 0 0 17.655172-6.591265zM776.121379 532.950805H404.421149A121.232184 121.232184 0 0 0 282.482759 639.352644a117.701149 117.701149 0 0 0 117.701149 129.000459h371.70023a121.232184 121.232184 0 0 0 121.938391-106.401839 117.701149 117.701149 0 0 0-117.70115-129.000459z m0 188.321839H402.302529a72.503908 72.503908 0 0 1-72.268506-56.496552 70.62069 70.62069 0 0 1 68.972874-84.744828h373.81885a72.503908 72.503908 0 0 1 72.268506 56.496552 70.62069 70.62069 0 0 1-68.502069 84.744828z" fill="#3F4651" /></svg>
|
package/setup.sh
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# ─── AgentFit Installer ─────────────────────────────────────────────
|
|
5
|
+
# Usage:
|
|
6
|
+
# curl -fsSL https://raw.githubusercontent.com/harrywang/agentfit/main/setup.sh | bash
|
|
7
|
+
#
|
|
8
|
+
# Or clone manually:
|
|
9
|
+
# git clone https://github.com/harrywang/agentfit.git && cd agentfit && ./setup.sh
|
|
10
|
+
# ─────────────────────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
REPO="https://github.com/harrywang/agentfit.git"
|
|
13
|
+
DIR="agentfit"
|
|
14
|
+
PORT="${AGENTFIT_PORT:-3000}"
|
|
15
|
+
|
|
16
|
+
info() { printf "\033[1;34m==>\033[0m %s\n" "$1"; }
|
|
17
|
+
ok() { printf "\033[1;32m==>\033[0m %s\n" "$1"; }
|
|
18
|
+
error() { printf "\033[1;31m==>\033[0m %s\n" "$1" >&2; }
|
|
19
|
+
|
|
20
|
+
# ─── Prerequisites ───────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
command -v node >/dev/null 2>&1 || { error "Node.js is required. Install it from https://nodejs.org"; exit 1; }
|
|
23
|
+
command -v npm >/dev/null 2>&1 || { error "npm is required. It ships with Node.js."; exit 1; }
|
|
24
|
+
|
|
25
|
+
NODE_MAJOR=$(node -e "process.stdout.write(String(process.versions.node.split('.')[0]))")
|
|
26
|
+
if [ "$NODE_MAJOR" -lt 20 ]; then
|
|
27
|
+
error "Node.js 20+ is required (found v$(node -v)). Please upgrade."
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# ─── Clone (skip if already inside the repo) ────────────────────────
|
|
32
|
+
|
|
33
|
+
if [ ! -f "package.json" ] || ! grep -q '"agentfit"' package.json 2>/dev/null; then
|
|
34
|
+
if [ -d "$DIR" ]; then
|
|
35
|
+
info "Directory '$DIR' already exists — pulling latest..."
|
|
36
|
+
cd "$DIR"
|
|
37
|
+
git pull --ff-only
|
|
38
|
+
else
|
|
39
|
+
info "Cloning AgentFit..."
|
|
40
|
+
git clone "$REPO" "$DIR"
|
|
41
|
+
cd "$DIR"
|
|
42
|
+
fi
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# ─── Install ─────────────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
info "Installing dependencies..."
|
|
48
|
+
npm install
|
|
49
|
+
|
|
50
|
+
# ─── Database ────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
info "Setting up database..."
|
|
53
|
+
echo 'DATABASE_URL="file:./dev.db"' > .env
|
|
54
|
+
npx prisma generate
|
|
55
|
+
npx prisma migrate deploy
|
|
56
|
+
|
|
57
|
+
# ─── Build ───────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
info "Building production bundle..."
|
|
60
|
+
npm run build
|
|
61
|
+
|
|
62
|
+
# ─── Done ────────────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
ok "AgentFit is ready!"
|
|
65
|
+
echo ""
|
|
66
|
+
echo " Start the dashboard:"
|
|
67
|
+
echo " cd ${DIR} && npm start"
|
|
68
|
+
echo ""
|
|
69
|
+
echo " Or run in dev mode:"
|
|
70
|
+
echo " cd ${DIR} && npm run dev"
|
|
71
|
+
echo ""
|
|
72
|
+
echo " Then open http://localhost:${PORT}"
|
|
73
|
+
echo ""
|