spexcode 0.5.4 → 0.5.6
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/package.json +1 -1
- package/spec-cli/hooks/dispatch.sh +10 -0
- package/spec-cli/src/cli.ts +6 -5
- package/spec-cli/src/contract-filter.ts +73 -29
- package/spec-cli/src/git.ts +80 -40
- package/spec-cli/src/harness.ts +127 -8
- package/spec-cli/src/index.ts +9 -3
- package/spec-cli/src/materialize.ts +118 -49
- package/spec-cli/src/reviewSnapshot.ts +4 -0
- package/spec-cli/src/reviews.ts +10 -5
- package/spec-cli/src/sessions.ts +113 -9
- package/spec-cli/templates/spec/project/.plugins/core/session-fail/spec.md +3 -1
- package/spec-cli/templates/spec/project/.plugins/core/spec.md +2 -2
- package/spec-dashboard/dist/assets/{App-C5vbTw8Q.js → App-B72LuS5I.js} +2 -2
- package/spec-dashboard/dist/assets/Dashboard-C5X4Va3V.js +27 -0
- package/spec-dashboard/dist/assets/{EvalsPage-BS7ITcNo.js → EvalsPage-BTvJIW8Q.js} +2 -2
- package/spec-dashboard/dist/assets/IssuesPage-Bn94h_HQ.js +1 -0
- package/spec-dashboard/dist/assets/{MobileApp-DVLnk9hz.js → MobileApp-ClbtwZ1e.js} +2 -2
- package/spec-dashboard/dist/assets/{Modal-6mHq6fbZ.js → Modal-6l_QtCKF.js} +1 -1
- package/spec-dashboard/dist/assets/{PageScroll-CAY4S4g4.js → PageScroll-B2kxcqJJ.js} +1 -1
- package/spec-dashboard/dist/assets/{ProjectsPage-UQyzsTWN.js → ProjectsPage-C8IPsMKV.js} +1 -1
- package/spec-dashboard/dist/assets/{SessionInterface-DKU4c1Z-.js → SessionInterface-B5jf7dW7.js} +11 -11
- package/spec-dashboard/dist/assets/SessionWindow-Dag_GiJB.js +1 -0
- package/spec-dashboard/dist/assets/{Settings-igR17pns.js → Settings-J3aibcXo.js} +1 -1
- package/spec-dashboard/dist/assets/{Thread-B-ZUarN1.js → Thread-Dg35J-Pu.js} +3 -3
- package/spec-dashboard/dist/assets/{TimelineChat-sc49Qj5d.js → TimelineChat-f0UF9fXq.js} +1 -1
- package/spec-dashboard/dist/assets/{data-B1ot4PF0.js → data-SNi0AmVT.js} +1 -1
- package/spec-dashboard/dist/assets/{index-BqBNCa1V.js → index-BUKLPN_4.js} +10 -10
- package/spec-dashboard/dist/index.html +1 -1
- package/spec-dashboard/dist/assets/Dashboard-u8RIS3NY.js +0 -27
- package/spec-dashboard/dist/assets/IssuesPage-DXbqQFW_.js +0 -1
- package/spec-dashboard/dist/assets/SessionWindow-zGwJaGbR.js +0 -1
package/spec-cli/src/reviews.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { buildSessionEvals, type SessionEvals } from '../../spec-eval/src/sessio
|
|
|
5
5
|
import { evalTimeline } from '../../spec-eval/src/evaltab.js'
|
|
6
6
|
import { issuesEnabled as issuesEnabledForReview } from './localIssues.js'
|
|
7
7
|
import { issueStores as issueStoresForReview } from './issues.js'
|
|
8
|
-
import { readReviewSnapshot } from './reviewSnapshot.js'
|
|
8
|
+
import { hasReviewSnapshot, readReviewSnapshot } from './reviewSnapshot.js'
|
|
9
9
|
// @ts-expect-error The dashboard module is deliberately plain JS so the browser and server execute the
|
|
10
10
|
// exact same tokenizer/matcher. It is shipped beside the built dashboard by the root package manifest.
|
|
11
11
|
import { EVAL_FILTER_KIND, evalFilterModel, evalReviewState, issueFilterModel, tokenFilterState } from '../../spec-dashboard/src/reviewFilters.js'
|
|
@@ -121,7 +121,11 @@ const issueOrder = (a: any, b: any): number => String(b.created ?? '').localeCom
|
|
|
121
121
|
|| String(a.id ?? '').localeCompare(String(b.id ?? ''))
|
|
122
122
|
|
|
123
123
|
export async function issuesReview(query: string | undefined, requestedPage: unknown) {
|
|
124
|
-
|
|
124
|
+
// The first request must wait for the first atomic publication. Once one exists, a graph refresh may be
|
|
125
|
+
// rebuilding unrelated board/session state; the published review source remains a valid answer and its
|
|
126
|
+
// revision/poll path will deliver the next generation without making this page join that flight.
|
|
127
|
+
if (!hasReviewSnapshot()) await getBoard()
|
|
128
|
+
const sessions = await listSessions()
|
|
125
129
|
const issues = readReviewSnapshot().issues.slice().sort(issueOrder)
|
|
126
130
|
const text = String(query ?? '').trim() || ISSUE_QUERY_DEFAULT
|
|
127
131
|
const model = issueFilterModel(issues, tokenFilterState(text, 'issue'), { sessions, defaultSection: '' })
|
|
@@ -337,15 +341,16 @@ export async function evalsReview(query: string | undefined, requestedPage: unkn
|
|
|
337
341
|
}),
|
|
338
342
|
}
|
|
339
343
|
}
|
|
340
|
-
|
|
344
|
+
if (!hasReviewSnapshot()) await getBoard()
|
|
345
|
+
const sessions = await listSessions()
|
|
341
346
|
const items = trunkEvalReviewItems(readReviewSnapshot().evalNodes)
|
|
342
|
-
const filtered = evalFilterModel(items, tokenFilterState(text, 'eval'), { sessions
|
|
347
|
+
const filtered = evalFilterModel(items, tokenFilterState(text, 'eval'), { sessions, defaultKind: 'all', defaultSection: '' })
|
|
343
348
|
return {
|
|
344
349
|
scope: null,
|
|
345
350
|
gates: [],
|
|
346
351
|
unknown: 0,
|
|
347
352
|
...paginateReview(items, filtered.shown, filtered, requestedPage, {
|
|
348
|
-
domain: 'evals', items, sessions:
|
|
353
|
+
domain: 'evals', items, sessions: sessions.map((session) => session.id),
|
|
349
354
|
}),
|
|
350
355
|
}
|
|
351
356
|
}
|
package/spec-cli/src/sessions.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { fileURLToPath } from 'node:url'
|
|
|
7
7
|
import { seedWorktreeHostState } from './worktree-sources.js'
|
|
8
8
|
import { git, gitA, gitTry, repoRoot, mergeBaseDiff, mergeConflicts, type ReviewDiffFile } from './git.js'
|
|
9
9
|
import { loadConfig, loadSpecs, type ConfigPreset, type SpecLite } from './specs.js'
|
|
10
|
-
import { adapterLoadedReferenceState, defaultHarness, sessionIdentityEnvVars, defaultLauncher, harnessById, procSnapshot, resolveLauncher, rendezvousListening, stampRvSock, type Harness, type HarnessLaunchReadinessFence, type DispatchResult, type PaneProbe, type ProcTable } from './harness.js'
|
|
10
|
+
import { adapterLoadedReferenceState, defaultHarness, sessionIdentityEnvVars, defaultLauncher, harnessById, procSnapshot, resolveLauncher, rendezvousListening, stampRvSock, type Harness, type HarnessLaunchReadinessFence, type TurnFailure, type FailureSubscription, type DispatchResult, type PaneProbe, type ProcTable } from './harness.js'
|
|
11
11
|
import { materialize } from './materialize.js'
|
|
12
12
|
import { mainBranch, gitCommonDir, readConfig, runtimeRoot, treeSlotDir, sessionStoreDir, sessionRecordPath, sessionArtifactPath, listSessionIds, rawLaunchReadinessOriginal, readAliasedRawRecord, readRecordEntry, readAliasedRecordEntry, readPublicRecordEntry, envSessionId, isSessionLifecycle, isSessionProposal, type PublicRecordEntry, type RawRecord, type SessionLifecycle, type SessionProposal } from './layout.js'
|
|
13
13
|
import { recordSent, recordStatus, lastHumanSendVia } from './session-timeline.js'
|
|
@@ -1651,6 +1651,106 @@ export function superviseQueue(intervalMs = 3000): void {
|
|
|
1651
1651
|
void tick()
|
|
1652
1652
|
}
|
|
1653
1653
|
|
|
1654
|
+
type TurnFailureObserverState = {
|
|
1655
|
+
fingerprint: string
|
|
1656
|
+
subscription: FailureSubscription | null
|
|
1657
|
+
startedAt: number
|
|
1658
|
+
failures: number
|
|
1659
|
+
retryAt: number
|
|
1660
|
+
lastReason: string | null
|
|
1661
|
+
}
|
|
1662
|
+
const turnFailureObservers = new Map<string, TurnFailureObserverState>()
|
|
1663
|
+
let supervisingTurnFailures = false
|
|
1664
|
+
const TURN_FAILURE_OBSERVER_STABLE_MS = 5000
|
|
1665
|
+
|
|
1666
|
+
export function turnFailureNote(harness: string, failure: TurnFailure): string {
|
|
1667
|
+
const message = failure.message.replace(/\s+/g, ' ').trim().slice(0, 500) || 'turn failed'
|
|
1668
|
+
const at = failure.completedAt == null ? '' : ` at ${new Date(failure.completedAt * 1000).toISOString()}`
|
|
1669
|
+
return `${harness} turn failed${at}: ${message}`
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
export function turnFailureRetryDelay(failures: number): number {
|
|
1673
|
+
return Math.min(30_000, 1000 * 2 ** Math.max(0, Math.min(failures - 1, 5)))
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
function deferTurnFailureObserver(id: string, harness: string, state: TurnFailureObserverState, reason: string): void {
|
|
1677
|
+
state.subscription = null
|
|
1678
|
+
state.failures++
|
|
1679
|
+
const delay = turnFailureRetryDelay(state.failures)
|
|
1680
|
+
state.retryAt = Date.now() + delay
|
|
1681
|
+
if (state.lastReason !== reason)
|
|
1682
|
+
console.warn(`[spex ${harness}] turn failure observer for ${id} disconnected (${reason}); retrying in ${delay}ms`)
|
|
1683
|
+
state.lastReason = reason
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
// Reconcile one adapter-owned native failure subscription per live governed session. Product code knows only
|
|
1687
|
+
// the optional interface capability; Codex owns WebSocket/thread semantics and Claude keeps using StopFailure.
|
|
1688
|
+
export function reconcileTurnFailureObservers(): void {
|
|
1689
|
+
const wanted = new Map<string, { rec: SessRec; harness: Harness; fingerprint: string }>()
|
|
1690
|
+
for (const id of listSessionIds()) {
|
|
1691
|
+
let rec: SessRec | null = null
|
|
1692
|
+
try { rec = readRecord(id) } catch { continue }
|
|
1693
|
+
if (!rec?.governed || rec.stopped || rec.archived || !rec.harnessSessionId) continue
|
|
1694
|
+
const harness = harnessById(rec.harness || defaultHarness.id)
|
|
1695
|
+
if (!harness.observeTurnFailures) continue
|
|
1696
|
+
wanted.set(id, { rec, harness, fingerprint: `${harness.id}:${rec.harnessSessionId}:${runtimeRoot()}` })
|
|
1697
|
+
}
|
|
1698
|
+
for (const [id, state] of turnFailureObservers) {
|
|
1699
|
+
if (wanted.get(id)?.fingerprint === state.fingerprint) continue
|
|
1700
|
+
turnFailureObservers.delete(id)
|
|
1701
|
+
state.subscription?.close()
|
|
1702
|
+
}
|
|
1703
|
+
for (const [id, target] of wanted) {
|
|
1704
|
+
const now = Date.now()
|
|
1705
|
+
let state = turnFailureObservers.get(id)
|
|
1706
|
+
if (state?.subscription) {
|
|
1707
|
+
if (state.failures > 0 && now - state.startedAt >= TURN_FAILURE_OBSERVER_STABLE_MS) {
|
|
1708
|
+
state.failures = 0
|
|
1709
|
+
state.retryAt = 0
|
|
1710
|
+
state.lastReason = null
|
|
1711
|
+
}
|
|
1712
|
+
continue
|
|
1713
|
+
}
|
|
1714
|
+
if (state && now < state.retryAt) continue
|
|
1715
|
+
state ??= { fingerprint: target.fingerprint, subscription: null, startedAt: 0, failures: 0, retryAt: 0, lastReason: null }
|
|
1716
|
+
state.startedAt = now
|
|
1717
|
+
turnFailureObservers.set(id, state)
|
|
1718
|
+
try {
|
|
1719
|
+
const subscription = target.harness.observeTurnFailures!({
|
|
1720
|
+
session: id,
|
|
1721
|
+
worktreePath: target.rec.worktreePath,
|
|
1722
|
+
harnessSessionId: target.rec.harnessSessionId,
|
|
1723
|
+
runtimeDir: runtimeRoot(),
|
|
1724
|
+
launchCmd: target.rec.launchCmd,
|
|
1725
|
+
}, (failure) => {
|
|
1726
|
+
if (turnFailureObservers.get(id)?.fingerprint !== target.fingerprint) return
|
|
1727
|
+
try { markTurnFailure(id, turnFailureNote(target.harness.id, failure)) }
|
|
1728
|
+
catch (error) { console.error(`[spex ${target.harness.id}] could not record native turn failure for ${id}: ${error instanceof Error ? error.message : String(error)}`) }
|
|
1729
|
+
})
|
|
1730
|
+
state.subscription = subscription
|
|
1731
|
+
void subscription.closed.then((reason) => {
|
|
1732
|
+
if (turnFailureObservers.get(id) !== state) return
|
|
1733
|
+
if (reason) deferTurnFailureObserver(id, target.harness.id, state, reason)
|
|
1734
|
+
else turnFailureObservers.delete(id)
|
|
1735
|
+
})
|
|
1736
|
+
} catch (error) {
|
|
1737
|
+
deferTurnFailureObserver(id, target.harness.id, state, error instanceof Error ? error.message : String(error))
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
export function superviseTurnFailures(intervalMs = 1000): void {
|
|
1743
|
+
if (supervisingTurnFailures) return
|
|
1744
|
+
supervisingTurnFailures = true
|
|
1745
|
+
const tick = () => {
|
|
1746
|
+
try { reconcileTurnFailureObservers() }
|
|
1747
|
+
catch (error) { console.error(`spex: turn failure reconciliation failed: ${error instanceof Error ? error.message : String(error)}`) }
|
|
1748
|
+
const timer = setTimeout(tick, intervalMs)
|
|
1749
|
+
timer.unref?.()
|
|
1750
|
+
}
|
|
1751
|
+
tick()
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1654
1754
|
// @@@ assertProjectMatch - a WRITE is PROJECT-BOUND, but routing is by URL. A mutating verb's intent is
|
|
1655
1755
|
// "act on the project my cwd is in", yet the resolved base is a pure URL carrying no project identity —
|
|
1656
1756
|
// the backend it answers acts on ITS OWN mainRoot, so a stale inherited SPEXCODE_API_URL (pointing at
|
|
@@ -2105,19 +2205,23 @@ export function markState(status: Lifecycle, opts: { proposal?: Proposal; note?:
|
|
|
2105
2205
|
}
|
|
2106
2206
|
export const markDone = (proposal: Proposal = 'nothing', sessionId?: string, note?: string) => markState('awaiting', { proposal, note, sessionId })
|
|
2107
2207
|
export const markError = (sessionId?: string) => markState('error', { sessionId })
|
|
2108
|
-
// @@@
|
|
2109
|
-
//
|
|
2110
|
-
//
|
|
2111
|
-
export function
|
|
2112
|
-
if (
|
|
2208
|
+
// @@@ harness turn failure - native adapter failures are external runtime facts that must become visible on
|
|
2209
|
+
// the durable board. Compare-and-set only an undeclared active record, so a declaration that landed before a
|
|
2210
|
+
// late process close or app-server completion remains authoritative.
|
|
2211
|
+
export function markTurnFailure(sessionId: string | undefined, note: string): boolean {
|
|
2212
|
+
if (!sessionId) return false
|
|
2113
2213
|
return runSessionOperationSync({ op: 'lifecycle-transition', sessionId }, () => withRecordLockSync(sessionId, () => {
|
|
2114
2214
|
const rec = readLiveRecord(sessionId)
|
|
2115
|
-
if (!rec || rec.status !== 'active') return false
|
|
2116
|
-
|
|
2117
|
-
writeRecord({ ...rec, status: 'error', proposal: null, note: `${harness} turn exited with ${outcome}` })
|
|
2215
|
+
if (!rec || rec.status !== 'active' || rec.stopped || rec.archived) return false
|
|
2216
|
+
writeRecord({ ...rec, status: 'error', proposal: null, note })
|
|
2118
2217
|
return true
|
|
2119
2218
|
}))
|
|
2120
2219
|
}
|
|
2220
|
+
export function markHeadlessTurnFailure(sessionId: string, harness: string, exitCode: string): boolean {
|
|
2221
|
+
if (exitCode === '0') return false
|
|
2222
|
+
const outcome = /^\d+$/.test(exitCode) ? `exit code ${exitCode}` : `signal ${exitCode}`
|
|
2223
|
+
return markTurnFailure(sessionId, `${harness} turn exited with ${outcome}`)
|
|
2224
|
+
}
|
|
2121
2225
|
export function markHarnessSessionId(sessionId: string | undefined, harnessSessionId: string | undefined): boolean {
|
|
2122
2226
|
const id = sessionId || ownSessionId()
|
|
2123
2227
|
if (!id || !harnessSessionId) return false
|
|
@@ -7,7 +7,9 @@ events:
|
|
|
7
7
|
- StopFailure
|
|
8
8
|
order: 10
|
|
9
9
|
block: false
|
|
10
|
+
code:
|
|
11
|
+
- .spec/project/.plugins/core/session-fail/fail.sh
|
|
10
12
|
---
|
|
11
13
|
When a turn ends not because the agent declared but because the API itself failed, this hook structurally marks the session `error`. A failed turn is a real outcome the board must show, and without this signal the session would freeze under whatever state it last held — reading as "active" or "awaiting" long after it actually died.
|
|
12
14
|
|
|
13
|
-
It is non-blocking
|
|
15
|
+
It is non-blocking on the failure event: the failure already happened, so the only job is to report it truthfully. As a board-lifecycle hook it acts only on a GOVERNED session — resolved in the global store from the payload's `session_id` — and writes via `spex internal session-fail --session <id>`. That machine entry reaches the same live-active compare-and-set as Codex's native failed completion and a headless turn's non-zero exit (harness-adapter): only an undeclared, non-stopped `active` record becomes `error`. A declaration, explicit stop, or archive that landed first remains authoritative; a late native failure never rewrites it. This one writer keeps the [[stop-gate]] family's invariant intact for every harness while each adapter retains only its native failure signal.
|
|
@@ -18,6 +18,6 @@ The body is the contract; update it with code when intent changes.
|
|
|
18
18
|
2. COMMIT BEFORE YOU DECLARE. Commit the spec and the code it justifies before declaring done or proposing merge.
|
|
19
19
|
Independent intent gets its own sibling node; do not ride it on an assigned node.
|
|
20
20
|
3. THE BODY IS A LIVING CURRENT-STATE DOCUMENT. Rewrite present intent in place; never add a `## vN` changelog.
|
|
21
|
-
4. KEEP THE LOSS SIGNAL HONEST. `spex spec lint` is the blocking correctness gate;
|
|
22
|
-
reports measurement gaps. Re-run changed eval scenarios through the real product, commit the verified tree, then
|
|
21
|
+
4. KEEP THE LOSS SIGNAL HONEST. Before declaring, run both: `spex spec lint` is the blocking correctness gate;
|
|
22
|
+
`spex eval lint --changed` reports measurement gaps. Re-run changed eval scenarios through the real product, commit the verified tree, then
|
|
23
23
|
file with `spex eval add`; the reading's `codeSha` must name that commit, and evidence must fit the behavior.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dashboard-
|
|
2
|
-
import{u as N,r as a,j as n,I as D,a as B,P as k,i as z,_ as T,D as M,b as G}from"./index-BqBNCa1V.js";import{a as J,l as q,s as F,p as V}from"./data-B1ot4PF0.js";const h=async e=>(e.headers.get("content-type")||"").includes("json")?e.json().catch(()=>null):null,H=5e3,O=(e,r,t)=>({title:typeof(e==null?void 0:e.title)=="string"&&e.title?e.title:r,icon:typeof(e==null?void 0:e.icon)=="string"&&e.icon?e.icon:t});function x(e){if(!e||typeof e!="object")return null;const r=e.id??e.projectId;return r?{id:String(r),identity:O(e.identity||{title:e.name,icon:e.icon},e.name||String(r),"spexcode"),root:typeof e.root=="string"?e.root:"",online:typeof e.online=="boolean"?e.online:null,url:e.url||"",port:e.port??null,gated:!!(e.gated??e.locked??e.hasPassword),configRevision:typeof e.configRevision=="string"?e.configRevision:""}:null}const W=e=>{const r=Array.isArray(e)?e:Array.isArray(e==null?void 0:e.projects)?e.projects:null;return r?r.map(x).filter(Boolean):null},Y=10;function ce(e,r,t=Y){const s=Array.isArray(e)?e:[],o=Math.max(1,Math.ceil(s.length/t)),l=Math.min(Math.max(1,Number.isInteger(r)?r:1),o);return{items:s.slice((l-1)*t,l*t),page:l,pageCount:o}}function Z(e,r,t){var s;if(!e)return t;if(!r)return null;if(r.state==="ok"){const o=(s=r.projects)==null?void 0:s.find(l=>l.id===e);return(o==null?void 0:o.identity)||{title:e,icon:"spexcode"}}return{title:(t==null?void 0:t.title)||e,icon:(t==null?void 0:t.icon)||"spexcode"}}const K=e=>(e==null?void 0:e.state)==="ok"?e.gateway.identity:{title:"Projects",icon:"gateway"},Q=e=>(e==null?void 0:e.title)||"SpexCode",R=(e,r)=>(r==null?void 0:r.state)==="absent"&&e&&e.state!=="absent"?e:r;async function X(){let e;try{e=await fetch("/projects",{cache:"no-store",headers:{Accept:"application/json"}})}catch{return{state:"absent"}}if(e.status===401)return{state:"denied",reason:"admin-login"};if(e.status===403)return{state:"denied",reason:"locked"};if(!e.ok)return{state:"absent"};const r=await h(e),t=W(r);if(!t)return{state:"absent"};const s=r!=null&&r.gateway&&typeof r.gateway=="object"?{identity:O(r.gateway,"Projects","gateway"),revision:typeof r.gateway.revision=="string"?r.gateway.revision:""}:{identity:{title:"Projects",icon:"gateway"},revision:""};return{state:"ok",adminGated:!!(r!=null&&r.adminGated),gateway:s,projects:t}}async function ie(e,{timeoutMs:r=2500}={}){try{const t=await fetch(`/p/${encodeURIComponent(e)}/health`,{cache:"no-store",signal:AbortSignal.timeout(r)});return!t.ok||t.redirected?"unreachable":(await t.text()).trim()==="ok"?"running":"unreachable"}catch{return"unreachable"}}async function C(e,r,t){let s;try{s=await fetch(e,{method:r,headers:{"Content-Type":"application/json",Accept:"application/json"},...r==="PUT"?{body:JSON.stringify({password:t})}:{}})}catch{return{ok:!1,error:"network"}}const o=await h(s)||{};return{ok:s.ok&&o.ok!==!1,status:s.status,...o.error?{error:o.error}:{}}}const le=(e,r)=>C(`/projects/${encodeURIComponent(e)}/password`,"PUT",r),ue=e=>C(`/projects/${encodeURIComponent(e)}/password`,"DELETE"),pe=e=>C("/projects/admin-password","PUT",e),de=()=>C("/projects/admin-password","DELETE");async function ee(e,r){const t=e==="admin"?"/login":`/p/${encodeURIComponent(e.projectId)}/login`;let s;try{s=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:r})})}catch{return{ok:!1,error:"network"}}return s.status===401?{ok:!1,error:"wrong-password"}:s.status===403?{ok:!1,error:"locked"}:s.ok||s.redirected?{ok:!0}:{ok:!1,error:`http-${s.status}`}}async function fe(e=""){let r;try{const s=e?`?path=${encodeURIComponent(e)}`:"";r=await fetch(`/projects/browse${s}`,{cache:"no-store",headers:{Accept:"application/json"}})}catch{return{ok:!1,error:"network"}}const t=await h(r);return r.ok?typeof(t==null?void 0:t.path)!="string"||!Array.isArray(t==null?void 0:t.entries)?{ok:!1,error:"unexpected answer"}:{ok:!0,path:t.path,parent:typeof t.parent=="string"?t.parent:null,home:typeof t.home=="string"?t.home:t.path,gitRoot:typeof t.gitRoot=="string"?t.gitRoot:null,initialized:!!t.initialized,cataloged:!!t.cataloged,entries:t.entries.filter(s=>s&&typeof s.name=="string"&&typeof s.path=="string").map(s=>({name:s.name,path:s.path,git:!!s.git,initialized:!!s.initialized}))}:{ok:!1,status:r.status,error:(t==null?void 0:t.error)||`http-${r.status}`}}async function he(e,r={}){let t;try{t=await fetch("/projects",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({root:e,...r})})}catch{return{ok:!1,error:"network"}}const s=await h(t);if(!t.ok)return{ok:!1,status:t.status,error:(s==null?void 0:s.error)||`http-${t.status}`,...s!=null&&s.init&&typeof s.init=="object"?{code:s.init.code??null,output:String(s.init.output??"")}:{}};const o=x(s);return o?{ok:!0,project:o,setup:s.setup??null}:{ok:!1,error:"unexpected answer"}}async function je(e){let r;try{r=await fetch(`/projects/${encodeURIComponent(e)}/config`,{cache:"no-store",headers:{Accept:"application/json"}})}catch{return{ok:!1,error:"network"}}const t=await h(r);return r.ok?typeof(t==null?void 0:t.content)!="string"||typeof(t==null?void 0:t.revision)!="string"?{ok:!1,error:"unexpected answer"}:{ok:!0,content:t.content,revision:t.revision}:{ok:!1,status:r.status,error:(t==null?void 0:t.error)||`http-${r.status}`}}async function me(e,r,t){let s;try{s=await fetch(`/projects/${encodeURIComponent(e)}/config`,{method:"PUT",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({content:r,revision:t})})}catch{return{ok:!1,error:"network"}}const o=await h(s);return s.ok?typeof(o==null?void 0:o.content)!="string"||typeof(o==null?void 0:o.revision)!="string"?{ok:!1,error:"unexpected answer"}:{ok:!0,content:o.content,revision:o.revision}:{ok:!1,status:s.status,error:(o==null?void 0:o.error)||`http-${s.status}`}}async function $(e,r,t){let s;try{s=await fetch(e,{method:"PUT",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({icon:r,revision:t})})}catch{return{ok:!1,error:"network"}}const o=await h(s);return s.ok?{ok:!0,...o}:{ok:!1,status:s.status,error:(o==null?void 0:o.error)||`http-${s.status}`}}const ke=(e,r)=>$("/projects/icon",e,r),ge=(e,r,t)=>$(`/projects/${encodeURIComponent(e)}/icon`,r,t);async function U(e,r,t={}){let s;try{s=await fetch(`/projects/${encodeURIComponent(e)}/${r}`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(t)})}catch{return{ok:!1,error:"network"}}const o=await h(s);return s.ok?!o||typeof o!="object"?{ok:!1,error:"unexpected answer"}:{ok:o.ok===!0,code:o.code??null,output:String(o.output??"")}:{ok:!1,status:s.status,error:(o==null?void 0:o.error)||`http-${s.status}`}}const we=(e,r)=>U(e,"init",{harness:r}),ye=e=>U(e,"doctor");async function Pe(e){let r;try{r=await fetch(`/projects/${encodeURIComponent(e)}/serve`,{method:"POST",headers:{Accept:"application/json"}})}catch{return{ok:!1,error:"network"}}const t=await h(r);return r.status===409?{ok:!0,already:!0,project:x(t==null?void 0:t.project)}:r.ok?{ok:!0,project:x(t==null?void 0:t.project)}:{ok:!1,status:r.status,error:(t==null?void 0:t.error)||`http-${r.status}`}}function I({scope:e,projectLabel:r,locked:t,onUnlocked:s}){const o=N(),[l,S]=a.useState(""),[j,A]=a.useState(!1),[g,P]=a.useState(null),m=e==="admin",p=async b=>{if(b.preventDefault(),!l||j)return;A(!0),P(null);const w=await ee(m?"admin":{projectId:e.projectId},l);A(!1),w.ok?(S(""),s()):P(w.error==="wrong-password"?o("credential.wrong"):o("credential.failed"))};return n.jsx("div",{className:"cred-wrap",children:n.jsxs("form",{className:"cred-card",onSubmit:p,children:[n.jsx("div",{className:"cred-brand",children:"$ spexcode"}),n.jsxs("div",{className:"cred-title",children:[n.jsx(D,{name:"lock",size:14,className:"cred-lock"}),t?o("credential.lockedTitle"):m?o("credential.adminTitle"):o("credential.projectTitle",{name:r||e&&e.projectId||""})]}),t?n.jsx("p",{className:"cred-sub",children:o("credential.lockedBody")}):n.jsxs(n.Fragment,{children:[n.jsx("p",{className:"cred-sub",children:o(m?"credential.adminBody":"credential.projectBody")}),g&&n.jsx("div",{className:"cred-err",children:g}),n.jsx("input",{className:"cred-input",type:"password",autoFocus:!0,required:!0,placeholder:"••••••••••","aria-label":o("credential.passwordLabel"),value:l,onChange:b=>S(b.target.value)}),n.jsx("button",{className:"cred-submit",type:"submit",disabled:j||!l,children:o(j?"credential.checking":"credential.unlock")})]})]})})}const te=a.lazy(()=>T(()=>import("./Dashboard-u8RIS3NY.js").then(e=>e.D),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9]))),re=a.lazy(()=>T(()=>import("./MobileApp-DVLnk9hz.js"),__vite__mapDeps([10,1,2,3,4,5,6,11,12]))),se=a.lazy(()=>T(()=>import("./ProjectsPage-UQyzsTWN.js"),__vite__mapDeps([13,1,2,7,5,6])));window.addEventListener("vite:preloadError",e=>{const r=String(e.payload);sessionStorage.getItem("spexcode.chunkReload")!==r&&(sessionStorage.setItem("spexcode.chunkReload",r),e.preventDefault(),location.reload())});function oe(){const e=N(),r=B(),[t,s]=a.useState(null),[o,l]=a.useState(!1),S=a.useRef(new Map),j=a.useCallback((u,c)=>{s(J(u,S.current,c))},[]),[A,g]=a.useState(!1),[P,m]=a.useState(null),[p,b]=a.useState(null);a.useEffect(()=>{let u=!0;const c=()=>X().then(y=>{u&&b(L=>R(L,y))}).catch(()=>{u&&b(y=>R(y,{state:"absent"}))});c();const d=setInterval(c,H);return()=>{u=!1,clearInterval(d)}},[]);const w=a.useRef(0),f=a.useCallback(()=>{const u=++w.current;return q().then(c=>{if(!(u!==w.current||!c)){if(c.authRequired){m(c.authRequired);return}m(null),g(!1),j(c.board,!0),c.seal()}}).catch(()=>{u===w.current&&g(!0)})},[j]),v=!k&&!t&&!!p&&p.state!=="absent",E=!k&&!t&&p===null;a.useEffect(()=>{if(v||E)return;f();const u=F({onBoard:(d,y)=>{w.current++,g(!1),j(d,!!(y!=null&&y.authoritative))},onLegacyChange:()=>{f()},onStatus:l}),c=setInterval(()=>{f()},15e3);return()=>{u(),clearInterval(c)}},[f,j,v,E]);const _=t?V(t):null,i=k?Z(k,p,_):v?K(p):_;return a.useEffect(()=>{i&&(document.title=Q(i))},[i==null?void 0:i.title]),a.useEffect(()=>{if(!i)return;const u=v?M:G,c=z(i.icon,u);let d=document.querySelector("link[rel~='icon']");d||(d=document.createElement("link"),d.rel="icon",document.head.appendChild(d)),d.getAttribute("href")!==c&&d.setAttribute("href",c)},[i==null?void 0:i.icon,v]),P&&k?n.jsx(I,{scope:{projectId:k},projectLabel:(i==null?void 0:i.title)||k,onUnlocked:()=>{m(null),f()}}):t?n.jsx(a.Suspense,{fallback:n.jsx("div",{className:"loading",children:e("hud.loading")}),children:r?n.jsx(re,{specs:t.nodes,sessions:t.sessions,issuesStamp:t.issuesStamp,reloadBoard:f}):n.jsx(te,{specs:t.nodes,sessions:t.sessions,issuesStamp:t.issuesStamp,reload:f,identity:i,catalog:p,boardLive:o})}):v?n.jsx(a.Suspense,{fallback:n.jsx("div",{className:"loading",children:e("hud.loading")}),children:n.jsx(se,{})}):P?n.jsx(I,{scope:"admin",locked:P==="locked",onUnlocked:()=>{m(null),f()}}):A&&(k||p&&p.state==="absent")?n.jsxs("div",{className:"loading load-error",children:[n.jsx("span",{children:e("hud.loadError")}),n.jsx("button",{className:"load-retry",onClick:()=>{g(!1),f()},children:e("hud.retry")})]}):n.jsx("div",{className:"loading",children:e("hud.loading")})}const be=Object.freeze(Object.defineProperty({__proto__:null,default:oe},Symbol.toStringTag,{value:"Module"}));export{be as A,H as C,ce as a,I as b,de as c,fe as d,je as e,ye as f,ke as g,he as h,we as i,me as j,ge as k,X as l,Pe as m,ue as n,le as o,ie as p,pe as s};
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dashboard-C5X4Va3V.js","assets/index-BUKLPN_4.js","assets/index-CzutlTDf.css","assets/SessionWindow-Dag_GiJB.js","assets/Thread-Dg35J-Pu.js","assets/PageScroll-B2kxcqJJ.js","assets/data-SNi0AmVT.js","assets/Modal-6l_QtCKF.js","assets/bindings-BC9vqpYU.js","assets/Dashboard-C5ap-Sga.css","assets/MobileApp-ClbtwZ1e.js","assets/TimelineChat-f0UF9fXq.js","assets/TimelineChat-Cp579UoJ.css","assets/ProjectsPage-C8IPsMKV.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{u as N,r as a,j as n,I as D,a as B,P as k,i as z,_ as T,D as M,b as G}from"./index-BUKLPN_4.js";import{a as J,l as q,s as F,p as V}from"./data-SNi0AmVT.js";const h=async e=>(e.headers.get("content-type")||"").includes("json")?e.json().catch(()=>null):null,H=5e3,O=(e,r,t)=>({title:typeof(e==null?void 0:e.title)=="string"&&e.title?e.title:r,icon:typeof(e==null?void 0:e.icon)=="string"&&e.icon?e.icon:t});function x(e){if(!e||typeof e!="object")return null;const r=e.id??e.projectId;return r?{id:String(r),identity:O(e.identity||{title:e.name,icon:e.icon},e.name||String(r),"spexcode"),root:typeof e.root=="string"?e.root:"",online:typeof e.online=="boolean"?e.online:null,url:e.url||"",port:e.port??null,gated:!!(e.gated??e.locked??e.hasPassword),configRevision:typeof e.configRevision=="string"?e.configRevision:""}:null}const W=e=>{const r=Array.isArray(e)?e:Array.isArray(e==null?void 0:e.projects)?e.projects:null;return r?r.map(x).filter(Boolean):null},Y=10;function ce(e,r,t=Y){const s=Array.isArray(e)?e:[],o=Math.max(1,Math.ceil(s.length/t)),l=Math.min(Math.max(1,Number.isInteger(r)?r:1),o);return{items:s.slice((l-1)*t,l*t),page:l,pageCount:o}}function Z(e,r,t){var s;if(!e)return t;if(!r)return null;if(r.state==="ok"){const o=(s=r.projects)==null?void 0:s.find(l=>l.id===e);return(o==null?void 0:o.identity)||{title:e,icon:"spexcode"}}return{title:(t==null?void 0:t.title)||e,icon:(t==null?void 0:t.icon)||"spexcode"}}const K=e=>(e==null?void 0:e.state)==="ok"?e.gateway.identity:{title:"Projects",icon:"gateway"},Q=e=>(e==null?void 0:e.title)||"SpexCode",R=(e,r)=>(r==null?void 0:r.state)==="absent"&&e&&e.state!=="absent"?e:r;async function X(){let e;try{e=await fetch("/projects",{cache:"no-store",headers:{Accept:"application/json"}})}catch{return{state:"absent"}}if(e.status===401)return{state:"denied",reason:"admin-login"};if(e.status===403)return{state:"denied",reason:"locked"};if(!e.ok)return{state:"absent"};const r=await h(e),t=W(r);if(!t)return{state:"absent"};const s=r!=null&&r.gateway&&typeof r.gateway=="object"?{identity:O(r.gateway,"Projects","gateway"),revision:typeof r.gateway.revision=="string"?r.gateway.revision:""}:{identity:{title:"Projects",icon:"gateway"},revision:""};return{state:"ok",adminGated:!!(r!=null&&r.adminGated),gateway:s,projects:t}}async function ie(e,{timeoutMs:r=2500}={}){try{const t=await fetch(`/p/${encodeURIComponent(e)}/health`,{cache:"no-store",signal:AbortSignal.timeout(r)});return!t.ok||t.redirected?"unreachable":(await t.text()).trim()==="ok"?"running":"unreachable"}catch{return"unreachable"}}async function C(e,r,t){let s;try{s=await fetch(e,{method:r,headers:{"Content-Type":"application/json",Accept:"application/json"},...r==="PUT"?{body:JSON.stringify({password:t})}:{}})}catch{return{ok:!1,error:"network"}}const o=await h(s)||{};return{ok:s.ok&&o.ok!==!1,status:s.status,...o.error?{error:o.error}:{}}}const le=(e,r)=>C(`/projects/${encodeURIComponent(e)}/password`,"PUT",r),ue=e=>C(`/projects/${encodeURIComponent(e)}/password`,"DELETE"),pe=e=>C("/projects/admin-password","PUT",e),de=()=>C("/projects/admin-password","DELETE");async function ee(e,r){const t=e==="admin"?"/login":`/p/${encodeURIComponent(e.projectId)}/login`;let s;try{s=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:r})})}catch{return{ok:!1,error:"network"}}return s.status===401?{ok:!1,error:"wrong-password"}:s.status===403?{ok:!1,error:"locked"}:s.ok||s.redirected?{ok:!0}:{ok:!1,error:`http-${s.status}`}}async function fe(e=""){let r;try{const s=e?`?path=${encodeURIComponent(e)}`:"";r=await fetch(`/projects/browse${s}`,{cache:"no-store",headers:{Accept:"application/json"}})}catch{return{ok:!1,error:"network"}}const t=await h(r);return r.ok?typeof(t==null?void 0:t.path)!="string"||!Array.isArray(t==null?void 0:t.entries)?{ok:!1,error:"unexpected answer"}:{ok:!0,path:t.path,parent:typeof t.parent=="string"?t.parent:null,home:typeof t.home=="string"?t.home:t.path,gitRoot:typeof t.gitRoot=="string"?t.gitRoot:null,initialized:!!t.initialized,cataloged:!!t.cataloged,entries:t.entries.filter(s=>s&&typeof s.name=="string"&&typeof s.path=="string").map(s=>({name:s.name,path:s.path,git:!!s.git,initialized:!!s.initialized}))}:{ok:!1,status:r.status,error:(t==null?void 0:t.error)||`http-${r.status}`}}async function he(e,r={}){let t;try{t=await fetch("/projects",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({root:e,...r})})}catch{return{ok:!1,error:"network"}}const s=await h(t);if(!t.ok)return{ok:!1,status:t.status,error:(s==null?void 0:s.error)||`http-${t.status}`,...s!=null&&s.init&&typeof s.init=="object"?{code:s.init.code??null,output:String(s.init.output??"")}:{}};const o=x(s);return o?{ok:!0,project:o,setup:s.setup??null}:{ok:!1,error:"unexpected answer"}}async function je(e){let r;try{r=await fetch(`/projects/${encodeURIComponent(e)}/config`,{cache:"no-store",headers:{Accept:"application/json"}})}catch{return{ok:!1,error:"network"}}const t=await h(r);return r.ok?typeof(t==null?void 0:t.content)!="string"||typeof(t==null?void 0:t.revision)!="string"?{ok:!1,error:"unexpected answer"}:{ok:!0,content:t.content,revision:t.revision}:{ok:!1,status:r.status,error:(t==null?void 0:t.error)||`http-${r.status}`}}async function me(e,r,t){let s;try{s=await fetch(`/projects/${encodeURIComponent(e)}/config`,{method:"PUT",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({content:r,revision:t})})}catch{return{ok:!1,error:"network"}}const o=await h(s);return s.ok?typeof(o==null?void 0:o.content)!="string"||typeof(o==null?void 0:o.revision)!="string"?{ok:!1,error:"unexpected answer"}:{ok:!0,content:o.content,revision:o.revision}:{ok:!1,status:s.status,error:(o==null?void 0:o.error)||`http-${s.status}`}}async function $(e,r,t){let s;try{s=await fetch(e,{method:"PUT",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({icon:r,revision:t})})}catch{return{ok:!1,error:"network"}}const o=await h(s);return s.ok?{ok:!0,...o}:{ok:!1,status:s.status,error:(o==null?void 0:o.error)||`http-${s.status}`}}const ke=(e,r)=>$("/projects/icon",e,r),ge=(e,r,t)=>$(`/projects/${encodeURIComponent(e)}/icon`,r,t);async function U(e,r,t={}){let s;try{s=await fetch(`/projects/${encodeURIComponent(e)}/${r}`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(t)})}catch{return{ok:!1,error:"network"}}const o=await h(s);return s.ok?!o||typeof o!="object"?{ok:!1,error:"unexpected answer"}:{ok:o.ok===!0,code:o.code??null,output:String(o.output??"")}:{ok:!1,status:s.status,error:(o==null?void 0:o.error)||`http-${s.status}`}}const we=(e,r)=>U(e,"init",{harness:r}),ye=e=>U(e,"doctor");async function Pe(e){let r;try{r=await fetch(`/projects/${encodeURIComponent(e)}/serve`,{method:"POST",headers:{Accept:"application/json"}})}catch{return{ok:!1,error:"network"}}const t=await h(r);return r.status===409?{ok:!0,already:!0,project:x(t==null?void 0:t.project)}:r.ok?{ok:!0,project:x(t==null?void 0:t.project)}:{ok:!1,status:r.status,error:(t==null?void 0:t.error)||`http-${r.status}`}}function I({scope:e,projectLabel:r,locked:t,onUnlocked:s}){const o=N(),[l,S]=a.useState(""),[j,A]=a.useState(!1),[g,P]=a.useState(null),m=e==="admin",p=async b=>{if(b.preventDefault(),!l||j)return;A(!0),P(null);const w=await ee(m?"admin":{projectId:e.projectId},l);A(!1),w.ok?(S(""),s()):P(w.error==="wrong-password"?o("credential.wrong"):o("credential.failed"))};return n.jsx("div",{className:"cred-wrap",children:n.jsxs("form",{className:"cred-card",onSubmit:p,children:[n.jsx("div",{className:"cred-brand",children:"$ spexcode"}),n.jsxs("div",{className:"cred-title",children:[n.jsx(D,{name:"lock",size:14,className:"cred-lock"}),t?o("credential.lockedTitle"):m?o("credential.adminTitle"):o("credential.projectTitle",{name:r||e&&e.projectId||""})]}),t?n.jsx("p",{className:"cred-sub",children:o("credential.lockedBody")}):n.jsxs(n.Fragment,{children:[n.jsx("p",{className:"cred-sub",children:o(m?"credential.adminBody":"credential.projectBody")}),g&&n.jsx("div",{className:"cred-err",children:g}),n.jsx("input",{className:"cred-input",type:"password",autoFocus:!0,required:!0,placeholder:"••••••••••","aria-label":o("credential.passwordLabel"),value:l,onChange:b=>S(b.target.value)}),n.jsx("button",{className:"cred-submit",type:"submit",disabled:j||!l,children:o(j?"credential.checking":"credential.unlock")})]})]})})}const te=a.lazy(()=>T(()=>import("./Dashboard-C5X4Va3V.js").then(e=>e.D),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9]))),re=a.lazy(()=>T(()=>import("./MobileApp-ClbtwZ1e.js"),__vite__mapDeps([10,1,2,3,4,5,6,11,12]))),se=a.lazy(()=>T(()=>import("./ProjectsPage-C8IPsMKV.js"),__vite__mapDeps([13,1,2,7,5,6])));window.addEventListener("vite:preloadError",e=>{const r=String(e.payload);sessionStorage.getItem("spexcode.chunkReload")!==r&&(sessionStorage.setItem("spexcode.chunkReload",r),e.preventDefault(),location.reload())});function oe(){const e=N(),r=B(),[t,s]=a.useState(null),[o,l]=a.useState(!1),S=a.useRef(new Map),j=a.useCallback((u,c)=>{s(J(u,S.current,c))},[]),[A,g]=a.useState(!1),[P,m]=a.useState(null),[p,b]=a.useState(null);a.useEffect(()=>{let u=!0;const c=()=>X().then(y=>{u&&b(L=>R(L,y))}).catch(()=>{u&&b(y=>R(y,{state:"absent"}))});c();const d=setInterval(c,H);return()=>{u=!1,clearInterval(d)}},[]);const w=a.useRef(0),f=a.useCallback(()=>{const u=++w.current;return q().then(c=>{if(!(u!==w.current||!c)){if(c.authRequired){m(c.authRequired);return}m(null),g(!1),j(c.board,!0),c.seal()}}).catch(()=>{u===w.current&&g(!0)})},[j]),v=!k&&!t&&!!p&&p.state!=="absent",E=!k&&!t&&p===null;a.useEffect(()=>{if(v||E)return;f();const u=F({onBoard:(d,y)=>{w.current++,g(!1),j(d,!!(y!=null&&y.authoritative))},onLegacyChange:()=>{f()},onStatus:l}),c=setInterval(()=>{f()},15e3);return()=>{u(),clearInterval(c)}},[f,j,v,E]);const _=t?V(t):null,i=k?Z(k,p,_):v?K(p):_;return a.useEffect(()=>{i&&(document.title=Q(i))},[i==null?void 0:i.title]),a.useEffect(()=>{if(!i)return;const u=v?M:G,c=z(i.icon,u);let d=document.querySelector("link[rel~='icon']");d||(d=document.createElement("link"),d.rel="icon",document.head.appendChild(d)),d.getAttribute("href")!==c&&d.setAttribute("href",c)},[i==null?void 0:i.icon,v]),P&&k?n.jsx(I,{scope:{projectId:k},projectLabel:(i==null?void 0:i.title)||k,onUnlocked:()=>{m(null),f()}}):t?n.jsx(a.Suspense,{fallback:n.jsx("div",{className:"loading",children:e("hud.loading")}),children:r?n.jsx(re,{specs:t.nodes,sessions:t.sessions,issuesStamp:t.issuesStamp,reloadBoard:f}):n.jsx(te,{specs:t.nodes,sessions:t.sessions,issuesStamp:t.issuesStamp,reload:f,identity:i,catalog:p,boardLive:o})}):v?n.jsx(a.Suspense,{fallback:n.jsx("div",{className:"loading",children:e("hud.loading")}),children:n.jsx(se,{})}):P?n.jsx(I,{scope:"admin",locked:P==="locked",onUnlocked:()=>{m(null),f()}}):A&&(k||p&&p.state==="absent")?n.jsxs("div",{className:"loading load-error",children:[n.jsx("span",{children:e("hud.loadError")}),n.jsx("button",{className:"load-retry",onClick:()=>{g(!1),f()},children:e("hud.retry")})]}):n.jsx("div",{className:"loading",children:e("hud.loading")})}const be=Object.freeze(Object.defineProperty({__proto__:null,default:oe},Symbol.toStringTag,{value:"Module"}));export{be as A,H as C,ce as a,I as b,de as c,fe as d,je as e,ye as f,ke as g,he as h,we as i,me as j,ge as k,X as l,Pe as m,ue as n,le as o,ie as p,pe as s};
|