nterminal 1.3.3 → 1.3.5
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/bin/nterminal.js +8 -3
- package/dist/client/assets/MarkdownPreview-BIrwUAaa.js +1 -0
- package/dist/client/assets/TranscriptMarkdownBody-CI0ztvMX.js +3 -0
- package/dist/client/assets/{index-DDCpqDNb.js → index-EN8ngMgv.js} +1 -1
- package/dist/client/assets/index-JQJ1Eet1.js +58 -0
- package/dist/client/assets/index-xkL4h3qt.css +1 -0
- package/dist/client/index.html +2 -2
- package/dist/scripts/hooks.js +83 -0
- package/dist/scripts/hooks.js.map +1 -0
- package/dist/server/accounts/accountService.d.ts +23 -1
- package/dist/server/accounts/accountService.js +235 -103
- package/dist/server/accounts/accountService.js.map +1 -1
- package/dist/server/accounts/providerRequests.d.ts +12 -0
- package/dist/server/accounts/providerRequests.js +159 -0
- package/dist/server/accounts/providerRequests.js.map +1 -0
- package/dist/server/agent/agentRoutes.js +11 -0
- package/dist/server/agent/agentRoutes.js.map +1 -1
- package/dist/server/hooks/helperJournal.d.ts +16 -0
- package/dist/server/hooks/helperJournal.js +74 -0
- package/dist/server/hooks/helperJournal.js.map +1 -0
- package/dist/server/hooks/hookBinding.d.ts +39 -0
- package/dist/server/hooks/hookBinding.js +91 -0
- package/dist/server/hooks/hookBinding.js.map +1 -0
- package/dist/server/hooks/hookFiles.d.ts +24 -0
- package/dist/server/hooks/hookFiles.js +160 -0
- package/dist/server/hooks/hookFiles.js.map +1 -0
- package/dist/server/hooks/hookInstallation.d.ts +79 -0
- package/dist/server/hooks/hookInstallation.js +978 -0
- package/dist/server/hooks/hookInstallation.js.map +1 -0
- package/dist/server/hooks/hookProcess.d.ts +5 -0
- package/dist/server/hooks/hookProcess.js +85 -0
- package/dist/server/hooks/hookProcess.js.map +1 -0
- package/dist/server/hooks/hookReceiver.d.ts +66 -0
- package/dist/server/hooks/hookReceiver.js +549 -0
- package/dist/server/hooks/hookReceiver.js.map +1 -0
- package/dist/server/hooks/lifecycle.d.ts +40 -0
- package/dist/server/hooks/lifecycle.js +200 -0
- package/dist/server/hooks/lifecycle.js.map +1 -0
- package/dist/server/hooks/publicationLock.d.ts +3 -0
- package/dist/server/hooks/publicationLock.js +137 -0
- package/dist/server/hooks/publicationLock.js.map +1 -0
- package/dist/server/hooks/verifiedLock.d.ts +24 -0
- package/dist/server/hooks/verifiedLock.js +207 -0
- package/dist/server/hooks/verifiedLock.js.map +1 -0
- package/dist/server/http.d.ts +4 -0
- package/dist/server/http.js +6 -0
- package/dist/server/http.js.map +1 -1
- package/dist/server/index.js +69 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/notifications/agentCompletionMonitor.d.ts +16 -1
- package/dist/server/notifications/agentCompletionMonitor.js +261 -47
- package/dist/server/notifications/agentCompletionMonitor.js.map +1 -1
- package/dist/server/notifications/completionNotificationRouter.d.ts +2 -0
- package/dist/server/notifications/completionNotificationRouter.js +9 -0
- package/dist/server/notifications/completionNotificationRouter.js.map +1 -1
- package/dist/server/routes/accountRoutes.js +11 -0
- package/dist/server/routes/accountRoutes.js.map +1 -1
- package/dist/server/routes/activityRoutes.d.ts +13 -0
- package/dist/server/routes/activityRoutes.js +165 -0
- package/dist/server/routes/activityRoutes.js.map +1 -0
- package/dist/server/routes/agentManagementRoutes.js +8 -1
- package/dist/server/routes/agentManagementRoutes.js.map +1 -1
- package/dist/server/routes/hookRoutes.d.ts +16 -0
- package/dist/server/routes/hookRoutes.js +77 -0
- package/dist/server/routes/hookRoutes.js.map +1 -0
- package/dist/server/routes/terminalRoutes.js +4 -0
- package/dist/server/routes/terminalRoutes.js.map +1 -1
- package/dist/server/routes/transcriptQuery.d.ts +2 -1
- package/dist/server/routes/transcriptQuery.js +3 -1
- package/dist/server/routes/transcriptQuery.js.map +1 -1
- package/dist/server/terminal/PtyAdapter.d.ts +18 -0
- package/dist/server/terminal/PtyAdapter.js.map +1 -1
- package/dist/server/terminal/TerminalManager.d.ts +61 -0
- package/dist/server/terminal/TerminalManager.js +665 -12
- package/dist/server/terminal/TerminalManager.js.map +1 -1
- package/dist/server/terminal/TmuxPtyAdapter.d.ts +14 -2
- package/dist/server/terminal/TmuxPtyAdapter.js +104 -16
- package/dist/server/terminal/TmuxPtyAdapter.js.map +1 -1
- package/dist/server/terminal/activityChannel.d.ts +57 -0
- package/dist/server/terminal/activityChannel.js +166 -0
- package/dist/server/terminal/activityChannel.js.map +1 -0
- package/dist/server/terminal/agentTranscriptStatus.d.ts +12 -0
- package/dist/server/terminal/agentTranscriptStatus.js +78 -7
- package/dist/server/terminal/agentTranscriptStatus.js.map +1 -1
- package/dist/server/terminal/codexTranscriptSource.d.ts +2 -0
- package/dist/server/terminal/codexTranscriptSource.js +53 -46
- package/dist/server/terminal/codexTranscriptSource.js.map +1 -1
- package/dist/server/terminal/subagentSources.js +2 -1
- package/dist/server/terminal/subagentSources.js.map +1 -1
- package/dist/server/terminal/transcriptHeader.d.ts +85 -0
- package/dist/server/terminal/transcriptHeader.js +376 -0
- package/dist/server/terminal/transcriptHeader.js.map +1 -0
- package/dist/server/terminal/transcriptHistory.d.ts +16 -2
- package/dist/server/terminal/transcriptHistory.js +120 -21
- package/dist/server/terminal/transcriptHistory.js.map +1 -1
- package/dist/server/terminal/transcriptStore.d.ts +6 -0
- package/dist/server/terminal/transcriptStore.js +222 -26
- package/dist/server/terminal/transcriptStore.js.map +1 -1
- package/dist/shared/activityProbe.d.ts +10 -0
- package/dist/shared/activityProbe.js +24 -0
- package/dist/shared/activityProbe.js.map +1 -0
- package/dist/shared/protocol.d.ts +45 -0
- package/dist/shared/protocol.js.map +1 -1
- package/dist/shared/types.d.ts +9 -1
- package/docs/features.md +10 -0
- package/docs/provider-hooks.md +287 -0
- package/docs/terminal-history.md +10 -0
- package/package.json +2 -1
- package/scripts/nterminal-hook.cjs +171 -0
- package/scripts/nterminalctl +26 -2
- package/dist/client/assets/MarkdownPreview-CWK2qIZp.js +0 -1
- package/dist/client/assets/TranscriptMarkdownBody-Ddi-rw6X.js +0 -3
- package/dist/client/assets/index-CcAQThtj.js +0 -56
- package/dist/client/assets/index-DTTX24tu.css +0 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Standalone installer payload: copy to <stateDir>/hooks/forward.cjs. No app imports.
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const fsp = require('node:fs/promises');
|
|
6
|
+
const http = require('node:http');
|
|
7
|
+
const path = require('node:path');
|
|
8
|
+
const { randomUUID } = require('node:crypto');
|
|
9
|
+
|
|
10
|
+
const MAX_INPUT = 4 * 1024 * 1024;
|
|
11
|
+
const ID = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,255}$/;
|
|
12
|
+
const ERRORS = new Set(['authentication_error', 'rate_limit_error', 'api_error', 'overloaded_error',
|
|
13
|
+
'server_error', 'timeout', 'permission_denied', 'cancelled', 'provider_error', 'rate_limit', 'overloaded',
|
|
14
|
+
'authentication_failed', 'oauth_org_not_allowed', 'account_on_hold', 'billing_error', 'invalid_request',
|
|
15
|
+
'model_not_found', 'max_output_tokens', 'cloud_credential_error', 'unknown']);
|
|
16
|
+
let request;
|
|
17
|
+
let finished = false;
|
|
18
|
+
const deadline = setTimeout(finish, 700);
|
|
19
|
+
|
|
20
|
+
function finish() {
|
|
21
|
+
if (finished) return;
|
|
22
|
+
finished = true;
|
|
23
|
+
clearTimeout(deadline);
|
|
24
|
+
request?.destroy();
|
|
25
|
+
// A hook must never request continuation, grant permission, or fail the provider.
|
|
26
|
+
try { fs.writeSync(1, '{}\n'); } catch {}
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
process.on('uncaughtException', finish);
|
|
30
|
+
process.on('unhandledRejection', finish);
|
|
31
|
+
process.stdin.on('error', finish);
|
|
32
|
+
process.stdout.on('error', finish);
|
|
33
|
+
|
|
34
|
+
function options() {
|
|
35
|
+
const args = process.argv.slice(2);
|
|
36
|
+
const result = { notify: false };
|
|
37
|
+
while (args.length) {
|
|
38
|
+
const key = args.shift();
|
|
39
|
+
if (key === '--provider' && result.provider === undefined) result.provider = args.shift();
|
|
40
|
+
else if (key === '--endpoint' && result.endpoint === undefined) result.endpoint = args.shift();
|
|
41
|
+
else if (key === '--notify' && !result.notify) result.notify = true;
|
|
42
|
+
else if (result.notify && args.length === 0 && result.raw === undefined) result.raw = key;
|
|
43
|
+
else throw new Error('arguments');
|
|
44
|
+
}
|
|
45
|
+
if (!['codex', 'claude'].includes(result.provider) || !result.endpoint || !path.isAbsolute(result.endpoint)
|
|
46
|
+
|| (result.notify && (result.provider !== 'codex' || result.raw === undefined))) throw new Error('arguments');
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function readPrivate(file, limit) {
|
|
51
|
+
const handle = await fsp.open(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
|
|
52
|
+
try {
|
|
53
|
+
const info = await handle.stat();
|
|
54
|
+
if (!info.isFile() || info.uid !== process.getuid() || (info.mode & 0o777) !== 0o600 || info.size > limit) throw new Error('file');
|
|
55
|
+
const buffer = Buffer.alloc(limit + 1);
|
|
56
|
+
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
57
|
+
if (bytesRead > limit) throw new Error('size');
|
|
58
|
+
return buffer.subarray(0, bytesRead).toString('utf8');
|
|
59
|
+
} finally { await handle.close(); }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function endpoint(file) {
|
|
63
|
+
if (path.basename(file) !== 'endpoint.json') throw new Error('endpoint');
|
|
64
|
+
const directory = path.dirname(file);
|
|
65
|
+
const info = await fsp.lstat(directory);
|
|
66
|
+
if (!info.isDirectory() || info.uid !== process.getuid() || (info.mode & 0o777) !== 0o700
|
|
67
|
+
|| await fsp.realpath(directory) !== directory) throw new Error('directory');
|
|
68
|
+
const value = JSON.parse(await readPrivate(file, 4096));
|
|
69
|
+
if (value.version !== 1 || !/^[0-9a-f]{32}$/.test(value.generation) || !/^[0-9a-f]{64}$/.test(value.token)
|
|
70
|
+
|| value.socketPath !== path.join(directory, `r-${value.generation}.sock`)
|
|
71
|
+
|| Buffer.byteLength(value.socketPath) > 103) throw new Error('endpoint');
|
|
72
|
+
const socket = await fsp.lstat(value.socketPath);
|
|
73
|
+
if (!socket.isSocket() || socket.uid !== process.getuid() || (socket.mode & 0o777) !== 0o600) throw new Error('socket');
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function ancestry() {
|
|
78
|
+
const chain = [];
|
|
79
|
+
const seen = new Set();
|
|
80
|
+
let pid = process.pid;
|
|
81
|
+
while (pid > 0 && chain.length < 64 && !seen.has(pid)) {
|
|
82
|
+
seen.add(pid);
|
|
83
|
+
const raw = await fsp.readFile(`/proc/${pid}/stat`, 'utf8');
|
|
84
|
+
if (raw.length > 4096 || !raw.startsWith(`${pid} (`)) throw new Error('stat');
|
|
85
|
+
const fields = raw.slice(raw.lastIndexOf(')') + 2).trim().split(/\s+/);
|
|
86
|
+
if (!/^\d{1,20}$/.test(fields[19] || '') || !/^\d+$/.test(fields[1] || '')
|
|
87
|
+
|| fields[0] === 'Z' || fields[0] === 'X') throw new Error('stat');
|
|
88
|
+
chain.push({ pid, startTicks: fields[19] });
|
|
89
|
+
pid = Number(fields[1]);
|
|
90
|
+
}
|
|
91
|
+
if (pid !== 0 || chain.length < 2) throw new Error('chain');
|
|
92
|
+
return chain;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function metadata(raw, provider, notify) {
|
|
96
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error('input');
|
|
97
|
+
const event = notify ? raw.type : raw.hook_event_name;
|
|
98
|
+
const sessionId = notify ? raw['thread-id'] : raw.session_id;
|
|
99
|
+
if (typeof event !== 'string' || !/^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(event)
|
|
100
|
+
|| (notify && event !== 'agent-turn-complete') || typeof sessionId !== 'string' || !ID.test(sessionId)) throw new Error('identity');
|
|
101
|
+
// Stamp the provider's spawn time, not the post-startup time: async (non-blocking)
|
|
102
|
+
// tool hooks may finish after a later synchronous Stop, and the receiver orders
|
|
103
|
+
// events by this timestamp. performance.timeOrigin is this process's start time.
|
|
104
|
+
const started = Math.min(Date.now(), Math.floor(performance.timeOrigin));
|
|
105
|
+
const result = { provider, event, sessionId, pid: process.pid, occurredAt: new Date(started).toISOString(), eventId: randomUUID() };
|
|
106
|
+
for (const [key, value] of Object.entries({ transcriptPath: raw.transcript_path, cwd: raw.cwd,
|
|
107
|
+
turnId: notify ? raw['turn-id'] : raw.turn_id, promptId: raw.prompt_id, agentId: raw.agent_id })) {
|
|
108
|
+
if (value === undefined || (provider === 'codex' && key === 'transcriptPath' && value === null)) continue;
|
|
109
|
+
if (typeof value !== 'string') throw new Error('metadata');
|
|
110
|
+
if (key === 'cwd' || key === 'transcriptPath') {
|
|
111
|
+
if (value.length > 4096 || !path.isAbsolute(value) || /[\x00-\x1f\x7f]/.test(value)) throw new Error('path');
|
|
112
|
+
} else if (!ID.test(value)) throw new Error('id');
|
|
113
|
+
result[key] = value;
|
|
114
|
+
}
|
|
115
|
+
for (const [key, value] of Object.entries({ background: raw.background, stopHookActive: raw.stop_hook_active, hasBackgroundTasks: raw.has_background_tasks })) {
|
|
116
|
+
if (value === undefined) continue;
|
|
117
|
+
if (typeof value !== 'boolean') throw new Error('flag');
|
|
118
|
+
result[key] = value;
|
|
119
|
+
}
|
|
120
|
+
if (provider === 'claude' && (event === 'Stop' || event === 'SubagentStop')) {
|
|
121
|
+
const tasks = raw.background_tasks;
|
|
122
|
+
const crons = raw.session_crons;
|
|
123
|
+
for (const value of [tasks, crons]) {
|
|
124
|
+
if (value !== undefined && !Array.isArray(value)) throw new Error('tasks');
|
|
125
|
+
}
|
|
126
|
+
// Only presence matters. Missing registry data is unknown; never copy task or prompt bodies.
|
|
127
|
+
if (tasks?.length || crons?.length) result.hasBackgroundTasks = true;
|
|
128
|
+
else if (tasks !== undefined && crons !== undefined && result.hasBackgroundTasks === undefined) result.hasBackgroundTasks = false;
|
|
129
|
+
}
|
|
130
|
+
if (raw.error !== undefined) result.error = typeof raw.error === 'string' && ERRORS.has(raw.error) ? raw.error : 'provider_error';
|
|
131
|
+
if (raw.notification_type !== undefined) {
|
|
132
|
+
if (typeof raw.notification_type !== 'string' || !/^[a-z][a-z0-9_]{0,63}$/.test(raw.notification_type)) throw new Error('notification');
|
|
133
|
+
result.notificationType = raw.notification_type;
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function stdin() {
|
|
139
|
+
let bytes = 0;
|
|
140
|
+
let chunks = [];
|
|
141
|
+
for await (const chunk of process.stdin) {
|
|
142
|
+
bytes += chunk.length;
|
|
143
|
+
if (bytes <= MAX_INPUT) chunks.push(chunk);
|
|
144
|
+
else chunks = []; // Drain overflow without keeping prompt/tool content in memory.
|
|
145
|
+
}
|
|
146
|
+
if (bytes > MAX_INPUT) throw new Error('size');
|
|
147
|
+
return Buffer.concat(chunks, bytes).toString('utf8');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function main() {
|
|
151
|
+
const opts = options();
|
|
152
|
+
const input = opts.notify ? opts.raw : await stdin();
|
|
153
|
+
if (Buffer.byteLength(input) > MAX_INPUT) return;
|
|
154
|
+
const event = metadata(JSON.parse(input), opts.provider, opts.notify);
|
|
155
|
+
const destination = await endpoint(opts.endpoint);
|
|
156
|
+
event.ancestors = await ancestry();
|
|
157
|
+
const body = JSON.stringify(event);
|
|
158
|
+
if (Buffer.byteLength(body) > 64 * 1024 || finished) return;
|
|
159
|
+
await new Promise(resolve => {
|
|
160
|
+
request = http.request({ socketPath: destination.socketPath, method: 'POST', path: '/hook', agent: false,
|
|
161
|
+
headers: { authorization: `Bearer ${destination.token}`, 'content-type': 'application/json', 'content-length': Buffer.byteLength(body), connection: 'close' } }, response => {
|
|
162
|
+
response.resume();
|
|
163
|
+
response.once('end', resolve);
|
|
164
|
+
response.once('error', resolve);
|
|
165
|
+
});
|
|
166
|
+
request.once('error', resolve);
|
|
167
|
+
request.end(body);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
main().then(finish, finish);
|
package/scripts/nterminalctl
CHANGED
|
@@ -790,6 +790,26 @@ clean_state_paths() {
|
|
|
790
790
|
rm -rf "$state_dir/transcript-cache"
|
|
791
791
|
}
|
|
792
792
|
|
|
793
|
+
# Best effort and never fatal: remove only NTerminal-owned provider hook entries
|
|
794
|
+
# (the installer verifies ownership from its manifests). Must run before .env is
|
|
795
|
+
# removed because CODEX_HOME/CLAUDE_CONFIG_DIR may be defined there.
|
|
796
|
+
remove_provider_hooks() {
|
|
797
|
+
local entry="$APP_DIR/dist/scripts/hooks.js"
|
|
798
|
+
local provider
|
|
799
|
+
if [[ ! -f "$entry" ]] || ! command -v "$NODE_BIN" >/dev/null 2>&1; then
|
|
800
|
+
info "warning: provider hooks were not checked (hooks CLI unavailable); run 'nterminal hooks remove --provider codex|claude' before uninstalling the package"
|
|
801
|
+
return 0
|
|
802
|
+
fi
|
|
803
|
+
for provider in codex claude; do
|
|
804
|
+
if "$NODE_BIN" "$entry" remove --provider "$provider" >/dev/null 2>&1; then
|
|
805
|
+
info "provider hooks removed provider=$provider"
|
|
806
|
+
else
|
|
807
|
+
info "warning: provider hooks may remain provider=$provider; check with: nterminal hooks status --provider $provider"
|
|
808
|
+
fi
|
|
809
|
+
done
|
|
810
|
+
return 0
|
|
811
|
+
}
|
|
812
|
+
|
|
793
813
|
cmd_clean() {
|
|
794
814
|
local force=0
|
|
795
815
|
local remove_env=0
|
|
@@ -816,6 +836,7 @@ cmd_clean() {
|
|
|
816
836
|
|
|
817
837
|
local state_dir
|
|
818
838
|
state_dir="$(dirname "$STATE_PATH")"
|
|
839
|
+
remove_provider_hooks || true
|
|
819
840
|
clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH" "$MONITOR_PID_PATH"
|
|
820
841
|
if (( remove_env == 1 )); then
|
|
821
842
|
rm -f "$ENV_FILE"
|
|
@@ -846,6 +867,7 @@ cmd_uninstall() {
|
|
|
846
867
|
if (( kill_tmux == 1 )) && command -v tmux >/dev/null 2>&1; then
|
|
847
868
|
tmux -L nterminal kill-server >/dev/null 2>&1 || true
|
|
848
869
|
fi
|
|
870
|
+
remove_provider_hooks || true
|
|
849
871
|
clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH" "$MONITOR_PID_PATH"
|
|
850
872
|
rm -f "$ENV_FILE"
|
|
851
873
|
remove_owned_launchd_plist
|
|
@@ -939,10 +961,12 @@ Commands:
|
|
|
939
961
|
Stop the supervisor and start again after an npm package update.
|
|
940
962
|
build No-op for package installs; verifies the bundled runtime exists.
|
|
941
963
|
deploy Restart the installed package using the bundled runtime.
|
|
942
|
-
clean --force Stop server, kill NTerminal tmux sessions,
|
|
964
|
+
clean --force Stop server, kill NTerminal tmux sessions, remove NTerminal's provider hooks,
|
|
965
|
+
and remove local state/log/pid files.
|
|
943
966
|
Add --env to also remove .env. Add --keep-tmux to preserve live panes.
|
|
944
967
|
uninstall --force
|
|
945
|
-
Stop server, unload NTerminal launchd agent, remove
|
|
968
|
+
Stop server, unload NTerminal launchd agent, remove NTerminal's provider hooks,
|
|
969
|
+
local runtime files and .env.
|
|
946
970
|
Add --keep-tmux to preserve live panes.
|
|
947
971
|
logs [N] Show the last N log lines. Default: 100.
|
|
948
972
|
logs -f [N] Follow logs.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as a}from"./index-CcAQThtj.js";import{M as e,r as o}from"./index-DDCpqDNb.js";function s({content:r}){return a.jsx(e,{remarkPlugins:[o],children:r})}export{s as default};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{j as o,R as a}from"./index-CcAQThtj.js";import{M as u,r as f}from"./index-DDCpqDNb.js";function k({text:r,searchQuery:t}){return o.jsx(u,{components:p(t),remarkPlugins:[f],children:j(r)})}function p(r){return{a({node:t,children:n,...e}){return o.jsx("a",{...e,target:"_blank",rel:"noreferrer",children:d(n,r)})},blockquote({node:t,children:n,...e}){return o.jsx("blockquote",{...e,children:d(n,r)})},code({node:t,children:n,...e}){return o.jsx("code",{...e,children:d(n,r)})},em({node:t,children:n,...e}){return o.jsx("em",{...e,children:d(n,r)})},h1({node:t,children:n,...e}){return o.jsx("h1",{...e,children:d(n,r)})},h2({node:t,children:n,...e}){return o.jsx("h2",{...e,children:d(n,r)})},h3({node:t,children:n,...e}){return o.jsx("h3",{...e,children:d(n,r)})},h4({node:t,children:n,...e}){return o.jsx("h4",{...e,children:d(n,r)})},h5({node:t,children:n,...e}){return o.jsx("h5",{...e,children:d(n,r)})},h6({node:t,children:n,...e}){return o.jsx("h6",{...e,children:d(n,r)})},li({node:t,children:n,...e}){return o.jsx("li",{...e,children:d(n,r)})},p({node:t,children:n,...e}){return o.jsx("p",{...e,children:d(n,r)})},pre({node:t,children:n,...e}){return o.jsx("pre",{...e,className:"transcript-markdown-code",children:n})},strong({node:t,children:n,...e}){return o.jsx("strong",{...e,children:d(n,r)})},td({node:t,children:n,...e}){return o.jsx("td",{...e,children:d(n,r)})},th({node:t,children:n,...e}){return o.jsx("th",{...e,children:d(n,r)})}}}function d(r,t){return a.Children.map(r,n=>typeof n=="string"?m(n,t):n)}function m(r,t){const n=t.trim();if(!n)return r||" ";const e=r.toLowerCase(),s=n.toLowerCase(),c=[];let l=0,i=e.indexOf(s);for(;i!==-1;){i>l&&c.push(r.slice(l,i));const h=i+n.length;c.push(o.jsx("mark",{className:"transcript-search-hit",children:r.slice(i,h)},`${i}-${h}`)),l=h,i=e.indexOf(s,l)}return l<r.length&&c.push(r.slice(l)),c.length>0?c:r||" "}function j(r){const t=r.split(`
|
|
2
|
-
`);let n=!1,e=null;return t.map((s,c)=>{const l=n,i=/^ {0,3}(```+|~~~+)/.exec(s);if(i){const h=i[1]?.startsWith("`")?"`":"~";n?e===h&&(n=!1,e=null):(n=!0,e=h)}return c===t.length-1||l||i||s.trim()===""||s.endsWith(" ")?s:`${s.replace(/[ \t]+$/,"")} `}).join(`
|
|
3
|
-
`)}export{k as default};
|