@astro-minimax/ai 0.9.0 → 0.9.3
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/README.md +108 -18
- package/dist/cache/global-cache.d.ts +6 -2
- package/dist/cache/global-cache.d.ts.map +1 -1
- package/dist/cache/global-cache.js +24 -9
- package/dist/cache/index.d.ts +7 -6
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +12 -4
- package/dist/cache/injection-cache.d.ts +36 -0
- package/dist/cache/injection-cache.d.ts.map +1 -0
- package/dist/cache/injection-cache.js +90 -0
- package/dist/cache/kv-adapter.d.ts.map +1 -1
- package/dist/cache/kv-adapter.js +2 -1
- package/dist/cache/memory-adapter.d.ts.map +1 -1
- package/dist/cache/memory-adapter.js +2 -1
- package/dist/cache/response-cache.d.ts +10 -5
- package/dist/cache/response-cache.d.ts.map +1 -1
- package/dist/cache/response-cache.js +18 -6
- package/dist/components/AIChatContainer.d.ts +2 -2
- package/dist/components/AIChatContainer.d.ts.map +1 -1
- package/dist/components/AIChatContainer.js +8 -920
- package/dist/components/ChatInput.d.ts +15 -0
- package/dist/components/ChatInput.d.ts.map +1 -0
- package/dist/components/ChatInput.js +72 -0
- package/dist/components/ChatPanel.d.ts +1 -1
- package/dist/components/ChatPanel.d.ts.map +1 -1
- package/dist/components/ChatPanel.js +210 -672
- package/dist/components/CodeBlock.d.ts +31 -0
- package/dist/components/CodeBlock.d.ts.map +1 -0
- package/dist/components/CodeBlock.js +143 -0
- package/dist/components/MarkmapBlock.d.ts +4 -0
- package/dist/components/MarkmapBlock.d.ts.map +1 -0
- package/dist/components/MarkmapBlock.js +180 -0
- package/dist/components/MermaidBlock.d.ts +4 -0
- package/dist/components/MermaidBlock.d.ts.map +1 -0
- package/dist/components/MermaidBlock.js +193 -0
- package/dist/components/MessageBubble.d.ts +21 -0
- package/dist/components/MessageBubble.d.ts.map +1 -0
- package/dist/components/MessageBubble.js +233 -0
- package/dist/components/ReasoningBlock.d.ts +6 -0
- package/dist/components/ReasoningBlock.d.ts.map +1 -0
- package/dist/components/ReasoningBlock.js +11 -0
- package/dist/components/RichText.d.ts +41 -0
- package/dist/components/RichText.d.ts.map +1 -0
- package/dist/components/RichText.js +202 -0
- package/dist/components/VizShared.d.ts +57 -0
- package/dist/components/VizShared.d.ts.map +1 -0
- package/dist/components/VizShared.js +233 -0
- package/dist/components/tool-auto-continue.d.ts +5 -0
- package/dist/components/tool-auto-continue.d.ts.map +1 -0
- package/dist/components/tool-auto-continue.js +33 -0
- package/dist/constants.d.ts +61 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +72 -0
- package/dist/data/index.d.ts +4 -3
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +4 -10
- package/dist/data/knowledge-types.d.ts +8 -0
- package/dist/data/knowledge-types.d.ts.map +1 -0
- package/dist/data/knowledge-types.js +14 -0
- package/dist/data/metadata-loader.d.ts +4 -28
- package/dist/data/metadata-loader.d.ts.map +1 -1
- package/dist/data/metadata-loader.js +11 -34
- package/dist/data/types.d.ts +17 -2
- package/dist/data/types.d.ts.map +1 -1
- package/dist/extensions/index.d.ts +5 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +24 -0
- package/dist/extensions/injector.d.ts +14 -0
- package/dist/extensions/injector.d.ts.map +1 -0
- package/dist/extensions/injector.js +146 -0
- package/dist/extensions/loader.d.ts +5 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +45 -0
- package/dist/extensions/registry.d.ts +4 -0
- package/dist/extensions/registry.d.ts.map +1 -0
- package/dist/extensions/registry.js +144 -0
- package/dist/extensions/types.d.ts +126 -0
- package/dist/extensions/types.d.ts.map +1 -0
- package/dist/extensions/types.js +0 -0
- package/dist/fact-registry/prompt-injector.d.ts +1 -1
- package/dist/fact-registry/prompt-injector.d.ts.map +1 -1
- package/dist/fact-registry/prompt-injector.js +2 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/intelligence/citation-guard.d.ts +2 -13
- package/dist/intelligence/citation-guard.d.ts.map +1 -1
- package/dist/intelligence/citation-guard.js +52 -23
- package/dist/intelligence/evidence-analysis.d.ts +24 -16
- package/dist/intelligence/evidence-analysis.d.ts.map +1 -1
- package/dist/intelligence/evidence-analysis.js +118 -20
- package/dist/intelligence/evidence-budget.d.ts +13 -0
- package/dist/intelligence/evidence-budget.d.ts.map +1 -0
- package/dist/intelligence/evidence-budget.js +49 -0
- package/dist/intelligence/index.d.ts +10 -4
- package/dist/intelligence/index.d.ts.map +1 -1
- package/dist/intelligence/index.js +27 -3
- package/dist/intelligence/keyword-extract.d.ts +1 -1
- package/dist/intelligence/keyword-extract.d.ts.map +1 -1
- package/dist/intelligence/keyword-extract.js +5 -9
- package/dist/intelligence/request-interpretation.d.ts +40 -0
- package/dist/intelligence/request-interpretation.d.ts.map +1 -0
- package/dist/intelligence/request-interpretation.js +71 -0
- package/dist/intelligence/response-templates.d.ts +1 -0
- package/dist/intelligence/response-templates.d.ts.map +1 -1
- package/dist/intelligence/response-templates.js +13 -0
- package/dist/prompt/dynamic-layer.d.ts +1 -5
- package/dist/prompt/dynamic-layer.d.ts.map +1 -1
- package/dist/prompt/dynamic-layer.js +145 -9
- package/dist/prompt/prompt-builder.d.ts +1 -1
- package/dist/prompt/prompt-builder.d.ts.map +1 -1
- package/dist/prompt/prompt-builder.js +5 -1
- package/dist/prompt/semi-static-layer.d.ts +1 -1
- package/dist/prompt/semi-static-layer.d.ts.map +1 -1
- package/dist/prompt/semi-static-layer.js +22 -12
- package/dist/prompt/static-layer.d.ts.map +1 -1
- package/dist/prompt/static-layer.js +37 -4
- package/dist/prompt/types.d.ts +9 -4
- package/dist/prompt/types.d.ts.map +1 -1
- package/dist/provider-manager/base.d.ts +5 -1
- package/dist/provider-manager/base.d.ts.map +1 -1
- package/dist/provider-manager/base.js +22 -2
- package/dist/provider-manager/config.d.ts.map +1 -1
- package/dist/provider-manager/config.js +3 -2
- package/dist/provider-manager/index.d.ts +1 -1
- package/dist/provider-manager/index.d.ts.map +1 -1
- package/dist/provider-manager/index.js +1 -2
- package/dist/provider-manager/manager.d.ts +10 -1
- package/dist/provider-manager/manager.d.ts.map +1 -1
- package/dist/provider-manager/manager.js +26 -10
- package/dist/provider-manager/openai.d.ts +2 -2
- package/dist/provider-manager/openai.d.ts.map +1 -1
- package/dist/provider-manager/openai.js +19 -4
- package/dist/provider-manager/types.d.ts +18 -38
- package/dist/provider-manager/types.d.ts.map +1 -1
- package/dist/provider-manager/workers.d.ts +2 -2
- package/dist/provider-manager/workers.d.ts.map +1 -1
- package/dist/provider-manager/workers.js +15 -4
- package/dist/query/followup.d.ts +7 -0
- package/dist/query/followup.d.ts.map +1 -0
- package/dist/query/followup.js +46 -0
- package/dist/query/intent.d.ts +6 -0
- package/dist/query/intent.d.ts.map +1 -0
- package/dist/query/intent.js +137 -0
- package/dist/query/types.d.ts +8 -0
- package/dist/query/types.d.ts.map +1 -0
- package/dist/query/types.js +0 -0
- package/dist/search/hybrid-search.d.ts +111 -0
- package/dist/search/hybrid-search.d.ts.map +1 -0
- package/dist/search/hybrid-search.js +326 -0
- package/dist/search/index.d.ts +11 -9
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +46 -10
- package/dist/search/scoring.d.ts +18 -0
- package/dist/search/scoring.d.ts.map +1 -0
- package/dist/search/{search-utils.js → scoring.js} +14 -27
- package/dist/search/search-api.d.ts +16 -1
- package/dist/search/search-api.d.ts.map +1 -1
- package/dist/search/search-api.js +118 -15
- package/dist/search/search-index.d.ts +2 -2
- package/dist/search/search-index.d.ts.map +1 -1
- package/dist/search/search-index.js +4 -2
- package/dist/search/session-cache.d.ts +4 -10
- package/dist/search/session-cache.d.ts.map +1 -1
- package/dist/search/session-cache.js +12 -45
- package/dist/search/types.d.ts +28 -0
- package/dist/search/types.d.ts.map +1 -1
- package/dist/search/vector-reranker.d.ts +3 -3
- package/dist/search/vector-reranker.d.ts.map +1 -1
- package/dist/search/vector-reranker.js +14 -2
- package/dist/server/chat-handler.d.ts +86 -1
- package/dist/server/chat-handler.d.ts.map +1 -1
- package/dist/server/chat-handler.js +835 -401
- package/dist/server/chat-message-utils.d.ts +6 -0
- package/dist/server/chat-message-utils.d.ts.map +1 -0
- package/dist/server/chat-message-utils.js +40 -0
- package/dist/server/chat-utils.d.ts +30 -0
- package/dist/server/chat-utils.d.ts.map +1 -0
- package/dist/server/chat-utils.js +88 -0
- package/dist/server/dev-server.js +238 -101
- package/dist/server/env-config.d.ts +22 -0
- package/dist/server/env-config.d.ts.map +1 -0
- package/dist/server/env-config.js +25 -0
- package/dist/server/errors.d.ts +1 -0
- package/dist/server/errors.d.ts.map +1 -1
- package/dist/server/errors.js +14 -7
- package/dist/server/index.d.ts +2 -4
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -25
- package/dist/server/metadata-init.d.ts +10 -5
- package/dist/server/metadata-init.d.ts.map +1 -1
- package/dist/server/metadata-init.js +78 -34
- package/dist/server/notify.d.ts +12 -11
- package/dist/server/notify.d.ts.map +1 -1
- package/dist/server/notify.js +46 -48
- package/dist/server/prompt-runtime.d.ts +60 -0
- package/dist/server/prompt-runtime.d.ts.map +1 -0
- package/dist/server/prompt-runtime.js +284 -0
- package/dist/server/stream-helpers.d.ts +30 -16
- package/dist/server/stream-helpers.d.ts.map +1 -1
- package/dist/server/stream-helpers.js +152 -15
- package/dist/server/types.d.ts +47 -12
- package/dist/server/types.d.ts.map +1 -1
- package/dist/structured-output/generator.d.ts +6 -0
- package/dist/structured-output/generator.d.ts.map +1 -0
- package/dist/structured-output/generator.js +164 -0
- package/dist/structured-output/index.d.ts +4 -0
- package/dist/structured-output/index.d.ts.map +1 -0
- package/dist/structured-output/index.js +6 -0
- package/dist/structured-output/schemas/evidence.d.ts +88 -0
- package/dist/structured-output/schemas/evidence.d.ts.map +1 -0
- package/dist/structured-output/schemas/evidence.js +65 -0
- package/dist/structured-output/types.d.ts +69 -0
- package/dist/structured-output/types.d.ts.map +1 -0
- package/dist/structured-output/types.js +0 -0
- package/dist/tools/action-tools.d.ts +63 -0
- package/dist/tools/action-tools.d.ts.map +1 -0
- package/dist/tools/action-tools.js +158 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +30 -0
- package/dist/utils/i18n.d.ts +1 -1
- package/dist/utils/i18n.d.ts.map +1 -1
- package/dist/utils/i18n.js +1 -1
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +36 -0
- package/dist/utils/text.d.ts +11 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +87 -0
- package/dist/utils/url.d.ts +19 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/url.js +13 -0
- package/package.json +46 -12
- package/dist/intelligence/intent-detect.d.ts +0 -40
- package/dist/intelligence/intent-detect.d.ts.map +0 -1
- package/dist/intelligence/intent-detect.js +0 -93
- package/dist/providers/index.d.ts +0 -2
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/providers/index.js +0 -5
- package/dist/search/search-utils.d.ts +0 -47
- package/dist/search/search-utils.d.ts.map +0 -1
- package/dist/stream/index.d.ts +0 -3
- package/dist/stream/index.d.ts.map +0 -1
- package/dist/stream/index.js +0 -8
- package/dist/stream/mock-stream.d.ts +0 -12
- package/dist/stream/mock-stream.d.ts.map +0 -1
- package/dist/stream/mock-stream.js +0 -26
- package/dist/stream/response.d.ts +0 -10
- package/dist/stream/response.d.ts.map +0 -1
- package/dist/stream/response.js +0 -21
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { UIMessage } from 'ai';
|
|
2
|
+
export declare function getMessageText(message: UIMessage): string;
|
|
3
|
+
export declare function hasContent(message: UIMessage): boolean;
|
|
4
|
+
export declare function filterValidMessages(messages: UIMessage[]): UIMessage[];
|
|
5
|
+
export declare function getLatestUserText(messages: UIMessage[]): string;
|
|
6
|
+
//# sourceMappingURL=chat-message-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-message-utils.d.ts","sourceRoot":"","sources":["../../src/server/chat-message-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEpC,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,GAAG,MAAM,CAQzD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAOtD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAYtE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,CAQ/D"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function getMessageText(message) {
|
|
2
|
+
if (Array.isArray(message.parts)) {
|
|
3
|
+
return message.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
4
|
+
}
|
|
5
|
+
return "";
|
|
6
|
+
}
|
|
7
|
+
function hasContent(message) {
|
|
8
|
+
const text = getMessageText(message);
|
|
9
|
+
if (text.trim()) return true;
|
|
10
|
+
if (Array.isArray(message.parts)) {
|
|
11
|
+
return message.parts.some((p) => p.type !== "text");
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
function filterValidMessages(messages) {
|
|
16
|
+
const filtered = [];
|
|
17
|
+
let lastRole = null;
|
|
18
|
+
for (const msg of messages) {
|
|
19
|
+
if (!hasContent(msg)) continue;
|
|
20
|
+
if (msg.role === lastRole) continue;
|
|
21
|
+
filtered.push(msg);
|
|
22
|
+
lastRole = msg.role;
|
|
23
|
+
}
|
|
24
|
+
return filtered;
|
|
25
|
+
}
|
|
26
|
+
function getLatestUserText(messages) {
|
|
27
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
28
|
+
const msg = messages[i];
|
|
29
|
+
if (msg?.role !== "user") continue;
|
|
30
|
+
const text = getMessageText(msg);
|
|
31
|
+
if (text.trim()) return text;
|
|
32
|
+
}
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
filterValidMessages,
|
|
37
|
+
getLatestUserText,
|
|
38
|
+
getMessageText,
|
|
39
|
+
hasContent
|
|
40
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { UIMessage } from "ai";
|
|
2
|
+
import type { ChatContext, NotifyModelInfo as ModelInfo, NotifyTokenUsage as TokenUsage, PhaseTiming } from "./types.js";
|
|
3
|
+
export declare function buildArticleContextPrompt(context: ChatContext): string;
|
|
4
|
+
export interface SendNotificationArgs {
|
|
5
|
+
env: Record<string, unknown>;
|
|
6
|
+
messages: UIMessage[];
|
|
7
|
+
responseText: string;
|
|
8
|
+
relatedArticles: Array<{
|
|
9
|
+
title: string;
|
|
10
|
+
url?: string;
|
|
11
|
+
}>;
|
|
12
|
+
model?: ModelInfo;
|
|
13
|
+
usage?: TokenUsage;
|
|
14
|
+
timing: PhaseTiming;
|
|
15
|
+
cacheKey?: string | null;
|
|
16
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
17
|
+
}
|
|
18
|
+
export declare function sendNotification(args: SendNotificationArgs): void;
|
|
19
|
+
export declare function parseNum(val: unknown, defaultVal: number): number;
|
|
20
|
+
export declare function getTimeoutConfig(env: Record<string, unknown>): {
|
|
21
|
+
request: number;
|
|
22
|
+
keywordExtraction: number;
|
|
23
|
+
evidenceAnalysis: number;
|
|
24
|
+
llmStreaming: number;
|
|
25
|
+
};
|
|
26
|
+
export declare function getHealthConfig(env: Record<string, unknown>): {
|
|
27
|
+
unhealthyThreshold: number;
|
|
28
|
+
recoveryTtl: number;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=chat-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-utils.d.ts","sourceRoot":"","sources":["../../src/server/chat-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,EACV,WAAW,EAEX,eAAe,IAAI,SAAS,EAC5B,gBAAgB,IAAI,UAAU,EAC9B,WAAW,EACZ,MAAM,YAAY,CAAC;AAIpB,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAiBtE;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;CACjD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAqCjE;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAQjE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;EAa5D;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;EAQ3D"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { notifyAiChat } from "./notify.js";
|
|
2
|
+
import { NOTIFICATION, TIMEOUTS, HEALTH } from "../constants.js";
|
|
3
|
+
function buildArticleContextPrompt(context) {
|
|
4
|
+
if (context.scope !== "article" || !context.article) return "";
|
|
5
|
+
const a = context.article;
|
|
6
|
+
const parts = ["\n[\u5F53\u524D\u9605\u8BFB\u6587\u7AE0]", `\u7528\u6237\u6B63\u5728\u9605\u8BFB\uFF1A\u300A${a.title}\u300B`];
|
|
7
|
+
if (a.categories?.length) parts.push(`\u5206\u7C7B\uFF1A${a.categories.join("\u3001")}`);
|
|
8
|
+
parts.push(
|
|
9
|
+
"",
|
|
10
|
+
"\u4F60\u6B63\u5728\u966A\u7528\u6237\u9605\u8BFB\u8FD9\u7BC7\u6587\u7AE0\u3002\u4F18\u5148\u56F4\u7ED5\u8FD9\u7BC7\u6587\u7AE0\u7684\u5185\u5BB9\u56DE\u7B54\u95EE\u9898\u3002",
|
|
11
|
+
"\u5F53\u7528\u6237\u7684\u95EE\u9898\u4E0E\u5F53\u524D\u6587\u7AE0\u76F8\u5173\u65F6\uFF0C\u4F18\u5148\u4F7F\u7528\u5F53\u524D\u6587\u7AE0\u539F\u6587\u6BB5\u843D\u4F5C\u7B54\uFF0C\u800C\u4E0D\u662F\u53EA\u590D\u8FF0\u6458\u8981\u3002",
|
|
12
|
+
"\u5982\u679C\u95EE\u9898\u662F\u5728\u95EE\u201C\u524D\u9762/\u540E\u9762\u662F\u4EC0\u4E48\u201D\u201C\u8FD9\u4E00\u8282\u8BB2\u4E86\u4EC0\u4E48\u201D\u201C\u8FD9\u4E00\u9879\u540E\u7EED\u5185\u5BB9\u662F\u4EC0\u4E48\u201D\uFF0C\u9ED8\u8BA4\u4F18\u5148\u4F9D\u636E\u5F53\u524D\u6587\u7AE0\u5DF2\u6CE8\u5165\u7684\u539F\u6587\u6BB5\u843D\u56DE\u7B54\u3002",
|
|
13
|
+
"\u5F53\u7528\u6237\u60F3\u8981\u5EF6\u4F38\u65F6\uFF0C\u63A8\u8350\u76F8\u5173\u7684\u535A\u5BA2\u6587\u7AE0\u3002"
|
|
14
|
+
);
|
|
15
|
+
return parts.join("\n");
|
|
16
|
+
}
|
|
17
|
+
function sendNotification(args) {
|
|
18
|
+
const {
|
|
19
|
+
env,
|
|
20
|
+
messages,
|
|
21
|
+
responseText,
|
|
22
|
+
relatedArticles,
|
|
23
|
+
model,
|
|
24
|
+
usage,
|
|
25
|
+
timing,
|
|
26
|
+
cacheKey,
|
|
27
|
+
waitUntil
|
|
28
|
+
} = args;
|
|
29
|
+
const sessionId = cacheKey || `dev-${Date.now().toString(36)}`;
|
|
30
|
+
const notifyArticles = relatedArticles.slice(0, NOTIFICATION.MAX_REFERENCED_ARTICLES).map((a) => ({
|
|
31
|
+
title: a.title,
|
|
32
|
+
url: a.url
|
|
33
|
+
}));
|
|
34
|
+
const notifyPromise = notifyAiChat({
|
|
35
|
+
env,
|
|
36
|
+
sessionId,
|
|
37
|
+
messages,
|
|
38
|
+
aiResponse: responseText,
|
|
39
|
+
referencedArticles: notifyArticles,
|
|
40
|
+
model,
|
|
41
|
+
usage,
|
|
42
|
+
timing
|
|
43
|
+
});
|
|
44
|
+
if (waitUntil) {
|
|
45
|
+
waitUntil(notifyPromise);
|
|
46
|
+
} else {
|
|
47
|
+
void notifyPromise;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function parseNum(val, defaultVal) {
|
|
51
|
+
if (val === void 0) return defaultVal;
|
|
52
|
+
if (typeof val === "number") return val;
|
|
53
|
+
if (typeof val === "string") {
|
|
54
|
+
const num = parseInt(val, 10);
|
|
55
|
+
return isNaN(num) ? defaultVal : num;
|
|
56
|
+
}
|
|
57
|
+
return defaultVal;
|
|
58
|
+
}
|
|
59
|
+
function getTimeoutConfig(env) {
|
|
60
|
+
return {
|
|
61
|
+
request: parseNum(env.AI_TIMEOUT_REQUEST, TIMEOUTS.REQUEST),
|
|
62
|
+
keywordExtraction: parseNum(
|
|
63
|
+
env.AI_TIMEOUT_KEYWORD,
|
|
64
|
+
TIMEOUTS.KEYWORD_EXTRACTION
|
|
65
|
+
),
|
|
66
|
+
evidenceAnalysis: parseNum(
|
|
67
|
+
env.AI_TIMEOUT_EVIDENCE,
|
|
68
|
+
TIMEOUTS.EVIDENCE_ANALYSIS
|
|
69
|
+
),
|
|
70
|
+
llmStreaming: parseNum(env.AI_TIMEOUT_LLM, TIMEOUTS.LLM_STREAMING)
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function getHealthConfig(env) {
|
|
74
|
+
return {
|
|
75
|
+
unhealthyThreshold: parseNum(
|
|
76
|
+
env.AI_HEALTH_THRESHOLD,
|
|
77
|
+
HEALTH.UNHEALTHY_THRESHOLD
|
|
78
|
+
),
|
|
79
|
+
recoveryTtl: parseNum(env.AI_HEALTH_RECOVERY_TTL, HEALTH.RECOVERY_TTL)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export {
|
|
83
|
+
buildArticleContextPrompt,
|
|
84
|
+
getHealthConfig,
|
|
85
|
+
getTimeoutConfig,
|
|
86
|
+
parseNum,
|
|
87
|
+
sendNotification
|
|
88
|
+
};
|
|
@@ -1,20 +1,62 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
createServer
|
|
4
|
+
} from "node:http";
|
|
3
5
|
import { readFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { resolve
|
|
5
|
-
import {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
|
+
import { setLogLevel } from "../utils/logger.js";
|
|
8
|
+
const DEFAULT_SUMMARIES = {
|
|
9
|
+
meta: {
|
|
10
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11
|
+
model: "none",
|
|
12
|
+
totalProcessed: 0
|
|
13
|
+
},
|
|
14
|
+
articles: {}
|
|
15
|
+
};
|
|
9
16
|
const DEFAULT_AUTHOR_CONTEXT = { author: {}, posts: [] };
|
|
10
17
|
const DEFAULT_VOICE_PROFILE = { style: {}, examples: [] };
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
const DEFAULT_FACT_REGISTRY = {
|
|
19
|
+
$schema: "fact-registry-v1",
|
|
20
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21
|
+
version: 1,
|
|
22
|
+
facts: [],
|
|
23
|
+
stats: {
|
|
24
|
+
total: 0,
|
|
25
|
+
byCategory: {
|
|
26
|
+
author: 0,
|
|
27
|
+
blog: 0,
|
|
28
|
+
content: 0,
|
|
29
|
+
project: 0,
|
|
30
|
+
tech: 0
|
|
31
|
+
},
|
|
32
|
+
avgConfidence: 0
|
|
15
33
|
}
|
|
16
|
-
|
|
17
|
-
|
|
34
|
+
};
|
|
35
|
+
const DEFAULT_KNOWLEDGE_BUNDLE = {
|
|
36
|
+
$schema: "knowledge-bundle-v1",
|
|
37
|
+
version: 1,
|
|
38
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39
|
+
corpusHash: "dev-server-default",
|
|
40
|
+
runtime: {
|
|
41
|
+
summaries: DEFAULT_SUMMARIES,
|
|
42
|
+
authorContext: DEFAULT_AUTHOR_CONTEXT,
|
|
43
|
+
voiceProfile: DEFAULT_VOICE_PROFILE,
|
|
44
|
+
factRegistry: DEFAULT_FACT_REGISTRY,
|
|
45
|
+
vectorIndex: null
|
|
46
|
+
},
|
|
47
|
+
corpus: {
|
|
48
|
+
$schema: "knowledge-corpus-v1",
|
|
49
|
+
version: 1,
|
|
50
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
51
|
+
documents: []
|
|
52
|
+
},
|
|
53
|
+
passages: {
|
|
54
|
+
$schema: "knowledge-passages-v1",
|
|
55
|
+
version: 1,
|
|
56
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57
|
+
passages: []
|
|
58
|
+
}
|
|
59
|
+
};
|
|
18
60
|
function findBlogRoot() {
|
|
19
61
|
let dir = process.cwd();
|
|
20
62
|
for (let i = 0; i < 10; i++) {
|
|
@@ -22,16 +64,21 @@ function findBlogRoot() {
|
|
|
22
64
|
return { root: dir, datasDir: resolve(dir, "datas"), hasDatas: true };
|
|
23
65
|
}
|
|
24
66
|
if (existsSync(resolve(dir, "apps", "blog", "datas"))) {
|
|
25
|
-
return {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
67
|
+
return {
|
|
68
|
+
root: resolve(dir, "apps", "blog"),
|
|
69
|
+
datasDir: resolve(dir, "apps", "blog", "datas"),
|
|
70
|
+
hasDatas: true
|
|
71
|
+
};
|
|
29
72
|
}
|
|
30
73
|
const parent = resolve(dir, "..");
|
|
31
74
|
if (parent === dir) break;
|
|
32
75
|
dir = parent;
|
|
33
76
|
}
|
|
34
|
-
return {
|
|
77
|
+
return {
|
|
78
|
+
root: process.cwd(),
|
|
79
|
+
datasDir: resolve(process.cwd(), "datas"),
|
|
80
|
+
hasDatas: false
|
|
81
|
+
};
|
|
35
82
|
}
|
|
36
83
|
function loadEnv(envPath) {
|
|
37
84
|
if (!existsSync(envPath)) return;
|
|
@@ -55,18 +102,21 @@ function initDatasDirectory(datasDir) {
|
|
|
55
102
|
if (!existsSync(datasDir)) {
|
|
56
103
|
mkdirSync(datasDir, { recursive: true });
|
|
57
104
|
}
|
|
105
|
+
const runtimeDir = resolve(datasDir, "knowledge", "runtime");
|
|
106
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
58
107
|
const files = [
|
|
59
|
-
{
|
|
60
|
-
|
|
61
|
-
|
|
108
|
+
{
|
|
109
|
+
name: resolve(runtimeDir, "knowledge-bundle.json"),
|
|
110
|
+
label: "knowledge/runtime/knowledge-bundle.json",
|
|
111
|
+
content: DEFAULT_KNOWLEDGE_BUNDLE
|
|
112
|
+
}
|
|
62
113
|
];
|
|
63
114
|
for (const file of files) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
console.log(` Created ${file.name}`);
|
|
115
|
+
if (!existsSync(file.name)) {
|
|
116
|
+
writeFileSync(file.name, JSON.stringify(file.content, null, 2) + "\n");
|
|
117
|
+
console.log(` Created ${file.label}`);
|
|
68
118
|
} else {
|
|
69
|
-
console.log(` Skipped ${file.
|
|
119
|
+
console.log(` Skipped ${file.label} (already exists)`);
|
|
70
120
|
}
|
|
71
121
|
}
|
|
72
122
|
}
|
|
@@ -84,27 +134,51 @@ function loadJson(datasDir, file, defaultValue) {
|
|
|
84
134
|
}
|
|
85
135
|
async function setupHandler(datasDir, hasDatas) {
|
|
86
136
|
const { handleChatRequest, initializeMetadata } = await import("./index.js");
|
|
137
|
+
const {
|
|
138
|
+
getProviderManager,
|
|
139
|
+
hasAnyProviderConfigured,
|
|
140
|
+
getResponseCacheConfig
|
|
141
|
+
} = await import("../index.js");
|
|
87
142
|
if (!hasDatas) {
|
|
88
|
-
console.log(
|
|
89
|
-
|
|
143
|
+
console.log(
|
|
144
|
+
"\n \u26A0\uFE0F No datas/ directory found. AI chat will work with empty context."
|
|
145
|
+
);
|
|
146
|
+
console.log(
|
|
147
|
+
' Run "pnpm exec astro-ai-dev --init" to create placeholder files.\n'
|
|
148
|
+
);
|
|
90
149
|
} else {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
150
|
+
const hasKnowledgeBundle = existsSync(
|
|
151
|
+
resolve(datasDir, "knowledge", "runtime", "knowledge-bundle.json")
|
|
152
|
+
);
|
|
153
|
+
if (!hasKnowledgeBundle) {
|
|
154
|
+
console.log(
|
|
155
|
+
"\n \u26A0\uFE0F knowledge/runtime/knowledge-bundle.json is missing. AI chat may have limited context.\n"
|
|
156
|
+
);
|
|
95
157
|
}
|
|
96
158
|
}
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
159
|
+
const knowledgeBundle = loadJson(
|
|
160
|
+
datasDir,
|
|
161
|
+
"knowledge/runtime/knowledge-bundle.json",
|
|
162
|
+
DEFAULT_KNOWLEDGE_BUNDLE
|
|
163
|
+
);
|
|
100
164
|
const env = { ...process.env };
|
|
101
|
-
initializeMetadata(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
165
|
+
initializeMetadata(
|
|
166
|
+
{
|
|
167
|
+
knowledgeBundle,
|
|
168
|
+
siteUrl: process.env.SITE_URL || "http://localhost:4321"
|
|
169
|
+
},
|
|
170
|
+
env
|
|
171
|
+
);
|
|
172
|
+
return {
|
|
173
|
+
handleChatRequest,
|
|
174
|
+
initializeMetadata,
|
|
175
|
+
getProviderManager,
|
|
176
|
+
hasAnyProviderConfigured,
|
|
177
|
+
getResponseCacheConfig,
|
|
178
|
+
env,
|
|
179
|
+
knowledgeBundle,
|
|
180
|
+
vectorIndex: knowledgeBundle.runtime.vectorIndex ?? null
|
|
181
|
+
};
|
|
108
182
|
}
|
|
109
183
|
function toWebRequest(req) {
|
|
110
184
|
return new Promise((resolve2, reject) => {
|
|
@@ -113,17 +187,23 @@ function toWebRequest(req) {
|
|
|
113
187
|
req.on("end", () => {
|
|
114
188
|
const body = Buffer.concat(chunks);
|
|
115
189
|
const url = `http://localhost${req.url || "/"}`;
|
|
116
|
-
resolve2(
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
190
|
+
resolve2(
|
|
191
|
+
new Request(url, {
|
|
192
|
+
method: req.method || "GET",
|
|
193
|
+
headers: req.headers,
|
|
194
|
+
body: req.method !== "GET" && req.method !== "HEAD" ? body : void 0
|
|
195
|
+
})
|
|
196
|
+
);
|
|
121
197
|
});
|
|
122
198
|
req.on("error", reject);
|
|
123
199
|
});
|
|
124
200
|
}
|
|
125
201
|
async function sendWebResponse(webRes, res) {
|
|
126
|
-
|
|
202
|
+
const headerEntries = [];
|
|
203
|
+
webRes.headers.forEach((value, key) => {
|
|
204
|
+
headerEntries.push([key, value]);
|
|
205
|
+
});
|
|
206
|
+
res.writeHead(webRes.status, Object.fromEntries(headerEntries));
|
|
127
207
|
if (!webRes.body) {
|
|
128
208
|
res.end();
|
|
129
209
|
return;
|
|
@@ -150,17 +230,36 @@ async function main() {
|
|
|
150
230
|
console.log("\n\u2705 Done! You can now configure your AI metadata files.\n");
|
|
151
231
|
process.exit(0);
|
|
152
232
|
}
|
|
233
|
+
if (process.env.AI_DEBUG) setLogLevel("debug");
|
|
234
|
+
else if (process.env.AI_LOG_LEVEL)
|
|
235
|
+
setLogLevel(
|
|
236
|
+
process.env.AI_LOG_LEVEL
|
|
237
|
+
);
|
|
153
238
|
const port = parseInt(process.env.AI_DEV_PORT || "8787", 10);
|
|
154
239
|
const { root: blogRoot, datasDir, hasDatas } = findBlogRoot();
|
|
155
240
|
loadEnv(resolve(blogRoot, ".env"));
|
|
156
241
|
console.log("\n\u{1F916} AI Dev Server starting...\n");
|
|
157
242
|
console.log(` Working directory: ${blogRoot}`);
|
|
158
|
-
console.log(
|
|
243
|
+
console.log(
|
|
244
|
+
` Datas directory: ${datasDir} ${hasDatas ? "\u2713" : "(not found)"}`
|
|
245
|
+
);
|
|
159
246
|
console.log(` Port: ${port}`);
|
|
160
|
-
console.log(
|
|
161
|
-
|
|
247
|
+
console.log(
|
|
248
|
+
` AI_BASE_URL: ${process.env.AI_BASE_URL ? "\u2713 configured" : "\u2717 not set"}`
|
|
249
|
+
);
|
|
250
|
+
console.log(
|
|
251
|
+
` AI_API_KEY: ${process.env.AI_API_KEY ? "\u2713 configured" : "\u2717 not set"}`
|
|
252
|
+
);
|
|
162
253
|
console.log(` AI_MODEL: ${process.env.AI_MODEL || "(default)"}`);
|
|
163
|
-
const {
|
|
254
|
+
const {
|
|
255
|
+
handleChatRequest,
|
|
256
|
+
getProviderManager,
|
|
257
|
+
hasAnyProviderConfigured,
|
|
258
|
+
getResponseCacheConfig,
|
|
259
|
+
env,
|
|
260
|
+
knowledgeBundle,
|
|
261
|
+
vectorIndex
|
|
262
|
+
} = await setupHandler(datasDir, hasDatas);
|
|
164
263
|
const server = createServer(async (req, res) => {
|
|
165
264
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
166
265
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
@@ -179,58 +278,89 @@ async function main() {
|
|
|
179
278
|
return;
|
|
180
279
|
}
|
|
181
280
|
if (url.startsWith("/api/notify/comment")) {
|
|
182
|
-
const {
|
|
281
|
+
const { handleCommentWebhook } = await import("@astro-minimax/notify");
|
|
183
282
|
const webReq = await toWebRequest(req);
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
res.writeHead(400, { "Content-Type": "application/json" });
|
|
187
|
-
res.end(JSON.stringify({ error: "Unsupported event type" }));
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
const data = body.data || {};
|
|
191
|
-
const siteUrl = process.env.SITE_URL || "http://localhost:4321";
|
|
192
|
-
const postUrl = data.url?.startsWith("http") ? data.url : `${siteUrl}${data.url || "/"}`;
|
|
193
|
-
const notifier = createNotifier({
|
|
194
|
-
telegram: process.env.NOTIFY_TELEGRAM_BOT_TOKEN && process.env.NOTIFY_TELEGRAM_CHAT_ID ? {
|
|
195
|
-
botToken: process.env.NOTIFY_TELEGRAM_BOT_TOKEN,
|
|
196
|
-
chatId: process.env.NOTIFY_TELEGRAM_CHAT_ID
|
|
197
|
-
} : void 0,
|
|
198
|
-
webhook: process.env.NOTIFY_WEBHOOK_URL ? {
|
|
199
|
-
url: process.env.NOTIFY_WEBHOOK_URL
|
|
200
|
-
} : void 0,
|
|
201
|
-
email: process.env.NOTIFY_RESEND_API_KEY && process.env.NOTIFY_RESEND_FROM && process.env.NOTIFY_RESEND_TO ? {
|
|
202
|
-
provider: "resend",
|
|
203
|
-
apiKey: process.env.NOTIFY_RESEND_API_KEY,
|
|
204
|
-
from: process.env.NOTIFY_RESEND_FROM,
|
|
205
|
-
to: process.env.NOTIFY_RESEND_TO
|
|
206
|
-
} : void 0
|
|
207
|
-
});
|
|
208
|
-
const result = await notifier.comment({
|
|
209
|
-
author: data.nick || "\u533F\u540D\u7528\u6237",
|
|
210
|
-
content: data.comment || "",
|
|
211
|
-
postTitle: extractPostTitle(data.url || "/"),
|
|
212
|
-
postUrl
|
|
213
|
-
});
|
|
214
|
-
console.log("[notify] Comment notification sent:", result.success ? "\u2713" : "\u2717", result.results);
|
|
215
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
216
|
-
res.end(JSON.stringify({
|
|
217
|
-
success: result.success,
|
|
218
|
-
event: "comment",
|
|
219
|
-
channels: result.results.map((r) => ({ channel: r.channel, success: r.success, error: r.error }))
|
|
220
|
-
}));
|
|
283
|
+
const webRes = await handleCommentWebhook(webReq, process.env);
|
|
284
|
+
await sendWebResponse(webRes, res);
|
|
221
285
|
return;
|
|
222
286
|
}
|
|
223
287
|
if (url.startsWith("/api/ai-info")) {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
288
|
+
const manager = getProviderManager(env, { enableMockFallback: true });
|
|
289
|
+
const providerStatus = manager.getProviderStatus();
|
|
290
|
+
const configured = hasAnyProviderConfigured(env);
|
|
291
|
+
const responseCacheConfig = getResponseCacheConfig(env);
|
|
292
|
+
const timeoutConfig = {
|
|
293
|
+
request: env.AI_TIMEOUT_REQUEST ?? 45e3,
|
|
294
|
+
keywordExtraction: env.AI_TIMEOUT_KEYWORD ?? 5e3,
|
|
295
|
+
evidenceAnalysis: env.AI_TIMEOUT_EVIDENCE ?? 8e3,
|
|
296
|
+
llmStreaming: env.AI_TIMEOUT_LLM ?? 3e4
|
|
297
|
+
};
|
|
298
|
+
const healthConfig = {
|
|
299
|
+
unhealthyThreshold: env.AI_HEALTH_THRESHOLD ?? 3,
|
|
300
|
+
recoveryTtl: env.AI_HEALTH_RECOVERY_TTL ?? 6e4
|
|
301
|
+
};
|
|
302
|
+
const dataStatus = {
|
|
303
|
+
knowledgeBundle: {
|
|
304
|
+
loaded: true,
|
|
305
|
+
count: Array.isArray(
|
|
306
|
+
knowledgeBundle?.corpus?.documents
|
|
307
|
+
) ? knowledgeBundle.corpus.documents.length : void 0,
|
|
308
|
+
lastUpdated: knowledgeBundle?.generatedAt
|
|
309
|
+
},
|
|
310
|
+
vectorIndex: {
|
|
311
|
+
loaded: Boolean(vectorIndex),
|
|
312
|
+
lastUpdated: knowledgeBundle?.generatedAt
|
|
232
313
|
}
|
|
233
|
-
}
|
|
314
|
+
};
|
|
315
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
316
|
+
res.end(
|
|
317
|
+
JSON.stringify(
|
|
318
|
+
{
|
|
319
|
+
status: "ok",
|
|
320
|
+
mode: "dev-server",
|
|
321
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
322
|
+
ai: {
|
|
323
|
+
enabled: true,
|
|
324
|
+
mockMode: !!env.AI_MOCK_MODE,
|
|
325
|
+
configured,
|
|
326
|
+
cache: {
|
|
327
|
+
enabled: responseCacheConfig.enabled,
|
|
328
|
+
ttl: responseCacheConfig.defaultTtl,
|
|
329
|
+
playbackDelay: responseCacheConfig.playbackDelayMs,
|
|
330
|
+
chunkSize: responseCacheConfig.chunkSize,
|
|
331
|
+
thinkingDelay: responseCacheConfig.thinkingPlaybackDelayMs
|
|
332
|
+
},
|
|
333
|
+
timeouts: timeoutConfig,
|
|
334
|
+
health: healthConfig,
|
|
335
|
+
providers: providerStatus.map((p) => ({
|
|
336
|
+
id: p.id,
|
|
337
|
+
type: p.type,
|
|
338
|
+
weight: p.weight,
|
|
339
|
+
healthy: p.health.healthy,
|
|
340
|
+
model: p.model,
|
|
341
|
+
healthDetails: {
|
|
342
|
+
consecutiveFailures: p.health.consecutiveFailures,
|
|
343
|
+
totalRequests: p.health.totalRequests,
|
|
344
|
+
successfulRequests: p.health.successfulRequests,
|
|
345
|
+
lastError: p.health.lastError,
|
|
346
|
+
lastErrorTime: p.health.lastErrorTime,
|
|
347
|
+
lastSuccessTime: p.health.lastSuccessTime
|
|
348
|
+
}
|
|
349
|
+
})),
|
|
350
|
+
dataStatus
|
|
351
|
+
},
|
|
352
|
+
hints: manager.hasProviders() ? [
|
|
353
|
+
`Providers available: ${manager.getProviderCount()}`,
|
|
354
|
+
"Mock fallback: enabled",
|
|
355
|
+
responseCacheConfig.enabled ? "Response cache: enabled" : "Response cache: disabled"
|
|
356
|
+
] : [
|
|
357
|
+
"No AI providers configured. Set AI_BASE_URL + AI_API_KEY environment variables."
|
|
358
|
+
]
|
|
359
|
+
},
|
|
360
|
+
null,
|
|
361
|
+
2
|
|
362
|
+
)
|
|
363
|
+
);
|
|
234
364
|
return;
|
|
235
365
|
}
|
|
236
366
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
@@ -238,7 +368,12 @@ async function main() {
|
|
|
238
368
|
} catch (err) {
|
|
239
369
|
console.error("[AI Dev Server] Error:", err);
|
|
240
370
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
241
|
-
res.end(
|
|
371
|
+
res.end(
|
|
372
|
+
JSON.stringify({
|
|
373
|
+
error: "Internal server error",
|
|
374
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
375
|
+
})
|
|
376
|
+
);
|
|
242
377
|
}
|
|
243
378
|
});
|
|
244
379
|
server.listen(port, () => {
|
|
@@ -246,9 +381,11 @@ async function main() {
|
|
|
246
381
|
\u2705 AI Dev Server running at http://localhost:${port}`);
|
|
247
382
|
console.log(` POST http://localhost:${port}/api/chat`);
|
|
248
383
|
console.log(` GET http://localhost:${port}/api/ai-info`);
|
|
249
|
-
console.log(
|
|
384
|
+
console.log(
|
|
385
|
+
`
|
|
250
386
|
Tip: Run "pnpm exec astro-ai-dev --init" to create datas/ directory.
|
|
251
|
-
`
|
|
387
|
+
`
|
|
388
|
+
);
|
|
252
389
|
});
|
|
253
390
|
const shutdown = (signal) => {
|
|
254
391
|
console.log(`
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ChatHandlerEnv } from "./types.js";
|
|
2
|
+
export declare function applyAiConfigDefaults(baseEnv: ChatHandlerEnv, aiConfig: {
|
|
3
|
+
cache?: {
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
ttl?: number;
|
|
6
|
+
playbackDelay?: number;
|
|
7
|
+
chunkSize?: number;
|
|
8
|
+
thinkingDelay?: number;
|
|
9
|
+
};
|
|
10
|
+
timeouts?: {
|
|
11
|
+
request?: number;
|
|
12
|
+
keywordExtraction?: number;
|
|
13
|
+
evidenceAnalysis?: number;
|
|
14
|
+
llmStreaming?: number;
|
|
15
|
+
};
|
|
16
|
+
health?: {
|
|
17
|
+
unhealthyThreshold?: number;
|
|
18
|
+
recoveryTtl?: number;
|
|
19
|
+
};
|
|
20
|
+
mockMode?: boolean;
|
|
21
|
+
} | null | undefined): ChatHandlerEnv;
|
|
22
|
+
//# sourceMappingURL=env-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-config.d.ts","sourceRoot":"","sources":["../../src/server/env-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,cAAc,EACvB,QAAQ,EACJ;IACE,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,MAAM,CAAC,EAAE;QACP,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD,IAAI,GACJ,SAAS,GACZ,cAAc,CA4BhB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function applyAiConfigDefaults(baseEnv, aiConfig) {
|
|
2
|
+
if (!aiConfig) return { ...baseEnv };
|
|
3
|
+
const envWithConfig = { ...baseEnv };
|
|
4
|
+
const setIfMissing = (envKey, configValue) => {
|
|
5
|
+
if (envWithConfig[envKey] === void 0 && configValue !== void 0) {
|
|
6
|
+
envWithConfig[envKey] = configValue;
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
setIfMissing("AI_CACHE_ENABLED", aiConfig.cache?.enabled);
|
|
10
|
+
setIfMissing("AI_CACHE_TTL", aiConfig.cache?.ttl);
|
|
11
|
+
setIfMissing("AI_CACHE_PLAYBACK_DELAY", aiConfig.cache?.playbackDelay);
|
|
12
|
+
setIfMissing("AI_CACHE_CHUNK_SIZE", aiConfig.cache?.chunkSize);
|
|
13
|
+
setIfMissing("AI_CACHE_THINKING_DELAY", aiConfig.cache?.thinkingDelay);
|
|
14
|
+
setIfMissing("AI_TIMEOUT_REQUEST", aiConfig.timeouts?.request);
|
|
15
|
+
setIfMissing("AI_TIMEOUT_KEYWORD", aiConfig.timeouts?.keywordExtraction);
|
|
16
|
+
setIfMissing("AI_TIMEOUT_EVIDENCE", aiConfig.timeouts?.evidenceAnalysis);
|
|
17
|
+
setIfMissing("AI_TIMEOUT_LLM", aiConfig.timeouts?.llmStreaming);
|
|
18
|
+
setIfMissing("AI_HEALTH_THRESHOLD", aiConfig.health?.unhealthyThreshold);
|
|
19
|
+
setIfMissing("AI_HEALTH_RECOVERY_TTL", aiConfig.health?.recoveryTtl);
|
|
20
|
+
setIfMissing("AI_MOCK_MODE", aiConfig.mockMode);
|
|
21
|
+
return envWithConfig;
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
applyAiConfigDefaults
|
|
25
|
+
};
|
package/dist/server/errors.d.ts
CHANGED