mirror of
https://github.com/wavetermdev/waveterm
synced 2026-04-21 14:37:16 +00:00
Show Claude icon in terminal header while Claude Code is active (#3046)
This updates the terminal shell-integration badge so it reflects Claude Code activity instead of always rendering the generic AI icon. When the active shell command is Claude Code, the header now shows the Claude logo. - **Terminal shell-integration badge** - Updated `getShellIntegrationIconButton()` to render the Claude logo while Claude Code is the active running command. - Kept the existing shell-integration states and messaging intact for non-Claude commands. - **Claude Code detection** - Added command detection for Claude Code in the OSC shell-integration flow. - Tracks active Claude sessions on `TermWrap`, including initial runtime-info hydration and command lifecycle transitions. - Handles common invocation forms, including direct binary paths and commands wrapped by env var assignments / `env`. - **UI rendering** - Added `@lobehub/icons` and used its `Claude` icon in the terminal header path. - Reused the existing icon-button rendering contract by passing a React node for the icon where needed. - **Focused coverage** - Added a small unit test for Claude command detection to lock in the supported command forms. ```ts const claudeCodeActive = get(this.termRef.current.claudeCodeActiveAtom); const icon = claudeCodeActive ? React.createElement(TermClaudeIcon) : "sparkles"; ``` - **screenshot** -  <!-- START COPILOT CODING AGENT TIPS --> --- 💬 Send tasks to Copilot coding agent from [Slack](https://gh.io/cca-slack-docs) and [Teams](https://gh.io/cca-teams-docs) to turn conversations into code. Copilot posts an update in your thread when it's finished. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: sawka <2722291+sawka@users.noreply.github.com> Co-authored-by: sawka <mike@commandline.dev>
This commit is contained in:
parent
f92a953e07
commit
889e628780
7 changed files with 159 additions and 62 deletions
1
frontend/app/asset/claude-color.svg
Normal file
1
frontend/app/asset/claude-color.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z" fill="#D97757" fill-rule="nonzero"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
23
frontend/app/view/term/osc-handlers.test.ts
Normal file
23
frontend/app/view/term/osc-handlers.test.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { isClaudeCodeCommand } from "./osc-handlers";
|
||||
|
||||
describe("isClaudeCodeCommand", () => {
|
||||
it("matches direct Claude Code invocations", () => {
|
||||
expect(isClaudeCodeCommand("claude")).toBe(true);
|
||||
expect(isClaudeCodeCommand("claude --dangerously-skip-permissions")).toBe(true);
|
||||
});
|
||||
|
||||
it("matches Claude Code invocations wrapped with env assignments", () => {
|
||||
expect(isClaudeCodeCommand('ANTHROPIC_API_KEY="test" claude')).toBe(true);
|
||||
expect(isClaudeCodeCommand("env FOO=bar claude --print")).toBe(true);
|
||||
});
|
||||
|
||||
it("ignores other commands", () => {
|
||||
expect(isClaudeCodeCommand("claudes")).toBe(false);
|
||||
expect(isClaudeCodeCommand("echo claude")).toBe(false);
|
||||
expect(isClaudeCodeCommand("ls ~/claude")).toBe(false);
|
||||
expect(isClaudeCodeCommand("cat /logs/claude")).toBe(false);
|
||||
expect(isClaudeCodeCommand("")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -25,6 +25,8 @@ const Osc52MaxRawLength = 128 * 1024; // includes selector + base64 + whitespace
|
|||
// See aiprompts/wave-osc-16162.md for full documentation
|
||||
export type ShellIntegrationStatus = "ready" | "running-command";
|
||||
|
||||
const ClaudeCodeRegex = /^claude\b/;
|
||||
|
||||
type Osc16162Command =
|
||||
| { command: "A"; data: Record<string, never> }
|
||||
| { command: "C"; data: { cmd64?: string } }
|
||||
|
|
@ -43,41 +45,56 @@ type Osc16162Command =
|
|||
| { command: "I"; data: { inputempty?: boolean } }
|
||||
| { command: "R"; data: Record<string, never> };
|
||||
|
||||
function normalizeCmd(decodedCmd: string): string {
|
||||
let normalizedCmd = decodedCmd.trim();
|
||||
normalizedCmd = normalizedCmd.replace(/^env\s+/, "");
|
||||
normalizedCmd = normalizedCmd.replace(/^(?:\w+=(?:"[^"]*"|'[^']*'|\S+)\s+)*/, "");
|
||||
return normalizedCmd;
|
||||
}
|
||||
|
||||
function checkCommandForTelemetry(decodedCmd: string) {
|
||||
if (!decodedCmd) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (decodedCmd.startsWith("ssh ")) {
|
||||
const normalizedCmd = normalizeCmd(decodedCmd);
|
||||
|
||||
if (normalizedCmd.startsWith("ssh ")) {
|
||||
recordTEvent("conn:connect", { "conn:conntype": "ssh-manual" });
|
||||
return;
|
||||
}
|
||||
|
||||
const editorsRegex = /^(vim|vi|nano|nvim)\b/;
|
||||
if (editorsRegex.test(decodedCmd)) {
|
||||
if (editorsRegex.test(normalizedCmd)) {
|
||||
recordTEvent("action:term", { "action:type": "cli-edit" });
|
||||
return;
|
||||
}
|
||||
|
||||
const tailFollowRegex = /(^|\|\s*)tail\s+-[fF]\b/;
|
||||
if (tailFollowRegex.test(decodedCmd)) {
|
||||
if (tailFollowRegex.test(normalizedCmd)) {
|
||||
recordTEvent("action:term", { "action:type": "cli-tailf" });
|
||||
return;
|
||||
}
|
||||
|
||||
const claudeRegex = /^claude\b/;
|
||||
if (claudeRegex.test(decodedCmd)) {
|
||||
if (ClaudeCodeRegex.test(normalizedCmd)) {
|
||||
recordTEvent("action:term", { "action:type": "claude" });
|
||||
return;
|
||||
}
|
||||
|
||||
const opencodeRegex = /^opencode\b/;
|
||||
if (opencodeRegex.test(decodedCmd)) {
|
||||
if (opencodeRegex.test(normalizedCmd)) {
|
||||
recordTEvent("action:term", { "action:type": "opencode" });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
export function isClaudeCodeCommand(decodedCmd: string): boolean {
|
||||
if (!decodedCmd) {
|
||||
return false;
|
||||
}
|
||||
return ClaudeCodeRegex.test(normalizeCmd(decodedCmd));
|
||||
}
|
||||
|
||||
function handleShellIntegrationCommandStart(
|
||||
termWrap: TermWrap,
|
||||
blockId: string,
|
||||
|
|
@ -101,16 +118,20 @@ function handleShellIntegrationCommandStart(
|
|||
const decodedCmd = base64ToString(cmd.data.cmd64);
|
||||
rtInfo["shell:lastcmd"] = decodedCmd;
|
||||
globalStore.set(termWrap.lastCommandAtom, decodedCmd);
|
||||
const isCC = isClaudeCodeCommand(decodedCmd);
|
||||
globalStore.set(termWrap.claudeCodeActiveAtom, isCC);
|
||||
checkCommandForTelemetry(decodedCmd);
|
||||
} catch (e) {
|
||||
console.error("Error decoding cmd64:", e);
|
||||
rtInfo["shell:lastcmd"] = null;
|
||||
globalStore.set(termWrap.lastCommandAtom, null);
|
||||
globalStore.set(termWrap.claudeCodeActiveAtom, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rtInfo["shell:lastcmd"] = null;
|
||||
globalStore.set(termWrap.lastCommandAtom, null);
|
||||
globalStore.set(termWrap.claudeCodeActiveAtom, false);
|
||||
}
|
||||
rtInfo["shell:lastcmdexitcode"] = null;
|
||||
}
|
||||
|
|
@ -287,6 +308,7 @@ export function handleOsc16162Command(data: string, blockId: string, loaded: boo
|
|||
case "A": {
|
||||
rtInfo["shell:state"] = "ready";
|
||||
globalStore.set(termWrap.shellIntegrationStatusAtom, "ready");
|
||||
globalStore.set(termWrap.claudeCodeActiveAtom, false);
|
||||
const marker = terminal.registerMarker(0);
|
||||
if (marker) {
|
||||
termWrap.promptMarkers.push(marker);
|
||||
|
|
@ -324,6 +346,7 @@ export function handleOsc16162Command(data: string, blockId: string, loaded: boo
|
|||
}
|
||||
break;
|
||||
case "D":
|
||||
globalStore.set(termWrap.claudeCodeActiveAtom, false);
|
||||
if (cmd.data.exitcode != null) {
|
||||
rtInfo["shell:lastcmdexitcode"] = cmd.data.exitcode;
|
||||
} else {
|
||||
|
|
@ -337,6 +360,7 @@ export function handleOsc16162Command(data: string, blockId: string, loaded: boo
|
|||
break;
|
||||
case "R":
|
||||
globalStore.set(termWrap.shellIntegrationStatusAtom, null);
|
||||
globalStore.set(termWrap.claudeCodeActiveAtom, false);
|
||||
if (terminal.buffer.active.type === "alternate") {
|
||||
terminal.write("\x1b[?1049l");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { waveEventSubscribeSingle } from "@/app/store/wps";
|
|||
import { RpcApi } from "@/app/store/wshclientapi";
|
||||
import { makeFeBlockRouteId } from "@/app/store/wshrouter";
|
||||
import { DefaultRouter, TabRpcClient } from "@/app/store/wshrpcutil";
|
||||
import { TerminalView } from "@/app/view/term/term";
|
||||
import { TermClaudeIcon, TerminalView } from "@/app/view/term/term";
|
||||
import { TermWshClient } from "@/app/view/term/term-wsh";
|
||||
import { VDomModel } from "@/app/view/vdom/vdom-model";
|
||||
import { WorkspaceLayoutModel } from "@/app/workspace/workspace-layout-model";
|
||||
|
|
@ -404,10 +404,12 @@ export class TermViewModel implements ViewModel {
|
|||
return null;
|
||||
}
|
||||
const shellIntegrationStatus = get(this.termRef.current.shellIntegrationStatusAtom);
|
||||
const claudeCodeActive = get(this.termRef.current.claudeCodeActiveAtom);
|
||||
const icon = claudeCodeActive ? React.createElement(TermClaudeIcon) : "sparkles";
|
||||
if (shellIntegrationStatus == null) {
|
||||
return {
|
||||
elemtype: "iconbutton",
|
||||
icon: "sparkles",
|
||||
icon,
|
||||
className: "text-muted",
|
||||
title: "No shell integration — Wave AI unable to run commands.",
|
||||
noAction: true,
|
||||
|
|
@ -416,14 +418,16 @@ export class TermViewModel implements ViewModel {
|
|||
if (shellIntegrationStatus === "ready") {
|
||||
return {
|
||||
elemtype: "iconbutton",
|
||||
icon: "sparkles",
|
||||
icon,
|
||||
className: "text-accent",
|
||||
title: "Shell ready — Wave AI can run commands in this terminal.",
|
||||
noAction: true,
|
||||
};
|
||||
}
|
||||
if (shellIntegrationStatus === "running-command") {
|
||||
let title = "Shell busy — Wave AI unable to run commands while another command is running.";
|
||||
let title = claudeCodeActive
|
||||
? "Claude Code Detected"
|
||||
: "Shell busy — Wave AI unable to run commands while another command is running.";
|
||||
|
||||
if (this.termRef.current) {
|
||||
const inAltBuffer = this.termRef.current.terminal?.buffer?.active?.type === "alternate";
|
||||
|
|
@ -436,7 +440,7 @@ export class TermViewModel implements ViewModel {
|
|||
|
||||
return {
|
||||
elemtype: "iconbutton",
|
||||
icon: "sparkles",
|
||||
icon,
|
||||
className: "text-warning",
|
||||
title: title,
|
||||
noAction: true,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright 2025, Command Line Inc.
|
||||
// Copyright 2026, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import ClaudeColorSvg from "@/app/asset/claude-color.svg";
|
||||
import { SubBlock } from "@/app/block/block";
|
||||
import type { BlockNodeModel } from "@/app/block/blocktypes";
|
||||
import { NullErrorBoundary } from "@/app/element/errorboundary";
|
||||
|
|
@ -34,6 +35,16 @@ interface TerminalViewProps {
|
|||
model: TermViewModel;
|
||||
}
|
||||
|
||||
const TermClaudeIcon = React.memo(() => {
|
||||
return (
|
||||
<div className="[&_svg]:w-[15px] [&_svg]:h-[15px]" aria-hidden="true">
|
||||
<ClaudeColorSvg />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
TermClaudeIcon.displayName = "TermClaudeIcon";
|
||||
|
||||
const TermResyncHandler = React.memo(({ blockId, model }: TerminalViewProps) => {
|
||||
const connStatus = jotai.useAtomValue(model.connStatus);
|
||||
const [lastConnStatus, setLastConnStatus] = React.useState<ConnStatus>(connStatus);
|
||||
|
|
@ -61,7 +72,7 @@ const TermVDomToolbarNode = ({ vdomBlockId, blockId, model }: TerminalViewProps
|
|||
const unsub = waveEventSubscribeSingle({
|
||||
eventType: "blockclose",
|
||||
scope: WOS.makeORef("block", vdomBlockId),
|
||||
handler: (event) => {
|
||||
handler: (_event) => {
|
||||
RpcApi.SetMetaCommand(TabRpcClient, {
|
||||
oref: WOS.makeORef("block", blockId),
|
||||
meta: {
|
||||
|
|
@ -104,7 +115,7 @@ const TermVDomNodeSingleId = ({ vdomBlockId, blockId, model }: TerminalViewProps
|
|||
const unsub = waveEventSubscribeSingle({
|
||||
eventType: "blockclose",
|
||||
scope: WOS.makeORef("block", vdomBlockId),
|
||||
handler: (event) => {
|
||||
handler: (_event) => {
|
||||
RpcApi.SetMetaCommand(TabRpcClient, {
|
||||
oref: WOS.makeORef("block", blockId),
|
||||
meta: {
|
||||
|
|
@ -390,4 +401,4 @@ const TerminalView = ({ blockId, model }: ViewComponentProps<TermViewModel>) =>
|
|||
);
|
||||
};
|
||||
|
||||
export { TerminalView };
|
||||
export { TermClaudeIcon, TerminalView };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2025, Command Line Inc.
|
||||
// Copyright 2026, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { BlockNodeModel } from "@/app/block/blocktypes";
|
||||
|
|
@ -32,6 +32,7 @@ import {
|
|||
handleOsc16162Command,
|
||||
handleOsc52Command,
|
||||
handleOsc7Command,
|
||||
isClaudeCodeCommand,
|
||||
type ShellIntegrationStatus,
|
||||
} from "./osc-handlers";
|
||||
import { bufferLinesToText, createTempFileFromBlob, extractAllClipboardData, normalizeCursorStyle } from "./termutil";
|
||||
|
|
@ -92,6 +93,7 @@ export class TermWrap {
|
|||
promptMarkers: TermTypes.IMarker[] = [];
|
||||
shellIntegrationStatusAtom: jotai.PrimitiveAtom<ShellIntegrationStatus | null>;
|
||||
lastCommandAtom: jotai.PrimitiveAtom<string | null>;
|
||||
claudeCodeActiveAtom: jotai.PrimitiveAtom<boolean>;
|
||||
nodeModel: BlockNodeModel; // this can be null
|
||||
hoveredLinkUri: string | null = null;
|
||||
onLinkHover?: (uri: string | null, mouseX: number, mouseY: number) => void;
|
||||
|
|
@ -131,6 +133,7 @@ export class TermWrap {
|
|||
this.promptMarkers = [];
|
||||
this.shellIntegrationStatusAtom = jotai.atom(null) as jotai.PrimitiveAtom<ShellIntegrationStatus | null>;
|
||||
this.lastCommandAtom = jotai.atom(null) as jotai.PrimitiveAtom<string | null>;
|
||||
this.claudeCodeActiveAtom = jotai.atom(false);
|
||||
this.webglEnabledAtom = jotai.atom(false) as jotai.PrimitiveAtom<boolean>;
|
||||
this.terminal = new Terminal(options);
|
||||
this.fitAddon = new FitAddon();
|
||||
|
|
@ -171,16 +174,34 @@ export class TermWrap {
|
|||
this.setTermRenderer(WebGLSupported && waveOptions.useWebGl ? "webgl" : "dom");
|
||||
// Register OSC handlers
|
||||
this.terminal.parser.registerOscHandler(7, (data: string) => {
|
||||
return handleOsc7Command(data, this.blockId, this.loaded);
|
||||
try {
|
||||
return handleOsc7Command(data, this.blockId, this.loaded);
|
||||
} catch (e) {
|
||||
console.error("[termwrap] osc 7 handler error", this.blockId, e);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this.terminal.parser.registerOscHandler(52, (data: string) => {
|
||||
return handleOsc52Command(data, this.blockId, this.loaded, this);
|
||||
try {
|
||||
return handleOsc52Command(data, this.blockId, this.loaded, this);
|
||||
} catch (e) {
|
||||
console.error("[termwrap] osc 52 handler error", this.blockId, e);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this.terminal.parser.registerOscHandler(16162, (data: string) => {
|
||||
return handleOsc16162Command(data, this.blockId, this.loaded, this);
|
||||
try {
|
||||
return handleOsc16162Command(data, this.blockId, this.loaded, this);
|
||||
} catch (e) {
|
||||
console.error("[termwrap] osc 16162 handler error", this.blockId, e);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this.toDispose.push(
|
||||
this.terminal.parser.registerCsiHandler({ final: "J" }, (params) => {
|
||||
if (params == null || params.length < 1) {
|
||||
return false;
|
||||
}
|
||||
if (params[0] === 3) {
|
||||
this.lastClearScrollbackTs = Date.now();
|
||||
if (this.inSyncTransaction) {
|
||||
|
|
@ -193,6 +214,9 @@ export class TermWrap {
|
|||
);
|
||||
this.toDispose.push(
|
||||
this.terminal.parser.registerCsiHandler({ prefix: "?", final: "h" }, (params) => {
|
||||
if (params == null || params.length < 1) {
|
||||
return false;
|
||||
}
|
||||
if (params[0] === 2026) {
|
||||
this.lastMode2026SetTs = Date.now();
|
||||
this.inSyncTransaction = true;
|
||||
|
|
@ -202,6 +226,9 @@ export class TermWrap {
|
|||
);
|
||||
this.toDispose.push(
|
||||
this.terminal.parser.registerCsiHandler({ prefix: "?", final: "l" }, (params) => {
|
||||
if (params == null || params.length < 1) {
|
||||
return false;
|
||||
}
|
||||
if (params[0] === 2026) {
|
||||
this.lastMode2026ResetTs = Date.now();
|
||||
this.inSyncTransaction = false;
|
||||
|
|
@ -345,16 +372,19 @@ export class TermWrap {
|
|||
const rtInfo = await RpcApi.GetRTInfoCommand(TabRpcClient, {
|
||||
oref: WOS.makeORef("block", this.blockId),
|
||||
});
|
||||
let shellState: ShellIntegrationStatus = null;
|
||||
|
||||
if (rtInfo && rtInfo["shell:integration"]) {
|
||||
const shellState = rtInfo["shell:state"] as ShellIntegrationStatus;
|
||||
shellState = rtInfo["shell:state"] as ShellIntegrationStatus;
|
||||
globalStore.set(this.shellIntegrationStatusAtom, shellState || null);
|
||||
} else {
|
||||
globalStore.set(this.shellIntegrationStatusAtom, null);
|
||||
}
|
||||
|
||||
const lastCmd = rtInfo ? rtInfo["shell:lastcmd"] : null;
|
||||
const isCC = shellState === "running-command" && isClaudeCodeCommand(lastCmd);
|
||||
globalStore.set(this.lastCommandAtom, lastCmd || null);
|
||||
globalStore.set(this.claudeCodeActiveAtom, isCC);
|
||||
} catch (e) {
|
||||
console.log("Error loading runtime info:", e);
|
||||
}
|
||||
|
|
@ -371,7 +401,9 @@ export class TermWrap {
|
|||
this.promptMarkers.forEach((marker) => {
|
||||
try {
|
||||
marker.dispose();
|
||||
} catch (_) {}
|
||||
} catch (_) {
|
||||
/* nothing */
|
||||
}
|
||||
});
|
||||
this.promptMarkers = [];
|
||||
this.webglContextLossDisposable?.dispose();
|
||||
|
|
@ -380,7 +412,9 @@ export class TermWrap {
|
|||
this.toDispose.forEach((d) => {
|
||||
try {
|
||||
d.dispose();
|
||||
} catch (_) {}
|
||||
} catch (_) {
|
||||
/* nothing */
|
||||
}
|
||||
});
|
||||
this.mainFileSubject.release();
|
||||
}
|
||||
|
|
|
|||
80
package-lock.json
generated
80
package-lock.json
generated
|
|
@ -5434,32 +5434,32 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
|
||||
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
|
||||
"integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/utils": "^0.2.10"
|
||||
"@floating-ui/utils": "^0.2.11"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
|
||||
"integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
|
||||
"version": "1.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
|
||||
"integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.7.3",
|
||||
"@floating-ui/utils": "^0.2.10"
|
||||
"@floating-ui/core": "^1.7.5",
|
||||
"@floating-ui/utils": "^0.2.11"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/react": {
|
||||
"version": "0.27.16",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.16.tgz",
|
||||
"integrity": "sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g==",
|
||||
"version": "0.27.19",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.19.tgz",
|
||||
"integrity": "sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react-dom": "^2.1.6",
|
||||
"@floating-ui/utils": "^0.2.10",
|
||||
"@floating-ui/react-dom": "^2.1.8",
|
||||
"@floating-ui/utils": "^0.2.11",
|
||||
"tabbable": "^6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
@ -5468,12 +5468,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@floating-ui/react-dom": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz",
|
||||
"integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
|
||||
"integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.7.4"
|
||||
"@floating-ui/dom": "^1.7.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
|
|
@ -5481,9 +5481,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@floating-ui/utils": {
|
||||
"version": "0.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
|
||||
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
|
||||
"version": "0.2.11",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
|
||||
"integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@hapi/hoek": {
|
||||
|
|
@ -15182,9 +15182,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "10.5.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz",
|
||||
"integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==",
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
|
||||
"integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/emojilib": {
|
||||
|
|
@ -15353,9 +15353,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/es-toolkit": {
|
||||
"version": "1.39.10",
|
||||
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.10.tgz",
|
||||
"integrity": "sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w==",
|
||||
"version": "1.45.1",
|
||||
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.45.1.tgz",
|
||||
"integrity": "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"docs",
|
||||
|
|
@ -18948,9 +18948,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/katex": {
|
||||
"version": "0.16.22",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz",
|
||||
"integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==",
|
||||
"version": "0.16.38",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.38.tgz",
|
||||
"integrity": "sha512-cjHooZUmIAUmDsHBN+1n8LaZdpmbj03LtYeYPyuYB7OuloiaeaV6N4LcfjcnHVzGWjVQmKrxxTrpDcmSzEZQwQ==",
|
||||
"funding": [
|
||||
"https://opencollective.com/katex",
|
||||
"https://github.com/sponsors/katex"
|
||||
|
|
@ -29918,13 +29918,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/swr": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/swr/-/swr-2.3.6.tgz",
|
||||
"integrity": "sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw==",
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/swr/-/swr-2.4.1.tgz",
|
||||
"integrity": "sha512-2CC6CiKQtEwaEeNiqWTAw9PGykW8SR5zZX8MZk6TeAvEAnVS7Visz8WzphqgtQ8v2xz/4Q5K+j+SeMaKXeeQIA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dequal": "^2.0.3",
|
||||
"use-sync-external-store": "^1.4.0"
|
||||
"use-sync-external-store": "^1.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
|
|
@ -29947,9 +29947,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/tabbable": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
|
||||
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz",
|
||||
"integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tailwind-merge": {
|
||||
|
|
@ -31867,9 +31867,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/use-sync-external-store": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
|
||||
"integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
|
||||
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
|
|
|
|||
Loading…
Reference in a new issue