@lmctl-ai/lmctl 0.2.38 → 0.2.40
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 +16 -0
- package/bin/lmbee +2 -0
- package/bin/lmscript +3 -0
- package/build-info.json +1 -0
- package/dist/cli/index.js +485 -460
- package/dist/cli/schema.sql +0 -169
- package/dist/cli/script.js +246 -246
- package/dist/lmbee.js +960 -0
- package/dist/lmscript.js +388 -0
- package/dist/public/app.js +379 -0
- package/dist/public/index.html +78 -0
- package/dist/public/styles.css +160 -0
- package/dist/schema.sql +455 -0
- package/dist/vendor-webui/index.html +18 -0
- package/dist/vendor-webui/local.js +231 -0
- package/dist/vendor-webui/styles.css +1852 -0
- package/package.json +11 -7
- package/dist/cli/batch.d.ts +0 -2
- package/dist/cli/busy-evidence.d.ts +0 -27
- package/dist/cli/chat-cycle.d.ts +0 -59
- package/dist/cli/chat-exec.d.ts +0 -91
- package/dist/cli/chat-policy.d.ts +0 -22
- package/dist/cli/chat.d.ts +0 -14
- package/dist/cli/code-resolver.d.ts +0 -8
- package/dist/cli/common.d.ts +0 -57
- package/dist/cli/context.d.ts +0 -12
- package/dist/cli/cost.d.ts +0 -2
- package/dist/cli/export.d.ts +0 -2
- package/dist/cli/hello.d.ts +0 -10
- package/dist/cli/index.d.ts +0 -3
- package/dist/cli/infra.d.ts +0 -78
- package/dist/cli/init.d.ts +0 -8
- package/dist/cli/intent-input.d.ts +0 -16
- package/dist/cli/intent-match.d.ts +0 -30
- package/dist/cli/intent-sessions.d.ts +0 -24
- package/dist/cli/intent-team.d.ts +0 -25
- package/dist/cli/intent.d.ts +0 -22
- package/dist/cli/ls.d.ts +0 -2
- package/dist/cli/mailbox-cli.d.ts +0 -6
- package/dist/cli/managed.d.ts +0 -62
- package/dist/cli/mcp-install.d.ts +0 -23
- package/dist/cli/mcp.d.ts +0 -2
- package/dist/cli/model.d.ts +0 -21
- package/dist/cli/paths.d.ts +0 -50
- package/dist/cli/plan-wizard.d.ts +0 -42
- package/dist/cli/plan.d.ts +0 -20
- package/dist/cli/queue-delivery.d.ts +0 -122
- package/dist/cli/quickrun.d.ts +0 -14
- package/dist/cli/ratelimit.d.ts +0 -2
- package/dist/cli/remote-fetch.d.ts +0 -7
- package/dist/cli/run-queries.d.ts +0 -82
- package/dist/cli/running.d.ts +0 -5
- package/dist/cli/save-script.d.ts +0 -41
- package/dist/cli/script.d.ts +0 -6
- package/dist/cli/seed-flight.d.ts +0 -2
- package/dist/cli/self-identity.d.ts +0 -25
- package/dist/cli/session-idle.d.ts +0 -118
- package/dist/cli/status.d.ts +0 -22
- package/dist/cli/tail.d.ts +0 -18
- package/dist/cli/target-resolver.d.ts +0 -139
- package/dist/cli/team-status.d.ts +0 -91
- package/dist/cli/teamfile-compat.d.ts +0 -116
- package/dist/cli/teamfile-store.d.ts +0 -18
- package/dist/cli/teamfile-template.d.ts +0 -47
- package/dist/cli/template-env.d.ts +0 -25
- package/dist/cli/terminal-lock.d.ts +0 -25
- package/dist/cli/terminal.d.ts +0 -23
- package/dist/cli/time-filter.d.ts +0 -10
- package/dist/cli/update-notifier.d.ts +0 -11
- package/dist/cli/version-util.d.ts +0 -23
- package/dist/config/seed_templates.d.ts +0 -1
- package/dist/db/backfill-event-log.d.ts +0 -26
- package/dist/db/delegation.d.ts +0 -37
- package/dist/db/escalation_vocab.d.ts +0 -45
- package/dist/db/event-log.d.ts +0 -40
- package/dist/db/index.d.ts +0 -1213
- package/dist/db/inflight-acquire.d.ts +0 -70
- package/dist/db/invocation-event-projections.d.ts +0 -65
- package/dist/db/ledger-identity.test.d.ts +0 -1
- package/dist/db/live-event-projections.d.ts +0 -92
- package/dist/db/migrate.d.ts +0 -51
- package/dist/db/open-readonly.d.ts +0 -2
- package/dist/db/process-liveness.d.ts +0 -37
- package/dist/db/sqlite.d.ts +0 -53
- package/dist/db/sqlite.test.d.ts +0 -1
- package/dist/db/terminal-lock.d.ts +0 -14
- package/dist/db/tracked-invocation-reconcile.d.ts +0 -52
- package/dist/db/tracked-invocation.d.ts +0 -116
- package/dist/mcp/dispatch.d.ts +0 -45
- package/dist/mcp/mediation.d.ts +0 -128
- package/dist/mcp/path-warning.d.ts +0 -7
- package/dist/mcp/server.d.ts +0 -63
- package/dist/mcp/tools.d.ts +0 -24
- package/dist/providers/adapter.d.ts +0 -271
- package/dist/providers/adapters/agy-adapter.d.ts +0 -18
- package/dist/providers/adapters/claude-adapter.d.ts +0 -20
- package/dist/providers/adapters/codex-adapter.d.ts +0 -22
- package/dist/providers/adapters/copilot-adapter.d.ts +0 -16
- package/dist/providers/adapters/dsh-adapter.d.ts +0 -89
- package/dist/providers/adapters/gemini-adapter.d.ts +0 -44
- package/dist/providers/adapters/hermes-adapter.d.ts +0 -71
- package/dist/providers/adapters/index.d.ts +0 -35
- package/dist/providers/adapters/kimi-adapter.d.ts +0 -16
- package/dist/providers/adapters/lmplayer-adapter.d.ts +0 -14
- package/dist/providers/adapters/opencode-adapter.d.ts +0 -11
- package/dist/providers/adapters/pi-adapter.d.ts +0 -17
- package/dist/providers/adapters/print-turn.d.ts +0 -29
- package/dist/providers/adapters/qwen-adapter.d.ts +0 -11
- package/dist/providers/agy.d.ts +0 -32
- package/dist/providers/base-adapter.d.ts +0 -110
- package/dist/providers/base.d.ts +0 -12
- package/dist/providers/binary-check.d.ts +0 -102
- package/dist/providers/bundle.d.ts +0 -124
- package/dist/providers/claude-mock.d.ts +0 -90
- package/dist/providers/claude.d.ts +0 -21
- package/dist/providers/codex-config.d.ts +0 -15
- package/dist/providers/codex.d.ts +0 -25
- package/dist/providers/config/init-config.d.ts +0 -59
- package/dist/providers/config/init-edit.d.ts +0 -3
- package/dist/providers/config/init-file.d.ts +0 -20
- package/dist/providers/config/init-write.d.ts +0 -2
- package/dist/providers/config/model-selection-lint.d.ts +0 -70
- package/dist/providers/config/team-config.d.ts +0 -184
- package/dist/providers/config/types.d.ts +0 -146
- package/dist/providers/config/user-config.d.ts +0 -88
- package/dist/providers/copilot.d.ts +0 -21
- package/dist/providers/debug.d.ts +0 -128
- package/dist/providers/dsh-sidecar.d.ts +0 -65
- package/dist/providers/dsh-zstd.d.ts +0 -27
- package/dist/providers/dsh.d.ts +0 -37
- package/dist/providers/frontmatter.d.ts +0 -46
- package/dist/providers/gemini-session-reader.d.ts +0 -151
- package/dist/providers/gemini.d.ts +0 -39
- package/dist/providers/hermes.d.ts +0 -90
- package/dist/providers/index.d.ts +0 -423
- package/dist/providers/kimi.d.ts +0 -37
- package/dist/providers/model-catalog.d.ts +0 -145
- package/dist/providers/model-suggestions.d.ts +0 -4
- package/dist/providers/one-shot-timeout.d.ts +0 -1
- package/dist/providers/opencode-config.d.ts +0 -62
- package/dist/providers/opencode.d.ts +0 -40
- package/dist/providers/parsers/acp.d.ts +0 -71
- package/dist/providers/parsers/codex-app-server.d.ts +0 -60
- package/dist/providers/parsers/stream-json.d.ts +0 -57
- package/dist/providers/passive-readers/agy.d.ts +0 -155
- package/dist/providers/passive-readers/copilot.d.ts +0 -173
- package/dist/providers/passive-readers/dsh.d.ts +0 -34
- package/dist/providers/passive-readers/kimi.d.ts +0 -44
- package/dist/providers/passive-readers/opencode.d.ts +0 -89
- package/dist/providers/passive-readers/qwen.d.ts +0 -151
- package/dist/providers/passive-readers/shared.d.ts +0 -138
- package/dist/providers/passive-session-reader.d.ts +0 -188
- package/dist/providers/path-utils.d.ts +0 -1
- package/dist/providers/pi.d.ts +0 -32
- package/dist/providers/pricing.d.ts +0 -107
- package/dist/providers/qwen.d.ts +0 -22
- package/dist/providers/ratelimit/agy.d.ts +0 -22
- package/dist/providers/ratelimit/claude-auth.d.ts +0 -13
- package/dist/providers/ratelimit/claude.d.ts +0 -6
- package/dist/providers/ratelimit/codex.d.ts +0 -7
- package/dist/providers/ratelimit/kimi-auth.d.ts +0 -15
- package/dist/providers/ratelimit/kimi.d.ts +0 -6
- package/dist/providers/ratelimit/schema.d.ts +0 -28
- package/dist/providers/ratelimit-readings.d.ts +0 -19
- package/dist/providers/registry.d.ts +0 -31
- package/dist/providers/resume.d.ts +0 -43
- package/dist/providers/seed-instruction.d.ts +0 -3
- package/dist/providers/self-session-env.d.ts +0 -21
- package/dist/providers/session-limit.d.ts +0 -9
- package/dist/providers/strip-ansi.d.ts +0 -5
- package/dist/providers/transport-errors.d.ts +0 -94
- package/dist/providers/transport-lifecycle.d.ts +0 -63
- package/dist/providers/transport-wrappers.d.ts +0 -110
- package/dist/providers/transports/acp-profiles/config-option-step.d.ts +0 -24
- package/dist/providers/transports/acp-profiles/copilot.d.ts +0 -12
- package/dist/providers/transports/acp-profiles/gemini.d.ts +0 -22
- package/dist/providers/transports/acp-profiles/hermes.d.ts +0 -27
- package/dist/providers/transports/acp-profiles/index.d.ts +0 -19
- package/dist/providers/transports/acp-profiles/kimi.d.ts +0 -24
- package/dist/providers/transports/acp-profiles/opencode.d.ts +0 -26
- package/dist/providers/transports/acp-profiles/types.d.ts +0 -258
- package/dist/providers/transports/acp-rpc.d.ts +0 -18
- package/dist/providers/transports/acp.d.ts +0 -217
- package/dist/providers/transports/codex-app-server.d.ts +0 -190
- package/dist/providers/transports/hold-open.d.ts +0 -120
- package/dist/providers/transports/manager.d.ts +0 -21
- package/dist/providers/transports/stream-json.d.ts +0 -162
- package/dist/providers/transports/types.d.ts +0 -56
- package/dist/providers/types.d.ts +0 -154
- package/dist/providers/yolo-contract.d.ts +0 -131
- package/dist/script/adapter.d.ts +0 -107
- package/dist/script/batch-script.d.ts +0 -7
- package/dist/script/index.d.ts +0 -3
- package/dist/script/init-environment.d.ts +0 -8
- package/dist/script/lmbee-module.d.ts +0 -2
- package/dist/script/lmscript.d.ts +0 -647
- package/dist/shared/policy.d.ts +0 -74
- package/dist/shared-lib/db.d.ts +0 -25
- package/dist/shared-lib/passive-session-reader.d.ts +0 -2
- package/dist/shared-lib/provider-parse.d.ts +0 -6
- package/dist/templates/basedir.d.ts +0 -52
- package/dist/uri/lmctl_uri.d.ts +0 -38
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";(()=>{function S(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function C(t,e){if(!e)return`<p class="muted" data-local-ran>ran: <code>${S(t)}</code></p>`;let r=Math.max(0,Math.round((Date.now()-Date.parse(e))/1e3));return`<p class="muted" data-local-ran>ran: <code>${S(t)}</code>, ${r}s ago</p>`}function F(t,e,r){return`
|
|
2
|
+
${C(e,r)}
|
|
3
|
+
<p data-local-account-whoami>
|
|
4
|
+
<strong>${S(t.label)}</strong> (<code>${S(t.userId)}</code>) \xB7 appkey source: ${S(t.appkeySource)}
|
|
5
|
+
</p>
|
|
6
|
+
`}function N(t){return`<p class="form-error" role="alert" data-local-account-whoami-error>${S(t)}</p>`}function O(t,e,r){return`
|
|
7
|
+
${C(e,r)}
|
|
8
|
+
<table class="local-table" data-local-account-mail-table>
|
|
9
|
+
<thead><tr><th>STATE</th><th>COUNT</th></tr></thead>
|
|
10
|
+
<tbody>
|
|
11
|
+
<tr><td>persisted</td><td>${t.counts.persisted}</td></tr>
|
|
12
|
+
<tr><td>dispatched</td><td>${t.counts.dispatched}</td></tr>
|
|
13
|
+
<tr><td>replied</td><td>${t.counts.replied}</td></tr>
|
|
14
|
+
<tr><td>failed</td><td>${t.counts.failed}</td></tr>
|
|
15
|
+
</tbody>
|
|
16
|
+
</table>
|
|
17
|
+
<p class="muted">retry-eligible: ${t.retryEligibleCount} \xB7 permanent: ${t.permanentCount} \xB7 due now: ${t.dueNowCount} \xB7 delivery errors: ${t.deliveryErrorCount}</p>
|
|
18
|
+
`}function W(t){return`<p class="form-error" role="alert" data-local-account-mail-error>${S(t)}</p>`}var U={id:"account",label:"Account",mount(t,e){let r=new AbortController;t.innerHTML=`
|
|
19
|
+
<section class="local-pane" data-local-pane="account">
|
|
20
|
+
<header><h2>Account</h2></header>
|
|
21
|
+
<div data-local-account-whoami-host><p class="muted" role="status">Loading identity\u2026</p></div>
|
|
22
|
+
<div data-local-account-mail-host><p class="muted" role="status">Loading mail status\u2026</p></div>
|
|
23
|
+
</section>
|
|
24
|
+
`;let a=t.querySelector("[data-local-account-whoami-host]"),s=t.querySelector("[data-local-account-mail-host]");return(async()=>{let i=await e.transport.read({kind:"whoami"},r.signal);if(!(r.signal.aborted||!a)){if(i.status==="error"){a.innerHTML=N(i.error.message);return}i.status!=="pending"&&(a.innerHTML=F(i.data,i.ranCommand,i.ranAt))}})(),(async()=>{let i=await e.transport.read({kind:"mail-status"},r.signal);if(!(r.signal.aborted||!s)){if(i.status==="error"){s.innerHTML=W(i.error.message);return}i.status!=="pending"&&(s.innerHTML=O(i.data,i.ranCommand,i.ranAt))}})(),()=>{r.abort()}}},E=U;function x(t){return t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function P(t,e){if(t&&typeof t=="object"&&"error"in t){let r=t.error;if(r&&typeof r=="object"){let a=r;if(typeof a.code=="string"&&typeof a.message=="string")return{code:a.code,message:a.message}}if(typeof r=="string")return{code:"http_error",message:r}}return{code:"http_error",message:`HTTP ${e}`}}function Q(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.name=="string"&&(e.channel==="local"||e.channel==="lmmail")}function B(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="number"&&typeof e.from_id=="string"&&typeof e.to_id=="string"&&typeof e.status=="string"}function G(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="number"&&typeof e.ts=="string"&&typeof e.team=="string"}function J(t){return!t||typeof t!="object"?!1:typeof t.team=="string"}function K(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="number"&&typeof e.path=="string"}function V(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.provider=="string"&&typeof e.sessionId=="string"&&Array.isArray(e.messages)}function z(t){if(!t||typeof t!="object")return!1;let e=t;return Array.isArray(e.running)&&Array.isArray(e.dead)&&Array.isArray(e.idle)}function X(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.userId=="string"&&typeof e.label=="string"}function Y(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.counts=="object"&&e.counts!==null}function Z(t){return!t||typeof t!="object"?!1:typeof t.team=="string"}function tt(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.live=="boolean"&&Array.isArray(e.teams)&&e.teams.every(Z)}var L=class{apiBase;constructor(e=""){this.apiBase=e}url(e){return`${this.apiBase}${e}`}async read(e,r){let a=()=>new Date().toISOString();if(e.kind==="teams")return this.get(this.url("api/teams"),"lmauto teams --json",n=>{let o=n;return Array.isArray(o.teams)?{teams:o.teams.filter(Q)}:null},a,r);if(e.kind==="queue-list"){let l=e.team?`?to=${encodeURIComponent(e.team)}`:"",n=e.team?`lmauto queue list ${e.team} --json`:"lmauto queue list --json";return this.get(this.url(`api/queue${l}`),n,o=>{let d=o;return Array.isArray(d.queue)?{queue:d.queue.filter(B)}:null},a,r)}if(e.kind==="history"){let l=new URLSearchParams;e.team&&l.set("team",e.team),e.limit!==void 0&&l.set("limit",String(e.limit));let n=l.toString(),o=`lmauto history${e.team?` ${e.team}`:""}${e.limit!==void 0?` ${e.limit}`:""} --json`;return this.get(this.url(`api/history${n?`?${n}`:""}`),o,d=>{let u=d;return Array.isArray(u.events)?{events:u.events.filter(G)}:null},a,r)}if(e.kind==="state-list")return this.get(this.url("api/state"),"lmauto state list --json",n=>{let o=n;return!Array.isArray(o.teams)||!Array.isArray(o.active)?null:{teams:o.teams.filter(J),active:o.active.filter(d=>typeof d=="string")}},a,r);if(e.kind==="sources")return this.get(this.url("api/sources"),"lmauto source list --json",n=>{let o=n;return typeof o.defaultTeamsConfPath!="string"||!Array.isArray(o.sources)?null:{defaultTeamsConfPath:o.defaultTeamsConfPath,sources:o.sources.filter(K)}},a,r);if(e.kind==="session"){let l=`lmctl session ${e.team} ${e.alias}`;return this.get(this.url(`api/session/${encodeURIComponent(e.team)}/${encodeURIComponent(e.alias)}`),l,n=>V(n)?n:null,a,r)}if(e.kind==="running")return this.get(this.url("api/running"),"lmctl running --json",n=>z(n)?n:null,a,r);if(e.kind==="whoami")return this.get(this.url("api/whoami"),"lmauto whoami --json",n=>X(n)?n:null,a,r);if(e.kind==="mail-status")return this.get(this.url("api/mail/status"),"lmauto mail status --json",n=>Y(n)?n:null,a,r);let s=e.live?"?live=1":"",i=e.live?"lmauto status --live --json":"lmauto status --json";return this.get(this.url(`api/status${s}`),i,l=>tt(l)?l:null,a,r)}async get(e,r,a,s,i){try{let l=await fetch(e,{method:"GET",signal:i}),n=null;try{n=await l.json()}catch{n=null}if(!l.ok)return{status:"error",data:null,ranCommand:r,ranAt:null,error:P(n,l.status)};let o=a(n);return o===null?{status:"error",data:null,ranCommand:r,ranAt:null,error:{code:"invalid_response",message:"Unexpected response shape."}}:{status:"ready",data:o,ranCommand:r,ranAt:s()}}catch(l){if(i.aborted)throw l;return{status:"error",data:null,ranCommand:r,ranAt:null,error:{code:"network_error",message:l instanceof Error?l.message:"Network error."}}}}async write(e,r){if(e.kind==="enqueue"){let s=`lmauto enqueue ${e.team} "${x(e.message)}" --from ${e.from}`;return this.post(this.url("api/enqueue"),{to:e.team,from:e.from,prompt:e.message},s,i=>{let l=i;return typeof l.id!="number"?null:`queued #${l.id} -> ${e.team}`},r)}if(e.kind==="send"){let s=`lmauto send ${e.team} "${x(e.message)}"`;return this.post(this.url("api/send"),{team:e.team,prompt:e.message},s,i=>{let l=i;return typeof l.status!="string"?null:`${e.team}: ${l.status}`},r)}if(e.kind==="source-add"){let s=e.label?`lmauto source add ${e.path} "${x(e.label)}"`:`lmauto source add ${e.path}`,i=e.label?{path:e.path,label:e.label}:{path:e.path};return this.post(this.url("api/sources"),i,s,l=>l.ok!==!0?null:`added ${e.path}`,r)}let a=`lmauto source remove ${e.path}`;return this.del(this.url(`api/sources?path=${encodeURIComponent(e.path)}`),a,s=>s.ok!==!0?null:`removed ${e.path}`,r)}async del(e,r,a,s){let i=new Date().toISOString();try{let l=await fetch(e,{method:"DELETE",signal:s}),n=null;try{n=await l.json()}catch{n=null}if(!l.ok){let d=P(n,l.status);return{ok:!1,ranCommand:r,ranAt:i,summary:d.message,raw:n,error:d}}let o=a(n);if(o===null){let d={code:"invalid_response",message:"Unexpected response shape."};return{ok:!1,ranCommand:r,ranAt:i,summary:d.message,raw:n,error:d}}return{ok:!0,ranCommand:r,ranAt:i,summary:o,raw:n}}catch(l){if(s.aborted)throw l;let n={code:"network_error",message:l instanceof Error?l.message:"Network error."};return{ok:!1,ranCommand:r,ranAt:i,summary:n.message,raw:null,error:n}}}async post(e,r,a,s,i){let l=new Date().toISOString();try{let n=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r),signal:i}),o=null;try{o=await n.json()}catch{o=null}if(!n.ok){let u=P(o,n.status);return{ok:!1,ranCommand:a,ranAt:l,summary:u.message,raw:o,error:u}}let d=s(o);if(d===null){let u={code:"invalid_response",message:"Unexpected response shape."};return{ok:!1,ranCommand:a,ranAt:l,summary:u.message,raw:o,error:u}}return{ok:!0,ranCommand:a,ranAt:l,summary:d,raw:o}}catch(n){if(i.aborted)throw n;let o={code:"network_error",message:n instanceof Error?n.message:"Network error."};return{ok:!1,ranCommand:a,ranAt:l,summary:o.message,raw:null,error:o}}}};function p(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function et(t,e){if(!e)return`<p class="muted" data-local-ran>ran: <code>${p(t)}</code></p>`;let r=Math.max(0,Math.round((Date.now()-Date.parse(e))/1e3));return`<p class="muted" data-local-ran>ran: <code>${p(t)}</code>, ${r}s ago</p>`}function I(t){return t===null?"":p(t)}function rt(t){return`<tr data-local-running-row="${t.id}"><td>${p(t.kind)}</td><td>${I(t.target)}</td><td>${p(t.started_at)}</td><td>${t.running_for_ms}</td><td>${p(t.holder_liveness)}</td></tr>`}function nt(t){return`<tr data-local-dead-row="${t.id}"><td>${p(t.kind)}</td><td>${I(t.target)}</td><td>${p(t.started_at)}</td><td>${t.stale_for_ms}</td></tr>`}function at(t){return`<tr data-local-idle-row="${t.id}"><td>${p(t.kind)}</td><td>${I(t.target)}</td><td>${p(t.status)}</td><td>${t.idle_ms}</td><td>${t.error?p(t.error):""}</td></tr>`}function ot(t,e,r,a,s,i){t.innerHTML=`
|
|
25
|
+
<section class="local-pane" data-local-pane="running">
|
|
26
|
+
<header><h2>Running</h2></header>
|
|
27
|
+
${et(s,i)}
|
|
28
|
+
<h3>Running (${e.length})</h3>
|
|
29
|
+
${e.length===0?'<p class="muted">Nothing running.</p>':`<table class="local-table" data-local-running-table><thead><tr><th>KIND</th><th>TARGET</th><th>STARTED</th><th>RUNNING-FOR-MS</th><th>LIVENESS</th></tr></thead><tbody>${e.map(rt).join("")}</tbody></table>`}
|
|
30
|
+
<h3>Dead (${r.length})</h3>
|
|
31
|
+
${r.length===0?'<p class="muted">None.</p>':`<table class="local-table" data-local-dead-table><thead><tr><th>KIND</th><th>TARGET</th><th>STARTED</th><th>STALE-FOR-MS</th></tr></thead><tbody>${r.map(nt).join("")}</tbody></table>`}
|
|
32
|
+
<h3>Idle (${a.length})</h3>
|
|
33
|
+
${a.length===0?'<p class="muted">None.</p>':`<table class="local-table" data-local-idle-table><thead><tr><th>KIND</th><th>TARGET</th><th>STATUS</th><th>IDLE-MS</th><th>ERROR</th></tr></thead><tbody>${a.map(at).join("")}</tbody></table>`}
|
|
34
|
+
</section>
|
|
35
|
+
`}function st(t,e){t.innerHTML=`<p class="form-error" role="alert" data-local-running-error>${p(e)}</p>`}var lt={id:"running",label:"Running",mount(t,e){let r=new AbortController;return t.innerHTML='<p class="muted" role="status">Loading running\u2026</p>',(async()=>{let a=await e.transport.read({kind:"running"},r.signal);if(!r.signal.aborted){if(a.status==="error"){st(t,a.error.message);return}a.status!=="pending"&&ot(t,a.data.running,a.data.dead,a.data.idle,a.ranCommand,a.ranAt)}})(),()=>{r.abort()}}},$=lt;function j(t,e,r){t.innerHTML=`
|
|
36
|
+
<div class="local-shell">
|
|
37
|
+
<nav class="local-shell-nav" data-local-shell-nav></nav>
|
|
38
|
+
<main class="local-shell-pane" data-local-shell-pane></main>
|
|
39
|
+
</div>
|
|
40
|
+
`;let a=t.querySelector("[data-local-shell-nav]"),s=t.querySelector("[data-local-shell-pane]");if(!a||!s)return()=>{};let i=null,l=null;function n(d){if(i===d)return;l?.(),l=null,i=d;for(let c of a?.querySelectorAll("[data-local-pane-button]")??[])c.setAttribute("aria-current",c.dataset.localPaneButton===d?"true":"false");let u=r.find(c=>c.id===d);!u||!s||(l=u.pane.mount(s,{transport:e}))}a.innerHTML=r.map(d=>`<button type="button" class="local-pane-button" data-local-pane-button="${d.id}">${d.label}</button>`).join("");for(let d of a.querySelectorAll("[data-local-pane-button]"))d.addEventListener("click",()=>n(d.dataset.localPaneButton??""));let o=r[0];return o&&n(o.id),()=>{l?.(),l=null}}function y(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function it(t,e){if(!e)return`<p class="muted" data-local-ran>ran: <code>${y(t)}</code></p>`;let r=Math.max(0,Math.round((Date.now()-Date.parse(e))/1e3));return`<p class="muted" data-local-ran>ran: <code>${y(t)}</code>, ${r}s ago</p>`}function dt(t){return`
|
|
41
|
+
<tr data-local-queue-row="${t.id}">
|
|
42
|
+
<td>${t.id}</td>
|
|
43
|
+
<td>${y(t.from_id)}</td>
|
|
44
|
+
<td>${y(t.to_id)}</td>
|
|
45
|
+
<td>${y(t.status)}</td>
|
|
46
|
+
<td>${y(t.created_ts)}</td>
|
|
47
|
+
</tr>
|
|
48
|
+
`}function ut(t,e){t.innerHTML=`
|
|
49
|
+
<section class="local-pane" data-local-pane="queue">
|
|
50
|
+
<header>
|
|
51
|
+
<h2>Queue</h2>
|
|
52
|
+
<form class="local-filter" data-local-queue-filter>
|
|
53
|
+
<input type="text" name="team" placeholder="Filter by team (optional)" value="${y(e)}" />
|
|
54
|
+
<button type="submit">Load</button>
|
|
55
|
+
</form>
|
|
56
|
+
</header>
|
|
57
|
+
<div data-local-queue-read><p class="muted" role="status">Loading queue\u2026</p></div>
|
|
58
|
+
<form class="local-write-form" data-local-queue-enqueue>
|
|
59
|
+
<h3>Enqueue</h3>
|
|
60
|
+
<label>Team <input type="text" name="team" required /></label>
|
|
61
|
+
<label>From (sender id) <input type="text" name="from" required /></label>
|
|
62
|
+
<label>Prompt <textarea name="message" required></textarea></label>
|
|
63
|
+
<button type="submit">Enqueue</button>
|
|
64
|
+
<p class="form-error" data-local-queue-write-error role="alert" hidden></p>
|
|
65
|
+
<p class="muted" data-local-queue-write-status hidden></p>
|
|
66
|
+
</form>
|
|
67
|
+
</section>
|
|
68
|
+
`}function ct(t,e,r,a){t.innerHTML=`
|
|
69
|
+
${it(r,a)}
|
|
70
|
+
${e.length===0?'<p class="muted">No queued items.</p>':`
|
|
71
|
+
<table class="local-table" data-local-queue-table>
|
|
72
|
+
<thead><tr><th>ID</th><th>FROM</th><th>TO</th><th>STATUS</th><th>CREATED</th></tr></thead>
|
|
73
|
+
<tbody>${e.map(dt).join("")}</tbody>
|
|
74
|
+
</table>
|
|
75
|
+
`}
|
|
76
|
+
`}function mt(t,e){t.innerHTML=`<p class="form-error" role="alert" data-local-queue-read-error>${y(e)}</p>`}var pt={id:"queue",label:"Queue",mount(t,e){let r=new AbortController,a="";ut(t,a);let s=t.querySelector("[data-local-queue-read]");async function i(){if(!s)return;let n=a?await e.transport.read({kind:"queue-list",team:a},r.signal):await e.transport.read({kind:"queue-list"},r.signal);if(!r.signal.aborted){if(n.status==="error"){mt(s,n.error.message);return}n.status!=="pending"&&ct(s,n.data.queue,n.ranCommand,n.ranAt)}}return t.querySelector("[data-local-queue-filter]")?.addEventListener("submit",n=>{n.preventDefault(),a=n.currentTarget.elements.namedItem("team")?.value.trim()??"",i()}),t.querySelector("[data-local-queue-enqueue]")?.addEventListener("submit",n=>{n.preventDefault();let o=n.currentTarget,d=o.querySelector("[data-local-queue-write-error]"),u=o.querySelector("[data-local-queue-write-status]");d&&(d.hidden=!0),u&&(u.hidden=!0);let c=o.elements.namedItem("team")?.value.trim()??"",h=o.elements.namedItem("from")?.value.trim()??"",m=o.elements.namedItem("message")?.value.trim()??"";!c||!h||!m||(async()=>{let w=await e.transport.write({kind:"enqueue",team:c,from:h,message:m},r.signal);if(r.signal.aborted)return;if(!w.ok){d&&(d.textContent=w.summary,d.hidden=!1);return}u&&(u.textContent=`${w.summary} \u2014 ran: ${w.ranCommand}`,u.hidden=!1),o.reset(),a=c;let _=t.querySelector('[data-local-queue-filter] input[name="team"]');_&&(_.value=c),i()})()}),i(),()=>{r.abort()}}},R=pt;function b(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function gt(t,e){if(!e)return`<p class="muted" data-local-ran>ran: <code>${b(t)}</code></p>`;let r=Math.max(0,Math.round((Date.now()-Date.parse(e))/1e3));return`<p class="muted" data-local-ran>ran: <code>${b(t)}</code>, ${r}s ago</p>`}function ft(t){return`
|
|
77
|
+
<tr data-local-history-row="${t.id}">
|
|
78
|
+
<td>${t.id}</td>
|
|
79
|
+
<td>${b(t.ts)}</td>
|
|
80
|
+
<td>${b(t.team)}</td>
|
|
81
|
+
<td>${b(t.status)}</td>
|
|
82
|
+
<td>${t.note?b(t.note):""}</td>
|
|
83
|
+
</tr>
|
|
84
|
+
`}function ht(t,e){t.innerHTML=`
|
|
85
|
+
<section class="local-pane" data-local-pane="send">
|
|
86
|
+
<header>
|
|
87
|
+
<h2>Send</h2>
|
|
88
|
+
<form class="local-filter" data-local-history-filter>
|
|
89
|
+
<input type="text" name="team" placeholder="Filter by team (optional)" value="${b(e)}" />
|
|
90
|
+
<button type="submit">Load</button>
|
|
91
|
+
</form>
|
|
92
|
+
</header>
|
|
93
|
+
<div data-local-history-read><p class="muted" role="status">Loading history\u2026</p></div>
|
|
94
|
+
<form class="local-write-form" data-local-send-form>
|
|
95
|
+
<h3>Send</h3>
|
|
96
|
+
<label>Team <input type="text" name="team" required /></label>
|
|
97
|
+
<label>Prompt <textarea name="message" required></textarea></label>
|
|
98
|
+
<button type="submit">Send</button>
|
|
99
|
+
<p class="form-error" data-local-send-write-error role="alert" hidden></p>
|
|
100
|
+
<p class="muted" data-local-send-write-status hidden></p>
|
|
101
|
+
</form>
|
|
102
|
+
</section>
|
|
103
|
+
`}function yt(t,e,r,a){t.innerHTML=`
|
|
104
|
+
${gt(r,a)}
|
|
105
|
+
${e.length===0?'<p class="muted">No history yet.</p>':`
|
|
106
|
+
<table class="local-table" data-local-history-table>
|
|
107
|
+
<thead><tr><th>ID</th><th>TS</th><th>TEAM</th><th>STATUS</th><th>NOTE</th></tr></thead>
|
|
108
|
+
<tbody>${e.map(ft).join("")}</tbody>
|
|
109
|
+
</table>
|
|
110
|
+
`}
|
|
111
|
+
`}function bt(t,e){t.innerHTML=`<p class="form-error" role="alert" data-local-history-error>${b(e)}</p>`}var Tt={id:"send",label:"Send",mount(t,e){let r=new AbortController,a="";ht(t,a);let s=t.querySelector("[data-local-history-read]");async function i(){if(!s)return;let n=a?await e.transport.read({kind:"history",team:a},r.signal):await e.transport.read({kind:"history"},r.signal);if(!r.signal.aborted){if(n.status==="error"){bt(s,n.error.message);return}n.status!=="pending"&&yt(s,n.data.events,n.ranCommand,n.ranAt)}}return t.querySelector("[data-local-history-filter]")?.addEventListener("submit",n=>{n.preventDefault(),a=n.currentTarget.elements.namedItem("team")?.value.trim()??"",i()}),t.querySelector("[data-local-send-form]")?.addEventListener("submit",n=>{n.preventDefault();let o=n.currentTarget,d=o.querySelector("[data-local-send-write-error]"),u=o.querySelector("[data-local-send-write-status]");d&&(d.hidden=!0),u&&(u.hidden=!0);let c=o.elements.namedItem("team")?.value.trim()??"",h=o.elements.namedItem("message")?.value.trim()??"";!c||!h||(async()=>{let m=await e.transport.write({kind:"send",team:c,message:h},r.signal);if(r.signal.aborted)return;if(!m.ok){d&&(d.textContent=m.summary,d.hidden=!1);return}u&&(u.textContent=`${m.summary} \u2014 ran: ${m.ranCommand}`,u.hidden=!1),o.reset(),a=c;let w=t.querySelector('[data-local-history-filter] input[name="team"]');w&&(w.value=c),i()})()}),i(),()=>{r.abort()}}},k=Tt;function T(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function wt(t,e){if(!e)return`<p class="muted" data-local-ran>ran: <code>${T(t)}</code></p>`;let r=Math.max(0,Math.round((Date.now()-Date.parse(e))/1e3));return`<p class="muted" data-local-ran>ran: <code>${T(t)}</code>, ${r}s ago</p>`}function St(t){let e=typeof t.content=="string"?t.content:JSON.stringify(t.content);return`
|
|
112
|
+
<li data-local-session-message>
|
|
113
|
+
<strong>${T(t.role)}</strong>
|
|
114
|
+
<span>${T(e)}</span>
|
|
115
|
+
</li>
|
|
116
|
+
`}function vt(t){t.innerHTML=`
|
|
117
|
+
<section class="local-pane" data-local-pane="session">
|
|
118
|
+
<header>
|
|
119
|
+
<h2>Session</h2>
|
|
120
|
+
<form class="local-filter" data-local-session-form>
|
|
121
|
+
<input type="text" name="team" placeholder="team" required />
|
|
122
|
+
<input type="text" name="alias" placeholder="alias" required />
|
|
123
|
+
<button type="submit">Load</button>
|
|
124
|
+
</form>
|
|
125
|
+
</header>
|
|
126
|
+
<div data-local-session-read>
|
|
127
|
+
<p class="muted">Enter a team and alias to load its session.</p>
|
|
128
|
+
</div>
|
|
129
|
+
<p class="muted local-write-gap" data-local-session-write-gap>
|
|
130
|
+
Answering from the web isn't available yet \u2014 no HTTP route for <code>lmctl chat</code>. The
|
|
131
|
+
transcript's <code>tail</code> view isn't wired here either: <code>/api/transcript</code>
|
|
132
|
+
re-parses text instead of passing through <code>lmctl tail --json</code> cleanly (a known
|
|
133
|
+
gap \u2014 see pane-command-contract.md) \u2014 this pane uses <code>/api/session</code> instead.
|
|
134
|
+
</p>
|
|
135
|
+
</section>
|
|
136
|
+
`}function Et(t,e,r,a){let s=e.modifiedAt===void 0?"unknown":T(e.modifiedAt);t.innerHTML=`
|
|
137
|
+
${wt(r,a)}
|
|
138
|
+
<p class="muted">
|
|
139
|
+
${T(e.provider)} \xB7 <code>${T(e.sessionId)}</code> \xB7 modified ${s}
|
|
140
|
+
</p>
|
|
141
|
+
${e.messages.length===0?'<p class="muted">No messages.</p>':`<ul class="local-session-messages" data-local-session-messages>${e.messages.map(St).join("")}</ul>`}
|
|
142
|
+
`}function Lt(t,e){t.innerHTML=`<p class="form-error" role="alert" data-local-session-error>${T(e)}</p>`}var $t={id:"session",label:"Session",mount(t,e){let r=new AbortController;vt(t);let a=t.querySelector("[data-local-session-read]");async function s(i,l){if(!a)return;a.innerHTML='<p class="muted" role="status">Loading session\u2026</p>';let n=await e.transport.read({kind:"session",team:i,alias:l},r.signal);if(!r.signal.aborted){if(n.status==="error"){Lt(a,n.error.message);return}n.status!=="pending"&&Et(a,n.data,n.ranCommand,n.ranAt)}}return t.querySelector("[data-local-session-form]")?.addEventListener("submit",i=>{i.preventDefault();let l=i.currentTarget,n=l.elements.namedItem("team")?.value.trim()??"",o=l.elements.namedItem("alias")?.value.trim()??"";!n||!o||s(n,o)}),()=>{r.abort()}}},M=$t;function v(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function Rt(t,e){if(!e)return`<p class="muted" data-local-ran>ran: <code>${v(t)}</code></p>`;let r=Math.max(0,Math.round((Date.now()-Date.parse(e))/1e3));return`<p class="muted" data-local-ran>ran: <code>${v(t)}</code>, ${r}s ago</p>`}function kt(t){return`
|
|
143
|
+
<tr data-local-source-row="${t.id}">
|
|
144
|
+
<td>${t.id}</td>
|
|
145
|
+
<td>${v(t.path)}</td>
|
|
146
|
+
<td>${t.label===null?"":v(t.label)}</td>
|
|
147
|
+
<td><button type="button" class="local-source-remove" data-local-source-remove="${v(t.path)}">Remove</button></td>
|
|
148
|
+
</tr>
|
|
149
|
+
`}function Mt(t){t.innerHTML=`
|
|
150
|
+
<section class="local-pane" data-local-pane="sources">
|
|
151
|
+
<header>
|
|
152
|
+
<h2>Sources</h2>
|
|
153
|
+
</header>
|
|
154
|
+
<div data-local-sources-read><p class="muted" role="status">Loading sources\u2026</p></div>
|
|
155
|
+
<form class="local-write-form" data-local-source-add>
|
|
156
|
+
<h3>Add source</h3>
|
|
157
|
+
<label>Path <input type="text" name="path" required /></label>
|
|
158
|
+
<label>Label (optional) <input type="text" name="label" /></label>
|
|
159
|
+
<button type="submit">Add</button>
|
|
160
|
+
<p class="form-error" data-local-source-add-error role="alert" hidden></p>
|
|
161
|
+
<p class="muted" data-local-source-add-status hidden></p>
|
|
162
|
+
</form>
|
|
163
|
+
</section>
|
|
164
|
+
`}function Ht(t,e,r,a,s){t.innerHTML=`
|
|
165
|
+
${Rt(a,s)}
|
|
166
|
+
<p class="muted">default: <code>${v(e)}</code></p>
|
|
167
|
+
${r.length===0?'<p class="muted">No additional sources.</p>':`
|
|
168
|
+
<table class="local-table" data-local-sources-table>
|
|
169
|
+
<thead><tr><th>ID</th><th>PATH</th><th>LABEL</th><th></th></tr></thead>
|
|
170
|
+
<tbody>${r.map(kt).join("")}</tbody>
|
|
171
|
+
</table>
|
|
172
|
+
`}
|
|
173
|
+
<p class="form-error" data-local-source-remove-error role="alert" hidden></p>
|
|
174
|
+
`}function At(t,e){t.innerHTML=`<p class="form-error" role="alert" data-local-sources-error>${v(e)}</p>`}var qt={id:"sources",label:"Sources",mount(t,e){let r=new AbortController;Mt(t);let a=t.querySelector("[data-local-sources-read]");async function s(){if(!a)return;let n=await e.transport.read({kind:"sources"},r.signal);if(!r.signal.aborted){if(n.status==="error"){At(a,n.error.message);return}n.status!=="pending"&&(Ht(a,n.data.defaultTeamsConfPath,n.data.sources,n.ranCommand,n.ranAt),a.querySelectorAll("[data-local-source-remove]").forEach(o=>{o.addEventListener("click",()=>{let d=o.dataset.localSourceRemove;d&&i(d)})}))}}async function i(n){let o=a?.querySelector("[data-local-source-remove-error]");o&&(o.hidden=!0);let d=await e.transport.write({kind:"source-remove",path:n},r.signal);if(!r.signal.aborted){if(!d.ok){o&&(o.textContent=d.summary,o.hidden=!1);return}s()}}return t.querySelector("[data-local-source-add]")?.addEventListener("submit",n=>{n.preventDefault();let o=n.currentTarget,d=o.querySelector("[data-local-source-add-error]"),u=o.querySelector("[data-local-source-add-status]");d&&(d.hidden=!0),u&&(u.hidden=!0);let c=o.elements.namedItem("path")?.value.trim()??"",h=o.elements.namedItem("label")?.value.trim()??"";c&&(async()=>{let m=await e.transport.write(h?{kind:"source-add",path:c,label:h}:{kind:"source-add",path:c},r.signal);if(!r.signal.aborted){if(!m.ok){d&&(d.textContent=m.summary,d.hidden=!1);return}u&&(u.textContent=`${m.summary} \u2014 ran: ${m.ranCommand}`,u.hidden=!1),o.reset(),s()}})()}),s(),()=>{r.abort()}}},H=qt;function g(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function xt(t,e){if(!e)return`<p class="muted" data-local-ran>ran: <code>${g(t)}</code></p>`;let r=Math.max(0,Math.round((Date.now()-Date.parse(e))/1e3));return`<p class="muted" data-local-ran>ran: <code>${g(t)}</code>, ${r}s ago</p>`}function Pt(t){return`
|
|
175
|
+
<tr data-local-state-row="${g(t.team)}">
|
|
176
|
+
<td>${g(t.team)}</td>
|
|
177
|
+
<td>${t.state?g(t.state.status):""}</td>
|
|
178
|
+
<td>${t.state?g(t.state.changed_ts):""}</td>
|
|
179
|
+
<td>${t.progress?.progress_status?g(t.progress.progress_status):""}</td>
|
|
180
|
+
<td>${t.progress?.confirmed_done_ts?g(t.progress.confirmed_done_ts):""}</td>
|
|
181
|
+
</tr>
|
|
182
|
+
`}function It(t,e,r,a,s,i){t.innerHTML=`
|
|
183
|
+
<section class="local-pane" data-local-pane="state">
|
|
184
|
+
<header>
|
|
185
|
+
<h2>State</h2>
|
|
186
|
+
<button type="button" class="local-refresh" data-local-state-refresh>Refresh</button>
|
|
187
|
+
</header>
|
|
188
|
+
${xt(a,s)}
|
|
189
|
+
<p class="muted" data-local-state-active>active: ${r.length?g(r.join(", ")):"(none)"}</p>
|
|
190
|
+
${e.length===0?'<p class="muted">No teams registered.</p>':`
|
|
191
|
+
<table class="local-table" data-local-state-table>
|
|
192
|
+
<thead><tr><th>TEAM</th><th>STATUS</th><th>CHANGED</th><th>PROGRESS</th><th>CONFIRMED-DONE</th></tr></thead>
|
|
193
|
+
<tbody>${e.map(Pt).join("")}</tbody>
|
|
194
|
+
</table>
|
|
195
|
+
`}
|
|
196
|
+
<p class="muted local-write-gap" data-local-state-write-gap>
|
|
197
|
+
Setting state isn't available from the web yet \u2014 no HTTP route exists (CLI only: <code>lmauto state set <team> <status></code>).
|
|
198
|
+
</p>
|
|
199
|
+
</section>
|
|
200
|
+
`,t.querySelector("[data-local-state-refresh]")?.addEventListener("click",i)}function _t(t,e){t.innerHTML=`<p class="form-error" role="alert" data-local-state-error>${g(e)}</p>`}var Ct={id:"state",label:"State",mount(t,e){let r=new AbortController;t.innerHTML='<p class="muted" role="status">Loading state\u2026</p>';async function a(){let s=await e.transport.read({kind:"state-list"},r.signal);if(!r.signal.aborted){if(s.status==="error"){_t(t,s.error.message);return}s.status!=="pending"&&It(t,s.data.teams,s.data.active,s.ranCommand,s.ranAt,()=>void a())}}return a(),()=>{r.abort()}}},A=Ct;function D(t){return t.channel==="local"}function f(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function jt(t,e){if(!e)return`<p class="muted" data-local-ran>ran: <code>${f(t)}</code></p>`;let r=Math.max(0,Math.round((Date.now()-Date.parse(e))/1e3));return`<p class="muted" data-local-ran>ran: <code>${f(t)}</code>, ${r}s ago</p>`}function Dt(t){return D(t)?`
|
|
201
|
+
<tr data-local-team-row="${f(t.name)}">
|
|
202
|
+
<td>${f(t.name)}</td>
|
|
203
|
+
<td>local</td>
|
|
204
|
+
<td>${f(t.leadAlias)}</td>
|
|
205
|
+
<td>${f(t.description)}</td>
|
|
206
|
+
</tr>
|
|
207
|
+
`:`
|
|
208
|
+
<tr data-local-team-row="${f(t.name)}">
|
|
209
|
+
<td>${f(t.name)}</td>
|
|
210
|
+
<td>remote (${f(t.peerSite)})</td>
|
|
211
|
+
<td>--</td>
|
|
212
|
+
<td>--</td>
|
|
213
|
+
</tr>
|
|
214
|
+
`}function Ft(t,e,r,a,s){t.innerHTML=`
|
|
215
|
+
<section class="local-pane" data-local-pane="teams">
|
|
216
|
+
<header>
|
|
217
|
+
<h2>Teams</h2>
|
|
218
|
+
<button type="button" class="local-refresh" data-local-teams-refresh>Refresh</button>
|
|
219
|
+
</header>
|
|
220
|
+
${jt(r,a)}
|
|
221
|
+
${e.length===0?'<p class="muted">No teams registered.</p>':`
|
|
222
|
+
<table class="local-table" data-local-teams-table>
|
|
223
|
+
<thead><tr><th>TEAM</th><th>CHANNEL</th><th>LEAD</th><th>DESCRIPTION</th></tr></thead>
|
|
224
|
+
<tbody>${e.map(Dt).join("")}</tbody>
|
|
225
|
+
</table>
|
|
226
|
+
`}
|
|
227
|
+
<p class="muted local-write-gap" data-local-teams-write-gap>
|
|
228
|
+
Nudge isn't available from the web yet \u2014 no HTTP route exists (CLI only: <code>lmauto nudge <team></code>).
|
|
229
|
+
</p>
|
|
230
|
+
</section>
|
|
231
|
+
`,t.querySelector("[data-local-teams-refresh]")?.addEventListener("click",s)}function Nt(t,e){t.innerHTML=`<p class="form-error" role="alert" data-local-teams-error>${f(e)}</p>`}var Ot={id:"teams",label:"Teams",mount(t,e){let r=new AbortController;t.innerHTML='<p class="muted" role="status">Loading teams\u2026</p>';async function a(){let s=await e.transport.read({kind:"teams"},r.signal);if(!r.signal.aborted){if(s.status==="error"){Nt(t,s.error.message);return}s.status!=="pending"&&Ft(t,s.data.teams,s.ranCommand,s.ranAt,()=>void a())}}return a(),()=>{r.abort()}}},q=Ot;var Wt=document.getElementById("app")??document.createElement("main"),Ut=new L(""),Qt=[{id:q.id,label:q.label,pane:q},{id:R.id,label:R.label,pane:R},{id:k.id,label:k.label,pane:k},{id:A.id,label:A.label,pane:A},{id:H.id,label:H.label,pane:H},{id:M.id,label:M.label,pane:M},{id:$.id,label:$.label,pane:$},{id:E.id,label:E.label,pane:E}];j(Wt,Ut,Qt);})();
|