@shawnstack/quickforge 1.5.6 → 1.6.2
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 +450 -450
- package/dist/assets/{AgentProfilesPage-DFUA4KiP.js → AgentProfilesPage-wpt1cJV0.js} +1 -1
- package/dist/assets/{ChatPanelHost-CBoFtBvB.js → ChatPanelHost-CnQoAfxW.js} +2 -2
- package/dist/assets/{PluginsPage-CKOP-P02.js → PluginsPage-0wwQydcP.js} +1 -1
- package/dist/assets/ScheduledTasksPage-qGHyGkjw.js +2 -0
- package/dist/assets/{SettingsWorkspacePage-Csr6xu0M.js → SettingsWorkspacePage-CeYg_VJl.js} +306 -306
- package/dist/assets/{SharedConversationPage-7I9MiMcj.js → SharedConversationPage-D97o9Ycp.js} +1 -1
- package/dist/assets/TerminalDock-D4zLoahb.js +2 -0
- package/dist/assets/WorkspaceInspector-Bn-am8g6.js +3 -0
- package/dist/assets/{WorkspaceReaderDialog-Dli8GgAq.js → WorkspaceReaderDialog-B2WEMVuF.js} +1 -1
- package/dist/assets/{diff-line-counts-Dvz3MNk2.js → diff-line-counts-B60LmPZX.js} +1 -1
- package/dist/assets/{icons-DXrzz0RO.js → icons-BlAm_pUr.js} +1 -1
- package/dist/assets/{index-BDNDRaPf.css → index-C3bhHGO4.css} +1 -1
- package/dist/assets/index-C_DXqhW8.js +69 -0
- package/dist/assets/{mcp-servers-dialog-DXR3fnZY.js → mcp-servers-dialog-DEyq3gmP.js} +3 -3
- package/dist/assets/{monaco-k8av2MY0.js → monaco-C5Lhy6-h.js} +1 -1
- package/dist/assets/{react-vendor-xMa3TUTb.js → react-vendor--m65aOgw.js} +1 -1
- package/dist/assets/{skills-dialog-Dax-_Ze5.js → skills-dialog-CZ3CuVtQ.js} +1 -1
- package/dist/assets/{useAppTheme-BzB8Q6AC.js → useAppTheme-ChXh3B2c.js} +1 -1
- package/dist/index.html +6 -6
- package/package.json +4 -1
- package/dist/assets/ScheduledTasksPage-CRPvyfmE.js +0 -2
- package/dist/assets/TerminalDock-DWZAOy7v.js +0 -2
- package/dist/assets/WorkspaceInspector-D4k8zQ4s.js +0 -3
- package/dist/assets/index-BIslkXQt.js +0 -69
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/AgentProfilesPage-
|
|
2
|
-
import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/AgentProfilesPage-wpt1cJV0.js","assets/rolldown-runtime-DWdDZTNf.js","assets/index-C_DXqhW8.js","assets/pi-ai-Cx633yhb.js","assets/pi-web-ui-DFNE2m5b.js","assets/lit-vendor-Dr3cpBGF.js","assets/css-utils-rkE68RDy.js","assets/icons-BlAm_pUr.js","assets/react-vendor--m65aOgw.js","assets/skills-dialog-CZ3CuVtQ.js","assets/logger-B65Akg8A.js","assets/index-C3bhHGO4.css","assets/mcp-servers-dialog-DEyq3gmP.js","assets/PluginsPage-0wwQydcP.js","assets/plugin-api-UKg_cgSG.js","assets/ScheduledTasksPage-qGHyGkjw.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,B as n,Dt as r,Mt as i,Ot as a,Tt as o,U as s,b as c,dt as l,f as ee,h as te,k as ne,kt as re,l as ie,ot as ae,s as oe,st as se,z as ce}from"./icons-BlAm_pUr.js";import{n as le,r as ue}from"./react-vendor--m65aOgw.js";import{p as u}from"./lit-vendor-Dr3cpBGF.js";import{a as d,u as f}from"./pi-web-ui-DFNE2m5b.js";import{y as p}from"./pi-ai-Cx633yhb.js";import{t as m}from"./logger-B65Akg8A.js";import{$ as de,A as fe,C as h,D as pe,E as g,G as me,H as _,J as he,M as v,S as y,T as ge,U as _e,V as b,X as ve,Y as x,_ as S,b as ye,et as C,g as be,it as w,j as T,k as xe,nt as Se,q as Ce,rt as E,tt as we,v as Te,w as Ee,x as De,y as Oe}from"./index-C_DXqhW8.js";var D=e(i(),1),ke={openai:{name:`OpenAI`,baseUrl:`https://api.openai.com/v1`,protocol:`openai-completions`,modelId:`gpt-4o`},deepseek:{name:`DeepSeek`,baseUrl:`https://api.deepseek.com/v1`,protocol:`openai-completions`,modelId:`deepseek-chat`},glm:{name:`Zhipu GLM`,baseUrl:`https://open.bigmodel.cn/api/paas/v4`,protocol:`openai-completions`,modelId:`glm-4-plus`},ollama:{name:`Ollama`,baseUrl:`http://localhost:11434/v1`,protocol:`openai-completions`,modelId:`llama3.1`},litellm:{name:b.name,baseUrl:b.baseUrl,protocol:`openai-completions`,modelId:b.modelId}},Ae=[{key:`openai`,label:w(`presetOpenai`)},{key:`deepseek`,label:w(`presetDeepseek`)},{key:`glm`,label:w(`presetGlm`)},{key:`ollama`,label:w(`presetOllama`)},{key:`litellm`,label:w(`presetLitellm`)},{key:`custom`,label:w(`presetCustom`)}],O=()=>({modelId:``,contextWindow:b.contextWindow,maxTokens:b.maxTokens,reasoning:!0,open:!1}),k=()=>({name:b.name,baseUrl:b.baseUrl,apiKey:``,headerRows:[],protocol:`openai-completions`,models:[O()]}),je=class extends d{providers=[];form=k();editingProviderId;formOpen=!1;loading=!0;apiKeyVisible=!1;advancedOpen=!1;activePreset=``;testing=!1;testResult=`idle`;testError=``;autoEditProviderName=null;async connectedCallback(){if(super.connectedCallback(),await this.loadProviders(),this.autoEditProviderName){let e=this.providers.find(e=>e.name===this.autoEditProviderName);e&&await this.openEditForm(e),this.autoEditProviderName=null}}getTabName(){return w(`customModels`)}async loadProviders(){this.loading=!0,this.requestUpdate();try{this.providers=await f().customProviders.getAll()}catch(e){m.error(`Failed to load custom providers:`,e),this.providers=[]}finally{this.loading=!1,this.requestUpdate()}}resetTestState(){this.testing=!1,this.testResult=`idle`,this.testError=``}openAddForm(){this.editingProviderId=void 0,this.form=k(),this.apiKeyVisible=!1,this.advancedOpen=!1,this.activePreset=``,this.resetTestState(),this.formOpen=!0,this.requestUpdate()}async openEditForm(e){let t=await f().providerKeys.get(e.name)??e.apiKey??``,n=e.models??[],r=n.length>0?n.map(e=>({modelId:e.id,contextWindow:e.contextWindow??b.contextWindow,maxTokens:e.maxTokens??b.maxTokens,reasoning:e.reasoning===!0,open:!1})):[O()],i=n[0]?.headers??{},a=Object.entries(i).map(([e,t])=>({key:e,value:String(t)}));this.editingProviderId=e.id,this.form={providerId:e.id,id:e.id,name:e.name,baseUrl:e.baseUrl,apiKey:t,headerRows:a,protocol:e.type===`anthropic-messages`?`anthropic-messages`:`openai-completions`,models:r},this.apiKeyVisible=!1,this.advancedOpen=a.length>0||e.type===`anthropic-messages`,this.activePreset=``,this.resetTestState(),this.formOpen=!0,this.requestUpdate()}closeForm(){this.formOpen=!1,this.editingProviderId=void 0,this.form=k(),this.apiKeyVisible=!1,this.advancedOpen=!1,this.activePreset=``,this.resetTestState(),this.requestUpdate()}toggleApiKeyVisibility(){this.apiKeyVisible=!this.apiKeyVisible,this.requestUpdate()}updateForm(e,t){this.form={...this.form,[e]:t},(e===`name`||e===`baseUrl`)&&(this.activePreset=``),this.resetTestState(),this.requestUpdate()}updateModelField(e,t,n){let r=this.form.models.map((r,i)=>i===e?{...r,[t]:n}:r);this.form={...this.form,models:r},t===`modelId`&&(this.activePreset=``,this.resetTestState()),this.requestUpdate()}addModelRow(){this.form={...this.form,models:[...this.form.models,O()]},this.requestUpdate()}removeModelRow(e){let t=this.form.models.filter((t,n)=>n!==e);this.form={...this.form,models:t},this.requestUpdate()}toggleModelExpanded(e){let t=this.form.models.map((t,n)=>n===e?{...t,open:!t.open}:t);this.form={...this.form,models:t},this.requestUpdate()}addHeaderRow(){this.form={...this.form,headerRows:[...this.form.headerRows,{key:``,value:``}]},this.requestUpdate()}updateHeaderRow(e,t,n){let r=this.form.headerRows.map((r,i)=>i===e?{...r,[t]:n}:r);this.form={...this.form,headerRows:r},this.requestUpdate()}removeHeaderRow(e){let t=this.form.headerRows.filter((t,n)=>n!==e);this.form={...this.form,headerRows:t},this.requestUpdate()}applyPreset(e){if(this.activePreset=e,e===`custom`)this.form={...this.form,name:``,baseUrl:``,protocol:`openai-completions`,models:[O()]};else{let t=ke[e];this.form={...this.form,name:t.name,baseUrl:t.baseUrl,protocol:t.protocol,models:[{...O(),modelId:t.modelId,open:!1}]}}this.resetTestState(),this.requestUpdate()}buildHeadersFromRows(){let e={};for(let t of this.form.headerRows){let n=t.key.trim(),r=t.value.trim();n&&r&&(e[n]=r)}return e}buildModel(e,t){let n=this.form.name.trim(),r=this.form.baseUrl.trim(),i=e.reasoning===!0,a=r.includes(`api.deepseek.com`);return Ce({id:e.modelId,name:`${e.modelId} (${n})`,api:this.form.protocol,provider:n,baseUrl:r.replace(/\/$/,``),reasoning:i,input:[`text`,`image`],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:Number(e.contextWindow)||b.contextWindow,maxTokens:Number(e.maxTokens)||b.maxTokens,headers:Object.keys(t).length>0?t:void 0,thinkingLevelMap:a&&i?{low:`high`,medium:`high`,high:`high`,xhigh:`max`}:void 0,compat:this.form.protocol===`openai-completions`?{supportsStore:!1,supportsDeveloperRole:!1,supportsReasoningEffort:i,supportsUsageInStreaming:!1,supportsStrictMode:!1,maxTokensField:`max_tokens`,...a&&i?{requiresReasoningContentOnAssistantMessages:!0,thinkingFormat:`deepseek`}:{}}:void 0})}async testConnection(){let e=this.form.baseUrl.trim(),t=this.form.models.find(e=>e.modelId.trim());if(!e||!t){this.testing=!1,this.testResult=`fail`,this.testError=w(`testRequiresFields`),this.requestUpdate();return}let n=this.buildHeadersFromRows(),r=this.buildModel(t,n);this.testing=!0,this.testResult=`idle`,this.testError=``,this.requestUpdate();try{let e=await(await fetch(`/api/models/test-connection`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({model:r,apiKey:this.form.apiKey.trim()})})).json().catch(()=>({}));e?.ok?(this.testResult=`ok`,this.testError=``):(this.testResult=`fail`,this.testError=e?.error||w(`connectionFailed`))}catch(e){this.testResult=`fail`,this.testError=e?.message||w(`connectionFailed`)}finally{this.testing=!1,this.requestUpdate()}}async saveModel(){let e=this.form.name.trim(),t=this.form.baseUrl.trim();if(!e||!t){T(w(`fillProviderBaseUrlModel`));return}let n=this.form.models.filter(e=>e.modelId.trim());if(n.length===0){T(w(`atLeastOneModel`));return}let r=n.map(e=>e.modelId.trim());if(new Set(r).size!==r.length){T(w(`duplicateModelId`));return}let i=this.buildHeadersFromRows(),a=n.map(e=>this.buildModel(e,i)),o=this.form.apiKey.trim(),s=this.editingProviderId?this.providers.find(e=>e.id===this.editingProviderId):void 0,c={id:this.editingProviderId??ve(),name:e,type:this.form.protocol,baseUrl:a[0].baseUrl,apiKey:o||void 0,models:a};try{let e=f();await e.customProviders.set(c),s&&s.name!==c.name&&await e.providerKeys.delete(s.name),o?await e.providerKeys.set(c.name,o):await e.providerKeys.delete(c.name),this.closeForm(),await this.loadProviders()}catch(e){m.error(`Failed to save custom model:`,e),T(w(`saveCustomModelFailed`))}}async deleteProvider(e){if(await v({description:w(`confirmDeleteProvider`,{name:e.name}),confirmLabel:w(`confirmDelete`),cancelLabel:w(`cancel`),variant:`destructive`}))try{let t=f();await t.customProviders.delete(e.id),await t.providerKeys.delete(e.name),await this.loadProviders()}catch(e){m.error(`Failed to delete custom provider:`,e),T(w(`deleteFailed`))}}renderProvider(e){let t=e.models??[],n=t.length;return u`
|
|
3
3
|
<div class="rounded-lg border border-border p-4">
|
|
4
4
|
<div class="flex items-start justify-between gap-4">
|
|
5
5
|
<div class="min-w-0 flex-1">
|
|
6
6
|
<div class="text-sm font-medium text-foreground">${e.name}</div>
|
|
7
7
|
<div class="mt-1 break-all text-xs text-muted-foreground">${e.baseUrl}</div>
|
|
8
8
|
<div class="mt-2 text-xs text-muted-foreground">
|
|
9
|
-
${
|
|
9
|
+
${w(`providerProtocol`)}: ${e.type===`anthropic-messages`?`Anthropic Messages`:`OpenAI Compatible`}
|
|
10
10
|
</div>
|
|
11
|
-
${n===0?
|
|
12
|
-
<div class="mt-2 text-xs text-muted-foreground">${
|
|
11
|
+
${n===0?u`<div class="mt-1 text-xs text-muted-foreground">${w(`noModelAdded`)}</div>`:u`
|
|
12
|
+
<div class="mt-2 text-xs text-muted-foreground">${w(`modelsCount`,{count:n})}</div>
|
|
13
13
|
<div class="mt-1 flex flex-wrap gap-1">
|
|
14
|
-
${t.map(e=>
|
|
14
|
+
${t.map(e=>u`
|
|
15
15
|
<span class="inline-flex items-center gap-1 rounded-md border border-border bg-muted px-2 py-0.5 text-xs text-foreground">
|
|
16
16
|
<span class="font-medium">${e.id}</span>
|
|
17
17
|
<span class="text-muted-foreground">${e.contextWindow}/${e.maxTokens}</span>
|
|
@@ -26,23 +26,23 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
26
26
|
type="button"
|
|
27
27
|
@click=${()=>this.openEditForm(e)}
|
|
28
28
|
>
|
|
29
|
-
${
|
|
29
|
+
${w(`editModel`)}
|
|
30
30
|
</button>
|
|
31
31
|
<button
|
|
32
32
|
class="rounded-md px-3 py-1.5 text-sm text-destructive hover:bg-secondary"
|
|
33
33
|
type="button"
|
|
34
34
|
@click=${()=>this.deleteProvider(e)}
|
|
35
35
|
>
|
|
36
|
-
${
|
|
36
|
+
${w(`delete`)}
|
|
37
37
|
</button>
|
|
38
38
|
</div>
|
|
39
39
|
</div>
|
|
40
40
|
</div>
|
|
41
|
-
`}renderPresetChips(){return
|
|
41
|
+
`}renderPresetChips(){return u`
|
|
42
42
|
<div class="grid gap-1.5">
|
|
43
|
-
<span class="text-xs text-muted-foreground">${
|
|
43
|
+
<span class="text-xs text-muted-foreground">${w(`presets`)}</span>
|
|
44
44
|
<div class="flex flex-wrap gap-1.5">
|
|
45
|
-
${
|
|
45
|
+
${Ae.map(e=>u`
|
|
46
46
|
<button
|
|
47
47
|
class="rounded-full border px-3 py-1 text-xs ${this.activePreset===e.key?`border-primary bg-primary text-primary-foreground`:`border-border text-muted-foreground hover:border-foreground/40 hover:text-foreground`}"
|
|
48
48
|
type="button"
|
|
@@ -53,13 +53,13 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
53
53
|
`)}
|
|
54
54
|
</div>
|
|
55
55
|
</div>
|
|
56
|
-
`}renderModelRow(e,t){let n=e.open===!0;return
|
|
56
|
+
`}renderModelRow(e,t){let n=e.open===!0;return u`
|
|
57
57
|
<div class="rounded-md border border-border">
|
|
58
58
|
<div class="flex items-center gap-2 p-2">
|
|
59
59
|
<button
|
|
60
60
|
class="shrink-0 inline-flex size-6 items-center justify-center rounded text-xs text-muted-foreground hover:bg-secondary hover:text-foreground"
|
|
61
61
|
type="button"
|
|
62
|
-
title=${
|
|
62
|
+
title=${w(`expandModel`)}
|
|
63
63
|
aria-expanded=${n?`true`:`false`}
|
|
64
64
|
@click=${()=>this.toggleModelExpanded(t)}
|
|
65
65
|
>
|
|
@@ -69,24 +69,24 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
69
69
|
class="min-w-0 flex-1 rounded-md border border-input bg-background px-3 py-1.5 text-sm"
|
|
70
70
|
.value=${e.modelId}
|
|
71
71
|
@input=${e=>this.updateModelField(t,`modelId`,e.target.value)}
|
|
72
|
-
placeholder=${
|
|
72
|
+
placeholder=${w(`modelIdPlaceholder`)}
|
|
73
73
|
/>
|
|
74
|
-
${this.form.models.length>1?
|
|
74
|
+
${this.form.models.length>1?u`
|
|
75
75
|
<button
|
|
76
76
|
class="shrink-0 rounded px-1.5 py-0.5 text-xs text-muted-foreground hover:bg-secondary hover:text-destructive"
|
|
77
77
|
type="button"
|
|
78
|
-
title=${
|
|
78
|
+
title=${w(`delete`)}
|
|
79
79
|
@click=${()=>this.removeModelRow(t)}
|
|
80
80
|
>
|
|
81
81
|
✕
|
|
82
82
|
</button>
|
|
83
83
|
`:``}
|
|
84
84
|
</div>
|
|
85
|
-
${n?
|
|
85
|
+
${n?u`
|
|
86
86
|
<div class="grid gap-3 border-t border-border p-3">
|
|
87
87
|
<div class="grid grid-cols-2 gap-3">
|
|
88
88
|
<label class="grid gap-1 text-xs">
|
|
89
|
-
<span class="text-muted-foreground">${
|
|
89
|
+
<span class="text-muted-foreground">${w(`contextWindow`)}</span>
|
|
90
90
|
<input
|
|
91
91
|
class="rounded-md border border-input bg-background px-3 py-1.5 text-sm"
|
|
92
92
|
.value=${String(e.contextWindow)}
|
|
@@ -95,7 +95,7 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
95
95
|
/>
|
|
96
96
|
</label>
|
|
97
97
|
<label class="grid gap-1 text-xs">
|
|
98
|
-
<span class="text-muted-foreground">${
|
|
98
|
+
<span class="text-muted-foreground">${w(`maxTokens`)}</span>
|
|
99
99
|
<input
|
|
100
100
|
class="rounded-md border border-input bg-background px-3 py-1.5 text-sm"
|
|
101
101
|
.value=${String(e.maxTokens)}
|
|
@@ -111,37 +111,37 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
111
111
|
.checked=${e.reasoning}
|
|
112
112
|
@change=${e=>this.updateModelField(t,`reasoning`,e.target.checked)}
|
|
113
113
|
/>
|
|
114
|
-
<span class="text-muted-foreground">${
|
|
114
|
+
<span class="text-muted-foreground">${w(`reasoningModel`)}</span>
|
|
115
115
|
</label>
|
|
116
116
|
</div>
|
|
117
117
|
`:``}
|
|
118
118
|
</div>
|
|
119
|
-
`}renderHeadersEditor(){return
|
|
119
|
+
`}renderHeadersEditor(){return u`
|
|
120
120
|
<div class="grid gap-1.5">
|
|
121
121
|
<span class="inline-flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
122
|
-
${
|
|
123
|
-
<quickforge-info-tip .label=${
|
|
122
|
+
${w(`customHeaders`)}
|
|
123
|
+
<quickforge-info-tip .label=${w(`customHeadersHelp`)}></quickforge-info-tip>
|
|
124
124
|
</span>
|
|
125
|
-
${this.form.headerRows.length===0?
|
|
125
|
+
${this.form.headerRows.length===0?u``:u`
|
|
126
126
|
<div class="grid gap-2">
|
|
127
|
-
${this.form.headerRows.map((e,t)=>
|
|
127
|
+
${this.form.headerRows.map((e,t)=>u`
|
|
128
128
|
<div class="grid grid-cols-[1fr_1fr_auto] items-center gap-2">
|
|
129
129
|
<input
|
|
130
130
|
class="rounded-md border border-input bg-background px-3 py-1.5 text-sm"
|
|
131
131
|
.value=${e.key}
|
|
132
132
|
@input=${e=>this.updateHeaderRow(t,`key`,e.target.value)}
|
|
133
|
-
placeholder=${
|
|
133
|
+
placeholder=${w(`headerName`)}
|
|
134
134
|
/>
|
|
135
135
|
<input
|
|
136
136
|
class="rounded-md border border-input bg-background px-3 py-1.5 text-sm"
|
|
137
137
|
.value=${e.value}
|
|
138
138
|
@input=${e=>this.updateHeaderRow(t,`value`,e.target.value)}
|
|
139
|
-
placeholder=${
|
|
139
|
+
placeholder=${w(`headerValue`)}
|
|
140
140
|
/>
|
|
141
141
|
<button
|
|
142
142
|
class="shrink-0 rounded px-1.5 py-1.5 text-xs text-muted-foreground hover:bg-secondary hover:text-destructive"
|
|
143
143
|
type="button"
|
|
144
|
-
title=${
|
|
144
|
+
title=${w(`removeHeader`)}
|
|
145
145
|
@click=${()=>this.removeHeaderRow(t)}
|
|
146
146
|
>
|
|
147
147
|
✕
|
|
@@ -155,25 +155,25 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
155
155
|
type="button"
|
|
156
156
|
@click=${()=>this.addHeaderRow()}
|
|
157
157
|
>
|
|
158
|
-
+ ${
|
|
158
|
+
+ ${w(`addHeader`)}
|
|
159
159
|
</button>
|
|
160
160
|
</div>
|
|
161
|
-
`}renderTestStatus(){return this.testResult===`idle`&&!this.testing?
|
|
161
|
+
`}renderTestStatus(){return this.testResult===`idle`&&!this.testing?u``:this.testing?u`<span class="text-xs text-muted-foreground">${w(`testingConnection`)}</span>`:this.testResult===`ok`?u`<span class="text-xs text-green-600">✓ ${w(`connectionOk`)}</span>`:u`<span class="break-all text-xs text-destructive">✗ ${this.testError||w(`connectionFailed`)}</span>`}renderForm(){return u`
|
|
162
162
|
<div class="rounded-lg border border-border p-4">
|
|
163
163
|
<div class="mb-4 text-sm font-semibold text-foreground">
|
|
164
|
-
${this.editingProviderId?
|
|
164
|
+
${this.editingProviderId?w(`editCustomModel`):w(`addCustomModel`)}
|
|
165
165
|
</div>
|
|
166
166
|
|
|
167
167
|
<div class="grid gap-4">
|
|
168
168
|
${this.renderPresetChips()}
|
|
169
169
|
|
|
170
170
|
<label class="grid gap-1.5 text-sm">
|
|
171
|
-
<span class="text-foreground">${
|
|
171
|
+
<span class="text-foreground">${w(`providerName`)}</span>
|
|
172
172
|
<input
|
|
173
173
|
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
174
174
|
.value=${this.form.name}
|
|
175
175
|
@input=${e=>this.updateForm(`name`,e.target.value)}
|
|
176
|
-
placeholder=${
|
|
176
|
+
placeholder=${w(`providerNamePlaceholder`)}
|
|
177
177
|
/>
|
|
178
178
|
</label>
|
|
179
179
|
|
|
@@ -188,37 +188,37 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
188
188
|
</label>
|
|
189
189
|
|
|
190
190
|
<label class="grid gap-1.5 text-sm">
|
|
191
|
-
<span class="text-foreground">${
|
|
191
|
+
<span class="text-foreground">${w(`apiKey`)}</span>
|
|
192
192
|
<div class="relative">
|
|
193
193
|
<input
|
|
194
194
|
class="w-full rounded-md border border-input bg-background px-3 py-2 pr-10 text-sm"
|
|
195
195
|
.value=${this.form.apiKey}
|
|
196
196
|
type=${this.apiKeyVisible?`text`:`password`}
|
|
197
197
|
@input=${e=>this.updateForm(`apiKey`,e.target.value)}
|
|
198
|
-
placeholder=${
|
|
198
|
+
placeholder=${w(`apiKeyPlaceholder`)}
|
|
199
199
|
/>
|
|
200
200
|
<button
|
|
201
201
|
class="absolute inset-y-0 right-0 flex w-10 items-center justify-center rounded-r-md text-muted-foreground hover:text-foreground/85 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
202
202
|
type="button"
|
|
203
|
-
title=${this.apiKeyVisible?
|
|
204
|
-
aria-label=${this.apiKeyVisible?
|
|
203
|
+
title=${this.apiKeyVisible?w(`hideApiKey`):w(`showApiKey`)}
|
|
204
|
+
aria-label=${this.apiKeyVisible?w(`hideApiKey`):w(`showApiKey`)}
|
|
205
205
|
aria-pressed=${this.apiKeyVisible?`true`:`false`}
|
|
206
206
|
@click=${()=>this.toggleApiKeyVisibility()}
|
|
207
207
|
>
|
|
208
|
-
${this.apiKeyVisible?
|
|
208
|
+
${this.apiKeyVisible?u`<svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.53 13.53 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" y1="2" x2="22" y2="22"/><path d="M8.53 8.53A5 5 0 0 0 12 17a5 5 0 0 0 3.47-8.53"/></svg>`:u`<svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>`}
|
|
209
209
|
</button>
|
|
210
210
|
</div>
|
|
211
211
|
</label>
|
|
212
212
|
|
|
213
213
|
<div class="grid gap-2">
|
|
214
214
|
<div class="flex items-center justify-between">
|
|
215
|
-
<span class="text-sm font-medium text-foreground">${
|
|
215
|
+
<span class="text-sm font-medium text-foreground">${w(`modelsList`)}</span>
|
|
216
216
|
<button
|
|
217
217
|
class="rounded-md px-2 py-1 text-xs hover:bg-secondary"
|
|
218
218
|
type="button"
|
|
219
219
|
@click=${()=>this.addModelRow()}
|
|
220
220
|
>
|
|
221
|
-
+ ${
|
|
221
|
+
+ ${w(`addModel`)}
|
|
222
222
|
</button>
|
|
223
223
|
</div>
|
|
224
224
|
${this.form.models.map((e,t)=>this.renderModelRow(e,t))}
|
|
@@ -231,15 +231,15 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
231
231
|
@click=${()=>{this.advancedOpen=!this.advancedOpen,this.requestUpdate()}}
|
|
232
232
|
>
|
|
233
233
|
<span>${this.advancedOpen?`▾`:`▸`}</span>
|
|
234
|
-
${
|
|
234
|
+
${w(`providerAdvanced`)}
|
|
235
235
|
</button>
|
|
236
236
|
|
|
237
|
-
${this.advancedOpen?
|
|
237
|
+
${this.advancedOpen?u`
|
|
238
238
|
<div class="grid gap-4 rounded-md border border-border p-3">
|
|
239
239
|
<label class="grid gap-1.5 text-sm">
|
|
240
240
|
<span class="inline-flex items-center gap-1.5 text-foreground">
|
|
241
|
-
${
|
|
242
|
-
<quickforge-info-tip .label=${
|
|
241
|
+
${w(`protocolType`)}
|
|
242
|
+
<quickforge-info-tip .label=${w(`protocolHelp`)}></quickforge-info-tip>
|
|
243
243
|
</span>
|
|
244
244
|
<select
|
|
245
245
|
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
@@ -262,7 +262,7 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
262
262
|
type="button"
|
|
263
263
|
@click=${()=>this.closeForm()}
|
|
264
264
|
>
|
|
265
|
-
${
|
|
265
|
+
${w(`cancel`)}
|
|
266
266
|
</button>
|
|
267
267
|
<button
|
|
268
268
|
class="rounded-md px-3 py-2 text-sm hover:bg-secondary ${this.testing?`opacity-50 pointer-events-none`:``}"
|
|
@@ -270,24 +270,24 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
270
270
|
?disabled=${this.testing}
|
|
271
271
|
@click=${()=>this.testConnection()}
|
|
272
272
|
>
|
|
273
|
-
${
|
|
273
|
+
${w(`testConnection`)}
|
|
274
274
|
</button>
|
|
275
275
|
<button
|
|
276
276
|
class="rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground"
|
|
277
277
|
type="button"
|
|
278
278
|
@click=${()=>this.saveModel()}
|
|
279
279
|
>
|
|
280
|
-
${
|
|
280
|
+
${w(`save`)}
|
|
281
281
|
</button>
|
|
282
282
|
</div>
|
|
283
283
|
</div>
|
|
284
|
-
`}render(){return
|
|
284
|
+
`}render(){return u`
|
|
285
285
|
<div class="flex flex-col gap-6">
|
|
286
286
|
<div class="flex items-center justify-between gap-4">
|
|
287
287
|
<div>
|
|
288
288
|
<h3 class="mb-2 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
289
|
-
${
|
|
290
|
-
<quickforge-info-tip .label=${
|
|
289
|
+
${w(`customModelsTitle`)}
|
|
290
|
+
<quickforge-info-tip .label=${w(`customModelsDescription`)}></quickforge-info-tip>
|
|
291
291
|
</h3>
|
|
292
292
|
</div>
|
|
293
293
|
<button
|
|
@@ -295,32 +295,32 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
295
295
|
type="button"
|
|
296
296
|
@click=${()=>this.openAddForm()}
|
|
297
297
|
>
|
|
298
|
-
${
|
|
298
|
+
${w(`addModel`)}
|
|
299
299
|
</button>
|
|
300
300
|
</div>
|
|
301
301
|
|
|
302
302
|
${this.formOpen?this.renderForm():``}
|
|
303
303
|
|
|
304
|
-
${this.loading?
|
|
304
|
+
${this.loading?u`<div class="py-8 text-center text-sm text-muted-foreground">${w(`loading`)}</div>`:this.providers.length===0?u`<div class="py-8 text-center text-sm text-muted-foreground">${w(`noCustomModels`)}</div>`:u`<div class="flex flex-col gap-3">${this.providers.map(e=>this.renderProvider(e))}</div>`}
|
|
305
305
|
</div>
|
|
306
|
-
`}},
|
|
306
|
+
`}},A=`quickforge-custom-providers-only-tab`;customElements.get(A)||customElements.define(A,je);function Me(e){let t=document.createElement(A);return e&&(t.autoEditProviderName=e),t}var Ne=class extends d{selectedLanguage=Se();getTabName(){return w(`language`)}updateLanguage(e){this.selectedLanguage=e===`zh`?`zh`:`en`,this.requestUpdate()}async applyLanguage(){await we(f(),this.selectedLanguage)||T(w(`noLanguageChange`))}render(){return u`
|
|
307
307
|
<div class="flex flex-col gap-6">
|
|
308
308
|
<div>
|
|
309
309
|
<h3 class="mb-2 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
310
|
-
${
|
|
311
|
-
<quickforge-info-tip .label=${
|
|
310
|
+
${w(`language`)}
|
|
311
|
+
<quickforge-info-tip .label=${w(`languageDescription`)}></quickforge-info-tip>
|
|
312
312
|
</h3>
|
|
313
313
|
</div>
|
|
314
314
|
|
|
315
315
|
<label class="grid max-w-sm gap-1.5 text-sm">
|
|
316
|
-
<span class="text-foreground">${
|
|
316
|
+
<span class="text-foreground">${w(`displayLanguage`)}</span>
|
|
317
317
|
<select
|
|
318
318
|
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
319
319
|
.value=${this.selectedLanguage}
|
|
320
320
|
@change=${e=>this.updateLanguage(e.target.value)}
|
|
321
321
|
>
|
|
322
|
-
<option value="zh">${
|
|
323
|
-
<option value="en">${
|
|
322
|
+
<option value="zh">${w(`simplifiedChinese`)}</option>
|
|
323
|
+
<option value="en">${w(`english`)}</option>
|
|
324
324
|
</select>
|
|
325
325
|
</label>
|
|
326
326
|
|
|
@@ -330,11 +330,11 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
330
330
|
type="button"
|
|
331
331
|
@click=${()=>this.applyLanguage()}
|
|
332
332
|
>
|
|
333
|
-
${
|
|
333
|
+
${w(`apply`)}
|
|
334
334
|
</button>
|
|
335
335
|
</div>
|
|
336
336
|
</div>
|
|
337
|
-
`}},
|
|
337
|
+
`}},j=`quickforge-language-settings-tab`;customElements.get(j)||customElements.define(j,Ne);function Pe(){return document.createElement(j)}var Fe=[{value:`light`,label:()=>w(`lightTheme`)},{value:`dark`,label:()=>w(`darkTheme`)}],Ie=class extends d{theme=Oe();interfaceFontSizePx=y.interfaceFontSizePx;messageFontSizePx=y.messageFontSizePx;loading=!0;error=``;getTabName(){return w(`appearance`)}async connectedCallback(){super.connectedCallback(),await this.loadSettings()}async loadSettings(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=f(),[t,n]=await Promise.all([ye(e),ge(e)]);this.theme=t.theme,this.interfaceFontSizePx=n.interfaceFontSizePx,this.messageFontSizePx=n.messageFontSizePx}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}async selectTheme(e){if(this.theme!==e){this.theme=e,this.requestUpdate();try{await De(f(),{theme:e}),this.error=``,this.requestUpdate()}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`),this.requestUpdate()}}}currentFontSizeSettings(){return g({interfaceFontSizePx:this.interfaceFontSizePx,messageFontSizePx:this.messageFontSizePx})}previewFontSize(e){let t=g(e);this.interfaceFontSizePx=t.interfaceFontSizePx,this.messageFontSizePx=t.messageFontSizePx,Ee(t),this.requestUpdate()}updateInterfaceFontSize(e){this.previewFontSize({...this.currentFontSizeSettings(),interfaceFontSizePx:Number(e)||y.interfaceFontSizePx})}updateMessageFontSize(e){this.previewFontSize({...this.currentFontSizeSettings(),messageFontSizePx:Number(e)||y.messageFontSizePx})}async saveFontSize(){try{await pe(f(),this.currentFontSizeSettings()),this.error=``,this.requestUpdate()}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`),this.requestUpdate()}}renderThemeOption(e){let t=this.theme===e.value,n=e.value===`dark`;return u`
|
|
338
338
|
<button
|
|
339
339
|
type="button"
|
|
340
340
|
class="group flex flex-col gap-2 rounded-lg border p-3 text-left transition-colors ${t?`border-primary ring-1 ring-primary`:`border-border hover:border-foreground/30`}"
|
|
@@ -355,7 +355,7 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
355
355
|
<span
|
|
356
356
|
class="flex size-4 items-center justify-center rounded-full border ${t?`border-primary bg-primary`:`border-muted-foreground/40`}"
|
|
357
357
|
>
|
|
358
|
-
${t?
|
|
358
|
+
${t?u`<svg class="size-3 text-primary-foreground" viewBox="0 0 12 12" fill="none">
|
|
359
359
|
<path
|
|
360
360
|
d="M2.5 6l2.5 2.5 4.5-5"
|
|
361
361
|
stroke="currentColor"
|
|
@@ -367,12 +367,12 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
367
367
|
</span>
|
|
368
368
|
</div>
|
|
369
369
|
</button>
|
|
370
|
-
`}getFontSizeRangeProgress(e){return(e-
|
|
370
|
+
`}getFontSizeRangeProgress(e){return(e-h.min)/(h.max-h.min)*100}renderFontSizeSlider(e,t,n,r){return u`
|
|
371
371
|
<label class="grid gap-2 text-sm">
|
|
372
372
|
<div class="flex items-center justify-between gap-3">
|
|
373
373
|
<span class="inline-flex items-center gap-1.5 text-foreground">
|
|
374
374
|
${e}
|
|
375
|
-
${t?
|
|
375
|
+
${t?u`<quickforge-info-tip .label=${t}></quickforge-info-tip>`:null}
|
|
376
376
|
</span>
|
|
377
377
|
<span class="rounded-md bg-muted px-2 py-0.5 font-mono text-xs text-foreground">${n}px</span>
|
|
378
378
|
</div>
|
|
@@ -380,79 +380,79 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
380
380
|
class="quickforge-font-size-slider w-full"
|
|
381
381
|
style=${`--quickforge-font-size-slider-progress: ${this.getFontSizeRangeProgress(n)}%`}
|
|
382
382
|
type="range"
|
|
383
|
-
min=${String(
|
|
384
|
-
max=${String(
|
|
383
|
+
min=${String(h.min)}
|
|
384
|
+
max=${String(h.max)}
|
|
385
385
|
step="1"
|
|
386
386
|
.value=${String(n)}
|
|
387
387
|
@input=${e=>r(e.target.value)}
|
|
388
388
|
@change=${()=>this.saveFontSize()}
|
|
389
389
|
/>
|
|
390
390
|
<div class="flex justify-between text-xs text-muted-foreground">
|
|
391
|
-
<span>${
|
|
392
|
-
<span>${
|
|
391
|
+
<span>${h.min}px</span>
|
|
392
|
+
<span>${h.max}px</span>
|
|
393
393
|
</div>
|
|
394
394
|
</label>
|
|
395
|
-
`}render(){return this.loading?
|
|
395
|
+
`}render(){return this.loading?u`<div class="text-sm text-muted-foreground">${w(`loading`)}</div>`:u`
|
|
396
396
|
<div class="flex flex-col gap-6">
|
|
397
397
|
<div>
|
|
398
398
|
<h3 class="mb-2 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
399
|
-
${
|
|
400
|
-
<quickforge-info-tip .label=${
|
|
399
|
+
${w(`appearance`)}
|
|
400
|
+
<quickforge-info-tip .label=${w(`appearanceDescription`)}></quickforge-info-tip>
|
|
401
401
|
</h3>
|
|
402
402
|
</div>
|
|
403
403
|
|
|
404
404
|
<div class="grid max-w-xl gap-3 rounded-lg border border-border p-4">
|
|
405
405
|
<div>
|
|
406
406
|
<h4 class="inline-flex items-center gap-1.5 text-sm font-medium text-foreground">
|
|
407
|
-
${
|
|
408
|
-
<quickforge-info-tip .label=${
|
|
407
|
+
${w(`theme`)}
|
|
408
|
+
<quickforge-info-tip .label=${w(`themeDescription`)}></quickforge-info-tip>
|
|
409
409
|
</h4>
|
|
410
410
|
</div>
|
|
411
411
|
<div class="grid grid-cols-2 gap-3">
|
|
412
|
-
${
|
|
412
|
+
${Fe.map(e=>this.renderThemeOption(e))}
|
|
413
413
|
</div>
|
|
414
414
|
</div>
|
|
415
415
|
|
|
416
416
|
<div class="grid max-w-xl gap-4 rounded-lg border border-border p-4">
|
|
417
417
|
<div>
|
|
418
418
|
<h4 class="inline-flex items-center gap-1.5 text-sm font-medium text-foreground">
|
|
419
|
-
${
|
|
420
|
-
<quickforge-info-tip .label=${
|
|
419
|
+
${w(`fontSize`)}
|
|
420
|
+
<quickforge-info-tip .label=${w(`fontSizeDescription`)}></quickforge-info-tip>
|
|
421
421
|
</h4>
|
|
422
422
|
</div>
|
|
423
423
|
|
|
424
|
-
${this.renderFontSizeSlider(
|
|
424
|
+
${this.renderFontSizeSlider(w(`interfaceFontSize`),null,this.interfaceFontSizePx,e=>this.updateInterfaceFontSize(e))}
|
|
425
425
|
|
|
426
|
-
${this.renderFontSizeSlider(
|
|
426
|
+
${this.renderFontSizeSlider(w(`messageFontSize`),w(`messageFontSizeNote`),this.messageFontSizePx,e=>this.updateMessageFontSize(e))}
|
|
427
427
|
</div>
|
|
428
428
|
|
|
429
|
-
${this.error?
|
|
429
|
+
${this.error?u`<span class="text-sm text-destructive">${this.error}</span>`:null}
|
|
430
430
|
</div>
|
|
431
|
-
`}},
|
|
431
|
+
`}},M=`quickforge-appearance-settings-tab`;customElements.get(M)||customElements.define(M,Ie);function Le(){return document.createElement(M)}var N=`auto-compact-settings`,P={enabled:!1,thresholdPercent:80,keepRecentTurns:3,minSourceChars:1600,requireConfirmation:!0};function F(e,t,n,r){let i=Number(e);return Number.isFinite(i)?Math.min(r,Math.max(n,Math.round(i))):t}function I(e){if(!e||typeof e!=`object`)return{...P};let t=e;return{enabled:t.enabled===!0,thresholdPercent:F(t.thresholdPercent,P.thresholdPercent,50,95),keepRecentTurns:F(t.keepRecentTurns,P.keepRecentTurns,1,20),minSourceChars:F(t.minSourceChars,P.minSourceChars,0,2e5),requireConfirmation:t.requireConfirmation!==!1}}async function Re(e){return I(await e.settings.get(N))}async function ze(e,t){await e.settings.set(N,I(t))}var L=[{value:`off`,label:()=>w(`thinkingOff`)},{value:`low`,label:()=>w(`thinkingLow`)},{value:`medium`,label:()=>w(`thinkingMedium`)},{value:`high`,label:()=>w(`thinkingHigh`)},{value:`xhigh`,label:()=>w(`thinkingXHigh`)}];function Be(e){return(e??``).trim().replace(/\/$/,``)}function R(e){return JSON.stringify([e.provider,e.id,e.api,Be(e.baseUrl)])}function Ve(e){return`${e.provider} / ${e.id}`}var He=class extends d{models=[];selectedModel;thinkingLevel=`off`;showToolDetails=!1;expandToolsByDefault=!1;autoCompactEnabled=!1;autoCompactRequireConfirmation=!0;autoCompactThresholdPercent=80;autoCompactThresholdPercentInput=`80`;autoCompactKeepRecentTurns=3;loading=!0;saved=!1;error=``;getTabName(){return w(`defaultOptions`)}async connectedCallback(){super.connectedCallback(),await this.loadSettings()}updated(){this.syncSelectValues()}syncSelectValues(){let e=this.querySelector(`[data-default-model-select]`);e&&this.selectedModel&&(e.value=R(this.selectedModel));let t=this.querySelector(`[data-default-thinking-select]`);t&&(t.value=this.thinkingLevel)}async loadSettings(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=f(),[t,n,r,i]=await Promise.all([_e(e),me(e),xe(e),Re(e)]);this.models=t,this.selectedModel=n.model?t.find(e=>R(e)===R(n.model))??n.model:t[0],this.thinkingLevel=n.thinkingLevel??_(this.selectedModel),this.showToolDetails=r.showToolDetails,this.expandToolsByDefault=r.expandToolsByDefault,this.autoCompactEnabled=i.enabled,this.autoCompactRequireConfirmation=i.requireConfirmation,this.autoCompactThresholdPercent=i.thresholdPercent,this.autoCompactThresholdPercentInput=String(i.thresholdPercent),this.autoCompactKeepRecentTurns=i.keepRecentTurns}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}updateModel(e){let t=this.models.find(t=>R(t)===e);this.selectedModel=t,this.thinkingLevel=_(t),this.saved=!1,this.requestUpdate()}updateThinkingLevel(e){this.thinkingLevel=L.some(t=>t.value===e)?e:`off`,this.saved=!1,this.requestUpdate()}updateShowToolDetails(e){this.showToolDetails=e,this.saved=!1,this.requestUpdate()}updateExpandToolsByDefault(e){this.expandToolsByDefault=e,this.saved=!1,this.requestUpdate()}updateAutoCompactEnabled(e){this.autoCompactEnabled=e,this.saved=!1,this.requestUpdate()}updateAutoCompactRequireConfirmation(e){this.autoCompactRequireConfirmation=e,this.saved=!1,this.requestUpdate()}updateAutoCompactThresholdPercent(e){this.autoCompactThresholdPercentInput=e;let t=Number(e);e!==``&&Number.isFinite(t)&&(this.autoCompactThresholdPercent=t),this.saved=!1,this.requestUpdate()}updateAutoCompactKeepRecentTurns(e){this.autoCompactKeepRecentTurns=Number(e)||3,this.saved=!1,this.requestUpdate()}modelOptions(){if(!this.selectedModel)return this.models;let e=R(this.selectedModel);return this.models.some(t=>R(t)===e)?this.models:[this.selectedModel,...this.models]}async save(){try{let e=this.selectedModel?.reasoning?this.thinkingLevel:`off`;await he(f(),{model:this.selectedModel,thinkingLevel:e}),await fe(f(),{showToolDetails:this.showToolDetails,expandToolsByDefault:this.expandToolsByDefault}),await ze(f(),{enabled:this.autoCompactEnabled,thresholdPercent:this.autoCompactThresholdPercent,keepRecentTurns:this.autoCompactKeepRecentTurns,minSourceChars:1600,requireConfirmation:this.autoCompactRequireConfirmation}),await this.loadSettings(),this.saved=!0,this.error=``,this.requestUpdate()}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`),this.requestUpdate()}}render(){return this.loading?u`<div class="text-sm text-muted-foreground">${w(`loading`)}</div>`:u`
|
|
432
432
|
<div class="flex flex-col gap-6">
|
|
433
433
|
<div>
|
|
434
434
|
<h3 class="mb-2 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
435
|
-
${
|
|
436
|
-
<quickforge-info-tip .label=${
|
|
435
|
+
${w(`defaultOptions`)}
|
|
436
|
+
<quickforge-info-tip .label=${w(`defaultOptionsDescription`)}></quickforge-info-tip>
|
|
437
437
|
</h3>
|
|
438
438
|
</div>
|
|
439
439
|
|
|
440
440
|
<label class="grid max-w-md gap-1.5 text-sm">
|
|
441
|
-
<span class="text-foreground">${
|
|
441
|
+
<span class="text-foreground">${w(`defaultModel`)}</span>
|
|
442
442
|
<select
|
|
443
443
|
data-default-model-select
|
|
444
444
|
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
445
|
-
.value=${this.selectedModel?
|
|
445
|
+
.value=${this.selectedModel?R(this.selectedModel):``}
|
|
446
446
|
@change=${e=>this.updateModel(e.target.value)}
|
|
447
447
|
>
|
|
448
|
-
${this.modelOptions().length===0?
|
|
449
|
-
<option .value=${
|
|
448
|
+
${this.modelOptions().length===0?u`<option value="">${w(`noModelAvailable`)}</option>`:this.modelOptions().map(e=>u`
|
|
449
|
+
<option .value=${R(e)}>${Ve(e)}</option>
|
|
450
450
|
`)}
|
|
451
451
|
</select>
|
|
452
452
|
</label>
|
|
453
453
|
|
|
454
454
|
<label class="grid max-w-sm gap-1.5 text-sm">
|
|
455
|
-
<span class="text-foreground">${
|
|
455
|
+
<span class="text-foreground">${w(`defaultThinkingLevel`)}</span>
|
|
456
456
|
<select
|
|
457
457
|
data-default-thinking-select
|
|
458
458
|
class="rounded-md border border-input bg-background px-3 py-2 text-sm disabled:opacity-60"
|
|
@@ -460,18 +460,18 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
460
460
|
?disabled=${!this.selectedModel?.reasoning}
|
|
461
461
|
@change=${e=>this.updateThinkingLevel(e.target.value)}
|
|
462
462
|
>
|
|
463
|
-
${
|
|
463
|
+
${L.map(e=>u`
|
|
464
464
|
<option .value=${e.value}>${e.label()}</option>
|
|
465
465
|
`)}
|
|
466
466
|
</select>
|
|
467
|
-
${this.selectedModel?.reasoning?null:
|
|
467
|
+
${this.selectedModel?.reasoning?null:u`<span class="text-xs text-muted-foreground">${w(`thinkingRequiresReasoningModel`)}</span>`}
|
|
468
468
|
</label>
|
|
469
469
|
|
|
470
470
|
<div class="grid max-w-xl gap-3 rounded-lg border border-border p-4">
|
|
471
471
|
<div>
|
|
472
472
|
<h4 class="inline-flex items-center gap-1.5 text-sm font-medium text-foreground">
|
|
473
|
-
${
|
|
474
|
-
<quickforge-info-tip .label=${
|
|
473
|
+
${w(`toolDisplay`)}
|
|
474
|
+
<quickforge-info-tip .label=${w(`showToolDetailsDescription`)}></quickforge-info-tip>
|
|
475
475
|
</h4>
|
|
476
476
|
</div>
|
|
477
477
|
<label class="flex items-center gap-2 text-sm text-foreground">
|
|
@@ -481,7 +481,7 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
481
481
|
.checked=${this.showToolDetails}
|
|
482
482
|
@change=${e=>this.updateShowToolDetails(e.target.checked)}
|
|
483
483
|
/>
|
|
484
|
-
<span>${
|
|
484
|
+
<span>${w(`showToolDetails`)}</span>
|
|
485
485
|
</label>
|
|
486
486
|
<label class="flex items-center gap-2 text-sm text-foreground">
|
|
487
487
|
<input
|
|
@@ -490,15 +490,15 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
490
490
|
.checked=${this.expandToolsByDefault}
|
|
491
491
|
@change=${e=>this.updateExpandToolsByDefault(e.target.checked)}
|
|
492
492
|
/>
|
|
493
|
-
<span>${
|
|
493
|
+
<span>${w(`expandToolsByDefault`)}</span>
|
|
494
494
|
</label>
|
|
495
495
|
</div>
|
|
496
496
|
|
|
497
497
|
<div class="grid max-w-xl gap-3 rounded-lg border border-border p-4">
|
|
498
498
|
<div>
|
|
499
499
|
<h4 class="inline-flex items-center gap-1.5 text-sm font-medium text-foreground">
|
|
500
|
-
${
|
|
501
|
-
<quickforge-info-tip .label=${
|
|
500
|
+
${w(`contextManagement`)}
|
|
501
|
+
<quickforge-info-tip .label=${w(`autoCompactDescription`)}></quickforge-info-tip>
|
|
502
502
|
</h4>
|
|
503
503
|
</div>
|
|
504
504
|
<label class="flex items-center gap-2 text-sm text-foreground">
|
|
@@ -509,8 +509,8 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
509
509
|
@change=${e=>this.updateAutoCompactEnabled(e.target.checked)}
|
|
510
510
|
/>
|
|
511
511
|
<span class="inline-flex items-center gap-1.5">
|
|
512
|
-
${
|
|
513
|
-
<quickforge-info-tip .label=${
|
|
512
|
+
${w(`autoCompactEnabled`)}
|
|
513
|
+
<quickforge-info-tip .label=${w(`autoCompactTriggerNote`)}></quickforge-info-tip>
|
|
514
514
|
</span>
|
|
515
515
|
</label>
|
|
516
516
|
<label class="flex items-center gap-2 text-sm text-foreground">
|
|
@@ -521,10 +521,10 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
521
521
|
?disabled=${!this.autoCompactEnabled}
|
|
522
522
|
@change=${e=>this.updateAutoCompactRequireConfirmation(e.target.checked)}
|
|
523
523
|
/>
|
|
524
|
-
<span>${
|
|
524
|
+
<span>${w(`autoCompactRequireConfirmation`)}</span>
|
|
525
525
|
</label>
|
|
526
526
|
<label class="grid max-w-xs gap-1.5 text-sm">
|
|
527
|
-
<span class="text-foreground">${
|
|
527
|
+
<span class="text-foreground">${w(`autoCompactThresholdPercent`)}</span>
|
|
528
528
|
<input
|
|
529
529
|
class="rounded-md border border-input bg-background px-3 py-2 text-sm disabled:opacity-60"
|
|
530
530
|
type="number"
|
|
@@ -538,8 +538,8 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
538
538
|
</label>
|
|
539
539
|
<label class="grid max-w-xs gap-1.5 text-sm">
|
|
540
540
|
<span class="inline-flex items-center gap-1.5 text-foreground">
|
|
541
|
-
${
|
|
542
|
-
<quickforge-info-tip .label=${
|
|
541
|
+
${w(`autoCompactKeepRecentTurns`)}
|
|
542
|
+
<quickforge-info-tip .label=${w(`autoCompactHistoryPreserved`)}></quickforge-info-tip>
|
|
543
543
|
</span>
|
|
544
544
|
<input
|
|
545
545
|
class="rounded-md border border-input bg-background px-3 py-2 text-sm disabled:opacity-60"
|
|
@@ -561,30 +561,30 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
561
561
|
?disabled=${!this.selectedModel}
|
|
562
562
|
@click=${()=>this.save()}
|
|
563
563
|
>
|
|
564
|
-
${
|
|
564
|
+
${w(`saveDefaultOptions`)}
|
|
565
565
|
</button>
|
|
566
|
-
${this.saved?
|
|
567
|
-
${this.error?
|
|
566
|
+
${this.saved?u`<span class="text-sm text-muted-foreground">${w(`defaultOptionsSaved`)}</span>`:null}
|
|
567
|
+
${this.error?u`<span class="text-sm text-destructive">${this.error}</span>`:null}
|
|
568
568
|
</div>
|
|
569
569
|
</div>
|
|
570
|
-
`}},
|
|
570
|
+
`}},z=`quickforge-default-options-settings-tab`;customElements.get(z)||customElements.define(z,He);function Ue(){return document.createElement(z)}var We=`quickforge-backup`,Ge=[{id:`settings`,countKey:`settings`,label:()=>w(`restoreSettings`),description:()=>w(`restoreSettingsDescription`)},{id:`mcp`,countKey:`mcp`,label:()=>w(`restoreMcp`),description:()=>w(`restoreMcpDescription`)},{id:`providerKeys`,countKey:`providerKeys`,label:()=>w(`restoreProviderKeys`),description:()=>w(`restoreProviderKeysDescription`)},{id:`customProviders`,countKey:`customProviders`,label:()=>w(`restoreCustomProviders`),description:()=>w(`restoreCustomProvidersDescription`)},{id:`projects`,countKey:`projects`,label:()=>w(`restoreProjects`),description:()=>w(`restoreProjectsDescription`)},{id:`scheduledTasks`,countKey:`scheduledTasks`,label:()=>w(`restoreScheduledTasks`),description:()=>w(`restoreScheduledTasksDescription`)},{id:`conversations`,countKey:`sessions`,label:()=>w(`restoreConversations`),description:()=>w(`restoreConversationsDescription`)}];function Ke(e,t){let n=new Blob([`${JSON.stringify(t,null,2)}\n`],{type:`application/json`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=e,document.body.appendChild(i),i.click(),i.remove(),URL.revokeObjectURL(r)}function qe(){return new Date().toISOString().replace(/[:.]/g,`-`)}function Je(e){return e?Object.entries(e).map(([e,t])=>`${e}: ${t}`).join(`, `):``}function Ye(e){return Ge.filter(t=>(e.sections?.[t.countKey]??0)>0)}var Xe=class extends d{exportScope=`all`;includeSecrets=!1;busy=!1;message=``;error=``;safetyBackupPath=``;pendingImport=null;getTabName(){return w(`backupRestore`)}setScope(e){this.exportScope=e===`config`||e===`sessions`?e:`all`,this.exportScope===`sessions`&&(this.includeSecrets=!1),this.clearStatus(),this.requestUpdate()}clearStatus(){this.message=``,this.error=``,this.safetyBackupPath=``}setIncludeSecrets(e){this.includeSecrets=e&&this.exportScope!==`sessions`,this.message=``,this.error=``,this.requestUpdate()}async exportBackup(){if(!(this.includeSecrets&&!await v({description:w(`backupExportSecretsConfirm`),confirmLabel:w(`exportBackup`),cancelLabel:w(`cancel`)}))){this.busy=!0,this.clearStatus(),this.requestUpdate();try{let e=new URLSearchParams({scope:this.exportScope,includeSecrets:this.includeSecrets?`1`:`0`}),t=await fetch(`/api/backup/export?${e.toString()}`,{cache:`no-store`}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||w(`backupExportFailed`));let r=this.includeSecrets?`with-secrets`:`no-secrets`;Ke(`${We}-${this.exportScope}-${r}-${qe()}.json`,n),this.message=w(`backupExported`)}catch(e){this.error=e instanceof Error?e.message:w(`backupExportFailed`)}finally{this.busy=!1,this.requestUpdate()}}}async inspectBackup(e){let t=await fetch(`/api/backup/inspect`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(e)}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||w(`backupInspectFailed`));if(!n)throw Error(w(`backupInspectFailed`));return n}async importBackupFromFile(e){this.busy=!0,this.clearStatus(),this.pendingImport=null,this.requestUpdate();try{let t=await e.text(),n=JSON.parse(t),r=await this.inspectBackup(n),i=new Set(Ye(r).map(e=>e.id));this.pendingImport={backup:n,inspect:r,selectedSections:i,mode:`replace`},this.message=w(`backupInspected`)}catch(e){this.error=e instanceof Error?e.message:w(`backupImportFailed`)}finally{this.busy=!1,this.requestUpdate()}}togglePendingSection(e,t){this.pendingImport&&(t?this.pendingImport.selectedSections.add(e):this.pendingImport.selectedSections.delete(e),this.message=``,this.error=``,this.requestUpdate())}setRestoreMode(e){this.pendingImport&&(this.pendingImport.mode=e,this.message=``,this.error=``,this.requestUpdate())}cancelPendingImport(){this.pendingImport=null,this.message=``,this.error=``,this.requestUpdate()}async confirmPendingImport(){if(this.pendingImport){if(this.pendingImport.selectedSections.size===0){this.error=w(`selectAtLeastOneRestoreSection`),this.requestUpdate();return}this.busy=!0,this.clearStatus(),this.requestUpdate();try{let e=await fetch(`/api/backup/import`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({backup:this.pendingImport.backup,sections:[...this.pendingImport.selectedSections],mode:this.pendingImport.mode})}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||w(`backupImportFailed`));let n=Je(t?.summary);this.safetyBackupPath=t?.safetyBackupPath||``,this.pendingImport=null,this.message=n?`${w(`backupImported`)} ${n}`:w(`backupImported`),window.setTimeout(()=>window.location.reload(),1500)}catch(e){this.error=e instanceof Error?e.message:w(`backupImportFailed`)}finally{this.busy=!1,this.requestUpdate()}}}handleFileChange(e){let t=e.target,n=t.files?.[0];t.value=``,n&&this.importBackupFromFile(n)}renderPendingImport(){if(!this.pendingImport)return null;let{inspect:e,selectedSections:t}=this.pendingImport,n=Ye(e);return u`
|
|
571
571
|
<section class="rounded-lg border border-amber-500/30 bg-amber-500/5 p-4">
|
|
572
|
-
<h4 class="text-sm font-semibold text-foreground">${
|
|
572
|
+
<h4 class="text-sm font-semibold text-foreground">${w(`backupInspectTitle`)}</h4>
|
|
573
573
|
<dl class="mt-3 grid gap-1 text-sm text-muted-foreground">
|
|
574
|
-
<div><span class="text-foreground">${
|
|
575
|
-
<div><span class="text-foreground">${
|
|
576
|
-
<div><span class="text-foreground">${
|
|
577
|
-
<div><span class="text-foreground">${
|
|
574
|
+
<div><span class="text-foreground">${w(`backupInspectExportedAt`)}:</span> ${e.exportedAt||`-`}</div>
|
|
575
|
+
<div><span class="text-foreground">${w(`backupInspectVersion`)}:</span> ${e.version??`-`}</div>
|
|
576
|
+
<div><span class="text-foreground">${w(`backupInspectScope`)}:</span> ${e.scope||`-`}</div>
|
|
577
|
+
<div><span class="text-foreground">${w(`backupInspectSecrets`)}:</span> ${e.includeSecrets?w(`yes`):w(`no`)}</div>
|
|
578
578
|
</dl>
|
|
579
579
|
|
|
580
|
-
${e.warnings?.length?
|
|
580
|
+
${e.warnings?.length?u`
|
|
581
581
|
<div class="mt-3 rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-xs text-amber-700 dark:text-amber-300">
|
|
582
|
-
${e.warnings.map(e=>
|
|
582
|
+
${e.warnings.map(e=>u`<div>⚠ ${e}</div>`)}
|
|
583
583
|
</div>
|
|
584
584
|
`:null}
|
|
585
585
|
|
|
586
586
|
<div class="mt-4">
|
|
587
|
-
<div class="text-sm font-medium text-foreground">${
|
|
587
|
+
<div class="text-sm font-medium text-foreground">${w(`restoreMode`)}</div>
|
|
588
588
|
<div class="mt-2 grid gap-2">
|
|
589
589
|
<label class="flex items-start gap-2 rounded-md border border-border bg-background/60 p-3 text-sm ${this.pendingImport.mode===`replace`?`border-primary`:``}">
|
|
590
590
|
<input
|
|
@@ -596,8 +596,8 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
596
596
|
@change=${()=>this.setRestoreMode(`replace`)}
|
|
597
597
|
/>
|
|
598
598
|
<span>
|
|
599
|
-
<span class="block text-foreground">${
|
|
600
|
-
<span class="block text-xs text-muted-foreground">${
|
|
599
|
+
<span class="block text-foreground">${w(`restoreModeReplace`)}</span>
|
|
600
|
+
<span class="block text-xs text-muted-foreground">${w(`restoreModeReplaceDescription`)}</span>
|
|
601
601
|
</span>
|
|
602
602
|
</label>
|
|
603
603
|
<label class="flex items-start gap-2 rounded-md border border-border bg-background/60 p-3 text-sm ${this.pendingImport.mode===`merge`?`border-primary`:``}">
|
|
@@ -610,17 +610,17 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
610
610
|
@change=${()=>this.setRestoreMode(`merge`)}
|
|
611
611
|
/>
|
|
612
612
|
<span>
|
|
613
|
-
<span class="block text-foreground">${
|
|
614
|
-
<span class="block text-xs text-muted-foreground">${
|
|
613
|
+
<span class="block text-foreground">${w(`restoreModeMerge`)}</span>
|
|
614
|
+
<span class="block text-xs text-muted-foreground">${w(`restoreModeMergeDescription`)}</span>
|
|
615
615
|
</span>
|
|
616
616
|
</label>
|
|
617
617
|
</div>
|
|
618
618
|
</div>
|
|
619
619
|
|
|
620
620
|
<div class="mt-4">
|
|
621
|
-
<div class="text-sm font-medium text-foreground">${
|
|
621
|
+
<div class="text-sm font-medium text-foreground">${w(`selectRestoreSections`)}</div>
|
|
622
622
|
<div class="mt-2 grid gap-2">
|
|
623
|
-
${n.map(n=>
|
|
623
|
+
${n.map(n=>u`
|
|
624
624
|
<label class="flex items-start gap-2 rounded-md border border-border bg-background/60 p-3 text-sm">
|
|
625
625
|
<input
|
|
626
626
|
class="mt-1"
|
|
@@ -645,7 +645,7 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
645
645
|
?disabled=${this.busy||t.size===0}
|
|
646
646
|
@click=${()=>this.confirmPendingImport()}
|
|
647
647
|
>
|
|
648
|
-
${this.busy?
|
|
648
|
+
${this.busy?w(`loading`):w(`confirmImportSelected`)}
|
|
649
649
|
</button>
|
|
650
650
|
<button
|
|
651
651
|
class="rounded-md border border-input px-3 py-2 text-sm hover:bg-muted/60 disabled:opacity-60"
|
|
@@ -653,36 +653,36 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
653
653
|
?disabled=${this.busy}
|
|
654
654
|
@click=${()=>this.cancelPendingImport()}
|
|
655
655
|
>
|
|
656
|
-
${
|
|
656
|
+
${w(`cancel`)}
|
|
657
657
|
</button>
|
|
658
658
|
</div>
|
|
659
659
|
</section>
|
|
660
|
-
`}render(){return
|
|
660
|
+
`}render(){return u`
|
|
661
661
|
<div class="flex flex-col gap-6">
|
|
662
662
|
<div>
|
|
663
663
|
<h3 class="mb-2 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
664
|
-
${
|
|
665
|
-
<quickforge-info-tip .label=${
|
|
664
|
+
${w(`backupRestore`)}
|
|
665
|
+
<quickforge-info-tip .label=${w(`backupRestoreDescription`)}></quickforge-info-tip>
|
|
666
666
|
</h3>
|
|
667
667
|
</div>
|
|
668
668
|
|
|
669
669
|
<section class="rounded-lg border border-border p-4">
|
|
670
670
|
<h4 class="inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
671
|
-
${
|
|
672
|
-
<quickforge-info-tip .label=${
|
|
671
|
+
${w(`exportData`)}
|
|
672
|
+
<quickforge-info-tip .label=${w(`exportDataDescription`)}></quickforge-info-tip>
|
|
673
673
|
</h4>
|
|
674
674
|
|
|
675
675
|
<label class="mt-4 grid max-w-sm gap-1.5 text-sm">
|
|
676
|
-
<span class="text-foreground">${
|
|
676
|
+
<span class="text-foreground">${w(`exportScope`)}</span>
|
|
677
677
|
<select
|
|
678
678
|
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
679
679
|
.value=${this.exportScope}
|
|
680
680
|
?disabled=${this.busy}
|
|
681
681
|
@change=${e=>this.setScope(e.target.value)}
|
|
682
682
|
>
|
|
683
|
-
<option value="all">${
|
|
684
|
-
<option value="config">${
|
|
685
|
-
<option value="sessions">${
|
|
683
|
+
<option value="all">${w(`exportScopeAll`)}</option>
|
|
684
|
+
<option value="config">${w(`exportScopeConfig`)}</option>
|
|
685
|
+
<option value="sessions">${w(`exportScopeSessions`)}</option>
|
|
686
686
|
</select>
|
|
687
687
|
</label>
|
|
688
688
|
|
|
@@ -695,8 +695,8 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
695
695
|
@change=${e=>this.setIncludeSecrets(e.target.checked)}
|
|
696
696
|
/>
|
|
697
697
|
<span>
|
|
698
|
-
<span class="block">${
|
|
699
|
-
<span class="block text-xs text-muted-foreground">${
|
|
698
|
+
<span class="block">${w(`includeApiKeys`)}</span>
|
|
699
|
+
<span class="block text-xs text-muted-foreground">${w(`includeApiKeysDescription`)}</span>
|
|
700
700
|
</span>
|
|
701
701
|
</label>
|
|
702
702
|
|
|
@@ -706,14 +706,14 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
706
706
|
?disabled=${this.busy}
|
|
707
707
|
@click=${()=>this.exportBackup()}
|
|
708
708
|
>
|
|
709
|
-
${this.busy?
|
|
709
|
+
${this.busy?w(`loading`):w(`exportBackup`)}
|
|
710
710
|
</button>
|
|
711
711
|
</section>
|
|
712
712
|
|
|
713
713
|
<section class="rounded-lg border border-border p-4">
|
|
714
714
|
<h4 class="inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
715
|
-
${
|
|
716
|
-
<quickforge-info-tip .label=${
|
|
715
|
+
${w(`importData`)}
|
|
716
|
+
<quickforge-info-tip .label=${w(`importDataDescription`)}></quickforge-info-tip>
|
|
717
717
|
</h4>
|
|
718
718
|
|
|
719
719
|
<label class="mt-4 inline-flex cursor-pointer rounded-md border border-input px-3 py-2 text-sm hover:bg-muted/60 ${this.busy?`pointer-events-none opacity-60`:``}">
|
|
@@ -724,22 +724,22 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
724
724
|
?disabled=${this.busy}
|
|
725
725
|
@change=${e=>this.handleFileChange(e)}
|
|
726
726
|
/>
|
|
727
|
-
${
|
|
727
|
+
${w(`importBackup`)}
|
|
728
728
|
</label>
|
|
729
729
|
</section>
|
|
730
730
|
|
|
731
731
|
${this.renderPendingImport()}
|
|
732
|
-
${this.message?
|
|
733
|
-
${this.safetyBackupPath?
|
|
734
|
-
${this.error?
|
|
732
|
+
${this.message?u`<div class="rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-300">${this.message}</div>`:null}
|
|
733
|
+
${this.safetyBackupPath?u`<div class="rounded-md border border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground">${w(`backupSafetyBackupPath`)}: <code>${this.safetyBackupPath}</code></div>`:null}
|
|
734
|
+
${this.error?u`<div class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${this.error}</div>`:null}
|
|
735
735
|
</div>
|
|
736
|
-
`}},
|
|
736
|
+
`}},B=`quickforge-backup-settings-tab`;customElements.get(B)||customElements.define(B,Xe);function Ze(){return document.createElement(B)}function Qe(e){if(!e)return`-`;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString(E())}function $e(e){let t={...e};return delete t.archivedAt,t}function V(){if(!(typeof BroadcastChannel>`u`))try{let e=new BroadcastChannel(`quickforge-sync`);e.postMessage({type:`sessions-changed`,sourceTabId:`archived-conversations-settings-tab`,timestamp:Date.now()}),e.close()}catch{}}var et=class extends d{sessions=[];projects=[];loading=!0;busySessionId=``;query=``;projectFilter=`all`;message=``;error=``;getTabName(){return w(`archivedConversations`)}async connectedCallback(){super.connectedCallback(),await this.loadData()}get projectNameById(){return new Map(this.projects.map(e=>[e.id,e.name]))}async loadData(){this.loading=!0,this.error=``,this.requestUpdate();try{let[e,t]=await Promise.all([fetch(`/api/storage/sessions-metadata/index/lastModified?direction=desc&limit=1000&offset=0&archived=only`,{cache:`no-store`}),fetch(`/api/project`,{cache:`no-store`}).catch(()=>null)]),n=await e.json().catch(()=>null);if(!e.ok)throw Error(n?.error||w(`requestFailed`));if(this.sessions=Array.isArray(n?.values)?n.values:[],t?.ok){let e=await t.json().catch(()=>null);this.projects=Array.isArray(e?.projects)?e.projects:[]}}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}filteredSessions(){let e=this.query.trim().toLowerCase();return this.sessions.filter(t=>{if(this.projectFilter!==`all`&&(this.projectFilter===`global`&&t.scope===`project`||this.projectFilter!==`global`&&t.projectId!==this.projectFilter))return!1;if(!e)return!0;let n=t.projectId&&this.projectNameById.get(t.projectId)||``;return`${x(t.title)} ${n}`.toLowerCase().includes(e)})}groupedSessions(){let e=new Map;for(let t of this.filteredSessions()){let n=t.scope===`project`&&t.projectId?t.projectId:`global`;e.set(n,[...e.get(n)??[],t])}return[...e.entries()]}projectLabel(e){return e===`global`?w(`normalChat`):this.projectNameById.get(e)||w(`unknownProject`)}async restoreSession(e){if(!this.busySessionId){this.busySessionId=e,this.message=``,this.error=``,this.requestUpdate();try{let t=f(),n=await t.sessions.get(e),r=await t.sessions.getMetadata(e);if(!n||!r)throw Error(w(`sessionNotFound`));await t.sessions.save($e(n),$e(r)),this.sessions=this.sessions.filter(t=>t.id!==e),this.message=w(`sessionRestored`),V()}catch(e){this.error=e instanceof Error?e.message:w(`restoreSessionFailed`)}finally{this.busySessionId=``,this.requestUpdate()}}}async deleteSession(e){if(!this.busySessionId&&await v({description:w(`deleteArchivedSessionConfirm`,{title:x(e.title)}),confirmLabel:w(`confirmDelete`),cancelLabel:w(`cancel`),variant:`destructive`})){this.busySessionId=e.id,this.message=``,this.error=``,this.requestUpdate();try{await f().sessions.delete(e.id),this.sessions=this.sessions.filter(t=>t.id!==e.id),this.message=w(`archivedSessionDeleted`),V()}catch(e){this.error=e instanceof Error?e.message:w(`deleteSessionFailed`)}finally{this.busySessionId=``,this.requestUpdate()}}}async deleteAllArchivedSessions(){if(!(this.busySessionId||this.sessions.length===0)&&await v({description:w(`deleteAllArchivedSessionsConfirm`),confirmLabel:w(`confirmDelete`),cancelLabel:w(`cancel`),variant:`destructive`})){this.busySessionId=`__all__`,this.message=``,this.error=``,this.requestUpdate();try{let e=f();await Promise.all(this.sessions.map(t=>e.sessions.delete(t.id))),this.sessions=[],this.message=w(`archivedSessionsDeleted`),V()}catch(e){this.error=e instanceof Error?e.message:w(`deleteSessionFailed`)}finally{this.busySessionId=``,this.requestUpdate()}}}renderSession(e){let t=this.busySessionId===e.id||this.busySessionId===`__all__`;return u`
|
|
737
737
|
<div class="border-t border-border px-4 py-3 first:border-t-0">
|
|
738
738
|
<div class="flex items-start justify-between gap-3">
|
|
739
739
|
<div class="min-w-0">
|
|
740
|
-
<div class="truncate text-sm font-medium text-foreground">${
|
|
740
|
+
<div class="truncate text-sm font-medium text-foreground">${x(e.title)}</div>
|
|
741
741
|
<div class="mt-1 text-xs text-muted-foreground">
|
|
742
|
-
${
|
|
742
|
+
${w(`lastModified`)}: ${Qe(e.lastModified)} · ${w(`archivedAt`)}: ${Qe(e.archivedAt)}
|
|
743
743
|
</div>
|
|
744
744
|
</div>
|
|
745
745
|
<div class="flex shrink-0 items-center gap-2">
|
|
@@ -749,7 +749,7 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
749
749
|
?disabled=${t}
|
|
750
750
|
@click=${()=>this.restoreSession(e.id)}
|
|
751
751
|
>
|
|
752
|
-
${
|
|
752
|
+
${w(`restoreSession`)}
|
|
753
753
|
</button>
|
|
754
754
|
<button
|
|
755
755
|
class="rounded-md px-2.5 py-1 text-xs text-destructive hover:bg-destructive/10 disabled:opacity-60"
|
|
@@ -757,17 +757,17 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
757
757
|
?disabled=${t}
|
|
758
758
|
@click=${()=>this.deleteSession(e)}
|
|
759
759
|
>
|
|
760
|
-
${
|
|
760
|
+
${w(`deletePermanently`)}
|
|
761
761
|
</button>
|
|
762
762
|
</div>
|
|
763
763
|
</div>
|
|
764
764
|
</div>
|
|
765
|
-
`}render(){let e=this.groupedSessions(),t=!!this.busySessionId;return
|
|
765
|
+
`}render(){let e=this.groupedSessions(),t=!!this.busySessionId;return u`
|
|
766
766
|
<div class="flex flex-col gap-4">
|
|
767
767
|
<div class="flex items-center justify-between gap-3">
|
|
768
768
|
<div>
|
|
769
|
-
<h3 class="text-sm font-semibold text-foreground">${
|
|
770
|
-
<p class="mt-1 text-xs text-muted-foreground">${
|
|
769
|
+
<h3 class="text-sm font-semibold text-foreground">${w(`archivedConversations`)}</h3>
|
|
770
|
+
<p class="mt-1 text-xs text-muted-foreground">${w(`archivedConversationsDescription`)}</p>
|
|
771
771
|
</div>
|
|
772
772
|
<button
|
|
773
773
|
class="rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive hover:bg-destructive/15 disabled:opacity-60"
|
|
@@ -775,7 +775,7 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
775
775
|
?disabled=${t||this.sessions.length===0}
|
|
776
776
|
@click=${()=>this.deleteAllArchivedSessions()}
|
|
777
777
|
>
|
|
778
|
-
${
|
|
778
|
+
${w(`deleteAll`)}
|
|
779
779
|
</button>
|
|
780
780
|
</div>
|
|
781
781
|
|
|
@@ -785,7 +785,7 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
785
785
|
class="rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-ring/30"
|
|
786
786
|
type="search"
|
|
787
787
|
.value=${this.query}
|
|
788
|
-
placeholder=${
|
|
788
|
+
placeholder=${w(`searchArchivedConversations`)}
|
|
789
789
|
@input=${e=>{this.query=e.target.value,this.requestUpdate()}}
|
|
790
790
|
/>
|
|
791
791
|
<select
|
|
@@ -793,23 +793,23 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
793
793
|
.value=${this.projectFilter}
|
|
794
794
|
@change=${e=>{this.projectFilter=e.target.value,this.requestUpdate()}}
|
|
795
795
|
>
|
|
796
|
-
<option value="all">${
|
|
797
|
-
<option value="global">${
|
|
798
|
-
${this.projects.map(e=>
|
|
796
|
+
<option value="all">${w(`allProjects`)}</option>
|
|
797
|
+
<option value="global">${w(`normalChat`)}</option>
|
|
798
|
+
${this.projects.map(e=>u`<option value=${e.id}>${e.name}</option>`)}
|
|
799
799
|
</select>
|
|
800
800
|
</div>
|
|
801
801
|
|
|
802
|
-
${this.loading?
|
|
803
|
-
<div class="px-4 py-8 text-center text-sm text-muted-foreground">${
|
|
804
|
-
`:e.length===0?
|
|
805
|
-
<div class="px-4 py-8 text-center text-sm text-muted-foreground">${
|
|
806
|
-
`:
|
|
802
|
+
${this.loading?u`
|
|
803
|
+
<div class="px-4 py-8 text-center text-sm text-muted-foreground">${w(`loading`)}</div>
|
|
804
|
+
`:e.length===0?u`
|
|
805
|
+
<div class="px-4 py-8 text-center text-sm text-muted-foreground">${w(`noArchivedConversations`)}</div>
|
|
806
|
+
`:u`
|
|
807
807
|
<div>
|
|
808
|
-
${e.map(([e,t])=>
|
|
808
|
+
${e.map(([e,t])=>u`
|
|
809
809
|
<div class="border-b border-border last:border-b-0">
|
|
810
810
|
<div class="flex items-center justify-between gap-3 bg-muted/20 px-4 py-2 text-sm text-muted-foreground">
|
|
811
811
|
<div class="truncate">${this.projectLabel(e)}</div>
|
|
812
|
-
<div class="shrink-0">${
|
|
812
|
+
<div class="shrink-0">${w(`conversationCount`,{count:t.length})}</div>
|
|
813
813
|
</div>
|
|
814
814
|
${t.map(e=>this.renderSession(e))}
|
|
815
815
|
</div>
|
|
@@ -818,112 +818,112 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
818
818
|
`}
|
|
819
819
|
</section>
|
|
820
820
|
|
|
821
|
-
${this.message?
|
|
822
|
-
${this.error?
|
|
821
|
+
${this.message?u`<div class="rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-300">${this.message}</div>`:null}
|
|
822
|
+
${this.error?u`<div class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${this.error}</div>`:null}
|
|
823
823
|
</div>
|
|
824
|
-
`}},H=`quickforge-archived-conversations-settings-tab`;customElements.get(H)||customElements.define(H,
|
|
824
|
+
`}},H=`quickforge-archived-conversations-settings-tab`;customElements.get(H)||customElements.define(H,et);function tt(){return document.createElement(H)}var nt=3e4,rt=800;function it(e){return new Promise(t=>window.setTimeout(t,e))}function at(e){if(!e)return`-`;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString(E())}function ot(){return`custom_${globalThis.crypto?.randomUUID?.().slice(0,8)||Date.now().toString(36)}`}function st(e){let t=e.trim(),n=t.split(/[\\/]/).pop()?.replace(/^"|"$/g,``)||t;return/^bash(\.exe)?$/i.test(n)?`Bash`:/^zsh$/i.test(n)?`Zsh`:/^fish$/i.test(n)?`Fish`:/^cmd(\.exe)?$/i.test(n)?`Command Prompt`:/^powershell(\.exe)?$/i.test(n)?`Windows PowerShell`:/^pwsh(\.exe)?$/i.test(n)?`PowerShell 7+`:n||`Custom Shell`}var ct=u`
|
|
825
825
|
<svg class="size-3.5" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
826
826
|
<path d="M3.5 8.2 6.6 11.3 12.7 4.7" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
|
|
827
827
|
</svg>
|
|
828
|
-
`,
|
|
828
|
+
`,lt=u`
|
|
829
829
|
<svg class="size-3.5" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
830
830
|
<circle cx="8" cy="8" r="4.8" stroke="currentColor" stroke-width="1.5" />
|
|
831
831
|
</svg>
|
|
832
|
-
`,
|
|
832
|
+
`,ut=u`
|
|
833
833
|
<svg class="size-3.5" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
834
834
|
<path d="M4.5 4.5 11.5 11.5M11.5 4.5 4.5 11.5" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" />
|
|
835
835
|
</svg>
|
|
836
|
-
`,
|
|
836
|
+
`,dt=class extends d{status;loading=!0;restarting=!1;message=``;error=``;terminalShellConfig={terminalShell:`auto`,defaultProfileId:`auto`,profiles:[]};customShellCommand=``;getTabName(){return w(`backendService`)}async connectedCallback(){super.connectedCallback(),await Promise.all([this.loadStatus(),this.loadTerminalShell()])}customShellProfiles(){return this.terminalShellConfig.profiles.filter(e=>!e.builtin)}async loadTerminalShell(){try{let e=await fetch(`/api/system/terminal-shell`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||w(`requestFailed`));this.terminalShellConfig={terminalShell:t?.terminalShell||`auto`,defaultProfileId:t?.defaultProfileId||`auto`,profiles:Array.isArray(t?.profiles)?t.profiles:[]}}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.requestUpdate()}}async saveTerminalShellConfig(e,t=this.customShellProfiles(),n=w(`terminalShellSaved`)){try{let r=await fetch(`/api/system/terminal-shell`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({defaultProfileId:e,profiles:t})}),i=await r.json().catch(()=>null);if(!r.ok)throw Error(i?.error||w(`requestFailed`));this.terminalShellConfig=i,this.message=n,this.error=``}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.requestUpdate()}}async addCustomTerminalShell(){let e=this.customShellCommand.trim();if(!e){this.error=w(`terminalShellProfileRequired`),this.requestUpdate();return}let t=[...this.customShellProfiles(),{id:ot(),name:st(e),command:e,builtin:!1}];this.customShellCommand=``,await this.saveTerminalShellConfig(this.terminalShellConfig.defaultProfileId,t,w(`terminalShellProfilesSaved`))}async deleteCustomTerminalShell(e){let t=this.terminalShellConfig.profiles.find(t=>t.id===e);if(!t||t.builtin||!await v({description:w(`terminalShellDeleteConfirm`,{name:t.name}),confirmLabel:w(`confirmDelete`),cancelLabel:w(`cancel`),variant:`destructive`}))return;let n=this.customShellProfiles().filter(t=>t.id!==e),r=this.terminalShellConfig.defaultProfileId===e?`auto`:this.terminalShellConfig.defaultProfileId;await this.saveTerminalShellConfig(r,n,w(`terminalShellProfilesSaved`))}async loadStatus(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=await fetch(`/api/health`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||w(`requestFailed`));this.status=t}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}async pollUntilRestarted(e){let t=Date.now();for(;Date.now()-t<nt;){await it(rt);try{let t=await fetch(`/api/health?restartPoll=${Date.now()}`,{cache:`no-store`}),n=await t.json().catch(()=>null);if(t.ok&&n?.ok&&n.bootId&&n.bootId!==e){this.message=w(`backendRestarted`),this.requestUpdate(),window.setTimeout(()=>window.location.reload(),300);return}}catch{}}throw Error(w(`backendRestartTimeout`))}async restartService(){if(!this.status||this.restarting||!await v({description:w(`restartBackendConfirm`),confirmLabel:w(`restartBackendService`),cancelLabel:w(`cancel`)}))return;this.restarting=!0,this.message=w(`backendRestarting`),this.error=``,this.requestUpdate();let e=this.status.bootId;try{let t=await fetch(`/api/system/restart`,{method:`POST`,headers:{"x-quickforge-action":`restart`}}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n?.error||w(`backendRestartFailed`));await this.pollUntilRestarted(e)}catch(e){this.error=e instanceof Error?e.message:w(`backendRestartFailed`),this.message=``,this.restarting=!1,this.requestUpdate()}}statusRows(){return this.status?u`
|
|
837
837
|
<dl class="grid gap-3 text-sm">
|
|
838
|
-
${[[
|
|
838
|
+
${[[w(`serviceMode`),this.status.mode],[w(`servicePid`),String(this.status.pid)],[w(`serviceStartedAt`),at(this.status.startedAt)],[w(`serviceDataDir`),this.status.dataDir],[w(`serviceWorkspace`),this.status.workspaceRoot]].map(([e,t])=>u`
|
|
839
839
|
<div class="grid gap-1 sm:grid-cols-[120px_1fr] sm:gap-3">
|
|
840
840
|
<dt class="text-muted-foreground">${e}</dt>
|
|
841
841
|
<dd class="min-w-0 break-all text-foreground">${t}</dd>
|
|
842
842
|
</div>
|
|
843
843
|
`)}
|
|
844
844
|
</dl>
|
|
845
|
-
`:null}shellProfileRow(e,t=!1){let n=e.id===this.terminalShellConfig.defaultProfileId||this.terminalShellConfig.defaultProfileId===`auto`&&t;return
|
|
845
|
+
`:null}shellProfileRow(e,t=!1){let n=e.id===this.terminalShellConfig.defaultProfileId||this.terminalShellConfig.defaultProfileId===`auto`&&t;return u`
|
|
846
846
|
<div class="flex min-w-0 items-center gap-3 border-b px-1.5 py-2 last:border-b-0 hover:bg-muted/5" style="border-bottom-color: color-mix(in oklab, var(--border) 32%, transparent);">
|
|
847
847
|
<div class="min-w-0 flex-1">
|
|
848
848
|
<div class="truncate text-sm font-medium text-foreground/90">${e.name}</div>
|
|
849
849
|
<div class="truncate font-mono text-xs text-muted-foreground/55" title=${e.command}>${e.command}</div>
|
|
850
850
|
</div>
|
|
851
851
|
<div class="flex shrink-0 items-center gap-1">
|
|
852
|
-
${n?
|
|
853
|
-
<span class="inline-flex size-7 items-center justify-center rounded-md text-emerald-500/85" title=${
|
|
854
|
-
${
|
|
852
|
+
${n?u`
|
|
853
|
+
<span class="inline-flex size-7 items-center justify-center rounded-md text-emerald-500/85" title=${w(`terminalShellDefaultBadge`)} aria-label=${w(`terminalShellDefaultBadge`)}>
|
|
854
|
+
${ct}
|
|
855
855
|
</span>
|
|
856
|
-
`:
|
|
856
|
+
`:u`
|
|
857
857
|
<button
|
|
858
858
|
class="inline-flex size-7 items-center justify-center rounded-md text-muted-foreground/55 hover:bg-muted/20 hover:text-foreground/85"
|
|
859
859
|
type="button"
|
|
860
|
-
title=${
|
|
861
|
-
aria-label=${
|
|
860
|
+
title=${w(`terminalShellSetDefault`)}
|
|
861
|
+
aria-label=${w(`terminalShellSetDefault`)}
|
|
862
862
|
@click=${()=>this.saveTerminalShellConfig(e.id)}
|
|
863
863
|
>
|
|
864
|
-
${
|
|
864
|
+
${lt}
|
|
865
865
|
</button>
|
|
866
866
|
`}
|
|
867
|
-
${e.builtin?null:
|
|
867
|
+
${e.builtin?null:u`
|
|
868
868
|
<button
|
|
869
869
|
class="inline-flex size-7 items-center justify-center rounded-md text-muted-foreground/55 hover:bg-destructive/10 hover:text-destructive"
|
|
870
870
|
type="button"
|
|
871
|
-
title=${
|
|
872
|
-
aria-label=${
|
|
871
|
+
title=${w(`delete`)}
|
|
872
|
+
aria-label=${w(`delete`)}
|
|
873
873
|
@click=${()=>this.deleteCustomTerminalShell(e.id)}
|
|
874
874
|
>
|
|
875
|
-
${
|
|
875
|
+
${ut}
|
|
876
876
|
</button>
|
|
877
877
|
`}
|
|
878
878
|
</div>
|
|
879
879
|
</div>
|
|
880
|
-
`}terminalShellSettings(){let e=this.terminalShellConfig.profiles;return
|
|
880
|
+
`}terminalShellSettings(){let e=this.terminalShellConfig.profiles;return u`
|
|
881
881
|
<section class="rounded-lg border border-border p-4">
|
|
882
882
|
<div>
|
|
883
883
|
<h4 class="inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
884
|
-
${
|
|
885
|
-
<quickforge-info-tip .label=${
|
|
884
|
+
${w(`terminalShell`)}
|
|
885
|
+
<quickforge-info-tip .label=${w(`terminalShellDescription`)}></quickforge-info-tip>
|
|
886
886
|
</h4>
|
|
887
|
-
<p class="mt-1 text-xs text-muted-foreground/60">${
|
|
887
|
+
<p class="mt-1 text-xs text-muted-foreground/60">${w(`terminalShellAutoDetectedHint`)}</p>
|
|
888
888
|
</div>
|
|
889
889
|
|
|
890
890
|
<div class="mt-4 overflow-hidden rounded-lg border bg-transparent" style="border-color: color-mix(in oklab, var(--border) 36%, transparent);">
|
|
891
|
-
${e.length>0?e.map((e,t)=>this.shellProfileRow(e,t===0)):
|
|
891
|
+
${e.length>0?e.map((e,t)=>this.shellProfileRow(e,t===0)):u`<div class="px-2 py-3 text-sm text-muted-foreground">${w(`terminalShellNoDetected`)}</div>`}
|
|
892
892
|
</div>
|
|
893
893
|
|
|
894
894
|
<div class="mt-3 grid gap-2 sm:grid-cols-[1fr_auto] sm:items-end">
|
|
895
895
|
<label class="grid gap-1 text-sm">
|
|
896
|
-
<span class="text-xs text-muted-foreground/70">${
|
|
896
|
+
<span class="text-xs text-muted-foreground/70">${w(`terminalShellCommand`)}</span>
|
|
897
897
|
<input
|
|
898
898
|
class="h-9 rounded-md border border-border bg-background px-3 font-mono text-sm text-foreground outline-none focus:border-ring"
|
|
899
899
|
type="text"
|
|
900
900
|
.value=${this.customShellCommand}
|
|
901
|
-
placeholder=${
|
|
901
|
+
placeholder=${w(`terminalShellCommandPlaceholder`)}
|
|
902
902
|
@input=${e=>{this.customShellCommand=e.target.value}}
|
|
903
903
|
/>
|
|
904
904
|
</label>
|
|
905
905
|
<button
|
|
906
906
|
class="h-9 rounded-md bg-primary px-3 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-60"
|
|
907
907
|
type="button"
|
|
908
|
-
title=${
|
|
909
|
-
aria-label=${
|
|
908
|
+
title=${w(`terminalShellAdd`)}
|
|
909
|
+
aria-label=${w(`terminalShellAdd`)}
|
|
910
910
|
@click=${()=>this.addCustomTerminalShell()}
|
|
911
911
|
>
|
|
912
|
-
${
|
|
912
|
+
${w(`terminalShellAdd`)}
|
|
913
913
|
</button>
|
|
914
914
|
</div>
|
|
915
915
|
</section>
|
|
916
|
-
`}render(){if(this.loading)return
|
|
916
|
+
`}render(){if(this.loading)return u`<div class="text-sm text-muted-foreground">${w(`loading`)}</div>`;let e=this.status?.restartUnsupportedReason||w(`backendRestartUnsupported`),t=this.restarting||!this.status?.restartSupported;return u`
|
|
917
917
|
<div class="flex flex-col gap-6">
|
|
918
918
|
<div>
|
|
919
919
|
<h3 class="mb-2 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
920
|
-
${
|
|
921
|
-
<quickforge-info-tip .label=${
|
|
920
|
+
${w(`backendService`)}
|
|
921
|
+
<quickforge-info-tip .label=${w(`backendServiceDescription`)}></quickforge-info-tip>
|
|
922
922
|
</h3>
|
|
923
923
|
</div>
|
|
924
924
|
|
|
925
925
|
<section class="rounded-lg border border-border p-4">
|
|
926
|
-
<h4 class="text-sm font-semibold text-foreground">${
|
|
926
|
+
<h4 class="text-sm font-semibold text-foreground">${w(`backendServiceStatus`)}</h4>
|
|
927
927
|
<div class="mt-4">${this.statusRows()}</div>
|
|
928
928
|
</section>
|
|
929
929
|
|
|
@@ -931,11 +931,11 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
931
931
|
|
|
932
932
|
<section class="rounded-lg border border-border p-4">
|
|
933
933
|
<h4 class="inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
934
|
-
${
|
|
935
|
-
<quickforge-info-tip .label=${
|
|
934
|
+
${w(`restartBackendService`)}
|
|
935
|
+
<quickforge-info-tip .label=${w(`restartBackendServiceDescription`)}></quickforge-info-tip>
|
|
936
936
|
</h4>
|
|
937
937
|
|
|
938
|
-
${this.status?.restartSupported?null:
|
|
938
|
+
${this.status?.restartSupported?null:u`<div class="mt-4 rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-sm text-amber-700 dark:text-amber-300">${e}</div>`}
|
|
939
939
|
|
|
940
940
|
<button
|
|
941
941
|
class="mt-4 rounded-md bg-destructive px-3 py-2 text-sm text-destructive-foreground disabled:opacity-60"
|
|
@@ -943,44 +943,44 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
943
943
|
?disabled=${t}
|
|
944
944
|
@click=${()=>this.restartService()}
|
|
945
945
|
>
|
|
946
|
-
${this.restarting?
|
|
946
|
+
${this.restarting?w(`backendRestarting`):w(`restartBackendService`)}
|
|
947
947
|
</button>
|
|
948
948
|
</section>
|
|
949
949
|
|
|
950
|
-
${this.message?
|
|
951
|
-
${this.error?
|
|
950
|
+
${this.message?u`<div class="rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-300">${this.message}</div>`:null}
|
|
951
|
+
${this.error?u`<div class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${this.error}</div>`:null}
|
|
952
952
|
</div>
|
|
953
|
-
`}},U=`quickforge-service-settings-tab`;customElements.get(U)||customElements.define(U,
|
|
953
|
+
`}},U=`quickforge-service-settings-tab`;customElements.get(U)||customElements.define(U,dt);function ft(){return document.createElement(U)}function pt(){return Array.from({length:16},()=>`ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!@#$%^&*`[Math.floor(Math.random()*65)]).join(``)}var mt=class extends d{loading=!0;saving=!1;enabled=!1;hasPassword=!1;password=``;sessionTtlHours=12;activeTokenCount=0;lanUrls=[];error=``;message=``;getTabName(){return w(`lanAccess`)}async connectedCallback(){super.connectedCallback(),await this.loadStatus()}async request(e,t){let n=await fetch(e,{...t,cache:`no-store`,headers:{...t?.body?{"content-type":`application/json`}:void 0,...t?.headers}}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||w(`requestFailed`));return r}applyStatus(e){this.enabled=!!e.enabled,this.hasPassword=!!e.hasPassword,this.sessionTtlHours=Number(e.sessionTtlHours||12),this.activeTokenCount=Number(e.activeTokenCount||0),this.lanUrls=Array.isArray(e.lanUrls)?e.lanUrls:[]}async loadStatus(){this.loading=!0,this.error=``,this.requestUpdate();try{this.applyStatus(await this.request(`/api/lan-access/status`))}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}updatePassword(e){this.password=e,this.requestUpdate()}updateEnabled(e){this.enabled=e,this.requestUpdate()}updateTtl(e){this.sessionTtlHours=Number(e)||12,this.requestUpdate()}async saveSettings(){if(!this.saving){if(this.enabled&&!this.hasPassword&&!this.password.trim()){this.error=w(`lanAccessPasswordRequired`),this.requestUpdate();return}if(this.password.trim()&&this.password.trim().length<8){this.error=w(`lanAccessPasswordTooShort`),this.requestUpdate();return}if(!(this.enabled&&!await v({description:w(`lanAccessEnableConfirm`),confirmLabel:w(`enabled`),cancelLabel:w(`cancel`)}))){this.saving=!0,this.error=``,this.message=``,this.requestUpdate();try{let e=await this.request(`/api/lan-access/settings`,{method:`PUT`,body:JSON.stringify({enabled:this.enabled,password:this.password.trim()||void 0,sessionTtlHours:this.sessionTtlHours})});this.applyStatus(e),this.password=``,this.message=w(`lanAccessSaved`)}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}}}async revokeAll(){if(await v({description:w(`lanAccessRevokeAllConfirm`),confirmLabel:w(`lanAccessRevokeAll`),cancelLabel:w(`cancel`),variant:`destructive`})){this.saving=!0,this.error=``,this.message=``,this.requestUpdate();try{let e=await this.request(`/api/lan-access/revoke-all`,{method:`POST`});this.applyStatus(e),this.message=w(`lanAccessRevoked`)}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}}render(){return this.loading?u`<div class="text-sm text-muted-foreground">${w(`loading`)}</div>`:u`
|
|
954
954
|
<div class="flex flex-col gap-6">
|
|
955
955
|
<div>
|
|
956
956
|
<h3 class="mb-2 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
957
|
-
${
|
|
958
|
-
<quickforge-info-tip .label=${
|
|
957
|
+
${w(`lanAccess`)}
|
|
958
|
+
<quickforge-info-tip .label=${w(`lanAccessDescription`)}></quickforge-info-tip>
|
|
959
959
|
</h3>
|
|
960
960
|
</div>
|
|
961
961
|
|
|
962
962
|
<section class="rounded-lg border border-amber-500/30 bg-amber-500/10 p-4 text-sm text-amber-800 dark:text-amber-200">
|
|
963
|
-
${
|
|
963
|
+
${w(`lanAccessRiskWarning`)}
|
|
964
964
|
</section>
|
|
965
965
|
|
|
966
966
|
<section class="rounded-lg border border-border p-4">
|
|
967
|
-
<h4 class="text-sm font-semibold text-foreground">${
|
|
967
|
+
<h4 class="text-sm font-semibold text-foreground">${w(`lanAccessStatus`)}</h4>
|
|
968
968
|
<dl class="mt-4 grid gap-3 text-sm">
|
|
969
969
|
<div class="grid gap-1 sm:grid-cols-[140px_1fr] sm:gap-3">
|
|
970
|
-
<dt class="text-muted-foreground">${
|
|
971
|
-
<dd>${this.enabled?
|
|
970
|
+
<dt class="text-muted-foreground">${w(`lanAccessEnabled`)}</dt>
|
|
971
|
+
<dd>${this.enabled?w(`enabled`):w(`disabled`)}</dd>
|
|
972
972
|
</div>
|
|
973
973
|
<div class="grid gap-1 sm:grid-cols-[140px_1fr] sm:gap-3">
|
|
974
|
-
<dt class="text-muted-foreground">${
|
|
975
|
-
<dd>${this.hasPassword?
|
|
974
|
+
<dt class="text-muted-foreground">${w(`lanAccessPassword`)}</dt>
|
|
975
|
+
<dd>${this.hasPassword?w(`configured`):w(`notConfigured`)}</dd>
|
|
976
976
|
</div>
|
|
977
977
|
<div class="grid gap-1 sm:grid-cols-[140px_1fr] sm:gap-3">
|
|
978
|
-
<dt class="text-muted-foreground">${
|
|
978
|
+
<dt class="text-muted-foreground">${w(`lanAccessActiveDevices`)}</dt>
|
|
979
979
|
<dd>${this.activeTokenCount}</dd>
|
|
980
980
|
</div>
|
|
981
981
|
<div class="grid gap-1 sm:grid-cols-[140px_1fr] sm:gap-3">
|
|
982
|
-
<dt class="text-muted-foreground">${
|
|
983
|
-
<dd class="min-w-0 break-all">${this.lanUrls.length?this.lanUrls.map(e=>
|
|
982
|
+
<dt class="text-muted-foreground">${w(`lanAccessUrls`)}</dt>
|
|
983
|
+
<dd class="min-w-0 break-all">${this.lanUrls.length?this.lanUrls.map(e=>u`<div>${e}</div>`):`-`}</dd>
|
|
984
984
|
</div>
|
|
985
985
|
</dl>
|
|
986
986
|
</section>
|
|
@@ -988,37 +988,37 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
988
988
|
<section class="rounded-lg border border-border p-4">
|
|
989
989
|
<label class="flex items-center gap-2 text-sm font-medium text-foreground">
|
|
990
990
|
<input type="checkbox" .checked=${this.enabled} @change=${e=>this.updateEnabled(e.target.checked)} />
|
|
991
|
-
${
|
|
991
|
+
${w(`lanAccessAllowFull`)}
|
|
992
992
|
</label>
|
|
993
993
|
|
|
994
994
|
<label class="mt-4 block text-sm font-medium text-foreground">
|
|
995
|
-
${
|
|
995
|
+
${w(`lanAccessPassword`)}
|
|
996
996
|
<div class="mt-2 flex flex-col gap-3 sm:flex-row">
|
|
997
|
-
<input class="h-10 min-w-0 flex-1 rounded-md border border-input bg-background px-3 text-sm" type="password" .value=${this.password} @input=${e=>this.updatePassword(e.target.value)} placeholder=${this.hasPassword?
|
|
998
|
-
<button class="rounded-md border border-input px-3 py-2 text-sm" type="button" @click=${()=>this.updatePassword(
|
|
997
|
+
<input class="h-10 min-w-0 flex-1 rounded-md border border-input bg-background px-3 text-sm" type="password" .value=${this.password} @input=${e=>this.updatePassword(e.target.value)} placeholder=${this.hasPassword?w(`lanAccessPasswordPlaceholderConfigured`):w(`lanAccessPasswordPlaceholder`)} />
|
|
998
|
+
<button class="rounded-md border border-input px-3 py-2 text-sm" type="button" @click=${()=>this.updatePassword(pt())}>${w(`generatePassword`)}</button>
|
|
999
999
|
</div>
|
|
1000
1000
|
</label>
|
|
1001
1001
|
|
|
1002
1002
|
<label class="mt-4 block text-sm font-medium text-foreground">
|
|
1003
|
-
${
|
|
1003
|
+
${w(`lanAccessSessionTtl`)}
|
|
1004
1004
|
<select class="mt-2 h-10 w-full rounded-md border border-input bg-background px-3 text-sm" .value=${String(this.sessionTtlHours)} @change=${e=>this.updateTtl(e.target.value)}>
|
|
1005
|
-
<option value="1">1 ${
|
|
1006
|
-
<option value="12">12 ${
|
|
1007
|
-
<option value="24">24 ${
|
|
1008
|
-
<option value="168">7 ${
|
|
1005
|
+
<option value="1">1 ${w(`hour`)}</option>
|
|
1006
|
+
<option value="12">12 ${w(`hours`)}</option>
|
|
1007
|
+
<option value="24">24 ${w(`hours`)}</option>
|
|
1008
|
+
<option value="168">7 ${w(`days`)}</option>
|
|
1009
1009
|
</select>
|
|
1010
1010
|
</label>
|
|
1011
1011
|
|
|
1012
1012
|
<div class="mt-4 flex flex-wrap gap-2">
|
|
1013
|
-
<button class="rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground disabled:opacity-60" type="button" ?disabled=${this.saving} @click=${()=>this.saveSettings()}>${this.saving?
|
|
1014
|
-
<button class="rounded-md border border-destructive/40 px-3 py-2 text-sm text-destructive disabled:opacity-60" type="button" ?disabled=${this.saving} @click=${()=>this.revokeAll()}>${
|
|
1013
|
+
<button class="rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground disabled:opacity-60" type="button" ?disabled=${this.saving} @click=${()=>this.saveSettings()}>${this.saving?w(`saving`):w(`save`)}</button>
|
|
1014
|
+
<button class="rounded-md border border-destructive/40 px-3 py-2 text-sm text-destructive disabled:opacity-60" type="button" ?disabled=${this.saving} @click=${()=>this.revokeAll()}>${w(`lanAccessRevokeAll`)}</button>
|
|
1015
1015
|
</div>
|
|
1016
1016
|
</section>
|
|
1017
1017
|
|
|
1018
|
-
${this.message?
|
|
1019
|
-
${this.error?
|
|
1018
|
+
${this.message?u`<div class="rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-300">${this.message}</div>`:null}
|
|
1019
|
+
${this.error?u`<div class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${this.error}</div>`:null}
|
|
1020
1020
|
</div>
|
|
1021
|
-
`}},W=`quickforge-lan-access-settings-tab`;customElements.get(W)||customElements.define(W,
|
|
1021
|
+
`}},W=`quickforge-lan-access-settings-tab`;customElements.get(W)||customElements.define(W,mt);function ht(){return document.createElement(W)}var gt=18e4,_t=1e3;function vt(e){return new Promise(t=>window.setTimeout(t,e))}var yt=[{value:`startup`,label:()=>w(`frequencyStartup`)},{value:`daily`,label:()=>w(`frequencyDaily`)},{value:`weekly`,label:()=>w(`frequencyWeekly`)},{value:`off`,label:()=>w(`frequencyOff`)}],bt=class extends d{about;updateInfo;loading=!0;checking=!1;updating=!1;message=``;error=``;frequency=be.frequency;lastCheckAt=null;getTabName(){return w(`about`)}async connectedCallback(){super.connectedCallback(),await this.loadAbout()}async loadAbout(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=await fetch(`/api/system/about`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||w(`requestFailed`));this.about=t;try{let e=await S(f());this.frequency=e.frequency,this.lastCheckAt=e.lastCheckAt}catch{}}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}async checkUpdate(){if(!(this.checking||this.updating)){this.checking=!0,this.message=``,this.error=``,this.requestUpdate();try{let e=await fetch(`/api/system/update/check`,{cache:`no-store`}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||w(`updateCheckFailed`));this.updateInfo=t,this.about=t,this.updateInfo.updateAvailable?this.message=w(`updateAvailableMessage`,{current:this.updateInfo.currentVersion,latest:this.updateInfo.latestVersion}):this.updateInfo.localVersionIsNewer?this.message=w(`localVersionNewerMessage`,{current:this.updateInfo.currentVersion,latest:this.updateInfo.latestVersion}):this.message=w(`alreadyLatestVersion`,{version:this.updateInfo.currentVersion})}catch(e){this.error=e instanceof Error?e.message:w(`updateCheckFailed`)}finally{this.checking=!1,this.requestUpdate()}}}async pollUntilUpdated(e){let t=Date.now();for(;Date.now()-t<gt;){await vt(_t);try{let t=await fetch(`/api/health?updatePoll=${Date.now()}`,{cache:`no-store`}),n=await t.json().catch(()=>null);if(t.ok&&n?.ok&&n.bootId&&n.bootId!==e){this.message=w(`updateRestarted`),this.requestUpdate(),window.setTimeout(()=>window.location.reload(),300);return}}catch{}}throw Error(w(`updateRestartTimeout`))}async updateQuickForge(){if(!(!this.updateInfo?.updateAvailable||this.updating)&&await v({description:w(`updateConfirm`,{command:this.updateInfo.installCommand}),confirmLabel:w(`updateNow`),cancelLabel:w(`cancel`)})){this.updating=!0,this.message=w(`updatingQuickForge`),this.error=``,this.requestUpdate();try{let e=await fetch(`/api/system/update`,{method:`POST`,headers:{"x-quickforge-action":`update`}}),t=await e.json().catch(()=>null);if(!e.ok)throw Error(t?.error||w(`updateFailed`));if(this.updateInfo=t,t?.updateStarted){let e=t.logFile?` ${w(`updateLogFile`,{path:t.logFile})}`:``;this.message=`${w(`updateStarted`)}${e}`,this.requestUpdate(),await this.pollUntilUpdated(t.bootId)}else this.message=t?.updated?w(`updateCompleted`):w(`alreadyLatestVersion`,{version:t?.currentVersion||this.about?.version||`-`}),this.updating=!1}catch(e){this.error=e instanceof Error?e.message:w(`updateFailed`),this.message=``,this.updating=!1}finally{this.requestUpdate()}}}async selectFrequency(e){if(this.frequency!==e){this.frequency=e,this.requestUpdate();try{let t=f();await Te(t,{...await S(t),frequency:e}),this.error=``}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.requestUpdate()}}}renderFrequencyOption(e){return u`
|
|
1022
1022
|
<button
|
|
1023
1023
|
type="button"
|
|
1024
1024
|
class="rounded-md border px-3 py-1.5 text-sm transition-colors ${this.frequency===e.value?`border-primary bg-primary text-primary-foreground`:`border-border bg-background text-foreground hover:bg-accent`}"
|
|
@@ -1026,16 +1026,16 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
1026
1026
|
>
|
|
1027
1027
|
${e.label()}
|
|
1028
1028
|
</button>
|
|
1029
|
-
`}infoRows(){let e=this.about;return e?
|
|
1029
|
+
`}infoRows(){let e=this.about;return e?u`
|
|
1030
1030
|
<dl class="grid gap-3 text-sm">
|
|
1031
|
-
${[[
|
|
1031
|
+
${[[w(`packageName`),e.name],[w(`currentVersion`),e.version]].map(([e,t])=>u`
|
|
1032
1032
|
<div class="grid gap-1 sm:grid-cols-[120px_1fr] sm:gap-3">
|
|
1033
1033
|
<dt class="text-muted-foreground">${e}</dt>
|
|
1034
1034
|
<dd class="min-w-0 break-all text-foreground">${t}</dd>
|
|
1035
1035
|
</div>
|
|
1036
1036
|
`)}
|
|
1037
1037
|
<div class="grid gap-1 sm:grid-cols-[120px_1fr] sm:gap-3">
|
|
1038
|
-
<dt class="text-muted-foreground">${
|
|
1038
|
+
<dt class="text-muted-foreground">${w(`github`)}</dt>
|
|
1039
1039
|
<dd class="min-w-0 break-all">
|
|
1040
1040
|
<a class="text-primary underline-offset-4 hover:underline" href=${e.repositoryUrl} target="_blank" rel="noreferrer">
|
|
1041
1041
|
${e.repositoryUrl}
|
|
@@ -1043,50 +1043,50 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
1043
1043
|
</dd>
|
|
1044
1044
|
</div>
|
|
1045
1045
|
</dl>
|
|
1046
|
-
`:null}updateStatus(){return this.updateInfo?
|
|
1046
|
+
`:null}updateStatus(){return this.updateInfo?u`
|
|
1047
1047
|
<div class="mt-4 rounded-lg border bg-transparent p-3 text-sm" style="border-color: color-mix(in oklab, var(--border) 36%, transparent);">
|
|
1048
1048
|
<div class="grid gap-2 sm:grid-cols-[120px_1fr] sm:gap-3">
|
|
1049
|
-
<span class="text-muted-foreground">${
|
|
1049
|
+
<span class="text-muted-foreground">${w(`latestVersion`)}</span>
|
|
1050
1050
|
<span class="text-foreground">${this.updateInfo.latestVersion}</span>
|
|
1051
1051
|
</div>
|
|
1052
1052
|
<div class="mt-2 grid gap-2 sm:grid-cols-[120px_1fr] sm:gap-3">
|
|
1053
|
-
<span class="text-muted-foreground">${
|
|
1053
|
+
<span class="text-muted-foreground">${w(`updateCommand`)}</span>
|
|
1054
1054
|
<code class="min-w-0 break-all rounded bg-muted/20 px-1.5 py-0.5 font-mono text-xs text-foreground/90">${this.updateInfo.installCommand}</code>
|
|
1055
1055
|
</div>
|
|
1056
|
-
${this.updateInfo.logFile?
|
|
1056
|
+
${this.updateInfo.logFile?u`
|
|
1057
1057
|
<div class="mt-2 grid gap-2 sm:grid-cols-[120px_1fr] sm:gap-3">
|
|
1058
|
-
<span class="text-muted-foreground">${
|
|
1058
|
+
<span class="text-muted-foreground">${w(`updateLog`)}</span>
|
|
1059
1059
|
<code class="min-w-0 break-all rounded bg-muted/20 px-1.5 py-0.5 font-mono text-xs text-foreground/90">${this.updateInfo.logFile}</code>
|
|
1060
1060
|
</div>
|
|
1061
1061
|
`:null}
|
|
1062
1062
|
</div>
|
|
1063
|
-
`:null}render(){if(this.loading)return
|
|
1063
|
+
`:null}render(){if(this.loading)return u`<div class="text-sm text-muted-foreground">${w(`loading`)}</div>`;let e=this.checking||this.updating||!this.updateInfo?.updateAvailable;return u`
|
|
1064
1064
|
<div class="flex flex-col gap-6">
|
|
1065
1065
|
<div>
|
|
1066
1066
|
<h3 class="mb-2 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
1067
|
-
${
|
|
1068
|
-
<quickforge-info-tip .label=${
|
|
1067
|
+
${w(`aboutQuickForge`)}
|
|
1068
|
+
<quickforge-info-tip .label=${w(`aboutQuickForgeDescription`)}></quickforge-info-tip>
|
|
1069
1069
|
</h3>
|
|
1070
1070
|
</div>
|
|
1071
1071
|
|
|
1072
1072
|
<section class="rounded-lg border border-border p-4">
|
|
1073
|
-
<h4 class="text-sm font-semibold text-foreground">${
|
|
1073
|
+
<h4 class="text-sm font-semibold text-foreground">${w(`projectInfo`)}</h4>
|
|
1074
1074
|
<div class="mt-4">${this.infoRows()}</div>
|
|
1075
1075
|
</section>
|
|
1076
1076
|
|
|
1077
1077
|
<section class="rounded-lg border border-border p-4">
|
|
1078
1078
|
<h4 class="inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
1079
|
-
${
|
|
1080
|
-
<quickforge-info-tip .label=${
|
|
1079
|
+
${w(`checkUpdate`)}
|
|
1080
|
+
<quickforge-info-tip .label=${w(`checkUpdateDescription`)}></quickforge-info-tip>
|
|
1081
1081
|
</h4>
|
|
1082
1082
|
|
|
1083
1083
|
<div class="mt-4">
|
|
1084
|
-
<div class="text-sm font-medium text-foreground">${
|
|
1085
|
-
<div class="mt-1 text-xs text-muted-foreground">${
|
|
1084
|
+
<div class="text-sm font-medium text-foreground">${w(`updateFrequencySection`)}</div>
|
|
1085
|
+
<div class="mt-1 text-xs text-muted-foreground">${w(`updateFrequencyDescription`)}</div>
|
|
1086
1086
|
<div class="mt-2 flex flex-wrap gap-2">
|
|
1087
|
-
${
|
|
1087
|
+
${yt.map(e=>this.renderFrequencyOption(e))}
|
|
1088
1088
|
</div>
|
|
1089
|
-
<div class="mt-2 text-xs text-muted-foreground">${this.lastCheckAt?
|
|
1089
|
+
<div class="mt-2 text-xs text-muted-foreground">${this.lastCheckAt?w(`lastCheckedAt`,{time:new Date(this.lastCheckAt).toLocaleString(E())}):w(`lastCheckedNever`)}</div>
|
|
1090
1090
|
</div>
|
|
1091
1091
|
|
|
1092
1092
|
<div class="my-4 border-t border-border"></div>
|
|
@@ -1100,7 +1100,7 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
1100
1100
|
?disabled=${this.checking||this.updating}
|
|
1101
1101
|
@click=${()=>this.checkUpdate()}
|
|
1102
1102
|
>
|
|
1103
|
-
${this.checking?
|
|
1103
|
+
${this.checking?w(`checkingUpdate`):w(`checkUpdate`)}
|
|
1104
1104
|
</button>
|
|
1105
1105
|
<button
|
|
1106
1106
|
class="rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-60"
|
|
@@ -1108,56 +1108,56 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
1108
1108
|
?disabled=${e}
|
|
1109
1109
|
@click=${()=>this.updateQuickForge()}
|
|
1110
1110
|
>
|
|
1111
|
-
${this.updating?
|
|
1111
|
+
${this.updating?w(`updatingQuickForge`):w(`updateNow`)}
|
|
1112
1112
|
</button>
|
|
1113
1113
|
</div>
|
|
1114
1114
|
</section>
|
|
1115
1115
|
|
|
1116
|
-
${this.message?
|
|
1117
|
-
${this.error?
|
|
1116
|
+
${this.message?u`<div class="rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-300">${this.message}</div>`:null}
|
|
1117
|
+
${this.error?u`<div class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${this.error}</div>`:null}
|
|
1118
1118
|
</div>
|
|
1119
|
-
`}},G=`quickforge-about-settings-tab`;customElements.get(G)||customElements.define(G,
|
|
1119
|
+
`}},G=`quickforge-about-settings-tab`;customElements.get(G)||customElements.define(G,bt);function xt(){return document.createElement(G)}var St=class extends d{loading=!0;saving=!1;saved=!1;error=``;message=``;projects=[];project;commandDir=``;commands=[];loadingCommands=!1;getTabName(){return w(`projectCommands`)}async connectedCallback(){super.connectedCallback(),await this.loadProjects()}async request(e,t){let n=await fetch(e,{...t,cache:`no-store`,headers:{...t?.body?{"content-type":`application/json`}:void 0,...t?.headers}}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||w(`requestFailed`));return r}async loadProjects(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=await this.request(`/api/project`);this.projects=e?.projects??(e?.project?[e.project]:[]),this.project=e?.project??this.projects[0],this.commandDir=typeof this.project?.commandDir==`string`?this.project.commandDir:``,await this.loadCommands()}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}selectProject(e){let t=e.target,n=this.projects.find(e=>e.id===t.value);n&&(this.project=n,this.commandDir=typeof n.commandDir==`string`?n.commandDir:``,this.saved=!1,this.message=``,this.error=``,this.commands=[],this.requestUpdate(),this.loadCommands())}async loadCommands(){if(this.project?.id){this.loadingCommands=!0,this.requestUpdate();try{let e=await this.request(`/api/project/commands?projectId=${encodeURIComponent(this.project.id)}`);this.commands=e?.commands??[]}catch{this.commands=[]}finally{this.loadingCommands=!1,this.requestUpdate()}}}updateCommandDir(e){this.commandDir=e,this.saved=!1,this.message=``,this.requestUpdate()}async save(){if(!(!this.project||this.saving)){this.saving=!0,this.saved=!1,this.error=``,this.message=``,this.requestUpdate();try{let e=await this.request(`/api/project/${encodeURIComponent(this.project.id)}/command-dir`,{method:`PUT`,body:JSON.stringify({commandDir:this.commandDir})});if(this.project=e?.project??this.project,this.project){let e=this.projects.findIndex(e=>e.id===this.project.id);e>=0&&(this.projects[e]=this.project)}this.commandDir=typeof this.project?.commandDir==`string`?this.project.commandDir:``,this.saved=!0,await this.loadCommands()}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.saving=!1,this.requestUpdate()}}}async openCommandDir(){if(this.project){this.error=``,this.message=``,this.requestUpdate();try{await this.request(`/api/project/open-path`,{method:`POST`,body:JSON.stringify({path:`.ai/commands`,projectId:this.project.id})})}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`),this.requestUpdate()}}}async createCommand(){if(!this.project)return;let e=window.prompt(w(`newCommandPrompt`));if(e?.trim()){this.error=``,this.message=``,this.requestUpdate();try{let t=await this.request(`/api/project/command`,{method:`POST`,body:JSON.stringify({name:e.trim(),projectId:this.project.id})});t.ok?(this.message=w(`commandCreated`,{name:t.name??e.trim()}),await this.loadCommands()):t.reason===`exists`?this.error=w(`commandAlreadyExists`,{name:t.name??e.trim()}):this.error=w(`invalidCommandName`)}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.requestUpdate()}}}render(){return this.loading?u`<div class="text-sm text-muted-foreground">${w(`loading`)}</div>`:this.projects.length===0?u`
|
|
1120
1120
|
<div class="flex flex-col gap-3">
|
|
1121
|
-
<h3 class="text-sm font-semibold text-foreground">${
|
|
1122
|
-
<p class="text-sm text-muted-foreground">${
|
|
1123
|
-
${this.error?
|
|
1121
|
+
<h3 class="text-sm font-semibold text-foreground">${w(`projectCommands`)}</h3>
|
|
1122
|
+
<p class="text-sm text-muted-foreground">${w(`selectProjectForCommands`)}</p>
|
|
1123
|
+
${this.error?u`<div class="text-sm text-destructive">${this.error}</div>`:null}
|
|
1124
1124
|
</div>
|
|
1125
|
-
`:
|
|
1125
|
+
`:u`
|
|
1126
1126
|
<div class="flex flex-col gap-6">
|
|
1127
1127
|
<div>
|
|
1128
1128
|
<h3 class="mb-2 text-sm font-semibold text-foreground">
|
|
1129
|
-
${
|
|
1130
|
-
<quickforge-info-tip .label=${
|
|
1129
|
+
${w(`projectCommands`)}
|
|
1130
|
+
<quickforge-info-tip .label=${w(`projectCommandsDescription`)}></quickforge-info-tip>
|
|
1131
1131
|
</h3>
|
|
1132
1132
|
</div>
|
|
1133
1133
|
|
|
1134
1134
|
<div class="grid max-w-xl gap-1.5 text-sm">
|
|
1135
|
-
<span class="text-foreground">${
|
|
1135
|
+
<span class="text-foreground">${w(`project`)}</span>
|
|
1136
1136
|
<select
|
|
1137
1137
|
class="rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
1138
1138
|
.value=${this.project?.id??``}
|
|
1139
1139
|
@change=${e=>this.selectProject(e)}
|
|
1140
1140
|
>
|
|
1141
|
-
${this.projects.map(e=>
|
|
1141
|
+
${this.projects.map(e=>u`<option value=${e.id} ?selected=${e.id===this.project?.id}>${e.name}</option>`)}
|
|
1142
1142
|
</select>
|
|
1143
|
-
${this.project?.path?
|
|
1143
|
+
${this.project?.path?u`<span class="break-all text-xs text-muted-foreground">${this.project.path}</span>`:null}
|
|
1144
1144
|
</div>
|
|
1145
1145
|
|
|
1146
1146
|
<label class="grid max-w-xl gap-1.5 text-sm">
|
|
1147
1147
|
<span class="inline-flex items-center gap-1.5 text-foreground">
|
|
1148
|
-
${
|
|
1149
|
-
<quickforge-info-tip .label=${
|
|
1148
|
+
${w(`commandDirectories`)}
|
|
1149
|
+
<quickforge-info-tip .label=${w(`commandDirectoryHelp`)}></quickforge-info-tip>
|
|
1150
1150
|
</span>
|
|
1151
1151
|
<textarea
|
|
1152
1152
|
class="min-h-28 rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
1153
1153
|
.value=${this.commandDir}
|
|
1154
|
-
placeholder=${
|
|
1154
|
+
placeholder=${w(`commandDirectoryPlaceholder`)}
|
|
1155
1155
|
@input=${e=>this.updateCommandDir(e.target.value)}
|
|
1156
1156
|
></textarea>
|
|
1157
1157
|
</label>
|
|
1158
1158
|
|
|
1159
1159
|
<div class="rounded-lg border border-border p-4 text-xs leading-5 text-muted-foreground">
|
|
1160
|
-
<div class="mb-1 font-medium text-foreground">${
|
|
1160
|
+
<div class="mb-1 font-medium text-foreground">${w(`commandDirectoryExamples`)}</div>
|
|
1161
1161
|
<ul class="list-disc space-y-1 pl-5">
|
|
1162
1162
|
<li>.ai/commands</li>
|
|
1163
1163
|
<li>.claude/commands</li>
|
|
@@ -1173,17 +1173,17 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
1173
1173
|
?disabled=${this.saving}
|
|
1174
1174
|
@click=${()=>this.save()}
|
|
1175
1175
|
>
|
|
1176
|
-
${this.saving?
|
|
1176
|
+
${this.saving?w(`saving`):w(`save`)}
|
|
1177
1177
|
</button>
|
|
1178
|
-
${this.saved?
|
|
1179
|
-
${this.message?
|
|
1180
|
-
${this.error?
|
|
1178
|
+
${this.saved?u`<span class="text-sm text-muted-foreground">${w(`projectCommandsSaved`)}</span>`:null}
|
|
1179
|
+
${this.message?u`<span class="text-sm text-muted-foreground">${this.message}</span>`:null}
|
|
1180
|
+
${this.error?u`<span class="text-sm text-destructive">${this.error}</span>`:null}
|
|
1181
1181
|
</div>
|
|
1182
1182
|
|
|
1183
1183
|
<section class="rounded-lg border border-border p-4">
|
|
1184
1184
|
<div class="mb-3 flex flex-wrap items-center justify-between gap-2">
|
|
1185
1185
|
<h4 class="text-sm font-semibold text-foreground">
|
|
1186
|
-
${
|
|
1186
|
+
${w(`loadedCommands`,{count:this.commands.length})}
|
|
1187
1187
|
</h4>
|
|
1188
1188
|
<div class="flex items-center gap-2">
|
|
1189
1189
|
<button
|
|
@@ -1192,7 +1192,7 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
1192
1192
|
?disabled=${this.loadingCommands}
|
|
1193
1193
|
@click=${()=>this.openCommandDir()}
|
|
1194
1194
|
>
|
|
1195
|
-
${
|
|
1195
|
+
${w(`openCommandDir`)}
|
|
1196
1196
|
</button>
|
|
1197
1197
|
<button
|
|
1198
1198
|
class="rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground hover:bg-primary/90 disabled:opacity-60"
|
|
@@ -1200,29 +1200,29 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
1200
1200
|
?disabled=${this.loadingCommands}
|
|
1201
1201
|
@click=${()=>this.createCommand()}
|
|
1202
1202
|
>
|
|
1203
|
-
${
|
|
1203
|
+
${w(`createCommand`)}
|
|
1204
1204
|
</button>
|
|
1205
1205
|
</div>
|
|
1206
1206
|
</div>
|
|
1207
1207
|
|
|
1208
|
-
${this.loadingCommands?
|
|
1209
|
-
${this.commands.map(e=>{let t=e.argumentHint?` ${e.argumentHint}`:``;return
|
|
1208
|
+
${this.loadingCommands?u`<div class="text-sm text-muted-foreground">${w(`loading`)}</div>`:this.commands.length===0?u`<p class="text-sm text-muted-foreground">${w(`noCommandsLoaded`)}</p>`:u`<ul class="grid gap-2">
|
|
1209
|
+
${this.commands.map(e=>{let t=e.argumentHint?` ${e.argumentHint}`:``;return u`
|
|
1210
1210
|
<li class="grid gap-0.5 text-sm">
|
|
1211
1211
|
<span class="text-foreground">
|
|
1212
1212
|
<code class="text-xs">/${e.name}${t}</code>
|
|
1213
|
-
${e.description?
|
|
1213
|
+
${e.description?u` — <span class="text-muted-foreground">${e.description}</span>`:null}
|
|
1214
1214
|
</span>
|
|
1215
|
-
${e.relativePath?
|
|
1215
|
+
${e.relativePath?u`<span class="text-xs text-muted-foreground">${e.relativePath}</span>`:null}
|
|
1216
1216
|
</li>
|
|
1217
1217
|
`})}
|
|
1218
1218
|
</ul>`}
|
|
1219
1219
|
</section>
|
|
1220
1220
|
</div>
|
|
1221
|
-
`}},K=`quickforge-project-commands-settings-tab`;customElements.get(K)||customElements.define(K,
|
|
1221
|
+
`}},K=`quickforge-project-commands-settings-tab`;customElements.get(K)||customElements.define(K,St);function Ct(){return document.createElement(K)}var q={"x-quickforge-action":`channel-action`};function wt(e){switch(e){case`running`:return`border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300`;case`waiting_scan`:case`starting`:case`stopping`:return`border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300`;case`error`:return`border-destructive/30 bg-destructive/10 text-destructive`;default:return`border-border bg-muted/15 text-muted-foreground`}}function Tt(e){switch(e){case`starting`:return w(`channelStatusStarting`);case`waiting_scan`:return w(`channelStatusWaitingScan`);case`running`:return w(`channelStatusRunning`);case`stopping`:return w(`channelStatusStopping`);case`error`:return w(`channelStatusError`);default:return w(`channelStatusStopped`)}}function Et(e){if(!e)return`-`;let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()}var Dt=class extends d{loading=!0;channels=[];workspaces=[];selectedWorkspaceIdByChannel={};error=``;message=``;eventSource;busyChannelId=``;getTabName(){return w(`channels`)}async connectedCallback(){super.connectedCallback(),await Promise.all([this.loadChannels(),this.loadWorkspaces()]),this.connectEvents()}disconnectedCallback(){this.eventSource?.close(),this.eventSource=void 0,super.disconnectedCallback()}async request(e,t){let n=await fetch(e,{...t,cache:`no-store`,headers:{...t?.headers||{}}}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||w(`requestFailed`));return r}async loadChannels(){this.loading=!0,this.error=``,this.requestUpdate();try{let e=await this.request(`/api/channels`);this.channels=Array.isArray(e.channels)?e.channels:[],this.ensureWorkspaceSelections()}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.loading=!1,this.requestUpdate()}}async loadWorkspaces(){try{let e=await this.request(`/api/project`),t=e.defaultWorkspaceRoot||``,n=t?[{id:`default`,name:w(`channelDefaultWorkspace`),path:t,kind:`default`}]:[],r=(Array.isArray(e.projects)?e.projects:[]).map(e=>({id:e.id,name:e.name,path:e.path,kind:`project`}));this.workspaces=[...n,...r],this.ensureWorkspaceSelections()}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.requestUpdate()}}ensureWorkspaceSelections(){let e=new Set(this.workspaces.map(e=>e.id)),t={...this.selectedWorkspaceIdByChannel};for(let n of this.channels){if(!n.supportsWorkspaceSelection)continue;let r=t[n.id],i=n.launchWorkspace?.id,a=n.status!==`stopped`&&n.status!==`error`;if(i&&e.has(i)&&a){t[n.id]=i;continue}r&&e.has(r)||(t[n.id]=i&&e.has(i)?i:`default`)}this.selectedWorkspaceIdByChannel=t}connectEvents(){this.eventSource?.close();let e=new EventSource(`/api/channels/events`);this.eventSource=e;let t=e=>{try{let t=JSON.parse(e.data);this.applyChannelEvent(t)}catch{}};e.addEventListener(`snapshot`,t),e.addEventListener(`status`,t),e.addEventListener(`log`,t),e.addEventListener(`qrcode`,t),e.addEventListener(`error`,()=>{})}applyChannelEvent(e){if(Array.isArray(e.channels)){this.channels=e.channels,this.ensureWorkspaceSelections(),this.requestUpdate();return}if(e.snapshot){this.upsertChannel(e.snapshot);return}if(e.channelId&&e.log){let t=this.channels.find(t=>t.id===e.channelId);t&&(t.logs=[...t.logs||[],e.log].slice(-300),this.requestUpdate())}}upsertChannel(e){let t=this.channels.findIndex(t=>t.id===e.id);t>=0?this.channels=[...this.channels.slice(0,t),e,...this.channels.slice(t+1)]:this.channels=[...this.channels,e],this.ensureWorkspaceSelections(),this.requestUpdate()}selectedWorkspaceId(e){return this.selectedWorkspaceIdByChannel[e.id]||e.launchWorkspace?.id||`default`}handleWorkspaceChange(e,t){let n=t.currentTarget;n&&(this.selectedWorkspaceIdByChannel={...this.selectedWorkspaceIdByChannel,[e.id]:n.value||`default`},this.requestUpdate())}startOptions(e){return e.supportsWorkspaceSelection?{projectId:this.selectedWorkspaceId(e)}:void 0}async invoke(e,t){if(!this.busyChannelId&&!(t===`restart`&&!await v({description:w(`channelRestartConfirm`,{name:e.name}),confirmLabel:w(`restart`),cancelLabel:w(`cancel`)}))){this.busyChannelId=e.id,this.error=``,this.message=``,this.requestUpdate();try{let n=t===`start`||t===`restart`?this.startOptions(e):void 0,r=await this.request(`/api/channels/${encodeURIComponent(e.id)}/${t}`,{method:`POST`,headers:n?{...q,"content-type":`application/json`}:q,body:n?JSON.stringify(n):void 0});this.upsertChannel(r)}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.busyChannelId=``,this.requestUpdate()}}}async invokeAction(e,t){if(!this.busyChannelId&&!((t.destructive||t.id===`relogin`)&&!await v({description:t.id===`relogin`?w(`channelReloginConfirm`,{name:e.name}):w(`channelLogoutConfirm`,{name:e.name}),confirmLabel:t.label,cancelLabel:w(`cancel`),variant:t.destructive?`destructive`:void 0}))){this.busyChannelId=e.id,this.error=``,this.message=``,this.requestUpdate();try{let n=t.id===`relogin`?this.startOptions(e):void 0,r=await this.request(`/api/channels/${encodeURIComponent(e.id)}/actions/${encodeURIComponent(t.id)}`,{method:`POST`,headers:n?{...q,"content-type":`application/json`}:q,body:n?JSON.stringify(n):void 0});this.upsertChannel(r)}catch(e){this.error=e instanceof Error?e.message:w(`requestFailed`)}finally{this.busyChannelId=``,this.requestUpdate()}}}workspaceSection(e,t){if(!e.supportsWorkspaceSelection)return null;let n=this.selectedWorkspaceId(e),r=e.launchWorkspace;return u`
|
|
1222
1222
|
<div class="mt-4 rounded-lg border border-border bg-muted/10 p-3">
|
|
1223
1223
|
<label class="inline-flex items-center gap-1.5 text-sm font-medium text-foreground" for=${`channel-workspace-${e.id}`}>
|
|
1224
|
-
${
|
|
1225
|
-
<quickforge-info-tip .label=${
|
|
1224
|
+
${w(`channelWorkspace`)}
|
|
1225
|
+
<quickforge-info-tip .label=${w(`channelWorkspaceDescription`)}></quickforge-info-tip>
|
|
1226
1226
|
</label>
|
|
1227
1227
|
<select
|
|
1228
1228
|
id=${`channel-workspace-${e.id}`}
|
|
@@ -1231,90 +1231,90 @@ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{At as t,Dt as n}from".
|
|
|
1231
1231
|
.value=${n}
|
|
1232
1232
|
@change=${t=>this.handleWorkspaceChange(e,t)}
|
|
1233
1233
|
>
|
|
1234
|
-
${this.workspaces.map(e=>
|
|
1235
|
-
<option value=${e.id}>${e.kind===`default`?
|
|
1234
|
+
${this.workspaces.map(e=>u`
|
|
1235
|
+
<option value=${e.id}>${e.kind===`default`?w(`channelDefaultWorkspace`):e.name} — ${e.path}</option>
|
|
1236
1236
|
`)}
|
|
1237
1237
|
</select>
|
|
1238
|
-
${r?
|
|
1238
|
+
${r?u`<div class="mt-2 text-xs text-muted-foreground">${w(`channelCurrentWorkspace`)}: <span class="font-mono">${r.path}</span></div>`:null}
|
|
1239
1239
|
</div>
|
|
1240
|
-
`}channelMeta(e){return
|
|
1240
|
+
`}channelMeta(e){return u`
|
|
1241
1241
|
<dl class="grid gap-2 text-sm">
|
|
1242
|
-
${[[
|
|
1242
|
+
${[[w(`channelProvider`),e.provider||`-`],[w(`channelCommand`),e.commandLabel||`-`],[w(`channelPid`),e.pid?String(e.pid):`-`],[w(`channelStartedAt`),Et(e.startedAt)]].map(([e,t])=>u`
|
|
1243
1243
|
<div class="grid gap-1 sm:grid-cols-[112px_1fr] sm:gap-3">
|
|
1244
1244
|
<dt class="text-muted-foreground">${e}</dt>
|
|
1245
|
-
<dd class="min-w-0 break-all ${e===
|
|
1245
|
+
<dd class="min-w-0 break-all ${e===w(`channelCommand`)?`font-mono text-xs`:`text-foreground`}">${t}</dd>
|
|
1246
1246
|
</div>
|
|
1247
1247
|
`)}
|
|
1248
1248
|
</dl>
|
|
1249
|
-
`}qrSection(e){return!e.qrCodeText&&!e.qrCodeUrl&&e.status!==`waiting_scan`?null:
|
|
1249
|
+
`}qrSection(e){return!e.qrCodeText&&!e.qrCodeUrl&&e.status!==`waiting_scan`?null:u`
|
|
1250
1250
|
<div class="mt-4 rounded-lg border border-border bg-muted/10 p-3">
|
|
1251
1251
|
<div class="inline-flex items-center gap-1.5 text-sm font-medium text-foreground">
|
|
1252
|
-
${
|
|
1253
|
-
<quickforge-info-tip .label=${
|
|
1252
|
+
${w(`channelQrTitle`)}
|
|
1253
|
+
<quickforge-info-tip .label=${w(`channelQrDescription`)}></quickforge-info-tip>
|
|
1254
1254
|
</div>
|
|
1255
|
-
${e.qrCodeText?
|
|
1256
|
-
${e.qrCodeUrl?
|
|
1257
|
-
<div class="mt-3 text-xs text-muted-foreground">${
|
|
1255
|
+
${e.qrCodeText?u`<pre class="mt-3 max-h-96 overflow-auto whitespace-pre font-mono text-[10px] leading-none text-foreground">${e.qrCodeText}</pre>`:null}
|
|
1256
|
+
${e.qrCodeUrl?u`
|
|
1257
|
+
<div class="mt-3 text-xs text-muted-foreground">${w(`channelQrLink`)}</div>
|
|
1258
1258
|
<a class="mt-1 block break-all font-mono text-xs text-primary hover:underline" href=${e.qrCodeUrl} target="_blank" rel="noreferrer">${e.qrCodeUrl}</a>
|
|
1259
1259
|
`:null}
|
|
1260
1260
|
</div>
|
|
1261
|
-
`}logsSection(e){let t=e.logs||[];return
|
|
1261
|
+
`}logsSection(e){let t=e.logs||[];return u`
|
|
1262
1262
|
<details class="mt-4 rounded-lg border border-border bg-muted/10" open>
|
|
1263
|
-
<summary class="quickforge-channel-logs-summary cursor-pointer px-3 py-2 text-sm font-medium text-foreground">${
|
|
1263
|
+
<summary class="quickforge-channel-logs-summary cursor-pointer px-3 py-2 text-sm font-medium text-foreground">${w(`channelRecentLogs`)}</summary>
|
|
1264
1264
|
<div class="max-h-72 overflow-auto p-3 font-mono text-xs leading-5">
|
|
1265
|
-
${t.length?t.slice(-80).map(e=>
|
|
1265
|
+
${t.length?t.slice(-80).map(e=>u`
|
|
1266
1266
|
<div class="grid gap-1 py-0.5 sm:grid-cols-[72px_56px_1fr]">
|
|
1267
1267
|
<span class="text-muted-foreground/55">${new Date(e.time).toLocaleTimeString()}</span>
|
|
1268
1268
|
<span class=${e.stream===`stderr`?`text-destructive/80`:`text-muted-foreground/70`}>${e.stream}</span>
|
|
1269
1269
|
<span class="min-w-0 whitespace-pre-wrap break-words text-foreground/85">${e.text}</span>
|
|
1270
1270
|
</div>
|
|
1271
|
-
`):
|
|
1271
|
+
`):u`<div class="text-muted-foreground">${w(`channelNoLogs`)}</div>`}
|
|
1272
1272
|
</div>
|
|
1273
1273
|
</details>
|
|
1274
|
-
`}channelCard(e){let t=this.busyChannelId===e.id||!!e.activeAction,n=e.status===`running`||e.status===`waiting_scan`||e.status===`starting`,r=e.status===`stopping`,i=!!(e.supportsWorkspaceSelection&&this.workspaces.length===0);return
|
|
1274
|
+
`}channelCard(e){let t=this.busyChannelId===e.id||!!e.activeAction,n=e.status===`running`||e.status===`waiting_scan`||e.status===`starting`,r=e.status===`stopping`,i=!!(e.supportsWorkspaceSelection&&this.workspaces.length===0);return u`
|
|
1275
1275
|
<section class="rounded-lg border border-border p-4">
|
|
1276
1276
|
<div class="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
|
1277
1277
|
<div class="min-w-0">
|
|
1278
1278
|
<div class="flex flex-wrap items-center gap-2">
|
|
1279
1279
|
<h4 class="text-sm font-semibold text-foreground">${e.name}</h4>
|
|
1280
|
-
<span class="inline-flex rounded-full border px-2 py-0.5 text-xs ${
|
|
1280
|
+
<span class="inline-flex rounded-full border px-2 py-0.5 text-xs ${wt(e.status)}">${Tt(e.status)}</span>
|
|
1281
1281
|
</div>
|
|
1282
1282
|
<p class="mt-1 text-sm text-muted-foreground">${e.description}</p>
|
|
1283
|
-
${e.requirements?.length?
|
|
1283
|
+
${e.requirements?.length?u`<div class="mt-2 text-xs text-muted-foreground/70">${w(`channelRequirements`)}: ${e.requirements.join(` · `)}</div>`:null}
|
|
1284
1284
|
</div>
|
|
1285
1285
|
<div class="flex shrink-0 flex-wrap gap-2">
|
|
1286
|
-
<button class="rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-60" type="button" ?disabled=${t||n||r||i} @click=${()=>this.invoke(e,`start`)}>${
|
|
1287
|
-
<button class="rounded-md border border-input px-3 py-2 text-sm hover:bg-muted/20 disabled:opacity-60" type="button" ?disabled=${t||!n||r} @click=${()=>this.invoke(e,`stop`)}>${
|
|
1288
|
-
<button class="rounded-md border border-input px-3 py-2 text-sm hover:bg-muted/20 disabled:opacity-60" type="button" ?disabled=${t||r||i} @click=${()=>this.invoke(e,`restart`)}>${
|
|
1289
|
-
${e.actions?.map(n=>
|
|
1286
|
+
<button class="rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-60" type="button" ?disabled=${t||n||r||i} @click=${()=>this.invoke(e,`start`)}>${w(`start`)}</button>
|
|
1287
|
+
<button class="rounded-md border border-input px-3 py-2 text-sm hover:bg-muted/20 disabled:opacity-60" type="button" ?disabled=${t||!n||r} @click=${()=>this.invoke(e,`stop`)}>${w(`stop`)}</button>
|
|
1288
|
+
<button class="rounded-md border border-input px-3 py-2 text-sm hover:bg-muted/20 disabled:opacity-60" type="button" ?disabled=${t||r||i} @click=${()=>this.invoke(e,`restart`)}>${w(`restart`)}</button>
|
|
1289
|
+
${e.actions?.map(n=>u`
|
|
1290
1290
|
<button class=${n.destructive?`rounded-md border border-destructive/40 px-3 py-2 text-sm text-destructive hover:bg-destructive/10 disabled:opacity-60`:`rounded-md border border-input px-3 py-2 text-sm hover:bg-muted/20 disabled:opacity-60`} type="button" ?disabled=${t} @click=${()=>this.invokeAction(e,n)}>${n.label}</button>
|
|
1291
1291
|
`)}
|
|
1292
1292
|
</div>
|
|
1293
1293
|
</div>
|
|
1294
1294
|
|
|
1295
1295
|
${this.workspaceSection(e,t||n||r)}
|
|
1296
|
-
${i?
|
|
1296
|
+
${i?u`<div class="mt-3 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${w(`channelNoWorkspaces`)}</div>`:null}
|
|
1297
1297
|
<div class="mt-4">${this.channelMeta(e)}</div>
|
|
1298
|
-
${e.error?
|
|
1298
|
+
${e.error?u`<div class="mt-4 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${e.error}</div>`:null}
|
|
1299
1299
|
${this.qrSection(e)}
|
|
1300
1300
|
${this.logsSection(e)}
|
|
1301
1301
|
</section>
|
|
1302
|
-
`}render(){return this.loading?
|
|
1302
|
+
`}render(){return this.loading?u`<div class="text-sm text-muted-foreground">${w(`loading`)}</div>`:u`
|
|
1303
1303
|
<div class="flex flex-col gap-6">
|
|
1304
1304
|
<div>
|
|
1305
1305
|
<h3 class="mb-2 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
1306
|
-
${
|
|
1307
|
-
<quickforge-info-tip .label=${
|
|
1306
|
+
${w(`channels`)}
|
|
1307
|
+
<quickforge-info-tip .label=${w(`channelsDescription`)}></quickforge-info-tip>
|
|
1308
1308
|
</h3>
|
|
1309
1309
|
</div>
|
|
1310
1310
|
|
|
1311
1311
|
<section class="rounded-lg border border-amber-500/30 bg-amber-500/10 p-4 text-sm text-amber-800 dark:text-amber-200">
|
|
1312
|
-
${
|
|
1312
|
+
${w(`channelsSecurityWarning`)}
|
|
1313
1313
|
</section>
|
|
1314
1314
|
|
|
1315
|
-
${this.channels.length?
|
|
1315
|
+
${this.channels.length?u`<div class="grid gap-4">${this.channels.map(e=>this.channelCard(e))}</div>`:u`<div class="rounded-lg border border-border p-4 text-sm text-muted-foreground">${w(`channelsEmpty`)}</div>`}
|
|
1316
1316
|
|
|
1317
|
-
${this.message?
|
|
1318
|
-
${this.error?
|
|
1317
|
+
${this.message?u`<div class="rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-300">${this.message}</div>`:null}
|
|
1318
|
+
${this.error?u`<div class="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">${this.error}</div>`:null}
|
|
1319
1319
|
</div>
|
|
1320
|
-
`}},J=`quickforge-channels-settings-tab`;customElements.get(J)||customElements.define(J,
|
|
1320
|
+
`}},J=`quickforge-channels-settings-tab`;customElements.get(J)||customElements.define(J,Dt);function Ot(){return document.createElement(J)}var kt=ue(),Y=le(),At=(0,D.lazy)(()=>p(()=>import(`./AgentProfilesPage-wpt1cJV0.js`).then(e=>({default:e.AgentProfilesPage})),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11]))),jt=(0,D.lazy)(()=>p(()=>import(`./mcp-servers-dialog-DEyq3gmP.js`).then(e=>({default:e.McpServersPanel})),__vite__mapDeps([12,1,2,3,4,5,6,7,8,9,10,11]))),Mt=(0,D.lazy)(()=>p(()=>import(`./skills-dialog-CZ3CuVtQ.js`).then(e=>e.n).then(e=>({default:e.SkillsManagerPanel})),__vite__mapDeps([9,1,2,3,4,5,6,7,8,10,11]))),Nt=(0,D.lazy)(()=>p(()=>import(`./PluginsPage-0wwQydcP.js`).then(e=>({default:e.PluginsPage})),__vite__mapDeps([13,1,2,3,4,5,6,7,8,9,10,11,14]))),Pt=(0,D.lazy)(()=>p(()=>import(`./ScheduledTasksPage-qGHyGkjw.js`).then(e=>({default:e.ScheduledTasksPage})),__vite__mapDeps([15,1,2,3,4,5,6,7,8,9,10,11]))),Ft=class extends d{tabName=``;renderReact;root;getTabName(){return this.tabName}connectedCallback(){super.connectedCallback(),this.updateComplete.then(()=>this.mountReact())}disconnectedCallback(){this.root?.unmount(),this.root=void 0,super.disconnectedCallback()}render(){return u`<div class="quickforge-react-settings-tab h-full min-h-0"></div>`}mountReact(){let e=this.querySelector(`.quickforge-react-settings-tab`);!e||!this.renderReact||(this.root??=(0,kt.createRoot)(e),this.root.render(this.renderReact()))}},X=`quickforge-react-settings-tab`;customElements.get(X)||customElements.define(X,Ft);function Z(e,t){let n=document.createElement(X);return n.tabName=e,n.renderReact=t,n}function Q({children:e}){return(0,Y.jsx)(`div`,{className:`h-full min-h-[30rem] overflow-hidden rounded-xl border border-border bg-background`,children:(0,Y.jsx)(D.Suspense,{fallback:(0,Y.jsx)(`div`,{className:`flex h-full items-center justify-center text-sm text-muted-foreground`,children:w(`loading`)}),children:e})})}function It(e){window.dispatchEvent(new CustomEvent(`quickforge:open-session-from-settings`,{detail:{sessionId:e}}))}function Lt(){return Z(w(`agentsTab`),()=>(0,Y.jsx)(Q,{children:(0,Y.jsx)(At,{})}))}function Rt(){return Z(w(`skills`),()=>(0,Y.jsx)(Q,{children:(0,Y.jsx)(Mt,{active:!0,scope:`global`,embedded:!0,onSaved:()=>void 0})}))}function zt(){return Z(w(`mcpServers`),()=>(0,Y.jsx)(Q,{children:(0,Y.jsx)(jt,{active:!0})}))}function Bt(){return Z(w(`plugins`),()=>(0,Y.jsx)(Q,{children:(0,Y.jsx)(Nt,{})}))}function Vt(){return Z(w(`scheduledTasks`),()=>(0,Y.jsx)(Q,{children:(0,Y.jsx)(Pt,{onOpenSession:It})}))}function Ht(e){let t=[{key:`language`,tab:Pe()},{key:`appearance`,tab:Le()},{key:`defaults`,tab:Ue()},{key:`customModels`,tab:Me(e)},{key:`agents`,tab:Lt()},{key:`skills`,tab:Rt()},{key:`mcp`,tab:zt()},{key:`plugins`,tab:Bt()},{key:`scheduledTasks`,tab:Vt()},{key:`projectCommands`,tab:Ct()},{key:`backup`,tab:Ze()},{key:`archivedConversations`,tab:tt()},{key:`service`,tab:ft()},{key:`channels`,tab:Ot()},{key:`lanAccess`,tab:ht()},{key:`about`,tab:xt()}];return{items:[...t],tabs:t.map(e=>e.tab),indexOf:e=>t.findIndex(t=>t.key===e)}}var $={language:ce,appearance:ne,defaults:ie,customModels:se,agents:r,skills:a,mcp:te,plugins:c,scheduledTasks:o,projectCommands:oe,backup:l,archivedConversations:t,service:s,channels:ee,lanAccess:ae,about:n};function Ut({tab:e}){let t=(0,D.useRef)(null);return(0,D.useEffect)(()=>{let n=t.current;if(n)return n.replaceChildren(e),()=>{e.parentNode===n&&n.removeChild(e)}},[e]),(0,Y.jsx)(`div`,{ref:t,className:`quickforge-settings-tab-host min-h-0 flex-1`})}function Wt({initialTab:e,customProvider:t,onBack:n}){let r=(0,D.useMemo)(()=>Ht(t),[t]),i=Math.max(0,r.indexOf(e)),[a,o]=(0,D.useState)(),s=a??i,c=r.items[s]??r.items[0],l=c?$[c.key]:void 0;return(0,Y.jsxs)(`div`,{className:`flex h-screen min-h-0 bg-[var(--quickforge-sidebar-bg)] text-foreground`,children:[(0,Y.jsxs)(`aside`,{className:`relative z-10 hidden w-80 shrink-0 overflow-hidden bg-[var(--quickforge-sidebar-bg)] md:flex md:min-h-0 md:flex-col`,children:[(0,Y.jsx)(`div`,{className:`shrink-0 px-3 pb-1 pt-3`,children:(0,Y.jsxs)(`button`,{type:`button`,className:`group relative flex w-full items-center gap-2 overflow-hidden rounded-lg px-2 py-1.5 text-left text-muted-foreground/72 transition-[background-color,color,box-shadow] duration-160 ease-out hover:bg-[var(--quickforge-sidebar-hover-bg)] hover:text-foreground/86 hover:shadow-[0_8px_20px_-18px_rgb(15_23_42_/_0.35)]`,onClick:n,"aria-label":`返回工作区`,children:[(0,Y.jsx)(`span`,{className:`inline-flex size-6 shrink-0 items-center justify-center rounded-full text-muted-foreground/55 transition-colors group-hover:text-foreground/70`,children:(0,Y.jsx)(re,{className:`size-4`})}),(0,Y.jsx)(`span`,{className:`truncate text-sm leading-5`,children:`返回工作区`})]})}),(0,Y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-3 pb-4 pt-4`,children:(0,Y.jsx)(`nav`,{className:`space-y-1`,"aria-label":w(`settings`),children:r.items.map((e,t)=>{let n=t===s,r=$[e.key];return(0,Y.jsxs)(`button`,{type:`button`,className:C(`group relative flex w-full items-center gap-2.5 overflow-hidden rounded-lg px-2 py-1.5 text-left text-sm leading-5 transition-[background-color,color,box-shadow] duration-160 ease-out`,n?`bg-[var(--quickforge-sidebar-active-bg)] font-medium text-foreground/92 shadow-[0_8px_22px_-20px_rgb(15_23_42_/_0.32)]`:`text-muted-foreground/76 hover:bg-[var(--quickforge-sidebar-hover-bg)] hover:text-foreground/90 hover:shadow-[0_8px_20px_-18px_rgb(15_23_42_/_0.35)]`),onClick:()=>o(t),"aria-current":n?`page`:void 0,children:[(0,Y.jsx)(`span`,{className:C(`inline-flex size-5 shrink-0 items-center justify-center transition-colors`,n?`text-foreground/72`:`text-muted-foreground/52 group-hover:text-foreground/68`),children:(0,Y.jsx)(r,{className:`size-4`,"aria-hidden":`true`})}),(0,Y.jsx)(`span`,{className:`truncate`,children:e.tab.getTabName()})]},e.key)})})})]}),(0,Y.jsxs)(`main`,{className:`flex min-w-0 flex-1 flex-col bg-[var(--quickforge-main-bg)] md:overflow-hidden md:rounded-l-2xl`,children:[(0,Y.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-2 border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_34%,transparent)] px-3 pr-4 md:px-5`,children:[(0,Y.jsx)(de,{variant:`ghost`,size:`icon`,className:`md:hidden`,onClick:n,"aria-label":`返回工作区`,children:(0,Y.jsx)(re,{className:`size-4`})}),(0,Y.jsx)(`div`,{className:`min-w-0 flex-1`,children:(0,Y.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[l?(0,Y.jsx)(l,{className:`size-4 shrink-0 text-muted-foreground/65`,"aria-hidden":`true`}):null,(0,Y.jsx)(`div`,{className:`min-w-0 truncate text-sm font-medium text-foreground/90`,children:c?.tab.getTabName()})]})})]}),(0,Y.jsx)(`div`,{className:`quickforge-settings-mobile-tabs flex shrink-0 gap-1 overflow-x-auto border-b-[0.5px] border-[color-mix(in_oklab,var(--border)_30%,transparent)] px-3 py-2 md:hidden`,children:r.items.map((e,t)=>{let n=t===s,r=$[e.key];return(0,Y.jsxs)(`button`,{type:`button`,className:C(`inline-flex shrink-0 items-center gap-1.5 rounded-full px-3 py-1.5 text-sm transition-colors`,n?`bg-muted text-foreground`:`text-muted-foreground hover:bg-muted/55 hover:text-foreground`),onClick:()=>o(t),children:[(0,Y.jsx)(r,{className:`size-3.5 shrink-0`,"aria-hidden":`true`}),(0,Y.jsx)(`span`,{children:e.tab.getTabName()})]},e.key)})}),(0,Y.jsx)(`section`,{className:`min-h-0 flex-1 overflow-y-auto px-4 py-5 md:px-8 md:py-7`,children:(0,Y.jsx)(`div`,{className:`mx-auto flex min-h-full w-full max-w-5xl flex-col`,children:c?(0,Y.jsx)(Ut,{tab:c.tab}):null})})]})]})}export{Wt as SettingsWorkspacePage};
|