fix: auto-fix code issues (cron)
- 修复重复导入/字段 (llm_client.py 中的重复注释) - 修复PEP8格式问题 (E501行长度超过100字符) - 修复多行SQL语句和字符串格式化 - 修复f-string过长问题 涉及文件: - backend/developer_ecosystem_manager.py - backend/document_processor.py - backend/enterprise_manager.py - backend/export_manager.py - backend/growth_manager.py - backend/llm_client.py - backend/localization_manager.py - backend/main.py - backend/neo4j_manager.py - backend/ops_manager.py - backend/performance_manager.py - backend/plugin_manager.py - backend/search_manager.py - backend/security_manager.py - backend/subscription_manager.py - backend/tenant_manager.py - backend/test_phase8_task6.py - backend/test_phase8_task8.py - backend/tingwu_client.py - backend/workflow_manager.py
This commit is contained in:
@@ -661,8 +661,10 @@ class DeveloperEcosystemManager:
|
|||||||
(id, name, description, category, subcategory, tags, author_id, author_name,
|
(id, name, description, category, subcategory, tags, author_id, author_name,
|
||||||
status, price, currency, preview_image_url, demo_url, documentation_url,
|
status, price, currency, preview_image_url, demo_url, documentation_url,
|
||||||
download_url, install_count, rating, rating_count, review_count, version,
|
download_url, install_count, rating, rating_count, review_count, version,
|
||||||
min_platform_version, file_size, checksum, created_at, updated_at, published_at)
|
min_platform_version, file_size, checksum, created_at, updated_at,
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
published_at)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
||||||
|
?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
template.id,
|
template.id,
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ class DocumentProcessor:
|
|||||||
return "\n\n".join(text_parts)
|
return "\n\n".join(text_parts)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError(
|
raise ImportError(
|
||||||
"PDF processing requires PyPDF2 or pdfplumber. Install with: pip install PyPDF2",
|
"PDF processing requires PyPDF2 or pdfplumber. "
|
||||||
|
"Install with: pip install PyPDF2",
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError(f"PDF extraction failed: {e!s}")
|
raise ValueError(f"PDF extraction failed: {e!s}")
|
||||||
|
|||||||
@@ -407,7 +407,8 @@ class EnterpriseManager:
|
|||||||
processed INTEGER DEFAULT 0,
|
processed INTEGER DEFAULT 0,
|
||||||
processed_at TIMESTAMP,
|
processed_at TIMESTAMP,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (request_id) REFERENCES saml_auth_requests(request_id) ON DELETE CASCADE,
|
FOREIGN KEY (request_id) REFERENCES saml_auth_requests(request_id)
|
||||||
|
ON DELETE CASCADE,
|
||||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
@@ -522,7 +523,8 @@ class EnterpriseManager:
|
|||||||
error_count INTEGER DEFAULT 0,
|
error_count INTEGER DEFAULT 0,
|
||||||
details TEXT DEFAULT '{}',
|
details TEXT DEFAULT '{}',
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (policy_id) REFERENCES data_retention_policies(id) ON DELETE CASCADE,
|
FOREIGN KEY (policy_id) REFERENCES data_retention_policies(id)
|
||||||
|
ON DELETE CASCADE,
|
||||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
@@ -531,40 +533,51 @@ class EnterpriseManager:
|
|||||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_sso_tenant ON sso_configs(tenant_id)")
|
cursor.execute("CREATE INDEX IF NOT EXISTS idx_sso_tenant ON sso_configs(tenant_id)")
|
||||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_sso_provider ON sso_configs(provider)")
|
cursor.execute("CREATE INDEX IF NOT EXISTS idx_sso_provider ON sso_configs(provider)")
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_saml_requests_config ON saml_auth_requests(sso_config_id)",
|
"CREATE INDEX IF NOT EXISTS idx_saml_requests_config "
|
||||||
|
"ON saml_auth_requests(sso_config_id)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_saml_requests_expires ON saml_auth_requests(expires_at)",
|
"CREATE INDEX IF NOT EXISTS idx_saml_requests_expires "
|
||||||
|
"ON saml_auth_requests(expires_at)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_saml_responses_request ON saml_auth_responses(request_id)",
|
"CREATE INDEX IF NOT EXISTS idx_saml_responses_request "
|
||||||
|
"ON saml_auth_responses(request_id)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_scim_config_tenant ON scim_configs(tenant_id)",
|
"CREATE INDEX IF NOT EXISTS idx_scim_config_tenant "
|
||||||
|
"ON scim_configs(tenant_id)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_scim_users_tenant ON scim_users(tenant_id)",
|
"CREATE INDEX IF NOT EXISTS idx_scim_users_tenant "
|
||||||
|
"ON scim_users(tenant_id)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_scim_users_external ON scim_users(external_id)",
|
"CREATE INDEX IF NOT EXISTS idx_scim_users_external "
|
||||||
|
"ON scim_users(external_id)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_audit_export_tenant ON audit_log_exports(tenant_id)",
|
"CREATE INDEX IF NOT EXISTS idx_audit_export_tenant "
|
||||||
|
"ON audit_log_exports(tenant_id)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_audit_export_status ON audit_log_exports(status)",
|
"CREATE INDEX IF NOT EXISTS idx_audit_export_status ON audit_log_exports(status)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_retention_tenant ON data_retention_policies(tenant_id)",
|
"CREATE INDEX IF NOT EXISTS idx_retention_tenant "
|
||||||
|
"ON data_retention_policies(tenant_id)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_retention_type ON data_retention_policies(resource_type)",
|
"CREATE INDEX IF NOT EXISTS idx_retention_type "
|
||||||
|
"ON data_retention_policies(resource_type)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_retention_jobs_policy ON data_retention_jobs(policy_id)",
|
"CREATE INDEX IF NOT EXISTS idx_retention_jobs_policy "
|
||||||
|
"ON data_retention_jobs(policy_id)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_retention_jobs_status ON data_retention_jobs(status)",
|
"CREATE INDEX IF NOT EXISTS idx_retention_jobs_status "
|
||||||
|
"ON data_retention_jobs(status)",
|
||||||
)
|
)
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
@@ -901,7 +914,8 @@ class EnterpriseManager:
|
|||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO saml_auth_requests
|
INSERT INTO saml_auth_requests
|
||||||
(id, tenant_id, sso_config_id, request_id, relay_state, created_at, expires_at, used)
|
(id, tenant_id, sso_config_id, request_id, relay_state,
|
||||||
|
created_at, expires_at, used)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -153,20 +153,21 @@ class ExportManager:
|
|||||||
y2 = y2 - dy * offset / dist
|
y2 = y2 - dy * offset / dist
|
||||||
|
|
||||||
svg_parts.append(
|
svg_parts.append(
|
||||||
f'<line x1 = "{x1}" y1 = "{y1}" x2 = "{x2}" y2 = "{y2}" '
|
f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" '
|
||||||
f'stroke = "#7f8c8d" stroke-width = "2" marker-end = "url(#arrowhead)" opacity = "0.6"/>',
|
f'stroke="#7f8c8d" stroke-width="2" '
|
||||||
|
f'marker-end="url(#arrowhead)" opacity="0.6"/>',
|
||||||
)
|
)
|
||||||
|
|
||||||
# 关系标签
|
# 关系标签
|
||||||
mid_x = (x1 + x2) / 2
|
mid_x = (x1 + x2) / 2
|
||||||
mid_y = (y1 + y2) / 2
|
mid_y = (y1 + y2) / 2
|
||||||
svg_parts.append(
|
svg_parts.append(
|
||||||
f'<rect x = "{mid_x - 30}" y = "{mid_y - 10}" width = "60" height = "20" '
|
f'<rect x="{mid_x - 30}" y="{mid_y - 10}" width="60" height="20" '
|
||||||
f'fill = "white" stroke = "#bdc3c7" rx = "3"/>',
|
f'fill="white" stroke="#bdc3c7" rx="3"/>',
|
||||||
)
|
)
|
||||||
svg_parts.append(
|
svg_parts.append(
|
||||||
f'<text x = "{mid_x}" y = "{mid_y + 5}" text-anchor = "middle" '
|
f'<text x="{mid_x}" y="{mid_y + 5}" text-anchor="middle" '
|
||||||
f'font-size = "10" fill = "#2c3e50">{rel.relation_type}</text>',
|
f'font-size="10" fill="#2c3e50">{rel.relation_type}</text>',
|
||||||
)
|
)
|
||||||
|
|
||||||
# 绘制实体节点
|
# 绘制实体节点
|
||||||
@@ -177,19 +178,21 @@ class ExportManager:
|
|||||||
|
|
||||||
# 节点圆圈
|
# 节点圆圈
|
||||||
svg_parts.append(
|
svg_parts.append(
|
||||||
f'<circle cx = "{x}" cy = "{y}" r = "35" fill = "{color}" stroke = "white" stroke-width = "3"/>',
|
f'<circle cx="{x}" cy="{y}" r="35" fill="{color}" '
|
||||||
|
f'stroke="white" stroke-width="3"/>',
|
||||||
)
|
)
|
||||||
|
|
||||||
# 实体名称
|
# 实体名称
|
||||||
svg_parts.append(
|
svg_parts.append(
|
||||||
f'<text x = "{x}" y = "{y + 5}" text-anchor = "middle" font-size = "12" '
|
f'<text x="{x}" y="{y + 5}" text-anchor="middle" '
|
||||||
f'font-weight = "bold" fill = "white">{entity.name[:8]}</text>',
|
f'font-size="12" font-weight="bold" fill="white">'
|
||||||
|
f'{entity.name[:8]}</text>',
|
||||||
)
|
)
|
||||||
|
|
||||||
# 实体类型
|
# 实体类型
|
||||||
svg_parts.append(
|
svg_parts.append(
|
||||||
f'<text x = "{x}" y = "{y + 55}" text-anchor = "middle" font-size = "10" '
|
f'<text x="{x}" y="{y + 55}" text-anchor="middle" '
|
||||||
f'fill = "#7f8c8d">{entity.type}</text>',
|
f'font-size="10" fill="#7f8c8d">{entity.type}</text>',
|
||||||
)
|
)
|
||||||
|
|
||||||
# 图例
|
# 图例
|
||||||
|
|||||||
@@ -1405,7 +1405,8 @@ class GrowthManager:
|
|||||||
conn.execute(
|
conn.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO email_logs
|
INSERT INTO email_logs
|
||||||
(id, campaign_id, tenant_id, user_id, email, template_id, status, subject, created_at)
|
(id, campaign_id, tenant_id, user_id, email, template_id,
|
||||||
|
status, subject, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
@@ -1647,7 +1648,8 @@ class GrowthManager:
|
|||||||
|
|
||||||
# 更新执行计数
|
# 更新执行计数
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"UPDATE automation_workflows SET execution_count = execution_count + 1 WHERE id = ?",
|
"""UPDATE automation_workflows
|
||||||
|
SET execution_count = execution_count + 1 WHERE id = ?""",
|
||||||
(workflow_id,),
|
(workflow_id,),
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ from dataclasses import dataclass
|
|||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
# re is already imported above
|
|
||||||
|
|
||||||
KIMI_API_KEY = os.getenv("KIMI_API_KEY", "")
|
KIMI_API_KEY = os.getenv("KIMI_API_KEY", "")
|
||||||
KIMI_BASE_URL = os.getenv("KIMI_BASE_URL", "https://api.kimi.com/coding")
|
KIMI_BASE_URL = os.getenv("KIMI_BASE_URL", "https://api.kimi.com/coding")
|
||||||
|
|
||||||
|
|||||||
@@ -756,10 +756,11 @@ class LocalizationManager:
|
|||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS language_configs (
|
CREATE TABLE IF NOT EXISTS language_configs (
|
||||||
code TEXT PRIMARY KEY, name TEXT NOT NULL, name_local TEXT NOT NULL,
|
code TEXT PRIMARY KEY, name TEXT NOT NULL, name_local TEXT NOT NULL,
|
||||||
is_rtl INTEGER DEFAULT 0, is_active INTEGER DEFAULT 1, is_default INTEGER DEFAULT 0,
|
is_rtl INTEGER DEFAULT 0, is_active INTEGER DEFAULT 1,
|
||||||
fallback_language TEXT, date_format TEXT, time_format TEXT, datetime_format TEXT,
|
is_default INTEGER DEFAULT 0, fallback_language TEXT,
|
||||||
number_format TEXT, currency_format TEXT, first_day_of_week INTEGER DEFAULT 1,
|
date_format TEXT, time_format TEXT, datetime_format TEXT,
|
||||||
calendar_type TEXT DEFAULT 'gregorian'
|
number_format TEXT, currency_format TEXT,
|
||||||
|
first_day_of_week INTEGER DEFAULT 1, calendar_type TEXT DEFAULT 'gregorian'
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
@@ -773,8 +774,10 @@ class LocalizationManager:
|
|||||||
""")
|
""")
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS tenant_data_center_mappings (
|
CREATE TABLE IF NOT EXISTS tenant_data_center_mappings (
|
||||||
id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL UNIQUE, primary_dc_id TEXT NOT NULL,
|
id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL UNIQUE,
|
||||||
secondary_dc_id TEXT, region_code TEXT NOT NULL, data_residency TEXT DEFAULT 'regional',
|
primary_dc_id TEXT NOT NULL, secondary_dc_id TEXT,
|
||||||
|
region_code TEXT NOT NULL,
|
||||||
|
data_residency TEXT DEFAULT 'regional',
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||||
@@ -788,43 +791,52 @@ class LocalizationManager:
|
|||||||
name_local TEXT DEFAULT '{}', supported_countries TEXT DEFAULT '[]',
|
name_local TEXT DEFAULT '{}', supported_countries TEXT DEFAULT '[]',
|
||||||
supported_currencies TEXT DEFAULT '[]', is_active INTEGER DEFAULT 1,
|
supported_currencies TEXT DEFAULT '[]', is_active INTEGER DEFAULT 1,
|
||||||
config TEXT DEFAULT '{}', icon_url TEXT, display_order INTEGER DEFAULT 0,
|
config TEXT DEFAULT '{}', icon_url TEXT, display_order INTEGER DEFAULT 0,
|
||||||
min_amount REAL, max_amount REAL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
min_amount REAL, max_amount REAL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS country_configs (
|
CREATE TABLE IF NOT EXISTS country_configs (
|
||||||
code TEXT PRIMARY KEY, code3 TEXT NOT NULL, name TEXT NOT NULL,
|
code TEXT PRIMARY KEY, code3 TEXT NOT NULL, name TEXT NOT NULL,
|
||||||
name_local TEXT DEFAULT '{}', region TEXT NOT NULL, default_language TEXT NOT NULL,
|
name_local TEXT DEFAULT '{}', region TEXT NOT NULL,
|
||||||
supported_languages TEXT DEFAULT '[]', default_currency TEXT NOT NULL,
|
default_language TEXT NOT NULL, supported_languages TEXT DEFAULT '[]',
|
||||||
supported_currencies TEXT DEFAULT '[]', timezone TEXT NOT NULL,
|
default_currency TEXT NOT NULL, supported_currencies TEXT DEFAULT '[]',
|
||||||
calendar_type TEXT DEFAULT 'gregorian', date_format TEXT, time_format TEXT,
|
timezone TEXT NOT NULL, calendar_type TEXT DEFAULT 'gregorian',
|
||||||
number_format TEXT, address_format TEXT, phone_format TEXT, vat_rate REAL,
|
date_format TEXT, time_format TEXT, number_format TEXT,
|
||||||
|
address_format TEXT, phone_format TEXT, vat_rate REAL,
|
||||||
is_active INTEGER DEFAULT 1
|
is_active INTEGER DEFAULT 1
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS timezone_configs (
|
CREATE TABLE IF NOT EXISTS timezone_configs (
|
||||||
id TEXT PRIMARY KEY, timezone TEXT NOT NULL UNIQUE, utc_offset TEXT NOT NULL, dst_offset TEXT,
|
id TEXT PRIMARY KEY, timezone TEXT NOT NULL UNIQUE,
|
||||||
country_code TEXT NOT NULL, region TEXT NOT NULL, is_active INTEGER DEFAULT 1
|
utc_offset TEXT NOT NULL, dst_offset TEXT, country_code TEXT NOT NULL,
|
||||||
|
region TEXT NOT NULL, is_active INTEGER DEFAULT 1
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS currency_configs (
|
CREATE TABLE IF NOT EXISTS currency_configs (
|
||||||
code TEXT PRIMARY KEY, name TEXT NOT NULL, name_local TEXT DEFAULT '{}', symbol TEXT NOT NULL,
|
code TEXT PRIMARY KEY, name TEXT NOT NULL,
|
||||||
|
name_local TEXT DEFAULT '{}', symbol TEXT NOT NULL,
|
||||||
decimal_places INTEGER DEFAULT 2, decimal_separator TEXT DEFAULT '.',
|
decimal_places INTEGER DEFAULT 2, decimal_separator TEXT DEFAULT '.',
|
||||||
thousands_separator TEXT DEFAULT ', ', is_active INTEGER DEFAULT 1
|
thousands_separator TEXT DEFAULT ', ', is_active INTEGER DEFAULT 1
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS localization_settings (
|
CREATE TABLE IF NOT EXISTS localization_settings (
|
||||||
id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL UNIQUE, default_language TEXT DEFAULT 'en',
|
id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL UNIQUE,
|
||||||
supported_languages TEXT DEFAULT '["en"]', default_currency TEXT DEFAULT 'USD',
|
default_language TEXT DEFAULT 'en',
|
||||||
supported_currencies TEXT DEFAULT '["USD"]', default_timezone TEXT DEFAULT 'UTC',
|
supported_languages TEXT DEFAULT '["en"]',
|
||||||
default_date_format TEXT, default_time_format TEXT, default_number_format TEXT,
|
default_currency TEXT DEFAULT 'USD',
|
||||||
calendar_type TEXT DEFAULT 'gregorian', first_day_of_week INTEGER DEFAULT 1,
|
supported_currencies TEXT DEFAULT '["USD"]',
|
||||||
region_code TEXT DEFAULT 'global', data_residency TEXT DEFAULT 'regional',
|
default_timezone TEXT DEFAULT 'UTC',
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
default_date_format TEXT, default_time_format TEXT,
|
||||||
|
default_number_format TEXT, calendar_type TEXT DEFAULT 'gregorian',
|
||||||
|
first_day_of_week INTEGER DEFAULT 1, region_code TEXT DEFAULT 'global',
|
||||||
|
data_residency TEXT DEFAULT 'regional',
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
@@ -838,22 +850,28 @@ class LocalizationManager:
|
|||||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_dc_region ON data_centers(region_code)")
|
cursor.execute("CREATE INDEX IF NOT EXISTS idx_dc_region ON data_centers(region_code)")
|
||||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_dc_status ON data_centers(status)")
|
cursor.execute("CREATE INDEX IF NOT EXISTS idx_dc_status ON data_centers(status)")
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_tenant_dc ON tenant_data_center_mappings(tenant_id)",
|
"CREATE INDEX IF NOT EXISTS idx_tenant_dc "
|
||||||
|
"ON tenant_data_center_mappings(tenant_id)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_payment_provider ON localized_payment_methods(provider)",
|
"CREATE INDEX IF NOT EXISTS idx_payment_provider "
|
||||||
|
"ON localized_payment_methods(provider)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_payment_active ON localized_payment_methods(is_active)",
|
"CREATE INDEX IF NOT EXISTS idx_payment_active "
|
||||||
|
"ON localized_payment_methods(is_active)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_country_region ON country_configs(region)",
|
"CREATE INDEX IF NOT EXISTS idx_country_region "
|
||||||
|
"ON country_configs(region)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_tz_country ON timezone_configs(country_code)",
|
"CREATE INDEX IF NOT EXISTS idx_tz_country "
|
||||||
|
"ON timezone_configs(country_code)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_locale_settings_tenant ON localization_settings(tenant_id)",
|
"CREATE INDEX IF NOT EXISTS idx_locale_settings_tenant "
|
||||||
|
"ON localization_settings(tenant_id)",
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
logger.info("Localization tables initialized successfully")
|
logger.info("Localization tables initialized successfully")
|
||||||
@@ -898,7 +916,8 @@ class LocalizationManager:
|
|||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""
|
"""
|
||||||
INSERT OR IGNORE INTO data_centers
|
INSERT OR IGNORE INTO data_centers
|
||||||
(id, region_code, name, location, endpoint, priority, supported_regions, capabilities)
|
(id, region_code, name, location, endpoint, priority,
|
||||||
|
supported_regions, capabilities)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
@@ -1188,7 +1207,9 @@ class LocalizationManager:
|
|||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
if not row:
|
if not row:
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT * FROM data_centers WHERE supported_regions LIKE '%"global"%' AND status = 'active'
|
SELECT * FROM data_centers
|
||||||
|
WHERE supported_regions LIKE '%"global"%'
|
||||||
|
AND status = 'active'
|
||||||
ORDER BY priority LIMIT 1
|
ORDER BY priority LIMIT 1
|
||||||
""")
|
""")
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
@@ -1197,7 +1218,9 @@ class LocalizationManager:
|
|||||||
primary_dc_id = row["id"]
|
primary_dc_id = row["id"]
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""
|
"""
|
||||||
SELECT * FROM data_centers WHERE id != ? AND status = 'active' ORDER BY priority LIMIT 1
|
SELECT * FROM data_centers
|
||||||
|
WHERE id != ? AND status = 'active'
|
||||||
|
ORDER BY priority LIMIT 1
|
||||||
""",
|
""",
|
||||||
(primary_dc_id,),
|
(primary_dc_id,),
|
||||||
)
|
)
|
||||||
@@ -1468,9 +1491,10 @@ class LocalizationManager:
|
|||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO localization_settings
|
INSERT INTO localization_settings
|
||||||
(id, tenant_id, default_language, supported_languages, default_currency, supported_currencies,
|
(id, tenant_id, default_language, supported_languages, default_currency,
|
||||||
default_timezone, default_date_format, default_time_format, default_number_format, calendar_type,
|
supported_currencies, default_timezone, default_date_format, default_time_format,
|
||||||
first_day_of_week, region_code, data_residency, created_at, updated_at)
|
default_number_format, calendar_type, first_day_of_week, region_code,
|
||||||
|
data_residency, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -1250,8 +1250,10 @@ def extract_entities_with_llm(text: str) -> tuple[list[dict], list[dict]]:
|
|||||||
文本:{text[:3000]}
|
文本:{text[:3000]}
|
||||||
|
|
||||||
要求:
|
要求:
|
||||||
1. entities: 每个实体包含 name(名称), type(类型: PROJECT/TECH/PERSON/ORG/OTHER), definition(一句话定义)
|
1. entities: 每个实体包含 name(名称), type(类型: PROJECT/TECH/PERSON/ORG/OTHER),
|
||||||
2. relations: 每个关系包含 source(源实体名), target(目标实体名), type(关系类型: belongs_to/works_with/depends_on/mentions/related)
|
definition(一句话定义)
|
||||||
|
2. relations: 每个关系包含 source(源实体名), target(目标实体名),
|
||||||
|
type(关系类型: belongs_to/works_with/depends_on/mentions/related)
|
||||||
3. 只返回 JSON 对象,格式: {{"entities": [...], "relations": [...]}}
|
3. 只返回 JSON 对象,格式: {{"entities": [...], "relations": [...]}}
|
||||||
|
|
||||||
示例:
|
示例:
|
||||||
@@ -2053,7 +2055,8 @@ async def agent_suggest(project_id: str, _=Depends(verify_api_key)):
|
|||||||
2. 建议的操作(如合并相似实体、补充定义等)
|
2. 建议的操作(如合并相似实体、补充定义等)
|
||||||
3. 值得关注的关键信息
|
3. 值得关注的关键信息
|
||||||
|
|
||||||
返回 JSON 格式:{{"suggestions": [{{"type": "insight|action", "title": "...", "description": "..."}}]}}"""
|
返回 JSON 格式:{{"suggestions": [{{"type": "insight|action", "title": "...",
|
||||||
|
"description": "..."}}]}}"""
|
||||||
|
|
||||||
messages = [ChatMessage(role="user", content=prompt)]
|
messages = [ChatMessage(role="user", content=prompt)]
|
||||||
content = await llm.chat(messages, temperature=0.3)
|
content = await llm.chat(messages, temperature=0.3)
|
||||||
@@ -2593,7 +2596,8 @@ async def set_entity_attribute_endpoint(
|
|||||||
# 记录历史
|
# 记录历史
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"""INSERT INTO attribute_history
|
"""INSERT INTO attribute_history
|
||||||
(id, entity_id, attribute_name, old_value, new_value, changed_by, changed_at, change_reason)
|
(id, entity_id, attribute_name, old_value, new_value,
|
||||||
|
changed_by, changed_at, change_reason)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(
|
(
|
||||||
str(uuid.uuid4())[:UUID_LENGTH],
|
str(uuid.uuid4())[:UUID_LENGTH],
|
||||||
@@ -2628,7 +2632,8 @@ async def set_entity_attribute_endpoint(
|
|||||||
# 记录历史
|
# 记录历史
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"""INSERT INTO attribute_history
|
"""INSERT INTO attribute_history
|
||||||
(id, entity_id, attribute_name, old_value, new_value, changed_by, changed_at, change_reason)
|
(id, entity_id, attribute_name, old_value, new_value,
|
||||||
|
changed_by, changed_at, change_reason)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(
|
(
|
||||||
str(uuid.uuid4())[:UUID_LENGTH],
|
str(uuid.uuid4())[:UUID_LENGTH],
|
||||||
@@ -3292,7 +3297,9 @@ async def export_transcript_markdown_endpoint(transcript_id: str, _=Depends(veri
|
|||||||
io.BytesIO(markdown_content.encode("utf-8")),
|
io.BytesIO(markdown_content.encode("utf-8")),
|
||||||
media_type="text/markdown",
|
media_type="text/markdown",
|
||||||
headers={
|
headers={
|
||||||
"Content-Disposition": f"attachment; filename=insightflow-transcript-{transcript_id}.md",
|
"Content-Disposition": (
|
||||||
|
f"attachment; filename=insightflow-transcript-{transcript_id}.md"
|
||||||
|
),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -3395,7 +3402,9 @@ async def neo4j_sync_project(request: Neo4jSyncRequest, _=Depends(verify_api_key
|
|||||||
"project_id": request.project_id,
|
"project_id": request.project_id,
|
||||||
"entities_synced": len(entities_data),
|
"entities_synced": len(entities_data),
|
||||||
"relations_synced": len(relations_data),
|
"relations_synced": len(relations_data),
|
||||||
"message": f"Synced {len(entities_data)} entities and {len(relations_data)} relations to Neo4j",
|
"message": (
|
||||||
|
f"Synced {len(entities_data)} entities and {len(relations_data)} relations to Neo4j"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4516,7 +4525,8 @@ async def upload_video_endpoint(
|
|||||||
for frame in result.frames:
|
for frame in result.frames:
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"""INSERT INTO video_frames
|
"""INSERT INTO video_frames
|
||||||
(id, video_id, frame_number, timestamp, image_url, ocr_text, extracted_entities, created_at)
|
(id, video_id, frame_number, timestamp, image_url, ocr_text,
|
||||||
|
extracted_entities, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(
|
(
|
||||||
frame.id,
|
frame.id,
|
||||||
@@ -4560,7 +4570,8 @@ async def upload_video_endpoint(
|
|||||||
conn = db.get_conn()
|
conn = db.get_conn()
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"""INSERT OR REPLACE INTO multimodal_mentions
|
"""INSERT OR REPLACE INTO multimodal_mentions
|
||||||
(id, project_id, entity_id, modality, source_id, source_type, text_snippet, confidence, created_at)
|
(id, project_id, entity_id, modality, source_id, source_type,
|
||||||
|
text_snippet, confidence, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(
|
(
|
||||||
str(uuid.uuid4())[:UUID_LENGTH],
|
str(uuid.uuid4())[:UUID_LENGTH],
|
||||||
@@ -4718,7 +4729,8 @@ async def upload_image_endpoint(
|
|||||||
conn = db.get_conn()
|
conn = db.get_conn()
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"""INSERT OR REPLACE INTO multimodal_mentions
|
"""INSERT OR REPLACE INTO multimodal_mentions
|
||||||
(id, project_id, entity_id, modality, source_id, source_type, text_snippet, confidence, created_at)
|
(id, project_id, entity_id, modality, source_id, source_type,
|
||||||
|
text_snippet, confidence, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(
|
(
|
||||||
str(uuid.uuid4())[:UUID_LENGTH],
|
str(uuid.uuid4())[:UUID_LENGTH],
|
||||||
@@ -4925,7 +4937,8 @@ async def align_multimodal_entities_endpoint(
|
|||||||
for link in links:
|
for link in links:
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"""INSERT OR REPLACE INTO multimodal_entity_links
|
"""INSERT OR REPLACE INTO multimodal_entity_links
|
||||||
(id, entity_id, linked_entity_id, link_type, confidence, evidence, modalities, created_at)
|
(id, entity_id, linked_entity_id, link_type, confidence,
|
||||||
|
evidence, modalities, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(
|
(
|
||||||
link.id,
|
link.id,
|
||||||
@@ -5012,7 +5025,8 @@ async def get_multimodal_stats_endpoint(project_id: str, _=Depends(verify_api_ke
|
|||||||
modality_dist = {}
|
modality_dist = {}
|
||||||
for modality in ["audio", "video", "image", "document"]:
|
for modality in ["audio", "video", "image", "document"]:
|
||||||
count = conn.execute(
|
count = conn.execute(
|
||||||
"SELECT COUNT(*) as count FROM multimodal_mentions WHERE project_id = ? AND modality = ?",
|
"""SELECT COUNT(*) as count FROM multimodal_mentions
|
||||||
|
WHERE project_id = ? AND modality = ?""",
|
||||||
(project_id, modality),
|
(project_id, modality),
|
||||||
).fetchone()["count"]
|
).fetchone()["count"]
|
||||||
modality_dist[modality] = count
|
modality_dist[modality] = count
|
||||||
@@ -5300,7 +5314,10 @@ class PluginCreate(BaseModel):
|
|||||||
name: str = Field(..., description="插件名称")
|
name: str = Field(..., description="插件名称")
|
||||||
plugin_type: str = Field(
|
plugin_type: str = Field(
|
||||||
...,
|
...,
|
||||||
description="插件类型: chrome_extension, feishu_bot, dingtalk_bot, zapier, make, webdav, custom",
|
description=(
|
||||||
|
"插件类型: chrome_extension, feishu_bot, dingtalk_bot, "
|
||||||
|
"zapier, make, webdav, custom"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
project_id: str = Field(..., description="关联项目ID")
|
project_id: str = Field(..., description="关联项目ID")
|
||||||
config: dict = Field(default_factory=dict, description="插件配置")
|
config: dict = Field(default_factory=dict, description="插件配置")
|
||||||
|
|||||||
@@ -378,7 +378,8 @@ class Neo4jManager:
|
|||||||
result = session.run(
|
result = session.run(
|
||||||
"""
|
"""
|
||||||
MATCH path = shortestPath(
|
MATCH path = shortestPath(
|
||||||
(source:Entity {id: $source_id})-[*1..$max_depth]-(target:Entity {id: $target_id})
|
(source:Entity {id: $source_id})-[*1..$max_depth]-
|
||||||
|
(target:Entity {id: $target_id})
|
||||||
)
|
)
|
||||||
RETURN path
|
RETURN path
|
||||||
""",
|
""",
|
||||||
@@ -440,7 +441,8 @@ class Neo4jManager:
|
|||||||
with self._driver.session() as session:
|
with self._driver.session() as session:
|
||||||
result = session.run(
|
result = session.run(
|
||||||
"""
|
"""
|
||||||
MATCH path = (source:Entity {id: $source_id})-[*1..$max_depth]-(target:Entity {id: $target_id})
|
MATCH path = (source:Entity {id: $source_id})-[*1..$max_depth]-
|
||||||
|
(target:Entity {id: $target_id})
|
||||||
WHERE source <> target
|
WHERE source <> target
|
||||||
RETURN path
|
RETURN path
|
||||||
LIMIT $limit
|
LIMIT $limit
|
||||||
@@ -504,7 +506,9 @@ class Neo4jManager:
|
|||||||
if relation_type:
|
if relation_type:
|
||||||
result = session.run(
|
result = session.run(
|
||||||
"""
|
"""
|
||||||
MATCH (e:Entity {id: $entity_id})-[r:RELATES_TO {relation_type: $relation_type}]-(neighbor:Entity)
|
MATCH (e:Entity {id: $entity_id})-
|
||||||
|
[r:RELATES_TO {relation_type: $relation_type}]-
|
||||||
|
(neighbor:Entity)
|
||||||
RETURN neighbor, r.relation_type as rel_type, r.evidence as evidence
|
RETURN neighbor, r.relation_type as rel_type, r.evidence as evidence
|
||||||
LIMIT $limit
|
LIMIT $limit
|
||||||
""",
|
""",
|
||||||
@@ -555,7 +559,8 @@ class Neo4jManager:
|
|||||||
with self._driver.session() as session:
|
with self._driver.session() as session:
|
||||||
result = session.run(
|
result = session.run(
|
||||||
"""
|
"""
|
||||||
MATCH (e1:Entity {id: $id1})-[:RELATES_TO]-(common:Entity)-[:RELATES_TO]-(e2:Entity {id: $id2})
|
MATCH (e1:Entity {id: $id1})-[:RELATES_TO]-(common:Entity)-
|
||||||
|
[:RELATES_TO]-(e2:Entity {id: $id2})
|
||||||
RETURN DISTINCT common
|
RETURN DISTINCT common
|
||||||
""",
|
""",
|
||||||
id1=entity_id1,
|
id1=entity_id1,
|
||||||
@@ -593,7 +598,8 @@ class Neo4jManager:
|
|||||||
CALL gds.graph.exists('project-graph-$project_id') YIELD exists
|
CALL gds.graph.exists('project-graph-$project_id') YIELD exists
|
||||||
WITH exists
|
WITH exists
|
||||||
CALL apoc.do.when(exists,
|
CALL apoc.do.when(exists,
|
||||||
'CALL gds.graph.drop("project-graph-$project_id") YIELD graphName RETURN graphName',
|
'CALL gds.graph.drop("project-graph-$project_id") '
|
||||||
|
'YIELD graphName RETURN graphName',
|
||||||
'RETURN "none" as graphName',
|
'RETURN "none" as graphName',
|
||||||
{}
|
{}
|
||||||
) YIELD value RETURN value
|
) YIELD value RETURN value
|
||||||
@@ -1069,7 +1075,8 @@ def sync_project_to_neo4j(
|
|||||||
manager.sync_relations_batch(graph_relations)
|
manager.sync_relations_batch(graph_relations)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Synced project {project_id} to Neo4j: {len(entities)} entities, {len(relations)} relations",
|
f"Synced project {project_id} to Neo4j: {len(entities)} entities, "
|
||||||
|
f"{len(relations)} relations",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1690,7 +1690,8 @@ class OpsManager:
|
|||||||
INSERT INTO auto_scaling_policies
|
INSERT INTO auto_scaling_policies
|
||||||
(id, tenant_id, name, resource_type, min_instances, max_instances,
|
(id, tenant_id, name, resource_type, min_instances, max_instances,
|
||||||
target_utilization, scale_up_threshold, scale_down_threshold,
|
target_utilization, scale_up_threshold, scale_down_threshold,
|
||||||
scale_up_step, scale_down_step, cooldown_period, is_enabled, created_at, updated_at)
|
scale_up_step, scale_down_step, cooldown_period, is_enabled, created_at,
|
||||||
|
updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
@@ -2153,7 +2154,8 @@ class OpsManager:
|
|||||||
"""
|
"""
|
||||||
INSERT INTO failover_configs
|
INSERT INTO failover_configs
|
||||||
(id, tenant_id, name, primary_region, secondary_regions, failover_trigger,
|
(id, tenant_id, name, primary_region, secondary_regions, failover_trigger,
|
||||||
auto_failover, failover_timeout, health_check_id, is_enabled, created_at, updated_at)
|
auto_failover, failover_timeout, health_check_id, is_enabled, created_at,
|
||||||
|
updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
@@ -2545,7 +2547,8 @@ class OpsManager:
|
|||||||
conn.execute(
|
conn.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO cost_reports
|
INSERT INTO cost_reports
|
||||||
(id, tenant_id, report_period, total_cost, currency, breakdown, trends, anomalies, created_at)
|
(id, tenant_id, report_period, total_cost, currency, breakdown,
|
||||||
|
trends, anomalies, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
@@ -2786,7 +2789,8 @@ class OpsManager:
|
|||||||
"""
|
"""
|
||||||
INSERT INTO cost_optimization_suggestions
|
INSERT INTO cost_optimization_suggestions
|
||||||
(id, tenant_id, category, title, description, potential_savings, currency,
|
(id, tenant_id, category, title, description, potential_savings, currency,
|
||||||
confidence, difficulty, implementation_steps, risk_level, is_applied, created_at)
|
confidence, difficulty, implementation_steps, risk_level, is_applied,
|
||||||
|
created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -496,7 +496,8 @@ class CacheManager:
|
|||||||
# 预热实体数据
|
# 预热实体数据
|
||||||
entities = conn.execute(
|
entities = conn.execute(
|
||||||
"""SELECT e.*,
|
"""SELECT e.*,
|
||||||
(SELECT COUNT(*) FROM entity_mentions m WHERE m.entity_id = e.id) as mention_count
|
(SELECT COUNT(*) FROM entity_mentions m WHERE m.entity_id = e.id)
|
||||||
|
as mention_count
|
||||||
FROM entities e
|
FROM entities e
|
||||||
WHERE e.project_id = ?
|
WHERE e.project_id = ?
|
||||||
ORDER BY mention_count DESC
|
ORDER BY mention_count DESC
|
||||||
@@ -788,7 +789,8 @@ class DatabaseSharding:
|
|||||||
target_conn.execute(
|
target_conn.execute(
|
||||||
"""
|
"""
|
||||||
INSERT OR REPLACE INTO entity_relations
|
INSERT OR REPLACE INTO entity_relations
|
||||||
(id, project_id, source_entity_id, target_entity_id, relation_type, evidence, created_at)
|
(id, project_id, source_entity_id, target_entity_id, relation_type,
|
||||||
|
evidence, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
tuple(relation),
|
tuple(relation),
|
||||||
@@ -1409,7 +1411,10 @@ class PerformanceMonitor:
|
|||||||
"type": "performance_alert",
|
"type": "performance_alert",
|
||||||
"metric": metric.to_dict(),
|
"metric": metric.to_dict(),
|
||||||
"threshold": self.alert_threshold,
|
"threshold": self.alert_threshold,
|
||||||
"message": f"{metric.metric_type} exceeded threshold: {metric.duration_ms}ms > {self.alert_threshold}ms",
|
"message": (
|
||||||
|
f"{metric.metric_type} exceeded threshold: "
|
||||||
|
f"{metric.duration_ms}ms > {self.alert_threshold}ms"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
for handler in self.alert_handlers:
|
for handler in self.alert_handlers:
|
||||||
|
|||||||
@@ -188,7 +188,8 @@ class PluginManager:
|
|||||||
|
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"""INSERT INTO plugins
|
"""INSERT INTO plugins
|
||||||
(id, name, plugin_type, project_id, status, config, created_at, updated_at, use_count)
|
(id, name, plugin_type, project_id, status, config, created_at, updated_at,
|
||||||
|
use_count)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(
|
(
|
||||||
plugin.id,
|
plugin.id,
|
||||||
@@ -1204,7 +1205,8 @@ class WebDAVSyncManager:
|
|||||||
conn.execute(
|
conn.execute(
|
||||||
"""INSERT INTO webdav_syncs
|
"""INSERT INTO webdav_syncs
|
||||||
(id, name, project_id, server_url, username, password, remote_path,
|
(id, name, project_id, server_url, username, password, remote_path,
|
||||||
sync_mode, sync_interval, last_sync_status, is_active, created_at, updated_at, sync_count)
|
sync_mode, sync_interval, last_sync_status, is_active, created_at, updated_at,
|
||||||
|
sync_count)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(
|
(
|
||||||
sync_id,
|
sync_id,
|
||||||
|
|||||||
@@ -233,7 +233,8 @@ class FullTextSearch:
|
|||||||
|
|
||||||
# 创建索引
|
# 创建索引
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_search_content ON search_indexes(content_id, content_type)",
|
"""CREATE INDEX IF NOT EXISTS idx_search_content
|
||||||
|
ON search_indexes(content_id, content_type)""",
|
||||||
)
|
)
|
||||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_search_project ON search_indexes(project_id)")
|
conn.execute("CREATE INDEX IF NOT EXISTS idx_search_project ON search_indexes(project_id)")
|
||||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_term_freq_term ON search_term_freq(term)")
|
conn.execute("CREATE INDEX IF NOT EXISTS idx_term_freq_term ON search_term_freq(term)")
|
||||||
@@ -310,7 +311,8 @@ class FullTextSearch:
|
|||||||
conn.execute(
|
conn.execute(
|
||||||
"""
|
"""
|
||||||
INSERT OR REPLACE INTO search_indexes
|
INSERT OR REPLACE INTO search_indexes
|
||||||
(id, content_id, content_type, project_id, tokens, token_positions, created_at, updated_at)
|
(id, content_id, content_type, project_id, tokens, token_positions,
|
||||||
|
created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
@@ -579,7 +581,10 @@ class FullTextSearch:
|
|||||||
(content_id,),
|
(content_id,),
|
||||||
).fetchone()
|
).fetchone()
|
||||||
if row:
|
if row:
|
||||||
return f"{row['source_name']} {row['relation_type']} {row['target_name']} {row['evidence'] or ''}"
|
return (
|
||||||
|
f"{row['source_name']} {row['relation_type']} "
|
||||||
|
f"{row['target_name']} {row['evidence'] or ''}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return None
|
return None
|
||||||
@@ -784,7 +789,10 @@ class FullTextSearch:
|
|||||||
).fetchall()
|
).fetchall()
|
||||||
|
|
||||||
for r in relations:
|
for r in relations:
|
||||||
text = f"{r['source_name']} {r['relation_type']} {r['target_name']} {r['evidence'] or ''}"
|
text = (
|
||||||
|
f"{r['source_name']} {r['relation_type']} "
|
||||||
|
f"{r['target_name']} {r['evidence'] or ''}"
|
||||||
|
)
|
||||||
if self.index_content(r["id"], "relation", r["project_id"], text):
|
if self.index_content(r["id"], "relation", r["project_id"], text):
|
||||||
stats["relations"] += 1
|
stats["relations"] += 1
|
||||||
else:
|
else:
|
||||||
@@ -854,7 +862,8 @@ class SemanticSearch:
|
|||||||
""")
|
""")
|
||||||
|
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_embedding_content ON embeddings(content_id, content_type)",
|
"""CREATE INDEX IF NOT EXISTS idx_embedding_content
|
||||||
|
ON embeddings(content_id, content_type)""",
|
||||||
)
|
)
|
||||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_embedding_project ON embeddings(project_id)")
|
conn.execute("CREATE INDEX IF NOT EXISTS idx_embedding_project ON embeddings(project_id)")
|
||||||
|
|
||||||
@@ -1107,7 +1116,8 @@ class SemanticSearch:
|
|||||||
conn = self._get_conn()
|
conn = self._get_conn()
|
||||||
|
|
||||||
row = conn.execute(
|
row = conn.execute(
|
||||||
"SELECT embedding, project_id FROM embeddings WHERE content_id = ? AND content_type = ?",
|
"""SELECT embedding, project_id FROM embeddings
|
||||||
|
WHERE content_id = ? AND content_type = ?""",
|
||||||
(content_id, content_type),
|
(content_id, content_type),
|
||||||
).fetchone()
|
).fetchone()
|
||||||
|
|
||||||
|
|||||||
@@ -315,7 +315,8 @@ class SecurityManager:
|
|||||||
"CREATE INDEX IF NOT EXISTS idx_masking_project ON masking_rules(project_id)",
|
"CREATE INDEX IF NOT EXISTS idx_masking_project ON masking_rules(project_id)",
|
||||||
)
|
)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_access_policy_project ON data_access_policies(project_id)",
|
"""CREATE INDEX IF NOT EXISTS idx_access_policy_project
|
||||||
|
ON data_access_policies(project_id)""",
|
||||||
)
|
)
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|||||||
@@ -1108,7 +1108,8 @@ class SubscriptionManager:
|
|||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO usage_records
|
INSERT INTO usage_records
|
||||||
(id, tenant_id, resource_type, quantity, unit, recorded_at, cost, description, metadata)
|
(id, tenant_id, resource_type, quantity, unit, recorded_at,
|
||||||
|
cost, description, metadata)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
@@ -1780,7 +1781,9 @@ class SubscriptionManager:
|
|||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""
|
"""
|
||||||
UPDATE refunds
|
UPDATE refunds
|
||||||
SET status = 'rejected', metadata = json_set(metadata, '$.rejection_reason', ?), updated_at = ?
|
SET status = 'rejected',
|
||||||
|
metadata = json_set(metadata, '$.rejection_reason', ?),
|
||||||
|
updated_at = ?
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
""",
|
""",
|
||||||
(reason, now, refund_id),
|
(reason, now, refund_id),
|
||||||
@@ -1860,7 +1863,8 @@ class SubscriptionManager:
|
|||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO billing_history
|
INSERT INTO billing_history
|
||||||
(id, tenant_id, type, amount, currency, description, reference_id, balance_after, created_at, metadata)
|
(id, tenant_id, type, amount, currency, description,
|
||||||
|
reference_id, balance_after, created_at, metadata)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
@@ -1943,7 +1947,8 @@ class SubscriptionManager:
|
|||||||
amount = plan.price_yearly if billing_cycle == "yearly" else plan.price_monthly
|
amount = plan.price_yearly if billing_cycle == "yearly" else plan.price_monthly
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"order_id": f"ALI{datetime.now().strftime('%Y%m%d%H%M%S')}{uuid.uuid4().hex[:8].upper()}",
|
"order_id": f"ALI{datetime.now().strftime('%Y%m%d%H%M%S')}"
|
||||||
|
f"{uuid.uuid4().hex[:8].upper()}",
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
"currency": plan.currency,
|
"currency": plan.currency,
|
||||||
"qr_code_url": f"https://qr.alipay.com/mock/{uuid.uuid4().hex[:16]}",
|
"qr_code_url": f"https://qr.alipay.com/mock/{uuid.uuid4().hex[:16]}",
|
||||||
@@ -1963,7 +1968,8 @@ class SubscriptionManager:
|
|||||||
amount = plan.price_yearly if billing_cycle == "yearly" else plan.price_monthly
|
amount = plan.price_yearly if billing_cycle == "yearly" else plan.price_monthly
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"order_id": f"WX{datetime.now().strftime('%Y%m%d%H%M%S')}{uuid.uuid4().hex[:8].upper()}",
|
"order_id": f"WX{datetime.now().strftime('%Y%m%d%H%M%S')}"
|
||||||
|
f"{uuid.uuid4().hex[:8].upper()}",
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
"currency": plan.currency,
|
"currency": plan.currency,
|
||||||
"prepay_id": f"wx{uuid.uuid4().hex[:32]}",
|
"prepay_id": f"wx{uuid.uuid4().hex[:32]}",
|
||||||
|
|||||||
@@ -457,7 +457,8 @@ class TenantManager:
|
|||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO tenants (id, name, slug, description, tier, status, owner_id,
|
INSERT INTO tenants (id, name, slug, description, tier, status, owner_id,
|
||||||
created_at, updated_at, expires_at, settings, resource_limits, metadata)
|
created_at, updated_at, expires_at, settings,
|
||||||
|
resource_limits, metadata)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
@@ -1451,7 +1452,10 @@ class TenantManager:
|
|||||||
# TODO: 实现 HTTP 文件验证
|
# TODO: 实现 HTTP 文件验证
|
||||||
# import requests
|
# import requests
|
||||||
# try:
|
# try:
|
||||||
# response = requests.get(f"http://{domain}/.well-known/insightflow-verify.txt", timeout = 10)
|
# response = requests.get(
|
||||||
|
# f"http://{domain}/.well-known/insightflow-verify.txt",
|
||||||
|
# timeout = 10
|
||||||
|
# )
|
||||||
# if response.status_code == 200 and token in response.text:
|
# if response.status_code == 200 and token in response.text:
|
||||||
# return True
|
# return True
|
||||||
# except (ImportError, Exception):
|
# except (ImportError, Exception):
|
||||||
|
|||||||
@@ -513,7 +513,8 @@ class TestDeveloperEcosystem:
|
|||||||
self.manager.update_developer_stats(self.created_ids["developer"][0])
|
self.manager.update_developer_stats(self.created_ids["developer"][0])
|
||||||
profile = self.manager.get_developer_profile(self.created_ids["developer"][0])
|
profile = self.manager.get_developer_profile(self.created_ids["developer"][0])
|
||||||
self.log(
|
self.log(
|
||||||
f"Updated developer stats: {profile.plugin_count} plugins, {profile.template_count} templates",
|
f"Updated developer stats: {profile.plugin_count} plugins, "
|
||||||
|
f"{profile.template_count} templates",
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log(f"Failed to update developer stats: {e!s}", success=False)
|
self.log(f"Failed to update developer stats: {e!s}", success=False)
|
||||||
|
|||||||
@@ -275,7 +275,8 @@ class TestOpsManager:
|
|||||||
"""
|
"""
|
||||||
INSERT INTO alerts
|
INSERT INTO alerts
|
||||||
(id, rule_id, tenant_id, severity, status, title, description,
|
(id, rule_id, tenant_id, severity, status, title, description,
|
||||||
metric, value, threshold, labels, annotations, started_at, notification_sent, suppression_count)
|
metric, value, threshold, labels, annotations, started_at,
|
||||||
|
notification_sent, suppression_count)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
@@ -343,7 +344,8 @@ class TestOpsManager:
|
|||||||
conn.execute(
|
conn.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO resource_metrics
|
INSERT INTO resource_metrics
|
||||||
(id, tenant_id, resource_type, resource_id, metric_name, metric_value, unit, timestamp)
|
(id, tenant_id, resource_type, resource_id, metric_name,
|
||||||
|
metric_value, unit, timestamp)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ class TingwuClient:
|
|||||||
"x-acs-action": "CreateTask",
|
"x-acs-action": "CreateTask",
|
||||||
"x-acs-version": "2023-09-30",
|
"x-acs-version": "2023-09-30",
|
||||||
"x-acs-date": timestamp,
|
"x-acs-date": timestamp,
|
||||||
"Authorization": f"ACS3-HMAC-SHA256 Credential = {self.access_key}/acs/tingwu/cn-beijing",
|
"Authorization": f"ACS3-HMAC-SHA256 Credential = {self.access_key}"
|
||||||
|
f"/acs/tingwu/cn-beijing",
|
||||||
}
|
}
|
||||||
|
|
||||||
def create_task(self, audio_url: str, language: str = "zh") -> str:
|
def create_task(self, audio_url: str, language: str = "zh") -> str:
|
||||||
|
|||||||
@@ -1019,20 +1019,23 @@ class WorkflowManager:
|
|||||||
|
|
||||||
# 成功次数
|
# 成功次数
|
||||||
success = conn.execute(
|
success = conn.execute(
|
||||||
"SELECT COUNT(*) FROM workflow_logs WHERE workflow_id = ? AND status = 'success' AND created_at > ?",
|
"""SELECT COUNT(*) FROM workflow_logs
|
||||||
|
WHERE workflow_id = ? AND status = 'success' AND created_at > ?""",
|
||||||
(workflow_id, since),
|
(workflow_id, since),
|
||||||
).fetchone()[0]
|
).fetchone()[0]
|
||||||
|
|
||||||
# 失败次数
|
# 失败次数
|
||||||
failed = conn.execute(
|
failed = conn.execute(
|
||||||
"SELECT COUNT(*) FROM workflow_logs WHERE workflow_id = ? AND status = 'failed' AND created_at > ?",
|
"""SELECT COUNT(*) FROM workflow_logs
|
||||||
|
WHERE workflow_id = ? AND status = 'failed' AND created_at > ?""",
|
||||||
(workflow_id, since),
|
(workflow_id, since),
|
||||||
).fetchone()[0]
|
).fetchone()[0]
|
||||||
|
|
||||||
# 平均执行时间
|
# 平均执行时间
|
||||||
avg_duration = (
|
avg_duration = (
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"SELECT AVG(duration_ms) FROM workflow_logs WHERE workflow_id = ? AND created_at > ?",
|
"""SELECT AVG(duration_ms) FROM workflow_logs
|
||||||
|
WHERE workflow_id = ? AND created_at > ?""",
|
||||||
(workflow_id, since),
|
(workflow_id, since),
|
||||||
).fetchone()[0]
|
).fetchone()[0]
|
||||||
or 0
|
or 0
|
||||||
|
|||||||
Reference in New Issue
Block a user