kaddidlehopper 0.5.0 → 0.6.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/dist/cli.js +104 -208
- package/dist/index.js +1 -31
- package/dist/types/cli.d.ts +1 -8
- package/dist/types/types.d.ts +7 -12
- package/package.json +1 -2
- package/src/cli.ts +129 -271
- package/src/index.ts +1 -47
- package/src/types.ts +7 -13
- package/CONTEXT.md +0 -139
- package/add-ons/ai/README.md +0 -34
- package/add-ons/ai/assets/AGENTS.md.append +0 -24
- package/add-ons/ai/assets/_dot_env.local.append +0 -13
- package/add-ons/ai/assets/src/components/AIAssistant.tsx +0 -149
- package/add-ons/ai/assets/src/lib/ai-hook.ts +0 -21
- package/add-ons/ai/assets/src/lib/weather-tools.ts +0 -30
- package/add-ons/ai/assets/src/routes/api.chat.ts +0 -94
- package/add-ons/ai/assets/src/routes/chat.css +0 -175
- package/add-ons/ai/assets/src/routes/chat.tsx +0 -141
- package/add-ons/ai/info.json +0 -22
- package/add-ons/ai/package.json +0 -17
- package/add-ons/ai/small-logo.svg +0 -8
- package/add-ons/db/assets/AGENTS.md.append +0 -22
- package/add-ons/db/assets/DB-SETUP.md +0 -65
- package/add-ons/db/assets/_dot_env.local.append +0 -2
- package/add-ons/db/assets/drizzle.config.ts +0 -10
- package/add-ons/db/assets/src/db/index.ts +0 -8
- package/add-ons/db/assets/src/db/schema.ts +0 -8
- package/add-ons/db/assets/src/routes/db-example.tsx +0 -118
- package/add-ons/db/assets/src/server/guestbook.functions.ts +0 -23
- package/add-ons/db/info.json +0 -22
- package/add-ons/db/package.json +0 -10
- package/add-ons/forms/assets/AGENTS.md.append +0 -13
- package/add-ons/forms/assets/public/form-example.html +0 -14
- package/add-ons/forms/assets/src/routes/form-example.tsx +0 -76
- package/add-ons/forms/info.json +0 -18
- package/add-ons/forms/package.json +0 -3
- package/examples/ai-chat/README.md +0 -36
- package/examples/ai-chat/assets/AGENTS.md.append +0 -24
- package/examples/ai-chat/assets/src/lib/ai-hook.ts +0 -21
- package/examples/ai-chat/assets/src/lib/weather-tools.ts +0 -30
- package/examples/ai-chat/assets/src/routes/__root.tsx +0 -57
- package/examples/ai-chat/assets/src/routes/api.chat.ts +0 -94
- package/examples/ai-chat/assets/src/routes/index.tsx +0 -141
- package/examples/ai-chat/assets/src/styles.css +0 -165
- package/examples/ai-chat/info.json +0 -25
- package/examples/ai-chat/package.json +0 -14
- package/examples/blog/README.md +0 -60
- package/examples/blog/assets/AGENTS.md.append +0 -18
- package/examples/blog/assets/content/posts/beach.md +0 -12
- package/examples/blog/assets/content/posts/jungle.md.ejs +0 -12
- package/examples/blog/assets/content/posts/mountains.md.ejs +0 -12
- package/examples/blog/assets/content/posts/snorkeling.md.ejs +0 -12
- package/examples/blog/assets/content/posts/waterfall.md.ejs +0 -12
- package/examples/blog/assets/content-collections.ts +0 -30
- package/examples/blog/assets/public/beach.jpg +0 -0
- package/examples/blog/assets/public/jungle.jpg +0 -0
- package/examples/blog/assets/public/mountains.jpg +0 -0
- package/examples/blog/assets/public/snorkeling.jpg +0 -0
- package/examples/blog/assets/public/waterfall.jpg +0 -0
- package/examples/blog/assets/src/components/Header.tsx +0 -52
- package/examples/blog/assets/src/components/VacayAssistant.tsx +0 -205
- package/examples/blog/assets/src/components/blog-posts.tsx +0 -78
- package/examples/blog/assets/src/components/ui/card.tsx +0 -92
- package/examples/blog/assets/src/lib/blog-ai-hook.ts +0 -25
- package/examples/blog/assets/src/lib/blog-tools.ts +0 -111
- package/examples/blog/assets/src/lib/utils.ts +0 -6
- package/examples/blog/assets/src/routes/__root.tsx +0 -57
- package/examples/blog/assets/src/routes/api.blog-chat.ts +0 -117
- package/examples/blog/assets/src/routes/category.$category.tsx +0 -19
- package/examples/blog/assets/src/routes/index.tsx +0 -19
- package/examples/blog/assets/src/routes/posts.$slug.tsx +0 -63
- package/examples/blog/assets/src/styles.css +0 -138
- package/examples/blog/info.json +0 -40
- package/examples/blog/package.json +0 -23
- package/examples/calculator/README.md +0 -16
- package/examples/calculator/assets/AGENTS.md.append +0 -9
- package/examples/calculator/assets/src/components/Calculator.tsx +0 -238
- package/examples/calculator/assets/src/components/Header.tsx +0 -17
- package/examples/calculator/assets/src/routes/__root.tsx +0 -57
- package/examples/calculator/assets/src/routes/index.tsx +0 -14
- package/examples/calculator/info.json +0 -20
- package/examples/calculator/package.json +0 -1
- package/examples/dashboard/README.md +0 -17
- package/examples/dashboard/assets/AGENTS.md.append +0 -12
- package/examples/dashboard/assets/src/components/Header.tsx +0 -17
- package/examples/dashboard/assets/src/routes/__root.tsx +0 -57
- package/examples/dashboard/assets/src/routes/index.tsx +0 -158
- package/examples/dashboard/info.json +0 -19
- package/examples/dashboard/package.json +0 -6
- package/examples/ecommerce/README.md +0 -48
- package/examples/ecommerce/assets/AGENTS.md.append +0 -22
- package/examples/ecommerce/assets/public/logo.png +0 -0
- package/examples/ecommerce/assets/public/motorcycle-scooter.jpg +0 -0
- package/examples/ecommerce/assets/src/components/BuyButton.tsx +0 -35
- package/examples/ecommerce/assets/src/components/Header.tsx +0 -36
- package/examples/ecommerce/assets/src/components/MotorcycleAIAssistant.tsx +0 -162
- package/examples/ecommerce/assets/src/components/MotorcycleRecommendation.tsx +0 -53
- package/examples/ecommerce/assets/src/data/motorcycles.ts +0 -27
- package/examples/ecommerce/assets/src/lib/motorcycle-ai-hook.ts +0 -24
- package/examples/ecommerce/assets/src/lib/motorcycle-tools.ts +0 -42
- package/examples/ecommerce/assets/src/lib/stripe.server.ts +0 -39
- package/examples/ecommerce/assets/src/routes/__root.tsx +0 -57
- package/examples/ecommerce/assets/src/routes/api.motorcycle-chat.ts +0 -78
- package/examples/ecommerce/assets/src/routes/checkout/cancel.tsx +0 -25
- package/examples/ecommerce/assets/src/routes/checkout/success.tsx +0 -25
- package/examples/ecommerce/assets/src/routes/index.tsx +0 -76
- package/examples/ecommerce/assets/src/routes/motorcycles/$motorcycleId.tsx +0 -55
- package/examples/ecommerce/assets/src/store/motorcycle-assistant.ts +0 -3
- package/examples/ecommerce/assets/src/styles.css +0 -212
- package/examples/ecommerce/info.json +0 -38
- package/examples/ecommerce/package.json +0 -13
- package/examples/events/README.md +0 -110
- package/examples/events/assets/AGENTS.md.append +0 -21
- package/examples/events/assets/content/speakers/andre-costa.md +0 -22
- package/examples/events/assets/content/speakers/hans-mueller.md.ejs +0 -22
- package/examples/events/assets/content/speakers/isabella-martinez.md.ejs +0 -22
- package/examples/events/assets/content/speakers/kenji-nakamura.md.ejs +0 -22
- package/examples/events/assets/content/speakers/marie-dubois.md.ejs +0 -20
- package/examples/events/assets/content/speakers/priya-sharma.md.ejs +0 -22
- package/examples/events/assets/content/talks/croissant-lamination-secrets.md +0 -39
- package/examples/events/assets/content/talks/french-macaron-mastery.md.ejs +0 -39
- package/examples/events/assets/content/talks/neapolitan-pizza-tradition-meets-innovation.md.ejs +0 -39
- package/examples/events/assets/content/talks/savory-breads-of-the-mediterranean.md.ejs +0 -39
- package/examples/events/assets/content/talks/sourdough-from-starter-to-masterpiece.md.ejs +0 -36
- package/examples/events/assets/content/talks/the-art-of-the-perfect-tart.md.ejs +0 -32
- package/examples/events/assets/content/talks/the-science-of-sugar.md.ejs +0 -39
- package/examples/events/assets/content/talks/umami-in-pastry-east-meets-west.md.ejs +0 -39
- package/examples/events/assets/content-collections.ts +0 -56
- package/examples/events/assets/public/background-1.jpg +0 -0
- package/examples/events/assets/public/background-2.jpg +0 -0
- package/examples/events/assets/public/background-3.jpg +0 -0
- package/examples/events/assets/public/background-4.jpg +0 -0
- package/examples/events/assets/public/conference-logo.png +0 -0
- package/examples/events/assets/public/favicon.ico +0 -0
- package/examples/events/assets/public/speakers/andre-costa.jpg +0 -0
- package/examples/events/assets/public/speakers/hans-mueller.jpg +0 -0
- package/examples/events/assets/public/speakers/isabella-martinez.jpg +0 -0
- package/examples/events/assets/public/speakers/kenji-nakamura.jpg +0 -0
- package/examples/events/assets/public/speakers/marie-dubois.jpg +0 -0
- package/examples/events/assets/public/speakers/priya-sharma.jpg +0 -0
- package/examples/events/assets/public/talks/croissant-lamination-secrets.jpg +0 -0
- package/examples/events/assets/public/talks/french-macaron-mastery.jpg +0 -0
- package/examples/events/assets/public/talks/neapolitan-pizza-tradition-meets-innovation.jpg +0 -0
- package/examples/events/assets/public/talks/savory-breads-of-the-mediterranean.jpg +0 -0
- package/examples/events/assets/public/talks/sourdough-from-starter-to-masterpiece.jpg +0 -0
- package/examples/events/assets/public/talks/the-art-of-the-perfect-tart.jpg +0 -0
- package/examples/events/assets/public/talks/the-science-of-sugar.jpg +0 -0
- package/examples/events/assets/public/talks/umami-in-pastry-east-meets-west.jpg +0 -0
- package/examples/events/assets/public/tanstack-circle-logo.png +0 -0
- package/examples/events/assets/public/tanstack-word-logo-white.svg +0 -1
- package/examples/events/assets/src/components/Header.tsx +0 -59
- package/examples/events/assets/src/components/HeaderNav.tsx +0 -67
- package/examples/events/assets/src/components/HeroCarousel.tsx +0 -61
- package/examples/events/assets/src/components/RemyAssistant.tsx +0 -207
- package/examples/events/assets/src/components/SpeakerCard.tsx +0 -67
- package/examples/events/assets/src/components/TalkCard.tsx +0 -77
- package/examples/events/assets/src/components/ui/card.tsx +0 -92
- package/examples/events/assets/src/lib/conference-ai-hook.ts +0 -26
- package/examples/events/assets/src/lib/conference-tools.ts +0 -210
- package/examples/events/assets/src/lib/model-selection.ts +0 -1
- package/examples/events/assets/src/lib/utils.ts +0 -6
- package/examples/events/assets/src/routes/__root.tsx +0 -70
- package/examples/events/assets/src/routes/api.remy-chat.ts +0 -119
- package/examples/events/assets/src/routes/index.tsx +0 -192
- package/examples/events/assets/src/routes/schedule.index.tsx +0 -274
- package/examples/events/assets/src/routes/speakers.$slug.tsx +0 -122
- package/examples/events/assets/src/routes/speakers.index.tsx +0 -40
- package/examples/events/assets/src/routes/talks.$slug.tsx +0 -116
- package/examples/events/assets/src/routes/talks.index.tsx +0 -40
- package/examples/events/assets/src/styles.css +0 -182
- package/examples/events/info.json +0 -61
- package/examples/events/package.json +0 -23
- package/examples/marketing/README.md +0 -60
- package/examples/marketing/assets/AGENTS.md.append +0 -15
- package/examples/marketing/assets/public/logo.png +0 -0
- package/examples/marketing/assets/public/motorcycle-adventure.jpg +0 -0
- package/examples/marketing/assets/public/motorcycle-cruiser.jpg +0 -0
- package/examples/marketing/assets/public/motorcycle-scooter.jpg +0 -0
- package/examples/marketing/assets/public/motorcycle-sport.jpg +0 -0
- package/examples/marketing/assets/public/motorcycle-supersport.jpg +0 -0
- package/examples/marketing/assets/src/components/Header.tsx +0 -36
- package/examples/marketing/assets/src/components/MotorcycleAIAssistant.tsx +0 -162
- package/examples/marketing/assets/src/components/MotorcycleRecommendation.tsx +0 -53
- package/examples/marketing/assets/src/data/motorcycles.ts.ejs +0 -77
- package/examples/marketing/assets/src/lib/motorcycle-ai-hook.ts +0 -24
- package/examples/marketing/assets/src/lib/motorcycle-tools.ts +0 -42
- package/examples/marketing/assets/src/routes/__root.tsx +0 -57
- package/examples/marketing/assets/src/routes/api.motorcycle-chat.ts +0 -78
- package/examples/marketing/assets/src/routes/index.tsx +0 -72
- package/examples/marketing/assets/src/routes/motorcycles/$motorcycleId.tsx +0 -56
- package/examples/marketing/assets/src/store/motorcycle-assistant.ts +0 -3
- package/examples/marketing/assets/src/styles.css +0 -212
- package/examples/marketing/info.json +0 -33
- package/examples/marketing/package.json +0 -14
- package/examples/portfolio/README.md +0 -49
- package/examples/portfolio/assets/AGENTS.md.append +0 -21
- package/examples/portfolio/assets/content/blog/getting-started-with-tanstack.md +0 -53
- package/examples/portfolio/assets/content/blog/react-19-features.md +0 -78
- package/examples/portfolio/assets/content/blog/tailwind-css-v4-guide.md +0 -60
- package/examples/portfolio/assets/content/education/code-school.md +0 -17
- package/examples/portfolio/assets/content/jobs/initech-junior.md +0 -20
- package/examples/portfolio/assets/content/projects/portfolio-site.md +0 -15
- package/examples/portfolio/assets/content/projects/task-manager.md +0 -15
- package/examples/portfolio/assets/content-collections.ts +0 -65
- package/examples/portfolio/assets/public/contact.html +0 -6
- package/examples/portfolio/assets/public/headshot-on-white.jpg +0 -0
- package/examples/portfolio/assets/src/components/Header.tsx +0 -33
- package/examples/portfolio/assets/src/components/ResumeAssistant.tsx +0 -193
- package/examples/portfolio/assets/src/components/ui/badge.tsx +0 -46
- package/examples/portfolio/assets/src/components/ui/card.tsx +0 -92
- package/examples/portfolio/assets/src/components/ui/checkbox.tsx +0 -30
- package/examples/portfolio/assets/src/components/ui/hover-card.tsx +0 -44
- package/examples/portfolio/assets/src/components/ui/separator.tsx +0 -26
- package/examples/portfolio/assets/src/lib/resume-ai-hook.ts +0 -21
- package/examples/portfolio/assets/src/lib/resume-tools.ts +0 -165
- package/examples/portfolio/assets/src/lib/utils.ts +0 -6
- package/examples/portfolio/assets/src/routes/__root.tsx +0 -57
- package/examples/portfolio/assets/src/routes/api.resume-chat.ts +0 -116
- package/examples/portfolio/assets/src/routes/blog/$slug.tsx +0 -73
- package/examples/portfolio/assets/src/routes/contact.tsx +0 -121
- package/examples/portfolio/assets/src/routes/index.tsx +0 -55
- package/examples/portfolio/assets/src/routes/projects.tsx +0 -62
- package/examples/portfolio/assets/src/routes/resume.tsx +0 -220
- package/examples/portfolio/assets/src/styles.css +0 -138
- package/examples/portfolio/info.json +0 -50
- package/examples/portfolio/package.json +0 -26
- package/examples/resume/README.md +0 -82
- package/examples/resume/assets/AGENTS.md.append +0 -19
- package/examples/resume/assets/content/education/code-school.md +0 -17
- package/examples/resume/assets/content/jobs/freelance.md.ejs +0 -13
- package/examples/resume/assets/content/jobs/initech-junior.md +0 -20
- package/examples/resume/assets/content/jobs/initech-lead.md.ejs +0 -29
- package/examples/resume/assets/content/jobs/initrode-senior.md.ejs +0 -28
- package/examples/resume/assets/content-collections.ts +0 -36
- package/examples/resume/assets/public/headshot-on-white.jpg +0 -0
- package/examples/resume/assets/src/components/Header.tsx +0 -33
- package/examples/resume/assets/src/components/ResumeAssistant.tsx +0 -193
- package/examples/resume/assets/src/components/ui/badge.tsx +0 -46
- package/examples/resume/assets/src/components/ui/card.tsx +0 -92
- package/examples/resume/assets/src/components/ui/checkbox.tsx +0 -30
- package/examples/resume/assets/src/components/ui/hover-card.tsx +0 -44
- package/examples/resume/assets/src/components/ui/separator.tsx +0 -26
- package/examples/resume/assets/src/lib/resume-ai-hook.ts +0 -21
- package/examples/resume/assets/src/lib/resume-tools.ts +0 -165
- package/examples/resume/assets/src/lib/utils.ts +0 -6
- package/examples/resume/assets/src/routes/api.resume-chat.ts +0 -110
- package/examples/resume/assets/src/routes/index.tsx +0 -220
- package/examples/resume/assets/src/styles.css +0 -138
- package/examples/resume/info.json +0 -35
- package/examples/resume/package.json +0 -26
- package/examples/saas/README.md +0 -16
- package/examples/saas/assets/AGENTS.md.append +0 -9
- package/examples/saas/assets/src/components/Header.tsx +0 -17
- package/examples/saas/assets/src/routes/__root.tsx +0 -57
- package/examples/saas/assets/src/routes/faq.tsx +0 -94
- package/examples/saas/assets/src/routes/index.tsx +0 -197
- package/examples/saas/info.json +0 -23
- package/examples/saas/package.json +0 -1
- package/examples/survey/README.md +0 -20
- package/examples/survey/assets/AGENTS.md.append +0 -9
- package/examples/survey/assets/public/form-survey.html +0 -15
- package/examples/survey/assets/src/components/SurveyForm.tsx +0 -128
- package/examples/survey/assets/src/routes/index.tsx +0 -14
- package/examples/survey/info.json +0 -19
- package/examples/survey/package.json +0 -1
- package/project/base/AGENTS.md +0 -86
- package/project/base/_dot_claude/skills/content-collections/SKILL.md +0 -505
- package/project/base/_dot_claude/skills/netlify-blobs/SKILL.md +0 -410
- package/project/base/_dot_claude/skills/netlify-db/SKILL.md +0 -424
- package/project/base/_dot_claude/skills/netlify-debugging/SKILL.md +0 -419
- package/project/base/_dot_claude/skills/netlify-forms/SKILL.md +0 -243
- package/project/base/_dot_claude/skills/netlify-functions/SKILL.md +0 -372
- package/project/base/_dot_claude/skills/tanstack-start-api-routes/SKILL.md +0 -421
- package/project/base/_dot_claude/skills/tanstack-start-loaders/SKILL.md +0 -426
- package/project/base/_dot_claude/skills/tanstack-start-project-setup/SKILL.md +0 -493
- package/project/base/_dot_claude/skills/tanstack-start-routes/SKILL.md +0 -430
- package/project/base/_dot_claude/skills/tanstack-start-server-functions/SKILL.md +0 -445
- package/project/base/_dot_claude/skills/tanstack-start-typesafe-routing/SKILL.md +0 -494
- package/project/base/_dot_gitignore +0 -8
- package/project/base/netlify.toml +0 -7
- package/project/base/package.json +0 -33
- package/project/base/public/favicon.ico +0 -0
- package/project/base/public/tanstack-circle-logo.png +0 -0
- package/project/base/public/tanstack-word-logo-white.svg +0 -1
- package/project/base/src/components/Header.tsx +0 -17
- package/project/base/src/components/HeaderNav.tsx.ejs +0 -179
- package/project/base/src/router.tsx +0 -15
- package/project/base/src/routes/__root.tsx +0 -57
- package/project/base/src/routes/index.tsx +0 -48
- package/project/base/src/styles.css +0 -15
- package/project/base/tsconfig.json +0 -28
- package/project/base/vite.config.ts.ejs +0 -25
- package/project/info.json +0 -17
- package/project/packages.json +0 -22
- package/scripts/check-outdated-packages.js +0 -421
- package/src/agents-md.ts +0 -139
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { createFileRoute } from '@tanstack/react-router'
|
|
2
|
-
import { chat, maxIterations, toServerSentEventsResponse } from '@tanstack/ai'
|
|
3
|
-
import { anthropicText } from '@tanstack/ai-anthropic'
|
|
4
|
-
import { openaiText } from '@tanstack/ai-openai'
|
|
5
|
-
import { geminiText } from '@tanstack/ai-gemini'
|
|
6
|
-
import { ollamaText } from '@tanstack/ai-ollama'
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
getPostBySlug,
|
|
10
|
-
getAllBlogPosts,
|
|
11
|
-
searchBlogPosts,
|
|
12
|
-
} from '@/lib/blog-tools'
|
|
13
|
-
import type { Provider } from '@/lib/model-selection'
|
|
14
|
-
|
|
15
|
-
export const Route = createFileRoute('/api/blog-chat')({
|
|
16
|
-
server: {
|
|
17
|
-
handlers: {
|
|
18
|
-
POST: async ({ request }) => {
|
|
19
|
-
const requestSignal = request.signal
|
|
20
|
-
|
|
21
|
-
if (requestSignal.aborted) {
|
|
22
|
-
return new Response(null, { status: 499 })
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const abortController = new AbortController()
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
const body = await request.json()
|
|
29
|
-
const { messages, slug } = body
|
|
30
|
-
const data = body.data || {}
|
|
31
|
-
|
|
32
|
-
const SYSTEM_PROMPT = slug
|
|
33
|
-
? `You are a helpful blog assistant. You help readers understand and engage with blog articles.
|
|
34
|
-
|
|
35
|
-
CAPABILITIES:
|
|
36
|
-
1. Use getPostBySlug to read the content of the article the user is currently viewing
|
|
37
|
-
2. Use getAllBlogPosts to see all available articles on the blog
|
|
38
|
-
3. Use searchBlogPosts to find articles that match the user's query
|
|
39
|
-
|
|
40
|
-
INSTRUCTIONS:
|
|
41
|
-
- When a user asks about "this article", "this post", or "what I'm reading", use getPostBySlug first
|
|
42
|
-
- Be conversational and helpful
|
|
43
|
-
- Summarize content when asked, highlight key points, and answer questions about the article
|
|
44
|
-
- If asked for recommendations, use getRelatedPosts to suggest similar content
|
|
45
|
-
- Keep responses concise but informative
|
|
46
|
-
- You can help explain concepts, provide additional context, or discuss themes from the articles
|
|
47
|
-
|
|
48
|
-
CONTEXT: The current article slug is "${slug}".`
|
|
49
|
-
: `You are a helpful blog assistant. You help readers understand and engage with blog articles.
|
|
50
|
-
|
|
51
|
-
CAPABILITIES:
|
|
52
|
-
1. Use getAllBlogPosts to see all available articles on the blog
|
|
53
|
-
2. UsUse searchBlogPosts to find articles that match the user's query
|
|
54
|
-
|
|
55
|
-
INSTRUCTIONS:
|
|
56
|
-
- When a user asks for a recommendation, use searchBlogPosts to suggest similar content
|
|
57
|
-
- Keep responses concise but informative
|
|
58
|
-
- You can help explain concepts, provide additional context, or discuss themes from the articles`
|
|
59
|
-
|
|
60
|
-
// Determine the best available provider
|
|
61
|
-
let provider: Provider = data.provider || 'ollama'
|
|
62
|
-
let model: string = data.model || 'mistral:7b'
|
|
63
|
-
|
|
64
|
-
// Use the first available provider with an API key, fallback to ollama
|
|
65
|
-
if (process.env.ANTHROPIC_API_KEY) {
|
|
66
|
-
provider = 'anthropic'
|
|
67
|
-
model = 'claude-haiku-4-5'
|
|
68
|
-
} else if (process.env.OPENAI_API_KEY) {
|
|
69
|
-
provider = 'openai'
|
|
70
|
-
model = 'gpt-4o'
|
|
71
|
-
} else if (process.env.GEMINI_API_KEY) {
|
|
72
|
-
provider = 'gemini'
|
|
73
|
-
model = 'gemini-2.0-flash-exp'
|
|
74
|
-
}
|
|
75
|
-
// else keep ollama as default
|
|
76
|
-
|
|
77
|
-
// Adapter factory pattern for multi-vendor support
|
|
78
|
-
const adapterConfig = {
|
|
79
|
-
anthropic: () =>
|
|
80
|
-
anthropicText((model || 'claude-haiku-4-5') as any),
|
|
81
|
-
openai: () => openaiText((model || 'gpt-4o') as any),
|
|
82
|
-
gemini: () => geminiText((model || 'gemini-2.0-flash-exp') as any),
|
|
83
|
-
ollama: () => ollamaText((model || 'mistral:7b') as any),
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const adapter = adapterConfig[provider]()
|
|
87
|
-
|
|
88
|
-
const stream = chat({
|
|
89
|
-
adapter,
|
|
90
|
-
tools: [getPostBySlug, getAllBlogPosts, searchBlogPosts],
|
|
91
|
-
systemPrompts: [SYSTEM_PROMPT],
|
|
92
|
-
agentLoopStrategy: maxIterations(5),
|
|
93
|
-
messages,
|
|
94
|
-
abortController,
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
return toServerSentEventsResponse(stream, { abortController })
|
|
98
|
-
} catch (error: any) {
|
|
99
|
-
console.error('Blog chat error:', error)
|
|
100
|
-
if (error.name === 'AbortError' || abortController.signal.aborted) {
|
|
101
|
-
return new Response(null, { status: 499 })
|
|
102
|
-
}
|
|
103
|
-
return new Response(
|
|
104
|
-
JSON.stringify({
|
|
105
|
-
error: 'Failed to process chat request',
|
|
106
|
-
message: error.message,
|
|
107
|
-
}),
|
|
108
|
-
{
|
|
109
|
-
status: 500,
|
|
110
|
-
headers: { 'Content-Type': 'application/json' },
|
|
111
|
-
},
|
|
112
|
-
)
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
})
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { createFileRoute } from "@tanstack/react-router";
|
|
2
|
-
|
|
3
|
-
import { allPosts } from "content-collections";
|
|
4
|
-
|
|
5
|
-
import BlogPosts from "@/components/blog-posts";
|
|
6
|
-
|
|
7
|
-
export const Route = createFileRoute("/category/$category")({
|
|
8
|
-
component: RouteComponent,
|
|
9
|
-
loader: async ({ params }) => {
|
|
10
|
-
const category = params.category;
|
|
11
|
-
const posts = allPosts.filter((post) => post.categories.includes(category));
|
|
12
|
-
return { category, posts };
|
|
13
|
-
},
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
function RouteComponent() {
|
|
17
|
-
const { category, posts } = Route.useLoaderData();
|
|
18
|
-
return <BlogPosts title={category} posts={posts} />;
|
|
19
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { createFileRoute } from '@tanstack/react-router'
|
|
2
|
-
|
|
3
|
-
import { allPosts } from 'content-collections'
|
|
4
|
-
|
|
5
|
-
import BlogPosts from '@/components/blog-posts'
|
|
6
|
-
import VacayAssistant from '@/components/VacayAssistant'
|
|
7
|
-
|
|
8
|
-
export const Route = createFileRoute('/')({
|
|
9
|
-
component: App,
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
function App() {
|
|
13
|
-
return (
|
|
14
|
-
<>
|
|
15
|
-
<VacayAssistant />
|
|
16
|
-
<BlogPosts title="Hawaii Adventures" posts={allPosts} />
|
|
17
|
-
</>
|
|
18
|
-
)
|
|
19
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { createFileRoute } from '@tanstack/react-router'
|
|
2
|
-
import { marked } from 'marked'
|
|
3
|
-
|
|
4
|
-
import { allPosts } from 'content-collections'
|
|
5
|
-
|
|
6
|
-
import VacayAssistant from '@/components/VacayAssistant'
|
|
7
|
-
|
|
8
|
-
export const Route = createFileRoute('/posts/$slug')({
|
|
9
|
-
loader: async ({ params }) => {
|
|
10
|
-
const post = allPosts.find((post) => post.slug === params.slug)
|
|
11
|
-
if (!post) {
|
|
12
|
-
throw new Error('Post not found')
|
|
13
|
-
}
|
|
14
|
-
return post
|
|
15
|
-
},
|
|
16
|
-
component: RouteComponent,
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
function RouteComponent() {
|
|
20
|
-
const post = Route.useLoaderData()
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<div className="min-h-screen flex flex-col">
|
|
24
|
-
<VacayAssistant slug={post.slug} postTitle={post.title} />
|
|
25
|
-
|
|
26
|
-
<div
|
|
27
|
-
className="relative h-[66vh]"
|
|
28
|
-
style={{
|
|
29
|
-
backgroundImage: `url(/${post.image})`,
|
|
30
|
-
backgroundSize: 'cover',
|
|
31
|
-
backgroundPosition: 'center',
|
|
32
|
-
}}
|
|
33
|
-
>
|
|
34
|
-
<div className="absolute inset-0 bg-black/30" />
|
|
35
|
-
</div>
|
|
36
|
-
|
|
37
|
-
<div className="relative -mt-[40vh]">
|
|
38
|
-
<div className="container mx-auto max-w-4xl px-4 text-white">
|
|
39
|
-
<div className="rounded-2xl overflow-hidden backdrop-blur-xl bg-white/10 border border-white/20 shadow-2xl">
|
|
40
|
-
<div className="p-8 md:p-12">
|
|
41
|
-
{/* Title section */}
|
|
42
|
-
<h1 className="text-4xl font-serif italic md:text-5xl font-bold mb-4 drop-shadow-lg">
|
|
43
|
-
{post.title}
|
|
44
|
-
</h1>
|
|
45
|
-
|
|
46
|
-
{/* Summary section */}
|
|
47
|
-
<p className="text-lg text-white mb-8 drop-shadow">
|
|
48
|
-
{post.summary}
|
|
49
|
-
</p>
|
|
50
|
-
|
|
51
|
-
{/* Main content */}
|
|
52
|
-
<div className="prose prose-lg max-w-none prose-invert prose-p:text-white prose-headings:text-white prose-strong:text-white prose-a:text-teal-300">
|
|
53
|
-
<div
|
|
54
|
-
dangerouslySetInnerHTML={{ __html: marked(post.content) }}
|
|
55
|
-
/>
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
)
|
|
63
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
@import 'tailwindcss';
|
|
2
|
-
|
|
3
|
-
@plugin "tailwindcss-animate";
|
|
4
|
-
|
|
5
|
-
@custom-variant dark (&:is(.dark *));
|
|
6
|
-
|
|
7
|
-
body {
|
|
8
|
-
@apply m-0;
|
|
9
|
-
font-family:
|
|
10
|
-
-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
|
|
11
|
-
'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
|
12
|
-
-webkit-font-smoothing: antialiased;
|
|
13
|
-
-moz-osx-font-smoothing: grayscale;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
code {
|
|
17
|
-
font-family:
|
|
18
|
-
source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
:root {
|
|
22
|
-
--background: oklch(1 0 0);
|
|
23
|
-
--foreground: oklch(0.141 0.005 285.823);
|
|
24
|
-
--card: oklch(1 0 0);
|
|
25
|
-
--card-foreground: oklch(0.141 0.005 285.823);
|
|
26
|
-
--popover: oklch(1 0 0);
|
|
27
|
-
--popover-foreground: oklch(0.141 0.005 285.823);
|
|
28
|
-
--primary: oklch(0.21 0.006 285.885);
|
|
29
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
30
|
-
--secondary: oklch(0.967 0.001 286.375);
|
|
31
|
-
--secondary-foreground: oklch(0.21 0.006 285.885);
|
|
32
|
-
--muted: oklch(0.967 0.001 286.375);
|
|
33
|
-
--muted-foreground: oklch(0.552 0.016 285.938);
|
|
34
|
-
--accent: oklch(0.967 0.001 286.375);
|
|
35
|
-
--accent-foreground: oklch(0.21 0.006 285.885);
|
|
36
|
-
--destructive: oklch(0.577 0.245 27.325);
|
|
37
|
-
--destructive-foreground: oklch(0.577 0.245 27.325);
|
|
38
|
-
--border: oklch(0.92 0.004 286.32);
|
|
39
|
-
--input: oklch(0.92 0.004 286.32);
|
|
40
|
-
--ring: oklch(0.871 0.006 286.286);
|
|
41
|
-
--chart-1: oklch(0.646 0.222 41.116);
|
|
42
|
-
--chart-2: oklch(0.6 0.118 184.704);
|
|
43
|
-
--chart-3: oklch(0.398 0.07 227.392);
|
|
44
|
-
--chart-4: oklch(0.828 0.189 84.429);
|
|
45
|
-
--chart-5: oklch(0.769 0.188 70.08);
|
|
46
|
-
--radius: 0.625rem;
|
|
47
|
-
--sidebar: oklch(0.985 0 0);
|
|
48
|
-
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
|
49
|
-
--sidebar-primary: oklch(0.21 0.006 285.885);
|
|
50
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
51
|
-
--sidebar-accent: oklch(0.967 0.001 286.375);
|
|
52
|
-
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
|
53
|
-
--sidebar-border: oklch(0.92 0.004 286.32);
|
|
54
|
-
--sidebar-ring: oklch(0.871 0.006 286.286);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.dark {
|
|
58
|
-
--background: oklch(0.141 0.005 285.823);
|
|
59
|
-
--foreground: oklch(0.985 0 0);
|
|
60
|
-
--card: oklch(0.141 0.005 285.823);
|
|
61
|
-
--card-foreground: oklch(0.985 0 0);
|
|
62
|
-
--popover: oklch(0.141 0.005 285.823);
|
|
63
|
-
--popover-foreground: oklch(0.985 0 0);
|
|
64
|
-
--primary: oklch(0.985 0 0);
|
|
65
|
-
--primary-foreground: oklch(0.21 0.006 285.885);
|
|
66
|
-
--secondary: oklch(0.274 0.006 286.033);
|
|
67
|
-
--secondary-foreground: oklch(0.985 0 0);
|
|
68
|
-
--muted: oklch(0.274 0.006 286.033);
|
|
69
|
-
--muted-foreground: oklch(0.705 0.015 286.067);
|
|
70
|
-
--accent: oklch(0.274 0.006 286.033);
|
|
71
|
-
--accent-foreground: oklch(0.985 0 0);
|
|
72
|
-
--destructive: oklch(0.396 0.141 25.723);
|
|
73
|
-
--destructive-foreground: oklch(0.637 0.237 25.331);
|
|
74
|
-
--border: oklch(0.274 0.006 286.033);
|
|
75
|
-
--input: oklch(0.274 0.006 286.033);
|
|
76
|
-
--ring: oklch(0.442 0.017 285.786);
|
|
77
|
-
--chart-1: oklch(0.488 0.243 264.376);
|
|
78
|
-
--chart-2: oklch(0.696 0.17 162.48);
|
|
79
|
-
--chart-3: oklch(0.769 0.188 70.08);
|
|
80
|
-
--chart-4: oklch(0.627 0.265 303.9);
|
|
81
|
-
--chart-5: oklch(0.645 0.246 16.439);
|
|
82
|
-
--sidebar: oklch(0.21 0.006 285.885);
|
|
83
|
-
--sidebar-foreground: oklch(0.985 0 0);
|
|
84
|
-
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
85
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
86
|
-
--sidebar-accent: oklch(0.274 0.006 286.033);
|
|
87
|
-
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
88
|
-
--sidebar-border: oklch(0.274 0.006 286.033);
|
|
89
|
-
--sidebar-ring: oklch(0.442 0.017 285.786);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
@theme inline {
|
|
93
|
-
--color-background: var(--background);
|
|
94
|
-
--color-foreground: var(--foreground);
|
|
95
|
-
--color-card: var(--card);
|
|
96
|
-
--color-card-foreground: var(--card-foreground);
|
|
97
|
-
--color-popover: var(--popover);
|
|
98
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
99
|
-
--color-primary: var(--primary);
|
|
100
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
101
|
-
--color-secondary: var(--secondary);
|
|
102
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
103
|
-
--color-muted: var(--muted);
|
|
104
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
105
|
-
--color-accent: var(--accent);
|
|
106
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
107
|
-
--color-destructive: var(--destructive);
|
|
108
|
-
--color-destructive-foreground: var(--destructive-foreground);
|
|
109
|
-
--color-border: var(--border);
|
|
110
|
-
--color-input: var(--input);
|
|
111
|
-
--color-ring: var(--ring);
|
|
112
|
-
--color-chart-1: var(--chart-1);
|
|
113
|
-
--color-chart-2: var(--chart-2);
|
|
114
|
-
--color-chart-3: var(--chart-3);
|
|
115
|
-
--color-chart-4: var(--chart-4);
|
|
116
|
-
--color-chart-5: var(--chart-5);
|
|
117
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
118
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
119
|
-
--radius-lg: var(--radius);
|
|
120
|
-
--radius-xl: calc(var(--radius) + 4px);
|
|
121
|
-
--color-sidebar: var(--sidebar);
|
|
122
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
123
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
124
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
125
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
126
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
127
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
128
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
@layer base {
|
|
132
|
-
* {
|
|
133
|
-
@apply border-border outline-ring/50;
|
|
134
|
-
}
|
|
135
|
-
body {
|
|
136
|
-
@apply bg-background text-foreground;
|
|
137
|
-
}
|
|
138
|
-
}
|
package/examples/blog/info.json
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Blog",
|
|
3
|
-
"description": "A Hawaii adventures travel blog built with content-collections and TanStack Start for Netlify.",
|
|
4
|
-
"phase": "example",
|
|
5
|
-
"modes": ["file-router"],
|
|
6
|
-
"type": "example",
|
|
7
|
-
"priority": 10,
|
|
8
|
-
"link": "",
|
|
9
|
-
"routes": [
|
|
10
|
-
{"url": "/", "path": "src/routes/index.tsx", "jsName": "BlogHome"},
|
|
11
|
-
{"url": "/posts/$slug", "path": "src/routes/posts.$slug.tsx", "jsName": "BlogPost"},
|
|
12
|
-
{"url": "/category/$category", "path": "src/routes/category.$category.tsx", "jsName": "BlogCategory"}
|
|
13
|
-
],
|
|
14
|
-
"features": ["tanstack-start", "content-collections", "tanstack-ai"],
|
|
15
|
-
"integrations": [{"type": "vite-plugin", "import": "import contentCollections from '@content-collections/vite'", "code": "contentCollections()"}],
|
|
16
|
-
"dependsOn": [],
|
|
17
|
-
"variables": [],
|
|
18
|
-
"bareBones": {"deleteFiles": ["public/jungle.jpg", "public/mountains.jpg", "public/snorkeling.jpg", "public/waterfall.jpg"]},
|
|
19
|
-
"packageFileDescriptions": {
|
|
20
|
-
"content-collections.ts": "Content Collections config: posts schema (title, summary, categories, slug, image, date).",
|
|
21
|
-
"content/posts/beach.md": "Blog post: beach adventure.",
|
|
22
|
-
"content/posts/jungle.md.ejs": "Blog post template: jungle adventure.",
|
|
23
|
-
"content/posts/mountains.md.ejs": "Blog post template: mountains adventure.",
|
|
24
|
-
"content/posts/snorkeling.md.ejs": "Blog post template: snorkeling adventure.",
|
|
25
|
-
"content/posts/waterfall.md.ejs": "Blog post template: waterfall adventure.",
|
|
26
|
-
"src/styles.css": "Global styles: Tailwind, prose, highlight.js.",
|
|
27
|
-
"src/routes/index.tsx": "Blog home: post list, VacayAssistant.",
|
|
28
|
-
"src/routes/posts.$slug.tsx": "Post detail route: single post by slug.",
|
|
29
|
-
"src/routes/category.$category.tsx": "Category route: posts filtered by category.",
|
|
30
|
-
"src/routes/api.blog-chat.ts": "POST handler for blog AI chat with getPostBySlug, getAllBlogPosts tools.",
|
|
31
|
-
"src/routes/__root.tsx": "Root layout: Header, styles, TanStack Devtools.",
|
|
32
|
-
"src/lib/utils.ts": "cn() helper for conditional Tailwind class merging.",
|
|
33
|
-
"src/lib/blog-tools.ts": "AI tools: getPostBySlug, getAllBlogPosts, getPostsByCategory for VacayAssistant.",
|
|
34
|
-
"src/lib/blog-ai-hook.ts": "useBlogChat hook for /api/blog-chat.",
|
|
35
|
-
"src/components/ui/card.tsx": "Card UI component.",
|
|
36
|
-
"src/components/blog-posts.tsx": "Blog post list/card display component.",
|
|
37
|
-
"src/components/VacayAssistant.tsx": "AI assistant for blog Q&A.",
|
|
38
|
-
"src/components/Header.tsx": "Site header with nav."
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"dependencies": {
|
|
3
|
-
"@tanstack/ai": "0.2.2",
|
|
4
|
-
"@tanstack/ai-anthropic": "0.2.0",
|
|
5
|
-
"@tanstack/ai-client": "0.2.2",
|
|
6
|
-
"@tanstack/ai-gemini": "0.3.2",
|
|
7
|
-
"@tanstack/ai-ollama": "0.3.0",
|
|
8
|
-
"@tanstack/ai-openai": "0.3.0",
|
|
9
|
-
"@tanstack/ai-react": "0.2.2",
|
|
10
|
-
"@tanstack/store": "^0.8.0",
|
|
11
|
-
"class-variance-authority": "^0.7.1",
|
|
12
|
-
"clsx": "^2.1.1",
|
|
13
|
-
"marked": "^17.0.1",
|
|
14
|
-
"streamdown": "^2.1.0",
|
|
15
|
-
"tailwind-merge": "^3.0.2",
|
|
16
|
-
"tailwindcss-animate": "^1.0.7",
|
|
17
|
-
"zod": "^4.3.5"
|
|
18
|
-
},
|
|
19
|
-
"devDependencies": {
|
|
20
|
-
"@content-collections/core": "^0.13.1",
|
|
21
|
-
"@content-collections/vite": "^0.2.8"
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Calculator Example
|
|
2
|
-
|
|
3
|
-
A sleek iOS-style calculator built with TanStack Start and Tailwind CSS for Netlify deployment.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Full Calculator**: Supports addition, subtraction, multiplication, division
|
|
8
|
-
- **Percentage & Sign Toggle**: Additional utility operations
|
|
9
|
-
- **Chained Operations**: Evaluate expressions with multiple operations
|
|
10
|
-
- **Formatted Display**: Number formatting with locale-aware separators
|
|
11
|
-
|
|
12
|
-
## Development
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
npm run dev
|
|
16
|
-
```
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
### Calculator Component
|
|
2
|
-
|
|
3
|
-
iOS-style calculator built with React `useReducer` for state management.
|
|
4
|
-
|
|
5
|
-
**State pattern:** `display`, `previousValue`, `operation`, `overwrite`
|
|
6
|
-
|
|
7
|
-
**Actions:** ADD_DIGIT, CHOOSE_OPERATION, EVALUATE, CLEAR, DELETE_DIGIT, PERCENT, TOGGLE_SIGN
|
|
8
|
-
|
|
9
|
-
No special dependencies beyond base TanStack Start. Pure React + Tailwind CSS.
|