main
html 504 lines 18.7 KB
Raw
1 <html>
2 <head>
3 <title>Orchestrator</title>
4 <script type="module" src="/plugins/_orchestrator/webui/orchestrator-store.js"></script>
5 <style>
6 .ta-settings {
7 display: grid;
8 gap: 16px;
9 }
10 .ta-header {
11 align-items: flex-start;
12 display: flex;
13 gap: 12px;
14 justify-content: space-between;
15 }
16 .ta-refresh.btn-icon-action {
17 border-radius: 8px;
18 color: var(--color-text);
19 height: 34px;
20 width: 34px;
21 }
22 .ta-usage {
23 color: var(--color-text);
24 font-size: 0.82rem;
25 line-height: 1.45;
26 margin-top: 10px;
27 max-width: 760px;
28 opacity: 0.82;
29 }
30 .ta-agent {
31 border: 1px solid var(--color-border, #333);
32 border-radius: 8px;
33 background: color-mix(in srgb, var(--color-background) 28%, transparent);
34 }
35 .ta-agent {
36 display: grid;
37 overflow: hidden;
38 padding: 0;
39 }
40 .ta-panel {
41 border-top: 1px solid color-mix(in srgb, var(--color-border) 50%, transparent);
42 display: grid;
43 gap: 16px;
44 padding: 16px;
45 }
46 summary.ta-agent-head {
47 cursor: pointer;
48 list-style: none;
49 }
50 summary.ta-agent-head::-webkit-details-marker {
51 display: none;
52 }
53 .ta-agent-head {
54 align-items: center;
55 display: grid;
56 gap: 12px;
57 grid-template-columns: minmax(0, 1fr) auto;
58 padding: 14px;
59 }
60 .ta-agent-copy {
61 display: grid;
62 gap: 4px;
63 min-width: 0;
64 }
65 .ta-agent-title {
66 align-items: baseline;
67 display: flex;
68 flex-wrap: wrap;
69 gap: 8px;
70 min-width: 0;
71 }
72 .ta-agent-title strong {
73 font-size: 0.94rem;
74 overflow: hidden;
75 text-overflow: ellipsis;
76 white-space: nowrap;
77 }
78 .ta-agent-title code {
79 color: var(--color-text-secondary, #aaa);
80 }
81 .ta-actions {
82 align-items: center;
83 display: flex;
84 flex-wrap: wrap;
85 gap: 8px;
86 justify-content: flex-end;
87 }
88 .ta-action {
89 align-items: center;
90 background: #f5f7fa;
91 border: 0;
92 border-radius: 8px;
93 color: #111418;
94 cursor: pointer;
95 display: inline-flex;
96 font: inherit;
97 font-size: 0.76rem;
98 font-weight: 750;
99 gap: 6px;
100 justify-content: center;
101 min-height: 34px;
102 padding: 0 10px;
103 white-space: nowrap;
104 }
105 .ta-action.secondary {
106 background: color-mix(in srgb, var(--color-border) 44%, transparent);
107 border: 1px solid color-mix(in srgb, var(--color-border) 76%, transparent);
108 color: var(--color-text);
109 }
110 .ta-action.danger {
111 background: color-mix(in srgb, #f06464 16%, var(--color-panel, transparent));
112 border: 1px solid color-mix(in srgb, #f06464 40%, var(--color-border));
113 color: var(--color-text);
114 }
115 .ta-action:disabled {
116 cursor: default;
117 opacity: 0.65;
118 }
119 .ta-action .material-symbols-outlined {
120 font-size: 1rem;
121 }
122 .ta-form {
123 display: grid;
124 align-items: start;
125 gap: 16px 18px;
126 grid-template-columns: repeat(2, minmax(0, 1fr));
127 }
128 .ta-field {
129 display: grid;
130 gap: 7px;
131 min-width: 0;
132 }
133 .ta-field-toggle {
134 align-items: center;
135 grid-template-columns: minmax(0, 1fr) auto;
136 }
137 .ta-field-toggle .field-control {
138 justify-content: flex-end;
139 width: auto;
140 }
141 .ta-field .field-label {
142 display: grid;
143 gap: 3px;
144 padding-right: 0;
145 }
146 .ta-field .field-title {
147 color: color-mix(in srgb, var(--color-text) 78%, var(--color-primary));
148 font-size: 0.84rem;
149 font-weight: 800;
150 }
151 .ta-field .field-description {
152 color: var(--color-text);
153 font-size: 0.8rem;
154 line-height: 1.35;
155 margin: 0;
156 opacity: 0.78;
157 }
158 .ta-field .field-control {
159 min-width: 0;
160 width: 100%;
161 }
162 .ta-readonly-value {
163 align-items: center;
164 color: var(--color-text);
165 display: flex;
166 font-size: 0.82rem;
167 font-weight: 800;
168 min-height: 36px;
169 overflow-wrap: anywhere;
170 }
171 .ta-field input:not([type="checkbox"]),
172 .ta-field select {
173 background: color-mix(in srgb, var(--color-background) 72%, transparent);
174 border: 1px solid color-mix(in srgb, var(--color-border) 70%, transparent);
175 border-radius: 7px;
176 color: var(--color-text);
177 min-height: 36px;
178 width: 100%;
179 }
180 .ta-wide {
181 grid-column: 1 / -1;
182 }
183 .ta-expand {
184 color: var(--color-text-secondary, #aaa);
185 transition: transform 140ms ease;
186 }
187 .ta-agent[open] .ta-expand {
188 transform: rotate(180deg);
189 }
190 .ta-login {
191 background: color-mix(in srgb, var(--color-border) 18%, transparent);
192 border: 1px solid color-mix(in srgb, var(--color-border) 70%, transparent);
193 border-radius: 8px;
194 display: grid;
195 gap: 8px;
196 padding: 12px;
197 }
198 .ta-login code {
199 font-size: 1.2rem;
200 letter-spacing: 2px;
201 }
202 @media (max-width: 720px) {
203 .ta-form {
204 grid-template-columns: 1fr;
205 }
206 .ta-header,
207 .ta-agent-head {
208 align-items: stretch;
209 grid-template-columns: 1fr;
210 }
211 .ta-actions {
212 justify-content: flex-start;
213 }
214 }
215 </style>
216 </head>
217 <body>
218 <div x-data>
219 <template x-if="config && $store.orchestratorStore">
220 <div
221 class="ta-settings"
222 x-init="$store.orchestratorStore.onOpen()"
223 x-destroy="$store.orchestratorStore.cleanup()"
224 >
225 <div class="ta-header">
226 <div>
227 <div class="section-title">Orchestrator</div>
228 <div class="section-description">
229 Command defaults and advanced settings for the <code>orchestrator</code> skill.
230 </div>
231 <div class="ta-usage">
232 Ask Agent Zero for a coding agent, or describe the session you want to start.
233 For example: “Consult with Codex CLI on this heavy refactor before writing code.”
234 Or: “Create a council with Claude Code and Codex using the models and effort levels I specify.”
235 </div>
236 </div>
237 <button
238 class="btn-icon-action ta-refresh"
239 type="button"
240 title="Refresh status"
241 aria-label="Refresh status"
242 :disabled="$store.orchestratorStore.loading"
243 @click="$store.orchestratorStore.refresh()"
244 >
245 <x-icon aria-hidden="true" :name="$store.orchestratorStore.loading ? 'progress_activity' : 'refresh'"></x-icon>
246 </button>
247 </div>
248
249 <template x-for="agent in $store.orchestratorStore.agents" :key="agent.id">
250 <details class="ta-agent" x-init="$store.orchestratorStore.ensureConfig(config, agent)">
251 <summary class="ta-agent-head">
252 <div class="ta-agent-copy">
253 <div class="ta-agent-title">
254 <strong x-text="agent.title"></strong>
255 <code x-text="agent.id"></code>
256 </div>
257 <div class="section-description" x-text="agent.description"></div>
258 </div>
259 <div class="ta-actions">
260 <button
261 class="ta-action"
262 type="button"
263 x-show="agent.installed && !agent.auth?.connected && agent.supports_device_login && (!$store.orchestratorStore.login || $store.orchestratorStore.login.agentId !== agent.id)"
264 @click.stop="$store.orchestratorStore.startLogin(agent.id)"
265 >
266 <x-icon aria-hidden="true" name="login"></x-icon>
267 <span>Connect</span>
268 </button>
269 <button
270 class="ta-action danger"
271 type="button"
272 x-show="agent.auth?.connected && agent.can_disconnect"
273 :disabled="$store.orchestratorStore.disconnectingAgent === agent.id"
274 @click.stop="$store.orchestratorStore.disconnect(agent.id)"
275 >
276 <x-icon aria-hidden="true" :name="$store.orchestratorStore.disconnectingAgent === agent.id ? 'progress_activity' : 'link_off'"></x-icon>
277 <span x-text="$store.orchestratorStore.disconnectingAgent === agent.id ? 'Disconnecting' : 'Disconnect'"></span>
278 </button>
279 <x-icon class="ta-expand" aria-hidden="true" name="expand_more"></x-icon>
280 </div>
281 </summary>
282
283 <div class="ta-panel">
284 <div class="ta-form">
285 <div class="ta-field">
286 <div class="field-label">
287 <div class="field-title">Binary</div>
288 <div class="field-description">Command name or absolute path.</div>
289 </div>
290 <div class="field-control">
291 <input type="text" x-model.trim="config[agent.id].binary" :placeholder="agent.id" spellcheck="false" />
292 </div>
293 </div>
294
295 <div class="ta-field">
296 <div class="field-label">
297 <div class="field-title">Auth</div>
298 <div class="field-description">Detected connection source.</div>
299 </div>
300 <div class="field-control">
301 <div class="ta-readonly-value" x-text="$store.orchestratorStore.authText(agent)"></div>
302 </div>
303 </div>
304
305 <div class="ta-field" x-show="agent.id === 'codex' || agent.id === 'claude' || agent.id === 'gemini' || agent.id === 'grok' || agent.id === 'hermes' || agent.id === 'opencode'">
306 <div class="field-label">
307 <div class="field-title">Model</div>
308 <div class="field-description">Optional CLI model override.</div>
309 </div>
310 <div class="field-control">
311 <input type="text" x-model.trim="config[agent.id].model" placeholder="default" spellcheck="false" />
312 </div>
313 </div>
314
315 <div class="ta-field" x-show="agent.id === 'hermes'">
316 <div class="field-label">
317 <div class="field-title">Provider</div>
318 <div class="field-description">Optional Hermes provider override.</div>
319 </div>
320 <div class="field-control">
321 <input type="text" x-model.trim="config[agent.id].provider" placeholder="openrouter" spellcheck="false" />
322 </div>
323 </div>
324
325 <div class="ta-field" x-show="agent.id === 'opencode'">
326 <div class="field-label">
327 <div class="field-title">Agent</div>
328 <div class="field-description">Optional OpenCode agent name.</div>
329 </div>
330 <div class="field-control">
331 <input type="text" x-model.trim="config[agent.id].agent" placeholder="build" spellcheck="false" />
332 </div>
333 </div>
334
335 <div class="ta-field ta-field-toggle" x-show="agent.id === 'codex'">
336 <div class="field-label">
337 <div class="field-title">Bypass sandbox</div>
338 <div class="field-description">Needed in this Docker runtime.</div>
339 </div>
340 <div class="field-control">
341 <label class="toggle">
342 <input type="checkbox" x-model="config[agent.id].bypass_sandbox" />
343 <span class="toggler"></span>
344 </label>
345 </div>
346 </div>
347
348 <div class="ta-field ta-field-toggle" x-show="agent.id === 'hermes'">
349 <div class="field-label">
350 <div class="field-title">Skip approvals</div>
351 <div class="field-description">Pass <code>--yolo</code> for non-interactive runs.</div>
352 </div>
353 <div class="field-control">
354 <label class="toggle">
355 <input type="checkbox" x-model="config[agent.id].yolo" />
356 <span class="toggler"></span>
357 </label>
358 </div>
359 </div>
360
361 <div class="ta-field ta-field-toggle" x-show="agent.id === 'cursor'">
362 <div class="field-label">
363 <div class="field-title">Force changes</div>
364 <div class="field-description">Pass <code>--force</code> so scripts can modify files.</div>
365 </div>
366 <div class="field-control">
367 <label class="toggle">
368 <input type="checkbox" x-model="config[agent.id].force" />
369 <span class="toggler"></span>
370 </label>
371 </div>
372 </div>
373
374 <div class="ta-field ta-field-toggle" x-show="agent.id === 'grok'">
375 <div class="field-label">
376 <div class="field-title">Always approve</div>
377 <div class="field-description">Pass <code>--always-approve</code> for headless runs.</div>
378 </div>
379 <div class="field-control">
380 <label class="toggle">
381 <input type="checkbox" x-model="config[agent.id].always_approve" />
382 <span class="toggler"></span>
383 </label>
384 </div>
385 </div>
386
387 <div class="ta-field ta-field-toggle" x-show="agent.id === 'grok'">
388 <div class="field-label">
389 <div class="field-title">No auto update</div>
390 <div class="field-description">Pass <code>--no-auto-update</code> in automation.</div>
391 </div>
392 <div class="field-control">
393 <label class="toggle">
394 <input type="checkbox" x-model="config[agent.id].no_auto_update" />
395 <span class="toggler"></span>
396 </label>
397 </div>
398 </div>
399
400 <div class="ta-field ta-field-toggle" x-show="agent.id === 'opencode'">
401 <div class="field-label">
402 <div class="field-title">Auto approve</div>
403 <div class="field-description">Pass <code>--auto</code> for non-interactive runs.</div>
404 </div>
405 <div class="field-control">
406 <label class="toggle">
407 <input type="checkbox" x-model="config[agent.id].auto" />
408 <span class="toggler"></span>
409 </label>
410 </div>
411 </div>
412
413 <div class="ta-field" x-show="agent.id === 'a0'">
414 <div class="field-label">
415 <div class="field-title">Host</div>
416 <div class="field-description">Empty uses the local Agent Zero runtime.</div>
417 </div>
418 <div class="field-control">
419 <input type="text" x-model.trim="config[agent.id].host" placeholder="http://localhost:80" spellcheck="false" />
420 </div>
421 </div>
422
423 <div class="ta-field" x-show="agent.id === 'claude'">
424 <div class="field-label">
425 <div class="field-title">Permission mode</div>
426 <div class="field-description">Claude Code permission preset.</div>
427 </div>
428 <div class="field-control">
429 <select x-model="config[agent.id].permission_mode">
430 <option value="bypassPermissions">Skip permissions</option>
431 <option value="acceptEdits">Accept edits</option>
432 <option value="default">Default</option>
433 <option value="plan">Plan</option>
434 <option value="auto">Auto</option>
435 <option value="dontAsk">Do not ask</option>
436 </select>
437 </div>
438 </div>
439
440 <div class="ta-field" x-show="agent.id === 'claude'">
441 <div class="field-label">
442 <div class="field-title">Allowed tools</div>
443 <div class="field-description">Passed to <code>--allowedTools</code>.</div>
444 </div>
445 <div class="field-control">
446 <input type="text" x-model.trim="config[agent.id].allowed_tools" placeholder="Bash,Read,Edit" spellcheck="false" />
447 </div>
448 </div>
449
450 <div class="ta-field ta-field-toggle" x-show="agent.id === 'claude'">
451 <div class="field-label">
452 <div class="field-title">Bare mode</div>
453 <div class="field-description">Skip local Claude Code project discovery.</div>
454 </div>
455 <div class="field-control">
456 <label class="toggle">
457 <input type="checkbox" x-model="config[agent.id].bare" />
458 <span class="toggler"></span>
459 </label>
460 </div>
461 </div>
462
463 <div class="ta-field" x-show="agent.id === 'hermes'">
464 <div class="field-label">
465 <div class="field-title">Toolsets</div>
466 <div class="field-description">Comma-separated Hermes toolsets.</div>
467 </div>
468 <div class="field-control">
469 <input type="text" x-model.trim="config[agent.id].toolsets" placeholder="terminal,files" spellcheck="false" />
470 </div>
471 </div>
472
473 </div>
474
475 <template x-if="$store.orchestratorStore.login && $store.orchestratorStore.login.agentId === agent.id">
476 <div class="ta-login">
477 <div>
478 1. Open
479 <a :href="$store.orchestratorStore.login.verificationUrl" target="_blank"
480 x-text="$store.orchestratorStore.login.verificationUrl"></a>
481 </div>
482 <div>
483 2. Enter code:
484 <code x-text="$store.orchestratorStore.login.userCode"></code>
485 </div>
486 <div>
487 Waiting for confirmation…
488 <button class="ta-action secondary" type="button" @click="$store.orchestratorStore.cancelLogin()">Cancel</button>
489 </div>
490 </div>
491 </template>
492 </div>
493 </details>
494 </template>
495
496 <div x-show="!$store.orchestratorStore.loading && $store.orchestratorStore.agents.length === 0" style="opacity: 0.7;">
497 No agents registered.
498 </div>
499
500 </div>
501 </template>
502 </div>
503 </body>
504 </html>