@idl3/claude-control 1.0.1 → 1.1.0
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/lib/codex.js +496 -0
- package/lib/config.js +36 -3
- package/lib/sessions.js +70 -10
- package/lib/transcript.js +5 -4
- package/package.json +1 -1
- package/server.js +124 -13
- package/web/dist/assets/{core-CEtbx-dx.js → core-CpT6tRRG.js} +1 -1
- package/web/dist/assets/index-CjOcrKRX.css +1 -0
- package/web/dist/assets/index-CxhR0MPg.js +103 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-CjJtW-Kv.css +0 -1
- package/web/dist/assets/index-DFru8Gzx.js +0 -103
package/lib/sessions.js
CHANGED
|
@@ -18,11 +18,14 @@ import { parsePanePrompt } from './prompt.js';
|
|
|
18
18
|
import { assignTranscripts, parseEtime, fingerprintScore, shouldRebind } from './match.js';
|
|
19
19
|
import { pinKey } from './pins.js';
|
|
20
20
|
import { readPaneRegistry, gcPaneRegistry } from './pane-registry.js';
|
|
21
|
+
import { matchesProcess as codexMatchesProcess, buildTranscriptIndex as buildCodexIndex } from './codex.js';
|
|
21
22
|
|
|
22
23
|
const execFile = promisify(_execFile);
|
|
23
24
|
|
|
24
25
|
// Matches Claude Code's executable basename (e.g. /Users/x/.local/bin/claude).
|
|
25
26
|
const CLAUDE_COMM_RE = /(^|\/)claude$/;
|
|
27
|
+
// Matches Codex CLI executable basename.
|
|
28
|
+
const CODEX_COMM_RE = /(^|\/)codex$/;
|
|
26
29
|
|
|
27
30
|
// A pane is a Claude Code session when its process title is the Claude version
|
|
28
31
|
// (e.g. "2.1.162") — shells report zsh/bash/etc. A linked transcript also counts.
|
|
@@ -337,11 +340,12 @@ export async function listRecentTranscripts({ projectsRoot, limit = 60 }) {
|
|
|
337
340
|
|
|
338
341
|
export class SessionRegistry extends EventEmitter {
|
|
339
342
|
/**
|
|
340
|
-
* @param {{ projectsRoot: string, tmux: object, debounceMs?: number }} opts
|
|
343
|
+
* @param {{ projectsRoot: string, codexSessionsRoot?: string, tmux: object, debounceMs?: number }} opts
|
|
341
344
|
*/
|
|
342
|
-
constructor({ projectsRoot, tmux, debounceMs = 1000 } = {}) {
|
|
345
|
+
constructor({ projectsRoot, codexSessionsRoot, tmux, debounceMs = 1000 } = {}) {
|
|
343
346
|
super();
|
|
344
347
|
this._projectsRoot = projectsRoot;
|
|
348
|
+
this._codexSessionsRoot = codexSessionsRoot;
|
|
345
349
|
this._tmux = tmux;
|
|
346
350
|
this._debounceMs = debounceMs;
|
|
347
351
|
|
|
@@ -451,14 +455,21 @@ export class SessionRegistry extends EventEmitter {
|
|
|
451
455
|
return true;
|
|
452
456
|
});
|
|
453
457
|
|
|
454
|
-
// Classify every pane by its process subtree (a `claude` descendant)
|
|
455
|
-
// its
|
|
458
|
+
// Classify every pane by its process subtree (a `claude` or `codex` descendant)
|
|
459
|
+
// and get its start time in one ps snapshot. Falls back to the cmd heuristic
|
|
456
460
|
// only when ps is unavailable.
|
|
457
461
|
const paneProc = await this._buildPaneProc(panes);
|
|
458
462
|
const isClaudePane = (p) => {
|
|
459
463
|
const info = paneProc.get(p.target);
|
|
460
464
|
return info ? info.isClaude : isClaudeCmd(p.cmd);
|
|
461
465
|
};
|
|
466
|
+
const paneKind = (p) => {
|
|
467
|
+
const info = paneProc.get(p.target);
|
|
468
|
+
if (info?.kind) return info.kind;
|
|
469
|
+
if (isClaudeCmd(p.cmd)) return 'claude';
|
|
470
|
+
if (codexMatchesProcess(p.cmd)) return 'codex';
|
|
471
|
+
return 'terminal';
|
|
472
|
+
};
|
|
462
473
|
const claudePanes = panes.filter(isClaudePane);
|
|
463
474
|
|
|
464
475
|
// The exact pane→transcript map authored by the SessionStart hook. This is
|
|
@@ -564,9 +575,54 @@ export class SessionRegistry extends EventEmitter {
|
|
|
564
575
|
}
|
|
565
576
|
// ── End self-heal ─────────────────────────────────────────────────────────
|
|
566
577
|
|
|
578
|
+
// ── Codex pane → transcript matching ────────────────────────────────────
|
|
579
|
+
// Discover Codex session transcripts and match them to Codex panes.
|
|
580
|
+
// The Claude assignment above is computed first and left untouched;
|
|
581
|
+
// codex results are merged in after.
|
|
582
|
+
const codexPanes = panes.filter((p) => paneKind(p) === 'codex');
|
|
583
|
+
if (codexPanes.length > 0) {
|
|
584
|
+
const codexIndex = await buildCodexIndex({ codexSessionsRoot: this._codexSessionsRoot });
|
|
585
|
+
const codexCandidates = [];
|
|
586
|
+
for (const rec of codexIndex.byCwd.values()) {
|
|
587
|
+
codexCandidates.push({
|
|
588
|
+
transcriptPath: rec.transcriptPath,
|
|
589
|
+
cwd: rec.cwd,
|
|
590
|
+
projectDir: null, // triggers isCwdConsistent scope fallback in match.js
|
|
591
|
+
birthtimeMs: rec.mtime,
|
|
592
|
+
mtimeMs: rec.mtime,
|
|
593
|
+
lastActivityMs: rec.mtime,
|
|
594
|
+
customTitle: rec.customTitle,
|
|
595
|
+
aiTitle: rec.aiTitle,
|
|
596
|
+
recentText: null,
|
|
597
|
+
// Pass through for later session assembly
|
|
598
|
+
sessionId: rec.sessionId,
|
|
599
|
+
lastActivity: rec.lastActivity,
|
|
600
|
+
model: rec.model,
|
|
601
|
+
transcriptPending: rec.transcriptPending,
|
|
602
|
+
pendingToolUseId: rec.pendingToolUseId,
|
|
603
|
+
pendingQuestion: rec.pendingQuestion,
|
|
604
|
+
agentType: rec.agentType,
|
|
605
|
+
mtime: rec.mtime,
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
const codexPaneInputs = codexPanes.map((p) => ({
|
|
609
|
+
target: p.target,
|
|
610
|
+
windowName: p.windowName,
|
|
611
|
+
cwd: p.cwd,
|
|
612
|
+
projectDir: null,
|
|
613
|
+
procStartMs: paneProc.get(p.target)?.startMs ?? null,
|
|
614
|
+
capturedText: this._paneTextCache.get(p.target) ?? null,
|
|
615
|
+
}));
|
|
616
|
+
const codexAssignment = assignTranscripts(codexPaneInputs, codexCandidates);
|
|
617
|
+
for (const [t, rec] of codexAssignment) assignment.set(t, rec);
|
|
618
|
+
}
|
|
619
|
+
// ── End Codex matching ───────────────────────────────────────────────────
|
|
620
|
+
|
|
567
621
|
const sessions = panes.map((win) => {
|
|
568
622
|
const isClaude = isClaudePane(win);
|
|
569
|
-
const
|
|
623
|
+
const kind = paneKind(win);
|
|
624
|
+
const hasTranscript = kind === 'claude' || kind === 'codex';
|
|
625
|
+
const transcript = hasTranscript ? assignment.get(win.target) ?? null : null;
|
|
570
626
|
const isPinned = pinnedByTarget.has(win.target);
|
|
571
627
|
const id = win.target;
|
|
572
628
|
// Pending = subscribed-tailer pending (live modal) OR transcript-derived
|
|
@@ -603,7 +659,7 @@ export class SessionRegistry extends EventEmitter {
|
|
|
603
659
|
pendingQuestion: transcript?.pendingQuestion ?? panePrompt?.question ?? null,
|
|
604
660
|
cmd: win.cmd,
|
|
605
661
|
isClaude,
|
|
606
|
-
kind
|
|
662
|
+
kind,
|
|
607
663
|
ccShell: !!win.ccShell, // a composer >_ sister shell pane
|
|
608
664
|
|
|
609
665
|
model: ctx.model || prettyModel(transcript?.model) || null,
|
|
@@ -854,7 +910,7 @@ export class SessionRegistry extends EventEmitter {
|
|
|
854
910
|
}
|
|
855
911
|
|
|
856
912
|
const now = Date.now();
|
|
857
|
-
// BFS from the pane shell pid for a `claude` descendant; return its start.
|
|
913
|
+
// BFS from the pane shell pid for a `claude` or `codex` descendant; return its start.
|
|
858
914
|
const findClaude = (rootPid) => {
|
|
859
915
|
const queue = [rootPid];
|
|
860
916
|
const seen = new Set();
|
|
@@ -865,15 +921,19 @@ export class SessionRegistry extends EventEmitter {
|
|
|
865
921
|
const meta = info.get(pid);
|
|
866
922
|
if (meta && CLAUDE_COMM_RE.test(meta.comm)) {
|
|
867
923
|
const sec = parseEtime(meta.etime);
|
|
868
|
-
return { isClaude: true, startMs: sec == null ? null : now - sec * 1000 };
|
|
924
|
+
return { isClaude: true, isCodex: false, kind: 'claude', startMs: sec == null ? null : now - sec * 1000 };
|
|
925
|
+
}
|
|
926
|
+
if (meta && CODEX_COMM_RE.test(meta.comm)) {
|
|
927
|
+
const sec = parseEtime(meta.etime);
|
|
928
|
+
return { isClaude: false, isCodex: true, kind: 'codex', startMs: sec == null ? null : now - sec * 1000 };
|
|
869
929
|
}
|
|
870
930
|
for (const c of children.get(pid) ?? []) queue.push(c);
|
|
871
931
|
}
|
|
872
|
-
return { isClaude: false, startMs: null };
|
|
932
|
+
return { isClaude: false, isCodex: false, kind: null, startMs: null };
|
|
873
933
|
};
|
|
874
934
|
|
|
875
935
|
for (const p of allPanes) {
|
|
876
|
-
out.set(p.target, p.panePid ? findClaude(p.panePid) : { isClaude: false, startMs: null });
|
|
936
|
+
out.set(p.target, p.panePid ? findClaude(p.panePid) : { isClaude: false, isCodex: false, kind: null, startMs: null });
|
|
877
937
|
}
|
|
878
938
|
return out;
|
|
879
939
|
}
|
package/lib/transcript.js
CHANGED
|
@@ -194,13 +194,14 @@ export function parseRecord(line) {
|
|
|
194
194
|
export class TranscriptTailer extends EventEmitter {
|
|
195
195
|
/**
|
|
196
196
|
* @param {string} filePath
|
|
197
|
-
* @param {{ maxBuffer?: number, debounceMs?: number }} options
|
|
197
|
+
* @param {{ maxBuffer?: number, debounceMs?: number, parser?: Function }} options
|
|
198
198
|
*/
|
|
199
|
-
constructor(filePath, { maxBuffer = DEFAULT_MAX_BUFFER, debounceMs = 150 } = {}) {
|
|
199
|
+
constructor(filePath, { maxBuffer = DEFAULT_MAX_BUFFER, debounceMs = 150, parser = parseRecord } = {}) {
|
|
200
200
|
super();
|
|
201
201
|
this._filePath = filePath;
|
|
202
202
|
this._maxBuffer = maxBuffer;
|
|
203
203
|
this._debounceMs = debounceMs;
|
|
204
|
+
this._parse = parser;
|
|
204
205
|
|
|
205
206
|
/** @type {import('./transcript.js').NormalizedMessage[]} */
|
|
206
207
|
this._messages = [];
|
|
@@ -340,7 +341,7 @@ export class TranscriptTailer extends EventEmitter {
|
|
|
340
341
|
|
|
341
342
|
const parsed = [];
|
|
342
343
|
for (const line of lines) {
|
|
343
|
-
const msg =
|
|
344
|
+
const msg = this._parse(line);
|
|
344
345
|
if (msg) {
|
|
345
346
|
parsed.push(msg);
|
|
346
347
|
this._trackPending(msg);
|
|
@@ -413,7 +414,7 @@ export class TranscriptTailer extends EventEmitter {
|
|
|
413
414
|
|
|
414
415
|
const newMsgs = [];
|
|
415
416
|
for (const line of complete) {
|
|
416
|
-
const msg =
|
|
417
|
+
const msg = this._parse(line);
|
|
417
418
|
if (msg) {
|
|
418
419
|
newMsgs.push(msg);
|
|
419
420
|
this._trackPending(msg);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idl3/claude-control",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Local web UI to watch and drive your Claude Code sessions running in tmux — live transcripts, reply, answer AskUserQuestion, attach files, from a browser or phone.",
|
|
6
6
|
"keywords": [
|
package/server.js
CHANGED
|
@@ -10,7 +10,11 @@ import fs from 'node:fs';
|
|
|
10
10
|
import path from 'node:path';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
12
|
import os from 'node:os';
|
|
13
|
-
import { spawn } from 'node:child_process';
|
|
13
|
+
import { spawn, execFile as _execFileRaw } from 'node:child_process';
|
|
14
|
+
import { promisify } from 'node:util';
|
|
15
|
+
import fsp from 'node:fs/promises';
|
|
16
|
+
|
|
17
|
+
const _execFile = promisify(_execFileRaw);
|
|
14
18
|
import { WebSocketServer } from 'ws';
|
|
15
19
|
|
|
16
20
|
import * as tmux from './lib/tmux.js';
|
|
@@ -27,6 +31,7 @@ import { sweepUploads, resolveUploadPath } from './lib/uploads.js';
|
|
|
27
31
|
import { getVersionInfo, currentVersion } from './lib/version.js';
|
|
28
32
|
import * as push from './lib/push.js';
|
|
29
33
|
import { readConfig, writeConfig } from './lib/config.js';
|
|
34
|
+
import { parseCodexRecord, parseCodexPrompt, buildSpawnCommand } from './lib/codex.js';
|
|
30
35
|
import { optimizePrompt, rulesOptimize } from './lib/optimize.js';
|
|
31
36
|
import * as mlx from './lib/mlx.js';
|
|
32
37
|
import {
|
|
@@ -76,6 +81,8 @@ const CONFIG = {
|
|
|
76
81
|
host: env('HOST') || '127.0.0.1',
|
|
77
82
|
projectsRoot:
|
|
78
83
|
env('PROJECTS') || path.join(os.homedir(), '.claude', 'projects'),
|
|
84
|
+
codexSessionsRoot:
|
|
85
|
+
env('CODEX_SESSIONS') || path.join(os.homedir(), '.codex', 'sessions'),
|
|
79
86
|
// 768MB: a long-running Node server (WS + transcript tailing + the bundled
|
|
80
87
|
// web app) baselines ~300-450MB of V8 heap + RSS, so the old 350MB budget
|
|
81
88
|
// tripped "over limit" permanently. Override with CLAUDE_CONTROL_RSS_LIMIT_MB.
|
|
@@ -123,7 +130,7 @@ const IMAGE_MIME = {
|
|
|
123
130
|
};
|
|
124
131
|
|
|
125
132
|
// --- shared state -----------------------------------------------------------
|
|
126
|
-
const registry = new SessionRegistry({ projectsRoot: CONFIG.projectsRoot, tmux });
|
|
133
|
+
const registry = new SessionRegistry({ projectsRoot: CONFIG.projectsRoot, codexSessionsRoot: CONFIG.codexSessionsRoot, tmux });
|
|
127
134
|
const resources = new ResourceMonitor({ rssLimitMB: CONFIG.rssLimitMB });
|
|
128
135
|
|
|
129
136
|
// Manual transcript pins (windowId.paneIndex -> transcript path). Loaded at boot,
|
|
@@ -347,6 +354,33 @@ const _handler = (req, res) => {
|
|
|
347
354
|
if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
|
|
348
355
|
return handleTranscribe(req, res, u);
|
|
349
356
|
}
|
|
357
|
+
// GET /api/spawn-agents — agent-type availability (claude vs codex).
|
|
358
|
+
// Returns which agent binaries are resolvable on this machine so the UI can
|
|
359
|
+
// disable an unavailable agent picker option and show a reason.
|
|
360
|
+
// Token-gated + localhost, same as other GET endpoints.
|
|
361
|
+
if (u.pathname === '/api/spawn-agents') {
|
|
362
|
+
if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
|
|
363
|
+
const cfg = readConfig();
|
|
364
|
+
return Promise.all([
|
|
365
|
+
resolveBin(cfg.claudeBin || cfg.launchCommand),
|
|
366
|
+
resolveBin(cfg.codexBin || cfg.codexLaunchCommand),
|
|
367
|
+
]).then(([claudeResult, codexResult]) => {
|
|
368
|
+
return endJson(res, 200, {
|
|
369
|
+
agents: [
|
|
370
|
+
{
|
|
371
|
+
id: 'claude',
|
|
372
|
+
available: claudeResult.available,
|
|
373
|
+
...(claudeResult.available ? {} : { reason: claudeResult.reason }),
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
id: 'codex',
|
|
377
|
+
available: codexResult.available,
|
|
378
|
+
...(codexResult.available ? {} : { reason: codexResult.reason }),
|
|
379
|
+
},
|
|
380
|
+
],
|
|
381
|
+
});
|
|
382
|
+
}).catch((err) => endJson(res, 500, { error: String(err?.message || err) }));
|
|
383
|
+
}
|
|
350
384
|
if (u.pathname === '/api/session/new') {
|
|
351
385
|
if (req.method !== 'POST') return endJson(res, 405, { error: 'method not allowed' });
|
|
352
386
|
if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
|
|
@@ -672,6 +706,40 @@ function handleTranscribe(req, res, u) {
|
|
|
672
706
|
});
|
|
673
707
|
}
|
|
674
708
|
|
|
709
|
+
// ---------------------------------------------------------------------------
|
|
710
|
+
// resolveBin — async PATH lookup for a binary name or absolute path.
|
|
711
|
+
//
|
|
712
|
+
// If `bin` is an absolute path, checks it is executable directly.
|
|
713
|
+
// Otherwise runs `which <bin>` on PATH.
|
|
714
|
+
//
|
|
715
|
+
// Returns { available: true, path } on success, { available: false, reason }
|
|
716
|
+
// on failure. Never throws.
|
|
717
|
+
// ---------------------------------------------------------------------------
|
|
718
|
+
async function resolveBin(bin) {
|
|
719
|
+
if (!bin || typeof bin !== 'string' || !bin.trim()) {
|
|
720
|
+
return { available: false, reason: 'no binary configured' };
|
|
721
|
+
}
|
|
722
|
+
const b = bin.trim();
|
|
723
|
+
// Absolute path: check existence + execute permission directly.
|
|
724
|
+
if (b.startsWith('/')) {
|
|
725
|
+
try {
|
|
726
|
+
await fsp.access(b, fsp.constants?.X_OK ?? 1);
|
|
727
|
+
return { available: true, path: b };
|
|
728
|
+
} catch {
|
|
729
|
+
return { available: false, reason: `binary not found or not executable: ${b}` };
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
// Relative / bare name: resolve via `which`.
|
|
733
|
+
try {
|
|
734
|
+
const { stdout } = await _execFile('which', [b], { timeout: 5000 });
|
|
735
|
+
const resolved = stdout.trim();
|
|
736
|
+
if (resolved) return { available: true, path: resolved };
|
|
737
|
+
return { available: false, reason: `${b} not found on PATH` };
|
|
738
|
+
} catch {
|
|
739
|
+
return { available: false, reason: `${b} not found on PATH` };
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
675
743
|
// POST /api/session/new — create a new tmux window in the configured (or
|
|
676
744
|
// body-overridden) cwd, then type the launch command into it via send-keys so
|
|
677
745
|
// the interactive shell resolves aliases. Security: the command is operator
|
|
@@ -687,23 +755,66 @@ async function handleSessionNew(req, res) {
|
|
|
687
755
|
const config = readConfig();
|
|
688
756
|
const cwd =
|
|
689
757
|
typeof body.cwd === 'string' && body.cwd.trim() ? body.cwd : config.defaultCwd;
|
|
758
|
+
|
|
759
|
+
// agent ∈ {'claude','codex'}, default 'claude'.
|
|
760
|
+
const agent = body.agent === 'codex' ? 'codex' : 'claude';
|
|
761
|
+
|
|
690
762
|
// Name is required-with-default: sanitize the requested name, falling back to
|
|
691
763
|
// `session-<short-ts>` so a session is ALWAYS named (the rail reads the tmux
|
|
692
764
|
// window name until a transcript title exists).
|
|
693
765
|
const name = tmux.sanitizeName(body.name) || tmux.defaultSessionName();
|
|
766
|
+
|
|
767
|
+
// --- Pre-validation: binary resolution + cwd check BEFORE creating any window ---
|
|
768
|
+
|
|
769
|
+
// (i) Resolve the agent binary and return 400 if unavailable.
|
|
770
|
+
const agentBin = agent === 'codex'
|
|
771
|
+
? (config.codexBin || config.codexLaunchCommand)
|
|
772
|
+
: (config.claudeBin || config.launchCommand);
|
|
773
|
+
const binCheck = await resolveBin(agentBin);
|
|
774
|
+
if (!binCheck.available) {
|
|
775
|
+
return endJson(res, 400, { error: `agent binary unavailable: ${binCheck.reason}` });
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// (ii) For codex: pre-validate cwd exists and is a directory BEFORE createWindow,
|
|
779
|
+
// so a bad request creates NO window (400 not 500, window-leak prevention).
|
|
780
|
+
if (agent === 'codex') {
|
|
781
|
+
try {
|
|
782
|
+
const st = await fsp.stat(cwd);
|
|
783
|
+
if (!st.isDirectory()) {
|
|
784
|
+
return endJson(res, 400, { error: `cwd is not a directory: ${cwd}` });
|
|
785
|
+
}
|
|
786
|
+
} catch {
|
|
787
|
+
return endJson(res, 400, { error: `cwd does not exist: ${cwd}` });
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
694
791
|
try {
|
|
695
792
|
// (1) Reliable named path: the tmux window name. createWindow sets it via
|
|
696
|
-
// `new-window -n
|
|
793
|
+
// `new-window -n` and the `-c cwd` flag — cwd flows through tmux's own
|
|
794
|
+
// working-directory flag, never a shell `cd`.
|
|
697
795
|
const target = await tmux.createWindow({ cwd, name });
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
796
|
+
|
|
797
|
+
let launch;
|
|
798
|
+
if (agent === 'codex') {
|
|
799
|
+
// Codex path: uses -C <cwd> (its own cwd flag). No --name flag — Codex
|
|
800
|
+
// has none. The tmux window is still named (above) so the rail shows it.
|
|
801
|
+
// cwd is shell-quoted (same quoting as names) since the command is typed
|
|
802
|
+
// into an interactive shell via sendText.
|
|
803
|
+
void buildSpawnCommand({ cwd, bin: config.codexLaunchCommand }); // validate shape
|
|
804
|
+
launch = `${config.codexLaunchCommand} -C ${tmux.shellQuoteName(cwd)}`;
|
|
805
|
+
} else {
|
|
806
|
+
// Claude path: BYTE-IDENTICAL to the pre-Phase-D implementation.
|
|
807
|
+
// (2) Claude's own session title: `claude --help` exposes `-n/--name`
|
|
808
|
+
// (display name in the prompt box, /resume picker, terminal title), so
|
|
809
|
+
// we append it to the launch command rather than relying on a delayed
|
|
810
|
+
// `/rename`. The name is shell-quoted (sanitizeName already stripped
|
|
811
|
+
// control chars/newlines) since the command is typed into an interactive
|
|
812
|
+
// shell so aliases like `yolo` resolve. sendText appends Enter → runs it.
|
|
813
|
+
launch = `${config.launchCommand} --name ${tmux.shellQuoteName(name)}`;
|
|
814
|
+
}
|
|
815
|
+
|
|
705
816
|
await tmux.sendText(target, launch);
|
|
706
|
-
return endJson(res, 200, { ok: true, target, name });
|
|
817
|
+
return endJson(res, 200, { ok: true, target, name, agent });
|
|
707
818
|
} catch (err) {
|
|
708
819
|
return endJson(res, 500, { error: String(err?.message || err) });
|
|
709
820
|
}
|
|
@@ -1135,7 +1246,7 @@ function ensureSubscription(id) {
|
|
|
1135
1246
|
return sub;
|
|
1136
1247
|
}
|
|
1137
1248
|
|
|
1138
|
-
const tailer = new TranscriptTailer(session.transcriptPath, { maxBuffer: CONFIG.maxBuffer });
|
|
1249
|
+
const tailer = new TranscriptTailer(session.transcriptPath, { maxBuffer: CONFIG.maxBuffer, parser: session.kind === 'codex' ? parseCodexRecord : undefined });
|
|
1139
1250
|
// Watch this session's sub-agent transcripts (Task/Agent). Discovery is polled
|
|
1140
1251
|
// when the parent transcript grows (when sub-agents spawn) + once at subscribe.
|
|
1141
1252
|
const subagents = new SubAgentsWatcher(session.transcriptPath);
|
|
@@ -1201,7 +1312,7 @@ function startPromptPoller(id, sub) {
|
|
|
1201
1312
|
let prompt = null;
|
|
1202
1313
|
try {
|
|
1203
1314
|
const cap = await tmux.capturePane(session.target, 40);
|
|
1204
|
-
prompt = parsePanePrompt(cap);
|
|
1315
|
+
prompt = session.kind === 'codex' ? parseCodexPrompt(cap) : parsePanePrompt(cap);
|
|
1205
1316
|
} catch {
|
|
1206
1317
|
return;
|
|
1207
1318
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{g as Ve}from"./index-DFru8Gzx.js";function xe(e){return e instanceof Map?e.clear=e.delete=e.set=function(){throw new Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=function(){throw new Error("set is read-only")}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach(t=>{const i=e[t],u=typeof i;(u==="object"||u==="function")&&!Object.isFrozen(i)&&xe(i)}),e}class he{constructor(t){t.data===void 0&&(t.data={}),this.data=t.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}}function we(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function B(e,...t){const i=Object.create(null);for(const u in e)i[u]=e[u];return t.forEach(function(u){for(const b in u)i[b]=u[b]}),i}const qe="</span>",pe=e=>!!e.scope,Qe=(e,{prefix:t})=>{if(e.startsWith("language:"))return e.replace("language:","language-");if(e.includes(".")){const i=e.split(".");return[`${t}${i.shift()}`,...i.map((u,b)=>`${u}${"_".repeat(b+1)}`)].join(" ")}return`${t}${e}`};class me{constructor(t,i){this.buffer="",this.classPrefix=i.classPrefix,t.walk(this)}addText(t){this.buffer+=we(t)}openNode(t){if(!pe(t))return;const i=Qe(t.scope,{prefix:this.classPrefix});this.span(i)}closeNode(t){pe(t)&&(this.buffer+=qe)}value(){return this.buffer}span(t){this.buffer+=`<span class="${t}">`}}const de=(e={})=>{const t={children:[]};return Object.assign(t,e),t};class te{constructor(){this.rootNode=de(),this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(t){this.top.children.push(t)}openNode(t){const i=de({scope:t});this.add(i),this.stack.push(i)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(t){return this.constructor._walk(t,this.rootNode)}static _walk(t,i){return typeof i=="string"?t.addText(i):i.children&&(t.openNode(i),i.children.forEach(u=>this._walk(t,u)),t.closeNode(i)),t}static _collapse(t){typeof t!="string"&&t.children&&(t.children.every(i=>typeof i=="string")?t.children=[t.children.join("")]:t.children.forEach(i=>{te._collapse(i)}))}}class et extends te{constructor(t){super(),this.options=t}addText(t){t!==""&&this.add(t)}startScope(t){this.openNode(t)}endScope(){this.closeNode()}__addSublanguage(t,i){const u=t.root;i&&(u.scope=`language:${i}`),this.add(u)}toHTML(){return new me(this,this.options).value()}finalize(){return this.closeAllNodes(),!0}}function P(e){return e?typeof e=="string"?e:e.source:null}function Oe(e){return C("(?=",e,")")}function tt(e){return C("(?:",e,")*")}function nt(e){return C("(?:",e,")?")}function C(...e){return e.map(i=>P(i)).join("")}function it(e){const t=e[e.length-1];return typeof t=="object"&&t.constructor===Object?(e.splice(e.length-1,1),t):{}}function ne(...e){return"("+(it(e).capture?"":"?:")+e.map(u=>P(u)).join("|")+")"}function Re(e){return new RegExp(e.toString()+"|").exec("").length-1}function st(e,t){const i=e&&e.exec(t);return i&&i.index===0}const rt=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function ie(e,{joinWith:t}){let i=0;return e.map(u=>{i+=1;const b=i;let _=P(u),c="";for(;_.length>0;){const r=rt.exec(_);if(!r){c+=_;break}c+=_.substring(0,r.index),_=_.substring(r.index+r[0].length),r[0][0]==="\\"&&r[1]?c+="\\"+String(Number(r[1])+b):(c+=r[0],r[0]==="("&&i++)}return c}).map(u=>`(${u})`).join(t)}const ct=/\b\B/,ye="[a-zA-Z]\\w*",se="[a-zA-Z_]\\w*",Se="\\b\\d+(\\.\\d+)?",Ne="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",Ae="\\b(0b[01]+)",ot="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",at=(e={})=>{const t=/^#![ ]*\//;return e.binary&&(e.begin=C(t,/.*\b/,e.binary,/\b.*/)),B({scope:"meta",begin:t,end:/$/,relevance:0,"on:begin":(i,u)=>{i.index!==0&&u.ignoreMatch()}},e)},U={begin:"\\\\[\\s\\S]",relevance:0},lt={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[U]},ut={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[U]},ft={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},Y=function(e,t,i={}){const u=B({scope:"comment",begin:e,end:t,contains:[]},i);u.contains.push({scope:"doctag",begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0});const b=ne("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/);return u.contains.push({begin:C(/[ ]+/,"(",b,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),u},gt=Y("//","$"),ht=Y("/\\*","\\*/"),pt=Y("#","$"),dt={scope:"number",begin:Se,relevance:0},Et={scope:"number",begin:Ne,relevance:0},bt={scope:"number",begin:Ae,relevance:0},_t={scope:"regexp",begin:/\/(?=[^/\n]*\/)/,end:/\/[gimuy]*/,contains:[U,{begin:/\[/,end:/\]/,relevance:0,contains:[U]}]},Mt={scope:"title",begin:ye,relevance:0},xt={scope:"title",begin:se,relevance:0},wt={begin:"\\.\\s*"+se,relevance:0},Ot=function(e){return Object.assign(e,{"on:begin":(t,i)=>{i.data._beginMatch=t[1]},"on:end":(t,i)=>{i.data._beginMatch!==t[1]&&i.ignoreMatch()}})};var z=Object.freeze({__proto__:null,APOS_STRING_MODE:lt,BACKSLASH_ESCAPE:U,BINARY_NUMBER_MODE:bt,BINARY_NUMBER_RE:Ae,COMMENT:Y,C_BLOCK_COMMENT_MODE:ht,C_LINE_COMMENT_MODE:gt,C_NUMBER_MODE:Et,C_NUMBER_RE:Ne,END_SAME_AS_BEGIN:Ot,HASH_COMMENT_MODE:pt,IDENT_RE:ye,MATCH_NOTHING_RE:ct,METHOD_GUARD:wt,NUMBER_MODE:dt,NUMBER_RE:Se,PHRASAL_WORDS_MODE:ft,QUOTE_STRING_MODE:ut,REGEXP_MODE:_t,RE_STARTERS_RE:ot,SHEBANG:at,TITLE_MODE:Mt,UNDERSCORE_IDENT_RE:se,UNDERSCORE_TITLE_MODE:xt});function Rt(e,t){e.input[e.index-1]==="."&&t.ignoreMatch()}function yt(e,t){e.className!==void 0&&(e.scope=e.className,delete e.className)}function St(e,t){t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=Rt,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,e.relevance===void 0&&(e.relevance=0))}function Nt(e,t){Array.isArray(e.illegal)&&(e.illegal=ne(...e.illegal))}function At(e,t){if(e.match){if(e.begin||e.end)throw new Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function kt(e,t){e.relevance===void 0&&(e.relevance=1)}const Tt=(e,t)=>{if(!e.beforeMatch)return;if(e.starts)throw new Error("beforeMatch cannot be used with starts");const i=Object.assign({},e);Object.keys(e).forEach(u=>{delete e[u]}),e.keywords=i.keywords,e.begin=C(i.beforeMatch,Oe(i.begin)),e.starts={relevance:0,contains:[Object.assign(i,{endsParent:!0})]},e.relevance=0,delete i.beforeMatch},It=["of","and","for","in","not","or","if","then","parent","list","value"],Bt="keyword";function ke(e,t,i=Bt){const u=Object.create(null);return typeof e=="string"?b(i,e.split(" ")):Array.isArray(e)?b(i,e):Object.keys(e).forEach(function(_){Object.assign(u,ke(e[_],t,_))}),u;function b(_,c){t&&(c=c.map(r=>r.toLowerCase())),c.forEach(function(r){const l=r.split("|");u[l[0]]=[_,Dt(l[0],l[1])]})}}function Dt(e,t){return t?Number(t):vt(e)?0:1}function vt(e){return It.includes(e.toLowerCase())}const Ee={},v=e=>{console.error(e)},be=(e,...t)=>{console.log(`WARN: ${e}`,...t)},L=(e,t)=>{Ee[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),Ee[`${e}/${t}`]=!0)},X=new Error;function Te(e,t,{key:i}){let u=0;const b=e[i],_={},c={};for(let r=1;r<=t.length;r++)c[r+u]=b[r],_[r+u]=!0,u+=Re(t[r-1]);e[i]=c,e[i]._emit=_,e[i]._multi=!0}function Ct(e){if(Array.isArray(e.begin)){if(e.skip||e.excludeBegin||e.returnBegin)throw v("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),X;if(typeof e.beginScope!="object"||e.beginScope===null)throw v("beginScope must be object"),X;Te(e,e.begin,{key:"beginScope"}),e.begin=ie(e.begin,{joinWith:""})}}function Lt(e){if(Array.isArray(e.end)){if(e.skip||e.excludeEnd||e.returnEnd)throw v("skip, excludeEnd, returnEnd not compatible with endScope: {}"),X;if(typeof e.endScope!="object"||e.endScope===null)throw v("endScope must be object"),X;Te(e,e.end,{key:"endScope"}),e.end=ie(e.end,{joinWith:""})}}function Ht(e){e.scope&&typeof e.scope=="object"&&e.scope!==null&&(e.beginScope=e.scope,delete e.scope)}function jt(e){Ht(e),typeof e.beginScope=="string"&&(e.beginScope={_wrap:e.beginScope}),typeof e.endScope=="string"&&(e.endScope={_wrap:e.endScope}),Ct(e),Lt(e)}function Pt(e){function t(c,r){return new RegExp(P(c),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(r?"g":""))}class i{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(r,l){l.position=this.position++,this.matchIndexes[this.matchAt]=l,this.regexes.push([l,r]),this.matchAt+=Re(r)+1}compile(){this.regexes.length===0&&(this.exec=()=>null);const r=this.regexes.map(l=>l[1]);this.matcherRe=t(ie(r,{joinWith:"|"}),!0),this.lastIndex=0}exec(r){this.matcherRe.lastIndex=this.lastIndex;const l=this.matcherRe.exec(r);if(!l)return null;const w=l.findIndex((j,Z)=>Z>0&&j!==void 0),M=this.matchIndexes[w];return l.splice(0,w),Object.assign(l,M)}}class u{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(r){if(this.multiRegexes[r])return this.multiRegexes[r];const l=new i;return this.rules.slice(r).forEach(([w,M])=>l.addRule(w,M)),l.compile(),this.multiRegexes[r]=l,l}resumingScanAtSamePosition(){return this.regexIndex!==0}considerAll(){this.regexIndex=0}addRule(r,l){this.rules.push([r,l]),l.type==="begin"&&this.count++}exec(r){const l=this.getMatcher(this.regexIndex);l.lastIndex=this.lastIndex;let w=l.exec(r);if(this.resumingScanAtSamePosition()&&!(w&&w.index===this.lastIndex)){const M=this.getMatcher(0);M.lastIndex=this.lastIndex+1,w=M.exec(r)}return w&&(this.regexIndex+=w.position+1,this.regexIndex===this.count&&this.considerAll()),w}}function b(c){const r=new u;return c.contains.forEach(l=>r.addRule(l.begin,{rule:l,type:"begin"})),c.terminatorEnd&&r.addRule(c.terminatorEnd,{type:"end"}),c.illegal&&r.addRule(c.illegal,{type:"illegal"}),r}function _(c,r){const l=c;if(c.isCompiled)return l;[yt,At,jt,Tt].forEach(M=>M(c,r)),e.compilerExtensions.forEach(M=>M(c,r)),c.__beforeBegin=null,[St,Nt,kt].forEach(M=>M(c,r)),c.isCompiled=!0;let w=null;return typeof c.keywords=="object"&&c.keywords.$pattern&&(c.keywords=Object.assign({},c.keywords),w=c.keywords.$pattern,delete c.keywords.$pattern),w=w||/\w+/,c.keywords&&(c.keywords=ke(c.keywords,e.case_insensitive)),l.keywordPatternRe=t(w,!0),r&&(c.begin||(c.begin=/\B|\b/),l.beginRe=t(l.begin),!c.end&&!c.endsWithParent&&(c.end=/\B|\b/),c.end&&(l.endRe=t(l.end)),l.terminatorEnd=P(l.end)||"",c.endsWithParent&&r.terminatorEnd&&(l.terminatorEnd+=(c.end?"|":"")+r.terminatorEnd)),c.illegal&&(l.illegalRe=t(c.illegal)),c.contains||(c.contains=[]),c.contains=[].concat(...c.contains.map(function(M){return Ut(M==="self"?c:M)})),c.contains.forEach(function(M){_(M,l)}),c.starts&&_(c.starts,r),l.matcher=b(l),l}if(e.compilerExtensions||(e.compilerExtensions=[]),e.contains&&e.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return e.classNameAliases=B(e.classNameAliases||{}),_(e)}function Ie(e){return e?e.endsWithParent||Ie(e.starts):!1}function Ut(e){return e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map(function(t){return B(e,{variants:null},t)})),e.cachedVariants?e.cachedVariants:Ie(e)?B(e,{starts:e.starts?B(e.starts):null}):Object.isFrozen(e)?B(e):e}var $t="11.11.1";class Gt extends Error{constructor(t,i){super(t),this.name="HTMLInjectionError",this.html=i}}const ee=we,_e=B,Me=Symbol("nomatch"),Wt=7,Be=function(e){const t=Object.create(null),i=Object.create(null),u=[];let b=!0;const _="Could not find the language '{}', did you forget to load/include a language module?",c={disableAutodetect:!0,name:"Plain text",contains:[]};let r={ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",cssSelector:"pre code",languages:null,__emitter:et};function l(n){return r.noHighlightRe.test(n)}function w(n){let a=n.className+" ";a+=n.parentNode?n.parentNode.className:"";const h=r.languageDetectRe.exec(a);if(h){const d=T(h[1]);return d||(be(_.replace("{}",h[1])),be("Falling back to no-highlight mode for this block.",n)),d?h[1]:"no-highlight"}return a.split(/\s+/).find(d=>l(d)||T(d))}function M(n,a,h){let d="",x="";typeof a=="object"?(d=n,h=a.ignoreIllegals,x=a.language):(L("10.7.0","highlight(lang, code, ...args) has been deprecated."),L("10.7.0",`Please use highlight(code, options) instead.
|
|
1
|
+
import{g as Ve}from"./index-CxhR0MPg.js";function xe(e){return e instanceof Map?e.clear=e.delete=e.set=function(){throw new Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=function(){throw new Error("set is read-only")}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach(t=>{const i=e[t],u=typeof i;(u==="object"||u==="function")&&!Object.isFrozen(i)&&xe(i)}),e}class he{constructor(t){t.data===void 0&&(t.data={}),this.data=t.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}}function we(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function B(e,...t){const i=Object.create(null);for(const u in e)i[u]=e[u];return t.forEach(function(u){for(const b in u)i[b]=u[b]}),i}const qe="</span>",pe=e=>!!e.scope,Qe=(e,{prefix:t})=>{if(e.startsWith("language:"))return e.replace("language:","language-");if(e.includes(".")){const i=e.split(".");return[`${t}${i.shift()}`,...i.map((u,b)=>`${u}${"_".repeat(b+1)}`)].join(" ")}return`${t}${e}`};class me{constructor(t,i){this.buffer="",this.classPrefix=i.classPrefix,t.walk(this)}addText(t){this.buffer+=we(t)}openNode(t){if(!pe(t))return;const i=Qe(t.scope,{prefix:this.classPrefix});this.span(i)}closeNode(t){pe(t)&&(this.buffer+=qe)}value(){return this.buffer}span(t){this.buffer+=`<span class="${t}">`}}const de=(e={})=>{const t={children:[]};return Object.assign(t,e),t};class te{constructor(){this.rootNode=de(),this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(t){this.top.children.push(t)}openNode(t){const i=de({scope:t});this.add(i),this.stack.push(i)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(t){return this.constructor._walk(t,this.rootNode)}static _walk(t,i){return typeof i=="string"?t.addText(i):i.children&&(t.openNode(i),i.children.forEach(u=>this._walk(t,u)),t.closeNode(i)),t}static _collapse(t){typeof t!="string"&&t.children&&(t.children.every(i=>typeof i=="string")?t.children=[t.children.join("")]:t.children.forEach(i=>{te._collapse(i)}))}}class et extends te{constructor(t){super(),this.options=t}addText(t){t!==""&&this.add(t)}startScope(t){this.openNode(t)}endScope(){this.closeNode()}__addSublanguage(t,i){const u=t.root;i&&(u.scope=`language:${i}`),this.add(u)}toHTML(){return new me(this,this.options).value()}finalize(){return this.closeAllNodes(),!0}}function P(e){return e?typeof e=="string"?e:e.source:null}function Oe(e){return C("(?=",e,")")}function tt(e){return C("(?:",e,")*")}function nt(e){return C("(?:",e,")?")}function C(...e){return e.map(i=>P(i)).join("")}function it(e){const t=e[e.length-1];return typeof t=="object"&&t.constructor===Object?(e.splice(e.length-1,1),t):{}}function ne(...e){return"("+(it(e).capture?"":"?:")+e.map(u=>P(u)).join("|")+")"}function Re(e){return new RegExp(e.toString()+"|").exec("").length-1}function st(e,t){const i=e&&e.exec(t);return i&&i.index===0}const rt=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function ie(e,{joinWith:t}){let i=0;return e.map(u=>{i+=1;const b=i;let _=P(u),c="";for(;_.length>0;){const r=rt.exec(_);if(!r){c+=_;break}c+=_.substring(0,r.index),_=_.substring(r.index+r[0].length),r[0][0]==="\\"&&r[1]?c+="\\"+String(Number(r[1])+b):(c+=r[0],r[0]==="("&&i++)}return c}).map(u=>`(${u})`).join(t)}const ct=/\b\B/,ye="[a-zA-Z]\\w*",se="[a-zA-Z_]\\w*",Se="\\b\\d+(\\.\\d+)?",Ne="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",Ae="\\b(0b[01]+)",ot="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",at=(e={})=>{const t=/^#![ ]*\//;return e.binary&&(e.begin=C(t,/.*\b/,e.binary,/\b.*/)),B({scope:"meta",begin:t,end:/$/,relevance:0,"on:begin":(i,u)=>{i.index!==0&&u.ignoreMatch()}},e)},U={begin:"\\\\[\\s\\S]",relevance:0},lt={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[U]},ut={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[U]},ft={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},Y=function(e,t,i={}){const u=B({scope:"comment",begin:e,end:t,contains:[]},i);u.contains.push({scope:"doctag",begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0});const b=ne("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/);return u.contains.push({begin:C(/[ ]+/,"(",b,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),u},gt=Y("//","$"),ht=Y("/\\*","\\*/"),pt=Y("#","$"),dt={scope:"number",begin:Se,relevance:0},Et={scope:"number",begin:Ne,relevance:0},bt={scope:"number",begin:Ae,relevance:0},_t={scope:"regexp",begin:/\/(?=[^/\n]*\/)/,end:/\/[gimuy]*/,contains:[U,{begin:/\[/,end:/\]/,relevance:0,contains:[U]}]},Mt={scope:"title",begin:ye,relevance:0},xt={scope:"title",begin:se,relevance:0},wt={begin:"\\.\\s*"+se,relevance:0},Ot=function(e){return Object.assign(e,{"on:begin":(t,i)=>{i.data._beginMatch=t[1]},"on:end":(t,i)=>{i.data._beginMatch!==t[1]&&i.ignoreMatch()}})};var z=Object.freeze({__proto__:null,APOS_STRING_MODE:lt,BACKSLASH_ESCAPE:U,BINARY_NUMBER_MODE:bt,BINARY_NUMBER_RE:Ae,COMMENT:Y,C_BLOCK_COMMENT_MODE:ht,C_LINE_COMMENT_MODE:gt,C_NUMBER_MODE:Et,C_NUMBER_RE:Ne,END_SAME_AS_BEGIN:Ot,HASH_COMMENT_MODE:pt,IDENT_RE:ye,MATCH_NOTHING_RE:ct,METHOD_GUARD:wt,NUMBER_MODE:dt,NUMBER_RE:Se,PHRASAL_WORDS_MODE:ft,QUOTE_STRING_MODE:ut,REGEXP_MODE:_t,RE_STARTERS_RE:ot,SHEBANG:at,TITLE_MODE:Mt,UNDERSCORE_IDENT_RE:se,UNDERSCORE_TITLE_MODE:xt});function Rt(e,t){e.input[e.index-1]==="."&&t.ignoreMatch()}function yt(e,t){e.className!==void 0&&(e.scope=e.className,delete e.className)}function St(e,t){t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=Rt,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,e.relevance===void 0&&(e.relevance=0))}function Nt(e,t){Array.isArray(e.illegal)&&(e.illegal=ne(...e.illegal))}function At(e,t){if(e.match){if(e.begin||e.end)throw new Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function kt(e,t){e.relevance===void 0&&(e.relevance=1)}const Tt=(e,t)=>{if(!e.beforeMatch)return;if(e.starts)throw new Error("beforeMatch cannot be used with starts");const i=Object.assign({},e);Object.keys(e).forEach(u=>{delete e[u]}),e.keywords=i.keywords,e.begin=C(i.beforeMatch,Oe(i.begin)),e.starts={relevance:0,contains:[Object.assign(i,{endsParent:!0})]},e.relevance=0,delete i.beforeMatch},It=["of","and","for","in","not","or","if","then","parent","list","value"],Bt="keyword";function ke(e,t,i=Bt){const u=Object.create(null);return typeof e=="string"?b(i,e.split(" ")):Array.isArray(e)?b(i,e):Object.keys(e).forEach(function(_){Object.assign(u,ke(e[_],t,_))}),u;function b(_,c){t&&(c=c.map(r=>r.toLowerCase())),c.forEach(function(r){const l=r.split("|");u[l[0]]=[_,Dt(l[0],l[1])]})}}function Dt(e,t){return t?Number(t):vt(e)?0:1}function vt(e){return It.includes(e.toLowerCase())}const Ee={},v=e=>{console.error(e)},be=(e,...t)=>{console.log(`WARN: ${e}`,...t)},L=(e,t)=>{Ee[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),Ee[`${e}/${t}`]=!0)},X=new Error;function Te(e,t,{key:i}){let u=0;const b=e[i],_={},c={};for(let r=1;r<=t.length;r++)c[r+u]=b[r],_[r+u]=!0,u+=Re(t[r-1]);e[i]=c,e[i]._emit=_,e[i]._multi=!0}function Ct(e){if(Array.isArray(e.begin)){if(e.skip||e.excludeBegin||e.returnBegin)throw v("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),X;if(typeof e.beginScope!="object"||e.beginScope===null)throw v("beginScope must be object"),X;Te(e,e.begin,{key:"beginScope"}),e.begin=ie(e.begin,{joinWith:""})}}function Lt(e){if(Array.isArray(e.end)){if(e.skip||e.excludeEnd||e.returnEnd)throw v("skip, excludeEnd, returnEnd not compatible with endScope: {}"),X;if(typeof e.endScope!="object"||e.endScope===null)throw v("endScope must be object"),X;Te(e,e.end,{key:"endScope"}),e.end=ie(e.end,{joinWith:""})}}function Ht(e){e.scope&&typeof e.scope=="object"&&e.scope!==null&&(e.beginScope=e.scope,delete e.scope)}function jt(e){Ht(e),typeof e.beginScope=="string"&&(e.beginScope={_wrap:e.beginScope}),typeof e.endScope=="string"&&(e.endScope={_wrap:e.endScope}),Ct(e),Lt(e)}function Pt(e){function t(c,r){return new RegExp(P(c),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(r?"g":""))}class i{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(r,l){l.position=this.position++,this.matchIndexes[this.matchAt]=l,this.regexes.push([l,r]),this.matchAt+=Re(r)+1}compile(){this.regexes.length===0&&(this.exec=()=>null);const r=this.regexes.map(l=>l[1]);this.matcherRe=t(ie(r,{joinWith:"|"}),!0),this.lastIndex=0}exec(r){this.matcherRe.lastIndex=this.lastIndex;const l=this.matcherRe.exec(r);if(!l)return null;const w=l.findIndex((j,Z)=>Z>0&&j!==void 0),M=this.matchIndexes[w];return l.splice(0,w),Object.assign(l,M)}}class u{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(r){if(this.multiRegexes[r])return this.multiRegexes[r];const l=new i;return this.rules.slice(r).forEach(([w,M])=>l.addRule(w,M)),l.compile(),this.multiRegexes[r]=l,l}resumingScanAtSamePosition(){return this.regexIndex!==0}considerAll(){this.regexIndex=0}addRule(r,l){this.rules.push([r,l]),l.type==="begin"&&this.count++}exec(r){const l=this.getMatcher(this.regexIndex);l.lastIndex=this.lastIndex;let w=l.exec(r);if(this.resumingScanAtSamePosition()&&!(w&&w.index===this.lastIndex)){const M=this.getMatcher(0);M.lastIndex=this.lastIndex+1,w=M.exec(r)}return w&&(this.regexIndex+=w.position+1,this.regexIndex===this.count&&this.considerAll()),w}}function b(c){const r=new u;return c.contains.forEach(l=>r.addRule(l.begin,{rule:l,type:"begin"})),c.terminatorEnd&&r.addRule(c.terminatorEnd,{type:"end"}),c.illegal&&r.addRule(c.illegal,{type:"illegal"}),r}function _(c,r){const l=c;if(c.isCompiled)return l;[yt,At,jt,Tt].forEach(M=>M(c,r)),e.compilerExtensions.forEach(M=>M(c,r)),c.__beforeBegin=null,[St,Nt,kt].forEach(M=>M(c,r)),c.isCompiled=!0;let w=null;return typeof c.keywords=="object"&&c.keywords.$pattern&&(c.keywords=Object.assign({},c.keywords),w=c.keywords.$pattern,delete c.keywords.$pattern),w=w||/\w+/,c.keywords&&(c.keywords=ke(c.keywords,e.case_insensitive)),l.keywordPatternRe=t(w,!0),r&&(c.begin||(c.begin=/\B|\b/),l.beginRe=t(l.begin),!c.end&&!c.endsWithParent&&(c.end=/\B|\b/),c.end&&(l.endRe=t(l.end)),l.terminatorEnd=P(l.end)||"",c.endsWithParent&&r.terminatorEnd&&(l.terminatorEnd+=(c.end?"|":"")+r.terminatorEnd)),c.illegal&&(l.illegalRe=t(c.illegal)),c.contains||(c.contains=[]),c.contains=[].concat(...c.contains.map(function(M){return Ut(M==="self"?c:M)})),c.contains.forEach(function(M){_(M,l)}),c.starts&&_(c.starts,r),l.matcher=b(l),l}if(e.compilerExtensions||(e.compilerExtensions=[]),e.contains&&e.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return e.classNameAliases=B(e.classNameAliases||{}),_(e)}function Ie(e){return e?e.endsWithParent||Ie(e.starts):!1}function Ut(e){return e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map(function(t){return B(e,{variants:null},t)})),e.cachedVariants?e.cachedVariants:Ie(e)?B(e,{starts:e.starts?B(e.starts):null}):Object.isFrozen(e)?B(e):e}var $t="11.11.1";class Gt extends Error{constructor(t,i){super(t),this.name="HTMLInjectionError",this.html=i}}const ee=we,_e=B,Me=Symbol("nomatch"),Wt=7,Be=function(e){const t=Object.create(null),i=Object.create(null),u=[];let b=!0;const _="Could not find the language '{}', did you forget to load/include a language module?",c={disableAutodetect:!0,name:"Plain text",contains:[]};let r={ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",cssSelector:"pre code",languages:null,__emitter:et};function l(n){return r.noHighlightRe.test(n)}function w(n){let a=n.className+" ";a+=n.parentNode?n.parentNode.className:"";const h=r.languageDetectRe.exec(a);if(h){const d=T(h[1]);return d||(be(_.replace("{}",h[1])),be("Falling back to no-highlight mode for this block.",n)),d?h[1]:"no-highlight"}return a.split(/\s+/).find(d=>l(d)||T(d))}function M(n,a,h){let d="",x="";typeof a=="object"?(d=n,h=a.ignoreIllegals,x=a.language):(L("10.7.0","highlight(lang, code, ...args) has been deprecated."),L("10.7.0",`Please use highlight(code, options) instead.
|
|
2
2
|
https://github.com/highlightjs/highlight.js/issues/2277`),x=n,d=a),h===void 0&&(h=!0);const S={code:d,language:x};G("before:highlight",S);const I=S.result?S.result:j(S.language,S.code,h);return I.code=S.code,G("after:highlight",I),I}function j(n,a,h,d){const x=Object.create(null);function S(s,o){return s.keywords[o]}function I(){if(!f.keywords){O.addText(E);return}let s=0;f.keywordPatternRe.lastIndex=0;let o=f.keywordPatternRe.exec(E),g="";for(;o;){g+=E.substring(s,o.index);const p=A.case_insensitive?o[0].toLowerCase():o[0],R=S(f,p);if(R){const[k,Ze]=R;if(O.addText(g),g="",x[p]=(x[p]||0)+1,x[p]<=Wt&&(F+=Ze),k.startsWith("_"))g+=o[0];else{const Je=A.classNameAliases[k]||k;N(o[0],Je)}}else g+=o[0];s=f.keywordPatternRe.lastIndex,o=f.keywordPatternRe.exec(E)}g+=E.substring(s),O.addText(g)}function W(){if(E==="")return;let s=null;if(typeof f.subLanguage=="string"){if(!t[f.subLanguage]){O.addText(E);return}s=j(f.subLanguage,E,!0,ge[f.subLanguage]),ge[f.subLanguage]=s._top}else s=J(E,f.subLanguage.length?f.subLanguage:null);f.relevance>0&&(F+=s.relevance),O.__addSublanguage(s._emitter,s.language)}function y(){f.subLanguage!=null?W():I(),E=""}function N(s,o){s!==""&&(O.startScope(o),O.addText(s),O.endScope())}function ae(s,o){let g=1;const p=o.length-1;for(;g<=p;){if(!s._emit[g]){g++;continue}const R=A.classNameAliases[s[g]]||s[g],k=o[g];R?N(k,R):(E=k,I(),E=""),g++}}function le(s,o){return s.scope&&typeof s.scope=="string"&&O.openNode(A.classNameAliases[s.scope]||s.scope),s.beginScope&&(s.beginScope._wrap?(N(E,A.classNameAliases[s.beginScope._wrap]||s.beginScope._wrap),E=""):s.beginScope._multi&&(ae(s.beginScope,o),E="")),f=Object.create(s,{parent:{value:f}}),f}function ue(s,o,g){let p=st(s.endRe,g);if(p){if(s["on:end"]){const R=new he(s);s["on:end"](o,R),R.isMatchIgnored&&(p=!1)}if(p){for(;s.endsParent&&s.parent;)s=s.parent;return s}}if(s.endsWithParent)return ue(s.parent,o,g)}function Ke(s){return f.matcher.regexIndex===0?(E+=s[0],1):(m=!0,0)}function Fe(s){const o=s[0],g=s.rule,p=new he(g),R=[g.__beforeBegin,g["on:begin"]];for(const k of R)if(k&&(k(s,p),p.isMatchIgnored))return Ke(o);return g.skip?E+=o:(g.excludeBegin&&(E+=o),y(),!g.returnBegin&&!g.excludeBegin&&(E=o)),le(g,s),g.returnBegin?0:o.length}function ze(s){const o=s[0],g=a.substring(s.index),p=ue(f,s,g);if(!p)return Me;const R=f;f.endScope&&f.endScope._wrap?(y(),N(o,f.endScope._wrap)):f.endScope&&f.endScope._multi?(y(),ae(f.endScope,s)):R.skip?E+=o:(R.returnEnd||R.excludeEnd||(E+=o),y(),R.excludeEnd&&(E=o));do f.scope&&O.closeNode(),!f.skip&&!f.subLanguage&&(F+=f.relevance),f=f.parent;while(f!==p.parent);return p.starts&&le(p.starts,s),R.returnEnd?0:o.length}function Xe(){const s=[];for(let o=f;o!==A;o=o.parent)o.scope&&s.unshift(o.scope);s.forEach(o=>O.openNode(o))}let K={};function fe(s,o){const g=o&&o[0];if(E+=s,g==null)return y(),0;if(K.type==="begin"&&o.type==="end"&&K.index===o.index&&g===""){if(E+=a.slice(o.index,o.index+1),!b){const p=new Error(`0 width match regex (${n})`);throw p.languageName=n,p.badRule=K.rule,p}return 1}if(K=o,o.type==="begin")return Fe(o);if(o.type==="illegal"&&!h){const p=new Error('Illegal lexeme "'+g+'" for mode "'+(f.scope||"<unnamed>")+'"');throw p.mode=f,p}else if(o.type==="end"){const p=ze(o);if(p!==Me)return p}if(o.type==="illegal"&&g==="")return E+=`
|
|
3
3
|
`,1;if(Q>1e5&&Q>o.index*3)throw new Error("potential infinite loop, way more iterations than matches");return E+=g,g.length}const A=T(n);if(!A)throw v(_.replace("{}",n)),new Error('Unknown language: "'+n+'"');const Ye=Pt(A);let q="",f=d||Ye;const ge={},O=new r.__emitter(r);Xe();let E="",F=0,D=0,Q=0,m=!1;try{if(A.__emitTokens)A.__emitTokens(a,O);else{for(f.matcher.considerAll();;){Q++,m?m=!1:f.matcher.considerAll(),f.matcher.lastIndex=D;const s=f.matcher.exec(a);if(!s)break;const o=a.substring(D,s.index),g=fe(o,s);D=s.index+g}fe(a.substring(D))}return O.finalize(),q=O.toHTML(),{language:n,value:q,relevance:F,illegal:!1,_emitter:O,_top:f}}catch(s){if(s.message&&s.message.includes("Illegal"))return{language:n,value:ee(a),illegal:!0,relevance:0,_illegalBy:{message:s.message,index:D,context:a.slice(D-100,D+100),mode:s.mode,resultSoFar:q},_emitter:O};if(b)return{language:n,value:ee(a),illegal:!1,relevance:0,errorRaised:s,_emitter:O,_top:f};throw s}}function Z(n){const a={value:ee(n),illegal:!1,relevance:0,_top:c,_emitter:new r.__emitter(r)};return a._emitter.addText(n),a}function J(n,a){a=a||r.languages||Object.keys(t);const h=Z(n),d=a.filter(T).filter(oe).map(y=>j(y,n,!1));d.unshift(h);const x=d.sort((y,N)=>{if(y.relevance!==N.relevance)return N.relevance-y.relevance;if(y.language&&N.language){if(T(y.language).supersetOf===N.language)return 1;if(T(N.language).supersetOf===y.language)return-1}return 0}),[S,I]=x,W=S;return W.secondBest=I,W}function De(n,a,h){const d=a&&i[a]||h;n.classList.add("hljs"),n.classList.add(`language-${d}`)}function V(n){let a=null;const h=w(n);if(l(h))return;if(G("before:highlightElement",{el:n,language:h}),n.dataset.highlighted){console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",n);return}if(n.children.length>0&&(r.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),console.warn("The element with unescaped HTML:"),console.warn(n)),r.throwUnescapedHTML))throw new Gt("One of your code blocks includes unescaped HTML.",n.innerHTML);a=n;const d=a.textContent,x=h?M(d,{language:h,ignoreIllegals:!0}):J(d);n.innerHTML=x.value,n.dataset.highlighted="yes",De(n,h,x.language),n.result={language:x.language,re:x.relevance,relevance:x.relevance},x.secondBest&&(n.secondBest={language:x.secondBest.language,relevance:x.secondBest.relevance}),G("after:highlightElement",{el:n,result:x,text:d})}function ve(n){r=_e(r,n)}const Ce=()=>{$(),L("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")};function Le(){$(),L("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")}let re=!1;function $(){function n(){$()}if(document.readyState==="loading"){re||window.addEventListener("DOMContentLoaded",n,!1),re=!0;return}document.querySelectorAll(r.cssSelector).forEach(V)}function He(n,a){let h=null;try{h=a(e)}catch(d){if(v("Language definition for '{}' could not be registered.".replace("{}",n)),b)v(d);else throw d;h=c}h.name||(h.name=n),t[n]=h,h.rawDefinition=a.bind(null,e),h.aliases&&ce(h.aliases,{languageName:n})}function je(n){delete t[n];for(const a of Object.keys(i))i[a]===n&&delete i[a]}function Pe(){return Object.keys(t)}function T(n){return n=(n||"").toLowerCase(),t[n]||t[i[n]]}function ce(n,{languageName:a}){typeof n=="string"&&(n=[n]),n.forEach(h=>{i[h.toLowerCase()]=a})}function oe(n){const a=T(n);return a&&!a.disableAutodetect}function Ue(n){n["before:highlightBlock"]&&!n["before:highlightElement"]&&(n["before:highlightElement"]=a=>{n["before:highlightBlock"](Object.assign({block:a.el},a))}),n["after:highlightBlock"]&&!n["after:highlightElement"]&&(n["after:highlightElement"]=a=>{n["after:highlightBlock"](Object.assign({block:a.el},a))})}function $e(n){Ue(n),u.push(n)}function Ge(n){const a=u.indexOf(n);a!==-1&&u.splice(a,1)}function G(n,a){const h=n;u.forEach(function(d){d[h]&&d[h](a)})}function We(n){return L("10.7.0","highlightBlock will be removed entirely in v12.0"),L("10.7.0","Please use highlightElement now."),V(n)}Object.assign(e,{highlight:M,highlightAuto:J,highlightAll:$,highlightElement:V,highlightBlock:We,configure:ve,initHighlighting:Ce,initHighlightingOnLoad:Le,registerLanguage:He,unregisterLanguage:je,listLanguages:Pe,getLanguage:T,registerAliases:ce,autoDetection:oe,inherit:_e,addPlugin:$e,removePlugin:Ge}),e.debugMode=function(){b=!1},e.safeMode=function(){b=!0},e.versionString=$t,e.regex={concat:C,lookahead:Oe,either:ne,optional:nt,anyNumberOfTimes:tt};for(const n in z)typeof z[n]=="object"&&xe(z[n]);return Object.assign(e,z),e},H=Be({});H.newInstance=()=>Be({});var Kt=H;H.HighlightJS=H;H.default=H;const zt=Ve(Kt);export{zt as HighlightJS,zt as default};
|