@hanzlaa/rcode 4.1.2 → 4.3.1
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/cli/install.js +176 -13
- package/cli/lib/config.cjs +4 -2
- package/cli/lib/fsutil.cjs +13 -2
- package/cli/lib/homedir.cjs +21 -0
- package/cli/lib/schemas.cjs +6 -1
- package/cli/nuke.js +13 -8
- package/cli/postinstall.js +14 -4
- package/cli/rcode-slash-router.cjs +118 -0
- package/cli/uninstall.js +59 -1
- package/cli/update.js +10 -5
- package/dist/rcode.js +234 -230
- package/package.json +1 -1
- package/rcode/references/auto-init-guard.md +2 -2
- package/rcode/references/output-format.md +5 -5
- package/rcode/skills/actions/2-plan/rcode-create-milestone/steps/step-10-complete.md +1 -1
- package/server/dashboard.js +33 -13
- package/server/lib/api.js +62 -4
- package/server/lib/html/client/agents-data.js +22 -18
- package/server/lib/html/client/app.js +3 -0
- package/server/lib/html/client/components/AgentCard.js +127 -0
- package/server/lib/html/client/components/App.js +104 -39
- package/server/lib/html/client/components/CommandPalette.js +133 -0
- package/server/lib/html/client/components/FileReader.js +116 -0
- package/server/lib/html/client/components/FilterChips.js +94 -0
- package/server/lib/html/client/components/NotifyCenter.js +117 -0
- package/server/lib/html/client/components/OrchPanel.js +80 -52
- package/server/lib/html/client/components/PhaseGraph.js +300 -0
- package/server/lib/html/client/components/RejectDialog.js +78 -0
- package/server/lib/html/client/components/RunnerPicker.js +190 -0
- package/server/lib/html/client/components/Sidebar.js +106 -61
- package/server/lib/html/client/components/StatusSummaryBar.js +76 -0
- package/server/lib/html/client/components/TaskPipeline.js +83 -0
- package/server/lib/html/client/components/Topbar.js +86 -39
- package/server/lib/html/client/components/dashboard/Blockers.js +57 -0
- package/server/lib/html/client/components/dashboard/CompletedTasks.js +47 -0
- package/server/lib/html/client/components/dashboard/CurrentPhase.js +107 -0
- package/server/lib/html/client/components/dashboard/InProgress.js +72 -0
- package/server/lib/html/client/components/dashboard/ProgressDonut.js +101 -0
- package/server/lib/html/client/components/dashboard/ProgressTimeline.js +101 -0
- package/server/lib/html/client/components/dashboard/ProjectHealth.js +80 -0
- package/server/lib/html/client/components/dashboard/RecentDecisions.js +57 -0
- package/server/lib/html/client/components/dashboard/Timeline.js +143 -0
- package/server/lib/html/client/components/shared.js +47 -11
- package/server/lib/html/client/filter-state.js +72 -0
- package/server/lib/html/client/icons-client.js +7 -0
- package/server/lib/html/client/notify.js +75 -0
- package/server/lib/html/client/orchestrator.js +168 -41
- package/server/lib/html/client/preact.js +13 -8
- package/server/lib/html/client/store.js +70 -6
- package/server/lib/html/client/util.js +78 -0
- package/server/lib/html/client/vendor/htm.js +1 -0
- package/server/lib/html/client/vendor/preact-hooks.js +2 -0
- package/server/lib/html/client/vendor/preact.js +2 -0
- package/server/lib/html/client/views/AgentsView.js +144 -51
- package/server/lib/html/client/views/FilesView.js +20 -103
- package/server/lib/html/client/views/KanbanView.js +40 -21
- package/server/lib/html/client/views/MemoryView.js +26 -9
- package/server/lib/html/client/views/MilestonesView.js +4 -4
- package/server/lib/html/client/views/OrchestrationView.js +154 -19
- package/server/lib/html/client/views/OverviewView.js +47 -239
- package/server/lib/html/client/views/PhasesView.js +50 -6
- package/server/lib/html/client/views/RoadmapView.js +6 -3
- package/server/lib/html/client/views/SprintsView.js +50 -6
- package/server/lib/html/client/views/TasksView.js +4 -3
- package/server/lib/html/client.js +21 -4
- package/server/lib/html/css.js +2761 -8
- package/server/lib/html/icons.js +7 -0
- package/server/lib/html/shell.js +10 -3
- package/server/lib/scanner.js +376 -39
- package/server/orchestrator.js +346 -7
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import { getState, setState } from './store.js';
|
|
14
14
|
import { showToast } from './components/shared.js';
|
|
15
|
+
import { trackBlocked } from './notify.js';
|
|
15
16
|
|
|
16
17
|
export const ORCH_HTTP = 'http://localhost:7718';
|
|
17
18
|
export const ORCH_WS = 'ws://localhost:7718';
|
|
@@ -38,17 +39,43 @@ export function refreshOrchToken() {
|
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* POST /api/run — start a PTY session for storyId.
|
|
42
|
+
* opts = { runner?, model? } — which agent CLI / model to launch. Omitted →
|
|
43
|
+
* the server default (claude, no model flag). The server re-validates both.
|
|
41
44
|
* Returns the parsed JSON response (or throws on network error).
|
|
42
45
|
*/
|
|
43
|
-
export function runSession(storyId, cmd) {
|
|
44
|
-
const tok
|
|
46
|
+
export function runSession(storyId, cmd, opts) {
|
|
47
|
+
const tok = orchToken();
|
|
48
|
+
const body = { storyId, cmd };
|
|
49
|
+
if (opts && opts.runner) {
|
|
50
|
+
body.runner = opts.runner;
|
|
51
|
+
if (opts.model) body.model = opts.model;
|
|
52
|
+
}
|
|
45
53
|
return fetch(ORCH_HTTP + '/api/run', {
|
|
46
54
|
method: 'POST',
|
|
47
55
|
headers: { 'Authorization': 'Bearer ' + tok, 'Content-Type': 'application/json' },
|
|
48
|
-
body: JSON.stringify(
|
|
56
|
+
body: JSON.stringify(body),
|
|
49
57
|
}).then(r => r.json());
|
|
50
58
|
}
|
|
51
59
|
|
|
60
|
+
/**
|
|
61
|
+
* GET /api/runners — detected agent CLIs: [{ id, label, available, models }].
|
|
62
|
+
* The list is fixed for the orchestrator's lifetime (detected once at boot),
|
|
63
|
+
* so the first successful response is cached; failures are not cached so a
|
|
64
|
+
* later open retries.
|
|
65
|
+
*/
|
|
66
|
+
let _runnersPromise = null;
|
|
67
|
+
export function fetchRunners() {
|
|
68
|
+
if (_runnersPromise) return _runnersPromise;
|
|
69
|
+
const tok = orchToken();
|
|
70
|
+
_runnersPromise = fetch(ORCH_HTTP + '/api/runners', {
|
|
71
|
+
headers: { 'Authorization': 'Bearer ' + tok },
|
|
72
|
+
})
|
|
73
|
+
.then(r => r.json())
|
|
74
|
+
.then(d => (d && d.runners) || [])
|
|
75
|
+
.catch(() => { _runnersPromise = null; return []; });
|
|
76
|
+
return _runnersPromise;
|
|
77
|
+
}
|
|
78
|
+
|
|
52
79
|
/**
|
|
53
80
|
* POST /api/stop — stop a running session.
|
|
54
81
|
*/
|
|
@@ -62,21 +89,95 @@ export function stopSession(storyId) {
|
|
|
62
89
|
}
|
|
63
90
|
|
|
64
91
|
/**
|
|
65
|
-
* GET /api/sessions —
|
|
92
|
+
* GET /api/sessions — resolve { ok, sessions }. ok=false means the
|
|
93
|
+
* orchestrator was unreachable (network failure / no token), which the
|
|
94
|
+
* session poll records as orchOnline so the UI can show a down state.
|
|
66
95
|
*/
|
|
67
|
-
|
|
96
|
+
function fetchSessionsWithStatus() {
|
|
68
97
|
const tok = orchToken();
|
|
69
|
-
if (!tok) return Promise.resolve([]);
|
|
98
|
+
if (!tok) return Promise.resolve({ ok: false, sessions: [] });
|
|
70
99
|
return fetch(ORCH_HTTP + '/api/sessions', {
|
|
71
100
|
headers: { 'Authorization': 'Bearer ' + tok },
|
|
72
101
|
})
|
|
102
|
+
.then(r => {
|
|
103
|
+
if (r.status === 401) { refreshOrchToken(); return { ok: true, sessions: [] }; }
|
|
104
|
+
return r.json().then(d => ({ ok: true, sessions: (d && d.sessions) || [] }));
|
|
105
|
+
})
|
|
106
|
+
.catch(() => ({ ok: false, sessions: [] }));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* GET /api/sessions — return the sessions array (or [] on error).
|
|
111
|
+
*/
|
|
112
|
+
export function fetchSessions() {
|
|
113
|
+
return fetchSessionsWithStatus().then(r => r.sessions);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* GET /api/history — return the persisted run history array (or [] on error).
|
|
118
|
+
*/
|
|
119
|
+
export function fetchHistory() {
|
|
120
|
+
const tok = orchToken();
|
|
121
|
+
if (!tok) return Promise.resolve([]);
|
|
122
|
+
return fetch(ORCH_HTTP + '/api/history', { headers: { 'Authorization': 'Bearer ' + tok } })
|
|
73
123
|
.then(r => {
|
|
74
124
|
if (r.status === 401) { refreshOrchToken(); return []; }
|
|
75
|
-
return r.json().then(d => (d && d.
|
|
125
|
+
return r.json().then(d => (d && d.history) || []);
|
|
76
126
|
})
|
|
77
127
|
.catch(() => []);
|
|
78
128
|
}
|
|
79
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Merge live sessions with persisted history, keyed on storyId.
|
|
132
|
+
* Live session fields win for most properties; durationMs and endTime are
|
|
133
|
+
* field-aware: the live record may not have them yet (session still running),
|
|
134
|
+
* so fall back to the history value if the live field is null/undefined.
|
|
135
|
+
*/
|
|
136
|
+
export function mergeSessionsAndHistory(live, hist) {
|
|
137
|
+
const byId = new Map();
|
|
138
|
+
for (const h of hist || []) byId.set(h.storyId, { ...h, source: 'history' });
|
|
139
|
+
for (const s of live || []) {
|
|
140
|
+
const h = byId.get(s.storyId) || {};
|
|
141
|
+
byId.set(s.storyId, {
|
|
142
|
+
...h,
|
|
143
|
+
...s,
|
|
144
|
+
source: 'live',
|
|
145
|
+
durationMs: s.durationMs ?? h.durationMs,
|
|
146
|
+
endTime: s.endTime ?? h.endTime,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return [...byId.values()];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** True unless the last session poll found the orchestrator unreachable. */
|
|
153
|
+
export function isOrchOnline() {
|
|
154
|
+
return getState().orchOnline !== false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* POST /api/reject — record a structured rejection reason for storyId.
|
|
159
|
+
* phase is optional. Returns the parsed JSON response.
|
|
160
|
+
*/
|
|
161
|
+
export function submitRejection(storyId, reason, phase) {
|
|
162
|
+
const tok = orchToken();
|
|
163
|
+
return fetch(ORCH_HTTP + '/api/reject', {
|
|
164
|
+
method: 'POST',
|
|
165
|
+
headers: { 'Authorization': 'Bearer ' + tok, 'Content-Type': 'application/json' },
|
|
166
|
+
body: JSON.stringify({ storyId, reason, phase: phase || null }),
|
|
167
|
+
}).then(r => r.json());
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* GET /api/rejections — return the persisted rejections array (or [] on error).
|
|
172
|
+
*/
|
|
173
|
+
export function fetchRejections() {
|
|
174
|
+
const tok = orchToken();
|
|
175
|
+
if (!tok) return Promise.resolve([]);
|
|
176
|
+
return fetch(ORCH_HTTP + '/api/rejections', { headers: { 'Authorization': 'Bearer ' + tok } })
|
|
177
|
+
.then(r => r.ok ? r.json().then(d => (d && d.rejections) || []) : [])
|
|
178
|
+
.catch(() => []);
|
|
179
|
+
}
|
|
180
|
+
|
|
80
181
|
/**
|
|
81
182
|
* POST /api/clean-sessions — remove ended sessions.
|
|
82
183
|
* olderThanDays = 0 removes all ended sessions; > 0 keeps recent ones.
|
|
@@ -102,10 +203,13 @@ export function activeSession(storyId) {
|
|
|
102
203
|
return (activeSessions || []).find(s => s.storyId === storyId) || null;
|
|
103
204
|
}
|
|
104
205
|
|
|
105
|
-
/**
|
|
206
|
+
/**
|
|
207
|
+
* True when storyId has a live session. 'blocked' is a live PTY waiting for
|
|
208
|
+
* input (server-side classification of running), so it counts as running here.
|
|
209
|
+
*/
|
|
106
210
|
export function isSessionRunning(storyId) {
|
|
107
|
-
const
|
|
108
|
-
return !!(
|
|
211
|
+
const { runningByStory } = getState();
|
|
212
|
+
return !!(storyId && runningByStory && runningByStory[storyId]);
|
|
109
213
|
}
|
|
110
214
|
|
|
111
215
|
/** Count running sessions touching this sprint (sprint-level + its stories). */
|
|
@@ -122,16 +226,22 @@ export function runningInPhase(p) {
|
|
|
122
226
|
return n;
|
|
123
227
|
}
|
|
124
228
|
|
|
125
|
-
/** Total count of sessions
|
|
229
|
+
/** Total count of live sessions (running or blocked-on-input). */
|
|
126
230
|
export function runningTotal() {
|
|
127
231
|
const { activeSessions } = getState();
|
|
128
|
-
return (activeSessions || []).filter(s => s.status === 'running').length;
|
|
232
|
+
return (activeSessions || []).filter(s => s.status === 'running' || s.status === 'blocked').length;
|
|
129
233
|
}
|
|
130
234
|
|
|
131
235
|
// ── Session poll ──────────────────────────────────────────────────────────────
|
|
132
236
|
|
|
133
237
|
let _pollTimer = null;
|
|
134
238
|
|
|
239
|
+
// Serialized snapshot of the last committed activeSessions. The 4s poll
|
|
240
|
+
// always produces a NEW array identity, which defeats the store's
|
|
241
|
+
// reference-equality change check — so compare content here and only
|
|
242
|
+
// setState when the sessions actually changed.
|
|
243
|
+
let _lastSessionsJson = null;
|
|
244
|
+
|
|
135
245
|
/**
|
|
136
246
|
* Start polling /api/sessions every 4 s and writing activeSessions into the
|
|
137
247
|
* store. Components react via useStore(). Safe to call multiple times — only
|
|
@@ -149,9 +259,23 @@ export function stopSessionsPoll() {
|
|
|
149
259
|
}
|
|
150
260
|
|
|
151
261
|
function _poll() {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
262
|
+
Promise.all([fetchSessionsWithStatus(), fetchHistory(), fetchRejections()])
|
|
263
|
+
.then(([{ ok, sessions }, history, rejections]) => {
|
|
264
|
+
// Merge any recorded rejection onto its matching session by storyId.
|
|
265
|
+
const byId = {};
|
|
266
|
+
for (const r of rejections) byId[r.storyId] = r;
|
|
267
|
+
const merged = sessions.map(s => byId[s.storyId] ? { ...s, rejection: byId[s.storyId] } : s);
|
|
268
|
+
|
|
269
|
+
// Dedupe: skip the setState when neither the session list, the
|
|
270
|
+
// orchestrator-online flag, nor the history changed — avoids a
|
|
271
|
+
// full-app re-render per poll tick.
|
|
272
|
+
const json = JSON.stringify(merged) + '|' + ok + '|' + JSON.stringify(history);
|
|
273
|
+
if (json === _lastSessionsJson) return;
|
|
274
|
+
_lastSessionsJson = json;
|
|
275
|
+
setState({ activeSessions: merged, history, orchOnline: ok });
|
|
276
|
+
// Detect running→blocked transitions and raise persistent alerts.
|
|
277
|
+
trackBlocked(merged);
|
|
278
|
+
});
|
|
155
279
|
}
|
|
156
280
|
|
|
157
281
|
// ── runAndOpenTerm convenience ────────────────────────────────────────────────
|
|
@@ -163,8 +287,9 @@ function _poll() {
|
|
|
163
287
|
* @param {string} storyId
|
|
164
288
|
* @param {string} cmd
|
|
165
289
|
* @param {string} title
|
|
290
|
+
* @param {{ runner?: string, model?: string }} [opts] — agent CLI selection
|
|
166
291
|
*/
|
|
167
|
-
export function runAndOpenTerm(storyId, cmd, title) {
|
|
292
|
+
export function runAndOpenTerm(storyId, cmd, title, opts) {
|
|
168
293
|
// Open the panel immediately (it shows "connecting" while the session starts).
|
|
169
294
|
setState({
|
|
170
295
|
terminal: {
|
|
@@ -177,9 +302,19 @@ export function runAndOpenTerm(storyId, cmd, title) {
|
|
|
177
302
|
});
|
|
178
303
|
|
|
179
304
|
const tok = orchToken();
|
|
180
|
-
if (!tok) return;
|
|
305
|
+
if (!tok) { showToast('No orchestrator token — restart the dashboard'); return; }
|
|
181
306
|
|
|
182
|
-
runSession(storyId, cmd
|
|
307
|
+
runSession(storyId, cmd, opts)
|
|
308
|
+
.then(data => {
|
|
309
|
+
// 409 = already running (terminal reattaches); anything else is surfaced.
|
|
310
|
+
if (data && data.error && !data.error.includes('already running')) {
|
|
311
|
+
showToast('Run error: ' + data.error);
|
|
312
|
+
}
|
|
313
|
+
})
|
|
314
|
+
.catch(err => {
|
|
315
|
+
console.error('[orchestrator] session op failed:', err.message);
|
|
316
|
+
showToast('Could not reach orchestrator — session not started');
|
|
317
|
+
});
|
|
183
318
|
}
|
|
184
319
|
|
|
185
320
|
/**
|
|
@@ -205,15 +340,6 @@ export function openOrchPanel(storyId) {
|
|
|
205
340
|
setState({ orchPanel: { open: true, storyId } });
|
|
206
341
|
}
|
|
207
342
|
|
|
208
|
-
/**
|
|
209
|
-
* runStory — Kanban "Run" action. Moves card to in_progress visually then
|
|
210
|
-
* delegates to runAndOpenTerm.
|
|
211
|
-
*/
|
|
212
|
-
export function runStory(storyId) {
|
|
213
|
-
if (!storyId) return;
|
|
214
|
-
runAndOpenTerm(storyId, '/rcode-dev-story ' + storyId, storyId);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
343
|
/**
|
|
218
344
|
* stopStory — Kanban "Stop" action.
|
|
219
345
|
*/
|
|
@@ -228,18 +354,18 @@ export function stopStory(storyId) {
|
|
|
228
354
|
* Update both when adding a new command.
|
|
229
355
|
*/
|
|
230
356
|
export const ALLOWED_COMMANDS = [
|
|
231
|
-
{ cmd: '/rcode-init', label: 'init — initialise project workspace' },
|
|
232
|
-
{ cmd: '/rcode-
|
|
233
|
-
{ cmd: '/rcode-
|
|
234
|
-
{ cmd: '/rcode-
|
|
235
|
-
{ cmd: '/rcode-
|
|
236
|
-
{ cmd: '/rcode-
|
|
237
|
-
{ cmd: '/rcode-show', label: 'show — show current plan' },
|
|
238
|
-
{ cmd: '/rcode-list-plans', label: 'list-plans — list all sprint plans' },
|
|
239
|
-
{ cmd: '/rcode-
|
|
240
|
-
{ cmd: '/rcode-
|
|
241
|
-
{ cmd: '/rcode-
|
|
242
|
-
{ cmd: '/rcode-
|
|
357
|
+
{ cmd: '/rcode-init', label: 'init — initialise project workspace', category: 'Project' },
|
|
358
|
+
{ cmd: '/rcode-config', label: 'config — show rcode config', category: 'Project' },
|
|
359
|
+
{ cmd: '/rcode-status', label: 'status — phase / sprint status', category: 'Status' },
|
|
360
|
+
{ cmd: '/rcode-progress', label: 'progress — milestone progress', category: 'Status' },
|
|
361
|
+
{ cmd: '/rcode-sprint-status', label: 'sprint-status — sprint execution status',category: 'Status' },
|
|
362
|
+
{ cmd: '/rcode-stats', label: 'stats — project statistics', category: 'Status' },
|
|
363
|
+
{ cmd: '/rcode-show', label: 'show — show current plan', category: 'Planning' },
|
|
364
|
+
{ cmd: '/rcode-list-plans', label: 'list-plans — list all sprint plans', category: 'Planning' },
|
|
365
|
+
{ cmd: '/rcode-next', label: 'next — suggest next action', category: 'Planning' },
|
|
366
|
+
{ cmd: '/rcode-help', label: 'help — command reference', category: 'Inspect' },
|
|
367
|
+
{ cmd: '/rcode-health', label: 'health — repo health check', category: 'Inspect' },
|
|
368
|
+
{ cmd: '/rcode-diff', label: 'diff — diff since last checkpoint', category: 'Inspect' },
|
|
243
369
|
];
|
|
244
370
|
|
|
245
371
|
/**
|
|
@@ -255,8 +381,9 @@ export const ALLOWED_COMMANDS = [
|
|
|
255
381
|
* - network failure → showToast('Could not reach orchestrator')
|
|
256
382
|
*
|
|
257
383
|
* @param {string} cmd Must be one of ALLOWED_COMMANDS[*].cmd.
|
|
384
|
+
* @param {{ runner?: string, model?: string }} [opts] — agent CLI selection
|
|
258
385
|
*/
|
|
259
|
-
export function runCommandFromUI(cmd) {
|
|
386
|
+
export function runCommandFromUI(cmd, opts) {
|
|
260
387
|
if (!cmd) return;
|
|
261
388
|
const slug = cmd.replace(/^\//, '').replace(/\//g, '-');
|
|
262
389
|
const storyId = 'cmd-' + slug;
|
|
@@ -269,7 +396,7 @@ export function runCommandFromUI(cmd) {
|
|
|
269
396
|
const tok = orchToken();
|
|
270
397
|
if (!tok) { showToast('No orchestrator token — restart the dashboard'); return; }
|
|
271
398
|
|
|
272
|
-
runSession(storyId, cmd)
|
|
399
|
+
runSession(storyId, cmd, opts)
|
|
273
400
|
.then(data => {
|
|
274
401
|
// 409 = already running (not an error — terminal is already attached).
|
|
275
402
|
if (data && data.error && !data.error.includes('already running')) {
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Preact + htm ESM runtime — single dependency surface.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Vendored locally under vendor/ so the dashboard works offline /
|
|
5
|
+
* air-gapped / on CI screens with no internet (no esm.sh dependency).
|
|
6
|
+
* Every other client module imports from this file so version bumps
|
|
7
|
+
* happen in one place: replace the vendor/ files and update the pins.
|
|
6
8
|
*
|
|
7
|
-
* Pinned versions
|
|
8
|
-
* preact 10.24.3
|
|
9
|
-
* htm 3.1.1
|
|
9
|
+
* Pinned vendored versions:
|
|
10
|
+
* preact 10.24.3 (vendor/preact.js, vendor/preact-hooks.js)
|
|
11
|
+
* htm 3.1.1 (vendor/htm.js)
|
|
12
|
+
*
|
|
13
|
+
* vendor/preact-hooks.js has its bare `from "preact"` import rewritten
|
|
14
|
+
* to `from "./preact.js"` so it resolves without an import map.
|
|
10
15
|
*/
|
|
11
16
|
|
|
12
|
-
import { h, render, Fragment } from '
|
|
17
|
+
import { h, render, Fragment } from './vendor/preact.js';
|
|
13
18
|
import {
|
|
14
19
|
useState,
|
|
15
20
|
useEffect,
|
|
@@ -17,8 +22,8 @@ import {
|
|
|
17
22
|
useMemo,
|
|
18
23
|
useCallback,
|
|
19
24
|
useReducer,
|
|
20
|
-
} from '
|
|
21
|
-
import htmLib from '
|
|
25
|
+
} from './vendor/preact-hooks.js';
|
|
26
|
+
import htmLib from './vendor/htm.js';
|
|
22
27
|
|
|
23
28
|
// htm bound to Preact's h — use as a tagged template literal: html`<div>...</div>`
|
|
24
29
|
export const html = htmLib.bind(h);
|
|
@@ -14,9 +14,19 @@ import { useState, useEffect } from './preact.js';
|
|
|
14
14
|
const _seed = (typeof window !== 'undefined' && window.__S__) || {};
|
|
15
15
|
|
|
16
16
|
let _state = {
|
|
17
|
+
// First-run signal — false only when the server scanned and found no .rcode.
|
|
18
|
+
initialized: _seed.initialized !== false,
|
|
19
|
+
// Redesign dashboard contract slices (DATA-CONTRACT.md) — read by the Overview
|
|
20
|
+
// slot components. Derived server-side by scanner.buildDashboard.
|
|
21
|
+
project: _seed.project || null,
|
|
22
|
+
progress: _seed.progress || null,
|
|
23
|
+
timeline: _seed.timeline || null,
|
|
24
|
+
tasks: _seed.tasks || null,
|
|
25
|
+
health: _seed.health || null,
|
|
17
26
|
// Fields injected by client.js / window.__S__
|
|
18
27
|
phases: _seed.phases || [],
|
|
19
28
|
milestone: _seed.milestone || '',
|
|
29
|
+
// currentPhase is now the contract object { name, status, milestones[] }.
|
|
20
30
|
currentPhase: _seed.currentPhase || null,
|
|
21
31
|
currentSprint: _seed.currentSprint || null,
|
|
22
32
|
decisions: _seed.decisions || [],
|
|
@@ -37,9 +47,26 @@ let _state = {
|
|
|
37
47
|
refreshing: false,
|
|
38
48
|
offline: false,
|
|
39
49
|
lastRefresh: null,
|
|
50
|
+
// state.json parse failure message (or null). Surfaced as a dismissible
|
|
51
|
+
// banner in App.js; parseErrorDismissed is session-local UI state.
|
|
52
|
+
rawParseError: _seed.rawParseError || null,
|
|
53
|
+
parseErrorDismissed: false,
|
|
40
54
|
// Live orchestrator sessions (populated by startSessionsPoll in orchestrator.js)
|
|
41
55
|
activeSessions: [],
|
|
42
|
-
//
|
|
56
|
+
// Derived join map: storyId → running session. Recomputed automatically by
|
|
57
|
+
// setState whenever activeSessions is written, so views can join tasks to
|
|
58
|
+
// live runs without scanning the array (TasksView, Kanban, Overview).
|
|
59
|
+
runningByStory: {},
|
|
60
|
+
// Persisted past runs (populated by startSessionsPoll → fetchHistory)
|
|
61
|
+
history: [],
|
|
62
|
+
// Orchestrator reachability: null = unknown (before first poll),
|
|
63
|
+
// true = reachable, false = unreachable. Written by the 4s session poll.
|
|
64
|
+
orchOnline: null,
|
|
65
|
+
// Persistent blocked-session alerts (written by notify.js trackBlocked).
|
|
66
|
+
// [{ storyId, cmd }] — rendered as clickable toasts by NotifyCenter.js.
|
|
67
|
+
blockedAlerts: [],
|
|
68
|
+
// File jump bridge: the agent drawer's "View file in Files" sets this to a
|
|
69
|
+
// project-relative .md path; FilesView opens it on arrival and clears it.
|
|
43
70
|
requestedFile: null,
|
|
44
71
|
// xterm terminal panel state (driven by orchestrator.js / XtermPanel.js)
|
|
45
72
|
// { open, storyId, title, minimized, fullscreen }
|
|
@@ -47,6 +74,9 @@ let _state = {
|
|
|
47
74
|
// Orchestrator side-panel state (driven by orchestrator.js / OrchPanel.js)
|
|
48
75
|
// { open, storyId }
|
|
49
76
|
orchPanel: null,
|
|
77
|
+
// Runner-picker popover state (driven by components/RunnerPicker.js)
|
|
78
|
+
// { open, x, y, run: { kind: 'session'|'command', storyId?, cmd, title? } }
|
|
79
|
+
runnerPicker: null,
|
|
50
80
|
};
|
|
51
81
|
|
|
52
82
|
/** Registered subscriber functions. */
|
|
@@ -57,11 +87,25 @@ export function getState() {
|
|
|
57
87
|
return { ..._state };
|
|
58
88
|
}
|
|
59
89
|
|
|
90
|
+
/** Build the storyId → session map for LIVE sessions. A 'blocked' session is
|
|
91
|
+
* a live PTY waiting for input, so it counts as live alongside 'running'. */
|
|
92
|
+
function deriveRunningByStory(sessions) {
|
|
93
|
+
const map = {};
|
|
94
|
+
for (const s of sessions || []) {
|
|
95
|
+
if (s && s.storyId && (s.status === 'running' || s.status === 'blocked')) map[s.storyId] = s;
|
|
96
|
+
}
|
|
97
|
+
return map;
|
|
98
|
+
}
|
|
99
|
+
|
|
60
100
|
/**
|
|
61
101
|
* Shallow-merge `patch` into state, then notify all subscribers.
|
|
62
102
|
* Only notifies if at least one key actually changed value.
|
|
103
|
+
* Writing activeSessions also refreshes the derived runningByStory map.
|
|
63
104
|
*/
|
|
64
105
|
export function setState(patch) {
|
|
106
|
+
if ('activeSessions' in patch) {
|
|
107
|
+
patch = { ...patch, runningByStory: deriveRunningByStory(patch.activeSessions) };
|
|
108
|
+
}
|
|
65
109
|
let changed = false;
|
|
66
110
|
for (const key of Object.keys(patch)) {
|
|
67
111
|
if (_state[key] !== patch[key]) {
|
|
@@ -107,14 +151,34 @@ export function refresh() {
|
|
|
107
151
|
|
|
108
152
|
/**
|
|
109
153
|
* Preact hook. Subscribes the calling component to the store and
|
|
110
|
-
* returns the current state
|
|
154
|
+
* returns the current state (or the selected slice).
|
|
155
|
+
*
|
|
156
|
+
* Without a selector the component re-renders on every setState().
|
|
157
|
+
* With a selector it re-renders only when the selected value changes
|
|
158
|
+
* (Object.is), so slice subscribers skip unrelated store traffic:
|
|
159
|
+
*
|
|
160
|
+
* const project = useStore(s => s.project);
|
|
161
|
+
*
|
|
162
|
+
* The selector must be pure and is captured on mount — pass a stable
|
|
163
|
+
* function (module-level or inline reading fixed keys), not one that
|
|
164
|
+
* closes over changing props.
|
|
111
165
|
*/
|
|
112
|
-
export function useStore() {
|
|
113
|
-
const [state, setLocalState] = useState(
|
|
166
|
+
export function useStore(selector) {
|
|
167
|
+
const [state, setLocalState] = useState(
|
|
168
|
+
() => (selector ? selector(_state) : getState())
|
|
169
|
+
);
|
|
114
170
|
useEffect(() => {
|
|
171
|
+
const update = (newState) => {
|
|
172
|
+
if (selector) {
|
|
173
|
+
const next = selector(newState);
|
|
174
|
+
setLocalState(prev => (Object.is(prev, next) ? prev : next));
|
|
175
|
+
} else {
|
|
176
|
+
setLocalState({ ...newState });
|
|
177
|
+
}
|
|
178
|
+
};
|
|
115
179
|
// Resync on mount in case setState was called before mount.
|
|
116
|
-
|
|
117
|
-
const unsub = subscribe(
|
|
180
|
+
update(_state);
|
|
181
|
+
const unsub = subscribe(update);
|
|
118
182
|
return unsub;
|
|
119
183
|
}, []);
|
|
120
184
|
return state;
|
|
@@ -33,6 +33,29 @@ export function humanDate(s) {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Display name for the store's `currentPhase`, which may be the contract
|
|
38
|
+
* object { id, name, status, milestones[] }, a legacy plain string/number
|
|
39
|
+
* (raw state.json current_phase), or null. Returns '' when absent —
|
|
40
|
+
* never "[object Object]".
|
|
41
|
+
*/
|
|
42
|
+
export function currentPhaseName(cp) {
|
|
43
|
+
if (cp == null) return '';
|
|
44
|
+
if (typeof cp === 'object') return cp.name || (cp.id != null ? String(cp.id) : '');
|
|
45
|
+
return String(cp);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Identifier for the store's `currentPhase` (same shapes as currentPhaseName).
|
|
50
|
+
* Prefers the phase id (what commands and phase-card comparisons use);
|
|
51
|
+
* falls back to the name. Returns '' when absent.
|
|
52
|
+
*/
|
|
53
|
+
export function currentPhaseId(cp) {
|
|
54
|
+
if (cp == null) return '';
|
|
55
|
+
if (typeof cp === 'object') return cp.id != null ? String(cp.id) : (cp.name || '');
|
|
56
|
+
return String(cp);
|
|
57
|
+
}
|
|
58
|
+
|
|
36
59
|
/**
|
|
37
60
|
* Flatten all sprints across phases.
|
|
38
61
|
* @param {Array} phases — the phases array from the store.
|
|
@@ -75,6 +98,27 @@ export function chip(status) {
|
|
|
75
98
|
return { cls, label: status };
|
|
76
99
|
}
|
|
77
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Props for a clickable card row that navigates to a hash route.
|
|
103
|
+
* Spread onto a list row (`<li ...${rowLink('tasks')}>`) to make it act like
|
|
104
|
+
* a link: pointer + keyboard activation and an accessible role. Pair with the
|
|
105
|
+
* `ovr-link` class for the hover/focus affordance.
|
|
106
|
+
*
|
|
107
|
+
* @param {string} hash — target hash route without the leading '#'.
|
|
108
|
+
* @returns {object} Preact props (role, tabindex, onClick, onKeyDown).
|
|
109
|
+
*/
|
|
110
|
+
export function rowLink(hash) {
|
|
111
|
+
const go = () => { location.hash = hash; };
|
|
112
|
+
return {
|
|
113
|
+
role: 'link',
|
|
114
|
+
tabindex: 0,
|
|
115
|
+
onClick: go,
|
|
116
|
+
onKeyDown: (e) => {
|
|
117
|
+
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); go(); }
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
78
122
|
/**
|
|
79
123
|
* Human-readable elapsed time since an ISO timestamp.
|
|
80
124
|
* Ported from _orchElapsed() in client-main.js.
|
|
@@ -176,3 +220,37 @@ export function phaseHints(p) {
|
|
|
176
220
|
];
|
|
177
221
|
}
|
|
178
222
|
}
|
|
223
|
+
|
|
224
|
+
// ---- Markdown helpers (moved from FilesView so AgentsView can share) ----
|
|
225
|
+
|
|
226
|
+
/** Strip a leading YAML frontmatter block from a markdown string. */
|
|
227
|
+
export function stripFrontmatter(md) {
|
|
228
|
+
if (!md.startsWith('---')) return md;
|
|
229
|
+
const end = md.indexOf('\n---', 3);
|
|
230
|
+
return end === -1 ? md : md.slice(end + 4).trimStart();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Minimal HTML sanitizer for rendered markdown. No DOMPurify dependency on
|
|
235
|
+
* the client, so we strip the dangerous primitives via regex after marked
|
|
236
|
+
* emits HTML: script/iframe/object/embed tags, inline event handlers, and
|
|
237
|
+
* javascript:/data: URLs in href/src. Markdown content comes from the project
|
|
238
|
+
* dir (semi-trusted) but may include attacker-controlled text checked into a
|
|
239
|
+
* repo, so we cannot trust raw HTML passthrough.
|
|
240
|
+
*/
|
|
241
|
+
export function sanitizeHtml(html) {
|
|
242
|
+
return String(html)
|
|
243
|
+
.replace(/<\s*(script|iframe|object|embed|link|meta|style)\b[^>]*>[\s\S]*?<\s*\/\s*\1\s*>/gi, '')
|
|
244
|
+
.replace(/<\s*(script|iframe|object|embed|link|meta|style)\b[^>]*\/?>/gi, '')
|
|
245
|
+
.replace(/\son[a-z]+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, '')
|
|
246
|
+
.replace(/(href|src|xlink:href)\s*=\s*(["'])\s*(?:javascript|data|vbscript):[^"']*\2/gi, '$1=$2#blocked$2');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Render markdown to sanitized HTML via the global `marked` CDN lib. */
|
|
250
|
+
export function renderMd(md) {
|
|
251
|
+
const clean = stripFrontmatter(md);
|
|
252
|
+
if (typeof marked === 'undefined') {
|
|
253
|
+
return '<pre>' + clean.replace(/</g, '<') + '</pre>';
|
|
254
|
+
}
|
|
255
|
+
return sanitizeHtml(marked.parse(clean));
|
|
256
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var n=function(t,s,r,e){var u;s[0]=0;for(var h=1;h<s.length;h++){var p=s[h++],a=s[h]?(s[0]|=p?1:2,r[s[h++]]):s[++h];3===p?e[0]=a:4===p?e[1]=Object.assign(e[1]||{},a):5===p?(e[1]=e[1]||{})[s[++h]]=a:6===p?e[1][s[++h]]+=a+"":p?(u=t.apply(a,n(t,a,r,["",null])),e.push(u),a[0]?s[0]|=2:(s[h-2]=0,s[h]=u)):e.push(a)}return e},t=new Map;export default function(s){var r=t.get(this);return r||(r=new Map,t.set(this,r)),(r=n(this,r.get(s)||(r.set(s,r=function(n){for(var t,s,r=1,e="",u="",h=[0],p=function(n){1===r&&(n||(e=e.replace(/^\s*\n\s*|\s*\n\s*$/g,"")))?h.push(0,n,e):3===r&&(n||e)?(h.push(3,n,e),r=2):2===r&&"..."===e&&n?h.push(4,n,0):2===r&&e&&!n?h.push(5,0,!0,e):r>=5&&((e||!n&&5===r)&&(h.push(r,0,e,s),r=6),n&&(h.push(r,n,0,s),r=6)),e=""},a=0;a<n.length;a++){a&&(1===r&&p(),p(a));for(var l=0;l<n[a].length;l++)t=n[a][l],1===r?"<"===t?(p(),h=[h],r=3):e+=t:4===r?"--"===e&&">"===t?(r=1,e=""):e=t+e[0]:u?t===u?u="":e+=t:'"'===t||"'"===t?u=t:">"===t?(p(),r=1):r&&("="===t?(r=5,s=e,e=""):"/"===t&&(r<5||">"===n[a][l+1])?(p(),3===r&&(h=h[0]),r=h,(h=h[0]).push(2,0,r),r=0):" "===t||"\t"===t||"\n"===t||"\r"===t?(p(),r=2):e+=t),3===r&&"!--"===e&&(r=4,h=h[0])}return p(),h}(s)),r),arguments,[])).length>1?r:r[0]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{options as n}from"./preact.js";var t,r,u,i,o=0,f=[],c=n,e=c.__b,a=c.__r,v=c.diffed,l=c.__c,m=c.unmount,s=c.__;function d(n,t){c.__h&&c.__h(r,n,o||t),o=0;var u=r.__H||(r.__H={__:[],__h:[]});return n>=u.__.length&&u.__.push({}),u.__[n]}function h(n){return o=1,p(D,n)}function p(n,u,i){var o=d(t++,2);if(o.t=n,!o.__c&&(o.__=[i?i(u):D(void 0,u),function(n){var t=o.__N?o.__N[0]:o.__[0],r=o.t(t,n);t!==r&&(o.__N=[r,o.__[1]],o.__c.setState({}))}],o.__c=r,!r.u)){var f=function(n,t,r){if(!o.__c.__H)return!0;var u=o.__c.__H.__.filter(function(n){return!!n.__c});if(u.every(function(n){return!n.__N}))return!c||c.call(this,n,t,r);var i=!1;return u.forEach(function(n){if(n.__N){var t=n.__[0];n.__=n.__N,n.__N=void 0,t!==n.__[0]&&(i=!0)}}),!(!i&&o.__c.props===n)&&(!c||c.call(this,n,t,r))};r.u=!0;var c=r.shouldComponentUpdate,e=r.componentWillUpdate;r.componentWillUpdate=function(n,t,r){if(this.__e){var u=c;c=void 0,f(n,t,r),c=u}e&&e.call(this,n,t,r)},r.shouldComponentUpdate=f}return o.__N||o.__}function y(n,u){var i=d(t++,3);!c.__s&&C(i.__H,u)&&(i.__=n,i.i=u,r.__H.__h.push(i))}function _(n,u){var i=d(t++,4);!c.__s&&C(i.__H,u)&&(i.__=n,i.i=u,r.__h.push(i))}function A(n){return o=5,T(function(){return{current:n}},[])}function F(n,t,r){o=6,_(function(){return"function"==typeof n?(n(t()),function(){return n(null)}):n?(n.current=t(),function(){return n.current=null}):void 0},null==r?r:r.concat(n))}function T(n,r){var u=d(t++,7);return C(u.__H,r)&&(u.__=n(),u.__H=r,u.__h=n),u.__}function q(n,t){return o=8,T(function(){return n},t)}function x(n){var u=r.context[n.__c],i=d(t++,9);return i.c=n,u?(null==i.__&&(i.__=!0,u.sub(r)),u.props.value):n.__}function P(n,t){c.useDebugValue&&c.useDebugValue(t?t(n):n)}function b(n){var u=d(t++,10),i=h();return u.__=n,r.componentDidCatch||(r.componentDidCatch=function(n,t){u.__&&u.__(n,t),i[1](n)}),[i[0],function(){i[1](void 0)}]}function g(){var n=d(t++,11);if(!n.__){for(var u=r.__v;null!==u&&!u.__m&&null!==u.__;)u=u.__;var i=u.__m||(u.__m=[0,0]);n.__="P"+i[0]+"-"+i[1]++}return n.__}function j(){for(var n;n=f.shift();)if(n.__P&&n.__H)try{n.__H.__h.forEach(z),n.__H.__h.forEach(B),n.__H.__h=[]}catch(t){n.__H.__h=[],c.__e(t,n.__v)}}c.__b=function(n){r=null,e&&e(n)},c.__=function(n,t){n&&t.__k&&t.__k.__m&&(n.__m=t.__k.__m),s&&s(n,t)},c.__r=function(n){a&&a(n),t=0;var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.i=n.__N=void 0})):(i.__h.forEach(z),i.__h.forEach(B),i.__h=[],t=0)),u=r},c.diffed=function(n){v&&v(n);var t=n.__c;t&&t.__H&&(t.__H.__h.length&&(1!==f.push(t)&&i===c.requestAnimationFrame||((i=c.requestAnimationFrame)||w)(j)),t.__H.__.forEach(function(n){n.i&&(n.__H=n.i),n.i=void 0})),u=r=null},c.__c=function(n,t){t.some(function(n){try{n.__h.forEach(z),n.__h=n.__h.filter(function(n){return!n.__||B(n)})}catch(r){t.some(function(n){n.__h&&(n.__h=[])}),t=[],c.__e(r,n.__v)}}),l&&l(n,t)},c.unmount=function(n){m&&m(n);var t,r=n.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{z(n)}catch(n){t=n}}),r.__H=void 0,t&&c.__e(t,r.__v))};var k="function"==typeof requestAnimationFrame;function w(n){var t,r=function(){clearTimeout(u),k&&cancelAnimationFrame(t),setTimeout(n)},u=setTimeout(r,100);k&&(t=requestAnimationFrame(r))}function z(n){var t=r,u=n.__c;"function"==typeof u&&(n.__c=void 0,u()),r=t}function B(n){var t=r;n.__c=n.__(),r=t}function C(n,t){return!n||n.length!==t.length||t.some(function(t,r){return t!==n[r]})}function D(n,t){return"function"==typeof t?t(n):t}export{q as useCallback,x as useContext,P as useDebugValue,y as useEffect,b as useErrorBoundary,g as useId,F as useImperativeHandle,_ as useLayoutEffect,T as useMemo,p as useReducer,A as useRef,h as useState};
|
|
2
|
+
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var n,l,u,t,i,o,r,f,e,c,s,a,h={},v=[],p=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,y=Array.isArray;function d(n,l){for(var u in l)n[u]=l[u];return n}function w(n){n&&n.parentNode&&n.parentNode.removeChild(n)}function _(l,u,t){var i,o,r,f={};for(r in u)"key"==r?i=u[r]:"ref"==r?o=u[r]:f[r]=u[r];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):t),"function"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===f[r]&&(f[r]=l.defaultProps[r]);return g(l,f,i,o,null)}function g(n,t,i,o,r){var f={type:n,props:t,key:i,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,constructor:void 0,__v:null==r?++u:r,__i:-1,__u:0};return null==r&&null!=l.vnode&&l.vnode(f),f}function m(){return{current:null}}function b(n){return n.children}function k(n,l){this.props=n,this.context=l}function x(n,l){if(null==l)return n.__?x(n.__,n.__i+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return"function"==typeof n.type?x(n):null}function C(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return C(n)}}function S(n){(!n.__d&&(n.__d=!0)&&i.push(n)&&!M.__r++||o!==l.debounceRendering)&&((o=l.debounceRendering)||r)(M)}function M(){var n,u,t,o,r,e,c,s;for(i.sort(f);n=i.shift();)n.__d&&(u=i.length,o=void 0,e=(r=(t=n).__v).__e,c=[],s=[],t.__P&&((o=d({},r)).__v=r.__v+1,l.vnode&&l.vnode(o),O(t.__P,o,r,t.__n,t.__P.namespaceURI,32&r.__u?[e]:null,c,null==e?x(r):e,!!(32&r.__u),s),o.__v=r.__v,o.__.__k[o.__i]=o,j(c,o,s),o.__e!=e&&C(o)),i.length>u&&i.sort(f));M.__r=0}function P(n,l,u,t,i,o,r,f,e,c,s){var a,p,y,d,w,_=t&&t.__k||v,g=l.length;for(u.__d=e,$(u,l,_),e=u.__d,a=0;a<g;a++)null!=(y=u.__k[a])&&(p=-1===y.__i?h:_[y.__i]||h,y.__i=a,O(n,y,p,i,o,r,f,e,c,s),d=y.__e,y.ref&&p.ref!=y.ref&&(p.ref&&N(p.ref,null,y),s.push(y.ref,y.__c||d,y)),null==w&&null!=d&&(w=d),65536&y.__u||p.__k===y.__k?e=I(y,e,n):"function"==typeof y.type&&void 0!==y.__d?e=y.__d:d&&(e=d.nextSibling),y.__d=void 0,y.__u&=-196609);u.__d=e,u.__e=w}function $(n,l,u){var t,i,o,r,f,e=l.length,c=u.length,s=c,a=0;for(n.__k=[],t=0;t<e;t++)null!=(i=l[t])&&"boolean"!=typeof i&&"function"!=typeof i?(r=t+a,(i=n.__k[t]="string"==typeof i||"number"==typeof i||"bigint"==typeof i||i.constructor==String?g(null,i,null,null,null):y(i)?g(b,{children:i},null,null,null):void 0===i.constructor&&i.__b>0?g(i.type,i.props,i.key,i.ref?i.ref:null,i.__v):i).__=n,i.__b=n.__b+1,o=null,-1!==(f=i.__i=L(i,u,r,s))&&(s--,(o=u[f])&&(o.__u|=131072)),null==o||null===o.__v?(-1==f&&a--,"function"!=typeof i.type&&(i.__u|=65536)):f!==r&&(f==r-1?a--:f==r+1?a++:(f>r?a--:a++,i.__u|=65536))):i=n.__k[t]=null;if(s)for(t=0;t<c;t++)null!=(o=u[t])&&0==(131072&o.__u)&&(o.__e==n.__d&&(n.__d=x(o)),V(o,o))}function I(n,l,u){var t,i;if("function"==typeof n.type){for(t=n.__k,i=0;t&&i<t.length;i++)t[i]&&(t[i].__=n,l=I(t[i],l,u));return l}n.__e!=l&&(l&&n.type&&!u.contains(l)&&(l=x(n)),u.insertBefore(n.__e,l||null),l=n.__e);do{l=l&&l.nextSibling}while(null!=l&&8===l.nodeType);return l}function H(n,l){return l=l||[],null==n||"boolean"==typeof n||(y(n)?n.some(function(n){H(n,l)}):l.push(n)),l}function L(n,l,u,t){var i=n.key,o=n.type,r=u-1,f=u+1,e=l[u];if(null===e||e&&i==e.key&&o===e.type&&0==(131072&e.__u))return u;if(t>(null!=e&&0==(131072&e.__u)?1:0))for(;r>=0||f<l.length;){if(r>=0){if((e=l[r])&&0==(131072&e.__u)&&i==e.key&&o===e.type)return r;r--}if(f<l.length){if((e=l[f])&&0==(131072&e.__u)&&i==e.key&&o===e.type)return f;f++}}return-1}function T(n,l,u){"-"===l[0]?n.setProperty(l,null==u?"":u):n[l]=null==u?"":"number"!=typeof u||p.test(l)?u:u+"px"}function A(n,l,u,t,i){var o;n:if("style"===l)if("string"==typeof u)n.style.cssText=u;else{if("string"==typeof t&&(n.style.cssText=t=""),t)for(l in t)u&&l in u||T(n.style,l,"");if(u)for(l in u)t&&u[l]===t[l]||T(n.style,l,u[l])}else if("o"===l[0]&&"n"===l[1])o=l!==(l=l.replace(/(PointerCapture)$|Capture$/i,"$1")),l=l.toLowerCase()in n||"onFocusOut"===l||"onFocusIn"===l?l.toLowerCase().slice(2):l.slice(2),n.l||(n.l={}),n.l[l+o]=u,u?t?u.u=t.u:(u.u=e,n.addEventListener(l,o?s:c,o)):n.removeEventListener(l,o?s:c,o);else{if("http://www.w3.org/2000/svg"==i)l=l.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!=l&&"height"!=l&&"href"!=l&&"list"!=l&&"form"!=l&&"tabIndex"!=l&&"download"!=l&&"rowSpan"!=l&&"colSpan"!=l&&"role"!=l&&"popover"!=l&&l in n)try{n[l]=null==u?"":u;break n}catch(n){}"function"==typeof u||(null==u||!1===u&&"-"!==l[4]?n.removeAttribute(l):n.setAttribute(l,"popover"==l&&1==u?"":u))}}function F(n){return function(u){if(this.l){var t=this.l[u.type+n];if(null==u.t)u.t=e++;else if(u.t<t.u)return;return t(l.event?l.event(u):u)}}}function O(n,u,t,i,o,r,f,e,c,s){var a,h,v,p,w,_,g,m,x,C,S,M,$,I,H,L,T=u.type;if(void 0!==u.constructor)return null;128&t.__u&&(c=!!(32&t.__u),r=[e=u.__e=t.__e]),(a=l.__b)&&a(u);n:if("function"==typeof T)try{if(m=u.props,x="prototype"in T&&T.prototype.render,C=(a=T.contextType)&&i[a.__c],S=a?C?C.props.value:a.__:i,t.__c?g=(h=u.__c=t.__c).__=h.__E:(x?u.__c=h=new T(m,S):(u.__c=h=new k(m,S),h.constructor=T,h.render=q),C&&C.sub(h),h.props=m,h.state||(h.state={}),h.context=S,h.__n=i,v=h.__d=!0,h.__h=[],h._sb=[]),x&&null==h.__s&&(h.__s=h.state),x&&null!=T.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=d({},h.__s)),d(h.__s,T.getDerivedStateFromProps(m,h.__s))),p=h.props,w=h.state,h.__v=u,v)x&&null==T.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),x&&null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else{if(x&&null==T.getDerivedStateFromProps&&m!==p&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(m,S),!h.__e&&(null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(m,h.__s,S)||u.__v===t.__v)){for(u.__v!==t.__v&&(h.props=m,h.state=h.__s,h.__d=!1),u.__e=t.__e,u.__k=t.__k,u.__k.some(function(n){n&&(n.__=u)}),M=0;M<h._sb.length;M++)h.__h.push(h._sb[M]);h._sb=[],h.__h.length&&f.push(h);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(m,h.__s,S),x&&null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(p,w,_)})}if(h.context=S,h.props=m,h.__P=n,h.__e=!1,$=l.__r,I=0,x){for(h.state=h.__s,h.__d=!1,$&&$(u),a=h.render(h.props,h.state,h.context),H=0;H<h._sb.length;H++)h.__h.push(h._sb[H]);h._sb=[]}else do{h.__d=!1,$&&$(u),a=h.render(h.props,h.state,h.context),h.state=h.__s}while(h.__d&&++I<25);h.state=h.__s,null!=h.getChildContext&&(i=d(d({},i),h.getChildContext())),x&&!v&&null!=h.getSnapshotBeforeUpdate&&(_=h.getSnapshotBeforeUpdate(p,w)),P(n,y(L=null!=a&&a.type===b&&null==a.key?a.props.children:a)?L:[L],u,t,i,o,r,f,e,c,s),h.base=u.__e,u.__u&=-161,h.__h.length&&f.push(h),g&&(h.__E=h.__=null)}catch(n){if(u.__v=null,c||null!=r){for(u.__u|=c?160:128;e&&8===e.nodeType&&e.nextSibling;)e=e.nextSibling;r[r.indexOf(e)]=null,u.__e=e}else u.__e=t.__e,u.__k=t.__k;l.__e(n,u,t)}else null==r&&u.__v===t.__v?(u.__k=t.__k,u.__e=t.__e):u.__e=z(t.__e,u,t,i,o,r,f,c,s);(a=l.diffed)&&a(u)}function j(n,u,t){u.__d=void 0;for(var i=0;i<t.length;i++)N(t[i],t[++i],t[++i]);l.__c&&l.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u)})}catch(n){l.__e(n,u.__v)}})}function z(u,t,i,o,r,f,e,c,s){var a,v,p,d,_,g,m,b=i.props,k=t.props,C=t.type;if("svg"===C?r="http://www.w3.org/2000/svg":"math"===C?r="http://www.w3.org/1998/Math/MathML":r||(r="http://www.w3.org/1999/xhtml"),null!=f)for(a=0;a<f.length;a++)if((_=f[a])&&"setAttribute"in _==!!C&&(C?_.localName===C:3===_.nodeType)){u=_,f[a]=null;break}if(null==u){if(null===C)return document.createTextNode(k);u=document.createElementNS(r,C,k.is&&k),c&&(l.__m&&l.__m(t,f),c=!1),f=null}if(null===C)b===k||c&&u.data===k||(u.data=k);else{if(f=f&&n.call(u.childNodes),b=i.props||h,!c&&null!=f)for(b={},a=0;a<u.attributes.length;a++)b[(_=u.attributes[a]).name]=_.value;for(a in b)if(_=b[a],"children"==a);else if("dangerouslySetInnerHTML"==a)p=_;else if(!(a in k)){if("value"==a&&"defaultValue"in k||"checked"==a&&"defaultChecked"in k)continue;A(u,a,null,_,r)}for(a in k)_=k[a],"children"==a?d=_:"dangerouslySetInnerHTML"==a?v=_:"value"==a?g=_:"checked"==a?m=_:c&&"function"!=typeof _||b[a]===_||A(u,a,_,b[a],r);if(v)c||p&&(v.__html===p.__html||v.__html===u.innerHTML)||(u.innerHTML=v.__html),t.__k=[];else if(p&&(u.innerHTML=""),P(u,y(d)?d:[d],t,i,o,"foreignObject"===C?"http://www.w3.org/1999/xhtml":r,f,e,f?f[0]:i.__k&&x(i,0),c,s),null!=f)for(a=f.length;a--;)w(f[a]);c||(a="value","progress"===C&&null==g?u.removeAttribute("value"):void 0!==g&&(g!==u[a]||"progress"===C&&!g||"option"===C&&g!==b[a])&&A(u,a,g,b[a],r),a="checked",void 0!==m&&m!==u[a]&&A(u,a,m,b[a],r))}return u}function N(n,u,t){try{if("function"==typeof n){var i="function"==typeof n.__u;i&&n.__u(),i&&null==u||(n.__u=n(u))}else n.current=u}catch(n){l.__e(n,t)}}function V(n,u,t){var i,o;if(l.unmount&&l.unmount(n),(i=n.ref)&&(i.current&&i.current!==n.__e||N(i,null,u)),null!=(i=n.__c)){if(i.componentWillUnmount)try{i.componentWillUnmount()}catch(n){l.__e(n,u)}i.base=i.__P=null}if(i=n.__k)for(o=0;o<i.length;o++)i[o]&&V(i[o],u,t||"function"!=typeof n.type);t||w(n.__e),n.__c=n.__=n.__e=n.__d=void 0}function q(n,l,u){return this.constructor(n,u)}function B(u,t,i){var o,r,f,e;l.__&&l.__(u,t),r=(o="function"==typeof i)?null:i&&i.__k||t.__k,f=[],e=[],O(t,u=(!o&&i||t).__k=_(b,null,[u]),r||h,h,t.namespaceURI,!o&&i?[i]:r?null:t.firstChild?n.call(t.childNodes):null,f,!o&&i?i:r?r.__e:t.firstChild,o,e),j(f,u,e)}function D(n,l){B(n,l,D)}function E(l,u,t){var i,o,r,f,e=d({},l.props);for(r in l.type&&l.type.defaultProps&&(f=l.type.defaultProps),u)"key"==r?i=u[r]:"ref"==r?o=u[r]:e[r]=void 0===u[r]&&void 0!==f?f[r]:u[r];return arguments.length>2&&(e.children=arguments.length>3?n.call(arguments,2):t),g(l.type,e,i||l.key,o||l.ref,null)}function G(n,l){var u={__c:l="__cC"+a++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var u,t;return this.getChildContext||(u=new Set,(t={})[l]=this,this.getChildContext=function(){return t},this.componentWillUnmount=function(){u=null},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.forEach(function(n){n.__e=!0,S(n)})},this.sub=function(n){u.add(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u&&u.delete(n),l&&l.call(n)}}),n.children}};return u.Provider.__=u.Consumer.contextType=u}n=v.slice,l={__e:function(n,l,u,t){for(var i,o,r;l=l.__;)if((i=l.__c)&&!i.__)try{if((o=i.constructor)&&null!=o.getDerivedStateFromError&&(i.setState(o.getDerivedStateFromError(n)),r=i.__d),null!=i.componentDidCatch&&(i.componentDidCatch(n,t||{}),r=i.__d),r)return i.__E=i}catch(l){n=l}throw n}},u=0,t=function(n){return null!=n&&null==n.constructor},k.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=d({},this.state),"function"==typeof n&&(n=n(d({},u),this.props)),n&&d(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),S(this))},k.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),S(this))},k.prototype.render=b,i=[],r="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,f=function(n,l){return n.__v.__b-l.__v.__b},M.__r=0,e=0,c=F(!1),s=F(!0),a=0;export{k as Component,b as Fragment,E as cloneElement,G as createContext,_ as createElement,m as createRef,_ as h,D as hydrate,t as isValidElement,l as options,B as render,H as toChildArray};
|
|
2
|
+
|