opencode-antigravity-config 1.0.0
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 +111 -0
- package/app.png +0 -0
- package/cli.js +17 -0
- package/config-data.js +23 -0
- package/i18n.js +198 -0
- package/index.html +432 -0
- package/main.js +307 -0
- package/package.json +27 -0
- package/preload.js +22 -0
- package/renderer.js +316 -0
- package/styles.css +1086 -0
- package/templates/dcp.jsonc +81 -0
- package/templates/oh-my-opencode.jsonc +173 -0
- package/templates/opencode-sync.jsonc +12 -0
- package/templates/opencode.json +236 -0
- package/templates/package.json +6 -0
- package/templates/supermemory.jsonc +15 -0
package/renderer.js
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
2
|
+
const pages = [0, 1, 2, 3, 4, 5].map(i => document.getElementById('page' + i));
|
|
3
|
+
let currentPage = 0;
|
|
4
|
+
|
|
5
|
+
document.getElementById('btnMinimize').addEventListener('click', () => window.api.minimize());
|
|
6
|
+
|
|
7
|
+
// Close confirmation modal
|
|
8
|
+
document.getElementById('btnClose').addEventListener('click', () => {
|
|
9
|
+
showModal(window.t('Close confirm title') || 'Tutup Aplikasi',
|
|
10
|
+
`<p style="margin-bottom:12px;">${window.t('Close confirm text') || 'Apakah Anda yakin ingin keluar dari program?'}</p>
|
|
11
|
+
<div style="display:flex;gap:8px;justify-content:flex-end;">
|
|
12
|
+
<button class="btn secondary" onclick="document.getElementById('modal').classList.remove('visible')">${window.t('Close cancel') || 'Tidak'}</button>
|
|
13
|
+
<button class="btn primary" id="btnConfirmExit" style="background:#E81123;">${window.t('Close exit') || 'Ya, Keluar'}</button>
|
|
14
|
+
</div>`);
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
const cb = document.getElementById('btnConfirmExit');
|
|
17
|
+
if (cb) cb.addEventListener('click', () => window.api.close());
|
|
18
|
+
}, 50);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Language Toggle
|
|
22
|
+
const btnLang = document.getElementById('btnLang');
|
|
23
|
+
if (btnLang) {
|
|
24
|
+
btnLang.addEventListener('click', () => {
|
|
25
|
+
const newLang = window.currentLang === 'ID' ? 'EN' : 'ID';
|
|
26
|
+
if (typeof window.updateLanguage === 'function') window.updateLanguage(newLang);
|
|
27
|
+
});
|
|
28
|
+
// Initial init
|
|
29
|
+
if (typeof window.updateLanguage === 'function') window.updateLanguage('ID');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const modal = document.getElementById('modal');
|
|
33
|
+
const modalTitle = document.getElementById('modalTitle');
|
|
34
|
+
const modalBody = document.getElementById('modalBody');
|
|
35
|
+
function showModal(t, h) { modalTitle.textContent = t; modalBody.innerHTML = h; modal.classList.add('visible'); }
|
|
36
|
+
function hideModal() { modal.classList.remove('visible'); }
|
|
37
|
+
document.getElementById('btnModalClose').addEventListener('click', hideModal);
|
|
38
|
+
modal.addEventListener('click', e => { if (e.target === modal) hideModal(); });
|
|
39
|
+
|
|
40
|
+
function navigateTo(idx) {
|
|
41
|
+
pages.forEach(p => { if (p) p.classList.remove('active'); });
|
|
42
|
+
if (pages[idx]) pages[idx].classList.add('active');
|
|
43
|
+
currentPage = idx;
|
|
44
|
+
for (let i = 0; i < 6; i++) {
|
|
45
|
+
const s = document.getElementById('step' + i);
|
|
46
|
+
if (!s) continue;
|
|
47
|
+
s.classList.remove('active', 'completed');
|
|
48
|
+
if (i < idx) s.classList.add('completed');
|
|
49
|
+
else if (i === idx) s.classList.add('active');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function escapeHtml(s) { return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); }
|
|
54
|
+
|
|
55
|
+
// ── Page 0: Welcome ──
|
|
56
|
+
document.getElementById('btnStart').addEventListener('click', () => { navigateTo(1); });
|
|
57
|
+
(async () => { const m = await window.api.getConfigMeta(); const el = document.getElementById('configMetaText'); if (el && m) el.textContent = `Config v${m.version} • ${m.date} • ${m.fileCount} files`; })();
|
|
58
|
+
|
|
59
|
+
// Agent Model Selection Logic
|
|
60
|
+
const AGENT_GROUPS = {
|
|
61
|
+
heavy: ['sisyphus', 'prometheus', 'metis', 'oracle'],
|
|
62
|
+
standard: ['hephaestus', 'momus', 'atlas'],
|
|
63
|
+
light: ['librarian', 'explore', 'multimodal_looker']
|
|
64
|
+
};
|
|
65
|
+
let agentAdvancedMode = false;
|
|
66
|
+
|
|
67
|
+
// Toggle Advanced / Group mode
|
|
68
|
+
document.getElementById('btnAgentAdvanced').addEventListener('click', () => {
|
|
69
|
+
agentAdvancedMode = !agentAdvancedMode;
|
|
70
|
+
document.getElementById('agentGroupMode').style.display = agentAdvancedMode ? 'none' : '';
|
|
71
|
+
document.getElementById('agentAdvancedMode').style.display = agentAdvancedMode ? '' : 'none';
|
|
72
|
+
document.getElementById('btnAgentAdvanced').textContent = agentAdvancedMode ? '← Simple' : '⚙ Advanced';
|
|
73
|
+
if (!agentAdvancedMode) syncAgentsFromGroups();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// When group dropdown changes → update per-agent dropdowns
|
|
77
|
+
function syncAgentsFromGroups() {
|
|
78
|
+
Object.entries(AGENT_GROUPS).forEach(([group, agents]) => {
|
|
79
|
+
const gSel = document.getElementById('selGroup' + group.charAt(0).toUpperCase() + group.slice(1));
|
|
80
|
+
if (!gSel) return;
|
|
81
|
+
agents.forEach(a => {
|
|
82
|
+
const aSel = document.getElementById('selAgent_' + a);
|
|
83
|
+
if (aSel) aSel.value = gSel.value;
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
['selGroupHeavy', 'selGroupStandard', 'selGroupLight'].forEach(id => {
|
|
88
|
+
const el = document.getElementById(id);
|
|
89
|
+
if (el) el.addEventListener('change', () => { if (!agentAdvancedMode) syncAgentsFromGroups(); });
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Global Template Presets
|
|
93
|
+
const selGlobalPreset = document.getElementById('selGlobalPreset');
|
|
94
|
+
if (selGlobalPreset) {
|
|
95
|
+
selGlobalPreset.addEventListener('change', (e) => {
|
|
96
|
+
const val = e.target.value;
|
|
97
|
+
if (!val) return;
|
|
98
|
+
|
|
99
|
+
const heavy = document.getElementById('selGroupHeavy');
|
|
100
|
+
const standard = document.getElementById('selGroupStandard');
|
|
101
|
+
const light = document.getElementById('selGroupLight');
|
|
102
|
+
const lookup = {
|
|
103
|
+
'antigravity_default': ['google/antigravity-gemini-3-1-pro', 'google/antigravity-gemini-3-1-pro', 'google/antigravity-gemini-3-flash'],
|
|
104
|
+
'max_reasoning': ['google/antigravity-claude-opus-4-6-thinking', 'google/antigravity-gemini-3-deep-think', 'google/antigravity-claude-sonnet-4-6'],
|
|
105
|
+
'fast_cheap': ['google/antigravity-gemini-3-flash', 'google/antigravity-gemini-3-flash', 'google/antigravity-gemini-3-flash'],
|
|
106
|
+
'claude_only': ['google/antigravity-claude-opus-4-6-thinking', 'google/antigravity-claude-sonnet-4-6', 'google/antigravity-claude-sonnet-4-6']
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
if (lookup[val] && heavy && standard && light) {
|
|
110
|
+
heavy.value = lookup[val][0];
|
|
111
|
+
standard.value = lookup[val][1];
|
|
112
|
+
light.value = lookup[val][2];
|
|
113
|
+
syncAgentsFromGroups(); // loop updates UI
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Gather agent model map (used during install)
|
|
119
|
+
function gatherAgentModels() {
|
|
120
|
+
const map = {};
|
|
121
|
+
const allAgents = ['sisyphus', 'prometheus', 'metis', 'oracle', 'hephaestus', 'momus', 'atlas', 'librarian', 'explore', 'multimodal_looker'];
|
|
122
|
+
if (agentAdvancedMode) {
|
|
123
|
+
allAgents.forEach(a => { const sel = document.getElementById('selAgent_' + a); if (sel) map[a] = sel.value; });
|
|
124
|
+
} else {
|
|
125
|
+
Object.entries(AGENT_GROUPS).forEach(([group, agents]) => {
|
|
126
|
+
const gSel = document.getElementById('selGroup' + group.charAt(0).toUpperCase() + group.slice(1));
|
|
127
|
+
if (!gSel) return;
|
|
128
|
+
agents.forEach(a => { map[a] = gSel.value; });
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return map;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
document.getElementById('btnVersionCheck').addEventListener('click', async () => {
|
|
135
|
+
const btn = document.getElementById('btnVersionCheck'); btn.textContent = '...'; btn.disabled = true;
|
|
136
|
+
const r = await window.api.checkVersion();
|
|
137
|
+
if (r.noEndpoint) showModal('Version Check', `<p>Current: <strong>v${r.current}</strong></p><p style="color:var(--text-secondary);font-size:11px;margin-top:6px;">No update endpoint configured.</p>`);
|
|
138
|
+
else if (r.upToDate) showModal('Version Check', `<p style="color:var(--accent-green)">✓ Latest: v${r.current}</p>`);
|
|
139
|
+
else showModal('Update Available', `<p>Current: v${r.current}</p><p>Latest: <strong style="color:var(--accent-green)">v${r.latest}</strong></p>`);
|
|
140
|
+
btn.textContent = '🔄 Updates'; btn.disabled = false;
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
document.getElementById('btnUninstall').addEventListener('click', async () => {
|
|
144
|
+
showModal('Uninstall', `<p style="margin-bottom:10px;">Remove all config files from <code>~/.config/opencode/</code>?</p><p style="color:var(--text-secondary);font-size:11px;margin-bottom:12px;">Safety backup created before deletion.</p><div style="display:flex;gap:8px;justify-content:flex-end;"><button class="btn secondary" onclick="document.getElementById('modal').classList.remove('visible')">Cancel</button><button class="btn primary" id="btnConfirmUninstall" style="background:#E81123;">Uninstall</button></div>`);
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
const cb = document.getElementById('btnConfirmUninstall');
|
|
147
|
+
if (cb) cb.addEventListener('click', async () => {
|
|
148
|
+
cb.textContent = '...'; cb.disabled = true;
|
|
149
|
+
const r = await window.api.uninstallConfig();
|
|
150
|
+
showModal(r.success ? 'Uninstalled' : 'Failed', r.success
|
|
151
|
+
? `<p style="color:var(--accent-green)">✓ Removed ${r.removed.length} files</p><p style="font-size:11px;color:var(--text-secondary);margin-top:4px;">${r.removed.join(', ')}</p><p style="font-size:11px;color:var(--text-secondary);margin-top:4px;">Backup: ${r.backupDir}</p>`
|
|
152
|
+
: `<p style="color:var(--accent-red)">✗ ${r.message}</p>`);
|
|
153
|
+
});
|
|
154
|
+
}, 50);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// ── Page 1: oMo Agent Model ──
|
|
158
|
+
document.getElementById('btnPrev1').addEventListener('click', () => navigateTo(0));
|
|
159
|
+
document.getElementById('btnNext1').addEventListener('click', async () => { navigateTo(2); await runSystemCheck(); });
|
|
160
|
+
|
|
161
|
+
// ── Page 2: System Check ──
|
|
162
|
+
document.getElementById('btnPrev2').addEventListener('click', () => navigateTo(1));
|
|
163
|
+
document.getElementById('btnNext2').addEventListener('click', () => navigateTo(3));
|
|
164
|
+
document.getElementById('btnRecheck').addEventListener('click', () => runSystemCheck());
|
|
165
|
+
|
|
166
|
+
async function runSystemCheck() {
|
|
167
|
+
const pp = document.getElementById('prereqPanel');
|
|
168
|
+
pp.innerHTML = `<p style="color:var(--text-secondary);font-size:11px;text-align:center;margin-top:20px;">${window.t('Checking...') || 'Checking...'}</p>`;
|
|
169
|
+
document.getElementById('btnNext2').disabled = true; document.getElementById('btnNext2').classList.add('disabled');
|
|
170
|
+
const res = await window.api.checkSystem(); pp.innerHTML = '';
|
|
171
|
+
let fail = false;
|
|
172
|
+
res.items.forEach(it => {
|
|
173
|
+
if (it.status === 'fail') fail = true;
|
|
174
|
+
const ic = it.status === 'ok' ? '✓' : it.status === 'warn' ? '⚠' : '✗';
|
|
175
|
+
pp.innerHTML += `<div class="prereq-item"><div class="prereq-info"><div class="label">${it.label}</div><div class="value">${it.value}</div></div><div class="prereq-status status-${it.status}">${ic}</div></div>`;
|
|
176
|
+
});
|
|
177
|
+
if (!fail) { document.getElementById('btnNext2').disabled = false; document.getElementById('btnNext2').classList.remove('disabled'); }
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// ── Page 3: Config ──
|
|
181
|
+
document.getElementById('btnPrev3').addEventListener('click', () => navigateTo(2));
|
|
182
|
+
document.getElementById('btnNext3').addEventListener('click', () => { navigateTo(4); startInstallation(); });
|
|
183
|
+
|
|
184
|
+
(async () => {
|
|
185
|
+
const k = await window.api.getExistingKeys();
|
|
186
|
+
if (k.supermemoryKey) document.getElementById('txtSupermemoryKey').value = k.supermemoryKey;
|
|
187
|
+
if (k.openSyncKey) document.getElementById('txtOpenSyncKey').value = k.openSyncKey;
|
|
188
|
+
if (k.openSyncUrl) document.getElementById('txtOpenSyncUrl').value = k.openSyncUrl;
|
|
189
|
+
valField('txtSupermemoryKey', 'valSupermemory'); valField('txtOpenSyncKey', 'valOpenSyncKey'); valField('txtOpenSyncUrl', 'valOpenSyncUrl');
|
|
190
|
+
})();
|
|
191
|
+
|
|
192
|
+
function valField(iid, vid) {
|
|
193
|
+
const v = document.getElementById(iid)?.value.trim() || '';
|
|
194
|
+
const el = document.getElementById(vid); if (!el) return;
|
|
195
|
+
if (!v) { el.textContent = window.t('(Optional)') || '(Optional)'; el.className = 'val-indicator val-empty'; }
|
|
196
|
+
else if (v.length < 8 || v.startsWith('__')) { el.textContent = window.t('✗ Invalid') || '✗ Invalid'; el.className = 'val-indicator val-bad'; }
|
|
197
|
+
else { el.textContent = window.t('✓ Set') || '✓ Set'; el.className = 'val-indicator val-ok'; }
|
|
198
|
+
}
|
|
199
|
+
window.reValInputs = () => { valField('txtSupermemoryKey', 'valSupermemory'); valField('txtOpenSyncKey', 'valOpenSyncKey'); valField('txtOpenSyncUrl', 'valOpenSyncUrl'); };
|
|
200
|
+
[['txtSupermemoryKey', 'valSupermemory'], ['txtOpenSyncKey', 'valOpenSyncKey'], ['txtOpenSyncUrl', 'valOpenSyncUrl']].forEach(([i, v]) => document.getElementById(i).addEventListener('input', () => { valField(i, v); updatePluginLogic(); }));
|
|
201
|
+
|
|
202
|
+
function updatePluginLogic() {
|
|
203
|
+
const total = document.querySelectorAll('.plugin-checkbox').length;
|
|
204
|
+
const checked = document.querySelectorAll('.plugin-checkbox:checked').length;
|
|
205
|
+
const elCount = document.getElementById('pluginCount');
|
|
206
|
+
if (elCount) elCount.textContent = `${checked}/${total}`;
|
|
207
|
+
|
|
208
|
+
const smCheck = document.getElementById('chkPluginSupermemory');
|
|
209
|
+
const smInput = document.getElementById('txtSupermemoryKey');
|
|
210
|
+
const smWarn = document.getElementById('warnSupermemory');
|
|
211
|
+
if (smCheck && smInput && smWarn) {
|
|
212
|
+
smInput.disabled = !smCheck.checked;
|
|
213
|
+
if (!smCheck.checked) smWarn.classList.add('hidden');
|
|
214
|
+
else smWarn.classList.toggle('hidden', !!smInput.value.trim());
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const osCheck = document.getElementById('chkPluginOpenSync');
|
|
218
|
+
const osInputKey = document.getElementById('txtOpenSyncKey');
|
|
219
|
+
const osInputUrl = document.getElementById('txtOpenSyncUrl');
|
|
220
|
+
const osWarn = document.getElementById('warnOpenSync');
|
|
221
|
+
if (osCheck && osInputKey && osInputUrl && osWarn) {
|
|
222
|
+
osInputKey.disabled = !osCheck.checked;
|
|
223
|
+
osInputUrl.disabled = !osCheck.checked;
|
|
224
|
+
if (!osCheck.checked) osWarn.classList.add('hidden');
|
|
225
|
+
else osWarn.classList.toggle('hidden', !!(osInputKey.value.trim() && osInputUrl.value.trim()));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const pluginGrid = document.getElementById('pluginGrid');
|
|
229
|
+
if (pluginGrid) pluginGrid.addEventListener('change', updatePluginLogic);
|
|
230
|
+
// Initial sync
|
|
231
|
+
setTimeout(updatePluginLogic, 100);
|
|
232
|
+
|
|
233
|
+
// Plugin select all/none
|
|
234
|
+
document.getElementById('btnPluginAll').addEventListener('click', () => { document.querySelectorAll('.plugin-checkbox:not(:disabled)').forEach(c => c.checked = true); updatePluginLogic(); });
|
|
235
|
+
document.getElementById('btnPluginNone').addEventListener('click', () => { document.querySelectorAll('.plugin-checkbox:not(:disabled)').forEach(c => c.checked = false); updatePluginLogic(); });
|
|
236
|
+
|
|
237
|
+
// Preview Final opencode.json
|
|
238
|
+
const btnPreviewConfig = document.getElementById('btnPreviewConfig');
|
|
239
|
+
if (btnPreviewConfig) {
|
|
240
|
+
btnPreviewConfig.addEventListener('click', async () => {
|
|
241
|
+
btnPreviewConfig.textContent = '...';
|
|
242
|
+
const sp = []; document.querySelectorAll('.plugin-checkbox').forEach(c => { if (c.checked) sp.push(c.value); });
|
|
243
|
+
const r = await window.api.previewFinalOpencode(sp);
|
|
244
|
+
btnPreviewConfig.textContent = window.t('👁 Preview opencode.json') || '👁 Preview opencode.json';
|
|
245
|
+
showModal('Preview: ' + r.fileName, `<pre class="modal-code">${escapeHtml(r.content)}</pre>`);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Preview
|
|
250
|
+
document.querySelectorAll('.btn-preview').forEach(b => b.addEventListener('click', async () => {
|
|
251
|
+
const f = b.dataset.file; b.textContent = '...';
|
|
252
|
+
const r = await window.api.previewConfig(f); b.textContent = '👁';
|
|
253
|
+
if (r.error) { showModal('Error', `<p>${r.error}</p>`); return; }
|
|
254
|
+
showModal('Preview: ' + r.fileName, `<pre class="modal-code">${escapeHtml(r.content)}</pre>`);
|
|
255
|
+
}));
|
|
256
|
+
|
|
257
|
+
// Diff
|
|
258
|
+
document.querySelectorAll('.btn-diff').forEach(b => b.addEventListener('click', async () => {
|
|
259
|
+
const f = b.dataset.file; b.textContent = '...';
|
|
260
|
+
const r = await window.api.diffConfig(f); b.textContent = '⇄';
|
|
261
|
+
if (r.error) { showModal('Error', `<p>${r.error}</p>`); return; }
|
|
262
|
+
if (r.isNew) { showModal('Diff: ' + r.fileName, `<p class="diff-new-badge">NEW FILE</p><pre class="modal-code">${escapeHtml(r.newContent)}</pre>`); return; }
|
|
263
|
+
if (!r.hasChanges) { showModal('Diff: ' + r.fileName, `<p style="color:var(--accent-green)">✓ Identical</p>`); return; }
|
|
264
|
+
let h = '<div class="diff-view">';
|
|
265
|
+
r.diffLines.forEach(d => { const c = d.type === 'add' ? 'diff-add' : d.type === 'del' ? 'diff-del' : 'diff-same'; const p = d.type === 'add' ? '+' : d.type === 'del' ? '-' : ' '; h += `<div class="diff-line ${c}"><span class="diff-prefix">${p}</span>${escapeHtml(d.content || '')}</div>`; });
|
|
266
|
+
showModal('Diff: ' + r.fileName, h + '</div>');
|
|
267
|
+
}));
|
|
268
|
+
|
|
269
|
+
// Export / Import
|
|
270
|
+
function gatherSettings() {
|
|
271
|
+
const sp = []; document.querySelectorAll('.plugin-checkbox').forEach(c => { if (c.checked) sp.push(c.value); });
|
|
272
|
+
return { supermemoryKey: document.getElementById('txtSupermemoryKey').value.trim(), openSyncKey: document.getElementById('txtOpenSyncKey').value.trim(), openSyncUrl: document.getElementById('txtOpenSyncUrl').value.trim(), backup: document.getElementById('chkBackup').checked, npmInstall: document.getElementById('chkNpmInstall').checked, selectedPlugins: sp, agentModels: gatherAgentModels() };
|
|
273
|
+
}
|
|
274
|
+
document.getElementById('btnExport').addEventListener('click', async () => { const r = await window.api.exportSettings(gatherSettings()); if (r.saved) showModal('Exported', `<p style="color:var(--accent-green)">✓ Saved to:<br><code style="font-size:11px;">${r.path}</code></p>`); });
|
|
275
|
+
document.getElementById('btnImport').addEventListener('click', async () => {
|
|
276
|
+
const r = await window.api.importSettings(); if (!r.loaded) { if (r.error) showModal('Error', `<p style="color:var(--accent-red)">${r.error}</p>`); return; }
|
|
277
|
+
const s = r.settings;
|
|
278
|
+
if (s.supermemoryKey) document.getElementById('txtSupermemoryKey').value = s.supermemoryKey;
|
|
279
|
+
if (s.openSyncKey) document.getElementById('txtOpenSyncKey').value = s.openSyncKey;
|
|
280
|
+
if (s.openSyncUrl) document.getElementById('txtOpenSyncUrl').value = s.openSyncUrl;
|
|
281
|
+
if (typeof s.backup === 'boolean') document.getElementById('chkBackup').checked = s.backup;
|
|
282
|
+
if (typeof s.npmInstall === 'boolean') document.getElementById('chkNpmInstall').checked = s.npmInstall;
|
|
283
|
+
if (s.selectedFiles) document.querySelectorAll('.file-checkbox').forEach(c => c.checked = s.selectedFiles.includes(c.value));
|
|
284
|
+
valField('txtSupermemoryKey', 'valSupermemory'); valField('txtOpenSyncKey', 'valOpenSyncKey'); valField('txtOpenSyncUrl', 'valOpenSyncUrl');
|
|
285
|
+
// Restore agent models if saved
|
|
286
|
+
if (s.agentModels) {
|
|
287
|
+
const allAgents = ['sisyphus', 'prometheus', 'metis', 'oracle', 'hephaestus', 'momus', 'atlas', 'librarian', 'explore', 'multimodal_looker'];
|
|
288
|
+
allAgents.forEach(a => { const sel = document.getElementById('selAgent_' + a); if (sel && s.agentModels[a]) sel.value = s.agentModels[a]; });
|
|
289
|
+
// Sync group dropdowns from per-agent values
|
|
290
|
+
Object.entries(AGENT_GROUPS).forEach(([group, agents]) => {
|
|
291
|
+
const gSel = document.getElementById('selGroup' + group.charAt(0).toUpperCase() + group.slice(1));
|
|
292
|
+
if (gSel && s.agentModels[agents[0]]) gSel.value = s.agentModels[agents[0]];
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
showModal('Imported', `<p style="color:var(--accent-green)">✓ Settings loaded</p>`);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// ── Page 4: Install ──
|
|
299
|
+
const logContent = document.getElementById('logContent'), progressBar = document.getElementById('installProgress');
|
|
300
|
+
const installTitle = document.getElementById('installTitle'), installSubtitle = document.getElementById('installSubtitle');
|
|
301
|
+
|
|
302
|
+
function startInstallation() { logContent.innerHTML = ''; progressBar.style.width = '0%'; window.api.startInstall(gatherSettings()); }
|
|
303
|
+
window.api.onInstallProgress(p => { progressBar.style.width = p + '%'; });
|
|
304
|
+
window.api.onInstallLog(l => { const d = document.createElement('div'); d.className = 'log-row log-' + l.type; const px = l.type === 'success' ? ' [OK] ' : l.type === 'error' ? ' [ERR] ' : l.type === 'warn' ? ' [!] ' : ' [i] '; d.textContent = l.message ? px + l.message : ''; logContent.appendChild(d); logContent.scrollTop = logContent.scrollHeight; });
|
|
305
|
+
window.api.onInstallComplete(r => {
|
|
306
|
+
if (r.success) { installTitle.textContent = 'Complete!'; installSubtitle.textContent = 'Semua konfigurasi berhasil di-install'; document.getElementById('txtConfigPath').textContent = r.configPath; }
|
|
307
|
+
else { installTitle.textContent = 'Failed'; installSubtitle.textContent = r.error; }
|
|
308
|
+
document.getElementById('btnNext4').classList.remove('hidden');
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// ── Page 5: Done ──
|
|
312
|
+
document.getElementById('btnNext4').addEventListener('click', () => navigateTo(5));
|
|
313
|
+
document.getElementById('btnOpenFolder').addEventListener('click', () => window.api.openConfigFolder());
|
|
314
|
+
document.getElementById('btnAuthLogin').addEventListener('click', () => window.api.runAuthLogin());
|
|
315
|
+
document.getElementById('btnFinish').addEventListener('click', () => window.api.close());
|
|
316
|
+
});
|