@bonginkan/maria 3.1.4 → 3.1.6
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 +73 -29
- package/dist/bin/maria.cjs +2797 -152
- package/dist/bin/maria.cjs.map +1 -1
- package/dist/cli.cjs +2832 -187
- package/dist/cli.cjs.map +1 -1
- package/package.json +2 -2
package/dist/bin/maria.cjs
CHANGED
|
@@ -11757,6 +11757,2522 @@ var init_ai_response_tetris_template = __esm({
|
|
|
11757
11757
|
}
|
|
11758
11758
|
});
|
|
11759
11759
|
|
|
11760
|
+
// src/services/ai-response/intent.ts
|
|
11761
|
+
function analyzeIntent(userInputRaw, recentText = "") {
|
|
11762
|
+
const input3 = userInputRaw.trim();
|
|
11763
|
+
const low = input3.toLowerCase();
|
|
11764
|
+
const combinedContext = (recentText + " " + input3).toLowerCase();
|
|
11765
|
+
if (low.includes("tetris") || input3.includes("\u30C6\u30C8\u30EA\u30B9")) {
|
|
11766
|
+
return {
|
|
11767
|
+
type: "TETRIS_REQUEST",
|
|
11768
|
+
confidence: 0.95,
|
|
11769
|
+
detail: "User explicitly requested Tetris game"
|
|
11770
|
+
};
|
|
11771
|
+
}
|
|
11772
|
+
if (summaryHints.some((hint) => low.includes(hint))) {
|
|
11773
|
+
return {
|
|
11774
|
+
type: "SUMMARIZE",
|
|
11775
|
+
confidence: 0.9,
|
|
11776
|
+
detail: "User wants a summary of the conversation"
|
|
11777
|
+
};
|
|
11778
|
+
}
|
|
11779
|
+
if (recentText && continuationHints.some(
|
|
11780
|
+
(hint) => low.includes(hint) || recentText.toLowerCase().includes(hint)
|
|
11781
|
+
)) {
|
|
11782
|
+
return {
|
|
11783
|
+
type: "CONTINUATION",
|
|
11784
|
+
confidence: 0.85,
|
|
11785
|
+
detail: "User wants to continue previous topic"
|
|
11786
|
+
};
|
|
11787
|
+
}
|
|
11788
|
+
const isQuestion = low.endsWith("?") || low.endsWith("\uFF1F") || jaQuestionStarts.some((w) => input3.startsWith(w)) || [
|
|
11789
|
+
"what",
|
|
11790
|
+
"how",
|
|
11791
|
+
"why",
|
|
11792
|
+
"when",
|
|
11793
|
+
"where",
|
|
11794
|
+
"which",
|
|
11795
|
+
"who",
|
|
11796
|
+
"can you",
|
|
11797
|
+
"could you",
|
|
11798
|
+
"would you",
|
|
11799
|
+
"is it",
|
|
11800
|
+
"are there"
|
|
11801
|
+
].some((w) => low.startsWith(w));
|
|
11802
|
+
if (isQuestion) {
|
|
11803
|
+
return {
|
|
11804
|
+
type: "QUESTION",
|
|
11805
|
+
confidence: 0.8,
|
|
11806
|
+
detail: "User is asking a question"
|
|
11807
|
+
};
|
|
11808
|
+
}
|
|
11809
|
+
const hasCodeSnippet = input3.includes("```") || input3.includes("`");
|
|
11810
|
+
const hasCodeHint = codeHints.some((hint) => combinedContext.includes(hint));
|
|
11811
|
+
const hasJaCodeTerm = jaCodeTerms.some((term) => input3.includes(term));
|
|
11812
|
+
const hasEnCodeTerms = [
|
|
11813
|
+
"implement",
|
|
11814
|
+
"create",
|
|
11815
|
+
"build",
|
|
11816
|
+
"write",
|
|
11817
|
+
"develop",
|
|
11818
|
+
"code",
|
|
11819
|
+
"function",
|
|
11820
|
+
"class",
|
|
11821
|
+
"method",
|
|
11822
|
+
"component"
|
|
11823
|
+
].some((w) => low.includes(w));
|
|
11824
|
+
if (hasCodeSnippet || hasCodeHint || hasJaCodeTerm || hasEnCodeTerms) {
|
|
11825
|
+
return {
|
|
11826
|
+
type: "CODE_REQUEST",
|
|
11827
|
+
confidence: hasCodeSnippet ? 0.9 : 0.75,
|
|
11828
|
+
detail: "User wants code implementation or help"
|
|
11829
|
+
};
|
|
11830
|
+
}
|
|
11831
|
+
if (["refactor", "\u30EA\u30D5\u30A1\u30AF\u30BF", "\u6539\u5584", "\u6700\u9069\u5316", "optimize", "improve"].some((w) => low.includes(w))) {
|
|
11832
|
+
return {
|
|
11833
|
+
type: "REFACTOR",
|
|
11834
|
+
confidence: 0.7,
|
|
11835
|
+
detail: "User wants code refactoring or optimization"
|
|
11836
|
+
};
|
|
11837
|
+
}
|
|
11838
|
+
return {
|
|
11839
|
+
type: "GENERAL",
|
|
11840
|
+
confidence: 0.3,
|
|
11841
|
+
detail: "General conversation or unclear intent"
|
|
11842
|
+
};
|
|
11843
|
+
}
|
|
11844
|
+
function detectLanguage(input3) {
|
|
11845
|
+
const hasJapanese = /[ぁ-んァ-ヶー一-龥]/.test(input3);
|
|
11846
|
+
return hasJapanese ? "ja" : "en";
|
|
11847
|
+
}
|
|
11848
|
+
var jaQuestionStarts, codeHints, jaCodeTerms, continuationHints, summaryHints;
|
|
11849
|
+
var init_intent = __esm({
|
|
11850
|
+
"src/services/ai-response/intent.ts"() {
|
|
11851
|
+
jaQuestionStarts = [
|
|
11852
|
+
"\u4F55",
|
|
11853
|
+
"\u3069\u3046",
|
|
11854
|
+
"\u306A\u305C",
|
|
11855
|
+
"\u3044\u3064",
|
|
11856
|
+
"\u3069\u3053",
|
|
11857
|
+
"\u3069\u308C",
|
|
11858
|
+
"\u8AB0",
|
|
11859
|
+
"\u3067\u304D\u307E\u3059\u304B",
|
|
11860
|
+
"\u6559\u3048\u3066",
|
|
11861
|
+
"\u3042\u308A\u307E\u3059\u304B",
|
|
11862
|
+
"\u3067\u3057\u3087\u3046\u304B"
|
|
11863
|
+
];
|
|
11864
|
+
codeHints = [
|
|
11865
|
+
"```",
|
|
11866
|
+
"function ",
|
|
11867
|
+
"class ",
|
|
11868
|
+
"const ",
|
|
11869
|
+
"let ",
|
|
11870
|
+
"import ",
|
|
11871
|
+
"export ",
|
|
11872
|
+
".ts",
|
|
11873
|
+
".tsx",
|
|
11874
|
+
".js",
|
|
11875
|
+
".jsx",
|
|
11876
|
+
".json",
|
|
11877
|
+
".py",
|
|
11878
|
+
".java",
|
|
11879
|
+
".go",
|
|
11880
|
+
".rs",
|
|
11881
|
+
"HTML",
|
|
11882
|
+
"CSS",
|
|
11883
|
+
"SQL",
|
|
11884
|
+
"Dockerfile",
|
|
11885
|
+
"yaml",
|
|
11886
|
+
"yml"
|
|
11887
|
+
];
|
|
11888
|
+
jaCodeTerms = [
|
|
11889
|
+
"\u5B9F\u88C5",
|
|
11890
|
+
"\u30B3\u30FC\u30C9",
|
|
11891
|
+
"\u95A2\u6570",
|
|
11892
|
+
"\u30AF\u30E9\u30B9",
|
|
11893
|
+
"\u30D3\u30EB\u30C9",
|
|
11894
|
+
"\u578B",
|
|
11895
|
+
"\u578B\u5B9A\u7FA9",
|
|
11896
|
+
"\u30C6\u30B9\u30C8",
|
|
11897
|
+
"\u30D7\u30ED\u30B0\u30E9\u30E0",
|
|
11898
|
+
"\u30B9\u30AF\u30EA\u30D7\u30C8",
|
|
11899
|
+
"\u30A2\u30D7\u30EA",
|
|
11900
|
+
"\u958B\u767A"
|
|
11901
|
+
];
|
|
11902
|
+
continuationHints = [
|
|
11903
|
+
"\u7D9A\u304D",
|
|
11904
|
+
"\u3064\u3065\u304D",
|
|
11905
|
+
"\u7D9A\u884C",
|
|
11906
|
+
"\u5148\u307B\u3069\u306E",
|
|
11907
|
+
"\u524D\u56DE\u306E",
|
|
11908
|
+
"\u3055\u3063\u304D\u306E",
|
|
11909
|
+
"complete",
|
|
11910
|
+
"continue",
|
|
11911
|
+
"start",
|
|
11912
|
+
"give me",
|
|
11913
|
+
"finish",
|
|
11914
|
+
"proceed",
|
|
11915
|
+
"next",
|
|
11916
|
+
"then",
|
|
11917
|
+
"whole code"
|
|
11918
|
+
];
|
|
11919
|
+
summaryHints = [
|
|
11920
|
+
"\u8981\u7D04",
|
|
11921
|
+
"\u307E\u3068\u3081",
|
|
11922
|
+
"\u30B5\u30DE\u30EA\u30FC",
|
|
11923
|
+
"\u307E\u3068\u3081\u3066",
|
|
11924
|
+
"\u6574\u7406",
|
|
11925
|
+
"summarize",
|
|
11926
|
+
"summary",
|
|
11927
|
+
"recap",
|
|
11928
|
+
"overview"
|
|
11929
|
+
];
|
|
11930
|
+
}
|
|
11931
|
+
});
|
|
11932
|
+
|
|
11933
|
+
// src/services/ai-response/providers/base-provider.ts
|
|
11934
|
+
var BaseAIProvider2;
|
|
11935
|
+
var init_base_provider = __esm({
|
|
11936
|
+
"src/services/ai-response/providers/base-provider.ts"() {
|
|
11937
|
+
BaseAIProvider2 = class {
|
|
11938
|
+
config = {};
|
|
11939
|
+
initialized = false;
|
|
11940
|
+
availableModels = [];
|
|
11941
|
+
async initialize(config2) {
|
|
11942
|
+
this.config = config2;
|
|
11943
|
+
this.initialized = true;
|
|
11944
|
+
await this.performInitialization();
|
|
11945
|
+
}
|
|
11946
|
+
async streamCompletion(request2, onChunk) {
|
|
11947
|
+
const response2 = await this.generateCompletion(request2);
|
|
11948
|
+
const chunks = this.chunkResponse(response2.content);
|
|
11949
|
+
for (const chunk2 of chunks) {
|
|
11950
|
+
onChunk(chunk2);
|
|
11951
|
+
await this.delay(50);
|
|
11952
|
+
}
|
|
11953
|
+
return response2;
|
|
11954
|
+
}
|
|
11955
|
+
isAvailable() {
|
|
11956
|
+
return this.initialized && this.checkAvailability();
|
|
11957
|
+
}
|
|
11958
|
+
getAvailableModels() {
|
|
11959
|
+
return this.availableModels;
|
|
11960
|
+
}
|
|
11961
|
+
/**
|
|
11962
|
+
* Chunk response into smaller pieces for simulated streaming
|
|
11963
|
+
*/
|
|
11964
|
+
chunkResponse(text2, chunkSize = 50) {
|
|
11965
|
+
const chunks = [];
|
|
11966
|
+
const words2 = text2.split(" ");
|
|
11967
|
+
for (let i2 = 0; i2 < words2.length; i2 += chunkSize) {
|
|
11968
|
+
chunks.push(words2.slice(i2, i2 + chunkSize).join(" ") + " ");
|
|
11969
|
+
}
|
|
11970
|
+
return chunks;
|
|
11971
|
+
}
|
|
11972
|
+
/**
|
|
11973
|
+
* Utility delay function
|
|
11974
|
+
*/
|
|
11975
|
+
delay(ms) {
|
|
11976
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
11977
|
+
}
|
|
11978
|
+
/**
|
|
11979
|
+
* Retry logic for API calls
|
|
11980
|
+
*/
|
|
11981
|
+
async withRetry(operation, maxRetries = 3) {
|
|
11982
|
+
let lastError;
|
|
11983
|
+
for (let i2 = 0; i2 < maxRetries; i2++) {
|
|
11984
|
+
try {
|
|
11985
|
+
return await operation();
|
|
11986
|
+
} catch (error2) {
|
|
11987
|
+
lastError = error2;
|
|
11988
|
+
if (this.isNonRetryableError(error2)) {
|
|
11989
|
+
throw error2;
|
|
11990
|
+
}
|
|
11991
|
+
if (i2 < maxRetries - 1) {
|
|
11992
|
+
await this.delay(Math.pow(2, i2) * 1e3);
|
|
11993
|
+
}
|
|
11994
|
+
}
|
|
11995
|
+
}
|
|
11996
|
+
throw lastError || new Error("Operation failed after retries");
|
|
11997
|
+
}
|
|
11998
|
+
/**
|
|
11999
|
+
* Check if error should not be retried
|
|
12000
|
+
*/
|
|
12001
|
+
isNonRetryableError(error2) {
|
|
12002
|
+
const message2 = error2?.message?.toLowerCase() || "";
|
|
12003
|
+
return message2.includes("invalid api key") || message2.includes("unauthorized") || message2.includes("forbidden");
|
|
12004
|
+
}
|
|
12005
|
+
};
|
|
12006
|
+
}
|
|
12007
|
+
});
|
|
12008
|
+
|
|
12009
|
+
// src/services/ai-response/providers/openai-provider.ts
|
|
12010
|
+
var OpenAIProvider2;
|
|
12011
|
+
var init_openai_provider2 = __esm({
|
|
12012
|
+
"src/services/ai-response/providers/openai-provider.ts"() {
|
|
12013
|
+
init_base_provider();
|
|
12014
|
+
OpenAIProvider2 = class extends BaseAIProvider2 {
|
|
12015
|
+
name = "OpenAI";
|
|
12016
|
+
apiEndpoint = "https://api.openai.com/v1/chat/completions";
|
|
12017
|
+
async performInitialization() {
|
|
12018
|
+
if (!this.config.defaultModel) {
|
|
12019
|
+
this.config.defaultModel = "gpt-3.5-turbo";
|
|
12020
|
+
}
|
|
12021
|
+
this.availableModels = [
|
|
12022
|
+
"gpt-4",
|
|
12023
|
+
"gpt-4-turbo-preview",
|
|
12024
|
+
"gpt-3.5-turbo",
|
|
12025
|
+
"gpt-3.5-turbo-16k"
|
|
12026
|
+
];
|
|
12027
|
+
if (!this.config.apiKey) {
|
|
12028
|
+
console.warn("[OpenAI Provider] No API key provided - will use template responses");
|
|
12029
|
+
}
|
|
12030
|
+
}
|
|
12031
|
+
checkAvailability() {
|
|
12032
|
+
return true;
|
|
12033
|
+
}
|
|
12034
|
+
async generateCompletion(request2) {
|
|
12035
|
+
if (!this.config.apiKey) {
|
|
12036
|
+
return this.generateTemplateResponse(request2);
|
|
12037
|
+
}
|
|
12038
|
+
try {
|
|
12039
|
+
const response2 = await this.withRetry(
|
|
12040
|
+
() => this.callOpenAIAPI(request2)
|
|
12041
|
+
);
|
|
12042
|
+
return this.parseOpenAIResponse(response2);
|
|
12043
|
+
} catch (error2) {
|
|
12044
|
+
console.error("[OpenAI Provider] API call failed:", error2);
|
|
12045
|
+
return this.generateTemplateResponse(request2);
|
|
12046
|
+
}
|
|
12047
|
+
}
|
|
12048
|
+
async callOpenAIAPI(request2) {
|
|
12049
|
+
const payload = {
|
|
12050
|
+
model: request2.model || this.config.defaultModel,
|
|
12051
|
+
messages: request2.messages,
|
|
12052
|
+
temperature: request2.temperature ?? 0.7,
|
|
12053
|
+
max_tokens: request2.maxTokens ?? 2e3,
|
|
12054
|
+
stream: false
|
|
12055
|
+
};
|
|
12056
|
+
const response2 = await fetch(this.apiEndpoint, {
|
|
12057
|
+
method: "POST",
|
|
12058
|
+
headers: {
|
|
12059
|
+
"Content-Type": "application/json",
|
|
12060
|
+
"Authorization": `Bearer ${this.config.apiKey}`
|
|
12061
|
+
},
|
|
12062
|
+
body: JSON.stringify(payload)
|
|
12063
|
+
});
|
|
12064
|
+
if (!response2.ok) {
|
|
12065
|
+
const error2 = await response2.text();
|
|
12066
|
+
throw new Error(`OpenAI API error: ${response2.status} - ${error2}`);
|
|
12067
|
+
}
|
|
12068
|
+
return response2.json();
|
|
12069
|
+
}
|
|
12070
|
+
parseOpenAIResponse(response2) {
|
|
12071
|
+
const choice2 = response2.choices?.[0];
|
|
12072
|
+
if (!choice2) {
|
|
12073
|
+
throw new Error("Invalid OpenAI response format");
|
|
12074
|
+
}
|
|
12075
|
+
return {
|
|
12076
|
+
content: choice2.message?.content || "",
|
|
12077
|
+
model: response2.model || this.config.defaultModel || "gpt-3.5-turbo",
|
|
12078
|
+
usage: response2.usage ? {
|
|
12079
|
+
promptTokens: response2.usage.prompt_tokens,
|
|
12080
|
+
completionTokens: response2.usage.completion_tokens,
|
|
12081
|
+
totalTokens: response2.usage.total_tokens
|
|
12082
|
+
} : void 0,
|
|
12083
|
+
finishReason: choice2.finish_reason
|
|
12084
|
+
};
|
|
12085
|
+
}
|
|
12086
|
+
/**
|
|
12087
|
+
* Generate template response when API is unavailable
|
|
12088
|
+
*/
|
|
12089
|
+
generateTemplateResponse(request2) {
|
|
12090
|
+
const lastMessage2 = request2.messages[request2.messages.length - 1];
|
|
12091
|
+
const input3 = lastMessage2?.content || "";
|
|
12092
|
+
const isJapanese = /[ぁ-んァ-ヶー一-龥]/.test(input3);
|
|
12093
|
+
let content2;
|
|
12094
|
+
if (input3.toLowerCase().includes("code") || input3.includes("\u5B9F\u88C5")) {
|
|
12095
|
+
content2 = isJapanese ? `\u30B3\u30FC\u30C9\u306E\u5B9F\u88C5\u306B\u3064\u3044\u3066\u304A\u624B\u4F1D\u3044\u3057\u307E\u3059\u3002
|
|
12096
|
+
|
|
12097
|
+
\`\`\`typescript
|
|
12098
|
+
// \u30B5\u30F3\u30D7\u30EB\u5B9F\u88C5
|
|
12099
|
+
function example() {
|
|
12100
|
+
console.log('Hello World');
|
|
12101
|
+
}
|
|
12102
|
+
\`\`\`
|
|
12103
|
+
|
|
12104
|
+
\u5B9F\u884C\u624B\u9806:
|
|
12105
|
+
1. \u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210
|
|
12106
|
+
2. \`node example.js\` \u3067\u5B9F\u884C` : `I'll help you with the code implementation.
|
|
12107
|
+
|
|
12108
|
+
\`\`\`typescript
|
|
12109
|
+
// Sample implementation
|
|
12110
|
+
function example() {
|
|
12111
|
+
console.log('Hello World');
|
|
12112
|
+
}
|
|
12113
|
+
\`\`\`
|
|
12114
|
+
|
|
12115
|
+
Run instructions:
|
|
12116
|
+
1. Create the file
|
|
12117
|
+
2. Run with \`node example.js\``;
|
|
12118
|
+
} else if (input3.includes("?") || input3.includes("\uFF1F")) {
|
|
12119
|
+
content2 = isJapanese ? `\u3054\u8CEA\u554F\u3042\u308A\u304C\u3068\u3046\u3054\u3056\u3044\u307E\u3059\u3002\u300C${input3.substring(0, 50)}\u300D\u306B\u3064\u3044\u3066\u8AAC\u660E\u3057\u307E\u3059\u3002
|
|
12120
|
+
|
|
12121
|
+
\u8A73\u7D30\u306A\u56DE\u7B54\u3092\u3054\u5E0C\u671B\u306E\u5834\u5408\u306F\u3001\u5177\u4F53\u7684\u306A\u70B9\u3092\u304A\u77E5\u3089\u305B\u304F\u3060\u3055\u3044\u3002` : `Great question about "${input3.substring(0, 50)}". Let me explain.
|
|
12122
|
+
|
|
12123
|
+
For more details, please specify what aspect you'd like to focus on.`;
|
|
12124
|
+
} else {
|
|
12125
|
+
content2 = isJapanese ? `\u300C${input3.substring(0, 50)}\u300D\u306B\u3064\u3044\u3066\u5BFE\u5FDC\u3044\u305F\u3057\u307E\u3059\u3002
|
|
12126
|
+
|
|
12127
|
+
\u6B21\u306E\u30B9\u30C6\u30C3\u30D7:
|
|
12128
|
+
1) \u8A73\u7D30\u3092\u78BA\u8A8D
|
|
12129
|
+
2) \u5B9F\u88C5\u3092\u958B\u59CB
|
|
12130
|
+
3) \u30C6\u30B9\u30C8\u3092\u5B9F\u884C
|
|
12131
|
+
|
|
12132
|
+
\u756A\u53F7\u3067\u304A\u9078\u3073\u304F\u3060\u3055\u3044\u3002` : `I'll help you with "${input3.substring(0, 50)}".
|
|
12133
|
+
|
|
12134
|
+
Next steps:
|
|
12135
|
+
1) Review details
|
|
12136
|
+
2) Start implementation
|
|
12137
|
+
3) Run tests
|
|
12138
|
+
|
|
12139
|
+
Choose a number.`;
|
|
12140
|
+
}
|
|
12141
|
+
return {
|
|
12142
|
+
content: content2,
|
|
12143
|
+
model: "template",
|
|
12144
|
+
usage: {
|
|
12145
|
+
promptTokens: input3.length,
|
|
12146
|
+
completionTokens: content2.length,
|
|
12147
|
+
totalTokens: input3.length + content2.length
|
|
12148
|
+
},
|
|
12149
|
+
finishReason: "stop"
|
|
12150
|
+
};
|
|
12151
|
+
}
|
|
12152
|
+
async streamCompletion(request2, onChunk) {
|
|
12153
|
+
if (!this.config.apiKey) {
|
|
12154
|
+
return super.streamCompletion(request2, onChunk);
|
|
12155
|
+
}
|
|
12156
|
+
try {
|
|
12157
|
+
return super.streamCompletion(request2, onChunk);
|
|
12158
|
+
} catch (error2) {
|
|
12159
|
+
console.error("[OpenAI Provider] Stream failed:", error2);
|
|
12160
|
+
return super.streamCompletion(request2, onChunk);
|
|
12161
|
+
}
|
|
12162
|
+
}
|
|
12163
|
+
};
|
|
12164
|
+
}
|
|
12165
|
+
});
|
|
12166
|
+
|
|
12167
|
+
// src/services/ai-response/providers/anthropic-provider.ts
|
|
12168
|
+
var AnthropicProvider2;
|
|
12169
|
+
var init_anthropic_provider2 = __esm({
|
|
12170
|
+
"src/services/ai-response/providers/anthropic-provider.ts"() {
|
|
12171
|
+
init_base_provider();
|
|
12172
|
+
AnthropicProvider2 = class extends BaseAIProvider2 {
|
|
12173
|
+
name = "Anthropic";
|
|
12174
|
+
apiEndpoint = "https://api.anthropic.com/v1/messages";
|
|
12175
|
+
async performInitialization() {
|
|
12176
|
+
if (!this.config.defaultModel) {
|
|
12177
|
+
this.config.defaultModel = "claude-3-sonnet-20240229";
|
|
12178
|
+
}
|
|
12179
|
+
this.availableModels = [
|
|
12180
|
+
"claude-3-opus-20240229",
|
|
12181
|
+
"claude-3-sonnet-20240229",
|
|
12182
|
+
"claude-3-haiku-20240307",
|
|
12183
|
+
"claude-2.1",
|
|
12184
|
+
"claude-instant-1.2"
|
|
12185
|
+
];
|
|
12186
|
+
if (!this.config.apiKey) {
|
|
12187
|
+
console.warn("[Anthropic Provider] No API key provided - will use template responses");
|
|
12188
|
+
}
|
|
12189
|
+
}
|
|
12190
|
+
checkAvailability() {
|
|
12191
|
+
return true;
|
|
12192
|
+
}
|
|
12193
|
+
async generateCompletion(request2) {
|
|
12194
|
+
if (!this.config.apiKey) {
|
|
12195
|
+
return this.generateTemplateResponse(request2);
|
|
12196
|
+
}
|
|
12197
|
+
try {
|
|
12198
|
+
const response2 = await this.withRetry(
|
|
12199
|
+
() => this.callAnthropicAPI(request2)
|
|
12200
|
+
);
|
|
12201
|
+
return this.parseAnthropicResponse(response2);
|
|
12202
|
+
} catch (error2) {
|
|
12203
|
+
console.error("[Anthropic Provider] API call failed:", error2);
|
|
12204
|
+
return this.generateTemplateResponse(request2);
|
|
12205
|
+
}
|
|
12206
|
+
}
|
|
12207
|
+
async callAnthropicAPI(request2) {
|
|
12208
|
+
const messages2 = request2.messages.map((msg2) => ({
|
|
12209
|
+
role: msg2.role === "system" ? "user" : msg2.role,
|
|
12210
|
+
content: msg2.content
|
|
12211
|
+
}));
|
|
12212
|
+
const systemMessage2 = request2.messages.find((m2) => m2.role === "system");
|
|
12213
|
+
const userMessages = request2.messages.filter((m2) => m2.role !== "system");
|
|
12214
|
+
const payload = {
|
|
12215
|
+
model: request2.model || this.config.defaultModel,
|
|
12216
|
+
messages: userMessages.map((msg2) => ({
|
|
12217
|
+
role: msg2.role === "user" ? "user" : "assistant",
|
|
12218
|
+
content: msg2.content
|
|
12219
|
+
})),
|
|
12220
|
+
max_tokens: request2.maxTokens ?? 2e3,
|
|
12221
|
+
temperature: request2.temperature ?? 0.7,
|
|
12222
|
+
...systemMessage2 && { system: systemMessage2.content }
|
|
12223
|
+
};
|
|
12224
|
+
const response2 = await fetch(this.apiEndpoint, {
|
|
12225
|
+
method: "POST",
|
|
12226
|
+
headers: {
|
|
12227
|
+
"Content-Type": "application/json",
|
|
12228
|
+
"X-API-Key": this.config.apiKey,
|
|
12229
|
+
"anthropic-version": "2023-06-01"
|
|
12230
|
+
},
|
|
12231
|
+
body: JSON.stringify(payload)
|
|
12232
|
+
});
|
|
12233
|
+
if (!response2.ok) {
|
|
12234
|
+
const error2 = await response2.text();
|
|
12235
|
+
throw new Error(`Anthropic API error: ${response2.status} - ${error2}`);
|
|
12236
|
+
}
|
|
12237
|
+
return response2.json();
|
|
12238
|
+
}
|
|
12239
|
+
parseAnthropicResponse(response2) {
|
|
12240
|
+
if (!response2.content || !Array.isArray(response2.content)) {
|
|
12241
|
+
throw new Error("Invalid Anthropic response format");
|
|
12242
|
+
}
|
|
12243
|
+
const textContent = response2.content.filter((block) => block.type === "text").map((block) => block.text).join("\n");
|
|
12244
|
+
return {
|
|
12245
|
+
content: textContent,
|
|
12246
|
+
model: response2.model || this.config.defaultModel || "claude-3-sonnet",
|
|
12247
|
+
usage: response2.usage ? {
|
|
12248
|
+
promptTokens: response2.usage.input_tokens,
|
|
12249
|
+
completionTokens: response2.usage.output_tokens,
|
|
12250
|
+
totalTokens: response2.usage.input_tokens + response2.usage.output_tokens
|
|
12251
|
+
} : void 0,
|
|
12252
|
+
finishReason: response2.stop_reason
|
|
12253
|
+
};
|
|
12254
|
+
}
|
|
12255
|
+
/**
|
|
12256
|
+
* Generate template response when API is unavailable
|
|
12257
|
+
*/
|
|
12258
|
+
generateTemplateResponse(request2) {
|
|
12259
|
+
const lastMessage2 = request2.messages[request2.messages.length - 1];
|
|
12260
|
+
const input3 = lastMessage2?.content || "";
|
|
12261
|
+
const isJapanese = /[ぁ-んァ-ヶー一-龥]/.test(input3);
|
|
12262
|
+
let content2;
|
|
12263
|
+
if (input3.toLowerCase().includes("analyze") || input3.includes("\u5206\u6790")) {
|
|
12264
|
+
content2 = isJapanese ? `\u300C${input3.substring(0, 50)}\u300D\u306E\u5206\u6790\u3092\u884C\u3044\u307E\u3059\u3002
|
|
12265
|
+
|
|
12266
|
+
## \u5206\u6790\u7D50\u679C
|
|
12267
|
+
|
|
12268
|
+
### 1. \u73FE\u72B6
|
|
12269
|
+
- \u30DD\u30A4\u30F3\u30C81
|
|
12270
|
+
- \u30DD\u30A4\u30F3\u30C82
|
|
12271
|
+
|
|
12272
|
+
### 2. \u8AB2\u984C
|
|
12273
|
+
- \u8AB2\u984C1
|
|
12274
|
+
- \u8AB2\u984C2
|
|
12275
|
+
|
|
12276
|
+
### 3. \u63D0\u6848
|
|
12277
|
+
- \u6539\u5584\u68481
|
|
12278
|
+
- \u6539\u5584\u68482
|
|
12279
|
+
|
|
12280
|
+
\u8A73\u7D30\u306A\u5206\u6790\u304C\u5FC5\u8981\u306A\u5834\u5408\u306F\u304A\u77E5\u3089\u305B\u304F\u3060\u3055\u3044\u3002` : `I'll analyze "${input3.substring(0, 50)}".
|
|
12281
|
+
|
|
12282
|
+
## Analysis
|
|
12283
|
+
|
|
12284
|
+
### 1. Current State
|
|
12285
|
+
- Point 1
|
|
12286
|
+
- Point 2
|
|
12287
|
+
|
|
12288
|
+
### 2. Issues
|
|
12289
|
+
- Issue 1
|
|
12290
|
+
- Issue 2
|
|
12291
|
+
|
|
12292
|
+
### 3. Recommendations
|
|
12293
|
+
- Solution 1
|
|
12294
|
+
- Solution 2
|
|
12295
|
+
|
|
12296
|
+
Let me know if you need deeper analysis.`;
|
|
12297
|
+
} else if (input3.toLowerCase().includes("explain") || input3.includes("\u8AAC\u660E")) {
|
|
12298
|
+
content2 = isJapanese ? `\u8A73\u3057\u304F\u8AAC\u660E\u3044\u305F\u3057\u307E\u3059\u3002
|
|
12299
|
+
|
|
12300
|
+
## \u6982\u8981
|
|
12301
|
+
${input3.substring(0, 50)}\u306B\u3064\u3044\u3066\u3001\u4EE5\u4E0B\u306E\u89B3\u70B9\u304B\u3089\u8AAC\u660E\u3057\u307E\u3059\uFF1A
|
|
12302
|
+
|
|
12303
|
+
1. **\u57FA\u672C\u6982\u5FF5**
|
|
12304
|
+
- \u5B9A\u7FA9\u3068\u80CC\u666F
|
|
12305
|
+
- \u91CD\u8981\u6027
|
|
12306
|
+
|
|
12307
|
+
2. **\u5B9F\u88C5\u8A73\u7D30**
|
|
12308
|
+
- \u5177\u4F53\u7684\u306A\u624B\u9806
|
|
12309
|
+
- \u30D9\u30B9\u30C8\u30D7\u30E9\u30AF\u30C6\u30A3\u30B9
|
|
12310
|
+
|
|
12311
|
+
3. **\u6CE8\u610F\u70B9**
|
|
12312
|
+
- \u3088\u304F\u3042\u308B\u9593\u9055\u3044
|
|
12313
|
+
- \u56DE\u907F\u65B9\u6CD5
|
|
12314
|
+
|
|
12315
|
+
\u3055\u3089\u306B\u8A73\u3057\u3044\u60C5\u5831\u304C\u5FC5\u8981\u3067\u3057\u3087\u3046\u304B\uFF1F` : `Let me explain in detail.
|
|
12316
|
+
|
|
12317
|
+
## Overview
|
|
12318
|
+
Regarding "${input3.substring(0, 50)}", I'll cover:
|
|
12319
|
+
|
|
12320
|
+
1. **Core Concepts**
|
|
12321
|
+
- Definition and background
|
|
12322
|
+
- Importance
|
|
12323
|
+
|
|
12324
|
+
2. **Implementation Details**
|
|
12325
|
+
- Step-by-step process
|
|
12326
|
+
- Best practices
|
|
12327
|
+
|
|
12328
|
+
3. **Considerations**
|
|
12329
|
+
- Common pitfalls
|
|
12330
|
+
- How to avoid them
|
|
12331
|
+
|
|
12332
|
+
Would you like more specific information?`;
|
|
12333
|
+
} else {
|
|
12334
|
+
content2 = isJapanese ? `\u627F\u77E5\u3044\u305F\u3057\u307E\u3057\u305F\u3002\u300C${input3.substring(0, 50)}\u300D\u306B\u3064\u3044\u3066\u5BFE\u5FDC\u3057\u307E\u3059\u3002
|
|
12335
|
+
|
|
12336
|
+
\u69CB\u9020\u7684\u306B\u30A2\u30D7\u30ED\u30FC\u30C1\u3059\u308B\u305F\u3081\u3001\u4EE5\u4E0B\u306E\u624B\u9806\u3092\u63D0\u6848\u3057\u307E\u3059\uFF1A
|
|
12337
|
+
|
|
12338
|
+
1. **\u8981\u4EF6\u306E\u660E\u78BA\u5316**
|
|
12339
|
+
2. **\u5B9F\u88C5\u8A08\u753B\u306E\u7B56\u5B9A**
|
|
12340
|
+
3. **\u6BB5\u968E\u7684\u306A\u5B9F\u88C5**
|
|
12341
|
+
4. **\u30C6\u30B9\u30C8\u3068\u691C\u8A3C**
|
|
12342
|
+
|
|
12343
|
+
\u3069\u306E\u6BB5\u968E\u304B\u3089\u59CB\u3081\u307E\u3057\u3087\u3046\u304B\uFF1F` : `I understand. I'll help with "${input3.substring(0, 50)}".
|
|
12344
|
+
|
|
12345
|
+
For a structured approach, I suggest:
|
|
12346
|
+
|
|
12347
|
+
1. **Clarify requirements**
|
|
12348
|
+
2. **Create implementation plan**
|
|
12349
|
+
3. **Phased implementation**
|
|
12350
|
+
4. **Testing and validation**
|
|
12351
|
+
|
|
12352
|
+
Which phase shall we start with?`;
|
|
12353
|
+
}
|
|
12354
|
+
return {
|
|
12355
|
+
content: content2,
|
|
12356
|
+
model: "template-claude",
|
|
12357
|
+
usage: {
|
|
12358
|
+
promptTokens: input3.length,
|
|
12359
|
+
completionTokens: content2.length,
|
|
12360
|
+
totalTokens: input3.length + content2.length
|
|
12361
|
+
},
|
|
12362
|
+
finishReason: "stop"
|
|
12363
|
+
};
|
|
12364
|
+
}
|
|
12365
|
+
};
|
|
12366
|
+
}
|
|
12367
|
+
});
|
|
12368
|
+
|
|
12369
|
+
// src/services/ai-response/providers/template-provider.ts
|
|
12370
|
+
var TemplateProvider;
|
|
12371
|
+
var init_template_provider = __esm({
|
|
12372
|
+
"src/services/ai-response/providers/template-provider.ts"() {
|
|
12373
|
+
init_base_provider();
|
|
12374
|
+
TemplateProvider = class extends BaseAIProvider2 {
|
|
12375
|
+
name = "Template";
|
|
12376
|
+
async performInitialization() {
|
|
12377
|
+
this.availableModels = ["template-v1"];
|
|
12378
|
+
}
|
|
12379
|
+
checkAvailability() {
|
|
12380
|
+
return true;
|
|
12381
|
+
}
|
|
12382
|
+
async generateCompletion(request2) {
|
|
12383
|
+
const lastMessage2 = request2.messages[request2.messages.length - 1];
|
|
12384
|
+
const input3 = lastMessage2?.content || "";
|
|
12385
|
+
const context2 = request2.messages.slice(-5).map((m2) => m2.content).join("\n");
|
|
12386
|
+
const isJapanese = /[ぁ-んァ-ヶー一-龥]/.test(input3);
|
|
12387
|
+
const intent2 = this.analyzeIntent(input3, context2);
|
|
12388
|
+
const content2 = this.generateTemplateByIntent(intent2, input3, isJapanese);
|
|
12389
|
+
return {
|
|
12390
|
+
content: content2,
|
|
12391
|
+
model: "template-v1",
|
|
12392
|
+
usage: {
|
|
12393
|
+
promptTokens: input3.length,
|
|
12394
|
+
completionTokens: content2.length,
|
|
12395
|
+
totalTokens: input3.length + content2.length
|
|
12396
|
+
},
|
|
12397
|
+
finishReason: "stop"
|
|
12398
|
+
};
|
|
12399
|
+
}
|
|
12400
|
+
analyzeIntent(input3, context2) {
|
|
12401
|
+
const lower = input3.toLowerCase();
|
|
12402
|
+
const combined = (context2 + " " + input3).toLowerCase();
|
|
12403
|
+
if (lower.includes("implement") || lower.includes("\u5B9F\u88C5")) {
|
|
12404
|
+
return "implementation";
|
|
12405
|
+
}
|
|
12406
|
+
if (lower.includes("debug") || lower.includes("error") || lower.includes("\u30A8\u30E9\u30FC")) {
|
|
12407
|
+
return "debugging";
|
|
12408
|
+
}
|
|
12409
|
+
if (lower.includes("explain") || lower.includes("\u8AAC\u660E")) {
|
|
12410
|
+
return "explanation";
|
|
12411
|
+
}
|
|
12412
|
+
if (lower.includes("?") || lower.includes("\uFF1F")) {
|
|
12413
|
+
return "question";
|
|
12414
|
+
}
|
|
12415
|
+
if (combined.includes("continue") || combined.includes("\u7D9A")) {
|
|
12416
|
+
return "continuation";
|
|
12417
|
+
}
|
|
12418
|
+
if (lower.includes("test") || lower.includes("\u30C6\u30B9\u30C8")) {
|
|
12419
|
+
return "testing";
|
|
12420
|
+
}
|
|
12421
|
+
if (lower.includes("optimize") || lower.includes("\u6700\u9069\u5316")) {
|
|
12422
|
+
return "optimization";
|
|
12423
|
+
}
|
|
12424
|
+
return "general";
|
|
12425
|
+
}
|
|
12426
|
+
generateTemplateByIntent(intent2, input3, isJapanese) {
|
|
12427
|
+
const cleanInput = input3.substring(0, 80);
|
|
12428
|
+
switch (intent2) {
|
|
12429
|
+
case "implementation":
|
|
12430
|
+
return this.generateImplementationTemplate(cleanInput, isJapanese);
|
|
12431
|
+
case "debugging":
|
|
12432
|
+
return this.generateDebuggingTemplate(cleanInput, isJapanese);
|
|
12433
|
+
case "explanation":
|
|
12434
|
+
return this.generateExplanationTemplate(cleanInput, isJapanese);
|
|
12435
|
+
case "question":
|
|
12436
|
+
return this.generateQuestionTemplate(cleanInput, isJapanese);
|
|
12437
|
+
case "continuation":
|
|
12438
|
+
return this.generateContinuationTemplate(cleanInput, isJapanese);
|
|
12439
|
+
case "testing":
|
|
12440
|
+
return this.generateTestingTemplate(cleanInput, isJapanese);
|
|
12441
|
+
case "optimization":
|
|
12442
|
+
return this.generateOptimizationTemplate(cleanInput, isJapanese);
|
|
12443
|
+
default:
|
|
12444
|
+
return this.generateGeneralTemplate(cleanInput, isJapanese);
|
|
12445
|
+
}
|
|
12446
|
+
}
|
|
12447
|
+
generateImplementationTemplate(input3, isJapanese) {
|
|
12448
|
+
return isJapanese ? `\u300C${input3}\u300D\u306E\u5B9F\u88C5\u3092\u958B\u59CB\u3057\u307E\u3059\u3002
|
|
12449
|
+
|
|
12450
|
+
## \u5B9F\u88C5\u8A08\u753B
|
|
12451
|
+
|
|
12452
|
+
### 1. \u30A2\u30FC\u30AD\u30C6\u30AF\u30C1\u30E3\u8A2D\u8A08
|
|
12453
|
+
- \u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u69CB\u9020
|
|
12454
|
+
- \u30C7\u30FC\u30BF\u30D5\u30ED\u30FC
|
|
12455
|
+
- \u30A8\u30E9\u30FC\u30CF\u30F3\u30C9\u30EA\u30F3\u30B0
|
|
12456
|
+
|
|
12457
|
+
### 2. \u57FA\u672C\u5B9F\u88C5
|
|
12458
|
+
\`\`\`typescript
|
|
12459
|
+
// \u30B5\u30F3\u30D7\u30EB\u5B9F\u88C5
|
|
12460
|
+
class Implementation {
|
|
12461
|
+
constructor(private config: Config) {}
|
|
12462
|
+
|
|
12463
|
+
async execute(): Promise<Result> {
|
|
12464
|
+
// \u5B9F\u88C5\u30ED\u30B8\u30C3\u30AF
|
|
12465
|
+
return this.process();
|
|
12466
|
+
}
|
|
12467
|
+
}
|
|
12468
|
+
\`\`\`
|
|
12469
|
+
|
|
12470
|
+
### 3. \u5B9F\u884C\u624B\u9806
|
|
12471
|
+
1. \u4F9D\u5B58\u95A2\u4FC2\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB: \`pnpm install\`
|
|
12472
|
+
2. \u30D3\u30EB\u30C9: \`pnpm build\`
|
|
12473
|
+
3. \u30C6\u30B9\u30C8\u5B9F\u884C: \`pnpm test\`
|
|
12474
|
+
|
|
12475
|
+
\u6B21\u306E\u30B9\u30C6\u30C3\u30D7\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF1A
|
|
12476
|
+
1) \u30A8\u30E9\u30FC\u30CF\u30F3\u30C9\u30EA\u30F3\u30B0\u3092\u8FFD\u52A0
|
|
12477
|
+
2) \u30C6\u30B9\u30C8\u30B1\u30FC\u30B9\u3092\u4F5C\u6210
|
|
12478
|
+
3) \u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u6700\u9069\u5316` : `I'll implement "${input3}".
|
|
12479
|
+
|
|
12480
|
+
## Implementation Plan
|
|
12481
|
+
|
|
12482
|
+
### 1. Architecture Design
|
|
12483
|
+
- Component structure
|
|
12484
|
+
- Data flow
|
|
12485
|
+
- Error handling
|
|
12486
|
+
|
|
12487
|
+
### 2. Base Implementation
|
|
12488
|
+
\`\`\`typescript
|
|
12489
|
+
// Sample implementation
|
|
12490
|
+
class Implementation {
|
|
12491
|
+
constructor(private config: Config) {}
|
|
12492
|
+
|
|
12493
|
+
async execute(): Promise<Result> {
|
|
12494
|
+
// Implementation logic
|
|
12495
|
+
return this.process();
|
|
12496
|
+
}
|
|
12497
|
+
}
|
|
12498
|
+
\`\`\`
|
|
12499
|
+
|
|
12500
|
+
### 3. Run Instructions
|
|
12501
|
+
1. Install dependencies: \`npm install\`
|
|
12502
|
+
2. Build: \`npm run build\`
|
|
12503
|
+
3. Run tests: \`npm test\`
|
|
12504
|
+
|
|
12505
|
+
Choose next step:
|
|
12506
|
+
1) Add error handling
|
|
12507
|
+
2) Create test cases
|
|
12508
|
+
3) Optimize performance`;
|
|
12509
|
+
}
|
|
12510
|
+
generateDebuggingTemplate(input3, isJapanese) {
|
|
12511
|
+
return isJapanese ? `\u300C${input3}\u300D\u306E\u30C7\u30D0\u30C3\u30B0\u3092\u652F\u63F4\u3057\u307E\u3059\u3002
|
|
12512
|
+
|
|
12513
|
+
## \u30C7\u30D0\u30C3\u30B0\u624B\u9806
|
|
12514
|
+
|
|
12515
|
+
### 1. \u554F\u984C\u306E\u7279\u5B9A
|
|
12516
|
+
- \u30A8\u30E9\u30FC\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u78BA\u8A8D
|
|
12517
|
+
- \u30B9\u30BF\u30C3\u30AF\u30C8\u30EC\u30FC\u30B9\u306E\u5206\u6790
|
|
12518
|
+
- \u518D\u73FE\u6761\u4EF6\u306E\u78BA\u8A8D
|
|
12519
|
+
|
|
12520
|
+
### 2. \u4E00\u822C\u7684\u306A\u539F\u56E0
|
|
12521
|
+
- \u578B\u306E\u4E0D\u4E00\u81F4
|
|
12522
|
+
- Null/Undefined\u53C2\u7167
|
|
12523
|
+
- \u975E\u540C\u671F\u51E6\u7406\u306E\u554F\u984C
|
|
12524
|
+
- \u4F9D\u5B58\u95A2\u4FC2\u306E\u4E0D\u8DB3
|
|
12525
|
+
|
|
12526
|
+
### 3. \u89E3\u6C7A\u7B56
|
|
12527
|
+
\`\`\`typescript
|
|
12528
|
+
// \u30C7\u30D0\u30C3\u30B0\u30B3\u30FC\u30C9\u4F8B
|
|
12529
|
+
try {
|
|
12530
|
+
// \u554F\u984C\u306E\u3042\u308B\u30B3\u30FC\u30C9
|
|
12531
|
+
const result = await operation();
|
|
12532
|
+
console.log('Success:', result);
|
|
12533
|
+
} catch (error) {
|
|
12534
|
+
console.error('Error details:', error);
|
|
12535
|
+
// \u30A8\u30E9\u30FC\u51E6\u7406
|
|
12536
|
+
}
|
|
12537
|
+
\`\`\`
|
|
12538
|
+
|
|
12539
|
+
\u6B21\u306E\u78BA\u8A8D\u4E8B\u9805\uFF1A
|
|
12540
|
+
1) \u30B3\u30F3\u30BD\u30FC\u30EB\u30ED\u30B0\u3092\u78BA\u8A8D
|
|
12541
|
+
2) \u30D6\u30EC\u30FC\u30AF\u30DD\u30A4\u30F3\u30C8\u3092\u8A2D\u5B9A
|
|
12542
|
+
3) \u5358\u4F53\u30C6\u30B9\u30C8\u3092\u5B9F\u884C` : `I'll help debug "${input3}".
|
|
12543
|
+
|
|
12544
|
+
## Debug Process
|
|
12545
|
+
|
|
12546
|
+
### 1. Problem Identification
|
|
12547
|
+
- Check error messages
|
|
12548
|
+
- Analyze stack trace
|
|
12549
|
+
- Verify reproduction steps
|
|
12550
|
+
|
|
12551
|
+
### 2. Common Causes
|
|
12552
|
+
- Type mismatches
|
|
12553
|
+
- Null/Undefined references
|
|
12554
|
+
- Async handling issues
|
|
12555
|
+
- Missing dependencies
|
|
12556
|
+
|
|
12557
|
+
### 3. Solution
|
|
12558
|
+
\`\`\`typescript
|
|
12559
|
+
// Debug code example
|
|
12560
|
+
try {
|
|
12561
|
+
// Problematic code
|
|
12562
|
+
const result = await operation();
|
|
12563
|
+
console.log('Success:', result);
|
|
12564
|
+
} catch (error) {
|
|
12565
|
+
console.error('Error details:', error);
|
|
12566
|
+
// Error handling
|
|
12567
|
+
}
|
|
12568
|
+
\`\`\`
|
|
12569
|
+
|
|
12570
|
+
Next checks:
|
|
12571
|
+
1) Review console logs
|
|
12572
|
+
2) Set breakpoints
|
|
12573
|
+
3) Run unit tests`;
|
|
12574
|
+
}
|
|
12575
|
+
generateExplanationTemplate(input3, isJapanese) {
|
|
12576
|
+
return isJapanese ? `\u300C${input3}\u300D\u306B\u3064\u3044\u3066\u8A73\u3057\u304F\u8AAC\u660E\u3057\u307E\u3059\u3002
|
|
12577
|
+
|
|
12578
|
+
## \u6982\u8981
|
|
12579
|
+
\u3053\u306E\u6982\u5FF5\u306F\u3001\u30BD\u30D5\u30C8\u30A6\u30A7\u30A2\u958B\u767A\u306B\u304A\u3044\u3066\u91CD\u8981\u306A\u5F79\u5272\u3092\u679C\u305F\u3057\u307E\u3059\u3002
|
|
12580
|
+
|
|
12581
|
+
## \u8A73\u7D30\u8AAC\u660E
|
|
12582
|
+
|
|
12583
|
+
### \u57FA\u672C\u539F\u7406
|
|
12584
|
+
- \u30B3\u30A2\u30B3\u30F3\u30BB\u30D7\u30C8
|
|
12585
|
+
- \u52D5\u4F5C\u539F\u7406
|
|
12586
|
+
- \u5229\u7528\u30B7\u30FC\u30F3
|
|
12587
|
+
|
|
12588
|
+
### \u5B9F\u88C5\u4F8B
|
|
12589
|
+
\`\`\`typescript
|
|
12590
|
+
// \u6982\u5FF5\u306E\u5B9F\u88C5\u4F8B
|
|
12591
|
+
const example = {
|
|
12592
|
+
property: 'value',
|
|
12593
|
+
method: () => 'result'
|
|
12594
|
+
};
|
|
12595
|
+
\`\`\`
|
|
12596
|
+
|
|
12597
|
+
### \u30E1\u30EA\u30C3\u30C8\u30FB\u30C7\u30E1\u30EA\u30C3\u30C8
|
|
12598
|
+
**\u30E1\u30EA\u30C3\u30C8:**
|
|
12599
|
+
- \u52B9\u7387\u7684\u306A\u51E6\u7406
|
|
12600
|
+
- \u4FDD\u5B88\u6027\u306E\u5411\u4E0A
|
|
12601
|
+
|
|
12602
|
+
**\u30C7\u30E1\u30EA\u30C3\u30C8:**
|
|
12603
|
+
- \u5B66\u7FD2\u30B3\u30B9\u30C8
|
|
12604
|
+
- \u521D\u671F\u8A2D\u5B9A\u306E\u8907\u96D1\u3055
|
|
12605
|
+
|
|
12606
|
+
\u3055\u3089\u306B\u8A73\u3057\u304F\u77E5\u308A\u305F\u3044\u70B9\u306F\u3042\u308A\u307E\u3059\u304B\uFF1F` : `Let me explain "${input3}" in detail.
|
|
12607
|
+
|
|
12608
|
+
## Overview
|
|
12609
|
+
This concept plays an important role in software development.
|
|
12610
|
+
|
|
12611
|
+
## Detailed Explanation
|
|
12612
|
+
|
|
12613
|
+
### Core Principles
|
|
12614
|
+
- Core concepts
|
|
12615
|
+
- How it works
|
|
12616
|
+
- Use cases
|
|
12617
|
+
|
|
12618
|
+
### Implementation Example
|
|
12619
|
+
\`\`\`typescript
|
|
12620
|
+
// Concept implementation
|
|
12621
|
+
const example = {
|
|
12622
|
+
property: 'value',
|
|
12623
|
+
method: () => 'result'
|
|
12624
|
+
};
|
|
12625
|
+
\`\`\`
|
|
12626
|
+
|
|
12627
|
+
### Pros and Cons
|
|
12628
|
+
**Pros:**
|
|
12629
|
+
- Efficient processing
|
|
12630
|
+
- Better maintainability
|
|
12631
|
+
|
|
12632
|
+
**Cons:**
|
|
12633
|
+
- Learning curve
|
|
12634
|
+
- Initial setup complexity
|
|
12635
|
+
|
|
12636
|
+
Would you like to know more?`;
|
|
12637
|
+
}
|
|
12638
|
+
generateQuestionTemplate(input3, isJapanese) {
|
|
12639
|
+
return isJapanese ? `\u3054\u8CEA\u554F\u300C${input3}\u300D\u306B\u304A\u7B54\u3048\u3057\u307E\u3059\u3002
|
|
12640
|
+
|
|
12641
|
+
## \u56DE\u7B54
|
|
12642
|
+
|
|
12643
|
+
\u7C21\u6F54\u306B\u7B54\u3048\u308B\u3068\u3001\u3053\u308C\u306F\u72B6\u6CC1\u3084\u8981\u4EF6\u306B\u3088\u3063\u3066\u7570\u306A\u308A\u307E\u3059\u3002
|
|
12644
|
+
|
|
12645
|
+
### \u8A73\u7D30\u306A\u56DE\u7B54
|
|
12646
|
+
|
|
12647
|
+
1. **\u6280\u8853\u7684\u89B3\u70B9**
|
|
12648
|
+
- \u5B9F\u88C5\u306E\u8907\u96D1\u3055
|
|
12649
|
+
- \u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u3078\u306E\u5F71\u97FF
|
|
12650
|
+
|
|
12651
|
+
2. **\u5B9F\u7528\u7684\u89B3\u70B9**
|
|
12652
|
+
- \u4F7F\u7528\u983B\u5EA6
|
|
12653
|
+
- \u30E1\u30F3\u30C6\u30CA\u30F3\u30B9\u6027
|
|
12654
|
+
|
|
12655
|
+
3. **\u30D9\u30B9\u30C8\u30D7\u30E9\u30AF\u30C6\u30A3\u30B9**
|
|
12656
|
+
- \u63A8\u5968\u3055\u308C\u308B\u65B9\u6CD5
|
|
12657
|
+
- \u907F\u3051\u308B\u3079\u304D\u30D1\u30BF\u30FC\u30F3
|
|
12658
|
+
|
|
12659
|
+
### \u95A2\u9023\u60C5\u5831
|
|
12660
|
+
- \u53C2\u8003\u3068\u306A\u308B\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8
|
|
12661
|
+
- \u985E\u4F3C\u306E\u554F\u984C\u3068\u89E3\u6C7A\u7B56
|
|
12662
|
+
|
|
12663
|
+
\u4ED6\u306B\u78BA\u8A8D\u3057\u305F\u3044\u70B9\u306F\u3042\u308A\u307E\u3059\u304B\uFF1F` : `I'll answer your question: "${input3}"
|
|
12664
|
+
|
|
12665
|
+
## Answer
|
|
12666
|
+
|
|
12667
|
+
In brief, this depends on the specific situation and requirements.
|
|
12668
|
+
|
|
12669
|
+
### Detailed Response
|
|
12670
|
+
|
|
12671
|
+
1. **Technical Perspective**
|
|
12672
|
+
- Implementation complexity
|
|
12673
|
+
- Performance impact
|
|
12674
|
+
|
|
12675
|
+
2. **Practical Perspective**
|
|
12676
|
+
- Usage frequency
|
|
12677
|
+
- Maintainability
|
|
12678
|
+
|
|
12679
|
+
3. **Best Practices**
|
|
12680
|
+
- Recommended approaches
|
|
12681
|
+
- Patterns to avoid
|
|
12682
|
+
|
|
12683
|
+
### Related Information
|
|
12684
|
+
- Reference documentation
|
|
12685
|
+
- Similar issues and solutions
|
|
12686
|
+
|
|
12687
|
+
Any other questions?`;
|
|
12688
|
+
}
|
|
12689
|
+
generateContinuationTemplate(input3, isJapanese) {
|
|
12690
|
+
return isJapanese ? `\u524D\u56DE\u306E\u7D9A\u304D\u304B\u3089\u9032\u3081\u307E\u3059\u3002
|
|
12691
|
+
|
|
12692
|
+
## \u9032\u884C\u72B6\u6CC1
|
|
12693
|
+
\u3053\u308C\u307E\u3067\u306E\u4F5C\u696D\u3092\u78BA\u8A8D\u3057\u307E\u3057\u305F\u3002
|
|
12694
|
+
|
|
12695
|
+
## \u6B21\u306E\u30B9\u30C6\u30C3\u30D7
|
|
12696
|
+
|
|
12697
|
+
\u4EE5\u4E0B\u304B\u3089\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF1A
|
|
12698
|
+
|
|
12699
|
+
1) **\u5B9F\u88C5\u3092\u7D99\u7D9A**
|
|
12700
|
+
- \u6B8B\u308A\u306E\u6A5F\u80FD\u3092\u5B9F\u88C5
|
|
12701
|
+
- \u30A8\u30C3\u30B8\u30B1\u30FC\u30B9\u306E\u51E6\u7406
|
|
12702
|
+
|
|
12703
|
+
2) **\u30C6\u30B9\u30C8\u3092\u8FFD\u52A0**
|
|
12704
|
+
- \u30E6\u30CB\u30C3\u30C8\u30C6\u30B9\u30C8
|
|
12705
|
+
- \u7D71\u5408\u30C6\u30B9\u30C8
|
|
12706
|
+
|
|
12707
|
+
3) **\u30EA\u30D5\u30A1\u30AF\u30BF\u30EA\u30F3\u30B0**
|
|
12708
|
+
- \u30B3\u30FC\u30C9\u306E\u6574\u7406
|
|
12709
|
+
- \u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u6539\u5584
|
|
12710
|
+
|
|
12711
|
+
4) **\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u4F5C\u6210**
|
|
12712
|
+
- API\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8
|
|
12713
|
+
- \u4F7F\u7528\u4F8B\u306E\u8FFD\u52A0
|
|
12714
|
+
|
|
12715
|
+
\u756A\u53F7\u3067\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF081-4\uFF09\u3002` : `Let's continue from where we left off.
|
|
12716
|
+
|
|
12717
|
+
## Progress
|
|
12718
|
+
I've reviewed our previous work.
|
|
12719
|
+
|
|
12720
|
+
## Next Steps
|
|
12721
|
+
|
|
12722
|
+
Please choose:
|
|
12723
|
+
|
|
12724
|
+
1) **Continue Implementation**
|
|
12725
|
+
- Remaining features
|
|
12726
|
+
- Edge case handling
|
|
12727
|
+
|
|
12728
|
+
2) **Add Tests**
|
|
12729
|
+
- Unit tests
|
|
12730
|
+
- Integration tests
|
|
12731
|
+
|
|
12732
|
+
3) **Refactoring**
|
|
12733
|
+
- Code organization
|
|
12734
|
+
- Performance improvements
|
|
12735
|
+
|
|
12736
|
+
4) **Documentation**
|
|
12737
|
+
- API documentation
|
|
12738
|
+
- Usage examples
|
|
12739
|
+
|
|
12740
|
+
Choose a number (1-4).`;
|
|
12741
|
+
}
|
|
12742
|
+
generateTestingTemplate(input3, isJapanese) {
|
|
12743
|
+
return isJapanese ? `\u300C${input3}\u300D\u306E\u30C6\u30B9\u30C8\u3092\u4F5C\u6210\u3057\u307E\u3059\u3002
|
|
12744
|
+
|
|
12745
|
+
## \u30C6\u30B9\u30C8\u6226\u7565
|
|
12746
|
+
|
|
12747
|
+
### \u30E6\u30CB\u30C3\u30C8\u30C6\u30B9\u30C8
|
|
12748
|
+
\`\`\`typescript
|
|
12749
|
+
describe('Component', () => {
|
|
12750
|
+
it('should work correctly', () => {
|
|
12751
|
+
const result = component.method();
|
|
12752
|
+
expect(result).toBe(expected);
|
|
12753
|
+
});
|
|
12754
|
+
|
|
12755
|
+
it('should handle errors', () => {
|
|
12756
|
+
expect(() => component.invalid()).toThrow();
|
|
12757
|
+
});
|
|
12758
|
+
});
|
|
12759
|
+
\`\`\`
|
|
12760
|
+
|
|
12761
|
+
### \u7D71\u5408\u30C6\u30B9\u30C8
|
|
12762
|
+
- API \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306E\u30C6\u30B9\u30C8
|
|
12763
|
+
- \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u63A5\u7D9A\u306E\u30C6\u30B9\u30C8
|
|
12764
|
+
- \u5916\u90E8\u30B5\u30FC\u30D3\u30B9\u3068\u306E\u9023\u643A\u30C6\u30B9\u30C8
|
|
12765
|
+
|
|
12766
|
+
### \u5B9F\u884C\u30B3\u30DE\u30F3\u30C9
|
|
12767
|
+
- \`pnpm test\` - \u5168\u30C6\u30B9\u30C8\u5B9F\u884C
|
|
12768
|
+
- \`pnpm test:watch\` - \u30A6\u30A9\u30C3\u30C1\u30E2\u30FC\u30C9
|
|
12769
|
+
- \`pnpm test:coverage\` - \u30AB\u30D0\u30EC\u30C3\u30B8\u30EC\u30DD\u30FC\u30C8
|
|
12770
|
+
|
|
12771
|
+
\u30C6\u30B9\u30C8\u30B1\u30FC\u30B9\u3092\u8FFD\u52A0\u3057\u307E\u3059\u304B\uFF1F` : `I'll create tests for "${input3}".
|
|
12772
|
+
|
|
12773
|
+
## Test Strategy
|
|
12774
|
+
|
|
12775
|
+
### Unit Tests
|
|
12776
|
+
\`\`\`typescript
|
|
12777
|
+
describe('Component', () => {
|
|
12778
|
+
it('should work correctly', () => {
|
|
12779
|
+
const result = component.method();
|
|
12780
|
+
expect(result).toBe(expected);
|
|
12781
|
+
});
|
|
12782
|
+
|
|
12783
|
+
it('should handle errors', () => {
|
|
12784
|
+
expect(() => component.invalid()).toThrow();
|
|
12785
|
+
});
|
|
12786
|
+
});
|
|
12787
|
+
\`\`\`
|
|
12788
|
+
|
|
12789
|
+
### Integration Tests
|
|
12790
|
+
- API endpoint tests
|
|
12791
|
+
- Database connection tests
|
|
12792
|
+
- External service integration
|
|
12793
|
+
|
|
12794
|
+
### Run Commands
|
|
12795
|
+
- \`npm test\` - Run all tests
|
|
12796
|
+
- \`npm test:watch\` - Watch mode
|
|
12797
|
+
- \`npm test:coverage\` - Coverage report
|
|
12798
|
+
|
|
12799
|
+
Add more test cases?`;
|
|
12800
|
+
}
|
|
12801
|
+
generateOptimizationTemplate(input3, isJapanese) {
|
|
12802
|
+
return isJapanese ? `\u300C${input3}\u300D\u306E\u6700\u9069\u5316\u3092\u884C\u3044\u307E\u3059\u3002
|
|
12803
|
+
|
|
12804
|
+
## \u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u5206\u6790
|
|
12805
|
+
|
|
12806
|
+
### \u73FE\u72B6\u306E\u8AB2\u984C
|
|
12807
|
+
- \u51E6\u7406\u6642\u9593: ~500ms
|
|
12808
|
+
- \u30E1\u30E2\u30EA\u4F7F\u7528\u91CF: ~50MB
|
|
12809
|
+
- CPU\u4F7F\u7528\u7387: \u9AD8
|
|
12810
|
+
|
|
12811
|
+
### \u6700\u9069\u5316\u6226\u7565
|
|
12812
|
+
|
|
12813
|
+
1. **\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306E\u6539\u5584**
|
|
12814
|
+
\`\`\`typescript
|
|
12815
|
+
// Before: O(n\xB2)
|
|
12816
|
+
for (let i = 0; i < n; i++) {
|
|
12817
|
+
for (let j = 0; j < n; j++) {
|
|
12818
|
+
// \u51E6\u7406
|
|
12819
|
+
}
|
|
12820
|
+
}
|
|
12821
|
+
|
|
12822
|
+
// After: O(n log n)
|
|
12823
|
+
items.sort((a, b) => a - b);
|
|
12824
|
+
// \u52B9\u7387\u7684\u306A\u51E6\u7406
|
|
12825
|
+
\`\`\`
|
|
12826
|
+
|
|
12827
|
+
2. **\u30AD\u30E3\u30C3\u30B7\u30F3\u30B0**
|
|
12828
|
+
- \u30E1\u30E2\u30EA\u30AD\u30E3\u30C3\u30B7\u30E5\u306E\u5B9F\u88C5
|
|
12829
|
+
- \u8A08\u7B97\u7D50\u679C\u306E\u518D\u5229\u7528
|
|
12830
|
+
|
|
12831
|
+
3. **\u975E\u540C\u671F\u51E6\u7406**
|
|
12832
|
+
- \u4E26\u5217\u51E6\u7406\u306E\u6D3B\u7528
|
|
12833
|
+
- \u30D0\u30C3\u30C1\u51E6\u7406\u306E\u5B9F\u88C5
|
|
12834
|
+
|
|
12835
|
+
\u6539\u5584\u52B9\u679C\u3092\u6E2C\u5B9A\u3057\u307E\u3059\u304B\uFF1F` : `I'll optimize "${input3}".
|
|
12836
|
+
|
|
12837
|
+
## Performance Analysis
|
|
12838
|
+
|
|
12839
|
+
### Current Issues
|
|
12840
|
+
- Processing time: ~500ms
|
|
12841
|
+
- Memory usage: ~50MB
|
|
12842
|
+
- CPU usage: High
|
|
12843
|
+
|
|
12844
|
+
### Optimization Strategy
|
|
12845
|
+
|
|
12846
|
+
1. **Algorithm Improvement**
|
|
12847
|
+
\`\`\`typescript
|
|
12848
|
+
// Before: O(n\xB2)
|
|
12849
|
+
for (let i = 0; i < n; i++) {
|
|
12850
|
+
for (let j = 0; j < n; j++) {
|
|
12851
|
+
// Process
|
|
12852
|
+
}
|
|
12853
|
+
}
|
|
12854
|
+
|
|
12855
|
+
// After: O(n log n)
|
|
12856
|
+
items.sort((a, b) => a - b);
|
|
12857
|
+
// Efficient processing
|
|
12858
|
+
\`\`\`
|
|
12859
|
+
|
|
12860
|
+
2. **Caching**
|
|
12861
|
+
- Memory cache implementation
|
|
12862
|
+
- Result reuse
|
|
12863
|
+
|
|
12864
|
+
3. **Async Processing**
|
|
12865
|
+
- Parallel processing
|
|
12866
|
+
- Batch processing
|
|
12867
|
+
|
|
12868
|
+
Measure improvements?`;
|
|
12869
|
+
}
|
|
12870
|
+
generateGeneralTemplate(input3, isJapanese) {
|
|
12871
|
+
return isJapanese ? `\u300C${input3}\u300D\u306B\u3064\u3044\u3066\u5BFE\u5FDC\u3044\u305F\u3057\u307E\u3059\u3002
|
|
12872
|
+
|
|
12873
|
+
\u3054\u8981\u671B\u3092\u6B63\u3057\u304F\u7406\u89E3\u3059\u308B\u305F\u3081\u3001\u4EE5\u4E0B\u304B\u3089\u6700\u3082\u8FD1\u3044\u3082\u306E\u3092\u304A\u9078\u3073\u304F\u3060\u3055\u3044\uFF1A
|
|
12874
|
+
|
|
12875
|
+
1) **\u30B3\u30FC\u30C9\u5B9F\u88C5**
|
|
12876
|
+
- \u65B0\u6A5F\u80FD\u306E\u958B\u767A
|
|
12877
|
+
- \u65E2\u5B58\u30B3\u30FC\u30C9\u306E\u4FEE\u6B63
|
|
12878
|
+
|
|
12879
|
+
2) **\u554F\u984C\u89E3\u6C7A**
|
|
12880
|
+
- \u30D0\u30B0\u4FEE\u6B63
|
|
12881
|
+
- \u30A8\u30E9\u30FC\u5BFE\u5FDC
|
|
12882
|
+
|
|
12883
|
+
3) **\u8A2D\u8A08\u76F8\u8AC7**
|
|
12884
|
+
- \u30A2\u30FC\u30AD\u30C6\u30AF\u30C1\u30E3\u8A2D\u8A08
|
|
12885
|
+
- \u30D9\u30B9\u30C8\u30D7\u30E9\u30AF\u30C6\u30A3\u30B9
|
|
12886
|
+
|
|
12887
|
+
4) **\u5B66\u7FD2\u30B5\u30DD\u30FC\u30C8**
|
|
12888
|
+
- \u6982\u5FF5\u306E\u8AAC\u660E
|
|
12889
|
+
- \u4F7F\u7528\u65B9\u6CD5\u306E\u89E3\u8AAC
|
|
12890
|
+
|
|
12891
|
+
\u756A\u53F7\u3067\u304A\u7B54\u3048\u304F\u3060\u3055\u3044\uFF081-4\uFF09\u3002` : `I'll help with "${input3}".
|
|
12892
|
+
|
|
12893
|
+
To better understand your needs, please choose:
|
|
12894
|
+
|
|
12895
|
+
1) **Code Implementation**
|
|
12896
|
+
- New features
|
|
12897
|
+
- Code modifications
|
|
12898
|
+
|
|
12899
|
+
2) **Problem Solving**
|
|
12900
|
+
- Bug fixes
|
|
12901
|
+
- Error resolution
|
|
12902
|
+
|
|
12903
|
+
3) **Design Consultation**
|
|
12904
|
+
- Architecture design
|
|
12905
|
+
- Best practices
|
|
12906
|
+
|
|
12907
|
+
4) **Learning Support**
|
|
12908
|
+
- Concept explanation
|
|
12909
|
+
- Usage guidance
|
|
12910
|
+
|
|
12911
|
+
Please reply with a number (1-4).`;
|
|
12912
|
+
}
|
|
12913
|
+
};
|
|
12914
|
+
}
|
|
12915
|
+
});
|
|
12916
|
+
|
|
12917
|
+
// src/services/ai-response/providers/provider-factory.ts
|
|
12918
|
+
var AIProviderFactory;
|
|
12919
|
+
var init_provider_factory = __esm({
|
|
12920
|
+
"src/services/ai-response/providers/provider-factory.ts"() {
|
|
12921
|
+
init_openai_provider2();
|
|
12922
|
+
init_anthropic_provider2();
|
|
12923
|
+
init_template_provider();
|
|
12924
|
+
AIProviderFactory = class _AIProviderFactory {
|
|
12925
|
+
static instance;
|
|
12926
|
+
providers = /* @__PURE__ */ new Map();
|
|
12927
|
+
currentProvider = "template";
|
|
12928
|
+
constructor() {
|
|
12929
|
+
}
|
|
12930
|
+
static getInstance() {
|
|
12931
|
+
if (!_AIProviderFactory.instance) {
|
|
12932
|
+
_AIProviderFactory.instance = new _AIProviderFactory();
|
|
12933
|
+
}
|
|
12934
|
+
return _AIProviderFactory.instance;
|
|
12935
|
+
}
|
|
12936
|
+
/**
|
|
12937
|
+
* Initialize a provider with configuration
|
|
12938
|
+
*/
|
|
12939
|
+
async initializeProvider(type2, config2) {
|
|
12940
|
+
const provider2 = this.createProvider(type2);
|
|
12941
|
+
await provider2.initialize(config2);
|
|
12942
|
+
this.providers.set(type2, provider2);
|
|
12943
|
+
console.log(`[Provider Factory] Initialized ${type2} provider`);
|
|
12944
|
+
}
|
|
12945
|
+
/**
|
|
12946
|
+
* Create a provider instance
|
|
12947
|
+
*/
|
|
12948
|
+
createProvider(type2) {
|
|
12949
|
+
switch (type2) {
|
|
12950
|
+
case "openai":
|
|
12951
|
+
return new OpenAIProvider2();
|
|
12952
|
+
case "anthropic":
|
|
12953
|
+
return new AnthropicProvider2();
|
|
12954
|
+
case "template":
|
|
12955
|
+
return new TemplateProvider();
|
|
12956
|
+
default:
|
|
12957
|
+
console.warn(`[Provider Factory] Unknown provider type: ${type2}, falling back to template`);
|
|
12958
|
+
return new TemplateProvider();
|
|
12959
|
+
}
|
|
12960
|
+
}
|
|
12961
|
+
/**
|
|
12962
|
+
* Get a specific provider
|
|
12963
|
+
*/
|
|
12964
|
+
getProvider(type2) {
|
|
12965
|
+
const targetType = type2 || this.currentProvider;
|
|
12966
|
+
if (!this.providers.has(targetType) && targetType === "template") {
|
|
12967
|
+
const templateProvider = new TemplateProvider();
|
|
12968
|
+
templateProvider.initialize({}).catch(console.error);
|
|
12969
|
+
this.providers.set("template", templateProvider);
|
|
12970
|
+
}
|
|
12971
|
+
return this.providers.get(targetType);
|
|
12972
|
+
}
|
|
12973
|
+
/**
|
|
12974
|
+
* Get the active provider with fallback
|
|
12975
|
+
*/
|
|
12976
|
+
async getActiveProvider() {
|
|
12977
|
+
let provider2 = this.getProvider(this.currentProvider);
|
|
12978
|
+
if (provider2?.isAvailable()) {
|
|
12979
|
+
return provider2;
|
|
12980
|
+
}
|
|
12981
|
+
const fallbackOrder = ["openai", "anthropic", "template"];
|
|
12982
|
+
for (const type2 of fallbackOrder) {
|
|
12983
|
+
provider2 = this.getProvider(type2);
|
|
12984
|
+
if (provider2?.isAvailable()) {
|
|
12985
|
+
console.log(`[Provider Factory] Falling back to ${type2} provider`);
|
|
12986
|
+
this.currentProvider = type2;
|
|
12987
|
+
return provider2;
|
|
12988
|
+
}
|
|
12989
|
+
}
|
|
12990
|
+
console.log("[Provider Factory] Using template provider as last resort");
|
|
12991
|
+
const templateProvider = new TemplateProvider();
|
|
12992
|
+
await templateProvider.initialize({});
|
|
12993
|
+
this.providers.set("template", templateProvider);
|
|
12994
|
+
this.currentProvider = "template";
|
|
12995
|
+
return templateProvider;
|
|
12996
|
+
}
|
|
12997
|
+
/**
|
|
12998
|
+
* Set the active provider
|
|
12999
|
+
*/
|
|
13000
|
+
setActiveProvider(type2) {
|
|
13001
|
+
if (!this.providers.has(type2)) {
|
|
13002
|
+
throw new Error(`Provider ${type2} not initialized`);
|
|
13003
|
+
}
|
|
13004
|
+
this.currentProvider = type2;
|
|
13005
|
+
console.log(`[Provider Factory] Active provider set to ${type2}`);
|
|
13006
|
+
}
|
|
13007
|
+
/**
|
|
13008
|
+
* Initialize providers from environment variables
|
|
13009
|
+
*/
|
|
13010
|
+
async initializeFromEnvironment() {
|
|
13011
|
+
const configs = [];
|
|
13012
|
+
if (process.env.OPENAI_API_KEY) {
|
|
13013
|
+
configs.push(["openai", {
|
|
13014
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
13015
|
+
defaultModel: process.env.OPENAI_MODEL || "gpt-3.5-turbo"
|
|
13016
|
+
}]);
|
|
13017
|
+
}
|
|
13018
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
13019
|
+
configs.push(["anthropic", {
|
|
13020
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
13021
|
+
defaultModel: process.env.ANTHROPIC_MODEL || "claude-3-sonnet-20240229"
|
|
13022
|
+
}]);
|
|
13023
|
+
}
|
|
13024
|
+
configs.push(["template", {}]);
|
|
13025
|
+
for (const [type2, config2] of configs) {
|
|
13026
|
+
try {
|
|
13027
|
+
await this.initializeProvider(type2, config2);
|
|
13028
|
+
} catch (error2) {
|
|
13029
|
+
console.error(`[Provider Factory] Failed to initialize ${type2}:`, error2);
|
|
13030
|
+
}
|
|
13031
|
+
}
|
|
13032
|
+
const preferredProvider = process.env.AI_PROVIDER || "template";
|
|
13033
|
+
if (this.providers.has(preferredProvider)) {
|
|
13034
|
+
this.setActiveProvider(preferredProvider);
|
|
13035
|
+
}
|
|
13036
|
+
}
|
|
13037
|
+
/**
|
|
13038
|
+
* Get list of available providers
|
|
13039
|
+
*/
|
|
13040
|
+
getAvailableProviders() {
|
|
13041
|
+
return Array.from(this.providers.keys()).filter((type2) => {
|
|
13042
|
+
const provider2 = this.providers.get(type2);
|
|
13043
|
+
return provider2?.isAvailable();
|
|
13044
|
+
});
|
|
13045
|
+
}
|
|
13046
|
+
/**
|
|
13047
|
+
* Clear all providers (for testing)
|
|
13048
|
+
*/
|
|
13049
|
+
clearProviders() {
|
|
13050
|
+
this.providers.clear();
|
|
13051
|
+
this.currentProvider = "template";
|
|
13052
|
+
}
|
|
13053
|
+
};
|
|
13054
|
+
}
|
|
13055
|
+
});
|
|
13056
|
+
|
|
13057
|
+
// src/services/ai-response/feature-flags.ts
|
|
13058
|
+
var FeatureFlagManager, featureFlags;
|
|
13059
|
+
var init_feature_flags = __esm({
|
|
13060
|
+
"src/services/ai-response/feature-flags.ts"() {
|
|
13061
|
+
FeatureFlagManager = class _FeatureFlagManager {
|
|
13062
|
+
static instance;
|
|
13063
|
+
flags;
|
|
13064
|
+
userHash = null;
|
|
13065
|
+
constructor() {
|
|
13066
|
+
this.flags = {
|
|
13067
|
+
useRealProviders: false,
|
|
13068
|
+
providerType: "template",
|
|
13069
|
+
enableStreaming: false,
|
|
13070
|
+
enableSafetyGuards: true,
|
|
13071
|
+
enableTelemetry: true,
|
|
13072
|
+
rolloutPercentage: 0
|
|
13073
|
+
};
|
|
13074
|
+
this.loadFromEnvironment();
|
|
13075
|
+
}
|
|
13076
|
+
static getInstance() {
|
|
13077
|
+
if (!_FeatureFlagManager.instance) {
|
|
13078
|
+
_FeatureFlagManager.instance = new _FeatureFlagManager();
|
|
13079
|
+
}
|
|
13080
|
+
return _FeatureFlagManager.instance;
|
|
13081
|
+
}
|
|
13082
|
+
/**
|
|
13083
|
+
* Load flags from environment variables
|
|
13084
|
+
*/
|
|
13085
|
+
loadFromEnvironment() {
|
|
13086
|
+
const v3Enabled = process.env.AI_RESPONSE_V3 === "true";
|
|
13087
|
+
if (v3Enabled) {
|
|
13088
|
+
this.flags.useRealProviders = process.env.USE_REAL_AI_PROVIDERS === "true";
|
|
13089
|
+
this.flags.providerType = process.env.AI_PROVIDER || "template";
|
|
13090
|
+
this.flags.enableStreaming = process.env.ENABLE_STREAMING === "true";
|
|
13091
|
+
this.flags.rolloutPercentage = parseInt(process.env.AI_ROLLOUT_PERCENTAGE || "0", 10);
|
|
13092
|
+
}
|
|
13093
|
+
this.flags.enableSafetyGuards = process.env.DISABLE_SAFETY_GUARDS !== "true";
|
|
13094
|
+
this.flags.enableTelemetry = process.env.DISABLE_TELEMETRY !== "true";
|
|
13095
|
+
console.log("[Feature Flags] Loaded configuration:", this.flags);
|
|
13096
|
+
}
|
|
13097
|
+
/**
|
|
13098
|
+
* Check if a feature is enabled for the current user
|
|
13099
|
+
*/
|
|
13100
|
+
isEnabled(feature) {
|
|
13101
|
+
if (feature === "useRealProviders" && this.flags.rolloutPercentage < 100) {
|
|
13102
|
+
return this.isInRolloutGroup();
|
|
13103
|
+
}
|
|
13104
|
+
return this.flags[feature];
|
|
13105
|
+
}
|
|
13106
|
+
/**
|
|
13107
|
+
* Get a flag value
|
|
13108
|
+
*/
|
|
13109
|
+
getFlag(key2) {
|
|
13110
|
+
return this.flags[key2];
|
|
13111
|
+
}
|
|
13112
|
+
/**
|
|
13113
|
+
* Set a flag value (for testing)
|
|
13114
|
+
*/
|
|
13115
|
+
setFlag(key2, value2) {
|
|
13116
|
+
this.flags[key2] = value2;
|
|
13117
|
+
console.log(`[Feature Flags] Updated ${key2} to ${value2}`);
|
|
13118
|
+
}
|
|
13119
|
+
/**
|
|
13120
|
+
* Set user identifier for consistent rollout
|
|
13121
|
+
*/
|
|
13122
|
+
setUserIdentifier(userId) {
|
|
13123
|
+
this.userHash = this.hashString(userId);
|
|
13124
|
+
}
|
|
13125
|
+
/**
|
|
13126
|
+
* Check if current user is in rollout group
|
|
13127
|
+
*/
|
|
13128
|
+
isInRolloutGroup() {
|
|
13129
|
+
if (!this.userHash) {
|
|
13130
|
+
return Math.random() * 100 < this.flags.rolloutPercentage;
|
|
13131
|
+
}
|
|
13132
|
+
const hashValue = parseInt(this.userHash.substring(0, 8), 16);
|
|
13133
|
+
const userPercentage = hashValue % 100;
|
|
13134
|
+
return userPercentage < this.flags.rolloutPercentage;
|
|
13135
|
+
}
|
|
13136
|
+
/**
|
|
13137
|
+
* Simple hash function for consistent user assignment
|
|
13138
|
+
*/
|
|
13139
|
+
hashString(str) {
|
|
13140
|
+
let hash = 0;
|
|
13141
|
+
for (let i2 = 0; i2 < str.length; i2++) {
|
|
13142
|
+
const char = str.charCodeAt(i2);
|
|
13143
|
+
hash = (hash << 5) - hash + char;
|
|
13144
|
+
hash = hash & hash;
|
|
13145
|
+
}
|
|
13146
|
+
return Math.abs(hash).toString(16);
|
|
13147
|
+
}
|
|
13148
|
+
/**
|
|
13149
|
+
* Get configuration for AI response service
|
|
13150
|
+
*/
|
|
13151
|
+
getAIResponseConfig() {
|
|
13152
|
+
return {
|
|
13153
|
+
useRealProviders: this.isEnabled("useRealProviders"),
|
|
13154
|
+
providerType: this.flags.providerType,
|
|
13155
|
+
enableStreaming: this.isEnabled("enableStreaming"),
|
|
13156
|
+
enableSafetyGuards: this.isEnabled("enableSafetyGuards"),
|
|
13157
|
+
enableTelemetry: this.isEnabled("enableTelemetry")
|
|
13158
|
+
};
|
|
13159
|
+
}
|
|
13160
|
+
/**
|
|
13161
|
+
* Reset to defaults (for testing)
|
|
13162
|
+
*/
|
|
13163
|
+
reset() {
|
|
13164
|
+
this.flags = {
|
|
13165
|
+
useRealProviders: false,
|
|
13166
|
+
providerType: "template",
|
|
13167
|
+
enableStreaming: false,
|
|
13168
|
+
enableSafetyGuards: true,
|
|
13169
|
+
enableTelemetry: true,
|
|
13170
|
+
rolloutPercentage: 0
|
|
13171
|
+
};
|
|
13172
|
+
this.userHash = null;
|
|
13173
|
+
}
|
|
13174
|
+
};
|
|
13175
|
+
featureFlags = FeatureFlagManager.getInstance();
|
|
13176
|
+
}
|
|
13177
|
+
});
|
|
13178
|
+
|
|
13179
|
+
// src/services/ai-response/telemetry/telemetry-collector.ts
|
|
13180
|
+
var TelemetryCollector;
|
|
13181
|
+
var init_telemetry_collector = __esm({
|
|
13182
|
+
"src/services/ai-response/telemetry/telemetry-collector.ts"() {
|
|
13183
|
+
TelemetryCollector = class _TelemetryCollector {
|
|
13184
|
+
static instance;
|
|
13185
|
+
events = [];
|
|
13186
|
+
sessionId;
|
|
13187
|
+
flushInterval = null;
|
|
13188
|
+
aggregationInterval = null;
|
|
13189
|
+
metricsBuffer = /* @__PURE__ */ new Map();
|
|
13190
|
+
constructor() {
|
|
13191
|
+
this.sessionId = this.generateSessionId();
|
|
13192
|
+
this.startCollection();
|
|
13193
|
+
}
|
|
13194
|
+
static getInstance() {
|
|
13195
|
+
if (!_TelemetryCollector.instance) {
|
|
13196
|
+
_TelemetryCollector.instance = new _TelemetryCollector();
|
|
13197
|
+
}
|
|
13198
|
+
return _TelemetryCollector.instance;
|
|
13199
|
+
}
|
|
13200
|
+
/**
|
|
13201
|
+
* Start collecting metrics
|
|
13202
|
+
*/
|
|
13203
|
+
startCollection() {
|
|
13204
|
+
this.flushInterval = setInterval(() => {
|
|
13205
|
+
this.flushEvents();
|
|
13206
|
+
}, 3e4);
|
|
13207
|
+
this.aggregationInterval = setInterval(() => {
|
|
13208
|
+
this.aggregateMetrics("minute");
|
|
13209
|
+
}, 6e4);
|
|
13210
|
+
console.log("[Telemetry] Collection started");
|
|
13211
|
+
}
|
|
13212
|
+
/**
|
|
13213
|
+
* Track intent decision
|
|
13214
|
+
*/
|
|
13215
|
+
trackIntent(metric) {
|
|
13216
|
+
this.addEvent({
|
|
13217
|
+
timestamp: Date.now(),
|
|
13218
|
+
eventType: "intent_decided",
|
|
13219
|
+
sessionId: this.sessionId,
|
|
13220
|
+
data: metric
|
|
13221
|
+
});
|
|
13222
|
+
}
|
|
13223
|
+
/**
|
|
13224
|
+
* Track response generation
|
|
13225
|
+
*/
|
|
13226
|
+
trackResponse(metric) {
|
|
13227
|
+
this.addEvent({
|
|
13228
|
+
timestamp: Date.now(),
|
|
13229
|
+
eventType: "response_generated",
|
|
13230
|
+
sessionId: this.sessionId,
|
|
13231
|
+
data: metric
|
|
13232
|
+
});
|
|
13233
|
+
if (!metric.fallback) {
|
|
13234
|
+
this.addEvent({
|
|
13235
|
+
timestamp: Date.now(),
|
|
13236
|
+
eventType: "provider_called",
|
|
13237
|
+
sessionId: this.sessionId,
|
|
13238
|
+
data: {
|
|
13239
|
+
provider: metric.provider,
|
|
13240
|
+
success: metric.success
|
|
13241
|
+
}
|
|
13242
|
+
});
|
|
13243
|
+
}
|
|
13244
|
+
}
|
|
13245
|
+
/**
|
|
13246
|
+
* Track safety violations
|
|
13247
|
+
*/
|
|
13248
|
+
trackSafetyViolation(metric) {
|
|
13249
|
+
this.addEvent({
|
|
13250
|
+
timestamp: Date.now(),
|
|
13251
|
+
eventType: "safety_violation",
|
|
13252
|
+
sessionId: this.sessionId,
|
|
13253
|
+
data: metric
|
|
13254
|
+
});
|
|
13255
|
+
}
|
|
13256
|
+
/**
|
|
13257
|
+
* Track user feedback
|
|
13258
|
+
*/
|
|
13259
|
+
trackUserFeedback(metric) {
|
|
13260
|
+
this.addEvent({
|
|
13261
|
+
timestamp: Date.now(),
|
|
13262
|
+
eventType: "user_feedback",
|
|
13263
|
+
sessionId: this.sessionId,
|
|
13264
|
+
data: metric
|
|
13265
|
+
});
|
|
13266
|
+
}
|
|
13267
|
+
/**
|
|
13268
|
+
* Track errors
|
|
13269
|
+
*/
|
|
13270
|
+
trackError(error2, context2) {
|
|
13271
|
+
this.addEvent({
|
|
13272
|
+
timestamp: Date.now(),
|
|
13273
|
+
eventType: "error_occurred",
|
|
13274
|
+
sessionId: this.sessionId,
|
|
13275
|
+
data: {
|
|
13276
|
+
message: error2.message,
|
|
13277
|
+
stack: error2.stack,
|
|
13278
|
+
...context2
|
|
13279
|
+
}
|
|
13280
|
+
});
|
|
13281
|
+
}
|
|
13282
|
+
/**
|
|
13283
|
+
* Add event to buffer
|
|
13284
|
+
*/
|
|
13285
|
+
addEvent(event) {
|
|
13286
|
+
this.events.push(event);
|
|
13287
|
+
if (this.events.length >= 100) {
|
|
13288
|
+
this.flushEvents();
|
|
13289
|
+
}
|
|
13290
|
+
}
|
|
13291
|
+
/**
|
|
13292
|
+
* Flush events to storage/API
|
|
13293
|
+
*/
|
|
13294
|
+
async flushEvents() {
|
|
13295
|
+
if (this.events.length === 0) return;
|
|
13296
|
+
const eventsToFlush = [...this.events];
|
|
13297
|
+
this.events = [];
|
|
13298
|
+
try {
|
|
13299
|
+
if (process.env.TELEMETRY_ENDPOINT) {
|
|
13300
|
+
await this.sendToEndpoint(eventsToFlush);
|
|
13301
|
+
} else {
|
|
13302
|
+
this.storeLocally(eventsToFlush);
|
|
13303
|
+
}
|
|
13304
|
+
} catch (error2) {
|
|
13305
|
+
console.error("[Telemetry] Failed to flush events:", error2);
|
|
13306
|
+
this.events.unshift(...eventsToFlush);
|
|
13307
|
+
}
|
|
13308
|
+
}
|
|
13309
|
+
/**
|
|
13310
|
+
* Send events to telemetry endpoint
|
|
13311
|
+
*/
|
|
13312
|
+
async sendToEndpoint(events) {
|
|
13313
|
+
const endpoint = process.env.TELEMETRY_ENDPOINT;
|
|
13314
|
+
const apiKey2 = process.env.TELEMETRY_API_KEY;
|
|
13315
|
+
if (!endpoint) return;
|
|
13316
|
+
const response2 = await fetch(endpoint, {
|
|
13317
|
+
method: "POST",
|
|
13318
|
+
headers: {
|
|
13319
|
+
"Content-Type": "application/json",
|
|
13320
|
+
...apiKey2 && { "Authorization": `Bearer ${apiKey2}` }
|
|
13321
|
+
},
|
|
13322
|
+
body: JSON.stringify({ events })
|
|
13323
|
+
});
|
|
13324
|
+
if (!response2.ok) {
|
|
13325
|
+
throw new Error(`Telemetry endpoint returned ${response2.status}`);
|
|
13326
|
+
}
|
|
13327
|
+
}
|
|
13328
|
+
/**
|
|
13329
|
+
* Store events locally (for development)
|
|
13330
|
+
*/
|
|
13331
|
+
storeLocally(events) {
|
|
13332
|
+
const key2 = `metrics_${Date.now()}`;
|
|
13333
|
+
this.metricsBuffer.set(key2, this.calculateMetrics(events));
|
|
13334
|
+
if (this.metricsBuffer.size > 100) {
|
|
13335
|
+
const keys = Array.from(this.metricsBuffer.keys());
|
|
13336
|
+
this.metricsBuffer.delete(keys[0]);
|
|
13337
|
+
}
|
|
13338
|
+
}
|
|
13339
|
+
/**
|
|
13340
|
+
* Calculate metrics from events
|
|
13341
|
+
*/
|
|
13342
|
+
calculateMetrics(events) {
|
|
13343
|
+
const now2 = Date.now();
|
|
13344
|
+
const metrics2 = {
|
|
13345
|
+
period: "minute",
|
|
13346
|
+
startTime: now2 - 6e4,
|
|
13347
|
+
endTime: now2,
|
|
13348
|
+
// Intent metrics
|
|
13349
|
+
intentCounts: {},
|
|
13350
|
+
intentAccuracy: 0,
|
|
13351
|
+
languageDistribution: {},
|
|
13352
|
+
// Response metrics
|
|
13353
|
+
totalResponses: 0,
|
|
13354
|
+
averageLatency: 0,
|
|
13355
|
+
p95Latency: 0,
|
|
13356
|
+
p99Latency: 0,
|
|
13357
|
+
providerDistribution: {},
|
|
13358
|
+
fallbackRate: 0,
|
|
13359
|
+
errorRate: 0,
|
|
13360
|
+
// Token usage
|
|
13361
|
+
totalTokens: 0,
|
|
13362
|
+
averageTokensPerRequest: 0,
|
|
13363
|
+
// Safety metrics
|
|
13364
|
+
safetyViolations: 0,
|
|
13365
|
+
violationTypes: {},
|
|
13366
|
+
// User satisfaction
|
|
13367
|
+
satisfactionRate: 0,
|
|
13368
|
+
feedbackCount: 0,
|
|
13369
|
+
feedbackDistribution: {}
|
|
13370
|
+
};
|
|
13371
|
+
const latencies = [];
|
|
13372
|
+
let totalTokens = 0;
|
|
13373
|
+
let feedbackPositive = 0;
|
|
13374
|
+
let feedbackTotal = 0;
|
|
13375
|
+
events.forEach((event) => {
|
|
13376
|
+
switch (event.eventType) {
|
|
13377
|
+
case "intent_decided":
|
|
13378
|
+
const intent2 = event.data;
|
|
13379
|
+
metrics2.intentCounts[intent2.type] = (metrics2.intentCounts[intent2.type] || 0) + 1;
|
|
13380
|
+
metrics2.languageDistribution[intent2.language] = (metrics2.languageDistribution[intent2.language] || 0) + 1;
|
|
13381
|
+
break;
|
|
13382
|
+
case "response_generated":
|
|
13383
|
+
const response2 = event.data;
|
|
13384
|
+
metrics2.totalResponses++;
|
|
13385
|
+
latencies.push(response2.latencyMs);
|
|
13386
|
+
metrics2.providerDistribution[response2.provider] = (metrics2.providerDistribution[response2.provider] || 0) + 1;
|
|
13387
|
+
if (response2.fallback) metrics2.fallbackRate++;
|
|
13388
|
+
if (!response2.success) metrics2.errorRate++;
|
|
13389
|
+
if (response2.tokenUsage) {
|
|
13390
|
+
totalTokens += response2.tokenUsage.total;
|
|
13391
|
+
}
|
|
13392
|
+
break;
|
|
13393
|
+
case "safety_violation":
|
|
13394
|
+
const safety = event.data;
|
|
13395
|
+
metrics2.safetyViolations++;
|
|
13396
|
+
metrics2.violationTypes[safety.violationType] = (metrics2.violationTypes[safety.violationType] || 0) + 1;
|
|
13397
|
+
break;
|
|
13398
|
+
case "user_feedback":
|
|
13399
|
+
const feedback = event.data;
|
|
13400
|
+
feedbackTotal++;
|
|
13401
|
+
if (feedback.rating === "positive") feedbackPositive++;
|
|
13402
|
+
metrics2.feedbackDistribution[feedback.rating] = (metrics2.feedbackDistribution[feedback.rating] || 0) + 1;
|
|
13403
|
+
break;
|
|
13404
|
+
}
|
|
13405
|
+
});
|
|
13406
|
+
if (latencies.length > 0) {
|
|
13407
|
+
latencies.sort((a2, b) => a2 - b);
|
|
13408
|
+
metrics2.averageLatency = latencies.reduce((a2, b) => a2 + b, 0) / latencies.length;
|
|
13409
|
+
metrics2.p95Latency = latencies[Math.floor(latencies.length * 0.95)] || 0;
|
|
13410
|
+
metrics2.p99Latency = latencies[Math.floor(latencies.length * 0.99)] || 0;
|
|
13411
|
+
}
|
|
13412
|
+
if (metrics2.totalResponses > 0) {
|
|
13413
|
+
metrics2.fallbackRate = metrics2.fallbackRate / metrics2.totalResponses;
|
|
13414
|
+
metrics2.errorRate = metrics2.errorRate / metrics2.totalResponses;
|
|
13415
|
+
metrics2.averageTokensPerRequest = totalTokens / metrics2.totalResponses;
|
|
13416
|
+
}
|
|
13417
|
+
if (feedbackTotal > 0) {
|
|
13418
|
+
metrics2.satisfactionRate = feedbackPositive / feedbackTotal;
|
|
13419
|
+
}
|
|
13420
|
+
metrics2.feedbackCount = feedbackTotal;
|
|
13421
|
+
metrics2.totalTokens = totalTokens;
|
|
13422
|
+
return metrics2;
|
|
13423
|
+
}
|
|
13424
|
+
/**
|
|
13425
|
+
* Aggregate metrics by period
|
|
13426
|
+
*/
|
|
13427
|
+
aggregateMetrics(period) {
|
|
13428
|
+
const recentEvents = this.getRecentEvents(period);
|
|
13429
|
+
const metrics2 = this.calculateMetrics(recentEvents);
|
|
13430
|
+
const key2 = `${period}_${Date.now()}`;
|
|
13431
|
+
this.metricsBuffer.set(key2, metrics2);
|
|
13432
|
+
console.log(`[Telemetry] Aggregated ${period} metrics:`, {
|
|
13433
|
+
responses: metrics2.totalResponses,
|
|
13434
|
+
avgLatency: Math.round(metrics2.averageLatency),
|
|
13435
|
+
satisfaction: Math.round(metrics2.satisfactionRate * 100) + "%"
|
|
13436
|
+
});
|
|
13437
|
+
}
|
|
13438
|
+
/**
|
|
13439
|
+
* Get recent events by period
|
|
13440
|
+
*/
|
|
13441
|
+
getRecentEvents(period) {
|
|
13442
|
+
const now2 = Date.now();
|
|
13443
|
+
const duration = period === "minute" ? 6e4 : period === "hour" ? 36e5 : 864e5;
|
|
13444
|
+
return this.events.filter((e2) => e2.timestamp > now2 - duration);
|
|
13445
|
+
}
|
|
13446
|
+
/**
|
|
13447
|
+
* Get current metrics
|
|
13448
|
+
*/
|
|
13449
|
+
getCurrentMetrics() {
|
|
13450
|
+
const keys = Array.from(this.metricsBuffer.keys()).filter((k) => k.startsWith("minute_")).sort();
|
|
13451
|
+
if (keys.length === 0) return null;
|
|
13452
|
+
return this.metricsBuffer.get(keys[keys.length - 1]) || null;
|
|
13453
|
+
}
|
|
13454
|
+
/**
|
|
13455
|
+
* Get historical metrics
|
|
13456
|
+
*/
|
|
13457
|
+
getHistoricalMetrics(period, count = 10) {
|
|
13458
|
+
const prefix = `${period}_`;
|
|
13459
|
+
const keys = Array.from(this.metricsBuffer.keys()).filter((k) => k.startsWith(prefix)).sort().slice(-count);
|
|
13460
|
+
return keys.map((k) => this.metricsBuffer.get(k)).filter(Boolean);
|
|
13461
|
+
}
|
|
13462
|
+
/**
|
|
13463
|
+
* Generate session ID
|
|
13464
|
+
*/
|
|
13465
|
+
generateSessionId() {
|
|
13466
|
+
return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
13467
|
+
}
|
|
13468
|
+
/**
|
|
13469
|
+
* Stop collection
|
|
13470
|
+
*/
|
|
13471
|
+
stop() {
|
|
13472
|
+
if (this.flushInterval) {
|
|
13473
|
+
clearInterval(this.flushInterval);
|
|
13474
|
+
this.flushInterval = null;
|
|
13475
|
+
}
|
|
13476
|
+
if (this.aggregationInterval) {
|
|
13477
|
+
clearInterval(this.aggregationInterval);
|
|
13478
|
+
this.aggregationInterval = null;
|
|
13479
|
+
}
|
|
13480
|
+
this.flushEvents();
|
|
13481
|
+
console.log("[Telemetry] Collection stopped");
|
|
13482
|
+
}
|
|
13483
|
+
};
|
|
13484
|
+
}
|
|
13485
|
+
});
|
|
13486
|
+
|
|
13487
|
+
// src/services/ai-response/context.ts
|
|
13488
|
+
function buildContextForAI(sessionMemory2, options2 = {}) {
|
|
13489
|
+
const {
|
|
13490
|
+
budgetChars = 8e3,
|
|
13491
|
+
maxMessages = 20,
|
|
13492
|
+
summaryThreshold = 6
|
|
13493
|
+
} = options2;
|
|
13494
|
+
const reversed = [...sessionMemory2].reverse();
|
|
13495
|
+
const recentMessages2 = [];
|
|
13496
|
+
let totalChars = 0;
|
|
13497
|
+
let messageCount = 0;
|
|
13498
|
+
for (const msg2 of reversed) {
|
|
13499
|
+
const content2 = msg2.content || "";
|
|
13500
|
+
const msgLength = content2.length;
|
|
13501
|
+
if (totalChars + msgLength > budgetChars || messageCount >= maxMessages) {
|
|
13502
|
+
break;
|
|
13503
|
+
}
|
|
13504
|
+
recentMessages2.push({
|
|
13505
|
+
role: msg2.role,
|
|
13506
|
+
content: content2,
|
|
13507
|
+
timestamp: msg2.timestamp
|
|
13508
|
+
});
|
|
13509
|
+
totalChars += msgLength;
|
|
13510
|
+
messageCount++;
|
|
13511
|
+
}
|
|
13512
|
+
recentMessages2.reverse();
|
|
13513
|
+
let rollingSummary;
|
|
13514
|
+
if (sessionMemory2.length > summaryThreshold && recentMessages2.length < sessionMemory2.length) {
|
|
13515
|
+
const olderMessages = sessionMemory2.slice(0, sessionMemory2.length - recentMessages2.length);
|
|
13516
|
+
rollingSummary = createRollingSummary(olderMessages, 1200);
|
|
13517
|
+
}
|
|
13518
|
+
return {
|
|
13519
|
+
recentMessages: recentMessages2,
|
|
13520
|
+
rollingSummary,
|
|
13521
|
+
totalChars,
|
|
13522
|
+
messageCount
|
|
13523
|
+
};
|
|
13524
|
+
}
|
|
13525
|
+
function createRollingSummary(messages2, maxChars) {
|
|
13526
|
+
const summaryParts = [];
|
|
13527
|
+
let currentLength = 0;
|
|
13528
|
+
for (const msg2 of messages2) {
|
|
13529
|
+
const role2 = msg2.role === "user" ? "U" : "A";
|
|
13530
|
+
const preview = msg2.content.substring(0, 100).replace(/\n/g, " ");
|
|
13531
|
+
const summary = `${role2}: ${preview}${msg2.content.length > 100 ? "..." : ""}`;
|
|
13532
|
+
if (currentLength + summary.length > maxChars) {
|
|
13533
|
+
break;
|
|
13534
|
+
}
|
|
13535
|
+
summaryParts.push(summary);
|
|
13536
|
+
currentLength += summary.length + 1;
|
|
13537
|
+
}
|
|
13538
|
+
return summaryParts.join("\n");
|
|
13539
|
+
}
|
|
13540
|
+
function extractKeyTopics(context2) {
|
|
13541
|
+
const topics = /* @__PURE__ */ new Set();
|
|
13542
|
+
const allText = context2.recentMessages.map((m2) => m2.content).join(" ").toLowerCase();
|
|
13543
|
+
const languages2 = ["typescript", "javascript", "python", "java", "go", "rust", "react", "vue", "angular"];
|
|
13544
|
+
languages2.forEach((lang) => {
|
|
13545
|
+
if (allText.includes(lang)) topics.add(lang);
|
|
13546
|
+
});
|
|
13547
|
+
const tools = ["next.js", "nextjs", "express", "fastapi", "django", "spring", "docker", "kubernetes"];
|
|
13548
|
+
tools.forEach((tool2) => {
|
|
13549
|
+
if (allText.includes(tool2)) topics.add(tool2);
|
|
13550
|
+
});
|
|
13551
|
+
const concepts = ["api", "database", "authentication", "testing", "deployment", "frontend", "backend"];
|
|
13552
|
+
concepts.forEach((concept) => {
|
|
13553
|
+
if (allText.includes(concept)) topics.add(concept);
|
|
13554
|
+
});
|
|
13555
|
+
return Array.from(topics);
|
|
13556
|
+
}
|
|
13557
|
+
function getContextStats(context2) {
|
|
13558
|
+
return {
|
|
13559
|
+
messageCount: context2.messageCount,
|
|
13560
|
+
totalChars: context2.totalChars,
|
|
13561
|
+
hasSummary: !!context2.rollingSummary,
|
|
13562
|
+
avgMessageLength: context2.totalChars / (context2.messageCount || 1),
|
|
13563
|
+
topics: extractKeyTopics(context2)
|
|
13564
|
+
};
|
|
13565
|
+
}
|
|
13566
|
+
var init_context = __esm({
|
|
13567
|
+
"src/services/ai-response/context.ts"() {
|
|
13568
|
+
}
|
|
13569
|
+
});
|
|
13570
|
+
|
|
13571
|
+
// src/services/ai-response/responders/common.ts
|
|
13572
|
+
function generateFooter(isJapanese, customOptions) {
|
|
13573
|
+
if (customOptions && customOptions.length > 0) {
|
|
13574
|
+
const numbered = customOptions.map((opt, i2) => `${i2 + 1}) ${opt}`).join(" ");
|
|
13575
|
+
return isJapanese ? `
|
|
13576
|
+
---
|
|
13577
|
+
\u6B21\u306E\u30B9\u30C6\u30C3\u30D7: ${numbered}
|
|
13578
|
+
\u756A\u53F7\u3067\u6307\u793A\u3057\u3066\u304F\u3060\u3055\u3044\u3002` : `
|
|
13579
|
+
---
|
|
13580
|
+
Next steps: ${numbered}
|
|
13581
|
+
Reply with a number.`;
|
|
13582
|
+
}
|
|
13583
|
+
return isJapanese ? "\n---\n\u6B21\u306B\u9032\u3081\u308B\u9805\u76EE: 1) \u6700\u5C0F\u3067\u52D5\u304B\u3059 2) \u8A2D\u8A08\u3092\u56FA\u3081\u308B 3) \u65E2\u5B58\u30B3\u30FC\u30C9\u306B\u9069\u7528\n\u756A\u53F7\u3067\u6307\u793A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" : "\n---\nNext: 1) Run minimal 2) Lock design 3) Apply to existing\nReply with a number.";
|
|
13584
|
+
}
|
|
13585
|
+
function formatFileBlock(path21, lang, content2) {
|
|
13586
|
+
return `**${path21}**
|
|
13587
|
+
\`\`\`${lang}
|
|
13588
|
+
${content2}
|
|
13589
|
+
\`\`\``;
|
|
13590
|
+
}
|
|
13591
|
+
function createSectionHeader(title2, level2 = 2) {
|
|
13592
|
+
const prefix = "#".repeat(level2);
|
|
13593
|
+
return `${prefix} ${title2}`;
|
|
13594
|
+
}
|
|
13595
|
+
function formatList(items, ordered = false) {
|
|
13596
|
+
return items.map(
|
|
13597
|
+
(item2, i2) => ordered ? `${i2 + 1}. ${item2}` : `\u2022 ${item2}`
|
|
13598
|
+
).join("\n");
|
|
13599
|
+
}
|
|
13600
|
+
function truncateText(text2, maxLength) {
|
|
13601
|
+
if (text2.length <= maxLength) return text2;
|
|
13602
|
+
return text2.substring(0, maxLength - 3) + "...";
|
|
13603
|
+
}
|
|
13604
|
+
function cleanUserInput(input3) {
|
|
13605
|
+
return input3.trim().replace(/\s+/g, " ").substring(0, 100);
|
|
13606
|
+
}
|
|
13607
|
+
var init_common = __esm({
|
|
13608
|
+
"src/services/ai-response/responders/common.ts"() {
|
|
13609
|
+
}
|
|
13610
|
+
});
|
|
13611
|
+
|
|
13612
|
+
// src/services/ai-response/responders/code.ts
|
|
13613
|
+
function buildCodeResponse(options2) {
|
|
13614
|
+
const {
|
|
13615
|
+
title: title2,
|
|
13616
|
+
files: files2,
|
|
13617
|
+
runCommands,
|
|
13618
|
+
notes = [],
|
|
13619
|
+
dependencies: dependencies2 = [],
|
|
13620
|
+
envVars = {},
|
|
13621
|
+
isJapanese = false
|
|
13622
|
+
} = options2;
|
|
13623
|
+
const parts2 = [];
|
|
13624
|
+
parts2.push(`### ${title2}`);
|
|
13625
|
+
parts2.push("");
|
|
13626
|
+
files2.forEach((file2) => {
|
|
13627
|
+
parts2.push(formatFileBlock(file2.path, file2.lang, file2.content));
|
|
13628
|
+
parts2.push("");
|
|
13629
|
+
});
|
|
13630
|
+
if (dependencies2.length > 0) {
|
|
13631
|
+
parts2.push(isJapanese ? "**\u5FC5\u8981\u306A\u4F9D\u5B58\u95A2\u4FC2**" : "**Dependencies**");
|
|
13632
|
+
parts2.push("```bash");
|
|
13633
|
+
parts2.push(
|
|
13634
|
+
isJapanese ? `pnpm add ${dependencies2.join(" ")}` : `npm install ${dependencies2.join(" ")}`
|
|
13635
|
+
);
|
|
13636
|
+
parts2.push("```");
|
|
13637
|
+
parts2.push("");
|
|
13638
|
+
}
|
|
13639
|
+
if (Object.keys(envVars).length > 0) {
|
|
13640
|
+
parts2.push(isJapanese ? "**\u74B0\u5883\u5909\u6570 (.env)**" : "**Environment Variables (.env)**");
|
|
13641
|
+
parts2.push("```env");
|
|
13642
|
+
Object.entries(envVars).forEach(([key2, value2]) => {
|
|
13643
|
+
parts2.push(`${key2}=${value2}`);
|
|
13644
|
+
});
|
|
13645
|
+
parts2.push("```");
|
|
13646
|
+
parts2.push("");
|
|
13647
|
+
}
|
|
13648
|
+
parts2.push(isJapanese ? "**\u5B9F\u884C\u624B\u9806**" : "**Run Instructions**");
|
|
13649
|
+
parts2.push(formatList(runCommands, true));
|
|
13650
|
+
parts2.push("");
|
|
13651
|
+
const defaultNotes = isJapanese ? ["\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u305F\u5834\u5408\u306F\u3001\u4F9D\u5B58\u95A2\u4FC2\u304C\u6B63\u3057\u304F\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3055\u308C\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044"] : ["If you encounter errors, ensure all dependencies are properly installed"];
|
|
13652
|
+
const allNotes = [...notes, ...defaultNotes];
|
|
13653
|
+
parts2.push(isJapanese ? "**\u6CE8\u610F\u4E8B\u9805**" : "**Notes**");
|
|
13654
|
+
parts2.push(formatList(allNotes));
|
|
13655
|
+
const footerOptions = isJapanese ? ["\u30A8\u30E9\u30FC\u51E6\u7406\u3092\u8FFD\u52A0", "\u30C6\u30B9\u30C8\u3092\u66F8\u304F", "\u6A5F\u80FD\u3092\u62E1\u5F35"] : ["Add error handling", "Write tests", "Extend features"];
|
|
13656
|
+
parts2.push(generateFooter(isJapanese, footerOptions));
|
|
13657
|
+
return parts2.join("\n");
|
|
13658
|
+
}
|
|
13659
|
+
function generateCLITemplate(isJapanese) {
|
|
13660
|
+
return buildCodeResponse({
|
|
13661
|
+
title: isJapanese ? "TypeScript CLI \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3" : "TypeScript CLI Application",
|
|
13662
|
+
files: [
|
|
13663
|
+
{
|
|
13664
|
+
path: "src/index.ts",
|
|
13665
|
+
lang: "typescript",
|
|
13666
|
+
content: `#!/usr/bin/env node
|
|
13667
|
+
import { Command } from 'commander';
|
|
13668
|
+
import chalk from 'chalk';
|
|
13669
|
+
|
|
13670
|
+
const program = new Command();
|
|
13671
|
+
|
|
13672
|
+
program
|
|
13673
|
+
.name('my-cli')
|
|
13674
|
+
.description('CLI application template')
|
|
13675
|
+
.version('1.0.0');
|
|
13676
|
+
|
|
13677
|
+
program
|
|
13678
|
+
.command('greet <name>')
|
|
13679
|
+
.description('Greet someone')
|
|
13680
|
+
.option('-u, --uppercase', 'Convert to uppercase')
|
|
13681
|
+
.action((name: string, options: { uppercase?: boolean }) => {
|
|
13682
|
+
const greeting = options.uppercase
|
|
13683
|
+
? \`HELLO \${name.toUpperCase()}!\`
|
|
13684
|
+
: \`Hello \${name}!\`;
|
|
13685
|
+
console.log(chalk.green(greeting));
|
|
13686
|
+
});
|
|
13687
|
+
|
|
13688
|
+
program.parse(process.argv);`
|
|
13689
|
+
},
|
|
13690
|
+
{
|
|
13691
|
+
path: "package.json",
|
|
13692
|
+
lang: "json",
|
|
13693
|
+
content: `{
|
|
13694
|
+
"name": "my-cli",
|
|
13695
|
+
"version": "1.0.0",
|
|
13696
|
+
"type": "module",
|
|
13697
|
+
"bin": {
|
|
13698
|
+
"my-cli": "./dist/index.js"
|
|
13699
|
+
},
|
|
13700
|
+
"scripts": {
|
|
13701
|
+
"build": "tsc",
|
|
13702
|
+
"dev": "tsx src/index.ts",
|
|
13703
|
+
"start": "node dist/index.js"
|
|
13704
|
+
},
|
|
13705
|
+
"dependencies": {
|
|
13706
|
+
"chalk": "^5.3.0",
|
|
13707
|
+
"commander": "^11.1.0"
|
|
13708
|
+
},
|
|
13709
|
+
"devDependencies": {
|
|
13710
|
+
"@types/node": "^20.10.0",
|
|
13711
|
+
"tsx": "^4.6.0",
|
|
13712
|
+
"typescript": "^5.3.0"
|
|
13713
|
+
}
|
|
13714
|
+
}`
|
|
13715
|
+
},
|
|
13716
|
+
{
|
|
13717
|
+
path: "tsconfig.json",
|
|
13718
|
+
lang: "json",
|
|
13719
|
+
content: `{
|
|
13720
|
+
"compilerOptions": {
|
|
13721
|
+
"target": "ES2022",
|
|
13722
|
+
"module": "ES2022",
|
|
13723
|
+
"lib": ["ES2022"],
|
|
13724
|
+
"outDir": "./dist",
|
|
13725
|
+
"rootDir": "./src",
|
|
13726
|
+
"strict": true,
|
|
13727
|
+
"esModuleInterop": true,
|
|
13728
|
+
"skipLibCheck": true,
|
|
13729
|
+
"forceConsistentCasingInFileNames": true,
|
|
13730
|
+
"moduleResolution": "node",
|
|
13731
|
+
"resolveJsonModule": true
|
|
13732
|
+
},
|
|
13733
|
+
"include": ["src/**/*"],
|
|
13734
|
+
"exclude": ["node_modules", "dist"]
|
|
13735
|
+
}`
|
|
13736
|
+
}
|
|
13737
|
+
],
|
|
13738
|
+
runCommands: isJapanese ? [
|
|
13739
|
+
"pnpm install",
|
|
13740
|
+
"pnpm build",
|
|
13741
|
+
"node dist/index.js greet World",
|
|
13742
|
+
"npm link (\u30B0\u30ED\u30FC\u30D0\u30EB\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u7528)"
|
|
13743
|
+
] : [
|
|
13744
|
+
"npm install",
|
|
13745
|
+
"npm run build",
|
|
13746
|
+
"node dist/index.js greet World",
|
|
13747
|
+
"npm link (for global installation)"
|
|
13748
|
+
],
|
|
13749
|
+
dependencies: ["chalk", "commander"],
|
|
13750
|
+
notes: isJapanese ? ["tsx \u3092\u4F7F\u7528\u3057\u3066\u958B\u767A\u4E2D\u306F TypeScript \u3092\u76F4\u63A5\u5B9F\u884C\u3067\u304D\u307E\u3059"] : ["Use tsx to run TypeScript directly during development"],
|
|
13751
|
+
isJapanese
|
|
13752
|
+
});
|
|
13753
|
+
}
|
|
13754
|
+
function generateNextAPITemplate(isJapanese) {
|
|
13755
|
+
return buildCodeResponse({
|
|
13756
|
+
title: isJapanese ? "Next.js API \u30EB\u30FC\u30C8" : "Next.js API Route",
|
|
13757
|
+
files: [
|
|
13758
|
+
{
|
|
13759
|
+
path: "app/api/users/route.ts",
|
|
13760
|
+
lang: "typescript",
|
|
13761
|
+
content: `import { NextRequest, NextResponse } from 'next/server';
|
|
13762
|
+
|
|
13763
|
+
// Sample data
|
|
13764
|
+
const users = [
|
|
13765
|
+
{ id: 1, name: 'Alice', email: 'alice@example.com' },
|
|
13766
|
+
{ id: 2, name: 'Bob', email: 'bob@example.com' }
|
|
13767
|
+
];
|
|
13768
|
+
|
|
13769
|
+
export async function GET(request: NextRequest) {
|
|
13770
|
+
try {
|
|
13771
|
+
const searchParams = request.nextUrl.searchParams;
|
|
13772
|
+
const id = searchParams.get('id');
|
|
13773
|
+
|
|
13774
|
+
if (id) {
|
|
13775
|
+
const user = users.find(u => u.id === parseInt(id));
|
|
13776
|
+
if (!user) {
|
|
13777
|
+
return NextResponse.json(
|
|
13778
|
+
{ error: 'User not found' },
|
|
13779
|
+
{ status: 404 }
|
|
13780
|
+
);
|
|
13781
|
+
}
|
|
13782
|
+
return NextResponse.json(user);
|
|
13783
|
+
}
|
|
13784
|
+
|
|
13785
|
+
return NextResponse.json(users);
|
|
13786
|
+
} catch (error) {
|
|
13787
|
+
return NextResponse.json(
|
|
13788
|
+
{ error: 'Internal server error' },
|
|
13789
|
+
{ status: 500 }
|
|
13790
|
+
);
|
|
13791
|
+
}
|
|
13792
|
+
}
|
|
13793
|
+
|
|
13794
|
+
export async function POST(request: NextRequest) {
|
|
13795
|
+
try {
|
|
13796
|
+
const body = await request.json();
|
|
13797
|
+
const { name, email } = body;
|
|
13798
|
+
|
|
13799
|
+
if (!name || !email) {
|
|
13800
|
+
return NextResponse.json(
|
|
13801
|
+
{ error: 'Name and email are required' },
|
|
13802
|
+
{ status: 400 }
|
|
13803
|
+
);
|
|
13804
|
+
}
|
|
13805
|
+
|
|
13806
|
+
const newUser = {
|
|
13807
|
+
id: users.length + 1,
|
|
13808
|
+
name,
|
|
13809
|
+
email
|
|
13810
|
+
};
|
|
13811
|
+
|
|
13812
|
+
users.push(newUser);
|
|
13813
|
+
|
|
13814
|
+
return NextResponse.json(newUser, { status: 201 });
|
|
13815
|
+
} catch (error) {
|
|
13816
|
+
return NextResponse.json(
|
|
13817
|
+
{ error: 'Invalid request body' },
|
|
13818
|
+
{ status: 400 }
|
|
13819
|
+
);
|
|
13820
|
+
}
|
|
13821
|
+
}`
|
|
13822
|
+
},
|
|
13823
|
+
{
|
|
13824
|
+
path: "app/api/users/[id]/route.ts",
|
|
13825
|
+
lang: "typescript",
|
|
13826
|
+
content: `import { NextRequest, NextResponse } from 'next/server';
|
|
13827
|
+
|
|
13828
|
+
export async function GET(
|
|
13829
|
+
request: NextRequest,
|
|
13830
|
+
{ params }: { params: { id: string } }
|
|
13831
|
+
) {
|
|
13832
|
+
return NextResponse.json({
|
|
13833
|
+
message: \`User \${params.id} details\`
|
|
13834
|
+
});
|
|
13835
|
+
}
|
|
13836
|
+
|
|
13837
|
+
export async function PUT(
|
|
13838
|
+
request: NextRequest,
|
|
13839
|
+
{ params }: { params: { id: string } }
|
|
13840
|
+
) {
|
|
13841
|
+
const body = await request.json();
|
|
13842
|
+
return NextResponse.json({
|
|
13843
|
+
message: \`Updated user \${params.id}\`,
|
|
13844
|
+
data: body
|
|
13845
|
+
});
|
|
13846
|
+
}
|
|
13847
|
+
|
|
13848
|
+
export async function DELETE(
|
|
13849
|
+
request: NextRequest,
|
|
13850
|
+
{ params }: { params: { id: string } }
|
|
13851
|
+
) {
|
|
13852
|
+
return NextResponse.json({
|
|
13853
|
+
message: \`Deleted user \${params.id}\`
|
|
13854
|
+
});
|
|
13855
|
+
}`
|
|
13856
|
+
}
|
|
13857
|
+
],
|
|
13858
|
+
runCommands: isJapanese ? [
|
|
13859
|
+
"Next.js \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u914D\u7F6E",
|
|
13860
|
+
"pnpm dev \u3067\u30B5\u30FC\u30D0\u30FC\u8D77\u52D5",
|
|
13861
|
+
"curl http://localhost:3000/api/users \u3067\u30C6\u30B9\u30C8"
|
|
13862
|
+
] : [
|
|
13863
|
+
"Place in Next.js project",
|
|
13864
|
+
"Run server with npm run dev",
|
|
13865
|
+
"Test with curl http://localhost:3000/api/users"
|
|
13866
|
+
],
|
|
13867
|
+
notes: isJapanese ? [
|
|
13868
|
+
"App Router (Next.js 13+) \u3092\u4F7F\u7528",
|
|
13869
|
+
"\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u63A5\u7D9A\u306F\u5225\u9014\u5B9F\u88C5\u304C\u5FC5\u8981",
|
|
13870
|
+
"Middleware \u3067\u8A8D\u8A3C\u3092\u8FFD\u52A0\u53EF\u80FD"
|
|
13871
|
+
] : [
|
|
13872
|
+
"Uses App Router (Next.js 13+)",
|
|
13873
|
+
"Database connection needs separate implementation",
|
|
13874
|
+
"Can add authentication via middleware"
|
|
13875
|
+
],
|
|
13876
|
+
envVars: {
|
|
13877
|
+
"DATABASE_URL": "postgresql://user:pass@localhost/db"
|
|
13878
|
+
},
|
|
13879
|
+
isJapanese
|
|
13880
|
+
});
|
|
13881
|
+
}
|
|
13882
|
+
var init_code = __esm({
|
|
13883
|
+
"src/services/ai-response/responders/code.ts"() {
|
|
13884
|
+
init_common();
|
|
13885
|
+
}
|
|
13886
|
+
});
|
|
13887
|
+
|
|
13888
|
+
// src/services/ai-response/responders/continuation.ts
|
|
13889
|
+
function buildContinuationPrompt(contextPreview, isJapanese, customOptions) {
|
|
13890
|
+
const parts2 = [];
|
|
13891
|
+
parts2.push(isJapanese ? "\u7D9A\u304D\u3067\u3059\u306D\u3002\u76F4\u8FD1\u306E\u6D41\u308C\u3092\u78BA\u8A8D\u3057\u307E\u3057\u305F\u3002" : "I see you want to continue. Here's the recent context.");
|
|
13892
|
+
parts2.push("");
|
|
13893
|
+
if (contextPreview) {
|
|
13894
|
+
parts2.push(isJapanese ? "**\u76F4\u8FD1\u306E\u5185\u5BB9:**" : "**Recent context:**");
|
|
13895
|
+
parts2.push(`> ${truncateText(contextPreview, 300)}`);
|
|
13896
|
+
parts2.push("");
|
|
13897
|
+
}
|
|
13898
|
+
const defaultOptions = isJapanese ? [
|
|
13899
|
+
"\u30A8\u30E9\u30FC\u51E6\u7406\u306E\u8FFD\u52A0\uFF08try/catch\u30FB\u5177\u4F53\u7684\u30E1\u30C3\u30BB\u30FC\u30B8\uFF09",
|
|
13900
|
+
"\u30E2\u30B8\u30E5\u30FC\u30EB\u5206\u5272\uFF08\u95A2\u5FC3\u306E\u5206\u96E2\uFF09",
|
|
13901
|
+
"\u30C6\u30B9\u30C8\u8FFD\u52A0\uFF08\u5358\u4F53\u30C6\u30B9\u30C8\u30FB\u7D71\u5408\u30C6\u30B9\u30C8\uFF09",
|
|
13902
|
+
"\u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u6539\u5584\uFF08\u6700\u9069\u5316\u30FB\u30AD\u30E3\u30C3\u30B7\u30E5\uFF09",
|
|
13903
|
+
"\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u4F5C\u6210\uFF08README\u30FBAPI\u4ED5\u69D8\uFF09"
|
|
13904
|
+
] : [
|
|
13905
|
+
"Add error handling (try/catch with specific messages)",
|
|
13906
|
+
"Split into modules (separation of concerns)",
|
|
13907
|
+
"Add tests (unit and integration)",
|
|
13908
|
+
"Improve performance (optimization & caching)",
|
|
13909
|
+
"Create documentation (README & API specs)"
|
|
13910
|
+
];
|
|
13911
|
+
const options2 = customOptions && customOptions.length > 0 ? customOptions : defaultOptions;
|
|
13912
|
+
parts2.push(
|
|
13913
|
+
isJapanese ? "**\u6B21\u306E\u30B9\u30C6\u30C3\u30D7\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044:**" : "**Choose your next step:**"
|
|
13914
|
+
);
|
|
13915
|
+
parts2.push("");
|
|
13916
|
+
options2.forEach((option, i2) => {
|
|
13917
|
+
parts2.push(`${i2 + 1}) ${option}`);
|
|
13918
|
+
});
|
|
13919
|
+
parts2.push("");
|
|
13920
|
+
parts2.push(
|
|
13921
|
+
isJapanese ? "\u{1F4A1} \u63A8\u5968: \u8FF7\u3046\u5834\u5408\u306F 2\u21921\u21923 \u306E\u9806\u304C\u304A\u3059\u3059\u3081\u3067\u3059\u3002" : "\u{1F4A1} Tip: If unsure, try 2\u21921\u21923 in that order."
|
|
13922
|
+
);
|
|
13923
|
+
parts2.push(
|
|
13924
|
+
isJapanese ? "\n\u756A\u53F7\u3067\u6307\u793A\u3057\u3066\u304F\u3060\u3055\u3044\uFF081-5\uFF09\u3002\u8A73\u7D30\u306A\u8AAC\u660E\u3092\u8FFD\u52A0\u3057\u3066\u3082\u69CB\u3044\u307E\u305B\u3093\u3002" : "\nReply with a number (1-5). You can add details to your choice."
|
|
13925
|
+
);
|
|
13926
|
+
return parts2.join("\n");
|
|
13927
|
+
}
|
|
13928
|
+
function generateTopicBasedContinuation(topics, isJapanese) {
|
|
13929
|
+
const options2 = [];
|
|
13930
|
+
if (topics.some((t) => ["react", "vue", "angular", "frontend"].includes(t))) {
|
|
13931
|
+
options2.push(
|
|
13932
|
+
isJapanese ? "\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u306E\u5206\u5272\u3068props\u8A2D\u8A08" : "Component splitting and props design"
|
|
13933
|
+
);
|
|
13934
|
+
options2.push(
|
|
13935
|
+
isJapanese ? "\u72B6\u614B\u7BA1\u7406\u306E\u5B9F\u88C5\uFF08Context/Redux/Zustand\uFF09" : "State management (Context/Redux/Zustand)"
|
|
13936
|
+
);
|
|
13937
|
+
}
|
|
13938
|
+
if (topics.some((t) => ["api", "backend", "express", "fastapi"].includes(t))) {
|
|
13939
|
+
options2.push(
|
|
13940
|
+
isJapanese ? "API\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306E\u8FFD\u52A0" : "Add API endpoints"
|
|
13941
|
+
);
|
|
13942
|
+
options2.push(
|
|
13943
|
+
isJapanese ? "\u8A8D\u8A3C\u30FB\u8A8D\u53EF\u306E\u5B9F\u88C5" : "Implement authentication & authorization"
|
|
13944
|
+
);
|
|
13945
|
+
}
|
|
13946
|
+
if (topics.some((t) => ["database", "sql", "mongodb", "postgres"].includes(t))) {
|
|
13947
|
+
options2.push(
|
|
13948
|
+
isJapanese ? "\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30B9\u30AD\u30FC\u30DE\u306E\u8A2D\u8A08" : "Design database schema"
|
|
13949
|
+
);
|
|
13950
|
+
options2.push(
|
|
13951
|
+
isJapanese ? "\u30DE\u30A4\u30B0\u30EC\u30FC\u30B7\u30E7\u30F3\u3068\u30B7\u30FC\u30C9\u4F5C\u6210" : "Create migrations and seeds"
|
|
13952
|
+
);
|
|
13953
|
+
}
|
|
13954
|
+
if (topics.some((t) => ["test", "testing", "jest", "vitest"].includes(t))) {
|
|
13955
|
+
options2.push(
|
|
13956
|
+
isJapanese ? "\u30E6\u30CB\u30C3\u30C8\u30C6\u30B9\u30C8\u306E\u8FFD\u52A0" : "Add unit tests"
|
|
13957
|
+
);
|
|
13958
|
+
options2.push(
|
|
13959
|
+
isJapanese ? "E2E\u30C6\u30B9\u30C8\u306E\u5B9F\u88C5" : "Implement E2E tests"
|
|
13960
|
+
);
|
|
13961
|
+
}
|
|
13962
|
+
if (options2.length === 0) {
|
|
13963
|
+
options2.push(
|
|
13964
|
+
isJapanese ? "\u30B3\u30FC\u30C9\u306E\u8A73\u7D30\u306A\u5B9F\u88C5" : "Detailed code implementation"
|
|
13965
|
+
);
|
|
13966
|
+
options2.push(
|
|
13967
|
+
isJapanese ? "\u8A2D\u8A08\u30D1\u30BF\u30FC\u30F3\u306E\u9069\u7528" : "Apply design patterns"
|
|
13968
|
+
);
|
|
13969
|
+
}
|
|
13970
|
+
return options2;
|
|
13971
|
+
}
|
|
13972
|
+
function buildSmartContinuation(context2, detectedTopics, isJapanese) {
|
|
13973
|
+
const topicOptions = generateTopicBasedContinuation(detectedTopics, isJapanese);
|
|
13974
|
+
const generalOptions = isJapanese ? ["\u65E2\u5B58\u30B3\u30FC\u30C9\u306E\u30EA\u30D5\u30A1\u30AF\u30BF\u30EA\u30F3\u30B0", "\u65B0\u6A5F\u80FD\u306E\u8FFD\u52A0"] : ["Refactor existing code", "Add new features"];
|
|
13975
|
+
const allOptions = [...topicOptions, ...generalOptions].slice(0, 5);
|
|
13976
|
+
return buildContinuationPrompt(context2, isJapanese, allOptions);
|
|
13977
|
+
}
|
|
13978
|
+
var init_continuation = __esm({
|
|
13979
|
+
"src/services/ai-response/responders/continuation.ts"() {
|
|
13980
|
+
init_common();
|
|
13981
|
+
}
|
|
13982
|
+
});
|
|
13983
|
+
|
|
13984
|
+
// src/services/ai-response/responders/question.ts
|
|
13985
|
+
function buildQuestionResponse(options2) {
|
|
13986
|
+
const { question, isJapanese, topics = [], includeExample = true } = options2;
|
|
13987
|
+
const parts2 = [];
|
|
13988
|
+
const cleanQuestion = cleanUserInput(question);
|
|
13989
|
+
parts2.push(
|
|
13990
|
+
isJapanese ? `\u3054\u8CEA\u554F\u3042\u308A\u304C\u3068\u3046\u3054\u3056\u3044\u307E\u3059\u3002\u300C${cleanQuestion}\u300D\u306B\u3064\u3044\u3066\u8AAC\u660E\u3057\u307E\u3059\u3002` : `Great question about "${cleanQuestion}". Let me explain.`
|
|
13991
|
+
);
|
|
13992
|
+
parts2.push("");
|
|
13993
|
+
parts2.push(createSectionHeader(
|
|
13994
|
+
isJapanese ? "\u56DE\u7B54\u306E\u69CB\u6210" : "Answer Structure",
|
|
13995
|
+
3
|
|
13996
|
+
));
|
|
13997
|
+
parts2.push("");
|
|
13998
|
+
const structure2 = isJapanese ? [
|
|
13999
|
+
"\u80CC\u666F\u3068\u57FA\u672C\u6982\u5FF5",
|
|
14000
|
+
"\u5B9F\u88C5\u65B9\u6CD5\uFF08\u6700\u5C0F\u4F8B\uFF09",
|
|
14001
|
+
"\u30D9\u30B9\u30C8\u30D7\u30E9\u30AF\u30C6\u30A3\u30B9\u3068\u6CE8\u610F\u70B9",
|
|
14002
|
+
"\u5B9F\u969B\u306E\u4F7F\u7528\u4F8B"
|
|
14003
|
+
] : [
|
|
14004
|
+
"Background & Concepts",
|
|
14005
|
+
"Implementation (minimal example)",
|
|
14006
|
+
"Best practices & pitfalls",
|
|
14007
|
+
"Real-world use cases"
|
|
14008
|
+
];
|
|
14009
|
+
parts2.push(formatList(structure2, true));
|
|
14010
|
+
parts2.push("");
|
|
14011
|
+
parts2.push(createSectionHeader(
|
|
14012
|
+
isJapanese ? "\u7C21\u6F54\u306A\u56DE\u7B54" : "Quick Answer",
|
|
14013
|
+
3
|
|
14014
|
+
));
|
|
14015
|
+
parts2.push("");
|
|
14016
|
+
parts2.push(generateQuickAnswer(question, isJapanese, topics));
|
|
14017
|
+
parts2.push("");
|
|
14018
|
+
if (includeExample && shouldIncludeCode(question)) {
|
|
14019
|
+
parts2.push(createSectionHeader(
|
|
14020
|
+
isJapanese ? "\u30B3\u30FC\u30C9\u4F8B" : "Code Example",
|
|
14021
|
+
3
|
|
14022
|
+
));
|
|
14023
|
+
parts2.push("");
|
|
14024
|
+
parts2.push(generateExampleCode(topics));
|
|
14025
|
+
parts2.push("");
|
|
14026
|
+
}
|
|
14027
|
+
parts2.push(createSectionHeader(
|
|
14028
|
+
isJapanese ? "\u8A73\u7D30\u3092\u77E5\u308A\u305F\u3044\u5834\u5408" : "Want to know more?",
|
|
14029
|
+
3
|
|
14030
|
+
));
|
|
14031
|
+
parts2.push("");
|
|
14032
|
+
const detailOptions = isJapanese ? [
|
|
14033
|
+
"\u8A73\u7D30\u306A\u5B9F\u88C5\u4F8B\u3092\u898B\u308B",
|
|
14034
|
+
"\u95A2\u9023\u3059\u308B\u6982\u5FF5\u3092\u5B66\u3076",
|
|
14035
|
+
"\u30C8\u30E9\u30D6\u30EB\u30B7\u30E5\u30FC\u30C6\u30A3\u30F3\u30B0",
|
|
14036
|
+
"\u5B9F\u969B\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3078\u306E\u9069\u7528"
|
|
14037
|
+
] : [
|
|
14038
|
+
"See detailed implementation",
|
|
14039
|
+
"Learn related concepts",
|
|
14040
|
+
"Troubleshooting guide",
|
|
14041
|
+
"Apply to real project"
|
|
14042
|
+
];
|
|
14043
|
+
parts2.push(formatList(detailOptions, true));
|
|
14044
|
+
parts2.push("");
|
|
14045
|
+
parts2.push(
|
|
14046
|
+
isJapanese ? "\u756A\u53F7\u3092\u9078\u3093\u3067\u8A73\u7D30\u3092\u78BA\u8A8D\u3059\u308B\u304B\u3001\u8FFD\u52A0\u306E\u8CEA\u554F\u3092\u3057\u3066\u304F\u3060\u3055\u3044\u3002" : "Choose a number for details or ask a follow-up question."
|
|
14047
|
+
);
|
|
14048
|
+
return parts2.join("\n");
|
|
14049
|
+
}
|
|
14050
|
+
function generateQuickAnswer(question, isJapanese, topics) {
|
|
14051
|
+
const lowerQuestion = question.toLowerCase();
|
|
14052
|
+
if (lowerQuestion.includes("difference") || lowerQuestion.includes("\u9055\u3044")) {
|
|
14053
|
+
return isJapanese ? "\u4E3B\u306A\u9055\u3044\u306F\u3001\u76EE\u7684\u3068\u4F7F\u7528\u5834\u9762\u306B\u3042\u308A\u307E\u3059\u3002\u305D\u308C\u305E\u308C\u306E\u7279\u5FB4\u3092\u6BD4\u8F03\u3059\u308B\u3068..." : "The main difference lies in their purpose and use cases. Comparing their features...";
|
|
14054
|
+
}
|
|
14055
|
+
if (lowerQuestion.includes("how to") || lowerQuestion.includes("\u65B9\u6CD5")) {
|
|
14056
|
+
return isJapanese ? "\u5B9F\u88C5\u3059\u308B\u306B\u306F\u3001\u4EE5\u4E0B\u306E\u624B\u9806\u306B\u5F93\u3044\u307E\u3059\uFF1A1) \u6E96\u5099\u30012) \u5B9F\u88C5\u30013) \u30C6\u30B9\u30C8" : "To implement this, follow these steps: 1) Setup, 2) Implementation, 3) Testing";
|
|
14057
|
+
}
|
|
14058
|
+
if (lowerQuestion.includes("why") || lowerQuestion.includes("\u306A\u305C")) {
|
|
14059
|
+
return isJapanese ? "\u3053\u308C\u306B\u306F\u6280\u8853\u7684\u306A\u7406\u7531\u3068\u5B9F\u7528\u7684\u306A\u7406\u7531\u304C\u3042\u308A\u307E\u3059\u3002\u4E3B\u306A\u7406\u7531\u306F..." : "There are both technical and practical reasons. The main reasons are...";
|
|
14060
|
+
}
|
|
14061
|
+
if (lowerQuestion.includes("when") || lowerQuestion.includes("\u3044\u3064")) {
|
|
14062
|
+
return isJapanese ? "\u4F7F\u7528\u3059\u308B\u30BF\u30A4\u30DF\u30F3\u30B0\u306F\u3001\u7279\u5B9A\u306E\u6761\u4EF6\u304C\u63C3\u3063\u305F\u6642\u3067\u3059\u3002\u5177\u4F53\u7684\u306B\u306F..." : "Use this when specific conditions are met. Specifically...";
|
|
14063
|
+
}
|
|
14064
|
+
return isJapanese ? `${topics.length > 0 ? topics[0] + "\u306B\u95A2\u3057\u3066\u3001" : ""}\u91CD\u8981\u306A\u30DD\u30A4\u30F3\u30C8\u3092\u307E\u3068\u3081\u308B\u3068...` : `${topics.length > 0 ? "Regarding " + topics[0] + ", " : ""}The key points are...`;
|
|
14065
|
+
}
|
|
14066
|
+
function shouldIncludeCode(question) {
|
|
14067
|
+
const codeIndicators = [
|
|
14068
|
+
"implement",
|
|
14069
|
+
"code",
|
|
14070
|
+
"example",
|
|
14071
|
+
"how to",
|
|
14072
|
+
"\u5B9F\u88C5",
|
|
14073
|
+
"\u30B3\u30FC\u30C9",
|
|
14074
|
+
"\u4F8B",
|
|
14075
|
+
"\u65B9\u6CD5",
|
|
14076
|
+
"\u30B5\u30F3\u30D7\u30EB"
|
|
14077
|
+
];
|
|
14078
|
+
const lower = question.toLowerCase();
|
|
14079
|
+
return codeIndicators.some((indicator) => lower.includes(indicator));
|
|
14080
|
+
}
|
|
14081
|
+
function generateExampleCode(topics) {
|
|
14082
|
+
if (topics.includes("react")) {
|
|
14083
|
+
return `\`\`\`tsx
|
|
14084
|
+
const MyComponent = ({ title }: { title: string }) => {
|
|
14085
|
+
const [count, setCount] = useState(0);
|
|
14086
|
+
|
|
14087
|
+
return (
|
|
14088
|
+
<div>
|
|
14089
|
+
<h1>{title}</h1>
|
|
14090
|
+
<button onClick={() => setCount(c => c + 1)}>
|
|
14091
|
+
Count: {count}
|
|
14092
|
+
</button>
|
|
14093
|
+
</div>
|
|
14094
|
+
);
|
|
14095
|
+
};
|
|
14096
|
+
\`\`\``;
|
|
14097
|
+
}
|
|
14098
|
+
if (topics.includes("api")) {
|
|
14099
|
+
return `\`\`\`typescript
|
|
14100
|
+
app.get('/api/users/:id', async (req, res) => {
|
|
14101
|
+
try {
|
|
14102
|
+
const user = await getUserById(req.params.id);
|
|
14103
|
+
res.json(user);
|
|
14104
|
+
} catch (error) {
|
|
14105
|
+
res.status(404).json({ error: 'User not found' });
|
|
14106
|
+
}
|
|
14107
|
+
});
|
|
14108
|
+
\`\`\``;
|
|
14109
|
+
}
|
|
14110
|
+
return `\`\`\`typescript
|
|
14111
|
+
// Example implementation
|
|
14112
|
+
function solution(input: string): string {
|
|
14113
|
+
// Process input
|
|
14114
|
+
const processed = input.trim().toLowerCase();
|
|
14115
|
+
|
|
14116
|
+
// Apply logic
|
|
14117
|
+
const result = processData(processed);
|
|
14118
|
+
|
|
14119
|
+
// Return result
|
|
14120
|
+
return result;
|
|
14121
|
+
}
|
|
14122
|
+
\`\`\``;
|
|
14123
|
+
}
|
|
14124
|
+
function buildComprehensiveAnswer(question, detectedTopics, isJapanese) {
|
|
14125
|
+
return buildQuestionResponse({
|
|
14126
|
+
question,
|
|
14127
|
+
isJapanese,
|
|
14128
|
+
topics: detectedTopics,
|
|
14129
|
+
includeExample: true
|
|
14130
|
+
});
|
|
14131
|
+
}
|
|
14132
|
+
var init_question = __esm({
|
|
14133
|
+
"src/services/ai-response/responders/question.ts"() {
|
|
14134
|
+
init_common();
|
|
14135
|
+
}
|
|
14136
|
+
});
|
|
14137
|
+
|
|
14138
|
+
// src/services/ai-response/guards/safety.ts
|
|
14139
|
+
function checkInputSafety(input3, config2 = {}) {
|
|
14140
|
+
const {
|
|
14141
|
+
enablePIICheck = true,
|
|
14142
|
+
enablePromptInjectionCheck = true
|
|
14143
|
+
} = config2;
|
|
14144
|
+
if (enablePIICheck && containsPII(input3)) {
|
|
14145
|
+
return {
|
|
14146
|
+
safe: false,
|
|
14147
|
+
reason: "Input contains potential personal information",
|
|
14148
|
+
suggestion: "Please remove sensitive information before proceeding"
|
|
14149
|
+
};
|
|
14150
|
+
}
|
|
14151
|
+
if (enablePromptInjectionCheck && containsInjection(input3)) {
|
|
14152
|
+
return {
|
|
14153
|
+
safe: false,
|
|
14154
|
+
reason: "Input contains potential prompt injection",
|
|
14155
|
+
suggestion: "Please rephrase your request without system instructions"
|
|
14156
|
+
};
|
|
14157
|
+
}
|
|
14158
|
+
const harmful = detectHarmfulContent(input3);
|
|
14159
|
+
if (harmful.length > 0) {
|
|
14160
|
+
return {
|
|
14161
|
+
safe: true,
|
|
14162
|
+
// Allow but warn
|
|
14163
|
+
reason: `Note: Input mentions sensitive topics: ${harmful.join(", ")}`,
|
|
14164
|
+
suggestion: "Ensure you're not exposing sensitive data"
|
|
14165
|
+
};
|
|
14166
|
+
}
|
|
14167
|
+
return { safe: true };
|
|
14168
|
+
}
|
|
14169
|
+
function checkOutputSafety(output2, config2 = {}) {
|
|
14170
|
+
const {
|
|
14171
|
+
maxOutputChars = 5e4,
|
|
14172
|
+
// ~50KB
|
|
14173
|
+
maxCodeBlocks = 10
|
|
14174
|
+
} = config2;
|
|
14175
|
+
if (output2.length > maxOutputChars) {
|
|
14176
|
+
return {
|
|
14177
|
+
safe: false,
|
|
14178
|
+
reason: `Output too large (${output2.length} chars > ${maxOutputChars})`,
|
|
14179
|
+
suggestion: "Output has been truncated for safety"
|
|
14180
|
+
};
|
|
14181
|
+
}
|
|
14182
|
+
const codeBlockCount = (output2.match(/```/g) || []).length / 2;
|
|
14183
|
+
if (codeBlockCount > maxCodeBlocks) {
|
|
14184
|
+
return {
|
|
14185
|
+
safe: false,
|
|
14186
|
+
reason: `Too many code blocks (${codeBlockCount} > ${maxCodeBlocks})`,
|
|
14187
|
+
suggestion: "Consider splitting into multiple responses"
|
|
14188
|
+
};
|
|
14189
|
+
}
|
|
14190
|
+
return { safe: true };
|
|
14191
|
+
}
|
|
14192
|
+
function containsPII(input3) {
|
|
14193
|
+
return PII_PATTERNS.some((pattern2) => pattern2.test(input3));
|
|
14194
|
+
}
|
|
14195
|
+
function containsInjection(input3) {
|
|
14196
|
+
return INJECTION_PATTERNS.some((pattern2) => pattern2.test(input3));
|
|
14197
|
+
}
|
|
14198
|
+
function detectHarmfulContent(input3) {
|
|
14199
|
+
const lower = input3.toLowerCase();
|
|
14200
|
+
return HARMFUL_KEYWORDS.filter((keyword) => lower.includes(keyword.toLowerCase()));
|
|
14201
|
+
}
|
|
14202
|
+
function sanitizeOutput(output2, maxChars = 5e4) {
|
|
14203
|
+
if (output2.length > maxChars) {
|
|
14204
|
+
return output2.substring(0, maxChars) + "\n\n... [Output truncated for safety]";
|
|
14205
|
+
}
|
|
14206
|
+
let sanitized = output2;
|
|
14207
|
+
PII_PATTERNS.forEach((pattern2) => {
|
|
14208
|
+
sanitized = sanitized.replace(pattern2, "[REDACTED]");
|
|
14209
|
+
});
|
|
14210
|
+
return sanitized;
|
|
14211
|
+
}
|
|
14212
|
+
function isExplicitContentAllowed(input3, explicitKeyword) {
|
|
14213
|
+
const lower = input3.toLowerCase();
|
|
14214
|
+
return lower.includes(explicitKeyword.toLowerCase());
|
|
14215
|
+
}
|
|
14216
|
+
function generateRejectionMessage(reason, isJapanese) {
|
|
14217
|
+
const baseMessage = isJapanese ? `\u7533\u3057\u8A33\u3054\u3056\u3044\u307E\u305B\u3093\u3002\u5B89\u5168\u4E0A\u306E\u7406\u7531\u306B\u3088\u308A\u3001\u3053\u306E\u30EA\u30AF\u30A8\u30B9\u30C8\u306F\u51E6\u7406\u3067\u304D\u307E\u305B\u3093\u3002` : `I apologize, but I cannot process this request for safety reasons.`;
|
|
14218
|
+
const suggestions2 = isJapanese ? [
|
|
14219
|
+
"\u500B\u4EBA\u60C5\u5831\u3092\u9664\u5916\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
14220
|
+
"\u30EA\u30AF\u30A8\u30B9\u30C8\u3092\u8A00\u3044\u63DB\u3048\u3066\u304F\u3060\u3055\u3044",
|
|
14221
|
+
"\u5C0F\u3055\u306A\u90E8\u5206\u306B\u5206\u5272\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
14222
|
+
] : [
|
|
14223
|
+
"Remove personal information",
|
|
14224
|
+
"Rephrase your request",
|
|
14225
|
+
"Break into smaller parts"
|
|
14226
|
+
];
|
|
14227
|
+
return `${baseMessage}
|
|
14228
|
+
|
|
14229
|
+
**${isJapanese ? "\u7406\u7531" : "Reason"}:** ${reason}
|
|
14230
|
+
|
|
14231
|
+
**${isJapanese ? "\u63D0\u6848" : "Suggestions"}:**
|
|
14232
|
+
${suggestions2.map((s2, i2) => `${i2 + 1}. ${s2}`).join("\n")}`;
|
|
14233
|
+
}
|
|
14234
|
+
function logSafetyEvent(event) {
|
|
14235
|
+
console.log("[Safety Guard]", {
|
|
14236
|
+
...event,
|
|
14237
|
+
timestamp: event.timestamp || Date.now()
|
|
14238
|
+
});
|
|
14239
|
+
}
|
|
14240
|
+
var PII_PATTERNS, HARMFUL_KEYWORDS, INJECTION_PATTERNS;
|
|
14241
|
+
var init_safety = __esm({
|
|
14242
|
+
"src/services/ai-response/guards/safety.ts"() {
|
|
14243
|
+
PII_PATTERNS = [
|
|
14244
|
+
/\b\d{3}-\d{2}-\d{4}\b/,
|
|
14245
|
+
// SSN
|
|
14246
|
+
/\b\d{16}\b/,
|
|
14247
|
+
// Credit card
|
|
14248
|
+
/\b[A-Z]{2}\d{6}\b/,
|
|
14249
|
+
// Passport
|
|
14250
|
+
/\b\d{3}-?\d{3}-?\d{4}\b/
|
|
14251
|
+
// Phone
|
|
14252
|
+
];
|
|
14253
|
+
HARMFUL_KEYWORDS = [
|
|
14254
|
+
"password",
|
|
14255
|
+
"secret",
|
|
14256
|
+
"token",
|
|
14257
|
+
"api_key",
|
|
14258
|
+
"private_key",
|
|
14259
|
+
"\u30D1\u30B9\u30EF\u30FC\u30C9",
|
|
14260
|
+
"\u30B7\u30FC\u30AF\u30EC\u30C3\u30C8",
|
|
14261
|
+
"\u30C8\u30FC\u30AF\u30F3",
|
|
14262
|
+
"\u79D8\u5BC6\u9375"
|
|
14263
|
+
];
|
|
14264
|
+
INJECTION_PATTERNS = [
|
|
14265
|
+
/ignore.*previous.*instructions?/i,
|
|
14266
|
+
/disregard.*above/i,
|
|
14267
|
+
/forget.*everything/i,
|
|
14268
|
+
/system.*prompt/i,
|
|
14269
|
+
/you.*are.*now/i,
|
|
14270
|
+
/前の.*指示.*無視/,
|
|
14271
|
+
/システム.*プロンプト/
|
|
14272
|
+
];
|
|
14273
|
+
}
|
|
14274
|
+
});
|
|
14275
|
+
|
|
11760
14276
|
// src/services/ai-response.service.ts
|
|
11761
14277
|
var AIResponseService;
|
|
11762
14278
|
var init_ai_response_service = __esm({
|
|
@@ -11764,216 +14280,345 @@ var init_ai_response_service = __esm({
|
|
|
11764
14280
|
init_chat_context_fixed_service();
|
|
11765
14281
|
init_conversation_persistence();
|
|
11766
14282
|
init_ai_response_tetris_template();
|
|
14283
|
+
init_intent();
|
|
14284
|
+
init_provider_factory();
|
|
14285
|
+
init_feature_flags();
|
|
14286
|
+
init_telemetry_collector();
|
|
14287
|
+
init_context();
|
|
14288
|
+
init_code();
|
|
14289
|
+
init_continuation();
|
|
14290
|
+
init_question();
|
|
14291
|
+
init_safety();
|
|
11767
14292
|
AIResponseService = class {
|
|
11768
14293
|
chatContext;
|
|
11769
|
-
|
|
14294
|
+
_conversationPersistence;
|
|
14295
|
+
providerFactory;
|
|
14296
|
+
telemetry;
|
|
14297
|
+
initialized = false;
|
|
11770
14298
|
constructor() {
|
|
11771
14299
|
this.chatContext = ChatContextService.getInstance();
|
|
11772
|
-
this.
|
|
14300
|
+
this._conversationPersistence = new ConversationPersistence();
|
|
14301
|
+
this.providerFactory = AIProviderFactory.getInstance();
|
|
14302
|
+
this.telemetry = TelemetryCollector.getInstance();
|
|
14303
|
+
this.initializeProviders().catch(console.error);
|
|
14304
|
+
}
|
|
14305
|
+
/**
|
|
14306
|
+
* Initialize AI providers based on configuration
|
|
14307
|
+
*/
|
|
14308
|
+
async initializeProviders() {
|
|
14309
|
+
if (this.initialized) return;
|
|
14310
|
+
try {
|
|
14311
|
+
await this.providerFactory.initializeFromEnvironment();
|
|
14312
|
+
this.initialized = true;
|
|
14313
|
+
console.log("[AI Response Service] Providers initialized");
|
|
14314
|
+
} catch (error2) {
|
|
14315
|
+
console.error("[AI Response Service] Provider initialization failed:", error2);
|
|
14316
|
+
}
|
|
11773
14317
|
}
|
|
11774
14318
|
/**
|
|
11775
|
-
* Generate intelligent AI response
|
|
11776
|
-
*
|
|
14319
|
+
* Generate intelligent AI response with multi-language support and safety guards
|
|
14320
|
+
* v3.0 - Complete rewrite with modular architecture
|
|
11777
14321
|
*/
|
|
11778
14322
|
async generateResponse(request2, options2 = {}) {
|
|
14323
|
+
const startTime = Date.now();
|
|
11779
14324
|
try {
|
|
14325
|
+
const inputSafety = checkInputSafety(request2.userInput);
|
|
14326
|
+
if (!inputSafety.safe) {
|
|
14327
|
+
logSafetyEvent({ type: "input_check", safe: false, reason: inputSafety.reason });
|
|
14328
|
+
const lang = detectLanguage(request2.userInput);
|
|
14329
|
+
return generateRejectionMessage(inputSafety.reason || "Safety check failed", lang === "ja");
|
|
14330
|
+
}
|
|
11780
14331
|
await this.chatContext.addMessage({
|
|
11781
14332
|
role: "user",
|
|
11782
14333
|
content: request2.userInput
|
|
11783
14334
|
});
|
|
11784
|
-
const context2 =
|
|
11785
|
-
|
|
14335
|
+
const context2 = buildContextForAI(
|
|
14336
|
+
request2.sessionMemory,
|
|
14337
|
+
{
|
|
14338
|
+
budgetChars: options2.contextLength ? options2.contextLength * 4 : 8e3,
|
|
14339
|
+
maxMessages: 20
|
|
14340
|
+
}
|
|
14341
|
+
);
|
|
14342
|
+
const language2 = detectLanguage(request2.userInput);
|
|
14343
|
+
const recentText = context2.recentMessages.map((m2) => m2.content).join(" ");
|
|
14344
|
+
const intent2 = analyzeIntent(request2.userInput, recentText);
|
|
14345
|
+
if (featureFlags.isEnabled("enableTelemetry")) {
|
|
14346
|
+
this.telemetry.trackIntent({
|
|
14347
|
+
type: intent2.type,
|
|
14348
|
+
confidence: intent2.confidence,
|
|
14349
|
+
language: language2,
|
|
14350
|
+
timestamp: Date.now()
|
|
14351
|
+
});
|
|
14352
|
+
}
|
|
14353
|
+
let aiResponse;
|
|
14354
|
+
const config2 = featureFlags.getAIResponseConfig();
|
|
14355
|
+
if (config2.useRealProviders && intent2.type !== "TETRIS_REQUEST") {
|
|
14356
|
+
aiResponse = await this.generateWithProvider(
|
|
14357
|
+
request2.userInput,
|
|
14358
|
+
context2,
|
|
14359
|
+
language2,
|
|
14360
|
+
options2
|
|
14361
|
+
);
|
|
14362
|
+
} else {
|
|
14363
|
+
aiResponse = await this.routeByIntent(
|
|
14364
|
+
intent2,
|
|
14365
|
+
request2.userInput,
|
|
14366
|
+
context2,
|
|
14367
|
+
{ language: language2, options: options2 }
|
|
14368
|
+
);
|
|
14369
|
+
}
|
|
14370
|
+
const outputSafety = checkOutputSafety(aiResponse);
|
|
14371
|
+
const finalResponse = outputSafety.safe ? aiResponse : sanitizeOutput(aiResponse, 5e4);
|
|
11786
14372
|
await this.chatContext.addMessage({
|
|
11787
14373
|
role: "assistant",
|
|
11788
|
-
content:
|
|
14374
|
+
content: finalResponse
|
|
11789
14375
|
});
|
|
11790
|
-
|
|
14376
|
+
const latency = Date.now() - startTime;
|
|
14377
|
+
if (featureFlags.isEnabled("enableTelemetry")) {
|
|
14378
|
+
this.telemetry.trackResponse({
|
|
14379
|
+
provider: config2.useRealProviders ? config2.providerType : "template",
|
|
14380
|
+
model: "unknown",
|
|
14381
|
+
// Would need to get from provider
|
|
14382
|
+
latencyMs: latency,
|
|
14383
|
+
success: true,
|
|
14384
|
+
fallback: !config2.useRealProviders,
|
|
14385
|
+
timestamp: Date.now()
|
|
14386
|
+
});
|
|
14387
|
+
}
|
|
14388
|
+
return finalResponse;
|
|
11791
14389
|
} catch (error2) {
|
|
11792
14390
|
console.error("AI Response generation failed:", error2);
|
|
14391
|
+
logSafetyEvent({ type: "rejection", safe: false, reason: "Generation failed" });
|
|
14392
|
+
if (featureFlags.isEnabled("enableTelemetry")) {
|
|
14393
|
+
this.telemetry.trackError(error2, {
|
|
14394
|
+
userInput: request2.userInput,
|
|
14395
|
+
provider: "unknown"
|
|
14396
|
+
});
|
|
14397
|
+
}
|
|
11793
14398
|
return this.generateFallbackResponse(request2.userInput);
|
|
11794
14399
|
}
|
|
11795
14400
|
}
|
|
11796
14401
|
/**
|
|
11797
|
-
*
|
|
11798
|
-
|
|
11799
|
-
buildContextForAI(request2) {
|
|
11800
|
-
const recentContext = request2.sessionMemory.slice(-5);
|
|
11801
|
-
return {
|
|
11802
|
-
messages: recentContext.map((msg2) => ({
|
|
11803
|
-
role: msg2.role,
|
|
11804
|
-
content: msg2.content
|
|
11805
|
-
})),
|
|
11806
|
-
currentInput: request2.userInput,
|
|
11807
|
-
contextStats: this.chatContext.getStats()
|
|
11808
|
-
};
|
|
11809
|
-
}
|
|
11810
|
-
/**
|
|
11811
|
-
* Call actual AI provider with intelligent intent recognition
|
|
14402
|
+
* Route request to appropriate responder based on intent
|
|
14403
|
+
* v3.0 - New routing logic with language awareness
|
|
11812
14404
|
*/
|
|
11813
|
-
async
|
|
11814
|
-
const
|
|
11815
|
-
const
|
|
11816
|
-
const
|
|
14405
|
+
async routeByIntent(intent2, userInput2, context2, config2) {
|
|
14406
|
+
const { language: language2 } = config2;
|
|
14407
|
+
const isJapanese = language2 === "ja";
|
|
14408
|
+
const topics = extractKeyTopics(context2);
|
|
11817
14409
|
switch (intent2.type) {
|
|
11818
14410
|
case "TETRIS_REQUEST":
|
|
11819
|
-
|
|
14411
|
+
if (isExplicitContentAllowed(userInput2, "tetris")) {
|
|
14412
|
+
return generateTetrisGameTemplate(userInput2);
|
|
14413
|
+
}
|
|
14414
|
+
return this.generateDefaultResponse(userInput2);
|
|
11820
14415
|
case "CODE_REQUEST":
|
|
11821
|
-
|
|
14416
|
+
if (userInput2.toLowerCase().includes("cli")) {
|
|
14417
|
+
return generateCLITemplate(isJapanese);
|
|
14418
|
+
}
|
|
14419
|
+
if (userInput2.toLowerCase().includes("api") || userInput2.toLowerCase().includes("next")) {
|
|
14420
|
+
return generateNextAPITemplate(isJapanese);
|
|
14421
|
+
}
|
|
14422
|
+
return buildCodeResponse({
|
|
14423
|
+
title: isJapanese ? "\u30B3\u30FC\u30C9\u5B9F\u88C5\u4F8B" : "Code Implementation",
|
|
14424
|
+
files: [{
|
|
14425
|
+
path: "example.ts",
|
|
14426
|
+
lang: "typescript",
|
|
14427
|
+
content: `// Your implementation here
|
|
14428
|
+
console.log('Hello World');`
|
|
14429
|
+
}],
|
|
14430
|
+
runCommands: isJapanese ? ["\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210", "node example.js \u3067\u5B9F\u884C"] : ["Create the file", "Run with node example.js"],
|
|
14431
|
+
isJapanese
|
|
14432
|
+
});
|
|
11822
14433
|
case "QUESTION":
|
|
11823
|
-
return
|
|
14434
|
+
return buildComprehensiveAnswer(userInput2, topics, isJapanese);
|
|
11824
14435
|
case "CONTINUATION":
|
|
11825
|
-
|
|
14436
|
+
const contextPreview = context2.recentMessages.slice(-3).map((m2) => m2.content).join(" ");
|
|
14437
|
+
return buildSmartContinuation(contextPreview, topics, isJapanese);
|
|
14438
|
+
case "SUMMARIZE":
|
|
14439
|
+
return this.generateSummaryResponse(context2, isJapanese);
|
|
14440
|
+
case "REFACTOR":
|
|
14441
|
+
return this.generateRefactorResponse(userInput2, isJapanese);
|
|
11826
14442
|
default:
|
|
11827
|
-
|
|
11828
|
-
return this.generateContextualResponse(userInput2, context2);
|
|
11829
|
-
}
|
|
11830
|
-
return this.generateDefaultResponse(userInput2);
|
|
11831
|
-
}
|
|
11832
|
-
}
|
|
11833
|
-
/**
|
|
11834
|
-
* Enhanced intent analysis with context awareness
|
|
11835
|
-
*/
|
|
11836
|
-
analyzeIntent(userInput2, context2) {
|
|
11837
|
-
const messages2 = context2.messages || [];
|
|
11838
|
-
const recentMessages2 = messages2.slice(-3);
|
|
11839
|
-
const contextString = recentMessages2.map((m2) => m2.content).join(" ").toLowerCase();
|
|
11840
|
-
if (userInput2.includes("tetris")) {
|
|
11841
|
-
return {
|
|
11842
|
-
type: "TETRIS_REQUEST",
|
|
11843
|
-
confidence: 0.9,
|
|
11844
|
-
context: "User wants Tetris game code"
|
|
11845
|
-
};
|
|
11846
|
-
}
|
|
11847
|
-
if (this.isCodeRequest(userInput2)) {
|
|
11848
|
-
return {
|
|
11849
|
-
type: "CODE_REQUEST",
|
|
11850
|
-
confidence: 0.8,
|
|
11851
|
-
context: "User wants code implementation"
|
|
11852
|
-
};
|
|
14443
|
+
return this.generateSmartDefault(userInput2, topics, isJapanese);
|
|
11853
14444
|
}
|
|
11854
|
-
if (contextString.length > 0 && (userInput2.includes("whole code") || userInput2.includes("complete") || userInput2.includes("start") || userInput2.includes("give me"))) {
|
|
11855
|
-
return {
|
|
11856
|
-
type: "CONTINUATION",
|
|
11857
|
-
confidence: 0.7,
|
|
11858
|
-
context: "User continuing previous conversation"
|
|
11859
|
-
};
|
|
11860
|
-
}
|
|
11861
|
-
if (this.isQuestionRequest(userInput2)) {
|
|
11862
|
-
return {
|
|
11863
|
-
type: "QUESTION",
|
|
11864
|
-
confidence: 0.6,
|
|
11865
|
-
context: "User asking a question"
|
|
11866
|
-
};
|
|
11867
|
-
}
|
|
11868
|
-
return {
|
|
11869
|
-
type: "GENERAL",
|
|
11870
|
-
confidence: 0.3,
|
|
11871
|
-
context: "General conversation"
|
|
11872
|
-
};
|
|
11873
14445
|
}
|
|
11874
14446
|
/**
|
|
11875
|
-
* Generate
|
|
14447
|
+
* Generate summary response
|
|
11876
14448
|
*/
|
|
11877
|
-
|
|
11878
|
-
const
|
|
11879
|
-
const
|
|
11880
|
-
|
|
11881
|
-
return `Got it \u2014 you'd like to continue from our recent context.
|
|
14449
|
+
generateSummaryResponse(context2, isJapanese) {
|
|
14450
|
+
const stats2 = getContextStats(context2);
|
|
14451
|
+
const topics = stats2.topics.join(", ") || (isJapanese ? "\u4E00\u822C\u7684\u306A\u4F1A\u8A71" : "general conversation");
|
|
14452
|
+
return isJapanese ? `\u76F4\u8FD1\u306E\u4F1A\u8A71\u3092\u8981\u7D04\u3057\u307E\u3059\uFF1A
|
|
11882
14453
|
|
|
11883
|
-
|
|
11884
|
-
|
|
14454
|
+
\u{1F4CA} **\u7D71\u8A08\u60C5\u5831**
|
|
14455
|
+
\u2022 \u30E1\u30C3\u30BB\u30FC\u30B8\u6570: ${stats2.messageCount}
|
|
14456
|
+
\u2022 \u5408\u8A08\u6587\u5B57\u6570: ${stats2.totalChars}
|
|
14457
|
+
\u2022 \u30C8\u30D4\u30C3\u30AF: ${topics}
|
|
11885
14458
|
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
/**
|
|
11889
|
-
* Detect if user is asking for code/implementation
|
|
11890
|
-
*/
|
|
11891
|
-
isCodeRequest(input3) {
|
|
11892
|
-
const codeKeywords = ["implement", "create", "build", "code", "function", "class", "html", "css", "javascript", "python", "typescript"];
|
|
11893
|
-
return codeKeywords.some((keyword) => input3.includes(keyword));
|
|
11894
|
-
}
|
|
11895
|
-
/**
|
|
11896
|
-
* Detect if user is asking a question
|
|
11897
|
-
*/
|
|
11898
|
-
isQuestionRequest(input3) {
|
|
11899
|
-
const questionWords = ["what", "how", "why", "when", "where", "which", "who"];
|
|
11900
|
-
return questionWords.some((word) => input3.startsWith(word)) || input3.includes("?");
|
|
11901
|
-
}
|
|
11902
|
-
/**
|
|
11903
|
-
* Generate code-focused response
|
|
11904
|
-
*/
|
|
11905
|
-
generateCodeResponse(input3, _context) {
|
|
11906
|
-
if (input3.includes("tetris") && (input3.includes("html") || input3.includes("index"))) {
|
|
11907
|
-
return this.generateTetrisGame(input3);
|
|
11908
|
-
}
|
|
11909
|
-
return `I understand you want to implement something with code. Let me help you build it step by step.
|
|
14459
|
+
\u{1F4DD} **\u8981\u7D04**
|
|
14460
|
+
${context2.rollingSummary || "\u8981\u7D04\u3059\u308B\u5185\u5BB9\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u307E\u3059\u3002"}
|
|
11910
14461
|
|
|
11911
|
-
|
|
11912
|
-
\
|
|
11913
|
-
\
|
|
11914
|
-
\
|
|
11915
|
-
\u2022 Testing suggestions
|
|
14462
|
+
\u6B21\u306E\u30B9\u30C6\u30C3\u30D7\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF1A
|
|
14463
|
+
1) \u8A73\u7D30\u306A\u8981\u7D04\u3092\u898B\u308B
|
|
14464
|
+
2) \u7279\u5B9A\u306E\u30C8\u30D4\u30C3\u30AF\u306B\u7D5E\u308B
|
|
14465
|
+
3) \u65B0\u3057\u3044\u8CEA\u554F\u3092\u3059\u308B` : `Here's a summary of our recent conversation:
|
|
11916
14466
|
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
11923
|
-
|
|
14467
|
+
\u{1F4CA} **Statistics**
|
|
14468
|
+
\u2022 Messages: ${stats2.messageCount}
|
|
14469
|
+
\u2022 Total chars: ${stats2.totalChars}
|
|
14470
|
+
\u2022 Topics: ${topics}
|
|
14471
|
+
|
|
14472
|
+
\u{1F4DD} **Summary**
|
|
14473
|
+
${context2.rollingSummary || "Not enough content to summarize."}
|
|
14474
|
+
|
|
14475
|
+
Choose your next step:
|
|
14476
|
+
1) See detailed summary
|
|
14477
|
+
2) Focus on specific topic
|
|
14478
|
+
3) Ask a new question`;
|
|
11924
14479
|
}
|
|
11925
14480
|
/**
|
|
11926
|
-
* Generate
|
|
14481
|
+
* Generate refactoring suggestions
|
|
11927
14482
|
*/
|
|
11928
|
-
|
|
11929
|
-
return
|
|
14483
|
+
generateRefactorResponse(input3, isJapanese) {
|
|
14484
|
+
return isJapanese ? `\u30EA\u30D5\u30A1\u30AF\u30BF\u30EA\u30F3\u30B0\u306E\u3054\u8981\u671B\u3067\u3059\u306D\u3002\u300C${input3.substring(0, 50)}\u300D\u3092\u6539\u5584\u3057\u307E\u3059\u3002
|
|
11930
14485
|
|
|
11931
|
-
|
|
14486
|
+
**\u6539\u5584\u30DD\u30A4\u30F3\u30C8**
|
|
14487
|
+
1) \u53EF\u8AAD\u6027\u306E\u5411\u4E0A\uFF08\u5909\u6570\u540D\u30FB\u95A2\u6570\u540D\u306E\u6539\u5584\uFF09
|
|
14488
|
+
2) \u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u306E\u6700\u9069\u5316
|
|
14489
|
+
3) \u91CD\u8907\u30B3\u30FC\u30C9\u306E\u524A\u9664
|
|
14490
|
+
4) \u30C7\u30B6\u30A4\u30F3\u30D1\u30BF\u30FC\u30F3\u306E\u9069\u7528
|
|
11932
14491
|
|
|
11933
|
-
\
|
|
11934
|
-
\u2022 Practical implementation details
|
|
11935
|
-
\u2022 Best practices and common pitfalls
|
|
11936
|
-
\u2022 Real-world examples and use cases
|
|
14492
|
+
\u3069\u306E\u89B3\u70B9\u304B\u3089\u59CB\u3081\u307E\u3059\u304B\uFF1F\uFF081-4\u3067\u9078\u629E\uFF09` : `I'll help you refactor "${input3.substring(0, 50)}".
|
|
11937
14493
|
|
|
11938
|
-
|
|
14494
|
+
**Improvement areas**
|
|
14495
|
+
1) Readability (better naming)
|
|
14496
|
+
2) Performance optimization
|
|
14497
|
+
3) Remove duplication
|
|
14498
|
+
4) Apply design patterns
|
|
14499
|
+
|
|
14500
|
+
Which aspect should we start with? (Choose 1-4)`;
|
|
11939
14501
|
}
|
|
11940
14502
|
/**
|
|
11941
|
-
* Generate
|
|
14503
|
+
* Generate smart default response with choices
|
|
11942
14504
|
*/
|
|
11943
|
-
|
|
11944
|
-
const
|
|
11945
|
-
|
|
14505
|
+
generateSmartDefault(input3, topics, isJapanese) {
|
|
14506
|
+
const cleanInput = input3.substring(0, 100);
|
|
14507
|
+
const options2 = isJapanese ? [
|
|
14508
|
+
"\u4ECA\u3059\u3050\u52D5\u304F\u6700\u5C0F\u30B3\u30FC\u30C9",
|
|
14509
|
+
"\u8A2D\u8A08\u65B9\u91DD\u3068\u30C8\u30EC\u30FC\u30C9\u30AA\u30D5",
|
|
14510
|
+
"\u65E2\u5B58\u30B3\u30FC\u30C9\u306E\u6539\u5584\u63D0\u6848",
|
|
14511
|
+
"\u8A73\u7D30\u306A\u8AAC\u660E\u3092\u805E\u304F"
|
|
14512
|
+
] : [
|
|
14513
|
+
"Minimal working code",
|
|
14514
|
+
"Design & trade-offs",
|
|
14515
|
+
"Improve existing code",
|
|
14516
|
+
"Detailed explanation"
|
|
14517
|
+
];
|
|
14518
|
+
const topicNote = topics.length > 0 ? isJapanese ? `
|
|
14519
|
+
\u691C\u51FA\u3055\u308C\u305F\u30C8\u30D4\u30C3\u30AF: ${topics.join(", ")}` : `
|
|
14520
|
+
Detected topics: ${topics.join(", ")}` : "";
|
|
14521
|
+
return isJapanese ? `\u3054\u4F9D\u983C\u3042\u308A\u304C\u3068\u3046\u3054\u3056\u3044\u307E\u3059\u3002\u300C${cleanInput}\u300D\u306B\u3064\u3044\u3066\u5BFE\u5FDC\u3057\u307E\u3059\u3002${topicNote}
|
|
11946
14522
|
|
|
11947
|
-
|
|
14523
|
+
\u6700\u77ED\u3067\u76EE\u7684\u3092\u9054\u6210\u3059\u308B\u305F\u3081\u3001\u4EE5\u4E0B\u304B\u3089\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF1A
|
|
14524
|
+
${options2.map((opt, i2) => `${i2 + 1}) ${opt}`).join("\n")}
|
|
11948
14525
|
|
|
11949
|
-
|
|
14526
|
+
\u756A\u53F7\u3067\u6307\u793A\u3057\u3066\u304F\u3060\u3055\u3044\uFF081-4\uFF09\u3002` : `Thanks for your request: "${cleanInput}"${topicNote}
|
|
11950
14527
|
|
|
11951
|
-
|
|
14528
|
+
Choose your fastest path to success:
|
|
14529
|
+
${options2.map((opt, i2) => `${i2 + 1}) ${opt}`).join("\n")}
|
|
14530
|
+
|
|
14531
|
+
Reply with a number (1-4).`;
|
|
14532
|
+
}
|
|
14533
|
+
/**
|
|
14534
|
+
* Generate response using real AI provider
|
|
14535
|
+
*/
|
|
14536
|
+
async generateWithProvider(userInput2, context2, language2, options2) {
|
|
14537
|
+
try {
|
|
14538
|
+
const provider2 = await this.providerFactory.getActiveProvider();
|
|
14539
|
+
const messages2 = [];
|
|
14540
|
+
messages2.push({
|
|
14541
|
+
role: "system",
|
|
14542
|
+
content: language2 === "ja" ? "\u3042\u306A\u305F\u306F\u89AA\u5207\u3067\u77E5\u8B58\u8C4A\u5BCC\u306A\u30A2\u30B7\u30B9\u30BF\u30F3\u30C8\u3067\u3059\u3002\u65E5\u672C\u8A9E\u3067\u4E01\u5BE7\u306B\u56DE\u7B54\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30B3\u30FC\u30C9\u3092\u63D0\u4F9B\u3059\u308B\u5834\u5408\u306F\u3001\u5B9F\u884C\u624B\u9806\u3082\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002" : "You are a helpful and knowledgeable assistant. Provide clear, actionable responses. When providing code, include execution instructions."
|
|
14543
|
+
});
|
|
14544
|
+
if (context2.rollingSummary) {
|
|
14545
|
+
messages2.push({
|
|
14546
|
+
role: "system",
|
|
14547
|
+
content: `Previous context summary: ${context2.rollingSummary}`
|
|
14548
|
+
});
|
|
14549
|
+
}
|
|
14550
|
+
context2.recentMessages.forEach((msg2) => {
|
|
14551
|
+
messages2.push({
|
|
14552
|
+
role: msg2.role,
|
|
14553
|
+
content: msg2.content
|
|
14554
|
+
});
|
|
14555
|
+
});
|
|
14556
|
+
const lastMessage2 = context2.recentMessages[context2.recentMessages.length - 1];
|
|
14557
|
+
if (!lastMessage2 || lastMessage2.content !== userInput2) {
|
|
14558
|
+
messages2.push({
|
|
14559
|
+
role: "user",
|
|
14560
|
+
content: userInput2
|
|
14561
|
+
});
|
|
14562
|
+
}
|
|
14563
|
+
const response2 = await provider2.generateCompletion({
|
|
14564
|
+
messages: messages2,
|
|
14565
|
+
temperature: options2.temperature,
|
|
14566
|
+
maxTokens: options2.contextLength,
|
|
14567
|
+
streaming: options2.streaming && featureFlags.isEnabled("enableStreaming")
|
|
14568
|
+
});
|
|
14569
|
+
const footer = language2 === "ja" ? "\n\n\u6B21\u306E\u30B9\u30C6\u30C3\u30D7\u3092\u304A\u9078\u3073\u304F\u3060\u3055\u3044\uFF1A\n1) \u8A73\u7D30\u3092\u898B\u308B\n2) \u5B9F\u88C5\u3092\u958B\u59CB\n3) \u5225\u306E\u8CEA\u554F" : "\n\nChoose next step:\n1) See details\n2) Start implementation\n3) Different question";
|
|
14570
|
+
return response2.content + footer;
|
|
14571
|
+
} catch (error2) {
|
|
14572
|
+
console.error("[AI Response] Provider generation failed:", error2);
|
|
14573
|
+
return this.routeByIntent(
|
|
14574
|
+
analyzeIntent(userInput2, ""),
|
|
14575
|
+
userInput2,
|
|
14576
|
+
context2,
|
|
14577
|
+
{ language: language2, options: options2 }
|
|
14578
|
+
);
|
|
14579
|
+
}
|
|
11952
14580
|
}
|
|
11953
14581
|
/**
|
|
11954
|
-
* Generate default
|
|
14582
|
+
* Generate default response (kept for compatibility)
|
|
11955
14583
|
*/
|
|
11956
14584
|
generateDefaultResponse(input3) {
|
|
11957
|
-
|
|
14585
|
+
const lang = detectLanguage(input3);
|
|
14586
|
+
const isJapanese = lang === "ja";
|
|
14587
|
+
return isJapanese ? `\u300C${input3.substring(0, 50)}\u300D\u306B\u3064\u3044\u3066\u5BFE\u5FDC\u3044\u305F\u3057\u307E\u3059\u3002
|
|
11958
14588
|
|
|
11959
|
-
|
|
11960
|
-
\
|
|
11961
|
-
\
|
|
11962
|
-
\
|
|
11963
|
-
\u2022 Best practices and optimization
|
|
14589
|
+
\u4EE5\u4E0B\u304B\u3089\u304A\u9078\u3073\u304F\u3060\u3055\u3044\uFF1A
|
|
14590
|
+
1) \u5B9F\u88C5\u65B9\u6CD5\u3092\u898B\u308B
|
|
14591
|
+
2) \u6982\u5FF5\u3092\u7406\u89E3\u3059\u308B
|
|
14592
|
+
3) \u554F\u984C\u3092\u89E3\u6C7A\u3059\u308B
|
|
11964
14593
|
|
|
11965
|
-
|
|
14594
|
+
\u756A\u53F7\u3067\u304A\u7B54\u3048\u304F\u3060\u3055\u3044\u3002` : `I'll help you with: "${input3.substring(0, 50)}"
|
|
14595
|
+
|
|
14596
|
+
Choose an option:
|
|
14597
|
+
1) See implementation
|
|
14598
|
+
2) Understand concepts
|
|
14599
|
+
3) Solve problems
|
|
14600
|
+
|
|
14601
|
+
Reply with a number.`;
|
|
11966
14602
|
}
|
|
11967
14603
|
/**
|
|
11968
|
-
* Fallback response for errors
|
|
14604
|
+
* Fallback response for errors with language detection
|
|
11969
14605
|
*/
|
|
11970
14606
|
generateFallbackResponse(input3) {
|
|
11971
|
-
|
|
14607
|
+
const lang = detectLanguage(input3);
|
|
14608
|
+
const isJapanese = lang === "ja";
|
|
14609
|
+
return isJapanese ? `\u7533\u3057\u8A33\u3054\u3056\u3044\u307E\u305B\u3093\u3002\u300C${input3.substring(0, 50)}\u300D\u306E\u51E6\u7406\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002
|
|
14610
|
+
|
|
14611
|
+
\u5225\u306E\u65B9\u6CD5\u3067\u304A\u624B\u4F1D\u3044\u3057\u307E\u3059\uFF1A
|
|
14612
|
+
\u2022 \u8CEA\u554F\u3092\u8A00\u3044\u63DB\u3048\u3066\u304F\u3060\u3055\u3044
|
|
14613
|
+
\u2022 \u3088\u308A\u5177\u4F53\u7684\u306A\u8A73\u7D30\u3092\u63D0\u4F9B\u3057\u3066\u304F\u3060\u3055\u3044
|
|
14614
|
+
\u2022 \u8907\u96D1\u306A\u30EA\u30AF\u30A8\u30B9\u30C8\u306F\u5C0F\u3055\u304F\u5206\u5272\u3057\u3066\u304F\u3060\u3055\u3044
|
|
14615
|
+
|
|
14616
|
+
\u52B9\u679C\u7684\u306B\u30B5\u30DD\u30FC\u30C8\u3055\u305B\u3066\u3044\u305F\u3060\u304D\u307E\u3059\uFF01` : `I apologize, but I encountered an issue processing: "${input3.substring(0, 50)}"
|
|
11972
14617
|
|
|
11973
|
-
Let me
|
|
11974
|
-
\u2022 Rephrase your question
|
|
11975
|
-
\u2022 Provide more specific details
|
|
11976
|
-
\u2022 Break down complex requests
|
|
14618
|
+
Let me help you differently:
|
|
14619
|
+
\u2022 Rephrase your question
|
|
14620
|
+
\u2022 Provide more specific details
|
|
14621
|
+
\u2022 Break down complex requests
|
|
11977
14622
|
|
|
11978
14623
|
I'm here to assist you effectively!`;
|
|
11979
14624
|
}
|
|
@@ -37725,8 +40370,8 @@ var init_package = __esm({
|
|
|
37725
40370
|
"package.json"() {
|
|
37726
40371
|
package_default = {
|
|
37727
40372
|
name: "@bonginkan/maria",
|
|
37728
|
-
version: "3.1.
|
|
37729
|
-
description: "\u{
|
|
40373
|
+
version: "3.1.6",
|
|
40374
|
+
description: "\u{1F4CA} MARIA v3.1.6 - Advanced Telemetry & Analytics. Enterprise AI platform with ML-powered monitoring, predictive analytics, and real-time insights.",
|
|
37730
40375
|
keywords: [
|
|
37731
40376
|
"ai",
|
|
37732
40377
|
"cli",
|