feat: enable full AI automation and safe startup updates
This commit is contained in:
1 parent
2ddec53954
commit
7b1a0755e2
62 files changed
+3123
-240
No files matched your search
@@ -9,6 +9,8 @@ interface ModelSettings {
|
||||
api_key_configured: boolean;
|
||||
timeout_seconds: number;
|
||||
max_retries: number;
|
||||
retry_interval_seconds: number;
|
||||
reasoning_effort: string;
|
||||
env_path: string;
|
||||
message?: string;
|
||||
}
|
||||
@@ -25,16 +27,25 @@ interface ModelSettings {
|
||||
placeholder="https://api.openai.com/v1" [disabled]="busy() || loading()" />
|
||||
<small>填写接口根地址,通常包含 /v1,无需添加 /responses。</small>
|
||||
<label for="model-name">模型名称</label>
|
||||
<input id="model-name" name="model" [(ngModel)]="model" required placeholder="输入接口支持的模型名"
|
||||
<input id="model-name" name="model" list="model-presets" [(ngModel)]="model" required placeholder="输入接口支持的模型名"
|
||||
[disabled]="busy() || loading()" />
|
||||
<datalist id="model-presets"><option value="gpt-5.6-luna"></option><option value="mimo-v2.6-flash"></option></datalist>
|
||||
<label for="model-reasoning">思考强度</label>
|
||||
<select id="model-reasoning" name="reasoning" [(ngModel)]="reasoning" [disabled]="busy() || loading()">
|
||||
<option value="default">由模型默认</option><option value="none">关闭(none)</option>
|
||||
<option value="minimal">最低(minimal)</option><option value="low">低(low)</option>
|
||||
<option value="medium">中(medium)</option><option value="high">高(high)</option><option value="xhigh">最高(xhigh)</option>
|
||||
</select>
|
||||
<small>接口需支持所选强度;不支持时会明确报错,可手动选择“由模型默认”。</small>
|
||||
<label for="model-key">API Key <span>{{ keyConfigured() ? '(已配置,留空保留)' : '(尚未配置)' }}</span></label>
|
||||
<input id="model-key" name="apiKey" type="password" [(ngModel)]="apiKey" autocomplete="new-password"
|
||||
placeholder="输入新密钥" [disabled]="busy() || loading()" />
|
||||
<div class="number-fields">
|
||||
<label>请求超时(秒)<input name="timeout" type="number" min="1" max="3600" required
|
||||
[(ngModel)]="timeout" [disabled]="busy() || loading()" /></label>
|
||||
<label>接口重试次数<input name="retries" type="number" min="0" max="10" required
|
||||
<label>失败后重试次数<input name="retries" type="number" min="0" max="10" required
|
||||
[(ngModel)]="retries" [disabled]="busy() || loading()" /></label>
|
||||
<label>重试间隔(秒)<input name="retryInterval" type="number" min="0" max="300" required [(ngModel)]="retryInterval" [disabled]="busy() || loading()" /></label>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button type="submit" [disabled]="busy() || loading() || !valid()">{{ busy() === 'save' ? '正在保存…' : '保存配置' }}</button>
|
||||
@@ -52,9 +63,9 @@ interface ModelSettings {
|
||||
.model-settings { display: grid; gap: 10px; color: #1e293b; }
|
||||
p, small { margin: 0; line-height: 1.6; color: #64748b; }
|
||||
label { font-weight: 600; } label span { font-weight: 400; font-size: 12px; }
|
||||
input { box-sizing: border-box; width: 100%; padding: 12px; border-radius: 10px; border: 1px solid #64748b66;
|
||||
input, select { box-sizing: border-box; width: 100%; padding: 12px; border-radius: 10px; border: 1px solid #64748b66;
|
||||
background: #f8fafc; color: inherit; font: inherit; }
|
||||
input:focus { outline: 2px solid #38bdf8; }
|
||||
input:focus, select:focus { outline: 2px solid #38bdf8; }
|
||||
.number-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 8px; }
|
||||
.number-fields input { margin-top: 8px; }
|
||||
.actions { display: flex; gap: 12px; margin-top: 8px; }
|
||||
@@ -66,7 +77,7 @@ interface ModelSettings {
|
||||
export class ModelSettingsComponent implements OnInit {
|
||||
private http = inject(HttpClient);
|
||||
saved = output<void>();
|
||||
baseUrl = ''; model = ''; apiKey = ''; timeout = 120; retries = 0;
|
||||
baseUrl = ''; model = ''; apiKey = ''; timeout = 300; retries = 5; retryInterval = 10; reasoning = 'high';
|
||||
busy = signal<'save' | 'test' | null>(null);
|
||||
loading = signal(true); keyConfigured = signal(false); envPath = signal('');
|
||||
message = signal(''); error = signal('');
|
||||
@@ -79,15 +90,15 @@ export class ModelSettingsComponent implements OnInit {
|
||||
}
|
||||
valid(): boolean {
|
||||
return !!this.baseUrl.trim() && !!this.model.trim() && (!!this.apiKey.trim() || this.keyConfigured())
|
||||
&& this.timeout > 0 && this.timeout <= 3600 && Number.isInteger(this.retries) && this.retries >= 0 && this.retries <= 10;
|
||||
&& this.timeout > 0 && this.timeout <= 3600 && Number.isInteger(this.retries) && this.retries >= 0 && this.retries <= 10 && this.retryInterval >= 0 && this.retryInterval <= 300;
|
||||
}
|
||||
private payload() {
|
||||
return { base_url: this.baseUrl.trim(), model: this.model.trim(), api_key: this.apiKey.trim() || undefined,
|
||||
timeout_seconds: this.timeout, max_retries: this.retries };
|
||||
timeout_seconds: this.timeout, max_retries: this.retries, retry_interval_seconds: this.retryInterval, reasoning_effort: this.reasoning };
|
||||
}
|
||||
private apply(config: ModelSettings): void {
|
||||
this.baseUrl = config.base_url; this.model = config.model; this.timeout = config.timeout_seconds;
|
||||
this.retries = config.max_retries; this.keyConfigured.set(config.api_key_configured); this.envPath.set(config.env_path);
|
||||
this.retries = config.max_retries; this.retryInterval = config.retry_interval_seconds ?? 10; this.reasoning = config.reasoning_effort ?? 'high'; this.keyConfigured.set(config.api_key_configured); this.envPath.set(config.env_path);
|
||||
}
|
||||
save(): void {
|
||||
if (this.busy() || !this.valid()) return;
|
||||
|
||||
Reference in new issue
Block a user