Merge branch 'codex/feishu-remote-v2'

This commit is contained in:
7418 committed 2026-03-14 16:30:20 +08:00
commit 1420c05cd9
28 files changed
+3525 -1149

No files matched your search

+5 -1
View File
@@ -5,7 +5,11 @@ export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
/**
* GET /api/bridge — Return bridge status (pure query, no side effects)
* GET /api/bridge — Return bridge status (pure query, no side effects).
*
* Does NOT run probe — probe is an explicit action via the per-channel
* status endpoint (e.g. /api/channels/feishu/status?probe=true).
* This endpoint is polled every 5s by useBridgeStatus so it must stay cheap.
*/
export async function GET() {
try {
+16 -1
View File
@@ -14,7 +14,7 @@ import type { MCPServerConfig } from '@/types';
export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
/** Read MCP server configs from ~/.claude.json and ~/.claude/settings.json */
/** Read MCP server configs from ~/.claude.json, ~/.claude/settings.json, and project .mcp.json */
function loadMcpServers(): Record<string, MCPServerConfig> | undefined {
try {
const readJson = (p: string): Record<string, unknown> => {
@@ -23,10 +23,25 @@ function loadMcpServers(): Record<string, MCPServerConfig> | undefined {
};
const userConfig = readJson(path.join(os.homedir(), '.claude.json'));
const settings = readJson(path.join(os.homedir(), '.claude', 'settings.json'));
// Also read project-level .mcp.json
const projectMcp = readJson(path.join(process.cwd(), '.mcp.json'));
const merged = {
...((userConfig.mcpServers || {}) as Record<string, MCPServerConfig>),
...((settings.mcpServers || {}) as Record<string, MCPServerConfig>),
...((projectMcp.mcpServers || {}) as Record<string, MCPServerConfig>),
};
// Resolve ${...} placeholders in env values against DB settings
for (const server of Object.values(merged)) {
if (server.env) {
for (const [key, value] of Object.entries(server.env)) {
if (typeof value === 'string' && value.startsWith('${') && value.endsWith('}')) {
const settingKey = value.slice(2, -1);
const resolved = getSetting(settingKey);
server.env[key] = resolved || '';
}
}
}
}
return Object.keys(merged).length > 0 ? merged : undefined;
} catch {
return undefined;
+5 -3
View File
@@ -11,7 +11,9 @@ const FEISHU_KEYS = [
'bridge_feishu_app_id',
'bridge_feishu_app_secret',
'bridge_feishu_domain',
'bridge_feishu_allowed_users',
'bridge_feishu_allow_from',
'bridge_feishu_dm_policy',
'bridge_feishu_thread_session',
'bridge_feishu_group_policy',
'bridge_feishu_group_allow_from',
'bridge_feishu_require_mention',
@@ -23,7 +25,7 @@ export async function GET() {
for (const key of FEISHU_KEYS) {
const value = getSetting(key);
if (value !== undefined) {
// Mask app secret for security
// Mask sensitive fields for security
if (key === 'bridge_feishu_app_secret' && value.length > 8) {
result[key] = '***' + value.slice(-8);
} else {
@@ -52,7 +54,7 @@ export async function PUT(request: NextRequest) {
if (!FEISHU_KEYS.includes(key as typeof FEISHU_KEYS[number])) continue;
const strValue = String(value ?? '').trim();
// Don't overwrite secret if user sent the masked version back
// Don't overwrite secrets if user sent the masked version back
if (key === 'bridge_feishu_app_secret' && strValue.startsWith('***')) {
continue;
}