@astro-minimax/ai 0.5.0 → 0.7.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.
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Stream helper utilities for chat-handler.
3
+ *
4
+ * Extracts duplicated stream-writing logic into reusable functions,
5
+ * eliminating 34+ `as never` casts and reducing chat-handler.ts size.
6
+ */
7
+ import { streamText, convertToModelMessages, } from 'ai';
8
+ import { t } from '../utils/i18n.js';
9
+ import { createChatStatusData } from './types.js';
10
+ import { createResponsePlaybackGenerator } from '../cache/response-cache.js';
11
+ // ── Metadata Writers ──────────────────────────────────────
12
+ export function writeSearchStatus(writer, count, lang) {
13
+ writer.write({
14
+ type: 'message-metadata',
15
+ messageMetadata: createChatStatusData({
16
+ stage: 'search',
17
+ message: t('ai.status.found', lang, { count }),
18
+ progress: 40,
19
+ }),
20
+ });
21
+ }
22
+ export function writeGeneratingStatus(writer, lang, progress = 60) {
23
+ writer.write({
24
+ type: 'message-metadata',
25
+ messageMetadata: createChatStatusData({
26
+ stage: 'answer',
27
+ message: t('ai.status.generating', lang),
28
+ progress,
29
+ }),
30
+ });
31
+ }
32
+ export function writeDoneStatus(writer, lang) {
33
+ writer.write({
34
+ type: 'message-metadata',
35
+ messageMetadata: createChatStatusData({
36
+ stage: 'answer',
37
+ message: t('ai.status.generating', lang),
38
+ progress: 100,
39
+ done: true,
40
+ }),
41
+ });
42
+ }
43
+ export function writeSourceArticles(writer, articles, max = 3) {
44
+ for (const article of articles.slice(0, max)) {
45
+ try {
46
+ writer.write({
47
+ type: 'source-url',
48
+ sourceId: `source-${article.title}`,
49
+ url: article.url ?? '#',
50
+ title: article.title,
51
+ });
52
+ }
53
+ catch { /* best-effort */ }
54
+ }
55
+ }
56
+ export function writeTextChunk(writer, text, idPrefix = 'text') {
57
+ const id = `${idPrefix}-${Date.now()}`;
58
+ writer.write({ type: 'text-start', id });
59
+ writer.write({ type: 'text-delta', id, delta: text });
60
+ writer.write({ type: 'text-end', id });
61
+ }
62
+ export function writeFinish(writer, reason = 'stop') {
63
+ writer.write({ type: 'finish', finishReason: reason });
64
+ }
65
+ // ── LLM Streaming ─────────────────────────────────────────
66
+ export async function streamLLMResponse(params) {
67
+ const { writer, adapter, systemPrompt, messages, lang, temperature = 0.3, maxOutputTokens = 2500, } = params;
68
+ const start = Date.now();
69
+ try {
70
+ const provider = adapter.getProvider();
71
+ const result = streamText({
72
+ model: provider.chatModel(adapter.model),
73
+ system: systemPrompt,
74
+ messages: await convertToModelMessages(messages),
75
+ temperature,
76
+ maxOutputTokens,
77
+ onError: ({ error }) => {
78
+ console.error('[stream-helpers] streamText error:', error);
79
+ },
80
+ });
81
+ const streamErrors = [];
82
+ writer.merge(result.toUIMessageStream({ sendFinish: false }));
83
+ await result.consumeStream({
84
+ onError: (error) => {
85
+ streamErrors.push(error instanceof Error ? error : new Error(String(error)));
86
+ },
87
+ });
88
+ const text = await result.text;
89
+ let reasoningText;
90
+ const reasoningPromise = result.reasoning;
91
+ if (reasoningPromise) {
92
+ try {
93
+ const reasoningOutput = await Promise.resolve(reasoningPromise);
94
+ reasoningText = typeof reasoningOutput === 'string'
95
+ ? reasoningOutput
96
+ : (Array.isArray(reasoningOutput)
97
+ ? reasoningOutput.map((r) => {
98
+ if (typeof r === 'object' && r !== null && 'text' in r)
99
+ return r.text;
100
+ return String(r);
101
+ }).join('')
102
+ : undefined);
103
+ }
104
+ catch { /* reasoning is optional */ }
105
+ }
106
+ let tokenUsage;
107
+ const usagePromise = result.usage;
108
+ if (usagePromise) {
109
+ try {
110
+ const usage = await Promise.resolve(usagePromise);
111
+ const inputTokens = usage.inputTokens ?? 0;
112
+ const outputTokens = usage.outputTokens ?? 0;
113
+ tokenUsage = {
114
+ total: usage.totalTokens ?? inputTokens + outputTokens,
115
+ input: inputTokens,
116
+ output: outputTokens,
117
+ };
118
+ }
119
+ catch { /* usage is optional */ }
120
+ }
121
+ const generationMs = Date.now() - start;
122
+ if (streamErrors.length > 0) {
123
+ adapter.recordFailure(streamErrors[0]);
124
+ writeTextChunk(writer, t('ai.error.generic', lang), 'error');
125
+ writeFinish(writer, 'error');
126
+ return { success: true, responseText: text, reasoningText, tokenUsage, generationMs };
127
+ }
128
+ if (text.length > 0) {
129
+ adapter.recordSuccess();
130
+ writeFinish(writer);
131
+ return { success: true, responseText: text, reasoningText, tokenUsage, generationMs };
132
+ }
133
+ writeTextChunk(writer, t('ai.error.noOutput', lang), 'no-output');
134
+ writeFinish(writer);
135
+ return { success: true, responseText: '', reasoningText, tokenUsage, generationMs };
136
+ }
137
+ catch (err) {
138
+ adapter.recordFailure(err instanceof Error ? err : new Error(String(err)));
139
+ console.error('[stream-helpers] Provider threw:', err.message);
140
+ return { success: false, responseText: '', generationMs: Date.now() - start };
141
+ }
142
+ }
143
+ // ── Mock Fallback ─────────────────────────────────────────
144
+ export async function streamMockFallback(writer, question, lang) {
145
+ const { getMockResponse } = await import('../providers/mock.js');
146
+ const mockText = getMockResponse(question, lang);
147
+ writer.write({
148
+ type: 'message-metadata',
149
+ messageMetadata: createChatStatusData({
150
+ stage: 'answer',
151
+ message: t('ai.status.fallback', lang),
152
+ progress: 80,
153
+ }),
154
+ });
155
+ writeTextChunk(writer, mockText, 'fallback');
156
+ writeFinish(writer);
157
+ return mockText;
158
+ }
159
+ // ── Cached Response Playback ──────────────────────────────
160
+ export async function streamCachedResponse(writer, cachedResponse, config, lang) {
161
+ writeSearchStatus(writer, cachedResponse.articles.length + cachedResponse.projects.length, lang);
162
+ writeGeneratingStatus(writer, lang);
163
+ writeSourceArticles(writer, cachedResponse.articles);
164
+ writeGeneratingStatus(writer, lang, 70);
165
+ const playbackGenerator = createResponsePlaybackGenerator(cachedResponse, config);
166
+ let thinkingId;
167
+ const textId = `text-${Date.now()}`;
168
+ let textStarted = false;
169
+ for await (const chunk of playbackGenerator) {
170
+ if (chunk.type === 'thinking') {
171
+ if (!thinkingId) {
172
+ thinkingId = `thinking-${Date.now()}`;
173
+ writer.write({ type: 'reasoning-start', id: thinkingId });
174
+ }
175
+ writer.write({ type: 'reasoning-delta', id: thinkingId, delta: chunk.text });
176
+ }
177
+ else {
178
+ if (thinkingId) {
179
+ writer.write({ type: 'reasoning-end', id: thinkingId });
180
+ thinkingId = undefined;
181
+ }
182
+ if (!textStarted) {
183
+ writer.write({ type: 'text-start', id: textId });
184
+ textStarted = true;
185
+ }
186
+ writer.write({ type: 'text-delta', id: textId, delta: chunk.text });
187
+ }
188
+ }
189
+ if (thinkingId) {
190
+ writer.write({ type: 'reasoning-end', id: thinkingId });
191
+ }
192
+ if (textStarted) {
193
+ writer.write({ type: 'text-end', id: textId });
194
+ }
195
+ writeDoneStatus(writer, lang);
196
+ writeFinish(writer);
197
+ }
@@ -28,6 +28,7 @@ export interface ChatHandlerEnv extends ProviderManagerEnv, CacheEnv {
28
28
  export interface ChatHandlerOptions {
29
29
  env: ChatHandlerEnv;
30
30
  request: Request;
31
+ waitUntil?: (promise: Promise<unknown>) => void;
31
32
  }
32
33
  export type ChatStatusStage = 'search' | 'answer' | 'complete';
33
34
  export interface ChatStatusData {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAIlD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAID,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAe,SAAQ,kBAAkB,EAAE,QAAQ;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,cAAc,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CAClB;AAID,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAChE,cAAc,CAMhB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAIxE;AAID,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAIlD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAID,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAe,SAAQ,kBAAkB,EAAE,QAAQ;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,cAAc,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;CACjD;AAID,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAChE,cAAc,CAMhB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAIxE;AAID,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
@@ -2,7 +2,7 @@
2
2
  * AI Package Internationalization
3
3
  * Follows the same pattern as packages/core/src/utils/i18n.ts
4
4
  */
5
- export type AITranslationKey = "ai.reasoning.thinking" | "ai.reasoning.viewReasoning" | "ai.reasoning.waiting" | "ai.error.network" | "ai.error.aborted" | "ai.error.rateLimit" | "ai.error.unavailable" | "ai.error.generic" | "ai.error.format" | "ai.error.noOutput" | "ai.placeholder" | "ai.clear" | "ai.clearConversation" | "ai.close" | "ai.closeChat" | "ai.retry" | "ai.status.searching" | "ai.status.generating" | "ai.status.found" | "ai.status.citation" | "ai.status.fallback" | "ai.prompt.techStack" | "ai.prompt.recommend" | "ai.prompt.build" | "ai.prompt.summarize" | "ai.prompt.explain" | "ai.prompt.related" | "ai.welcome.reading" | "ai.welcome.canHelp" | "ai.welcome.greeting" | "ai.welcome.demo" | "ai.welcome.demoHint" | "ai.welcome.demoPrompt" | "ai.header.reading" | "ai.header.mode" | "ai.assistantName" | "ai.status.live" | "ai.error.emptyMessage" | "ai.error.emptyContent" | "ai.error.inputTooLong" | "ai.error.timeout" | "ai.error.rateLimit.burst" | "ai.error.rateLimit.sustained" | "ai.error.rateLimit.daily" | "ai.prompt.section.responsibilities" | "ai.prompt.section.format" | "ai.prompt.section.principles" | "ai.prompt.section.constraints";
5
+ export type AITranslationKey = "ai.reasoning.thinking" | "ai.reasoning.viewReasoning" | "ai.reasoning.waiting" | "ai.error.network" | "ai.error.aborted" | "ai.error.rateLimit" | "ai.error.unavailable" | "ai.error.generic" | "ai.error.format" | "ai.error.noOutput" | "ai.placeholder" | "ai.clear" | "ai.clearConversation" | "ai.close" | "ai.closeChat" | "ai.retry" | "ai.status.searching" | "ai.status.generating" | "ai.status.found" | "ai.status.citation" | "ai.status.fallback" | "ai.prompt.techStack" | "ai.prompt.recommend" | "ai.prompt.build" | "ai.prompt.summarize" | "ai.prompt.explain" | "ai.prompt.related" | "ai.welcome.reading" | "ai.welcome.canHelp" | "ai.welcome.greeting" | "ai.welcome.demo" | "ai.welcome.demoHint" | "ai.welcome.demoPrompt" | "ai.header.reading" | "ai.header.mode" | "ai.assistantName" | "ai.status.live" | "ai.error.emptyMessage" | "ai.error.emptyContent" | "ai.error.inputTooLong" | "ai.error.timeout" | "ai.error.rateLimit.burst" | "ai.error.rateLimit.sustained" | "ai.error.rateLimit.daily" | "ai.prompt.section.responsibilities" | "ai.prompt.section.format" | "ai.prompt.section.principles" | "ai.prompt.section.constraints" | "ai.prompt.section.sourceLayers" | "ai.prompt.section.privacy" | "ai.prompt.section.answerModes" | "ai.prompt.section.preOutputChecks";
6
6
  /**
7
7
  * Get translation by key.
8
8
  * @param key - Translation key (type-safe)
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/utils/i18n.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,gBAAgB,GAExB,uBAAuB,GACvB,4BAA4B,GAC5B,sBAAsB,GAEtB,kBAAkB,GAClB,kBAAkB,GAClB,oBAAoB,GACpB,sBAAsB,GACtB,kBAAkB,GAClB,iBAAiB,GACjB,mBAAmB,GAEnB,gBAAgB,GAChB,UAAU,GACV,sBAAsB,GACtB,UAAU,GACV,cAAc,GACd,UAAU,GACV,qBAAqB,GACrB,sBAAsB,GACtB,iBAAiB,GACjB,oBAAoB,GACpB,oBAAoB,GAEpB,qBAAqB,GACrB,qBAAqB,GACrB,iBAAiB,GACjB,qBAAqB,GACrB,mBAAmB,GACnB,mBAAmB,GAEnB,oBAAoB,GACpB,oBAAoB,GACpB,qBAAqB,GACrB,iBAAiB,GACjB,qBAAqB,GACrB,uBAAuB,GAEvB,mBAAmB,GACnB,gBAAgB,GAEhB,kBAAkB,GAClB,gBAAgB,GAEhB,uBAAuB,GACvB,uBAAuB,GACvB,uBAAuB,GACvB,kBAAkB,GAElB,0BAA0B,GAC1B,8BAA8B,GAC9B,0BAA0B,GAE1B,oCAAoC,GACpC,0BAA0B,GAC1B,8BAA8B,GAC9B,+BAA+B,CAAC;AA2HpC;;;;;GAKG;AACH,wBAAgB,CAAC,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,GAAE,MAAa,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM,CAY5G;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/utils/i18n.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,gBAAgB,GAExB,uBAAuB,GACvB,4BAA4B,GAC5B,sBAAsB,GAEtB,kBAAkB,GAClB,kBAAkB,GAClB,oBAAoB,GACpB,sBAAsB,GACtB,kBAAkB,GAClB,iBAAiB,GACjB,mBAAmB,GAEnB,gBAAgB,GAChB,UAAU,GACV,sBAAsB,GACtB,UAAU,GACV,cAAc,GACd,UAAU,GACV,qBAAqB,GACrB,sBAAsB,GACtB,iBAAiB,GACjB,oBAAoB,GACpB,oBAAoB,GAEpB,qBAAqB,GACrB,qBAAqB,GACrB,iBAAiB,GACjB,qBAAqB,GACrB,mBAAmB,GACnB,mBAAmB,GAEnB,oBAAoB,GACpB,oBAAoB,GACpB,qBAAqB,GACrB,iBAAiB,GACjB,qBAAqB,GACrB,uBAAuB,GAEvB,mBAAmB,GACnB,gBAAgB,GAEhB,kBAAkB,GAClB,gBAAgB,GAEhB,uBAAuB,GACvB,uBAAuB,GACvB,uBAAuB,GACvB,kBAAkB,GAElB,0BAA0B,GAC1B,8BAA8B,GAC9B,0BAA0B,GAE1B,oCAAoC,GACpC,0BAA0B,GAC1B,8BAA8B,GAC9B,+BAA+B,GAC/B,gCAAgC,GAChC,2BAA2B,GAC3B,+BAA+B,GAC/B,mCAAmC,CAAC;AAmIxC;;;;;GAKG;AACH,wBAAgB,CAAC,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,GAAE,MAAa,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM,CAY5G;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C"}
@@ -61,6 +61,10 @@ const translations = {
61
61
  "ai.prompt.section.format": "Response Format",
62
62
  "ai.prompt.section.principles": "Recommendation Principles",
63
63
  "ai.prompt.section.constraints": "Constraints",
64
+ "ai.prompt.section.sourceLayers": "Source Priority Protocol (must follow)",
65
+ "ai.prompt.section.privacy": "Privacy Protection",
66
+ "ai.prompt.section.answerModes": "Answer Mode Guide (follow detected mode)",
67
+ "ai.prompt.section.preOutputChecks": "Pre-Output Checks (execute mentally, do not output steps)",
64
68
  },
65
69
  zh: {
66
70
  // Reasoning UI
@@ -120,6 +124,10 @@ const translations = {
120
124
  "ai.prompt.section.format": "回答格式",
121
125
  "ai.prompt.section.principles": "推荐原则",
122
126
  "ai.prompt.section.constraints": "约束",
127
+ "ai.prompt.section.sourceLayers": "来源分层协议(必须遵守)",
128
+ "ai.prompt.section.privacy": "隐私保护",
129
+ "ai.prompt.section.answerModes": "回答模式指导(按检测到的模式执行)",
130
+ "ai.prompt.section.preOutputChecks": "输出前检查(在心里执行,不输出步骤)",
123
131
  },
124
132
  };
125
133
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astro-minimax/ai",
3
- "version": "0.5.0",
3
+ "version": "0.7.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",
@@ -80,7 +80,7 @@
80
80
  "@ai-sdk/openai-compatible": "^2.0.35",
81
81
  "ai": "^6.0.116",
82
82
  "workers-ai-provider": "^3.1.2",
83
- "@astro-minimax/notify": "0.5.0"
83
+ "@astro-minimax/notify": "0.7.0"
84
84
  },
85
85
  "optionalDependencies": {
86
86
  "undici": "^6.0.0"