mirror of
https://github.com/lobehub/lobehub
synced 2026-04-21 17:47:27 +00:00
🔨 chore: track user last active time (#10733)
This commit is contained in:
parent
542f4d97dd
commit
458cbf4d5c
21 changed files with 8595 additions and 92 deletions
|
|
@ -1,2 +1,2 @@
|
|||
npm run type-check
|
||||
npm run typecheck
|
||||
npx --no-install lint-staged
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ The project follows a well-organized monorepo structure:
|
|||
|
||||
### Type Checking
|
||||
|
||||
- Use `bun run type-check` to check for type errors
|
||||
- Use `bun run typecheck` to check for type errors
|
||||
|
||||
### i18n
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ see @.cursor/rules/typescript.mdc
|
|||
|
||||
### Typecheck
|
||||
|
||||
- use `bun run type-check` to check type errors.
|
||||
- use `bun run typecheck` to check type errors.
|
||||
|
||||
### i18n
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ When working with Linear issues:
|
|||
**Workflow for EACH individual issue:**
|
||||
|
||||
1. Complete the implementation for this specific issue
|
||||
2. Run type check: `bun run type-check`
|
||||
2. Run type check: `bun run typecheck`
|
||||
3. Run related tests if applicable
|
||||
4. Create PR if needed
|
||||
5. **IMMEDIATELY** update issue status to **"In Review"** (NOT "Done"): `mcp__linear-server__update_issue`
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ see @.cursor/rules/typescript.mdc
|
|||
|
||||
### Typecheck
|
||||
|
||||
- use `bun run type-check` to check type errors.
|
||||
- use `bun run typecheck` to check type errors.
|
||||
|
||||
### i18n
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
"@types/resolve": "^1.20.6",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@types/set-cookie-parser": "^2.4.10",
|
||||
"@typescript/native-preview": "7.0.0-dev.20250711.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20251210.1",
|
||||
"async-retry": "^1.3.3",
|
||||
"consola": "^3.4.2",
|
||||
"cookie": "^1.1.1",
|
||||
|
|
@ -67,18 +67,18 @@
|
|||
"happy-dom": "^20.0.11",
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"i18next": "^25.6.3",
|
||||
"i18next": "^25.7.2",
|
||||
"just-diff": "^6.0.2",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"resolve": "^1.22.11",
|
||||
"semver": "^7.7.3",
|
||||
"set-cookie-parser": "^2.7.2",
|
||||
"tsx": "^4.20.6",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.9.3",
|
||||
"undici": "^7.16.0",
|
||||
"uuid": "^13.0.0",
|
||||
"vite": "^7.2.4",
|
||||
"vite": "^7.2.7",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"pnpm": {
|
||||
|
|
|
|||
|
|
@ -8,23 +8,14 @@
|
|||
"esModuleInterop": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"composite": true,
|
||||
"baseUrl": ".",
|
||||
"experimentalDecorators": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/main/*"
|
||||
],
|
||||
"~common/*": [
|
||||
"src/common/*"
|
||||
]
|
||||
"@/*": ["./src/main/*"],
|
||||
"~common/*": ["./src/common/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src/main/**/*",
|
||||
"src/preload/**/*",
|
||||
"electron-builder.js"
|
||||
]
|
||||
}
|
||||
"include": ["src/main/**/*", "src/preload/**/*", "src/common/**/*", "electron-builder.js"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1063,6 +1063,7 @@ table users {
|
|||
ban_expires "timestamp with time zone"
|
||||
two_factor_enabled boolean [default: false]
|
||||
phone_number_verified boolean
|
||||
last_active_at "timestamp with time zone" [not null, default: `now()`]
|
||||
accessed_at "timestamp with time zone" [not null, default: `now()`]
|
||||
created_at "timestamp with time zone" [not null, default: `now()`]
|
||||
updated_at "timestamp with time zone" [not null, default: `now()`]
|
||||
|
|
|
|||
84
package.json
84
package.json
|
|
@ -60,7 +60,7 @@
|
|||
"e2e:install": "playwright install",
|
||||
"e2e:ui": "playwright test --ui",
|
||||
"i18n": "npm run workflow:i18n && lobe-i18n && prettier -c --write \"locales/**\"",
|
||||
"lint": "npm run lint:ts && npm run lint:style && npm run type-check && npm run lint:circular",
|
||||
"lint": "npm run lint:ts && npm run lint:style && npm run typecheck && npm run lint:circular",
|
||||
"lint:circular": "npm run lint:circular:main && npm run lint:circular:packages",
|
||||
"lint:circular:main": "dpdm src/**/*.ts --no-warning --no-tree --exit-code circular:1 --no-progress -T true --skip-dynamic-imports circular",
|
||||
"lint:circular:packages": "dpdm packages/**/src/**/*.ts --no-warning --no-tree --exit-code circular:1 --no-progress -T true --skip-dynamic-imports circular",
|
||||
|
|
@ -85,7 +85,7 @@
|
|||
"test:e2e": "pnpm --filter @lobechat/e2e-tests test",
|
||||
"test:e2e:smoke": "pnpm --filter @lobechat/e2e-tests test:smoke",
|
||||
"test:update": "vitest -u",
|
||||
"type-check": "tsgo --noEmit",
|
||||
"typecheck": "tsgo --noEmit",
|
||||
"webhook:ngrok": "ngrok http http://localhost:3011",
|
||||
"workflow:cdn": "tsx ./scripts/cdnWorkflow/index.ts",
|
||||
"workflow:changelog": "tsx ./scripts/changelogWorkflow/index.ts",
|
||||
|
|
@ -137,20 +137,20 @@
|
|||
"@azure-rest/ai-inference": "1.0.0-beta.5",
|
||||
"@azure/core-auth": "^1.10.1",
|
||||
"@cfworker/json-schema": "^4.1.1",
|
||||
"@clerk/localizations": "^3.28.5",
|
||||
"@clerk/nextjs": "^6.35.5",
|
||||
"@clerk/themes": "^2.4.40",
|
||||
"@clerk/localizations": "^3.30.1",
|
||||
"@clerk/nextjs": "^6.36.2",
|
||||
"@clerk/themes": "^2.4.43",
|
||||
"@codesandbox/sandpack-react": "^2.20.0",
|
||||
"@cyntler/react-doc-viewer": "^1.17.1",
|
||||
"@electric-sql/pglite": "0.2.17",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@fal-ai/client": "^1.7.2",
|
||||
"@formkit/auto-animate": "^0.9.0",
|
||||
"@google/genai": "^1.30.0",
|
||||
"@huggingface/inference": "^4.13.4",
|
||||
"@google/genai": "^1.33.0",
|
||||
"@huggingface/inference": "^4.13.5",
|
||||
"@icons-pack/react-simple-icons": "^13.8.0",
|
||||
"@khmyznikov/pwa-install": "0.3.9",
|
||||
"@langchain/community": "^0.3.57",
|
||||
"@langchain/community": "^0.3.58",
|
||||
"@lobechat/agent-runtime": "workspace:*",
|
||||
"@lobechat/const": "workspace:*",
|
||||
"@lobechat/context-engine": "workspace:*",
|
||||
|
|
@ -171,14 +171,14 @@
|
|||
"@lobehub/chat-plugin-sdk": "^1.32.4",
|
||||
"@lobehub/chat-plugins-gateway": "^1.9.0",
|
||||
"@lobehub/desktop-ipc-typings": "workspace:*",
|
||||
"@lobehub/editor": "^1.23.1",
|
||||
"@lobehub/icons": "^2.43.1",
|
||||
"@lobehub/market-sdk": "^0.23.2",
|
||||
"@lobehub/editor": "^1.31.2",
|
||||
"@lobehub/icons": "^2.45.0",
|
||||
"@lobehub/market-sdk": "^0.23.7",
|
||||
"@lobehub/tts": "^2.0.1",
|
||||
"@lobehub/ui": "^2.18.3",
|
||||
"@modelcontextprotocol/sdk": "^1.24.0",
|
||||
"@lobehub/ui": "^2.22.0",
|
||||
"@modelcontextprotocol/sdk": "^1.24.3",
|
||||
"@neondatabase/serverless": "^1.0.2",
|
||||
"@next/third-parties": "^16.0.5",
|
||||
"@next/third-parties": "^16.0.8",
|
||||
"@opentelemetry/exporter-jaeger": "^2.2.0",
|
||||
"@opentelemetry/winston-transport": "^0.19.0",
|
||||
"@react-pdf/renderer": "^4.3.1",
|
||||
|
|
@ -186,16 +186,16 @@
|
|||
"@saintno/comfyui-sdk": "^0.2.49",
|
||||
"@serwist/next": "^9.2.3",
|
||||
"@t3-oss/env-nextjs": "^0.13.8",
|
||||
"@tanstack/react-query": "^5.90.11",
|
||||
"@tanstack/react-query": "^5.90.12",
|
||||
"@trpc/client": "^11.7.2",
|
||||
"@trpc/next": "^11.7.2",
|
||||
"@trpc/react-query": "^11.7.2",
|
||||
"@trpc/server": "^11.7.2",
|
||||
"@upstash/redis": "^1.35.7",
|
||||
"@vercel/analytics": "^1.5.0",
|
||||
"@vercel/analytics": "^1.6.1",
|
||||
"@vercel/edge-config": "^1.4.3",
|
||||
"@vercel/functions": "^3.3.4",
|
||||
"@vercel/speed-insights": "^1.2.0",
|
||||
"@vercel/speed-insights": "^1.3.1",
|
||||
"@virtuoso.dev/masonry": "^1.3.5",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"@zumer/snapdom": "^1.9.14",
|
||||
|
|
@ -203,7 +203,7 @@
|
|||
"antd": "^5.29.1",
|
||||
"antd-style": "^3.7.1",
|
||||
"async-retry": "^1.3.3",
|
||||
"better-auth": "^1.4.3",
|
||||
"better-auth": "^1.4.6",
|
||||
"better-auth-harmony": "^1.2.5",
|
||||
"brotli-wasm": "^3.0.1",
|
||||
"chroma-js": "^3.2.0",
|
||||
|
|
@ -220,10 +220,10 @@
|
|||
"fast-deep-equal": "^3.1.3",
|
||||
"fflate": "^0.8.2",
|
||||
"file-type": "^21.1.1",
|
||||
"framer-motion": "^12.23.24",
|
||||
"framer-motion": "^12.23.26",
|
||||
"gray-matter": "^4.0.3",
|
||||
"html-to-text": "^9.0.5",
|
||||
"i18next": "^25.6.3",
|
||||
"i18next": "^25.7.2",
|
||||
"i18next-browser-languagedetector": "^8.2.0",
|
||||
"i18next-resources-to-backend": "^1.2.1",
|
||||
"immer": "^10.2.0",
|
||||
|
|
@ -231,7 +231,7 @@
|
|||
"jose": "^5.10.0",
|
||||
"js-sha256": "^0.11.1",
|
||||
"jsonl-parse-stringify": "^1.0.3",
|
||||
"klavis": "^2.13.2",
|
||||
"klavis": "^2.15.0",
|
||||
"langchain": "^0.3.36",
|
||||
"langfuse": "^3.38.6",
|
||||
"langfuse-core": "^3.38.6",
|
||||
|
|
@ -243,16 +243,16 @@
|
|||
"mdast-util-to-markdown": "^2.1.2",
|
||||
"model-bank": "workspace:*",
|
||||
"nanoid": "^5.1.6",
|
||||
"next": "^16.0.7",
|
||||
"next": "^16.0.8",
|
||||
"next-auth": "5.0.0-beta.30",
|
||||
"next-mdx-remote": "^5.0.0",
|
||||
"nextjs-toploader": "^3.9.17",
|
||||
"node-machine-id": "^1.1.12",
|
||||
"nodemailer": "^7.0.11",
|
||||
"numeral": "^2.0.6",
|
||||
"nuqs": "^2.8.1",
|
||||
"nuqs": "^2.8.5",
|
||||
"officeparser": "5.1.1",
|
||||
"oidc-provider": "^9.5.2",
|
||||
"oidc-provider": "^9.6.0",
|
||||
"ollama": "^0.6.3",
|
||||
"openai": "^4.104.0",
|
||||
"openapi-fetch": "^0.14.1",
|
||||
|
|
@ -283,23 +283,23 @@
|
|||
"react-pdf": "^9.2.1",
|
||||
"react-responsive": "^10.0.1",
|
||||
"react-rnd": "^10.5.2",
|
||||
"react-router-dom": "^7.9.6",
|
||||
"react-router-dom": "^7.10.1",
|
||||
"react-scan": "^0.4.3",
|
||||
"react-virtuoso": "^4.15.0",
|
||||
"react-virtuoso": "^4.17.0",
|
||||
"react-wrap-balancer": "^1.1.1",
|
||||
"remark": "^15.0.1",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"remark-html": "^16.0.1",
|
||||
"resend": "^6.5.2",
|
||||
"resend": "^6.6.0",
|
||||
"resolve-accept-language": "^3.1.15",
|
||||
"rtl-detect": "^1.1.2",
|
||||
"semver": "^7.7.3",
|
||||
"sharp": "^0.34.5",
|
||||
"shiki": "^3.17.0",
|
||||
"shiki": "^3.19.0",
|
||||
"ssrf-safe-fetch": "workspace:*",
|
||||
"stripe": "^17.7.0",
|
||||
"superjson": "^2.2.6",
|
||||
"svix": "^1.81.0",
|
||||
"svix": "^1.82.0",
|
||||
"swr": "^2.3.7",
|
||||
"systemjs": "^6.15.1",
|
||||
"tokenx": "^1.2.1",
|
||||
|
|
@ -309,7 +309,7 @@
|
|||
"url-join": "^5.0.0",
|
||||
"use-merge-value": "^1.2.0",
|
||||
"uuid": "^13.0.0",
|
||||
"virtua": "^0.47.0",
|
||||
"virtua": "^0.47.2",
|
||||
"word-extractor": "^1.0.4",
|
||||
"ws": "^8.18.3",
|
||||
"yaml": "^2.8.2",
|
||||
|
|
@ -320,14 +320,14 @@
|
|||
"devDependencies": {
|
||||
"@commitlint/cli": "^19.8.1",
|
||||
"@edge-runtime/vm": "^5.0.0",
|
||||
"@huggingface/tasks": "^0.19.63",
|
||||
"@huggingface/tasks": "^0.19.69",
|
||||
"@lobechat/types": "workspace:*",
|
||||
"@lobehub/i18n-cli": "^1.25.1",
|
||||
"@lobehub/lint": "^1.26.3",
|
||||
"@lobehub/market-types": "^1.11.4",
|
||||
"@lobehub/market-types": "^1.11.5",
|
||||
"@lobehub/seo-cli": "^1.7.0",
|
||||
"@next/bundle-analyzer": "^16.0.5",
|
||||
"@next/eslint-plugin-next": "^15.5.6",
|
||||
"@next/bundle-analyzer": "^16.0.8",
|
||||
"@next/eslint-plugin-next": "^15.5.7",
|
||||
"@peculiar/webcrypto": "^1.5.0",
|
||||
"@playwright/test": "^1.57.0",
|
||||
"@prettier/sync": "^0.6.1",
|
||||
|
|
@ -344,12 +344,12 @@
|
|||
"@types/json-schema": "^7.0.15",
|
||||
"@types/lodash": "^4.17.21",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/node": "^24.10.3",
|
||||
"@types/nodemailer": "^7.0.4",
|
||||
"@types/numeral": "^2.0.5",
|
||||
"@types/oidc-provider": "^9.5.0",
|
||||
"@types/pdfkit": "^0.17.4",
|
||||
"@types/pg": "^8.15.6",
|
||||
"@types/pg": "^8.16.0",
|
||||
"@types/react": "19.2.2",
|
||||
"@types/react-dom": "19.2.2",
|
||||
"@types/rtl-detect": "^1.0.3",
|
||||
|
|
@ -358,7 +358,7 @@
|
|||
"@types/ua-parser-js": "^0.7.39",
|
||||
"@types/unist": "^3.0.3",
|
||||
"@types/ws": "^8.18.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20251102.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20251210.1",
|
||||
"@vitest/coverage-v8": "^3.2.4",
|
||||
"ajv-keywords": "^5.1.0",
|
||||
"code-inspector-plugin": "1.3.0",
|
||||
|
|
@ -371,7 +371,7 @@
|
|||
"dotenv-expand": "^12.0.3",
|
||||
"dpdm-fast": "^1.0.14",
|
||||
"drizzle-dbml-generator": "^0.10.0",
|
||||
"drizzle-kit": "^0.31.6",
|
||||
"drizzle-kit": "^0.31.8",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-plugin-mdx": "^3.6.2",
|
||||
"fake-indexeddb": "^6.2.5",
|
||||
|
|
@ -390,7 +390,7 @@
|
|||
"node-gyp": "^11.5.0",
|
||||
"openapi-typescript": "^7.10.1",
|
||||
"p-map": "^7.0.4",
|
||||
"prettier": "^3.7.3",
|
||||
"prettier": "^3.7.4",
|
||||
"remark-cli": "^12.0.1",
|
||||
"remark-frontmatter": "^5.0.0",
|
||||
"remark-mdx": "^3.1.1",
|
||||
|
|
@ -399,12 +399,12 @@
|
|||
"semantic-release": "^21.1.2",
|
||||
"serwist": "^9.2.3",
|
||||
"stylelint": "^15.11.0",
|
||||
"tsx": "^4.20.6",
|
||||
"type-fest": "^5.2.0",
|
||||
"tsx": "^4.21.0",
|
||||
"type-fest": "^5.3.1",
|
||||
"typescript": "^5.9.3",
|
||||
"unified": "^11.0.5",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"vite": "^7.2.4",
|
||||
"vite": "^7.2.7",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"packageManager": "pnpm@10.20.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "last_active_at" timestamp with time zone DEFAULT now() NOT NULL;
|
||||
8481
packages/database/migrations/meta/0060_snapshot.json
Normal file
8481
packages/database/migrations/meta/0060_snapshot.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -420,7 +420,14 @@
|
|||
"when": 1764858574403,
|
||||
"tag": "0059_add_normalized_email_indexes",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 60,
|
||||
"version": "7",
|
||||
"when": 1765437218969,
|
||||
"tag": "0060_add_user_last_active_at",
|
||||
"breakpoints": true
|
||||
}
|
||||
],
|
||||
"version": "6"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -938,5 +938,13 @@
|
|||
"bps": true,
|
||||
"folderMillis": 1764858574403,
|
||||
"hash": "7838f9938b370867470e5e11807855253d23b11c2ac6aa9e90687844a356c949"
|
||||
},
|
||||
{
|
||||
"sql": [
|
||||
"ALTER TABLE \"users\" ADD COLUMN IF NOT EXISTS \"last_active_at\" timestamp with time zone DEFAULT now() NOT NULL;"
|
||||
],
|
||||
"bps": true,
|
||||
"folderMillis": 1765437218969,
|
||||
"hash": "004923916a27bc61294eeb20738f2884f1ca43978a03aa9f0216fc849c98465b"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ export const users = pgTable(
|
|||
|
||||
// better-auth phone number
|
||||
phoneNumberVerified: boolean('phone_number_verified'),
|
||||
lastActiveAt: timestamptz('last_active_at').notNull().defaultNow(),
|
||||
|
||||
...timestamps,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
"./ppio": "./src/aiModels/ppio.ts",
|
||||
"./qiniu": "./src/aiModels/qiniu.ts",
|
||||
"./qwen": "./src/aiModels/qwen.ts",
|
||||
"./replicate": "./src/aiModels/replicate.ts",
|
||||
"./sambanova": "./src/aiModels/sambanova.ts",
|
||||
"./search1api": "./src/aiModels/search1api.ts",
|
||||
"./sensenova": "./src/aiModels/sensenova.ts",
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@ bunx vitest run --silent='passed-only' 'src/providers/{provider}/index.test.ts'
|
|||
|
||||
```bash
|
||||
# Check TypeScript types (from project root)
|
||||
cd ../../../ && bun run type-check
|
||||
cd ../../../ && bun run typecheck
|
||||
|
||||
# Or run typecheck for model-runtime only
|
||||
bunx tsc --noEmit
|
||||
|
|
@ -475,7 +475,7 @@ Based on your development summary, update the following sections:
|
|||
bunx vitest run --silent='passed-only' 'src/providers/{provider}/index.test.ts'
|
||||
|
||||
# Verify type check still passes
|
||||
cd ../../../ && bun run type-check
|
||||
cd ../../../ && bun run typecheck
|
||||
```
|
||||
|
||||
#### Complete Workflow Example
|
||||
|
|
@ -486,7 +486,7 @@ cd ../../../ && bun run type-check
|
|||
bunx vitest run --silent='passed-only' 'src/providers/example/index.test.ts'
|
||||
|
||||
# 2. Type/Lint Phase (REQUIRED)
|
||||
cd ../../../ && bun run type-check # Must pass!
|
||||
cd ../../../ && bun run typecheck # Must pass!
|
||||
bunx eslint src/providers/example/ --fix
|
||||
|
||||
# 3. Coverage Phase
|
||||
|
|
@ -501,7 +501,7 @@ bunx vitest run --coverage --silent='passed-only'
|
|||
|
||||
# 6. Final Verification
|
||||
bunx vitest run --silent='passed-only' 'src/providers/example/index.test.ts'
|
||||
cd ../../../ && bun run type-check
|
||||
cd ../../../ && bun run typecheck
|
||||
|
||||
# 7. Commit
|
||||
git add .
|
||||
|
|
@ -539,7 +539,7 @@ bunx vitest watch 'src/providers/{provider}/index.test.ts'
|
|||
|
||||
```bash
|
||||
# Type check entire project (from project root)
|
||||
cd ../../../ && bun run type-check
|
||||
cd ../../../ && bun run typecheck
|
||||
|
||||
# Type check model-runtime only
|
||||
bunx tsc --noEmit
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ export const MODEL_OWNER_DETECTION_CONFIG = {
|
|||
moonshot: ['moonshot', 'kimi'],
|
||||
openai: ['o1', 'o3', 'o4', 'gpt-'],
|
||||
qwen: ['qwen', 'qwq', 'qvq'],
|
||||
replicate: [],
|
||||
v0: ['v0'],
|
||||
volcengine: ['doubao'],
|
||||
wenxin: ['ernie', 'qianfan'],
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ describe('userRouter', () => {
|
|||
() =>
|
||||
({
|
||||
getUserState: vi.fn().mockResolvedValue(mockState),
|
||||
updateUser: vi.fn().mockResolvedValue({ rowCount: 1 }),
|
||||
}) as any,
|
||||
);
|
||||
|
||||
|
|
@ -163,6 +164,7 @@ describe('userRouter', () => {
|
|||
preference: { telemetry: null },
|
||||
settings: {},
|
||||
}),
|
||||
updateUser: vi.fn().mockResolvedValue({ rowCount: 1 }),
|
||||
}) as any,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { serialize } from 'cookie';
|
|||
import debug from 'debug';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { ToolCallContent } from '@/libs/mcp';
|
||||
import { authedProcedure, publicProcedure, router } from '@/libs/trpc/lambda';
|
||||
import { serverDatabase } from '@/libs/trpc/lambda/middleware';
|
||||
import { DiscoverService } from '@/server/services/discover';
|
||||
|
|
@ -80,13 +81,15 @@ export const marketRouter = router({
|
|||
toolName: input.toolName,
|
||||
userAccessToken,
|
||||
});
|
||||
const cloudResultContent = (cloudResult?.content ?? []) as ToolCallContent[];
|
||||
|
||||
// Format the cloud result to MCPToolCallResult format
|
||||
// Process content blocks (upload images, etc.)
|
||||
const newContent =
|
||||
cloudResult?.isError || !ctx.fileService
|
||||
? cloudResult?.content
|
||||
: await processContentBlocks(cloudResult?.content, ctx.fileService);
|
||||
? cloudResultContent
|
||||
: // FIXME: the type assertion here is a temporary solution, need to remove it after refactoring
|
||||
await processContentBlocks(cloudResultContent, ctx.fileService);
|
||||
|
||||
// Convert content blocks to string
|
||||
const content = contentBlocksToString(newContent);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@ export const userRouter = router({
|
|||
}),
|
||||
|
||||
getUserState: userProcedure.query(async ({ ctx }): Promise<UserInitializationState> => {
|
||||
// don't block following process
|
||||
ctx.userModel.updateUser({ lastActiveAt: new Date() }).catch((err) => {
|
||||
console.error('update lastActiveAt failed, error:', err);
|
||||
});
|
||||
|
||||
let state: Awaited<ReturnType<UserModel['getUserState']>> | undefined;
|
||||
|
||||
// get or create first-time user
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ class MCPService {
|
|||
// Call cloud gateway via lambda market endpoint
|
||||
// Server will automatically get user access token from database
|
||||
// and format the result to MCPToolCallResult
|
||||
// @ts-ignore tsgo 误报错误
|
||||
result = await lambdaClient.market.callCloudMcpEndpoint.mutate({
|
||||
apiParams,
|
||||
identifier,
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ Key principles:
|
|||
**Subagent workflow**:
|
||||
|
||||
1. **One subagent per action file** - Each subagent focuses on testing ONE action file completely
|
||||
2. **Independent verification** - Each subagent runs its own type-check, lint, and test verification
|
||||
2. **Independent verification** - Each subagent runs its own typecheck, lint, and test verification
|
||||
3. **No commits from subagents** - Only the parent agent creates the final commit after all subagents complete
|
||||
4. **Parallel execution** - Launch all subagents in a single message using multiple Task tool calls
|
||||
5. **Consolidate results** - Parent agent reviews all results, runs final verification, updates docs, and commits
|
||||
|
|
@ -129,12 +129,12 @@ For files with multiple action files to test, use the Task tool to create subage
|
|||
2. **Launch one subagent per action file** using the Task tool
|
||||
3. **Each subagent independently**:
|
||||
- Writes tests for ONE action file only
|
||||
- Runs type-check and lint
|
||||
- Runs typecheck and lint
|
||||
- Verifies tests pass
|
||||
- Reports results back
|
||||
- **DOES NOT commit** (parent agent handles commits)
|
||||
4. **After all subagents complete**, review all results
|
||||
5. **Run final verification** (type-check, lint, tests)
|
||||
5. **Run final verification** (typecheck, lint, tests)
|
||||
6. **Update test-coverage.md** with combined results
|
||||
7. **Create single commit** with all new tests
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ Write comprehensive tests for src/store/discover/slices/plugin/action.ts followi
|
|||
Requirements:
|
||||
1. Write tests covering all actions in the file
|
||||
2. Follow SWR hooks testing pattern (if applicable)
|
||||
3. Run type-check and lint to verify
|
||||
3. Run typecheck and lint to verify
|
||||
4. Run tests to ensure they pass
|
||||
5. Report back with:
|
||||
- Number of tests written
|
||||
|
|
@ -163,7 +163,7 @@ DO NOT:
|
|||
|
||||
- ✅ Parallel execution - multiple action files tested simultaneously
|
||||
- ✅ Focused scope - each subagent handles one file completely
|
||||
- ✅ Independent verification - each file gets type-check/lint/test verification
|
||||
- ✅ Independent verification - each file gets typecheck/lint/test verification
|
||||
- ✅ Clean commits - single commit after all work is done
|
||||
- ✅ Better organization - clear separation of concerns
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ bunx vitest run --silent='passed-only' 'src/store/[domain]/slices/[slice]/action
|
|||
|
||||
```bash
|
||||
# Check TypeScript types (from project root)
|
||||
bun run type-check
|
||||
bun run typecheck
|
||||
|
||||
# Fix any linting issues
|
||||
bunx eslint src/store/[domain]/ --fix
|
||||
|
|
@ -270,7 +270,7 @@ Based on your development summary, update the following sections:
|
|||
bunx vitest run 'src/store'
|
||||
|
||||
# Verify type check still passes
|
||||
bun run type-check
|
||||
bun run typecheck
|
||||
```
|
||||
|
||||
### Complete Workflow Example (Single File)
|
||||
|
|
@ -281,7 +281,7 @@ bun run type-check
|
|||
bunx vitest run --silent='passed-only' 'src/store/tool/slices/mcpStore/action.test.ts'
|
||||
|
||||
# 2. Type/Lint Phase (REQUIRED)
|
||||
bun run type-check # Must pass!
|
||||
bun run typecheck # Must pass!
|
||||
bunx eslint src/store/tool/ --fix
|
||||
|
||||
# 3. Coverage Phase
|
||||
|
|
@ -295,7 +295,7 @@ bunx vitest run --coverage 'src/store'
|
|||
|
||||
# 6. Final Verification
|
||||
bunx vitest run 'src/store'
|
||||
bun run type-check
|
||||
bun run typecheck
|
||||
|
||||
# 7. Commit
|
||||
git add .
|
||||
|
|
@ -320,7 +320,7 @@ Task({
|
|||
Requirements:
|
||||
1. Write tests covering all actions (usePluginCategories, usePluginDetail, usePluginList, usePluginIdentifiers)
|
||||
2. Follow SWR hooks testing pattern
|
||||
3. Run type-check and lint to verify
|
||||
3. Run typecheck and lint to verify
|
||||
4. Run tests to ensure they pass
|
||||
5. Report back with number of tests written and coverage areas
|
||||
|
||||
|
|
@ -335,7 +335,7 @@ Task({
|
|||
Requirements:
|
||||
1. Write tests covering all actions (useFetchMcpDetail, useFetchMcpList, useMcpCategories)
|
||||
2. Follow SWR hooks testing pattern
|
||||
3. Run type-check and lint to verify
|
||||
3. Run typecheck and lint to verify
|
||||
4. Run tests to ensure they pass
|
||||
5. Report back with number of tests written and coverage areas
|
||||
|
||||
|
|
@ -350,7 +350,7 @@ DO NOT commit changes or update test-coverage.md.`,
|
|||
Each subagent will:
|
||||
|
||||
- Write tests
|
||||
- Run type-check and lint
|
||||
- Run typecheck and lint
|
||||
- Verify tests pass
|
||||
- Report results
|
||||
|
||||
|
|
@ -365,8 +365,8 @@ After all subagents complete:
|
|||
**Step 4: Final Verification**
|
||||
|
||||
```bash
|
||||
# Run type-check on entire project
|
||||
bun run type-check
|
||||
# Run typecheck on entire project
|
||||
bun run typecheck
|
||||
|
||||
# Run lint on all new test files
|
||||
bunx eslint src/store/discover/ --fix
|
||||
|
|
@ -396,7 +396,7 @@ git commit -m "✅ test(store): add comprehensive tests for discover store
|
|||
|
||||
- Add tests for plugin, mcp, assistant, model, provider slices
|
||||
- Coverage: X% → Y% (+Z tests, 5 new test files)
|
||||
- All tests pass type-check and lint
|
||||
- All tests pass typecheck and lint
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
|
|
@ -444,7 +444,7 @@ bunx vitest watch 'src/store/[domain]/slices/[slice]/action.test.ts'
|
|||
|
||||
```bash
|
||||
# Type check entire project (from project root)
|
||||
bun run type-check
|
||||
bun run typecheck
|
||||
|
||||
# Watch mode
|
||||
bunx tsc --noEmit --watch
|
||||
|
|
@ -494,7 +494,7 @@ bunx eslint src/store/[domain]/
|
|||
- Semantic search and RAG integration testing
|
||||
- File upload with progress callbacks
|
||||
- **Development Method**: Used parallel subagents (9 subagents running simultaneously)
|
||||
- **Type Safety**: All tests pass type-check ✅
|
||||
- **Type Safety**: All tests pass typecheck ✅
|
||||
- **Lint**: All tests pass lint ✅
|
||||
- **Action Files Coverage**: 31/40 → 40/40 tested (100%, +9 files)
|
||||
- **🎉 MILESTONE**: All 40 action files now have comprehensive test coverage!
|
||||
|
|
@ -523,7 +523,7 @@ bunx eslint src/store/[domain]/
|
|||
- AbortController management testing
|
||||
- Mock return types matching actual services
|
||||
- **Development Method**: Used parallel subagents (2 subagents, one per file)
|
||||
- **Type Safety**: All tests pass type-check ✅
|
||||
- **Type Safety**: All tests pass typecheck ✅
|
||||
- **Lint**: All tests pass lint ✅
|
||||
- **Action Files Coverage**: 31/40 tested (77.5%, +2 files)
|
||||
- **Milestone**: 🏆 All high priority files (>200 LOC) now have comprehensive tests!
|
||||
|
|
@ -544,7 +544,7 @@ bunx eslint src/store/[domain]/
|
|||
- Successfully adapted zustand testing patterns for SWR hooks
|
||||
- Mock strategy: Synchronously return data from mock useSWR
|
||||
- Type safety: Used `as any` for test mock data where needed
|
||||
- **Type Safety**: All tests pass type-check
|
||||
- **Type Safety**: All tests pass typecheck
|
||||
- **Action Files Coverage**: 29/40 tested (72.5%, +2 files)
|
||||
|
||||
**Session (2024-10-14)**: 📋 Store Testing Documentation Created
|
||||
|
|
|
|||
Loading…
Reference in a new issue