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.
Files changed (107) hide show
  1. package/.claude/settings.local.json +26 -0
  2. package/.prettierignore +7 -0
  3. package/.prettierrc +11 -0
  4. package/CONTRIBUTING.md +209 -0
  5. package/LICENSE +21 -0
  6. package/README.md +109 -0
  7. package/app/(dashboard)/coach/page.tsx +11 -0
  8. package/app/(dashboard)/commands/page.tsx +7 -0
  9. package/app/(dashboard)/community/[slug]/page.tsx +23 -0
  10. package/app/(dashboard)/community/page.tsx +71 -0
  11. package/app/(dashboard)/daily/page.tsx +19 -0
  12. package/app/(dashboard)/images/page.tsx +5 -0
  13. package/app/(dashboard)/layout.tsx +12 -0
  14. package/app/(dashboard)/page.tsx +23 -0
  15. package/app/(dashboard)/personality/page.tsx +11 -0
  16. package/app/(dashboard)/projects/page.tsx +11 -0
  17. package/app/(dashboard)/sessions/page.tsx +11 -0
  18. package/app/(dashboard)/tokens/page.tsx +11 -0
  19. package/app/(dashboard)/tools/page.tsx +11 -0
  20. package/app/api/check/route.ts +13 -0
  21. package/app/api/commands/route.ts +16 -0
  22. package/app/api/images/[...path]/route.ts +33 -0
  23. package/app/api/images-analysis/route.ts +177 -0
  24. package/app/api/sync/route.ts +14 -0
  25. package/app/api/usage/route.ts +117 -0
  26. package/app/favicon.ico +0 -0
  27. package/app/globals.css +144 -0
  28. package/app/icon.svg +3 -0
  29. package/app/layout.tsx +35 -0
  30. package/bin/agentfit.mjs +69 -0
  31. package/components/.gitkeep +0 -0
  32. package/components/agent-coach.tsx +248 -0
  33. package/components/app-sidebar.tsx +161 -0
  34. package/components/command-usage.tsx +294 -0
  35. package/components/daily-chart.tsx +118 -0
  36. package/components/daily-table.tsx +115 -0
  37. package/components/dashboard-shell.tsx +149 -0
  38. package/components/data-provider.tsx +213 -0
  39. package/components/fitness-score.tsx +95 -0
  40. package/components/overview-cards.tsx +198 -0
  41. package/components/pagination-controls.tsx +104 -0
  42. package/components/personality-fit.tsx +446 -0
  43. package/components/projects-table.tsx +70 -0
  44. package/components/screenshots-analysis.tsx +359 -0
  45. package/components/sessions-table.tsx +97 -0
  46. package/components/theme-provider.tsx +71 -0
  47. package/components/token-breakdown.tsx +179 -0
  48. package/components/tool-usage-chart.tsx +63 -0
  49. package/components/ui/badge.tsx +52 -0
  50. package/components/ui/button.tsx +60 -0
  51. package/components/ui/card.tsx +103 -0
  52. package/components/ui/chart.tsx +373 -0
  53. package/components/ui/dialog.tsx +160 -0
  54. package/components/ui/input.tsx +20 -0
  55. package/components/ui/scroll-area.tsx +55 -0
  56. package/components/ui/select.tsx +201 -0
  57. package/components/ui/separator.tsx +25 -0
  58. package/components/ui/sheet.tsx +138 -0
  59. package/components/ui/sidebar.tsx +723 -0
  60. package/components/ui/skeleton.tsx +13 -0
  61. package/components/ui/table.tsx +116 -0
  62. package/components/ui/tabs.tsx +82 -0
  63. package/components/ui/tooltip.tsx +66 -0
  64. package/components.json +25 -0
  65. package/generated/prisma/browser.ts +34 -0
  66. package/generated/prisma/client.ts +58 -0
  67. package/generated/prisma/commonInputTypes.ts +237 -0
  68. package/generated/prisma/enums.ts +15 -0
  69. package/generated/prisma/internal/class.ts +224 -0
  70. package/generated/prisma/internal/prismaNamespace.ts +920 -0
  71. package/generated/prisma/internal/prismaNamespaceBrowser.ts +130 -0
  72. package/generated/prisma/models/Image.ts +1310 -0
  73. package/generated/prisma/models/Session.ts +1695 -0
  74. package/generated/prisma/models/SyncLog.ts +1203 -0
  75. package/generated/prisma/models.ts +14 -0
  76. package/hooks/.gitkeep +0 -0
  77. package/hooks/use-mobile.ts +19 -0
  78. package/hooks/use-pagination.ts +60 -0
  79. package/lib/.gitkeep +0 -0
  80. package/lib/coach.ts +425 -0
  81. package/lib/commands.ts +239 -0
  82. package/lib/db.ts +15 -0
  83. package/lib/format.ts +26 -0
  84. package/lib/parse-codex.ts +201 -0
  85. package/lib/parse-logs.ts +369 -0
  86. package/lib/personality.ts +481 -0
  87. package/lib/plugins.ts +107 -0
  88. package/lib/pricing.ts +112 -0
  89. package/lib/queries-codex.ts +130 -0
  90. package/lib/queries.ts +154 -0
  91. package/lib/resolve-icon.ts +12 -0
  92. package/lib/sync.ts +335 -0
  93. package/lib/utils.ts +6 -0
  94. package/next.config.mjs +4 -0
  95. package/package.json +73 -0
  96. package/plugins/cost-heatmap/component.test.tsx +52 -0
  97. package/plugins/cost-heatmap/component.tsx +227 -0
  98. package/plugins/cost-heatmap/manifest.ts +13 -0
  99. package/plugins/index.ts +18 -0
  100. package/prisma/migrations/20260328152517_init/migration.sql +41 -0
  101. package/prisma/migrations/20260328153801_add_image_model/migration.sql +18 -0
  102. package/prisma/migrations/migration_lock.toml +3 -0
  103. package/prisma/schema.prisma +57 -0
  104. package/prisma.config.ts +14 -0
  105. package/public/.gitkeep +0 -0
  106. package/public/logo.svg +3 -0
  107. 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
@@ -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,3 @@
1
+ # Please do not edit this file manually
2
+ # It should be added in your version-control system (e.g., Git)
3
+ provider = "sqlite"
@@ -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
+ }
@@ -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
+ });
File without changes
@@ -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 ""