@hirohsu/user-web-feedback 2.8.1 → 2.8.8
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/dist/cli.cjs +393 -13
- package/dist/index.cjs +393 -13
- package/dist/static/logs.html +3 -3
- package/dist/static/settings.html +46 -11
- package/dist/static/settings.js +242 -18
- package/package.json +6 -3
package/dist/cli.cjs
CHANGED
|
@@ -3302,6 +3302,7 @@ __export(database_exports, {
|
|
|
3302
3302
|
getMCPServerById: () => getMCPServerById,
|
|
3303
3303
|
getPinnedPrompts: () => getPinnedPrompts,
|
|
3304
3304
|
getPromptById: () => getPromptById,
|
|
3305
|
+
getPromptConfigs: () => getPromptConfigs,
|
|
3305
3306
|
getRecentMCPServerErrors: () => getRecentMCPServerErrors,
|
|
3306
3307
|
getSelfProbeSettings: () => getSelfProbeSettings,
|
|
3307
3308
|
getToolEnableConfigs: () => getToolEnableConfigs,
|
|
@@ -3319,6 +3320,7 @@ __export(database_exports, {
|
|
|
3319
3320
|
queryLogs: () => queryLogs,
|
|
3320
3321
|
queryMCPServerLogs: () => queryMCPServerLogs,
|
|
3321
3322
|
reorderPrompts: () => reorderPrompts,
|
|
3323
|
+
resetPromptConfigs: () => resetPromptConfigs,
|
|
3322
3324
|
saveSelfProbeSettings: () => saveSelfProbeSettings,
|
|
3323
3325
|
setToolEnabled: () => setToolEnabled,
|
|
3324
3326
|
toggleMCPServerEnabled: () => toggleMCPServerEnabled,
|
|
@@ -3329,6 +3331,7 @@ __export(database_exports, {
|
|
|
3329
3331
|
updateCLITerminalActivity: () => updateCLITerminalActivity,
|
|
3330
3332
|
updateMCPServer: () => updateMCPServer,
|
|
3331
3333
|
updatePrompt: () => updatePrompt,
|
|
3334
|
+
updatePromptConfigs: () => updatePromptConfigs,
|
|
3332
3335
|
updateUserPreferences: () => updateUserPreferences
|
|
3333
3336
|
});
|
|
3334
3337
|
function hashPrompt(prompt) {
|
|
@@ -3626,6 +3629,21 @@ function createTables() {
|
|
|
3626
3629
|
updated_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
3627
3630
|
)
|
|
3628
3631
|
`);
|
|
3632
|
+
db.exec(`
|
|
3633
|
+
CREATE TABLE IF NOT EXISTS prompt_configs (
|
|
3634
|
+
id TEXT PRIMARY KEY,
|
|
3635
|
+
name TEXT NOT NULL,
|
|
3636
|
+
display_name TEXT NOT NULL,
|
|
3637
|
+
content TEXT,
|
|
3638
|
+
first_order INTEGER DEFAULT 0,
|
|
3639
|
+
second_order INTEGER DEFAULT 0,
|
|
3640
|
+
enabled INTEGER DEFAULT 1,
|
|
3641
|
+
editable INTEGER DEFAULT 1,
|
|
3642
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
3643
|
+
updated_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
3644
|
+
)
|
|
3645
|
+
`);
|
|
3646
|
+
initDefaultPromptConfigs();
|
|
3629
3647
|
}
|
|
3630
3648
|
function initDefaultSettings() {
|
|
3631
3649
|
if (!db) throw new Error("Database not initialized");
|
|
@@ -5020,7 +5038,104 @@ function saveSelfProbeSettings(settings) {
|
|
|
5020
5038
|
}
|
|
5021
5039
|
return getSelfProbeSettings();
|
|
5022
5040
|
}
|
|
5023
|
-
|
|
5041
|
+
function initDefaultPromptConfigs() {
|
|
5042
|
+
const db2 = tryGetDb();
|
|
5043
|
+
if (!db2) return;
|
|
5044
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5045
|
+
const existingIds = db2.prepare("SELECT id FROM prompt_configs").all().map((row) => row.id);
|
|
5046
|
+
const stmt = db2.prepare(`
|
|
5047
|
+
INSERT INTO prompt_configs (id, name, display_name, content, first_order, second_order, enabled, editable, created_at, updated_at)
|
|
5048
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5049
|
+
`);
|
|
5050
|
+
for (const config2 of DEFAULT_PROMPT_CONFIGS) {
|
|
5051
|
+
if (!existingIds.includes(config2.id)) {
|
|
5052
|
+
stmt.run(
|
|
5053
|
+
config2.id,
|
|
5054
|
+
config2.name,
|
|
5055
|
+
config2.displayName,
|
|
5056
|
+
config2.content,
|
|
5057
|
+
config2.firstOrder,
|
|
5058
|
+
config2.secondOrder,
|
|
5059
|
+
config2.enabled ? 1 : 0,
|
|
5060
|
+
config2.editable ? 1 : 0,
|
|
5061
|
+
now,
|
|
5062
|
+
now
|
|
5063
|
+
);
|
|
5064
|
+
logger.info(`Added missing prompt config: ${config2.id}`);
|
|
5065
|
+
}
|
|
5066
|
+
}
|
|
5067
|
+
}
|
|
5068
|
+
function getPromptConfigs() {
|
|
5069
|
+
const db2 = tryGetDb();
|
|
5070
|
+
if (!db2) return [];
|
|
5071
|
+
const rows = db2.prepare(`
|
|
5072
|
+
SELECT id, name, display_name as displayName, content,
|
|
5073
|
+
first_order as firstOrder, second_order as secondOrder,
|
|
5074
|
+
enabled, editable, created_at as createdAt, updated_at as updatedAt
|
|
5075
|
+
FROM prompt_configs
|
|
5076
|
+
ORDER BY first_order ASC
|
|
5077
|
+
`).all();
|
|
5078
|
+
const aiSettings = getAISettings();
|
|
5079
|
+
return rows.map((row) => {
|
|
5080
|
+
let content = row.content;
|
|
5081
|
+
if (row.id === "system_prompt" && !content && aiSettings.systemPrompt) {
|
|
5082
|
+
content = aiSettings.systemPrompt;
|
|
5083
|
+
} else if (row.id === "mcp_tools" && !content && aiSettings.mcpToolsPrompt) {
|
|
5084
|
+
content = aiSettings.mcpToolsPrompt;
|
|
5085
|
+
}
|
|
5086
|
+
return {
|
|
5087
|
+
...row,
|
|
5088
|
+
content,
|
|
5089
|
+
enabled: row.enabled === 1,
|
|
5090
|
+
editable: row.editable === 1
|
|
5091
|
+
};
|
|
5092
|
+
});
|
|
5093
|
+
}
|
|
5094
|
+
function updatePromptConfigs(request) {
|
|
5095
|
+
const db2 = tryGetDb();
|
|
5096
|
+
if (!db2) return false;
|
|
5097
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5098
|
+
for (const prompt of request.prompts) {
|
|
5099
|
+
const updates = [];
|
|
5100
|
+
const values = [];
|
|
5101
|
+
if (prompt.firstOrder !== void 0) {
|
|
5102
|
+
updates.push("first_order = ?");
|
|
5103
|
+
values.push(prompt.firstOrder);
|
|
5104
|
+
}
|
|
5105
|
+
if (prompt.secondOrder !== void 0) {
|
|
5106
|
+
updates.push("second_order = ?");
|
|
5107
|
+
values.push(prompt.secondOrder);
|
|
5108
|
+
}
|
|
5109
|
+
if (prompt.enabled !== void 0) {
|
|
5110
|
+
updates.push("enabled = ?");
|
|
5111
|
+
values.push(prompt.enabled ? 1 : 0);
|
|
5112
|
+
}
|
|
5113
|
+
if (prompt.content !== void 0) {
|
|
5114
|
+
updates.push("content = ?");
|
|
5115
|
+
values.push(prompt.content);
|
|
5116
|
+
if (prompt.id === "system_prompt") {
|
|
5117
|
+
db2.prepare("UPDATE ai_settings SET system_prompt = ?, updated_at = ? WHERE id = 1").run(prompt.content || "", now);
|
|
5118
|
+
} else if (prompt.id === "mcp_tools") {
|
|
5119
|
+
db2.prepare("UPDATE ai_settings SET mcp_tools_prompt = ?, updated_at = ? WHERE id = 1").run(prompt.content || "", now);
|
|
5120
|
+
}
|
|
5121
|
+
}
|
|
5122
|
+
if (updates.length > 0) {
|
|
5123
|
+
updates.push("updated_at = ?");
|
|
5124
|
+
values.push(now);
|
|
5125
|
+
values.push(prompt.id);
|
|
5126
|
+
db2.prepare(`UPDATE prompt_configs SET ${updates.join(", ")} WHERE id = ?`).run(...values);
|
|
5127
|
+
}
|
|
5128
|
+
}
|
|
5129
|
+
return true;
|
|
5130
|
+
}
|
|
5131
|
+
function resetPromptConfigs() {
|
|
5132
|
+
const db2 = tryGetDb();
|
|
5133
|
+
if (!db2) return [];
|
|
5134
|
+
db2.prepare("DELETE FROM prompt_configs").run();
|
|
5135
|
+
initDefaultPromptConfigs();
|
|
5136
|
+
return getPromptConfigs();
|
|
5137
|
+
}
|
|
5138
|
+
var import_better_sqlite3, import_path2, import_fs2, import_crypto2, DB_DIR, DB_PATH, db, SYSTEM_PROMPT_VERSIONS, CURRENT_PROMPT_VERSION, DEFAULT_PROMPT_CONFIGS;
|
|
5024
5139
|
var init_database = __esm({
|
|
5025
5140
|
"src/utils/database.ts"() {
|
|
5026
5141
|
"use strict";
|
|
@@ -5067,6 +5182,14 @@ var init_database = __esm({
|
|
|
5067
5182
|
\u4FDD\u6301\u56DE\u61C9\u7C21\u77ED\uFF082-3\u53E5\u8A71\uFF09\uFF0C\u9664\u975E\u9700\u8981\u66F4\u8A73\u7D30\u7684\u8AAA\u660E\u3002`
|
|
5068
5183
|
};
|
|
5069
5184
|
CURRENT_PROMPT_VERSION = "v2";
|
|
5185
|
+
DEFAULT_PROMPT_CONFIGS = [
|
|
5186
|
+
{ id: "system_prompt", name: "System Prompt", displayName: "\u7CFB\u7D71\u63D0\u793A\u8A5E", content: null, firstOrder: 10, secondOrder: 10, enabled: true, editable: true },
|
|
5187
|
+
{ id: "mcp_tools", name: "MCP Tools", displayName: "MCP \u5DE5\u5177\u8AAA\u660E", content: null, firstOrder: 20, secondOrder: 0, enabled: true, editable: true },
|
|
5188
|
+
{ id: "mcp_tools_detailed", name: "MCP Tools Detailed", displayName: "MCP \u5DE5\u5177\u8A73\u7D30\u5217\u8868", content: null, firstOrder: 25, secondOrder: 15, enabled: true, editable: false },
|
|
5189
|
+
{ id: "user_context", name: "User Context", displayName: "\u7528\u6236\u4E0A\u4E0B\u6587", content: null, firstOrder: 30, secondOrder: 20, enabled: true, editable: false },
|
|
5190
|
+
{ id: "tool_results", name: "Tool Results", displayName: "\u5DE5\u5177\u57F7\u884C\u7D50\u679C", content: null, firstOrder: 0, secondOrder: 30, enabled: true, editable: false },
|
|
5191
|
+
{ id: "closing", name: "Closing", displayName: "\u7D50\u5C3E\u63D0\u793A", content: null, firstOrder: 100, secondOrder: 100, enabled: true, editable: true }
|
|
5192
|
+
];
|
|
5070
5193
|
}
|
|
5071
5194
|
});
|
|
5072
5195
|
|
|
@@ -5160,6 +5283,9 @@ var init_logger = __esm({
|
|
|
5160
5283
|
this.flushInterval = setInterval(() => {
|
|
5161
5284
|
this.flushToDatabase();
|
|
5162
5285
|
}, this.FLUSH_INTERVAL_MS);
|
|
5286
|
+
if (this.flushInterval.unref) {
|
|
5287
|
+
this.flushInterval.unref();
|
|
5288
|
+
}
|
|
5163
5289
|
process.on("beforeExit", () => {
|
|
5164
5290
|
this.flushToDatabase();
|
|
5165
5291
|
});
|
|
@@ -77793,6 +77919,107 @@ ${mcpPrompt}`;
|
|
|
77793
77919
|
}
|
|
77794
77920
|
});
|
|
77795
77921
|
|
|
77922
|
+
// src/utils/prompt-aggregator/components/mcp-tools-detailed.ts
|
|
77923
|
+
var MCPToolsDetailedComponent;
|
|
77924
|
+
var init_mcp_tools_detailed = __esm({
|
|
77925
|
+
"src/utils/prompt-aggregator/components/mcp-tools-detailed.ts"() {
|
|
77926
|
+
"use strict";
|
|
77927
|
+
init_cjs_shims();
|
|
77928
|
+
init_base_component();
|
|
77929
|
+
init_mcp_client_manager();
|
|
77930
|
+
MCPToolsDetailedComponent = class extends BasePromptComponent {
|
|
77931
|
+
constructor() {
|
|
77932
|
+
super("MCPToolsDetailed", 25);
|
|
77933
|
+
}
|
|
77934
|
+
build(context) {
|
|
77935
|
+
const { request } = context;
|
|
77936
|
+
if (!request.includeMCPTools) {
|
|
77937
|
+
return null;
|
|
77938
|
+
}
|
|
77939
|
+
try {
|
|
77940
|
+
const allTools = mcpClientManager.getAllTools();
|
|
77941
|
+
if (!allTools || allTools.length === 0) {
|
|
77942
|
+
return null;
|
|
77943
|
+
}
|
|
77944
|
+
let result = "## MCP \u5DE5\u5177\u8A73\u7D30\u4F7F\u7528\u8AAA\u660E\n\n";
|
|
77945
|
+
result += "\u4EE5\u4E0B\u662F\u6240\u6709\u53EF\u7528\u7684 MCP \u5DE5\u5177\u53CA\u5176\u8A73\u7D30\u4F7F\u7528\u65B9\u5F0F\uFF1A\n\n";
|
|
77946
|
+
for (const tool of allTools) {
|
|
77947
|
+
result += `### ${tool.name}
|
|
77948
|
+
|
|
77949
|
+
`;
|
|
77950
|
+
if (tool.description) {
|
|
77951
|
+
result += `**\u8AAA\u660E**: ${tool.description}
|
|
77952
|
+
|
|
77953
|
+
`;
|
|
77954
|
+
}
|
|
77955
|
+
if (tool.inputSchema) {
|
|
77956
|
+
result += "**\u53C3\u6578\u683C\u5F0F**:\n```json\n";
|
|
77957
|
+
result += JSON.stringify(tool.inputSchema, null, 2);
|
|
77958
|
+
result += "\n```\n\n";
|
|
77959
|
+
const schema = tool.inputSchema;
|
|
77960
|
+
if (schema.properties && typeof schema.properties === "object") {
|
|
77961
|
+
result += "**\u53C3\u6578\u8AAA\u660E**:\n";
|
|
77962
|
+
const props = schema.properties;
|
|
77963
|
+
const required2 = schema.required || [];
|
|
77964
|
+
for (const [propName, propDef] of Object.entries(props)) {
|
|
77965
|
+
const isRequired = required2.includes(propName);
|
|
77966
|
+
result += `- \`${propName}\``;
|
|
77967
|
+
if (propDef.type) result += ` (${propDef.type})`;
|
|
77968
|
+
if (isRequired) result += " **\u5FC5\u586B**";
|
|
77969
|
+
if (propDef.description) result += `: ${propDef.description}`;
|
|
77970
|
+
result += "\n";
|
|
77971
|
+
}
|
|
77972
|
+
result += "\n";
|
|
77973
|
+
}
|
|
77974
|
+
}
|
|
77975
|
+
result += "**\u8ABF\u7528\u7BC4\u4F8B**:\n```json\n";
|
|
77976
|
+
result += JSON.stringify({
|
|
77977
|
+
tool_calls: [{
|
|
77978
|
+
name: tool.name,
|
|
77979
|
+
arguments: this.generateExampleArgs(tool.inputSchema)
|
|
77980
|
+
}]
|
|
77981
|
+
}, null, 2);
|
|
77982
|
+
result += "\n```\n\n---\n\n";
|
|
77983
|
+
}
|
|
77984
|
+
return result;
|
|
77985
|
+
} catch {
|
|
77986
|
+
return null;
|
|
77987
|
+
}
|
|
77988
|
+
}
|
|
77989
|
+
generateExampleArgs(schema) {
|
|
77990
|
+
if (!schema || !schema.properties) {
|
|
77991
|
+
return {};
|
|
77992
|
+
}
|
|
77993
|
+
const result = {};
|
|
77994
|
+
const props = schema.properties;
|
|
77995
|
+
for (const [propName, propDef] of Object.entries(props)) {
|
|
77996
|
+
switch (propDef.type) {
|
|
77997
|
+
case "string":
|
|
77998
|
+
result[propName] = "<\u5B57\u4E32\u503C>";
|
|
77999
|
+
break;
|
|
78000
|
+
case "number":
|
|
78001
|
+
case "integer":
|
|
78002
|
+
result[propName] = 0;
|
|
78003
|
+
break;
|
|
78004
|
+
case "boolean":
|
|
78005
|
+
result[propName] = true;
|
|
78006
|
+
break;
|
|
78007
|
+
case "array":
|
|
78008
|
+
result[propName] = [];
|
|
78009
|
+
break;
|
|
78010
|
+
case "object":
|
|
78011
|
+
result[propName] = {};
|
|
78012
|
+
break;
|
|
78013
|
+
default:
|
|
78014
|
+
result[propName] = "<\u503C>";
|
|
78015
|
+
}
|
|
78016
|
+
}
|
|
78017
|
+
return result;
|
|
78018
|
+
}
|
|
78019
|
+
};
|
|
78020
|
+
}
|
|
78021
|
+
});
|
|
78022
|
+
|
|
77796
78023
|
// src/utils/prompt-aggregator/components/user-context.ts
|
|
77797
78024
|
var UserContextComponent;
|
|
77798
78025
|
var init_user_context = __esm({
|
|
@@ -77905,6 +78132,7 @@ var init_components = __esm({
|
|
|
77905
78132
|
init_system_prompt();
|
|
77906
78133
|
init_pinned_prompts();
|
|
77907
78134
|
init_mcp_tools();
|
|
78135
|
+
init_mcp_tools_detailed();
|
|
77908
78136
|
init_user_context();
|
|
77909
78137
|
init_tool_results();
|
|
77910
78138
|
init_ai_message();
|
|
@@ -77916,7 +78144,7 @@ var init_components = __esm({
|
|
|
77916
78144
|
function getPromptAggregator() {
|
|
77917
78145
|
return PromptAggregator.getInstance();
|
|
77918
78146
|
}
|
|
77919
|
-
var PromptAggregator;
|
|
78147
|
+
var COMPONENT_NAME_MAP, PromptAggregator;
|
|
77920
78148
|
var init_prompt_aggregator = __esm({
|
|
77921
78149
|
"src/utils/prompt-aggregator/prompt-aggregator.ts"() {
|
|
77922
78150
|
"use strict";
|
|
@@ -77925,6 +78153,14 @@ var init_prompt_aggregator = __esm({
|
|
|
77925
78153
|
init_database();
|
|
77926
78154
|
init_mcp_client_manager();
|
|
77927
78155
|
init_logger();
|
|
78156
|
+
COMPONENT_NAME_MAP = {
|
|
78157
|
+
"system_prompt": "SystemPrompt",
|
|
78158
|
+
"mcp_tools": "MCPToolsPrompt",
|
|
78159
|
+
"mcp_tools_detailed": "MCPToolsDetailed",
|
|
78160
|
+
"user_context": "UserContext",
|
|
78161
|
+
"tool_results": "ToolResults",
|
|
78162
|
+
"closing": "ClosingPrompt"
|
|
78163
|
+
};
|
|
77928
78164
|
PromptAggregator = class _PromptAggregator {
|
|
77929
78165
|
static instance;
|
|
77930
78166
|
components = [];
|
|
@@ -77943,6 +78179,7 @@ var init_prompt_aggregator = __esm({
|
|
|
77943
78179
|
this.register(new SystemPromptComponent());
|
|
77944
78180
|
this.register(new PinnedPromptsComponent());
|
|
77945
78181
|
this.register(new MCPToolsPromptComponent());
|
|
78182
|
+
this.register(new MCPToolsDetailedComponent());
|
|
77946
78183
|
this.register(new UserContextComponent());
|
|
77947
78184
|
this.register(new ToolResultsComponent());
|
|
77948
78185
|
this.register(new AIMessageComponent());
|
|
@@ -77958,14 +78195,21 @@ var init_prompt_aggregator = __esm({
|
|
|
77958
78195
|
aggregate(context) {
|
|
77959
78196
|
const sections = [];
|
|
77960
78197
|
const promptParts = [];
|
|
77961
|
-
|
|
78198
|
+
const configs = this.getPromptConfigsWithDefaults();
|
|
78199
|
+
const isFirstCall = context.isFirstCall !== false;
|
|
78200
|
+
const configuredComponents = this.components.map((component) => {
|
|
78201
|
+
const configId = Object.entries(COMPONENT_NAME_MAP).find(
|
|
78202
|
+
([, name]) => name === component.getName()
|
|
78203
|
+
)?.[0];
|
|
78204
|
+
const config2 = configId ? configs.find((c) => c.id === configId) : null;
|
|
78205
|
+
const order = config2 ? isFirstCall ? config2.firstOrder : config2.secondOrder : component.getOrder();
|
|
78206
|
+
const enabled = config2 ? config2.enabled : true;
|
|
78207
|
+
return { component, order, enabled };
|
|
78208
|
+
}).filter((item) => item.enabled && item.order > 0).sort((a, b) => a.order - b.order);
|
|
78209
|
+
for (const { component, order } of configuredComponents) {
|
|
77962
78210
|
const content = component.build(context);
|
|
77963
78211
|
if (content) {
|
|
77964
|
-
sections.push({
|
|
77965
|
-
name: component.getName(),
|
|
77966
|
-
content,
|
|
77967
|
-
order: component.getOrder()
|
|
77968
|
-
});
|
|
78212
|
+
sections.push({ name: component.getName(), content, order });
|
|
77969
78213
|
promptParts.push(content);
|
|
77970
78214
|
}
|
|
77971
78215
|
}
|
|
@@ -78056,6 +78300,21 @@ var init_prompt_aggregator = __esm({
|
|
|
78056
78300
|
getComponentNames() {
|
|
78057
78301
|
return this.components.map((c) => c.getName());
|
|
78058
78302
|
}
|
|
78303
|
+
getPromptConfigsWithDefaults() {
|
|
78304
|
+
try {
|
|
78305
|
+
const configs = getPromptConfigs();
|
|
78306
|
+
if (configs.length > 0) return configs;
|
|
78307
|
+
} catch {
|
|
78308
|
+
logger.warn("[PromptAggregator] \u7121\u6CD5\u5F9E\u8CC7\u6599\u5EAB\u7372\u53D6\u63D0\u793A\u8A5E\u914D\u7F6E\uFF0C\u4F7F\u7528\u9810\u8A2D\u503C");
|
|
78309
|
+
}
|
|
78310
|
+
return [
|
|
78311
|
+
{ id: "system_prompt", name: "System Prompt", displayName: "\u7CFB\u7D71\u63D0\u793A\u8A5E", content: null, firstOrder: 10, secondOrder: 10, enabled: true, editable: false, createdAt: "", updatedAt: "" },
|
|
78312
|
+
{ id: "mcp_tools", name: "MCP Tools", displayName: "MCP \u5DE5\u5177\u8AAA\u660E", content: null, firstOrder: 20, secondOrder: 0, enabled: true, editable: true, createdAt: "", updatedAt: "" },
|
|
78313
|
+
{ id: "user_context", name: "User Context", displayName: "\u7528\u6236\u4E0A\u4E0B\u6587", content: null, firstOrder: 30, secondOrder: 20, enabled: true, editable: true, createdAt: "", updatedAt: "" },
|
|
78314
|
+
{ id: "tool_results", name: "Tool Results", displayName: "\u5DE5\u5177\u57F7\u884C\u7D50\u679C", content: null, firstOrder: 0, secondOrder: 30, enabled: true, editable: false, createdAt: "", updatedAt: "" },
|
|
78315
|
+
{ id: "closing", name: "Closing", displayName: "\u7D50\u5C3E\u63D0\u793A", content: null, firstOrder: 40, secondOrder: 40, enabled: true, editable: true, createdAt: "", updatedAt: "" }
|
|
78316
|
+
];
|
|
78317
|
+
}
|
|
78059
78318
|
};
|
|
78060
78319
|
}
|
|
78061
78320
|
});
|
|
@@ -78788,8 +79047,25 @@ function cleanExpiredCache() {
|
|
|
78788
79047
|
function clearAICache() {
|
|
78789
79048
|
cache.clear();
|
|
78790
79049
|
}
|
|
78791
|
-
async function validateAPIKey(apiKey, model) {
|
|
79050
|
+
async function validateAPIKey(apiKey, model, apiUrl, openaiCompatible) {
|
|
78792
79051
|
try {
|
|
79052
|
+
const provider = getProviderFromUrl(apiUrl);
|
|
79053
|
+
if (openaiCompatible || provider === "openai" || provider === "nvidia" || provider === "zai") {
|
|
79054
|
+
const OpenAI = (await import("openai")).default;
|
|
79055
|
+
const client = new OpenAI({
|
|
79056
|
+
apiKey,
|
|
79057
|
+
baseURL: apiUrl || "https://api.openai.com/v1"
|
|
79058
|
+
});
|
|
79059
|
+
const response2 = await client.chat.completions.create({
|
|
79060
|
+
model,
|
|
79061
|
+
messages: [{ role: "user", content: "Hello" }],
|
|
79062
|
+
max_tokens: 10
|
|
79063
|
+
});
|
|
79064
|
+
if (response2.choices && response2.choices.length > 0) {
|
|
79065
|
+
return { valid: true };
|
|
79066
|
+
}
|
|
79067
|
+
return { valid: false, error: "\u7121\u6CD5\u751F\u6210\u56DE\u61C9" };
|
|
79068
|
+
}
|
|
78793
79069
|
const genAI = new GoogleGenerativeAI(apiKey);
|
|
78794
79070
|
const generativeModel = genAI.getGenerativeModel({ model });
|
|
78795
79071
|
const result = await generativeModel.generateContent("Hello");
|
|
@@ -78806,6 +79082,16 @@ async function validateAPIKey(apiKey, model) {
|
|
|
78806
79082
|
};
|
|
78807
79083
|
}
|
|
78808
79084
|
}
|
|
79085
|
+
function getProviderFromUrl(apiUrl) {
|
|
79086
|
+
if (!apiUrl) return "google";
|
|
79087
|
+
const normalizedUrl = apiUrl.toLowerCase();
|
|
79088
|
+
if (normalizedUrl.includes("api.openai.com")) return "openai";
|
|
79089
|
+
if (normalizedUrl.includes("api.anthropic.com")) return "anthropic";
|
|
79090
|
+
if (normalizedUrl.includes("generativelanguage.googleapis.com")) return "google";
|
|
79091
|
+
if (normalizedUrl.includes("nvidia.com")) return "nvidia";
|
|
79092
|
+
if (normalizedUrl.includes("bigmodel.cn") || normalizedUrl.includes("z.ai")) return "zai";
|
|
79093
|
+
return "openai";
|
|
79094
|
+
}
|
|
78809
79095
|
function estimateTokenCount(text) {
|
|
78810
79096
|
const englishChars = (text.match(/[a-zA-Z0-9]/g) || []).length;
|
|
78811
79097
|
const chineseChars = (text.match(/[\u4e00-\u9fa5]/g) || []).length;
|
|
@@ -93380,7 +93666,7 @@ var WebServer = class {
|
|
|
93380
93666
|
this.app.post("/api/ai-settings/validate", async (req, res) => {
|
|
93381
93667
|
const startTime = Date.now();
|
|
93382
93668
|
try {
|
|
93383
|
-
let { apiKey } = req.body;
|
|
93669
|
+
let { apiKey, apiUrl, openaiCompatible } = req.body;
|
|
93384
93670
|
const { model } = req.body;
|
|
93385
93671
|
if (!model) {
|
|
93386
93672
|
const errorMsg = "\u6A21\u578B\u70BA\u5FC5\u586B\u6B04\u4F4D";
|
|
@@ -93400,6 +93686,7 @@ var WebServer = class {
|
|
|
93400
93686
|
return;
|
|
93401
93687
|
}
|
|
93402
93688
|
let usingDatabaseKey = false;
|
|
93689
|
+
let usingDatabaseUrl = false;
|
|
93403
93690
|
if (!apiKey) {
|
|
93404
93691
|
const settings = getAISettings();
|
|
93405
93692
|
if (!settings || !settings.apiKey || settings.apiKey === "YOUR_API_KEY_HERE") {
|
|
@@ -93422,13 +93709,18 @@ var WebServer = class {
|
|
|
93422
93709
|
}
|
|
93423
93710
|
apiKey = settings.apiKey;
|
|
93424
93711
|
usingDatabaseKey = true;
|
|
93712
|
+
if (!apiUrl) {
|
|
93713
|
+
apiUrl = settings.apiUrl;
|
|
93714
|
+
usingDatabaseUrl = true;
|
|
93715
|
+
}
|
|
93425
93716
|
logger.info("\u4F7F\u7528\u8CC7\u6599\u5EAB\u4E2D\u89E3\u5BC6\u7684 API Key \u9032\u884C\u9A57\u8B49");
|
|
93426
93717
|
logger.debug(`\u89E3\u5BC6\u5F8C\u7684 API Key \u9577\u5EA6: ${apiKey.length}, \u524D\u7DB4: ${apiKey.substring(0, 3)}...`);
|
|
93427
93718
|
} else {
|
|
93428
93719
|
logger.info("\u4F7F\u7528\u65B0\u8F38\u5165\u7684 API Key \u9032\u884C\u9A57\u8B49");
|
|
93429
93720
|
logger.debug(`\u65B0\u8F38\u5165\u7684 API Key \u9577\u5EA6: ${apiKey.length}, \u524D\u7DB4: ${apiKey.substring(0, 3)}...`);
|
|
93430
93721
|
}
|
|
93431
|
-
|
|
93722
|
+
logger.info(`\u9A57\u8B49\u4F7F\u7528 API URL: ${apiUrl} (\u8CC7\u6599\u5EAB: ${usingDatabaseUrl}), OpenAI \u76F8\u5BB9: ${openaiCompatible}`);
|
|
93723
|
+
const result = await validateAPIKey(apiKey, model, apiUrl, openaiCompatible);
|
|
93432
93724
|
if (result.valid) {
|
|
93433
93725
|
logger.info(`API Key \u9A57\u8B49\u6210\u529F (${usingDatabaseKey ? "\u8CC7\u6599\u5EAB" : "\u65B0\u8F38\u5165"})`);
|
|
93434
93726
|
logAPIRequest({
|
|
@@ -93591,6 +93883,68 @@ var WebServer = class {
|
|
|
93591
93883
|
});
|
|
93592
93884
|
}
|
|
93593
93885
|
});
|
|
93886
|
+
this.app.get("/api/settings/prompts", (req, res) => {
|
|
93887
|
+
try {
|
|
93888
|
+
const prompts = getPromptConfigs();
|
|
93889
|
+
res.json({ success: true, prompts });
|
|
93890
|
+
} catch (error2) {
|
|
93891
|
+
logger.error("\u7372\u53D6\u63D0\u793A\u8A5E\u914D\u7F6E\u5931\u6557:", error2);
|
|
93892
|
+
res.status(500).json({
|
|
93893
|
+
success: false,
|
|
93894
|
+
error: error2 instanceof Error ? error2.message : "\u7372\u53D6\u63D0\u793A\u8A5E\u914D\u7F6E\u5931\u6557"
|
|
93895
|
+
});
|
|
93896
|
+
}
|
|
93897
|
+
});
|
|
93898
|
+
this.app.put("/api/settings/prompts", (req, res) => {
|
|
93899
|
+
try {
|
|
93900
|
+
const { prompts } = req.body;
|
|
93901
|
+
if (!prompts || !Array.isArray(prompts)) {
|
|
93902
|
+
res.status(400).json({ success: false, error: "prompts \u5FC5\u9808\u662F\u9663\u5217" });
|
|
93903
|
+
return;
|
|
93904
|
+
}
|
|
93905
|
+
for (const prompt of prompts) {
|
|
93906
|
+
if (!prompt.id) {
|
|
93907
|
+
res.status(400).json({ success: false, error: "\u6BCF\u500B\u914D\u7F6E\u5FC5\u9808\u5305\u542B id" });
|
|
93908
|
+
return;
|
|
93909
|
+
}
|
|
93910
|
+
if (prompt.firstOrder !== void 0 && (prompt.firstOrder < 0 || prompt.firstOrder > 1e3)) {
|
|
93911
|
+
res.status(400).json({ success: false, error: "firstOrder \u5FC5\u9808\u5728 0-1000 \u4E4B\u9593" });
|
|
93912
|
+
return;
|
|
93913
|
+
}
|
|
93914
|
+
if (prompt.secondOrder !== void 0 && (prompt.secondOrder < 0 || prompt.secondOrder > 1e3)) {
|
|
93915
|
+
res.status(400).json({ success: false, error: "secondOrder \u5FC5\u9808\u5728 0-1000 \u4E4B\u9593" });
|
|
93916
|
+
return;
|
|
93917
|
+
}
|
|
93918
|
+
}
|
|
93919
|
+
const success = updatePromptConfigs({ prompts });
|
|
93920
|
+
if (success) {
|
|
93921
|
+
const updatedPrompts = getPromptConfigs();
|
|
93922
|
+
logger.info(`\u63D0\u793A\u8A5E\u914D\u7F6E\u5DF2\u66F4\u65B0: ${prompts.length} \u9805`);
|
|
93923
|
+
res.json({ success: true, prompts: updatedPrompts });
|
|
93924
|
+
} else {
|
|
93925
|
+
res.status(500).json({ success: false, error: "\u66F4\u65B0\u5931\u6557" });
|
|
93926
|
+
}
|
|
93927
|
+
} catch (error2) {
|
|
93928
|
+
logger.error("\u66F4\u65B0\u63D0\u793A\u8A5E\u914D\u7F6E\u5931\u6557:", error2);
|
|
93929
|
+
res.status(500).json({
|
|
93930
|
+
success: false,
|
|
93931
|
+
error: error2 instanceof Error ? error2.message : "\u66F4\u65B0\u63D0\u793A\u8A5E\u914D\u7F6E\u5931\u6557"
|
|
93932
|
+
});
|
|
93933
|
+
}
|
|
93934
|
+
});
|
|
93935
|
+
this.app.post("/api/settings/prompts/reset", (req, res) => {
|
|
93936
|
+
try {
|
|
93937
|
+
const prompts = resetPromptConfigs();
|
|
93938
|
+
logger.info("\u63D0\u793A\u8A5E\u914D\u7F6E\u5DF2\u91CD\u7F6E\u70BA\u9810\u8A2D\u503C");
|
|
93939
|
+
res.json({ success: true, prompts });
|
|
93940
|
+
} catch (error2) {
|
|
93941
|
+
logger.error("\u91CD\u7F6E\u63D0\u793A\u8A5E\u914D\u7F6E\u5931\u6557:", error2);
|
|
93942
|
+
res.status(500).json({
|
|
93943
|
+
success: false,
|
|
93944
|
+
error: error2 instanceof Error ? error2.message : "\u91CD\u7F6E\u63D0\u793A\u8A5E\u914D\u7F6E\u5931\u6557"
|
|
93945
|
+
});
|
|
93946
|
+
}
|
|
93947
|
+
});
|
|
93594
93948
|
this.app.get("/api/logs", (req, res) => {
|
|
93595
93949
|
try {
|
|
93596
93950
|
const options = {};
|
|
@@ -95254,9 +95608,35 @@ var MCPServer = class {
|
|
|
95254
95608
|
this.mcpServer.registerTool(
|
|
95255
95609
|
"collect_feedback",
|
|
95256
95610
|
{
|
|
95257
|
-
description:
|
|
95611
|
+
description: `Collect feedback from users about AI work. This tool opens a web interface for users to provide feedback.
|
|
95612
|
+
|
|
95613
|
+
CRITICAL: The 'work_summary' field is the PRIMARY and ONLY content displayed to users in the feedback UI. You MUST include ALL relevant information in this field as a comprehensive Markdown-formatted report. The UI renders Markdown, so use headings, tables, code blocks, and lists for better readability.`,
|
|
95258
95614
|
inputSchema: {
|
|
95259
|
-
work_summary: external_exports.string().describe(
|
|
95615
|
+
work_summary: external_exports.string().describe(`\u3010CRITICAL - THIS IS THE ONLY CONTENT SHOWN TO USERS\u3011
|
|
95616
|
+
|
|
95617
|
+
Include a COMPLETE Markdown report with ALL of the following sections:
|
|
95618
|
+
|
|
95619
|
+
## Required Sections:
|
|
95620
|
+
1. **\u{1F4CB} Task Summary** - Brief description of what was requested and accomplished
|
|
95621
|
+
2. **\u{1F4C1} Implementation Details** - Files created/modified with:
|
|
95622
|
+
- Full file paths
|
|
95623
|
+
- Key code snippets in fenced code blocks
|
|
95624
|
+
- Explanation of changes
|
|
95625
|
+
3. **\u2705 Status Table** - Markdown table showing completion status:
|
|
95626
|
+
| Item | Status | Notes |
|
|
95627
|
+
|------|--------|-------|
|
|
95628
|
+
| Feature A | \u2705 Done | ... |
|
|
95629
|
+
4. **\u{1F9EA} Test Results** - Build/test command outputs and outcomes
|
|
95630
|
+
5. **\u27A1\uFE0F Next Steps** - Actionable options in A/B/C format for user decision:
|
|
95631
|
+
- Option A: [action] - [description]
|
|
95632
|
+
- Option B: [action] - [description]
|
|
95633
|
+
6. **\u{1F3D7}\uFE0F Architecture** (if applicable) - ASCII diagrams or Mermaid code blocks
|
|
95634
|
+
|
|
95635
|
+
## Format Requirements:
|
|
95636
|
+
- Use Markdown: ## headings, \`code\`, **bold**, tables
|
|
95637
|
+
- Minimum 500 characters for non-trivial tasks
|
|
95638
|
+
- Be specific with file paths and code examples
|
|
95639
|
+
- Include ALL information user needs to make decisions`),
|
|
95260
95640
|
project_name: external_exports.string().optional().describe("\u5C08\u6848\u540D\u7A31\uFF08\u7528\u65BC Dashboard \u5206\u7D44\u986F\u793A\uFF09"),
|
|
95261
95641
|
project_path: external_exports.string().optional().describe("\u5C08\u6848\u8DEF\u5F91\uFF08\u7528\u65BC\u552F\u4E00\u8B58\u5225\u5C08\u6848\uFF09")
|
|
95262
95642
|
}
|