@astro-minimax/cli 0.5.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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +170 -0
  3. package/index.js +36 -0
  4. package/package.json +44 -0
  5. package/template/.env.example +53 -0
  6. package/template/astro.config.ts +204 -0
  7. package/template/datas/ai-summaries.json +8 -0
  8. package/template/datas/author-context.json +4 -0
  9. package/template/datas/sources/blog-digest.json +5 -0
  10. package/template/datas/voice-profile.json +4 -0
  11. package/template/eslint.config.js +19 -0
  12. package/template/functions/api/ai-info.ts +39 -0
  13. package/template/functions/api/chat.ts +20 -0
  14. package/template/functions/api/notify/comment.ts +109 -0
  15. package/template/package.json +77 -0
  16. package/template/public/favicon.svg +4 -0
  17. package/template/src/config.ts +104 -0
  18. package/template/src/constants.ts +62 -0
  19. package/template/src/content.config.ts +27 -0
  20. package/template/src/data/blog/zh/hello-world.md +33 -0
  21. package/template/src/data/friends.ts +3 -0
  22. package/template/src/env.d.ts +29 -0
  23. package/template/tools/README.md +169 -0
  24. package/template/tools/ai-process.ts +816 -0
  25. package/template/tools/build-author-context.ts +405 -0
  26. package/template/tools/build-voice-profile.ts +322 -0
  27. package/template/tools/generate-author-profile.ts +369 -0
  28. package/template/tools/generate-cover.ts +123 -0
  29. package/template/tools/generate-og.ts +280 -0
  30. package/template/tools/generate-related.ts +146 -0
  31. package/template/tools/generate-tags.ts +251 -0
  32. package/template/tools/lib/ai-provider.ts +240 -0
  33. package/template/tools/lib/frontmatter.ts +94 -0
  34. package/template/tools/lib/index.ts +6 -0
  35. package/template/tools/lib/markdown.ts +40 -0
  36. package/template/tools/lib/posts.ts +89 -0
  37. package/template/tools/lib/utils.ts +138 -0
  38. package/template/tools/lib/vectors.ts +96 -0
  39. package/template/tools/summarize.ts +142 -0
  40. package/template/tools/translate.ts +60 -0
  41. package/template/tools/vectorize.ts +105 -0
  42. package/template/tsconfig.json +11 -0
  43. package/template/wrangler.toml +16 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Souloss
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,170 @@
1
+ # @astro-minimax/cli
2
+
3
+ CLI tool to scaffold a new blog project using the astro-minimax theme.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ # npx (recommended)
9
+ npx @astro-minimax/cli my-blog
10
+
11
+ # pnpm
12
+ pnpm dlx @astro-minimax/cli my-blog
13
+
14
+ # yarn
15
+ yarn dlx @astro-minimax/cli my-blog
16
+ ```
17
+
18
+ ## Generated Structure
19
+
20
+ ```
21
+ my-blog/
22
+ ├── astro.config.ts # Astro + minimax integration config
23
+ ├── package.json # Dependencies (core, viz, tailwind, etc.)
24
+ ├── tsconfig.json # TypeScript configuration
25
+ ├── public/
26
+ │ └── favicon.svg
27
+ └── src/
28
+ ├── config.ts # SITE configuration object
29
+ ├── constants.ts # Social links and share links
30
+ ├── content.config.ts # Astro content collection schema
31
+ ├── env.d.ts
32
+ └── data/
33
+ ├── blog/zh/hello-world.md # Sample blog post
34
+ └── friends.ts # Friend links data
35
+ ```
36
+
37
+ No `src/pages/` directory — all routes are injected by `@astro-minimax/core`.
38
+
39
+ ## After Scaffolding
40
+
41
+ 1. **Install dependencies:**
42
+
43
+ ```bash
44
+ cd my-blog && pnpm install
45
+ ```
46
+
47
+ 2. **Configure your site** in `src/config.ts`:
48
+ - Set `website`, `author`, `title`, `desc`
49
+ - Configure features (tags, categories, series, etc.)
50
+
51
+ 3. **Start development:**
52
+
53
+ ```bash
54
+ pnpm dev
55
+ ```
56
+
57
+ 4. **Add blog posts** in `src/data/blog/zh/` (Chinese) or `src/data/blog/en/` (English).
58
+
59
+ ## Features
60
+
61
+ ### Built-in Features
62
+
63
+ | Feature | Description | Default |
64
+ | ---------- | --------------------------- | ------- |
65
+ | Tags | Tag-based article filtering | Enabled |
66
+ | Categories | Category-based navigation | Enabled |
67
+ | Series | Article series grouping | Enabled |
68
+ | Archives | Time-based article archive | Enabled |
69
+ | Search | Full-text search (Pagefind) | Enabled |
70
+ | Dark Mode | Light/dark theme toggle | Enabled |
71
+
72
+ ### Content Enhancements
73
+
74
+ | Feature | Syntax | Description |
75
+ | ------- | -------------------- | ----------------------------------------- |
76
+ | Mermaid | ` ```mermaid ` | Flowcharts, sequence diagrams, pie charts |
77
+ | Markmap | ` ```markmap ` | Interactive mind maps |
78
+ | Math | `$...$` or `$$...$$` | KaTeX math equations |
79
+ | Code | ` ```language ` | Shiki syntax highlighting |
80
+ | Emoji | `:emoji_name:` | Emoji shortcodes |
81
+ | Alerts | `> [!NOTE]` | GitHub-style alerts |
82
+ | Tables | Markdown tables | Styled responsive tables |
83
+
84
+ ## Customization
85
+
86
+ - **Colors**: Override CSS custom properties in your own CSS file
87
+ - **Features**: Toggle features in `SITE.features`
88
+ - **Visualizations**: Use mermaid/markmap code blocks in Markdown
89
+
90
+ ## AI Chat Setup
91
+
92
+ The template includes Preact integration ready for AI features.
93
+
94
+ ### Step 1: Install AI Package
95
+
96
+ ```bash
97
+ pnpm add @astro-minimax/ai
98
+ ```
99
+
100
+ ### Step 2: Enable in Config
101
+
102
+ Update `src/config.ts`:
103
+
104
+ ```typescript
105
+ features: {
106
+ ai: true, // Enable AI feature flag
107
+ },
108
+
109
+ ai: {
110
+ enabled: true,
111
+ mockMode: false,
112
+ apiEndpoint: "/api/chat",
113
+ },
114
+ ```
115
+
116
+ ### Step 3: Create API Endpoint
117
+
118
+ Create `functions/api/chat.ts`:
119
+
120
+ ```typescript
121
+ import { handleChatRequest, initializeMetadata } from '@astro-minimax/ai/server';
122
+
123
+ export const onRequest: PagesFunction = async (context) => {
124
+ initializeMetadata({}, context.env);
125
+ return handleChatRequest({ env: context.env, request: context.request });
126
+ };
127
+ ```
128
+
129
+ ### Step 4: Configure Environment
130
+
131
+ Create `.env` file:
132
+
133
+ ```env
134
+ # OpenAI-compatible API
135
+ AI_BASE_URL=https://api.openai.com/v1
136
+ AI_API_KEY=your-api-key
137
+ AI_MODEL=gpt-4o-mini
138
+
139
+ # Or use Cloudflare Workers AI (in wrangler.toml)
140
+ # [ai]
141
+ # binding = "AI"
142
+ ```
143
+
144
+ ### Step 5: Run Dev Server
145
+
146
+ For local development with AI:
147
+
148
+ ```bash
149
+ # Start AI dev server (port 8787)
150
+ node dev-ai-server.mjs
151
+
152
+ # In another terminal, start Astro dev
153
+ pnpm dev
154
+ ```
155
+
156
+ The AI widget will appear as a floating button on your blog.
157
+
158
+ ## Optional Packages
159
+
160
+ | Package | Purpose |
161
+ | ------------------- | ------------------------ |
162
+ | `@astro-minimax/ai` | AI chat assistant widget |
163
+
164
+ ## Related Articles
165
+
166
+ - [快速开始:两种使用方式](https://demo-astro-minimax.souloss.cn/zh/posts/getting-started)
167
+ - [如何在 Astro 博客文章中添加 LaTeX 公式](https://demo-astro-minimax.souloss.cn/zh/posts/add-latex-to-astro-blog)
168
+ - [如何使用 Git 钩子设置创建和修改日期](https://demo-astro-minimax.souloss.cn/zh/posts/git-hooks-for-date)
169
+ - [如何更新 astro-minimax 的依赖](https://demo-astro-minimax.souloss.cn/zh/posts/update-dependencies)
170
+ - [在 astro-minimax 中动态生成 OG 图片](https://demo-astro-minimax.souloss.cn/zh/posts/dynamic-og-image)
package/index.js ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ import { cpSync, mkdirSync, existsSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { join, resolve, basename } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const __dirname = fileURLToPath(new URL(".", import.meta.url));
7
+ const templateDir = join(__dirname, "template");
8
+
9
+ const projectName = process.argv[2];
10
+ if (!projectName) {
11
+ console.error("Usage: astro-minimax <project-name>");
12
+ console.error(" npx @astro-minimax/cli <project-name>");
13
+ process.exit(1);
14
+ }
15
+
16
+ const targetDir = resolve(process.cwd(), projectName);
17
+
18
+ if (existsSync(targetDir)) {
19
+ console.error(`Directory "${projectName}" already exists.`);
20
+ process.exit(1);
21
+ }
22
+
23
+ mkdirSync(targetDir, { recursive: true });
24
+ cpSync(templateDir, targetDir, { recursive: true });
25
+
26
+ const pkgPath = join(targetDir, "package.json");
27
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
28
+ pkg.name = basename(targetDir);
29
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
30
+
31
+ console.log(`\n ✅ Created "${projectName}" successfully!\n`);
32
+ console.log(" Next steps:\n");
33
+ console.log(` cd ${projectName}`);
34
+ console.log(" pnpm install");
35
+ console.log(" pnpm dev\n");
36
+ console.log(" Docs: https://github.com/souloss/astro-minimax\n");
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@astro-minimax/cli",
3
+ "version": "0.5.0",
4
+ "type": "module",
5
+ "description": "CLI tool to create a new astro-minimax blog project — a minimalist, fast, and modern Astro blog theme with AI-powered features.",
6
+ "author": "Souloss",
7
+ "license": "MIT",
8
+ "keywords": [
9
+ "astro",
10
+ "scaffold",
11
+ "cli",
12
+ "template",
13
+ "blog-starter",
14
+ "create-app"
15
+ ],
16
+ "homepage": "https://github.com/souloss/astro-minimax#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/souloss/astro-minimax/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/souloss/astro-minimax",
23
+ "directory": "packages/cli"
24
+ },
25
+ "bin": {
26
+ "astro-minimax": "./index.js"
27
+ },
28
+ "files": [
29
+ "index.js",
30
+ "template/"
31
+ ],
32
+ "sideEffects": false,
33
+ "devDependencies": {
34
+ "astro": "^5.0.0",
35
+ "typescript": "^5.9.3"
36
+ },
37
+ "engines": {
38
+ "node": ">=22.12.0",
39
+ "pnpm": ">=9.0.0"
40
+ },
41
+ "scripts": {
42
+ "typecheck": "tsc --noEmit"
43
+ }
44
+ }
@@ -0,0 +1,53 @@
1
+ # ─────────────────────────────────────────────────────────────
2
+ # Workers AI Configuration (Recommended for Cloudflare deployment)
3
+ # ─────────────────────────────────────────────────────────────
4
+ AI_BINDING_NAME=minimaxAI
5
+ AI_WORKERS_MODEL=@cf/zai-org/glm-4.7-flash
6
+
7
+ # ─────────────────────────────────────────────────────────────
8
+ # OpenAI-Compatible API (For local dev or non-Cloudflare deployment)
9
+ # ─────────────────────────────────────────────────────────────
10
+ AI_API_KEY=your_api_key
11
+ AI_BASE_URL=https://api.openai.com/v1
12
+ AI_MODEL=gpt-4o-mini
13
+
14
+ # ─────────────────────────────────────────────────────────────
15
+ # AI Response Cache (Optional - Reduces API costs)
16
+ # ─────────────────────────────────────────────────────────────
17
+ AI_RESPONSE_CACHE_ENABLED=false
18
+ AI_RESPONSE_CACHE_TTL=7200
19
+ AI_RESPONSE_CACHE_PLAYBACK_DELAY=20
20
+ AI_RESPONSE_CACHE_CHUNK_SIZE=15
21
+ AI_RESPONSE_CACHE_THINKING_DELAY=5
22
+
23
+ # ─────────────────────────────────────────────────────────────
24
+ # Site Configuration
25
+ # ─────────────────────────────────────────────────────────────
26
+ SITE_URL=https://your-domain.com
27
+ SITE_AUTHOR=Your Name
28
+ SITE_DESCRIPTION=Your blog description
29
+
30
+ # ─────────────────────────────────────────────────────────────
31
+ # Notification - Telegram Provider (Optional)
32
+ # Get token from @BotFather, chat ID from @userinfobot
33
+ # ─────────────────────────────────────────────────────────────
34
+ # NOTIFY_TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
35
+ # NOTIFY_TELEGRAM_CHAT_ID=123456789
36
+
37
+ # ─────────────────────────────────────────────────────────────
38
+ # Notification - Email Provider via Resend (Optional)
39
+ # Sign up at https://resend.com
40
+ # ─────────────────────────────────────────────────────────────
41
+ # NOTIFY_RESEND_API_KEY=re_xxxxxxxxxx
42
+ # NOTIFY_RESEND_FROM=noreply@yourdomain.com
43
+ # NOTIFY_RESEND_TO=you@example.com
44
+
45
+ # ─────────────────────────────────────────────────────────────
46
+ # Notification - Webhook (Optional)
47
+ # ─────────────────────────────────────────────────────────────
48
+ # NOTIFY_WEBHOOK_URL=https://your-webhook.com/notify
49
+
50
+ # ─────────────────────────────────────────────────────────────
51
+ # SEO - Google Site Verification (Optional)
52
+ # ─────────────────────────────────────────────────────────────
53
+ # PUBLIC_GOOGLE_SITE_VERIFICATION=your-verification-code
@@ -0,0 +1,204 @@
1
+ import { defineConfig, envField } from "astro/config";
2
+ import tailwindcss from "@tailwindcss/vite";
3
+ import minimax from "@astro-minimax/core";
4
+ import minimaxViz from "@astro-minimax/viz";
5
+ import sitemap from "@astrojs/sitemap";
6
+ import mdx from "@astrojs/mdx";
7
+ import preact from "@astrojs/preact";
8
+ import remarkToc from "remark-toc";
9
+ import remarkCollapse from "remark-collapse";
10
+ import remarkMath from "remark-math";
11
+ import remarkGithubAlerts from "remark-github-alerts";
12
+ import remarkEmoji from "remark-emoji";
13
+ import rehypeKatex from "rehype-katex";
14
+ import { remarkReadingTime } from "@astro-minimax/core/plugins/remark-reading-time";
15
+ import { remarkAddZoomable } from "@astro-minimax/core/plugins/remark-add-zoomable";
16
+ import { rehypeExternalLinks } from "@astro-minimax/core/plugins/rehype-external-links";
17
+ import { rehypeTableScroll } from "@astro-minimax/core/plugins/rehype-table-scroll";
18
+ import { rehypeAutolinkHeadings } from "@astro-minimax/core/plugins/rehype-autolink-headings";
19
+ import {
20
+ transformerNotationDiff,
21
+ transformerNotationHighlight,
22
+ transformerNotationWordHighlight,
23
+ } from "@shikijs/transformers";
24
+ import {
25
+ updateStyle,
26
+ addTitle,
27
+ addLanguage,
28
+ addCopyButton,
29
+ addCollapse,
30
+ } from "@astro-minimax/core/plugins/shiki-transformers";
31
+ import { SITE } from "./src/config";
32
+ import { SOCIALS, SHARE_LINKS } from "./src/constants";
33
+ import { FRIENDS } from "./src/data/friends";
34
+
35
+ const asTransformer = (t: unknown) => t;
36
+
37
+ const shikiTransformers = [
38
+ asTransformer(updateStyle()),
39
+ asTransformer(addTitle()),
40
+ asTransformer(addLanguage()),
41
+ asTransformer(addCopyButton(2000)),
42
+ asTransformer(addCollapse(15)),
43
+ transformerNotationHighlight(),
44
+ transformerNotationWordHighlight(),
45
+ transformerNotationDiff({ matchAlgorithm: "v3" }),
46
+ ];
47
+
48
+ export default defineConfig({
49
+ site: SITE.website,
50
+ output: "static",
51
+ prefetch: {
52
+ prefetchAll: true,
53
+ defaultStrategy: "hover",
54
+ },
55
+ integrations: [
56
+ minimax({
57
+ site: SITE,
58
+ socials: SOCIALS,
59
+ shareLinks: SHARE_LINKS,
60
+ friends: FRIENDS,
61
+ blogPath: "src/data/blog",
62
+ }),
63
+ minimaxViz({ mermaid: true, markmap: true }),
64
+ preact({ compat: true }),
65
+ sitemap({
66
+ filter: page => SITE.showArchives || !page.endsWith("/archives"),
67
+ }),
68
+ mdx({
69
+ shikiConfig: {
70
+ themes: { light: "github-light", dark: "night-owl" },
71
+ defaultColor: false,
72
+ wrap: false,
73
+ transformers: shikiTransformers,
74
+ },
75
+ }),
76
+ ],
77
+ markdown: {
78
+ remarkPlugins: [
79
+ remarkToc,
80
+ [remarkCollapse, { test: "Table of contents" }],
81
+ remarkMath,
82
+ remarkGithubAlerts,
83
+ remarkEmoji,
84
+ remarkReadingTime,
85
+ [remarkAddZoomable, { className: "zoomable" }],
86
+ ],
87
+ rehypePlugins: [
88
+ rehypeKatex,
89
+ rehypeExternalLinks,
90
+ rehypeTableScroll,
91
+ rehypeAutolinkHeadings,
92
+ ],
93
+ shikiConfig: {
94
+ themes: { light: "github-light", dark: "night-owl" },
95
+ defaultColor: false,
96
+ wrap: false,
97
+ transformers: shikiTransformers,
98
+ },
99
+ },
100
+ vite: {
101
+ plugins: [
102
+ tailwindcss() as never,
103
+ {
104
+ name: "astro-minimax-preact-singleton",
105
+ enforce: "pre" as const,
106
+ async resolveId(source, importer, options) {
107
+ if (source.startsWith("@/components/media")) {
108
+ const vizDir = new URL("../../packages/viz/src/components", import.meta.url).pathname;
109
+ return this.resolve(source.replace("@/components/media", vizDir), importer, { ...options, skipSelf: true });
110
+ }
111
+ },
112
+ },
113
+ ],
114
+ server: {
115
+ fs: {
116
+ strict: true,
117
+ allow: [
118
+ new URL("../../packages", import.meta.url).pathname,
119
+ new URL("../../node_modules", import.meta.url).pathname,
120
+ "./src",
121
+ "./.astro",
122
+ ],
123
+ },
124
+ proxy: {
125
+ "/api": {
126
+ target: `http://localhost:${process.env.AI_DEV_PORT || "8787"}`,
127
+ changeOrigin: true,
128
+ },
129
+ },
130
+ },
131
+ resolve: {
132
+ alias: {
133
+ "@/components/media": new URL("../../packages/viz/src/components", import.meta.url).pathname,
134
+ "@/" : new URL("./src/", import.meta.url).pathname,
135
+ "react": "preact/compat",
136
+ "react-dom": "preact/compat",
137
+ "react/jsx-runtime": "preact/jsx-runtime",
138
+ },
139
+ dedupe: ["preact", "preact/hooks", "preact/compat", "preact/debug", "preact/devtools", "react", "react-dom"],
140
+ },
141
+ optimizeDeps: {
142
+ exclude: ["@resvg/resvg-js"],
143
+ include: [
144
+ "preact",
145
+ "preact/hooks",
146
+ "preact/compat",
147
+ "preact/debug",
148
+ "preact/devtools",
149
+ "preact/jsx-runtime",
150
+ "preact/jsx-dev-runtime",
151
+ "@ai-sdk/react",
152
+ "ai",
153
+ "@astro-minimax/ai",
154
+ "@astro-minimax/core",
155
+ "@astro-minimax/viz",
156
+ ],
157
+ },
158
+ ssr: {
159
+ external: ["@resvg/resvg-js", "sharp"],
160
+ noExternal: [
161
+ "@astro-minimax/ai",
162
+ "@astro-minimax/core",
163
+ "@astro-minimax/viz",
164
+ "@ai-sdk/react",
165
+ "ai",
166
+ ],
167
+ },
168
+ build: {
169
+ rollupOptions: {
170
+ external: [/@resvg\/resvg-js/, /@resvg\/resvg-js-linux-.*/, /\.node$/],
171
+ },
172
+ cssMinify: true,
173
+ minify: "esbuild",
174
+ sourcemap: false,
175
+ reportCompressedSize: true,
176
+ },
177
+ environments: {
178
+ client: {
179
+ build: {
180
+ rollupOptions: {
181
+ output: {
182
+ chunkFileNames: "assets/[name]-[hash].js",
183
+ entryFileNames: "assets/[name]-[hash].js",
184
+ assetFileNames: "assets/[name]-[hash].[ext]",
185
+ },
186
+ },
187
+ },
188
+ },
189
+ },
190
+ },
191
+ image: {
192
+ responsiveStyles: true,
193
+ layout: "constrained",
194
+ },
195
+ env: {
196
+ schema: {
197
+ PUBLIC_GOOGLE_SITE_VERIFICATION: envField.string({
198
+ access: "public",
199
+ context: "client",
200
+ optional: true,
201
+ }),
202
+ },
203
+ },
204
+ });
@@ -0,0 +1,8 @@
1
+ {
2
+ "meta": {
3
+ "lastUpdated": "2026-01-01T00:00:00.000Z",
4
+ "model": "none",
5
+ "totalProcessed": 0
6
+ },
7
+ "articles": {}
8
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "author": {},
3
+ "posts": []
4
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "generatedAt": "",
3
+ "count": 0,
4
+ "posts": []
5
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "style": {},
3
+ "examples": []
4
+ }
@@ -0,0 +1,19 @@
1
+ import eslintPluginAstro from "eslint-plugin-astro";
2
+ import globals from "globals";
3
+ import tseslint from "typescript-eslint";
4
+
5
+ export default [
6
+ ...tseslint.configs.recommended,
7
+ ...eslintPluginAstro.configs.recommended,
8
+ {
9
+ languageOptions: {
10
+ globals: {
11
+ ...globals.browser,
12
+ ...globals.node,
13
+ },
14
+ },
15
+ },
16
+ { rules: { "no-console": "error" } },
17
+ { files: ["tools/**"], rules: { "no-console": "off" } },
18
+ { ignores: ["dist/**", ".astro/**", "public/pagefind/**"] },
19
+ ];
@@ -0,0 +1,39 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+ import { ProviderManager, hasAnyProviderConfigured, DEFAULT_WORKERS_BINDING_NAME } from '@astro-minimax/ai';
3
+ import { initializeMetadata } from '@astro-minimax/ai/server';
4
+ import type { ChatHandlerEnv } from '@astro-minimax/ai/server';
5
+ import aiSummaries from '../../datas/ai-summaries.json';
6
+ import authorContext from '../../datas/author-context.json';
7
+ import voiceProfile from '../../datas/voice-profile.json';
8
+
9
+ interface FunctionEnv extends ChatHandlerEnv {
10
+ [key: string]: unknown;
11
+ }
12
+
13
+ export const onRequest: PagesFunction<FunctionEnv> = async (context) => {
14
+ const env = context.env;
15
+ initializeMetadata(
16
+ { summaries: aiSummaries, authorContext, voiceProfile },
17
+ env,
18
+ );
19
+
20
+ const manager = new ProviderManager(env, { enableMockFallback: true });
21
+ const providerStatus = manager.getProviderStatus();
22
+ const bindingName = (env.AI_BINDING_NAME as string) || DEFAULT_WORKERS_BINDING_NAME;
23
+
24
+ return new Response(JSON.stringify({
25
+ status: 'ok',
26
+ timestamp: new Date().toISOString(),
27
+ ai: {
28
+ configured: hasAnyProviderConfigured(env) || !!(env as Record<string, unknown>)[bindingName],
29
+ providers: providerStatus.map(p => ({
30
+ id: p.id, type: p.type, weight: p.weight, healthy: p.health.healthy, model: p.model,
31
+ })),
32
+ },
33
+ hints: manager.hasProviders()
34
+ ? [`Providers available: ${manager.getProviderCount()}`, 'Mock fallback: enabled']
35
+ : ['No AI providers configured. Set AI_BASE_URL + AI_API_KEY or configure Workers AI binding.'],
36
+ }, null, 2), {
37
+ headers: { 'Content-Type': 'application/json' },
38
+ });
39
+ };
@@ -0,0 +1,20 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+ import { handleChatRequest, initializeMetadata } from '@astro-minimax/ai/server';
3
+ import type { ChatHandlerEnv } from '@astro-minimax/ai/server';
4
+ import aiSummaries from '../../datas/ai-summaries.json';
5
+ import authorContext from '../../datas/author-context.json';
6
+ import voiceProfile from '../../datas/voice-profile.json';
7
+
8
+ interface FunctionEnv extends ChatHandlerEnv {
9
+ CACHE_KV?: KVNamespace;
10
+ minimaxAI?: Ai;
11
+ [key: string]: unknown;
12
+ }
13
+
14
+ export const onRequest: PagesFunction<FunctionEnv> = async (context) => {
15
+ initializeMetadata(
16
+ { summaries: aiSummaries, authorContext, voiceProfile },
17
+ context.env,
18
+ );
19
+ return handleChatRequest({ env: context.env, request: context.request });
20
+ };