stableclaw 2026.5.2 → 2026.5.3
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/dist/.buildstamp +1 -1
- package/dist/control-ui/apple-touch-icon.png +0 -0
- package/dist/control-ui/assets/agents-DIJiVfPj.js +813 -0
- package/dist/control-ui/assets/anthropic-BnQLajET.js +37 -0
- package/dist/control-ui/assets/azure-openai-responses-D6oH5P8v.js +2 -0
- package/dist/control-ui/assets/channel-config-extras-Cu8rP5sC.js +2 -0
- package/dist/control-ui/assets/channels-DMte0OdA.js +349 -0
- package/dist/control-ui/assets/cron-hM6tj-cg.js +928 -0
- package/dist/control-ui/assets/de-BzA7Smom.js +2 -0
- package/dist/control-ui/assets/debug-ChdgbieB.js +94 -0
- package/dist/control-ui/assets/directive-C6NBp6xJ.js +2 -0
- package/dist/control-ui/assets/es--sAce87o.js +2 -0
- package/dist/control-ui/assets/event-stream-B8X6sYaV.js +2 -0
- package/dist/control-ui/assets/format-nUIQxx1z.js +2 -0
- package/dist/control-ui/assets/github-copilot-headers-cUjskhp6.js +2 -0
- package/dist/control-ui/assets/google-DDYMjR2f.js +2 -0
- package/dist/control-ui/assets/google-gemini-cli-BBZpF1Bz.js +3 -0
- package/dist/control-ui/assets/google-shared-Brxly9jR.js +12 -0
- package/dist/control-ui/assets/google-vertex-moPkJqQt.js +2 -0
- package/dist/control-ui/assets/hash-BN8UQrrC.js +2 -0
- package/dist/control-ui/assets/index-DOMg2RvO.css +1 -0
- package/dist/control-ui/assets/index-hSu8pNmQ.js +4841 -0
- package/dist/control-ui/assets/instances-BO-5LU4G.js +57 -0
- package/dist/control-ui/assets/lit-zdTgzAJI.js +3 -0
- package/dist/control-ui/assets/logs-CaFT90eM.js +74 -0
- package/dist/control-ui/assets/mistral-yMnz8nsP.js +8 -0
- package/dist/control-ui/assets/nodes-6XxETMb5.js +430 -0
- package/dist/control-ui/assets/openai-CQsomflW.js +17 -0
- package/dist/control-ui/assets/openai-codex-responses-DXqDuiSK.js +8 -0
- package/dist/control-ui/assets/openai-completions-Bme8q7yw.js +6 -0
- package/dist/control-ui/assets/openai-responses-DpESo9k8.js +2 -0
- package/dist/control-ui/assets/openai-responses-shared-CjacPL_h.js +11 -0
- package/dist/control-ui/assets/preload-helper-xBbMyY7u.js +1 -0
- package/dist/control-ui/assets/preview-Ca6p7-4-.js +2 -0
- package/dist/control-ui/assets/pt-BR-DkjnRLn3.js +2 -0
- package/dist/control-ui/assets/sessions-USutdtjY.js +236 -0
- package/dist/control-ui/assets/skills-DLY8KTEh.js +216 -0
- package/dist/control-ui/assets/skills-shared-DUfo2UBp.js +11 -0
- package/dist/control-ui/assets/transform-messages-Lu1Q3cQf.js +2 -0
- package/dist/control-ui/assets/zh-CN-Di7IMlSu.js +2 -0
- package/dist/control-ui/assets/zh-TW-yENTnmx1.js +2 -0
- package/dist/control-ui/favicon-32.png +0 -0
- package/dist/control-ui/favicon.ico +0 -0
- package/dist/control-ui/favicon.svg +66 -0
- package/dist/control-ui/index.html +75 -0
- package/package.json +1 -1
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import{i as e,n as t}from"./lit-zdTgzAJI.js";import{l as n,r,t as i}from"./format-nUIQxx1z.js";function a(e){let t=e?.agents??{},n=Array.isArray(t.list)?t.list:[],r=[];return n.forEach((e,t)=>{if(!e||typeof e!=`object`)return;let n=e,i=typeof n.id==`string`?n.id.trim():``;if(!i)return;let a=typeof n.name==`string`?n.name.trim():void 0,o=n.default===!0;r.push({id:i,name:a||void 0,isDefault:o,index:t,record:n})}),r}function o(e,t){let n=new Set(t),r=[];for(let t of e){if(!(Array.isArray(t.commands)?t.commands:[]).some(e=>n.has(String(e))))continue;let e=typeof t.nodeId==`string`?t.nodeId.trim():``;if(!e)continue;let i=typeof t.displayName==`string`&&t.displayName.trim()?t.displayName.trim():e;r.push({id:e,label:i===e?e:`${i} · ${e}`})}return r.sort((e,t)=>e.label.localeCompare(t.label)),r}var s=`__defaults__`,c=[{value:`deny`,label:`Deny`},{value:`allowlist`,label:`Allowlist`},{value:`full`,label:`Full`}],l=[{value:`off`,label:`Off`},{value:`on-miss`,label:`On miss`},{value:`always`,label:`Always`}];function u(e){return e===`allowlist`||e===`full`||e===`deny`?e:`deny`}function d(e){return e===`always`||e===`off`||e===`on-miss`?e:`on-miss`}function f(e){let t=e?.defaults??{};return{security:u(t.security),ask:d(t.ask),askFallback:u(t.askFallback??`deny`),autoAllowSkills:!!(t.autoAllowSkills??!1)}}function p(e){return a(e).map(e=>({id:e.id,name:e.name,isDefault:e.isDefault}))}function m(e,t){let n=p(e),r=Object.keys(t?.agents??{}),i=new Map;n.forEach(e=>i.set(e.id,e)),r.forEach(e=>{i.has(e)||i.set(e,{id:e})});let a=Array.from(i.values());return a.length===0&&a.push({id:`main`,isDefault:!0}),a.sort((e,t)=>{if(e.isDefault&&!t.isDefault)return-1;if(!e.isDefault&&t.isDefault)return 1;let n=e.name?.trim()?e.name:e.id,r=t.name?.trim()?t.name:t.id;return n.localeCompare(r)}),a}function h(e,t){return e===s?s:e&&t.some(t=>t.id===e)?e:s}function g(e){let t=e.execApprovalsForm??e.execApprovalsSnapshot?.file??null,n=!!t,r=f(t),i=m(e.configForm,t),a=C(e.nodes),o=e.execApprovalsTarget,c=o===`node`&&e.execApprovalsTargetNodeId?e.execApprovalsTargetNodeId:null;o===`node`&&c&&!a.some(e=>e.id===c)&&(c=null);let l=h(e.execApprovalsSelectedAgent,i),u=l===s?null:(t?.agents??{})[l]??null,d=Array.isArray(u?.allowlist)?u.allowlist??[]:[];return{ready:n,disabled:e.execApprovalsSaving||e.execApprovalsLoading,dirty:e.execApprovalsDirty,loading:e.execApprovalsLoading,saving:e.execApprovalsSaving,form:t,defaults:r,selectedScope:l,selectedAgent:u,agents:i,allowlist:d,target:o,targetNodeId:c,targetNodes:a,onSelectScope:e.onExecApprovalsSelectAgent,onSelectTarget:e.onExecApprovalsTargetChange,onPatch:e.onExecApprovalsPatch,onRemove:e.onExecApprovalsRemove,onLoad:e.onLoadExecApprovals,onSave:e.onSaveExecApprovals}}function _(n){let r=n.ready,i=n.target!==`node`||!!n.targetNodeId;return e`
|
|
2
|
+
<section class="card">
|
|
3
|
+
<div class="row" style="justify-content: space-between; align-items: center;">
|
|
4
|
+
<div>
|
|
5
|
+
<div class="card-title">Exec approvals</div>
|
|
6
|
+
<div class="card-sub">
|
|
7
|
+
Allowlist and approval policy for <span class="mono">exec host=gateway/node</span>.
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
<button
|
|
11
|
+
class="btn"
|
|
12
|
+
?disabled=${n.disabled||!n.dirty||!i}
|
|
13
|
+
@click=${n.onSave}
|
|
14
|
+
>
|
|
15
|
+
${n.saving?`Saving…`:`Save`}
|
|
16
|
+
</button>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
${v(n)}
|
|
20
|
+
${r?e`
|
|
21
|
+
${y(n)} ${b(n)}
|
|
22
|
+
${n.selectedScope===s?t:x(n)}
|
|
23
|
+
`:e`<div class="row" style="margin-top: 12px; gap: 12px;">
|
|
24
|
+
<div class="muted">Load exec approvals to edit allowlists.</div>
|
|
25
|
+
<button class="btn" ?disabled=${n.loading||!i} @click=${n.onLoad}>
|
|
26
|
+
${n.loading?`Loading…`:`Load approvals`}
|
|
27
|
+
</button>
|
|
28
|
+
</div>`}
|
|
29
|
+
</section>
|
|
30
|
+
`}function v(n){let r=n.targetNodes.length>0,i=n.targetNodeId??``;return e`
|
|
31
|
+
<div class="list" style="margin-top: 12px;">
|
|
32
|
+
<div class="list-item">
|
|
33
|
+
<div class="list-main">
|
|
34
|
+
<div class="list-title">Target</div>
|
|
35
|
+
<div class="list-sub">Gateway edits local approvals; node edits the selected node.</div>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="list-meta">
|
|
38
|
+
<label class="field">
|
|
39
|
+
<span>Host</span>
|
|
40
|
+
<select
|
|
41
|
+
?disabled=${n.disabled}
|
|
42
|
+
@change=${e=>{if(e.target.value===`node`){let e=n.targetNodes[0]?.id??null;n.onSelectTarget(`node`,i||e)}else n.onSelectTarget(`gateway`,null)}}
|
|
43
|
+
>
|
|
44
|
+
<option value="gateway" ?selected=${n.target===`gateway`}>Gateway</option>
|
|
45
|
+
<option value="node" ?selected=${n.target===`node`}>Node</option>
|
|
46
|
+
</select>
|
|
47
|
+
</label>
|
|
48
|
+
${n.target===`node`?e`
|
|
49
|
+
<label class="field">
|
|
50
|
+
<span>Node</span>
|
|
51
|
+
<select
|
|
52
|
+
?disabled=${n.disabled||!r}
|
|
53
|
+
@change=${e=>{let t=e.target.value.trim();n.onSelectTarget(`node`,t||null)}}
|
|
54
|
+
>
|
|
55
|
+
<option value="" ?selected=${i===``}>Select node</option>
|
|
56
|
+
${n.targetNodes.map(t=>e`<option value=${t.id} ?selected=${i===t.id}>
|
|
57
|
+
${t.label}
|
|
58
|
+
</option>`)}
|
|
59
|
+
</select>
|
|
60
|
+
</label>
|
|
61
|
+
`:t}
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
${n.target===`node`&&!r?e` <div class="muted">No nodes advertise exec approvals yet.</div> `:t}
|
|
65
|
+
</div>
|
|
66
|
+
`}function y(t){return e`
|
|
67
|
+
<div class="row" style="margin-top: 12px; gap: 8px; flex-wrap: wrap;">
|
|
68
|
+
<span class="label">Scope</span>
|
|
69
|
+
<div class="row" style="gap: 8px; flex-wrap: wrap;">
|
|
70
|
+
<button
|
|
71
|
+
class="btn btn--sm ${t.selectedScope===s?`active`:``}"
|
|
72
|
+
@click=${()=>t.onSelectScope(s)}
|
|
73
|
+
>
|
|
74
|
+
Defaults
|
|
75
|
+
</button>
|
|
76
|
+
${t.agents.map(n=>{let r=n.name?.trim()?`${n.name} (${n.id})`:n.id;return e`
|
|
77
|
+
<button
|
|
78
|
+
class="btn btn--sm ${t.selectedScope===n.id?`active`:``}"
|
|
79
|
+
@click=${()=>t.onSelectScope(n.id)}
|
|
80
|
+
>
|
|
81
|
+
${r}
|
|
82
|
+
</button>
|
|
83
|
+
`})}
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
`}function b(n){let r=n.selectedScope===s,i=n.defaults,a=n.selectedAgent??{},o=r?[`defaults`]:[`agents`,n.selectedScope],u=typeof a.security==`string`?a.security:void 0,d=typeof a.ask==`string`?a.ask:void 0,f=typeof a.askFallback==`string`?a.askFallback:void 0,p=r?i.security:u??`__default__`,m=r?i.ask:d??`__default__`,h=r?i.askFallback:f??`__default__`,g=typeof a.autoAllowSkills==`boolean`?a.autoAllowSkills:void 0,_=g??i.autoAllowSkills,v=g==null;return e`
|
|
87
|
+
<div class="list" style="margin-top: 16px;">
|
|
88
|
+
<div class="list-item">
|
|
89
|
+
<div class="list-main">
|
|
90
|
+
<div class="list-title">Security</div>
|
|
91
|
+
<div class="list-sub">
|
|
92
|
+
${r?`Default security mode.`:`Default: ${i.security}.`}
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
<div class="list-meta">
|
|
96
|
+
<label class="field">
|
|
97
|
+
<span>Mode</span>
|
|
98
|
+
<select
|
|
99
|
+
?disabled=${n.disabled}
|
|
100
|
+
@change=${e=>{let t=e.target.value;!r&&t===`__default__`?n.onRemove([...o,`security`]):n.onPatch([...o,`security`],t)}}
|
|
101
|
+
>
|
|
102
|
+
${r?t:e`<option value="__default__" ?selected=${p===`__default__`}>
|
|
103
|
+
Use default (${i.security})
|
|
104
|
+
</option>`}
|
|
105
|
+
${c.map(t=>e`<option value=${t.value} ?selected=${p===t.value}>
|
|
106
|
+
${t.label}
|
|
107
|
+
</option>`)}
|
|
108
|
+
</select>
|
|
109
|
+
</label>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<div class="list-item">
|
|
114
|
+
<div class="list-main">
|
|
115
|
+
<div class="list-title">Ask</div>
|
|
116
|
+
<div class="list-sub">
|
|
117
|
+
${r?`Default prompt policy.`:`Default: ${i.ask}.`}
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
<div class="list-meta">
|
|
121
|
+
<label class="field">
|
|
122
|
+
<span>Mode</span>
|
|
123
|
+
<select
|
|
124
|
+
?disabled=${n.disabled}
|
|
125
|
+
@change=${e=>{let t=e.target.value;!r&&t===`__default__`?n.onRemove([...o,`ask`]):n.onPatch([...o,`ask`],t)}}
|
|
126
|
+
>
|
|
127
|
+
${r?t:e`<option value="__default__" ?selected=${m===`__default__`}>
|
|
128
|
+
Use default (${i.ask})
|
|
129
|
+
</option>`}
|
|
130
|
+
${l.map(t=>e`<option value=${t.value} ?selected=${m===t.value}>
|
|
131
|
+
${t.label}
|
|
132
|
+
</option>`)}
|
|
133
|
+
</select>
|
|
134
|
+
</label>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<div class="list-item">
|
|
139
|
+
<div class="list-main">
|
|
140
|
+
<div class="list-title">Ask fallback</div>
|
|
141
|
+
<div class="list-sub">
|
|
142
|
+
${r?`Applied when the UI prompt is unavailable.`:`Default: ${i.askFallback}.`}
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
<div class="list-meta">
|
|
146
|
+
<label class="field">
|
|
147
|
+
<span>Fallback</span>
|
|
148
|
+
<select
|
|
149
|
+
?disabled=${n.disabled}
|
|
150
|
+
@change=${e=>{let t=e.target.value;!r&&t===`__default__`?n.onRemove([...o,`askFallback`]):n.onPatch([...o,`askFallback`],t)}}
|
|
151
|
+
>
|
|
152
|
+
${r?t:e`<option value="__default__" ?selected=${h===`__default__`}>
|
|
153
|
+
Use default (${i.askFallback})
|
|
154
|
+
</option>`}
|
|
155
|
+
${c.map(t=>e`<option value=${t.value} ?selected=${h===t.value}>
|
|
156
|
+
${t.label}
|
|
157
|
+
</option>`)}
|
|
158
|
+
</select>
|
|
159
|
+
</label>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
<div class="list-item">
|
|
164
|
+
<div class="list-main">
|
|
165
|
+
<div class="list-title">Auto-allow skill CLIs</div>
|
|
166
|
+
<div class="list-sub">
|
|
167
|
+
${r?`Allow skill executables listed by the Gateway.`:v?`Using default (${i.autoAllowSkills?`on`:`off`}).`:`Override (${_?`on`:`off`}).`}
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
<div class="list-meta">
|
|
171
|
+
<label class="field">
|
|
172
|
+
<span>Enabled</span>
|
|
173
|
+
<input
|
|
174
|
+
type="checkbox"
|
|
175
|
+
?disabled=${n.disabled}
|
|
176
|
+
.checked=${_}
|
|
177
|
+
@change=${e=>{let t=e.target;n.onPatch([...o,`autoAllowSkills`],t.checked)}}
|
|
178
|
+
/>
|
|
179
|
+
</label>
|
|
180
|
+
${!r&&!v?e`<button
|
|
181
|
+
class="btn btn--sm"
|
|
182
|
+
?disabled=${n.disabled}
|
|
183
|
+
@click=${()=>n.onRemove([...o,`autoAllowSkills`])}
|
|
184
|
+
>
|
|
185
|
+
Use default
|
|
186
|
+
</button>`:t}
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
`}function x(t){let n=[`agents`,t.selectedScope,`allowlist`],r=t.allowlist;return e`
|
|
191
|
+
<div class="row" style="margin-top: 18px; justify-content: space-between;">
|
|
192
|
+
<div>
|
|
193
|
+
<div class="card-title">Allowlist</div>
|
|
194
|
+
<div class="card-sub">Case-insensitive glob patterns.</div>
|
|
195
|
+
</div>
|
|
196
|
+
<button
|
|
197
|
+
class="btn btn--sm"
|
|
198
|
+
?disabled=${t.disabled}
|
|
199
|
+
@click=${()=>{let e=[...r,{pattern:``}];t.onPatch(n,e)}}
|
|
200
|
+
>
|
|
201
|
+
Add pattern
|
|
202
|
+
</button>
|
|
203
|
+
</div>
|
|
204
|
+
<div class="list" style="margin-top: 12px;">
|
|
205
|
+
${r.length===0?e` <div class="muted">No allowlist entries yet.</div> `:r.map((e,n)=>S(t,e,n))}
|
|
206
|
+
</div>
|
|
207
|
+
`}function S(r,a,o){let s=a.lastUsedAt?n(a.lastUsedAt):`never`,c=a.lastUsedCommand?i(a.lastUsedCommand,120):null,l=a.lastResolvedPath?i(a.lastResolvedPath,120):null;return e`
|
|
208
|
+
<div class="list-item">
|
|
209
|
+
<div class="list-main">
|
|
210
|
+
<div class="list-title">${a.pattern?.trim()?a.pattern:`New pattern`}</div>
|
|
211
|
+
<div class="list-sub">Last used: ${s}</div>
|
|
212
|
+
${c?e`<div class="list-sub mono">${c}</div>`:t}
|
|
213
|
+
${l?e`<div class="list-sub mono">${l}</div>`:t}
|
|
214
|
+
</div>
|
|
215
|
+
<div class="list-meta">
|
|
216
|
+
<label class="field">
|
|
217
|
+
<span>Pattern</span>
|
|
218
|
+
<input
|
|
219
|
+
type="text"
|
|
220
|
+
.value=${a.pattern??``}
|
|
221
|
+
?disabled=${r.disabled}
|
|
222
|
+
@input=${e=>{let t=e.target;r.onPatch([`agents`,r.selectedScope,`allowlist`,o,`pattern`],t.value)}}
|
|
223
|
+
/>
|
|
224
|
+
</label>
|
|
225
|
+
<button
|
|
226
|
+
class="btn btn--sm danger"
|
|
227
|
+
?disabled=${r.disabled}
|
|
228
|
+
@click=${()=>{if(r.allowlist.length<=1){r.onRemove([`agents`,r.selectedScope,`allowlist`]);return}r.onRemove([`agents`,r.selectedScope,`allowlist`,o])}}
|
|
229
|
+
>
|
|
230
|
+
Remove
|
|
231
|
+
</button>
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
`}function C(e){return o(e,[`system.execApprovals.get`,`system.execApprovals.set`])}function w(t){let n=k(t);return e`
|
|
235
|
+
${_(g(t))} ${A(n)} ${T(t)}
|
|
236
|
+
<section class="card">
|
|
237
|
+
<div class="row" style="justify-content: space-between;">
|
|
238
|
+
<div>
|
|
239
|
+
<div class="card-title">Nodes</div>
|
|
240
|
+
<div class="card-sub">Paired devices and live links.</div>
|
|
241
|
+
</div>
|
|
242
|
+
<button class="btn" ?disabled=${t.loading} @click=${t.onRefresh}>
|
|
243
|
+
${t.loading?`Loading…`:`Refresh`}
|
|
244
|
+
</button>
|
|
245
|
+
</div>
|
|
246
|
+
<div class="list" style="margin-top: 16px;">
|
|
247
|
+
${t.nodes.length===0?e` <div class="muted">No nodes found.</div> `:t.nodes.map(e=>P(e))}
|
|
248
|
+
</div>
|
|
249
|
+
</section>
|
|
250
|
+
`}function T(n){let r=n.devicesList??{pending:[],paired:[]},i=Array.isArray(r.pending)?r.pending:[],a=Array.isArray(r.paired)?r.paired:[];return e`
|
|
251
|
+
<section class="card">
|
|
252
|
+
<div class="row" style="justify-content: space-between;">
|
|
253
|
+
<div>
|
|
254
|
+
<div class="card-title">Devices</div>
|
|
255
|
+
<div class="card-sub">Pairing requests + role tokens.</div>
|
|
256
|
+
</div>
|
|
257
|
+
<button class="btn" ?disabled=${n.devicesLoading} @click=${n.onDevicesRefresh}>
|
|
258
|
+
${n.devicesLoading?`Loading…`:`Refresh`}
|
|
259
|
+
</button>
|
|
260
|
+
</div>
|
|
261
|
+
${n.devicesError?e`<div class="callout danger" style="margin-top: 12px;">${n.devicesError}</div>`:t}
|
|
262
|
+
<div class="list" style="margin-top: 16px;">
|
|
263
|
+
${i.length>0?e`
|
|
264
|
+
<div class="muted" style="margin-bottom: 8px;">Pending</div>
|
|
265
|
+
${i.map(e=>E(e,n))}
|
|
266
|
+
`:t}
|
|
267
|
+
${a.length>0?e`
|
|
268
|
+
<div class="muted" style="margin-top: 12px; margin-bottom: 8px;">Paired</div>
|
|
269
|
+
${a.map(e=>D(e,n))}
|
|
270
|
+
`:t}
|
|
271
|
+
${i.length===0&&a.length===0?e` <div class="muted">No paired devices.</div> `:t}
|
|
272
|
+
</div>
|
|
273
|
+
</section>
|
|
274
|
+
`}function E(t,i){let a=t.displayName?.trim()||t.deviceId,o=typeof t.ts==`number`?n(t.ts):`n/a`,s=t.role?.trim()||r(t.roles),c=r(t.scopes),l=t.isRepair?` · repair`:``,u=t.remoteIp?` · ${t.remoteIp}`:``;return e`
|
|
275
|
+
<div class="list-item">
|
|
276
|
+
<div class="list-main">
|
|
277
|
+
<div class="list-title">${a}</div>
|
|
278
|
+
<div class="list-sub">${t.deviceId}${u}</div>
|
|
279
|
+
<div class="muted" style="margin-top: 6px;">
|
|
280
|
+
role: ${s} · scopes: ${c} · requested ${o}${l}
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
<div class="list-meta">
|
|
284
|
+
<div class="row" style="justify-content: flex-end; gap: 8px; flex-wrap: wrap;">
|
|
285
|
+
<button class="btn btn--sm primary" @click=${()=>i.onDeviceApprove(t.requestId)}>
|
|
286
|
+
Approve
|
|
287
|
+
</button>
|
|
288
|
+
<button class="btn btn--sm" @click=${()=>i.onDeviceReject(t.requestId)}>
|
|
289
|
+
Reject
|
|
290
|
+
</button>
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
294
|
+
`}function D(t,n){let i=t.displayName?.trim()||t.deviceId,a=t.remoteIp?` · ${t.remoteIp}`:``,o=`roles: ${r(t.roles)}`,s=`scopes: ${r(t.scopes)}`,c=Array.isArray(t.tokens)?t.tokens:[];return e`
|
|
295
|
+
<div class="list-item">
|
|
296
|
+
<div class="list-main">
|
|
297
|
+
<div class="list-title">${i}</div>
|
|
298
|
+
<div class="list-sub">${t.deviceId}${a}</div>
|
|
299
|
+
<div class="muted" style="margin-top: 6px;">${o} · ${s}</div>
|
|
300
|
+
${c.length===0?e` <div class="muted" style="margin-top: 6px">Tokens: none</div> `:e`
|
|
301
|
+
<div class="muted" style="margin-top: 10px;">Tokens</div>
|
|
302
|
+
<div style="display: flex; flex-direction: column; gap: 8px; margin-top: 6px;">
|
|
303
|
+
${c.map(e=>O(t.deviceId,e,n))}
|
|
304
|
+
</div>
|
|
305
|
+
`}
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
`}function O(i,a,o){let s=a.revokedAtMs?`revoked`:`active`,c=`scopes: ${r(a.scopes)}`,l=n(a.rotatedAtMs??a.createdAtMs??a.lastUsedAtMs??null);return e`
|
|
309
|
+
<div class="row" style="justify-content: space-between; gap: 8px;">
|
|
310
|
+
<div class="list-sub">${a.role} · ${s} · ${c} · ${l}</div>
|
|
311
|
+
<div class="row" style="justify-content: flex-end; gap: 6px; flex-wrap: wrap;">
|
|
312
|
+
<button
|
|
313
|
+
class="btn btn--sm"
|
|
314
|
+
@click=${()=>o.onDeviceRotate(i,a.role,a.scopes)}
|
|
315
|
+
>
|
|
316
|
+
Rotate
|
|
317
|
+
</button>
|
|
318
|
+
${a.revokedAtMs?t:e`
|
|
319
|
+
<button
|
|
320
|
+
class="btn btn--sm danger"
|
|
321
|
+
@click=${()=>o.onDeviceRevoke(i,a.role)}
|
|
322
|
+
>
|
|
323
|
+
Revoke
|
|
324
|
+
</button>
|
|
325
|
+
`}
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
`}function k(e){let t=e.configForm,n=M(e.nodes),{defaultBinding:r,agents:i}=N(t);return{ready:!!t,disabled:e.configSaving||e.configFormMode===`raw`,configDirty:e.configDirty,configLoading:e.configLoading,configSaving:e.configSaving,defaultBinding:r,agents:i,nodes:n,onBindDefault:e.onBindDefault,onBindAgent:e.onBindAgent,onSave:e.onSaveBindings,onLoadConfig:e.onLoadConfig,formMode:e.configFormMode}}function A(n){let r=n.nodes.length>0,i=n.defaultBinding??``;return e`
|
|
329
|
+
<section class="card">
|
|
330
|
+
<div class="row" style="justify-content: space-between; align-items: center;">
|
|
331
|
+
<div>
|
|
332
|
+
<div class="card-title">Exec node binding</div>
|
|
333
|
+
<div class="card-sub">
|
|
334
|
+
Pin agents to a specific node when using <span class="mono">exec host=node</span>.
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
<button
|
|
338
|
+
class="btn"
|
|
339
|
+
?disabled=${n.disabled||!n.configDirty}
|
|
340
|
+
@click=${n.onSave}
|
|
341
|
+
>
|
|
342
|
+
${n.configSaving?`Saving…`:`Save`}
|
|
343
|
+
</button>
|
|
344
|
+
</div>
|
|
345
|
+
|
|
346
|
+
${n.formMode===`raw`?e`
|
|
347
|
+
<div class="callout warn" style="margin-top: 12px">
|
|
348
|
+
Switch the Config tab to <strong>Form</strong> mode to edit bindings here.
|
|
349
|
+
</div>
|
|
350
|
+
`:t}
|
|
351
|
+
${n.ready?e`
|
|
352
|
+
<div class="list" style="margin-top: 16px;">
|
|
353
|
+
<div class="list-item">
|
|
354
|
+
<div class="list-main">
|
|
355
|
+
<div class="list-title">Default binding</div>
|
|
356
|
+
<div class="list-sub">Used when agents do not override a node binding.</div>
|
|
357
|
+
</div>
|
|
358
|
+
<div class="list-meta">
|
|
359
|
+
<label class="field">
|
|
360
|
+
<span>Node</span>
|
|
361
|
+
<select
|
|
362
|
+
?disabled=${n.disabled||!r}
|
|
363
|
+
@change=${e=>{let t=e.target.value.trim();n.onBindDefault(t||null)}}
|
|
364
|
+
>
|
|
365
|
+
<option value="" ?selected=${i===``}>Any node</option>
|
|
366
|
+
${n.nodes.map(t=>e`<option value=${t.id} ?selected=${i===t.id}>
|
|
367
|
+
${t.label}
|
|
368
|
+
</option>`)}
|
|
369
|
+
</select>
|
|
370
|
+
</label>
|
|
371
|
+
${r?t:e` <div class="muted">No nodes with system.run available.</div> `}
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
|
|
375
|
+
${n.agents.length===0?e` <div class="muted">No agents found.</div> `:n.agents.map(e=>j(e,n))}
|
|
376
|
+
</div>
|
|
377
|
+
`:e`<div class="row" style="margin-top: 12px; gap: 12px;">
|
|
378
|
+
<div class="muted">Load config to edit bindings.</div>
|
|
379
|
+
<button class="btn" ?disabled=${n.configLoading} @click=${n.onLoadConfig}>
|
|
380
|
+
${n.configLoading?`Loading…`:`Load config`}
|
|
381
|
+
</button>
|
|
382
|
+
</div>`}
|
|
383
|
+
</section>
|
|
384
|
+
`}function j(t,n){let r=t.binding??`__default__`,i=t.name?.trim()?`${t.name} (${t.id})`:t.id,a=n.nodes.length>0;return e`
|
|
385
|
+
<div class="list-item">
|
|
386
|
+
<div class="list-main">
|
|
387
|
+
<div class="list-title">${i}</div>
|
|
388
|
+
<div class="list-sub">
|
|
389
|
+
${t.isDefault?`default agent`:`agent`} ·
|
|
390
|
+
${r===`__default__`?`uses default (${n.defaultBinding??`any`})`:`override: ${t.binding}`}
|
|
391
|
+
</div>
|
|
392
|
+
</div>
|
|
393
|
+
<div class="list-meta">
|
|
394
|
+
<label class="field">
|
|
395
|
+
<span>Binding</span>
|
|
396
|
+
<select
|
|
397
|
+
?disabled=${n.disabled||!a}
|
|
398
|
+
@change=${e=>{let r=e.target.value.trim();n.onBindAgent(t.index,r===`__default__`?null:r)}}
|
|
399
|
+
>
|
|
400
|
+
<option value="__default__" ?selected=${r===`__default__`}>
|
|
401
|
+
Use default
|
|
402
|
+
</option>
|
|
403
|
+
${n.nodes.map(t=>e`<option value=${t.id} ?selected=${r===t.id}>
|
|
404
|
+
${t.label}
|
|
405
|
+
</option>`)}
|
|
406
|
+
</select>
|
|
407
|
+
</label>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
`}function M(e){return o(e,[`system.run`])}function N(e){let t={id:`main`,name:void 0,index:0,isDefault:!0,binding:null};if(!e||typeof e!=`object`)return{defaultBinding:null,agents:[t]};let n=(e.tools??{}).exec??{},r=typeof n.node==`string`&&n.node.trim()?n.node.trim():null,i=e.agents??{};if(!Array.isArray(i.list)||i.list.length===0)return{defaultBinding:r,agents:[t]};let o=a(e).map(e=>{let t=(e.record.tools??{}).exec??{},n=typeof t.node==`string`&&t.node.trim()?t.node.trim():null;return{id:e.id,name:e.name,index:e.index,isDefault:e.isDefault,binding:n}});return o.length===0&&o.push(t),{defaultBinding:r,agents:o}}function P(t){let n=!!t.connected,r=!!t.paired,i=typeof t.displayName==`string`&&t.displayName.trim()||(typeof t.nodeId==`string`?t.nodeId:`unknown`),a=Array.isArray(t.caps)?t.caps:[],o=Array.isArray(t.commands)?t.commands:[];return e`
|
|
411
|
+
<div class="list-item">
|
|
412
|
+
<div class="list-main">
|
|
413
|
+
<div class="list-title">${i}</div>
|
|
414
|
+
<div class="list-sub">
|
|
415
|
+
${typeof t.nodeId==`string`?t.nodeId:``}
|
|
416
|
+
${typeof t.remoteIp==`string`?` · ${t.remoteIp}`:``}
|
|
417
|
+
${typeof t.version==`string`?` · ${t.version}`:``}
|
|
418
|
+
</div>
|
|
419
|
+
<div class="chip-row" style="margin-top: 6px;">
|
|
420
|
+
<span class="chip">${r?`paired`:`unpaired`}</span>
|
|
421
|
+
<span class="chip ${n?`chip-ok`:`chip-warn`}">
|
|
422
|
+
${n?`connected`:`offline`}
|
|
423
|
+
</span>
|
|
424
|
+
${a.slice(0,12).map(t=>e`<span class="chip">${String(t)}</span>`)}
|
|
425
|
+
${o.slice(0,8).map(t=>e`<span class="chip">${String(t)}</span>`)}
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
428
|
+
</div>
|
|
429
|
+
`}export{w as renderNodes};
|
|
430
|
+
//# sourceMappingURL=nodes-6XxETMb5.js.map
|