@astro-minimax/ai 0.7.4 → 0.8.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 (80) hide show
  1. package/dist/components/AIChatContainer.d.ts +9 -0
  2. package/dist/components/AIChatContainer.d.ts.map +1 -0
  3. package/dist/components/AIChatContainer.js +936 -0
  4. package/{src → dist}/components/AIChatWidget.astro +1 -1
  5. package/dist/components/ChatPanel.d.ts +19 -0
  6. package/dist/components/ChatPanel.d.ts.map +1 -0
  7. package/dist/components/ChatPanel.js +914 -0
  8. package/dist/data/index.js +18 -1
  9. package/dist/fact-registry/index.js +16 -3
  10. package/dist/index.js +11 -30
  11. package/dist/intelligence/evidence-analysis.d.ts.map +1 -1
  12. package/dist/intelligence/index.js +56 -5
  13. package/dist/intelligence/keyword-extract.d.ts.map +1 -1
  14. package/dist/middleware/index.js +10 -1
  15. package/dist/prompt/index.js +10 -4
  16. package/dist/provider-manager/base.d.ts +1 -0
  17. package/dist/provider-manager/base.d.ts.map +1 -1
  18. package/dist/provider-manager/types.d.ts +1 -0
  19. package/dist/provider-manager/types.d.ts.map +1 -1
  20. package/dist/providers/index.js +5 -1
  21. package/dist/search/index.js +48 -6
  22. package/dist/server/dev-server.js +236 -259
  23. package/dist/server/index.js +39 -6
  24. package/dist/stream/index.js +8 -2
  25. package/package.json +16 -10
  26. package/dist/cache/global-cache.js +0 -141
  27. package/dist/cache/index.js +0 -62
  28. package/dist/cache/kv-adapter.js +0 -102
  29. package/dist/cache/memory-adapter.js +0 -95
  30. package/dist/cache/response-cache.js +0 -85
  31. package/dist/cache/types.js +0 -16
  32. package/dist/data/metadata-loader.js +0 -66
  33. package/dist/data/types.js +0 -1
  34. package/dist/fact-registry/fact-matcher.js +0 -94
  35. package/dist/fact-registry/prompt-injector.js +0 -57
  36. package/dist/fact-registry/registry.js +0 -38
  37. package/dist/fact-registry/types.js +0 -5
  38. package/dist/intelligence/citation-appender.js +0 -65
  39. package/dist/intelligence/citation-guard.js +0 -125
  40. package/dist/intelligence/evidence-analysis.js +0 -88
  41. package/dist/intelligence/intent-detect.js +0 -131
  42. package/dist/intelligence/keyword-extract.js +0 -114
  43. package/dist/intelligence/response-templates.js +0 -116
  44. package/dist/intelligence/types.js +0 -1
  45. package/dist/middleware/rate-limiter.js +0 -129
  46. package/dist/prompt/dynamic-layer.js +0 -67
  47. package/dist/prompt/prompt-builder.js +0 -12
  48. package/dist/prompt/semi-static-layer.js +0 -29
  49. package/dist/prompt/static-layer.js +0 -150
  50. package/dist/prompt/types.js +0 -1
  51. package/dist/provider-manager/base.js +0 -47
  52. package/dist/provider-manager/config.js +0 -134
  53. package/dist/provider-manager/index.js +0 -6
  54. package/dist/provider-manager/manager.js +0 -121
  55. package/dist/provider-manager/mock.js +0 -56
  56. package/dist/provider-manager/openai.js +0 -112
  57. package/dist/provider-manager/types.js +0 -6
  58. package/dist/provider-manager/workers.js +0 -74
  59. package/dist/providers/mock.js +0 -234
  60. package/dist/search/idf.js +0 -31
  61. package/dist/search/search-api.js +0 -119
  62. package/dist/search/search-index.js +0 -35
  63. package/dist/search/search-utils.js +0 -122
  64. package/dist/search/session-cache.js +0 -92
  65. package/dist/search/types.js +0 -1
  66. package/dist/search/vector-reranker.js +0 -135
  67. package/dist/server/chat-handler.js +0 -590
  68. package/dist/server/errors.js +0 -41
  69. package/dist/server/metadata-init.js +0 -47
  70. package/dist/server/notify.js +0 -74
  71. package/dist/server/stream-helpers.js +0 -197
  72. package/dist/server/types.js +0 -13
  73. package/dist/stream/mock-stream.js +0 -27
  74. package/dist/stream/response.js +0 -22
  75. package/dist/utils/i18n.js +0 -164
  76. package/src/components/AIChatContainer.tsx +0 -31
  77. package/src/components/ChatPanel.tsx +0 -866
  78. package/src/providers/mock.ts +0 -240
  79. package/src/server/types.ts +0 -89
  80. package/src/utils/i18n.ts +0 -238
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astro-minimax/ai",
3
- "version": "0.7.4",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "description": "Vendor-agnostic AI integration package with full RAG pipeline for astro-minimax blogs — supports OpenAI, Cloudflare AI, and custom providers.",
6
6
  "author": "Souloss",
@@ -69,25 +69,29 @@
69
69
  "types": "./dist/server/index.d.ts",
70
70
  "import": "./dist/server/index.js"
71
71
  },
72
- "./components/*": "./src/components/*",
72
+ "./components/ChatPanel": {
73
+ "types": "./dist/components/ChatPanel.d.ts",
74
+ "import": "./dist/components/ChatPanel.js"
75
+ },
76
+ "./components/AIChatContainer": {
77
+ "types": "./dist/components/AIChatContainer.d.ts",
78
+ "import": "./dist/components/AIChatContainer.js"
79
+ },
80
+ "./components/AIChatWidget.astro": "./dist/components/AIChatWidget.astro",
73
81
  "./styles/source.css": "./src/styles/source.css",
74
82
  "./package.json": "./package.json"
75
83
  },
76
84
  "files": [
77
85
  "dist/",
78
- "src/components/",
79
- "src/providers/mock.ts",
80
- "src/server/types.ts",
81
- "src/utils/i18n.ts",
82
86
  "src/styles/",
83
87
  "README.md"
84
88
  ],
85
89
  "sideEffects": false,
86
90
  "dependencies": {
87
91
  "@ai-sdk/openai-compatible": "^2.0.35",
92
+ "@astro-minimax/notify": "^0.7.5",
88
93
  "ai": "^6.0.116",
89
- "workers-ai-provider": "^3.1.2",
90
- "@astro-minimax/notify": "0.7.4"
94
+ "workers-ai-provider": "^3.1.2"
91
95
  },
92
96
  "optionalDependencies": {
93
97
  "undici": "^6.0.0"
@@ -108,6 +112,7 @@
108
112
  "devDependencies": {
109
113
  "@cloudflare/workers-types": "^4.0.0",
110
114
  "@types/node": "^22.0.0",
115
+ "esbuild": "^0.25.0",
111
116
  "typescript": "^5.9.3"
112
117
  },
113
118
  "engines": {
@@ -115,8 +120,9 @@
115
120
  "pnpm": ">=9.0.0"
116
121
  },
117
122
  "scripts": {
118
- "build": "tsc -p tsconfig.build.json && chmod +x dist/server/dev-server.js",
119
- "build:watch": "tsc -p tsconfig.build.json --watch",
123
+ "build": "node scripts/build.mjs",
124
+ "build:watch": "node scripts/build.mjs --watch",
125
+ "build:components": "node scripts/build-components.mjs",
120
126
  "typecheck": "tsc --noEmit",
121
127
  "clean": "rm -rf dist"
122
128
  }
@@ -1,141 +0,0 @@
1
- export const PUBLIC_QUESTION_PATTERNS = [
2
- {
3
- type: 'tech',
4
- keywords: ['技术栈', '技术', '框架', '用了什么', 'built with', 'tech stack', 'framework'],
5
- patterns: [
6
- /这个博客用了什么/,
7
- /博客.*技术栈/,
8
- /用了什么技术/,
9
- /what.*tech.*stack/,
10
- /built with/,
11
- /用什么框架/,
12
- ],
13
- ttl: 86400,
14
- needsContext: false,
15
- },
16
- {
17
- type: 'recommend',
18
- keywords: ['推荐', '文章推荐', '好文', 'recommend', 'suggest'],
19
- patterns: [
20
- /推荐.*文章/,
21
- /有哪些推荐/,
22
- /文章推荐/,
23
- /recommend.*article/,
24
- /any.*recommend/,
25
- ],
26
- ttl: 1800,
27
- needsContext: false,
28
- },
29
- {
30
- type: 'build',
31
- keywords: ['搭建', '部署', '怎么建', 'how to build', 'deploy', 'setup'],
32
- patterns: [
33
- /怎么搭建/,
34
- /如何搭建/,
35
- /怎么部署/,
36
- /how to build/,
37
- /how to deploy/,
38
- /搭建.*博客/,
39
- ],
40
- ttl: 86400,
41
- needsContext: false,
42
- },
43
- {
44
- type: 'summary',
45
- keywords: ['总结', '概括', '摘要', 'summarize', 'summary', 'tl;dr'],
46
- patterns: [
47
- /总结(一下|这篇文章)/,
48
- /概括(一下|这篇文章)/,
49
- /文章摘要/,
50
- /summarize/,
51
- /summary/,
52
- /主要讲了什么/,
53
- ],
54
- ttl: 14400,
55
- needsContext: true,
56
- },
57
- {
58
- type: 'author',
59
- keywords: ['作者', '博主', '谁', 'author', 'who'],
60
- patterns: [
61
- /作者是谁/,
62
- /博主是谁/,
63
- /关于作者/,
64
- /who.*author/,
65
- /about author/,
66
- ],
67
- ttl: 86400,
68
- needsContext: false,
69
- },
70
- {
71
- type: 'about',
72
- keywords: ['关于', '介绍', 'about', 'intro'],
73
- patterns: [
74
- /关于.*博客/,
75
- /博客介绍/,
76
- /about.*blog/,
77
- /介绍一下/,
78
- ],
79
- ttl: 86400,
80
- needsContext: false,
81
- },
82
- ];
83
- export function detectPublicQuestion(query) {
84
- const normalized = normalizeQuery(query);
85
- let bestMatch = null;
86
- let bestScore = 0;
87
- for (const pattern of PUBLIC_QUESTION_PATTERNS) {
88
- let score = 0;
89
- for (const keyword of pattern.keywords) {
90
- if (normalized.includes(keyword.toLowerCase())) {
91
- score += 1;
92
- }
93
- }
94
- for (const regex of pattern.patterns) {
95
- if (regex.test(normalized)) {
96
- score += 3;
97
- }
98
- }
99
- if (score > bestScore && score >= 2) {
100
- bestScore = score;
101
- const confidence = Math.min(score / 5, 1);
102
- bestMatch = {
103
- type: pattern.type,
104
- confidence,
105
- ttl: pattern.ttl,
106
- needsContext: pattern.needsContext,
107
- };
108
- }
109
- }
110
- return bestMatch;
111
- }
112
- export function buildGlobalCacheKey(type, context) {
113
- const parts = ['global', type];
114
- if (context?.articleSlug) {
115
- parts.push(context.articleSlug);
116
- }
117
- if (context?.lang) {
118
- parts.push(context.lang);
119
- }
120
- return parts.join(':');
121
- }
122
- function normalizeQuery(query) {
123
- return query
124
- .toLowerCase()
125
- .replace(/[??!!。,,.]/g, '')
126
- .replace(/\s+/g, ' ')
127
- .trim();
128
- }
129
- export async function getGlobalSearchCache(cache, type, context) {
130
- const key = buildGlobalCacheKey(type, context);
131
- const entry = await cache.get(key);
132
- return entry?.value ?? null;
133
- }
134
- export async function setGlobalSearchCache(cache, type, data, ttl, context) {
135
- const key = buildGlobalCacheKey(type, context);
136
- await cache.set(key, data, { ttl });
137
- }
138
- export function getGlobalCacheTTL(type) {
139
- const pattern = PUBLIC_QUESTION_PATTERNS.find(p => p.type === type);
140
- return pattern?.ttl ?? 3600;
141
- }
@@ -1,62 +0,0 @@
1
- export { MemoryCacheAdapter, } from './memory-adapter.js';
2
- export { KVCacheAdapter, } from './kv-adapter.js';
3
- export { createCacheKeyBuilder, } from './types.js';
4
- export { detectPublicQuestion, buildGlobalCacheKey, getGlobalSearchCache, setGlobalSearchCache, getGlobalCacheTTL, PUBLIC_QUESTION_PATTERNS, } from './global-cache.js';
5
- export { getResponseCache, setResponseCache, deleteResponseCache, getResponseCacheConfig, buildResponseCacheKey, createResponsePlaybackGenerator, DEFAULT_RESPONSE_CACHE_CONFIG, } from './response-cache.js';
6
- import { MemoryCacheAdapter } from './memory-adapter.js';
7
- import { KVCacheAdapter } from './kv-adapter.js';
8
- const DEFAULT_TTL = 600;
9
- const DEFAULT_MAX_ENTRIES = 400;
10
- let globalMemoryCache = null;
11
- function getGlobalMemoryCache(ttl, maxEntries) {
12
- if (!globalMemoryCache) {
13
- globalMemoryCache = new MemoryCacheAdapter({ defaultTtl: ttl, maxEntries });
14
- }
15
- return globalMemoryCache;
16
- }
17
- export function createCacheAdapter(env, config) {
18
- const ttl = config?.defaultTtl ?? parseTtl(env.CACHE_TTL) ?? DEFAULT_TTL;
19
- const maxEntries = config?.maxEntries ?? DEFAULT_MAX_ENTRIES;
20
- if (isCacheDisabled(env)) {
21
- return getGlobalMemoryCache(ttl, maxEntries);
22
- }
23
- const kvBinding = getKVBinding(env);
24
- if (kvBinding) {
25
- return new KVCacheAdapter(kvBinding, { defaultTtl: ttl });
26
- }
27
- return getGlobalMemoryCache(ttl, maxEntries);
28
- }
29
- function isCacheDisabled(env) {
30
- const val = env.CACHE_DISABLED;
31
- if (val === true || val === 'true' || val === '1') {
32
- return true;
33
- }
34
- return false;
35
- }
36
- function getKVBinding(env) {
37
- const customBinding = env.CACHE_KV_BINDING;
38
- if (customBinding && typeof customBinding === 'string') {
39
- const binding = env[customBinding];
40
- return isKVNamespace(binding) ? binding : null;
41
- }
42
- if (env.CACHE_KV && isKVNamespace(env.CACHE_KV)) {
43
- return env.CACHE_KV;
44
- }
45
- const defaultBinding = env['CACHE_KV'];
46
- return isKVNamespace(defaultBinding) ? defaultBinding : null;
47
- }
48
- function isKVNamespace(value) {
49
- return (typeof value === 'object' &&
50
- value !== null &&
51
- 'get' in value &&
52
- 'put' in value &&
53
- 'delete' in value);
54
- }
55
- function parseTtl(value) {
56
- if (value === undefined)
57
- return undefined;
58
- if (typeof value === 'number')
59
- return value;
60
- const parsed = parseInt(value, 10);
61
- return isNaN(parsed) ? undefined : parsed;
62
- }
@@ -1,102 +0,0 @@
1
- const DEFAULT_TTL_SECONDS = 600;
2
- const MIN_TTL_SECONDS = 60;
3
- export class KVCacheAdapter {
4
- name = 'cloudflare-kv';
5
- kv;
6
- defaultTtl;
7
- prefix;
8
- constructor(kv, options) {
9
- this.kv = kv;
10
- this.defaultTtl = options?.defaultTtl ?? DEFAULT_TTL_SECONDS;
11
- this.prefix = options?.prefix ?? '';
12
- }
13
- buildKey(key) {
14
- return this.prefix ? `${this.prefix}:${key}` : key;
15
- }
16
- async get(key, options) {
17
- try {
18
- const fullKey = this.buildKey(key);
19
- const result = await this.kv.getWithMetadata(fullKey, 'json');
20
- if (!result.value) {
21
- return null;
22
- }
23
- const storedEntry = result.value;
24
- if (!storedEntry.value || !storedEntry.metadata) {
25
- return null;
26
- }
27
- return {
28
- value: storedEntry.value,
29
- metadata: storedEntry.metadata,
30
- };
31
- }
32
- catch (error) {
33
- if (!options?.silent) {
34
- console.error('[KVCacheAdapter] Get error:', error);
35
- }
36
- return null;
37
- }
38
- }
39
- async set(key, value, options) {
40
- try {
41
- const now = Date.now();
42
- const ttl = options?.ttl ?? this.defaultTtl;
43
- const entry = {
44
- value,
45
- metadata: {
46
- createdAt: now,
47
- updatedAt: now,
48
- custom: options?.metadata,
49
- },
50
- };
51
- const fullKey = this.buildKey(key);
52
- const effectiveTtl = Math.max(ttl, MIN_TTL_SECONDS);
53
- await this.kv.put(fullKey, JSON.stringify(entry), {
54
- expirationTtl: effectiveTtl,
55
- });
56
- }
57
- catch (error) {
58
- console.error('[KVCacheAdapter] Set error:', error);
59
- throw error;
60
- }
61
- }
62
- async delete(key) {
63
- try {
64
- const fullKey = this.buildKey(key);
65
- const existing = await this.kv.get(fullKey);
66
- if (existing === null) {
67
- return false;
68
- }
69
- await this.kv.delete(fullKey);
70
- return true;
71
- }
72
- catch (error) {
73
- console.error('[KVCacheAdapter] Delete error:', error);
74
- return false;
75
- }
76
- }
77
- async clear() {
78
- console.warn('[KVCacheAdapter] Clear not supported for KV namespace');
79
- }
80
- async has(key) {
81
- try {
82
- const fullKey = this.buildKey(key);
83
- const value = await this.kv.get(fullKey);
84
- return value !== null;
85
- }
86
- catch {
87
- return false;
88
- }
89
- }
90
- async isAvailable() {
91
- try {
92
- await this.kv.get('__health_check__');
93
- return true;
94
- }
95
- catch {
96
- return false;
97
- }
98
- }
99
- dispose() {
100
- // KV adapter doesn't hold any resources that need cleanup
101
- }
102
- }
@@ -1,95 +0,0 @@
1
- const DEFAULT_MAX_ENTRIES = 400;
2
- const DEFAULT_TTL_SECONDS = 600;
3
- export class MemoryCacheAdapter {
4
- name = 'memory';
5
- cache = new Map();
6
- maxEntries;
7
- defaultTtl;
8
- cleanupTimer;
9
- constructor(options) {
10
- this.maxEntries = options?.maxEntries ?? DEFAULT_MAX_ENTRIES;
11
- this.defaultTtl = options?.defaultTtl ?? DEFAULT_TTL_SECONDS;
12
- if (options?.cleanupInterval) {
13
- this.cleanupTimer = setInterval(() => this.cleanup(), options.cleanupInterval * 1000);
14
- }
15
- }
16
- async get(key, _options) {
17
- const entry = this.cache.get(key);
18
- if (!entry)
19
- return null;
20
- if (entry.expiresAt && Date.now() > entry.expiresAt) {
21
- this.cache.delete(key);
22
- return null;
23
- }
24
- this.cache.delete(key);
25
- this.cache.set(key, entry);
26
- return {
27
- value: entry.value,
28
- metadata: entry.metadata,
29
- };
30
- }
31
- async set(key, value, options) {
32
- const now = Date.now();
33
- const ttl = options?.ttl ?? this.defaultTtl;
34
- const entry = {
35
- value,
36
- metadata: {
37
- createdAt: now,
38
- updatedAt: now,
39
- custom: options?.metadata,
40
- },
41
- expiresAt: ttl ? now + ttl * 1000 : undefined,
42
- };
43
- this.cache.delete(key);
44
- this.cache.set(key, entry);
45
- if (this.cache.size > this.maxEntries) {
46
- this.evictLRU();
47
- }
48
- }
49
- async delete(key) {
50
- return this.cache.delete(key);
51
- }
52
- async clear() {
53
- this.cache.clear();
54
- }
55
- async has(key) {
56
- const entry = this.cache.get(key);
57
- if (!entry)
58
- return false;
59
- if (entry.expiresAt && Date.now() > entry.expiresAt) {
60
- this.cache.delete(key);
61
- return false;
62
- }
63
- return true;
64
- }
65
- async isAvailable() {
66
- return true;
67
- }
68
- cleanup() {
69
- const now = Date.now();
70
- for (const [key, entry] of this.cache) {
71
- if (entry.expiresAt && now > entry.expiresAt) {
72
- this.cache.delete(key);
73
- }
74
- }
75
- }
76
- evictLRU() {
77
- const overflow = this.cache.size - this.maxEntries;
78
- if (overflow <= 0)
79
- return;
80
- const keys = this.cache.keys();
81
- for (let i = 0; i < overflow; i++) {
82
- const next = keys.next();
83
- if (next.done)
84
- break;
85
- this.cache.delete(next.value);
86
- }
87
- }
88
- dispose() {
89
- if (this.cleanupTimer) {
90
- clearInterval(this.cleanupTimer);
91
- this.cleanupTimer = undefined;
92
- }
93
- this.cache.clear();
94
- }
95
- }
@@ -1,85 +0,0 @@
1
- export const DEFAULT_RESPONSE_CACHE_CONFIG = {
2
- enabled: false,
3
- defaultTtl: 3600,
4
- playbackDelayMs: 20,
5
- chunkSize: 15,
6
- thinkingPlaybackDelayMs: 5,
7
- };
8
- export function getResponseCacheConfig(env) {
9
- const parseBool = (val) => {
10
- if (val === undefined)
11
- return false;
12
- if (typeof val === 'boolean')
13
- return val;
14
- if (typeof val === 'string')
15
- return val === 'true' || val === '1';
16
- return false;
17
- };
18
- const parseNum = (val, defaultVal) => {
19
- if (val === undefined)
20
- return defaultVal;
21
- if (typeof val === 'number')
22
- return val;
23
- if (typeof val === 'string') {
24
- const num = parseInt(val, 10);
25
- return isNaN(num) ? defaultVal : num;
26
- }
27
- return defaultVal;
28
- };
29
- return {
30
- enabled: parseBool(env.AI_RESPONSE_CACHE_ENABLED),
31
- defaultTtl: parseNum(env.AI_RESPONSE_CACHE_TTL, 3600),
32
- playbackDelayMs: parseNum(env.AI_RESPONSE_CACHE_PLAYBACK_DELAY, 20),
33
- chunkSize: parseNum(env.AI_RESPONSE_CACHE_CHUNK_SIZE, 15),
34
- thinkingPlaybackDelayMs: parseNum(env.AI_RESPONSE_CACHE_THINKING_DELAY, 5),
35
- };
36
- }
37
- const RESPONSE_CACHE_PREFIX = 'response';
38
- export function buildResponseCacheKey(type, context) {
39
- const parts = [RESPONSE_CACHE_PREFIX, type];
40
- if (context?.articleSlug)
41
- parts.push(context.articleSlug);
42
- if (context?.lang)
43
- parts.push(context.lang);
44
- return parts.join(':');
45
- }
46
- export async function getResponseCache(cache, type, context) {
47
- const key = buildResponseCacheKey(type, context);
48
- const entry = await cache.get(key);
49
- return entry?.value ?? null;
50
- }
51
- export async function setResponseCache(cache, type, data, ttl, context) {
52
- const key = buildResponseCacheKey(type, context);
53
- await cache.set(key, data, { ttl });
54
- }
55
- export async function deleteResponseCache(cache, type, context) {
56
- const key = buildResponseCacheKey(type, context);
57
- return cache.delete(key);
58
- }
59
- export function createResponsePlaybackGenerator(cached, config) {
60
- const { playbackDelayMs, chunkSize, thinkingPlaybackDelayMs } = config;
61
- return (async function* () {
62
- if (cached.thinking) {
63
- const thinkingChunks = Math.ceil(cached.thinking.length / chunkSize);
64
- for (let i = 0; i < thinkingChunks; i++) {
65
- const chunk = cached.thinking.slice(i * chunkSize, (i + 1) * chunkSize);
66
- if (chunk) {
67
- yield { type: 'thinking', text: chunk };
68
- if (i < thinkingChunks - 1 && thinkingPlaybackDelayMs > 0) {
69
- await new Promise(resolve => setTimeout(resolve, thinkingPlaybackDelayMs));
70
- }
71
- }
72
- }
73
- }
74
- const responseChunks = Math.ceil(cached.response.length / chunkSize);
75
- for (let i = 0; i < responseChunks; i++) {
76
- const chunk = cached.response.slice(i * chunkSize, (i + 1) * chunkSize);
77
- if (chunk) {
78
- yield { type: 'response', text: chunk };
79
- if (i < responseChunks - 1 && playbackDelayMs > 0) {
80
- await new Promise(resolve => setTimeout(resolve, playbackDelayMs));
81
- }
82
- }
83
- }
84
- })();
85
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * @astro-minimax/ai
3
- *
4
- * Cache abstraction layer for AI conversation system.
5
- * Supports multiple storage backends (memory, Cloudflare KV).
6
- *
7
- * @module cache/types
8
- */
9
- /**
10
- * Default cache key builder implementation.
11
- */
12
- export const createCacheKeyBuilder = (prefix = 'chat') => ({
13
- session: (sessionId) => `${prefix}:sid:${sessionId}`,
14
- article: (sessionId, slug) => `${prefix}:sid:${sessionId}:article:${slug}`,
15
- custom: (...parts) => `${prefix}:${parts.join(':')}`,
16
- });
@@ -1,66 +0,0 @@
1
- import { loadFactRegistry as loadFactRegistryCache } from '../fact-registry/registry.js';
2
- import { loadVectorIndex as loadVectorIndexCache } from '../search/vector-reranker.js';
3
- // Lazy-loaded, memory-cached metadata
4
- let cachedMetadata = null;
5
- /**
6
- * Pre-loads metadata synchronously from imported JSON objects.
7
- * Use this at function initialization time in edge environments.
8
- *
9
- * Example (in functions/lib/ai.ts):
10
- * import summaries from '../../datas/ai-summaries.json' with { type: 'json' };
11
- * preloadMetadata({ summaries, authorContext, voiceProfile, factRegistry });
12
- */
13
- export function preloadMetadata(data) {
14
- cachedMetadata = {
15
- summaries: data.summaries ?? null,
16
- authorContext: data.authorContext ?? null,
17
- voiceProfile: data.voiceProfile ?? null,
18
- factRegistry: data.factRegistry ?? null,
19
- vectorIndex: data.vectorIndex ?? null,
20
- };
21
- if (cachedMetadata.factRegistry) {
22
- loadFactRegistryCache(cachedMetadata.factRegistry);
23
- }
24
- if (cachedMetadata.vectorIndex) {
25
- loadVectorIndexCache(cachedMetadata.vectorIndex);
26
- }
27
- }
28
- /**
29
- * Clears the metadata cache and all associated sub-caches (useful for testing).
30
- */
31
- export function clearMetadataCache() {
32
- cachedMetadata = null;
33
- loadFactRegistryCache(null);
34
- loadVectorIndexCache(null);
35
- }
36
- /**
37
- * Returns the cached metadata. Must call preloadMetadata() first.
38
- */
39
- export function getMetadata() {
40
- return cachedMetadata ?? { summaries: null, authorContext: null, voiceProfile: null, factRegistry: null, vectorIndex: null };
41
- }
42
- /**
43
- * Returns the AI-generated summary for an article by its slug.
44
- */
45
- export function getArticleSummary(slug) {
46
- return cachedMetadata?.summaries?.articles[slug]?.data;
47
- }
48
- /**
49
- * Returns all article summaries as a flat array.
50
- */
51
- export function getAllSummaries() {
52
- const articles = cachedMetadata?.summaries?.articles ?? {};
53
- return Object.entries(articles).map(([slug, entry]) => ({ slug, ...entry.data }));
54
- }
55
- /**
56
- * Returns the author context (name, site URL, recent posts list).
57
- */
58
- export function getAuthorContext() {
59
- return cachedMetadata?.authorContext ?? null;
60
- }
61
- /**
62
- * Returns the author's voice/style profile.
63
- */
64
- export function getVoiceProfile() {
65
- return cachedMetadata?.voiceProfile ?? null;
66
- }
@@ -1 +0,0 @@
1
- export {};