mirror of
https://github.com/cline/cline.git
synced 2026-09-05 05:02:27 +08:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f7cc4907f | |||
| 27e3541569 | |||
| ae9c5b4d9d | |||
| f86ca6b36b | |||
| 0e0b11032e | |||
| a93d850aee | |||
| fe25258b0d | |||
| 53d1567731 | |||
| 9a93008463 | |||
| 678b0ae951 | |||
| 8b6f2cf0b7 | |||
| 25ef0939cc | |||
| 4f770011e9 | |||
| a1d69fee6f | |||
| 3575b38122 | |||
| b5468e1227 | |||
| 10d1c41b7a | |||
| b823358867 | |||
| b876945c6d |
@@ -149,7 +149,7 @@ Toggle between Plan mode and Act mode. In Plan mode, Cline explores your codebas
|
||||
|
||||
## Rules and Skills
|
||||
|
||||
Define project-specific rules in `.clinerules` files that guide how Cline works in your codebase: coding standards, architecture conventions, deployment procedures, testing requirements. Rules are picked up automatically by the CLI, VS Code extension, and JetBrains plugin. Use skills to let the model load specific rules when needed.
|
||||
Define project-specific rules in `.clinerules` files that guide how Cline works in your codebase: coding standards, architecture conventions, deployment procedures, testing requirements. Rules are picked up automatically by the CLI, VS Code extension, and JetBrains plugin. Use skills to let the model load specific rules when needed.
|
||||
|
||||
## Works With Every Model
|
||||
|
||||
@@ -158,10 +158,10 @@ Cline is not locked to a single AI provider. Use whichever model fits your workf
|
||||
| Provider | Models |
|
||||
|----------|--------|
|
||||
| Anthropic | Claude Opus, Sonnet, Haiku |
|
||||
| OpenAI | GPT series model |
|
||||
| Google | Gemini series model |
|
||||
| OpenAI | GPT series models |
|
||||
| Google | Gemini series models |
|
||||
| OpenRouter | 200+ models from any provider |
|
||||
| Vercel AI Gateway | Models through Vercel AI Gateway |
|
||||
| Vercel AI Gateway | Route to many providers through one gateway |
|
||||
| AWS Bedrock | Claude, Llama, and more |
|
||||
| Azure / GCP Vertex | All hosted models |
|
||||
| Cerebras / Groq | Fast inference models |
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
# Cline CLI Changelog
|
||||
|
||||
## 3.0.38
|
||||
|
||||
- New plan/act accent palette: act mode is now blue (`#79b8ff`) and plan mode amber, replacing the old cyan/yellow — applied across dialogs, the model selector, config, onboarding, markdown, and syntax highlighting, with light-theme variants tuned for contrast
|
||||
- Restyled chat input: a minimal frame with full-width horizontal rules and a bold accent prompt glyph instead of the tinted background, plus slimmer user-message bubbles
|
||||
- Assistant markdown accents are now tinted by the mode (plan/act) they were produced in
|
||||
- Polished the status bar usage display and ClinePass model name
|
||||
- Harmonized the success/diff green and dark syntax-highlighting colors with the new brand palette
|
||||
- The thinking-level picker now defaults its cursor to Medium instead of Off
|
||||
- `read_files` now tolerates malformed input from weaker models: line-range entries (`start_line`/`end_line`) sent as separate array items are coalesced back onto the preceding file path instead of being rejected (from SDK v0.0.58)
|
||||
- Models in the live catalog that don't report a context window now default to a 128K input-token limit, so under-specified models get a usable context budget (from SDK v0.0.57)
|
||||
|
||||
## 3.0.37
|
||||
|
||||
- Weaker models (e.g. DeepSeek) that emit malformed tool calls — wrong argument types or truncated JSON — are now handled gracefully and run instead of erroring out
|
||||
- Plan/act mode switches are now visible to the model, so it knows when you change modes mid-session
|
||||
- Fixed plan/act mode notices being dropped from prompts sent to the model
|
||||
- Fixed a race where switching modes in an empty session could trigger an unexpected restart
|
||||
|
||||
## 3.0.36
|
||||
|
||||
- Fixed plan mode's `switch_to_act_mode` tool not taking effect until the end of the turn: the model would keep running with plan-mode tools (no file editor) and fall back to editing files through shell commands. Switching to act mode now ends the plan-mode run and automatically continues with the approved plan using the full act-mode toolset. A Tab mode toggle racing a completing turn can no longer auto-start plan execution you didn't approve.
|
||||
|
||||
## 3.0.35
|
||||
|
||||
- ClinePass is now enabled for all CLI users
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@cline/cli",
|
||||
"displayName": "cline",
|
||||
"version": "3.0.35",
|
||||
"version": "3.0.38",
|
||||
"description": "Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -2,7 +2,15 @@ import { createTool } from "@cline/shared";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { Config } from "../../utils/types";
|
||||
import { resolveSystemPrompt } from "../prompt";
|
||||
import { applyInteractiveModeConfig } from "./mode";
|
||||
import {
|
||||
ACT_MODE_CONTINUATION_PROMPT,
|
||||
type AppliedModeChange,
|
||||
applyInteractiveModeConfig,
|
||||
createInteractiveModeSwitchTool,
|
||||
createModeSwitchNoticeTracker,
|
||||
type PendingModeChange,
|
||||
sendTurnWithActModeContinuation,
|
||||
} from "./mode";
|
||||
|
||||
vi.mock("../prompt", () => ({
|
||||
resolveSystemPrompt: vi.fn(async (input: { mode?: string }) => {
|
||||
@@ -40,6 +48,190 @@ const switchToActModeTool = createTool({
|
||||
execute: async () => "ok",
|
||||
});
|
||||
|
||||
describe("createInteractiveModeSwitchTool", () => {
|
||||
function makeSwitchTool(config: Config) {
|
||||
const pendingModeChange: PendingModeChange = {
|
||||
current: null,
|
||||
source: null,
|
||||
};
|
||||
const tuiModeChanged: {
|
||||
current: ((mode: "plan" | "act") => void) | null;
|
||||
} = { current: vi.fn() };
|
||||
const tool = createInteractiveModeSwitchTool({
|
||||
config,
|
||||
pendingModeChange,
|
||||
tuiModeChanged,
|
||||
});
|
||||
return { tool, pendingModeChange, tuiModeChanged };
|
||||
}
|
||||
|
||||
const toolContext = {
|
||||
agentId: "agent-1",
|
||||
iteration: 0,
|
||||
} as const;
|
||||
|
||||
it("completes the run so the model never continues with plan-mode tools", () => {
|
||||
const config = makeConfig();
|
||||
config.mode = "plan";
|
||||
const { tool } = makeSwitchTool(config);
|
||||
|
||||
// The act-mode tool set only exists after the session rebuild, which
|
||||
// happens between runs; without completesRun the model keeps working
|
||||
// with stale plan-mode tools after being told the switch succeeded.
|
||||
expect(tool.lifecycle?.completesRun).toBe(true);
|
||||
});
|
||||
|
||||
it("queues a tool-sourced mode change and notifies the TUI", async () => {
|
||||
const config = makeConfig();
|
||||
config.mode = "plan";
|
||||
const { tool, pendingModeChange, tuiModeChanged } = makeSwitchTool(config);
|
||||
|
||||
const result = await tool.execute({}, toolContext);
|
||||
|
||||
expect(pendingModeChange).toEqual({ current: "act", source: "tool" });
|
||||
expect(tuiModeChanged.current).toHaveBeenCalledWith("act");
|
||||
expect(result).toContain("successfully switched to act mode");
|
||||
});
|
||||
|
||||
it("errors instead of completing the run when already in act mode", async () => {
|
||||
const config = makeConfig();
|
||||
config.mode = "act";
|
||||
const { tool, pendingModeChange } = makeSwitchTool(config);
|
||||
|
||||
// A successful result would end the run via completesRun even though
|
||||
// nothing changed, so the no-op case must surface as a tool error.
|
||||
await expect(tool.execute({}, toolContext)).rejects.toThrow(
|
||||
"Already in act mode.",
|
||||
);
|
||||
expect(pendingModeChange.current).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("sendTurnWithActModeContinuation", () => {
|
||||
type TurnResult = { finishReason: string; iterations: number };
|
||||
|
||||
function makeHarness(input: {
|
||||
initial: TurnResult | undefined;
|
||||
continuation?: TurnResult | undefined;
|
||||
modeChanges: Array<AppliedModeChange | undefined>;
|
||||
}) {
|
||||
const applied = [...input.modeChanges];
|
||||
const sendContinuationTurn = vi.fn(async () => input.continuation);
|
||||
return {
|
||||
sendContinuationTurn,
|
||||
run: () =>
|
||||
sendTurnWithActModeContinuation<TurnResult>({
|
||||
sendInitialTurn: async () => input.initial,
|
||||
sendContinuationTurn,
|
||||
applyPendingModeChange: async () => applied.shift(),
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
it("continues the plan after a tool-initiated switch completes the run", async () => {
|
||||
const { run, sendContinuationTurn } = makeHarness({
|
||||
initial: { finishReason: "completed", iterations: 2 },
|
||||
continuation: { finishReason: "completed", iterations: 3 },
|
||||
modeChanges: [{ mode: "act", source: "tool" }, undefined],
|
||||
});
|
||||
|
||||
const result = await run();
|
||||
|
||||
expect(sendContinuationTurn).toHaveBeenCalledWith(
|
||||
ACT_MODE_CONTINUATION_PROMPT,
|
||||
);
|
||||
expect(result).toEqual({ finishReason: "completed", iterations: 5 });
|
||||
});
|
||||
|
||||
it("does not continue after a UI-initiated mode change", async () => {
|
||||
// A Tab toggle can race a natural turn completion; a "ui" source must
|
||||
// never start executing a plan the user did not approve.
|
||||
const { run, sendContinuationTurn } = makeHarness({
|
||||
initial: { finishReason: "completed", iterations: 2 },
|
||||
modeChanges: [{ mode: "act", source: "ui" }],
|
||||
});
|
||||
|
||||
const result = await run();
|
||||
|
||||
expect(sendContinuationTurn).not.toHaveBeenCalled();
|
||||
expect(result).toEqual({ finishReason: "completed", iterations: 2 });
|
||||
});
|
||||
|
||||
it("does not continue when the switch turn was aborted", async () => {
|
||||
const { run, sendContinuationTurn } = makeHarness({
|
||||
initial: { finishReason: "aborted", iterations: 1 },
|
||||
modeChanges: [{ mode: "act", source: "tool" }],
|
||||
});
|
||||
|
||||
const result = await run();
|
||||
|
||||
expect(sendContinuationTurn).not.toHaveBeenCalled();
|
||||
expect(result).toEqual({ finishReason: "aborted", iterations: 1 });
|
||||
});
|
||||
|
||||
it("does not continue when no mode change was pending", async () => {
|
||||
const { run, sendContinuationTurn } = makeHarness({
|
||||
initial: { finishReason: "completed", iterations: 2 },
|
||||
modeChanges: [undefined],
|
||||
});
|
||||
|
||||
const result = await run();
|
||||
|
||||
expect(sendContinuationTurn).not.toHaveBeenCalled();
|
||||
expect(result).toEqual({ finishReason: "completed", iterations: 2 });
|
||||
});
|
||||
|
||||
it("returns the switch turn result when the continuation yields nothing", async () => {
|
||||
const { run } = makeHarness({
|
||||
initial: { finishReason: "completed", iterations: 2 },
|
||||
continuation: undefined,
|
||||
modeChanges: [{ mode: "act", source: "tool" }, undefined],
|
||||
});
|
||||
|
||||
const result = await run();
|
||||
|
||||
expect(result).toEqual({ finishReason: "completed", iterations: 2 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("createModeSwitchNoticeTracker", () => {
|
||||
it("records a switch and clears it on consume", () => {
|
||||
const tracker = createModeSwitchNoticeTracker();
|
||||
|
||||
tracker.record("act", "plan");
|
||||
|
||||
expect(tracker.consume()).toEqual({ from: "act", to: "plan" });
|
||||
expect(tracker.consume()).toBeNull();
|
||||
});
|
||||
|
||||
it("cancels a round trip that returns to the mode the model last saw", () => {
|
||||
const tracker = createModeSwitchNoticeTracker();
|
||||
|
||||
tracker.record("act", "plan");
|
||||
tracker.record("plan", "act");
|
||||
|
||||
expect(tracker.consume()).toBeNull();
|
||||
});
|
||||
|
||||
it("keeps the original starting mode across chained switches", () => {
|
||||
const tracker = createModeSwitchNoticeTracker();
|
||||
|
||||
tracker.record("act", "plan");
|
||||
tracker.record("plan", "act");
|
||||
tracker.record("act", "plan");
|
||||
|
||||
expect(tracker.consume()).toEqual({ from: "act", to: "plan" });
|
||||
});
|
||||
|
||||
it("ignores a no-op switch", () => {
|
||||
const tracker = createModeSwitchNoticeTracker();
|
||||
|
||||
tracker.record("plan", "plan");
|
||||
|
||||
expect(tracker.consume()).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("applyInteractiveModeConfig", () => {
|
||||
beforeEach(() => {
|
||||
vi.mocked(resolveSystemPrompt).mockClear();
|
||||
|
||||
@@ -2,17 +2,42 @@ import { createTool } from "@cline/shared";
|
||||
import type { Config } from "../../utils/types";
|
||||
import { resolveSystemPrompt } from "../prompt";
|
||||
|
||||
type InteractiveUiMode = "plan" | "act";
|
||||
export type InteractiveUiMode = "plan" | "act";
|
||||
|
||||
/**
|
||||
* Pending mode change plus who requested it. The switch_to_act_mode tool and
|
||||
* the TUI mode toggle share this slot, but only a tool-initiated switch means
|
||||
* "the user approved the plan" -- a UI toggle that lands as a turn finishes
|
||||
* must not trigger plan execution.
|
||||
*/
|
||||
export type PendingModeChange = {
|
||||
current: InteractiveUiMode | null;
|
||||
source: "tool" | "ui" | null;
|
||||
};
|
||||
|
||||
export type AppliedModeChange = {
|
||||
mode: InteractiveUiMode;
|
||||
source: "tool" | "ui";
|
||||
};
|
||||
|
||||
/**
|
||||
* Canned prompt that drives the auto-continue turn after the model calls
|
||||
* switch_to_act_mode. It is a synthetic user message, so transcript hydration
|
||||
* filters it out of the chat display.
|
||||
*/
|
||||
export const ACT_MODE_CONTINUATION_PROMPT =
|
||||
"The user approved switching to act mode. Continue with the approved plan now.";
|
||||
|
||||
export function createInteractiveModeSwitchTool(input: {
|
||||
config: Config;
|
||||
pendingModeChange: { current: InteractiveUiMode | null };
|
||||
pendingModeChange: PendingModeChange;
|
||||
tuiModeChanged: { current: ((mode: InteractiveUiMode) => void) | null };
|
||||
}) {
|
||||
return createTool({
|
||||
name: "switch_to_act_mode",
|
||||
description:
|
||||
"Switch from plan mode to act mode. Call this after the user has confirmed they want to proceed with the plan. Do not call this proactively or before the user has agreed.",
|
||||
"Switch from plan mode to act mode. Switching to act mode immediately starts executing the plan, so only call this after the user has explicitly approved the plan in a message sent AFTER you presented it (e.g. 'looks good', 'go ahead', 'switch to act mode'). " +
|
||||
"Never call this in the same turn you present a plan, never call it proactively, and never treat the original task request as approval.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
@@ -20,17 +45,101 @@ export function createInteractiveModeSwitchTool(input: {
|
||||
timeoutMs: 5000,
|
||||
retryable: false,
|
||||
maxRetries: 0,
|
||||
// The act-mode tools only exist after the session is rebuilt with the
|
||||
// new mode config, which can't happen mid-run. End the run right after
|
||||
// the tool result so the model never keeps working with plan-mode tools
|
||||
// it was just told it no longer has; run-interactive applies the pending
|
||||
// change and auto-continues on the rebuilt session.
|
||||
lifecycle: {
|
||||
completesRun: true,
|
||||
},
|
||||
execute: async () => {
|
||||
if (input.config.mode === "act") {
|
||||
return "Already in act mode.";
|
||||
// Throw instead of returning: a successful result would end the
|
||||
// run via completesRun even though nothing changed.
|
||||
throw new Error("Already in act mode.");
|
||||
}
|
||||
input.pendingModeChange.current = "act";
|
||||
input.pendingModeChange.source = "tool";
|
||||
input.tuiModeChanged.current?.("act");
|
||||
return "You successfully switched to act mode, proceed with the plan. You now have access to editing files and running commands. (The switch_to_act_mode tool is only available in plan mode.)";
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs one interactive turn, and when the model ended it by calling
|
||||
* switch_to_act_mode, continues the approved plan on the rebuilt act-mode
|
||||
* session instead of waiting for the user to prompt again.
|
||||
*
|
||||
* The continuation only fires for a tool-initiated switch on a turn that
|
||||
* finished "completed": a UI toggle mid-run aborts the turn, and even if the
|
||||
* toggle races a natural completion its source is "ui", so the user's Tab
|
||||
* press can never start executing a plan they did not approve.
|
||||
*/
|
||||
export async function sendTurnWithActModeContinuation<
|
||||
T extends { finishReason: string; iterations: number },
|
||||
>(input: {
|
||||
sendInitialTurn: () => Promise<T | undefined>;
|
||||
sendContinuationTurn: (prompt: string) => Promise<T | undefined>;
|
||||
applyPendingModeChange: () => Promise<AppliedModeChange | undefined>;
|
||||
}): Promise<T | undefined> {
|
||||
const result = await input.sendInitialTurn();
|
||||
const switched = await input.applyPendingModeChange();
|
||||
if (
|
||||
switched?.mode !== "act" ||
|
||||
switched.source !== "tool" ||
|
||||
result?.finishReason !== "completed"
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
const continuation = await input.sendContinuationTurn(
|
||||
ACT_MODE_CONTINUATION_PROMPT,
|
||||
);
|
||||
// Honor a mode toggle made while the continuation was running.
|
||||
await input.applyPendingModeChange();
|
||||
if (!continuation) {
|
||||
return result;
|
||||
}
|
||||
return {
|
||||
...continuation,
|
||||
iterations: result.iterations + continuation.iterations,
|
||||
};
|
||||
}
|
||||
|
||||
export type ModeSwitchNotice = {
|
||||
from: InteractiveUiMode;
|
||||
to: InteractiveUiMode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tracks a user-initiated mode switch so the next user message can carry a
|
||||
* <mode_notice> marking it. Only UI toggles are recorded: the model-initiated
|
||||
* switch_to_act_mode path already announces itself via the continuation
|
||||
* prompt. A round trip (plan -> act -> plan before sending anything) cancels
|
||||
* out, since the mode the model last saw never effectively changed.
|
||||
*/
|
||||
export function createModeSwitchNoticeTracker() {
|
||||
let pending: ModeSwitchNotice | null = null;
|
||||
return {
|
||||
record(from: InteractiveUiMode, to: InteractiveUiMode): void {
|
||||
if (from === to) {
|
||||
return;
|
||||
}
|
||||
if (pending) {
|
||||
pending = pending.from === to ? null : { from: pending.from, to };
|
||||
return;
|
||||
}
|
||||
pending = { from, to };
|
||||
},
|
||||
consume(): ModeSwitchNotice | null {
|
||||
const notice = pending;
|
||||
pending = null;
|
||||
return notice;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function applyInteractiveModeConfig(input: {
|
||||
config: Config;
|
||||
mode: InteractiveUiMode;
|
||||
|
||||
@@ -210,6 +210,40 @@ describe("createInteractiveSessionRuntime", () => {
|
||||
expect(runtime.getActiveSessionId()).toBe("session-2");
|
||||
});
|
||||
|
||||
it("holds concurrent ensureReady during a restart instead of booting an empty session", async () => {
|
||||
const manager = makeManager();
|
||||
const runtime = makeRuntime(manager);
|
||||
|
||||
await runtime.ensureReady();
|
||||
expect(runtime.getActiveSessionId()).toBe("session-1");
|
||||
|
||||
// Keep the replacement session's start in flight so the restart window
|
||||
// (old session stopped, no active session yet) stays open.
|
||||
const gate = deferred<void>();
|
||||
manager.start.mockImplementationOnce(async () => {
|
||||
await gate.promise;
|
||||
return {
|
||||
sessionId: "session-restarted",
|
||||
manifest: { session_id: "session-restarted" },
|
||||
};
|
||||
});
|
||||
|
||||
const restart = runtime.restartWithCurrentMessages();
|
||||
await vi.waitFor(() => {
|
||||
expect(manager.start).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
// A message submitted mid-restart (e.g. right after a plan/act toggle)
|
||||
// calls ensureReady; it must wait for the restart instead of booting a
|
||||
// blank session that races the replacement for the active slot.
|
||||
const ready = runtime.ensureReady();
|
||||
gate.resolve();
|
||||
await Promise.all([restart, ready]);
|
||||
|
||||
expect(manager.start).toHaveBeenCalledTimes(2);
|
||||
expect(runtime.getActiveSessionId()).toBe("session-restarted");
|
||||
});
|
||||
|
||||
it("adds a live interactive approval policy hook to started sessions", async () => {
|
||||
const manager = makeManager();
|
||||
const upstreamBeforeTool = vi.fn(async () => ({
|
||||
|
||||
@@ -383,11 +383,31 @@ export function createInteractiveSessionRuntime(input: {
|
||||
): Promise<void> => {
|
||||
sessionStartGeneration += 1;
|
||||
pendingResumeSessionId = undefined;
|
||||
startupPromise = undefined;
|
||||
startupError = undefined;
|
||||
await stopCurrentSession();
|
||||
clearActiveSession();
|
||||
await startFreshSession(messages, sessionMetadata);
|
||||
// Publish the restart as the in-flight startup. Teardown leaves a window
|
||||
// with no active session, and without this barrier a concurrent
|
||||
// ensureReady() (e.g. a message submitted right after a plan/act toggle)
|
||||
// reads that window as "no session" and boots an empty session that then
|
||||
// races the restarted one for the active slot.
|
||||
const restart = (async () => {
|
||||
await stopCurrentSession();
|
||||
clearActiveSession();
|
||||
await startFreshSession(messages, sessionMetadata);
|
||||
})().catch((error) => {
|
||||
startupError = error;
|
||||
throw error;
|
||||
});
|
||||
startupPromise = restart;
|
||||
try {
|
||||
await restart;
|
||||
} finally {
|
||||
// Restore the pre-restart steady state (startupPromise unset) so a
|
||||
// failed restart stays retryable by the next ensureReady(). A newer
|
||||
// startup that already replaced the barrier is left alone.
|
||||
if (startupPromise === restart) {
|
||||
startupPromise = undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const restartWithCurrentMessages = async (): Promise<void> => {
|
||||
|
||||
@@ -9,6 +9,10 @@ import {
|
||||
import { type AgentMode, buildClineSystemPrompt } from "@cline/shared";
|
||||
import { isImagePath, loadImageAsDataUrl } from "../utils/image-attachments";
|
||||
|
||||
const MODE_TAG_INSTRUCTIONS = `# Plan / Act Modes
|
||||
|
||||
User messages arrive wrapped in a <user_input mode="..."> tag. The mode attribute is the interaction mode the user was in when they sent that message: "plan" means plan-mode constraints applied (explore, analyze, and align on a plan -- no edits or state-changing commands), while "act" (or "yolo") means implementation was allowed. If the mode attribute changes between messages, the user switched modes -- the newest message's mode is what governs right now, regardless of what earlier messages allowed. A <mode_notice> block inside a message marks exactly when such a switch happened.`;
|
||||
|
||||
const PLAN_MODE_INSTRUCTIONS = `# Plan Mode
|
||||
|
||||
You are in Plan mode. Your role is to explore, analyze, and plan -- not to execute.
|
||||
@@ -20,7 +24,7 @@ You are in Plan mode. Your role is to explore, analyze, and plan -- not to execu
|
||||
- Do NOT edit files, write code, run destructive commands, or make any changes
|
||||
- Do NOT implement anything -- focus on understanding and alignment first
|
||||
|
||||
When the user aligns on a plan and is ready to proceed, use the switch_to_act_mode tool to switch to act mode and begin implementation.`;
|
||||
Once the user has reviewed your plan and explicitly approved it in a follow-up message, use the switch_to_act_mode tool to switch to act mode and begin implementation. Calling switch_to_act_mode immediately starts execution, so never call it in the same turn you present a plan and never treat the original task request as approval -- end your turn after presenting the plan and wait for the user's response.`;
|
||||
|
||||
export async function resolveSystemPrompt(input: {
|
||||
cwd: string;
|
||||
@@ -31,10 +35,13 @@ export async function resolveSystemPrompt(input: {
|
||||
}): Promise<string> {
|
||||
const metadata = await buildWorkspaceMetadata(input.cwd);
|
||||
let rules = mergeRulesForSystemPrompt(undefined, input.rules);
|
||||
// Both modes get the mode-tag explanation: after a switch, the transcript
|
||||
// still contains messages tagged with the other mode.
|
||||
rules = rules
|
||||
? `${rules}\n\n${MODE_TAG_INSTRUCTIONS}`
|
||||
: MODE_TAG_INSTRUCTIONS;
|
||||
if (input.mode === "plan") {
|
||||
rules = rules
|
||||
? `${rules}\n\n${PLAN_MODE_INSTRUCTIONS}`
|
||||
: PLAN_MODE_INSTRUCTIONS;
|
||||
rules = `${rules}\n\n${PLAN_MODE_INSTRUCTIONS}`;
|
||||
}
|
||||
return buildClineSystemPrompt({
|
||||
ide: "Terminal Shell",
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
ProviderSettingsManager,
|
||||
type UserInstructionConfigService,
|
||||
} from "@cline/core";
|
||||
import { formatModeSwitchNotice } from "@cline/shared";
|
||||
import type { CliMigrationNotice } from "../kanban-migration/notice";
|
||||
import { logCliError } from "../logging/errors";
|
||||
import {
|
||||
@@ -52,7 +53,13 @@ import {
|
||||
type InteractiveExitSummary,
|
||||
} from "./interactive/exit-summary";
|
||||
import { createMistakeLimitDecisionResolver } from "./interactive/mistakes";
|
||||
import { createInteractiveModeSwitchTool } from "./interactive/mode";
|
||||
import {
|
||||
type AppliedModeChange,
|
||||
createInteractiveModeSwitchTool,
|
||||
createModeSwitchNoticeTracker,
|
||||
type PendingModeChange,
|
||||
sendTurnWithActModeContinuation,
|
||||
} from "./interactive/mode";
|
||||
import { assertInteractivePreflight } from "./interactive/preflight";
|
||||
import { createInteractiveSessionRuntime } from "./interactive/session-runtime";
|
||||
import { buildUserInputMessage } from "./prompt";
|
||||
@@ -149,8 +156,9 @@ export async function runInteractive(
|
||||
tuiAskQuestion,
|
||||
} = createInteractiveApprovalController(config);
|
||||
|
||||
const pendingModeChange: { current: "plan" | "act" | null } = {
|
||||
const pendingModeChange: PendingModeChange = {
|
||||
current: null,
|
||||
source: null,
|
||||
};
|
||||
const tuiModeChanged: {
|
||||
current: ((mode: "plan" | "act") => void) | null;
|
||||
@@ -204,6 +212,7 @@ export async function runInteractive(
|
||||
});
|
||||
let modeChangePromise: Promise<void> | undefined;
|
||||
let modeChangeTarget: "plan" | "act" | undefined;
|
||||
const modeSwitchNotice = createModeSwitchNoticeTracker();
|
||||
|
||||
const isInteractiveMode = (mode: unknown): mode is "plan" | "act" =>
|
||||
mode === "plan" || mode === "act";
|
||||
@@ -218,7 +227,11 @@ export async function runInteractive(
|
||||
await modeChangePromise;
|
||||
}
|
||||
await sessionRuntime.ensureReady();
|
||||
const from = config.mode;
|
||||
await sessionRuntime.applyMode(mode);
|
||||
if (isInteractiveMode(from)) {
|
||||
modeSwitchNotice.record(from, mode);
|
||||
}
|
||||
})().finally(() => {
|
||||
if (modeChangePromise === next) {
|
||||
modeChangePromise = undefined;
|
||||
@@ -520,27 +533,50 @@ export async function runInteractive(
|
||||
...(attachments?.userImages ?? []),
|
||||
...userImages,
|
||||
];
|
||||
// Mark a preceding user-initiated mode switch on this message so
|
||||
// the model sees exactly when the rules changed, instead of only
|
||||
// inferring it from the user_input mode attribute flipping.
|
||||
const switchNotice = modeSwitchNotice.consume();
|
||||
const noticedUserInput = switchNotice
|
||||
? `${formatModeSwitchNotice(switchNotice.from, switchNotice.to)}\n${userInput}`
|
||||
: userInput;
|
||||
|
||||
const applyPendingModeChange = async () => {
|
||||
const applyPendingModeChange = async (): Promise<
|
||||
AppliedModeChange | undefined
|
||||
> => {
|
||||
if (!pendingModeChange.current) return undefined;
|
||||
const newMode = pendingModeChange.current;
|
||||
const applied: AppliedModeChange = {
|
||||
mode: pendingModeChange.current,
|
||||
source: pendingModeChange.source ?? "ui",
|
||||
};
|
||||
pendingModeChange.current = null;
|
||||
await sessionRuntime.applyMode(newMode);
|
||||
tuiModeChanged.current?.(newMode);
|
||||
return newMode;
|
||||
pendingModeChange.source = null;
|
||||
const from = config.mode;
|
||||
await sessionRuntime.applyMode(applied.mode);
|
||||
tuiModeChanged.current?.(applied.mode);
|
||||
// The switch_to_act_mode path announces itself through the
|
||||
// continuation prompt; only UI toggles need a notice.
|
||||
if (applied.source === "ui" && isInteractiveMode(from)) {
|
||||
modeSwitchNotice.record(from, applied.mode);
|
||||
}
|
||||
return applied;
|
||||
};
|
||||
|
||||
const result = await sessionRuntime.sendCurrentTurn({
|
||||
prompt: userInput,
|
||||
mode,
|
||||
userImages:
|
||||
mergedUserImages.length > 0 ? mergedUserImages : undefined,
|
||||
userFiles: userFiles.length > 0 ? userFiles : undefined,
|
||||
delivery,
|
||||
const result = await sendTurnWithActModeContinuation({
|
||||
sendInitialTurn: () =>
|
||||
sessionRuntime.sendCurrentTurn({
|
||||
prompt: noticedUserInput,
|
||||
mode,
|
||||
userImages:
|
||||
mergedUserImages.length > 0 ? mergedUserImages : undefined,
|
||||
userFiles: userFiles.length > 0 ? userFiles : undefined,
|
||||
delivery,
|
||||
}),
|
||||
sendContinuationTurn: (prompt) =>
|
||||
sessionRuntime.sendCurrentTurn({ prompt, mode: "act" }),
|
||||
applyPendingModeChange,
|
||||
});
|
||||
|
||||
await applyPendingModeChange();
|
||||
|
||||
if (!result) {
|
||||
return {
|
||||
usage: { inputTokens: 0, outputTokens: 0 },
|
||||
@@ -642,6 +678,7 @@ export async function runInteractive(
|
||||
if (!isInteractiveMode(mode)) return;
|
||||
if (isRunning) {
|
||||
pendingModeChange.current = mode;
|
||||
pendingModeChange.source = "ui";
|
||||
sessionRuntime.abortAll();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
type ContentBlock,
|
||||
formatDisplayUserInput,
|
||||
type MessageWithMetadata,
|
||||
normalizeUserInput,
|
||||
type ToolResultContent,
|
||||
type ToolUseContent,
|
||||
} from "@cline/shared";
|
||||
@@ -681,7 +681,7 @@ function renderContentHTML(
|
||||
toolResultsMap: Map<string, ToolResultContent>,
|
||||
): string {
|
||||
if (typeof content === "string") {
|
||||
const text = isUser ? normalizeUserInput(content) : content;
|
||||
const text = isUser ? formatDisplayUserInput(content) : content;
|
||||
return renderTextHTML(text);
|
||||
}
|
||||
|
||||
@@ -689,7 +689,7 @@ function renderContentHTML(
|
||||
.map((block) => {
|
||||
switch (block.type) {
|
||||
case "text": {
|
||||
const text = isUser ? normalizeUserInput(block.text) : block.text;
|
||||
const text = isUser ? formatDisplayUserInput(block.text) : block.text;
|
||||
return renderTextHTML(text);
|
||||
}
|
||||
case "tool_use":
|
||||
|
||||
@@ -18,12 +18,12 @@ import { useTerminalBackground } from "../hooks/use-terminal-background";
|
||||
import {
|
||||
getDefaultForeground,
|
||||
getModeAccent,
|
||||
getModeInputBackground,
|
||||
getUserMessageBackground,
|
||||
palette,
|
||||
type TerminalTheme,
|
||||
} from "../palette";
|
||||
import type { ChatEntry } from "../types";
|
||||
import { getSyntaxStyle } from "../utils/syntax-style";
|
||||
import { getSyntaxStyle, type SyntaxAccentMode } from "../utils/syntax-style";
|
||||
import { isWarningToolError } from "../utils/tool-errors";
|
||||
import {
|
||||
parseApplyPatchInput,
|
||||
@@ -291,7 +291,7 @@ function ClineCreditsClinePassErrorView(props: { defaultFg?: string }) {
|
||||
/>
|
||||
<box flexDirection="row">
|
||||
<text fg="gray">Purchase Credits: </text>
|
||||
<text fg="cyan" selectable>
|
||||
<text fg={palette.act} selectable>
|
||||
<a href={CLINE_CREDITS_DASHBOARD_URL}>
|
||||
{CLINE_CREDITS_DASHBOARD_URL}
|
||||
</a>
|
||||
@@ -299,7 +299,7 @@ function ClineCreditsClinePassErrorView(props: { defaultFg?: string }) {
|
||||
</box>
|
||||
<box flexDirection="row">
|
||||
<text fg="gray">Purchase ClinePass: </text>
|
||||
<text fg="cyan" selectable>
|
||||
<text fg={palette.act} selectable>
|
||||
<a href={subscriptionUrl}>{subscriptionUrl}</a>
|
||||
</text>
|
||||
</box>
|
||||
@@ -377,13 +377,13 @@ function ClinePassSubscriptionErrorView(props: {
|
||||
)}
|
||||
<box flexDirection="row">
|
||||
<text fg="gray">Subscribe: </text>
|
||||
<text fg="cyan" selectable>
|
||||
<text fg={palette.act} selectable>
|
||||
<a href={subscriptionUrl}>Open subscription page</a>
|
||||
</text>
|
||||
</box>
|
||||
<box flexDirection="row">
|
||||
<text fg="gray">URL: </text>
|
||||
<text fg="cyan" selectable>
|
||||
<text fg={palette.act} selectable>
|
||||
<a href={subscriptionUrl}>{subscriptionUrl}</a>
|
||||
</text>
|
||||
</box>
|
||||
@@ -422,16 +422,15 @@ function ClineOrgIndividualInferenceSubscriptionErrorView(props: {
|
||||
export function ChatEntryView(props: {
|
||||
entry: ChatEntry;
|
||||
accent?: string;
|
||||
/** Mode the entry was produced in (resolved with the current-mode fallback). */
|
||||
mode?: SyntaxAccentMode;
|
||||
loadIndividualSubscriptionPlans?: () => Promise<ClineSubscriptionPlan[]>;
|
||||
terminalTheme: TerminalTheme;
|
||||
}) {
|
||||
const { entry, accent = palette.act, terminalTheme } = props;
|
||||
const { entry, accent = palette.act, mode = "act", terminalTheme } = props;
|
||||
const terminalBg = useTerminalBackground();
|
||||
const defaultFg = getDefaultForeground(terminalBg);
|
||||
const userMsgBg = getModeInputBackground(
|
||||
accent === palette.plan ? "plan" : "act",
|
||||
terminalBg,
|
||||
);
|
||||
const userMsgBg = getUserMessageBackground(terminalBg);
|
||||
|
||||
switch (entry.kind) {
|
||||
case "user":
|
||||
@@ -442,10 +441,9 @@ export function ChatEntryView(props: {
|
||||
marginX={-1}
|
||||
paddingLeft={1}
|
||||
paddingRight={2}
|
||||
paddingY={1}
|
||||
>
|
||||
<box width={2}>
|
||||
<text fg={accent}>{">"}</text>
|
||||
<text fg={accent}>{"❯"}</text>
|
||||
</box>
|
||||
<text fg={defaultFg} selectable>
|
||||
{entry.text}
|
||||
@@ -461,10 +459,9 @@ export function ChatEntryView(props: {
|
||||
marginX={-1}
|
||||
paddingLeft={1}
|
||||
paddingRight={2}
|
||||
paddingY={1}
|
||||
>
|
||||
<box width={2}>
|
||||
<text fg={accent}>{">"}</text>
|
||||
<text fg={accent}>{"❯"}</text>
|
||||
</box>
|
||||
{entry.delivery === "steer" && <text fg="yellow">[steer] </text>}
|
||||
{entry.delivery === "queue" && <text fg="gray">[queued] </text>}
|
||||
@@ -489,7 +486,7 @@ export function ChatEntryView(props: {
|
||||
<box flexGrow={1}>
|
||||
<markdown
|
||||
content={content}
|
||||
syntaxStyle={getSyntaxStyle(terminalTheme)}
|
||||
syntaxStyle={getSyntaxStyle(terminalTheme, mode)}
|
||||
streaming={entry.streaming}
|
||||
fg={defaultFg}
|
||||
/>
|
||||
@@ -565,7 +562,7 @@ export function ChatEntryView(props: {
|
||||
if (entry.elapsed) parts.push(`${entry.elapsed}s`);
|
||||
if (entry.tokens > 0)
|
||||
parts.push(`${entry.tokens.toLocaleString()} tokens`);
|
||||
if (entry.cost > 0) parts.push(`$${entry.cost.toFixed(3)}`);
|
||||
if (entry.cost > 0) parts.push(`$${entry.cost.toFixed(2)}`);
|
||||
if (entry.iterations > 0)
|
||||
parts.push(
|
||||
`${entry.iterations} iteration${entry.iterations !== 1 ? "s" : ""}`,
|
||||
|
||||
@@ -96,11 +96,15 @@ export const ChatMessageList = forwardRef<
|
||||
<box flexDirection="column" paddingX={1} paddingY={1} gap={1}>
|
||||
{props.entries.map((entry, i) => {
|
||||
const key = `${i}:${entry.kind}`;
|
||||
// Single source of truth for the entry's mode: the glyph accent
|
||||
// and the markdown accent must never diverge.
|
||||
const entryMode = entry.mode ?? props.uiMode ?? "act";
|
||||
return (
|
||||
<ChatEntryView
|
||||
key={key}
|
||||
entry={entry}
|
||||
accent={accent}
|
||||
accent={getModeAccent(entryMode, terminalTheme)}
|
||||
mode={entryMode === "plan" ? "plan" : "act"}
|
||||
loadIndividualSubscriptionPlans={
|
||||
props.loadIndividualSubscriptionPlans
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ export function AccountDialogContent(
|
||||
if (state.status === "loading") {
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1} gap={1}>
|
||||
<text fg="cyan">Cline Account</text>
|
||||
<text fg={palette.act}>Cline Account</text>
|
||||
<text fg="gray">{state.message}</text>
|
||||
<text fg="gray">Esc to close</text>
|
||||
</box>
|
||||
@@ -434,7 +434,7 @@ export function AccountDialogContent(
|
||||
if (state.status === "error") {
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1} gap={1}>
|
||||
<text fg="cyan">Cline Account</text>
|
||||
<text fg={palette.act}>Cline Account</text>
|
||||
<text fg="red">{state.message}</text>
|
||||
<text fg="gray">Esc to close</text>
|
||||
</box>
|
||||
@@ -444,7 +444,7 @@ export function AccountDialogContent(
|
||||
if (state.status === "unauthenticated") {
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1} gap={1}>
|
||||
<text fg="cyan">Cline Account</text>
|
||||
<text fg={palette.act}>Cline Account</text>
|
||||
<text>Sign in or create a Cline account.</text>
|
||||
<text fg="gray">
|
||||
Get access to the latest models with regular free promos and
|
||||
@@ -473,7 +473,7 @@ export function AccountDialogContent(
|
||||
if (view === "organizations") {
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1}>
|
||||
<text fg="cyan">Change Account</text>
|
||||
<text fg={palette.act}>Change Account</text>
|
||||
<box flexDirection="column" gap={0}>
|
||||
{orgRows.map((row, index) => (
|
||||
<OrganizationRow
|
||||
@@ -503,7 +503,7 @@ export function AccountDialogContent(
|
||||
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1} gap={1}>
|
||||
<text fg="cyan">Cline Account</text>
|
||||
<text fg={palette.act}>Cline Account</text>
|
||||
|
||||
<box flexDirection="row" gap={2}>
|
||||
<box
|
||||
@@ -514,7 +514,7 @@ export function AccountDialogContent(
|
||||
border
|
||||
borderColor="gray"
|
||||
>
|
||||
<text fg="cyan">{userInitial(loaded)}</text>
|
||||
<text fg={palette.act}>{userInitial(loaded)}</text>
|
||||
</box>
|
||||
<box flexDirection="column" flexGrow={1}>
|
||||
<text selectable>{displayName}</text>
|
||||
|
||||
@@ -191,7 +191,7 @@ export function CommandPaletteContent(
|
||||
{" "}
|
||||
</text>
|
||||
<text
|
||||
fg={isSelected ? palette.textOnSelection : "cyan"}
|
||||
fg={isSelected ? palette.textOnSelection : palette.act}
|
||||
width={shortcutWidth}
|
||||
flexShrink={0}
|
||||
>
|
||||
|
||||
@@ -90,7 +90,7 @@ export function ExtDetailContent(
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<text fg="cyan">
|
||||
<text fg={palette.act}>
|
||||
<strong>{row.name}</strong>
|
||||
</text>
|
||||
<text
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @jsxImportSource @opentui/react
|
||||
import type { ChoiceContext } from "@opentui-ui/dialog";
|
||||
import { useDialogKeyboard } from "@opentui-ui/dialog/react";
|
||||
import { palette } from "../../palette";
|
||||
|
||||
type HelpRow =
|
||||
| { kind: "heading"; id: string; text: string }
|
||||
@@ -277,7 +278,7 @@ export function HelpDialogContent(props: ChoiceContext<void>) {
|
||||
}
|
||||
return (
|
||||
<box key={row.id} flexDirection="row" paddingX={1}>
|
||||
<text fg="cyan" width={KEY_WIDTH} flexShrink={0}>
|
||||
<text fg={palette.act} width={KEY_WIDTH} flexShrink={0}>
|
||||
{row.key}
|
||||
</text>
|
||||
<text fg="gray">{row.desc}</text>
|
||||
|
||||
@@ -121,7 +121,7 @@ export function McpManagerContent(
|
||||
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1}>
|
||||
<text fg="cyan">MCP Servers</text>
|
||||
<text fg={palette.act}>MCP Servers</text>
|
||||
|
||||
<text fg="gray" marginTop={1}>
|
||||
Settings file:
|
||||
@@ -141,7 +141,7 @@ export function McpManagerContent(
|
||||
const enabledIcon =
|
||||
typeof srv.enabled === "boolean" ? (enabled ? "● " : "○ ") : "";
|
||||
const status = getMcpManagerEntryStatus(srv);
|
||||
let rowColor = isSel ? "cyan" : "gray";
|
||||
let rowColor = isSel ? palette.act : "gray";
|
||||
if (enabled && typeof srv.enabled === "boolean") {
|
||||
rowColor = palette.success;
|
||||
}
|
||||
|
||||
@@ -371,14 +371,14 @@ function ClinePassBrowserPageContent(
|
||||
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1} gap={1}>
|
||||
<text fg="cyan">
|
||||
<text fg={palette.act}>
|
||||
<strong>{providerName}</strong>
|
||||
</text>
|
||||
|
||||
<text>{status}</text>
|
||||
|
||||
<text fg="gray">{pageLabel}:</text>
|
||||
<text fg="cyan" selectable>
|
||||
<text fg={palette.act} selectable>
|
||||
<a href={url}>{url}</a>
|
||||
</text>
|
||||
|
||||
@@ -596,7 +596,7 @@ export function ProviderConfigInputContent(
|
||||
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1} gap={1}>
|
||||
<text fg="cyan">
|
||||
<text fg={palette.act}>
|
||||
<strong>{providerName}</strong>
|
||||
</text>
|
||||
|
||||
@@ -689,7 +689,7 @@ export function CodexCliStatusContent(
|
||||
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1} gap={1}>
|
||||
<text fg="cyan">
|
||||
<text fg={palette.act}>
|
||||
<strong>{providerName}</strong>
|
||||
</text>
|
||||
|
||||
@@ -707,7 +707,7 @@ export function CodexCliStatusContent(
|
||||
<text fg="yellow">Codex CLI was not found</text>
|
||||
<text fg="gray">{status.reason}</text>
|
||||
<text fg="gray">Install Codex CLI from:</text>
|
||||
<text fg="cyan" selectable>
|
||||
<text fg={palette.act} selectable>
|
||||
{CODEX_CLI_INSTALL_URL}
|
||||
</text>
|
||||
</box>
|
||||
@@ -869,7 +869,7 @@ export function OAuthLoginContent(
|
||||
if (mode === "device") {
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1} gap={1}>
|
||||
<text fg="cyan">
|
||||
<text fg={palette.act}>
|
||||
<strong>{providerName}</strong>
|
||||
</text>
|
||||
|
||||
@@ -884,7 +884,7 @@ export function OAuthLoginContent(
|
||||
<strong>{deviceUserCode}</strong>
|
||||
</text>
|
||||
<text fg="gray">Visit this URL and enter the code above:</text>
|
||||
<text fg="cyan" selectable>
|
||||
<text fg={palette.act} selectable>
|
||||
<a href={deviceVerifyUrl}>{deviceVerifyUrl}</a>
|
||||
</text>
|
||||
</box>
|
||||
@@ -901,7 +901,7 @@ export function OAuthLoginContent(
|
||||
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1} gap={1}>
|
||||
<text fg="cyan">
|
||||
<text fg={palette.act}>
|
||||
<strong>{providerName}</strong>
|
||||
</text>
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ export function SkillsPickerContent(props: SkillsPickerContentProps) {
|
||||
onMouseDown={() => resolve(SKILLS_MARKETPLACE_ACTION)}
|
||||
height={1}
|
||||
>
|
||||
<text fg={isSelected ? palette.textOnSelection : "cyan"}>
|
||||
<text fg={isSelected ? palette.textOnSelection : palette.act}>
|
||||
{isSelected ? "❯ " : " "}
|
||||
Browse more skills at {SKILLS_MARKETPLACE_URL}
|
||||
</text>
|
||||
|
||||
@@ -155,7 +155,7 @@ export function ToolApprovalContent(
|
||||
<box flexDirection="column" paddingX={1}>
|
||||
<text fg="yellow">Approve tool call?</text>
|
||||
|
||||
<text fg="cyan" marginTop={1}>
|
||||
<text fg={palette.act} marginTop={1}>
|
||||
<strong>{props.request.toolName}</strong>
|
||||
</text>
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ export type TextareaHandle = Pick<
|
||||
|
||||
export interface InputBarProps {
|
||||
accent: string;
|
||||
inputBackground: string;
|
||||
ruleColor: string;
|
||||
inputForeground: string;
|
||||
inputPlaceholder: string;
|
||||
placeholder: string;
|
||||
@@ -62,7 +62,7 @@ function readTextPaste(event: PasteEvent): string | null {
|
||||
export function InputBar(props: InputBarProps) {
|
||||
const {
|
||||
accent,
|
||||
inputBackground,
|
||||
ruleColor,
|
||||
inputForeground,
|
||||
inputPlaceholder,
|
||||
placeholder,
|
||||
@@ -197,13 +197,13 @@ export function InputBar(props: InputBarProps) {
|
||||
<box
|
||||
flexDirection="row"
|
||||
alignItems="flex-start"
|
||||
backgroundColor={inputBackground}
|
||||
paddingX={2}
|
||||
paddingY={1}
|
||||
border={["top", "bottom"]}
|
||||
borderStyle="single"
|
||||
borderColor={ruleColor}
|
||||
onMouseDown={props.onFocusRequest}
|
||||
>
|
||||
<text fg={accent}>
|
||||
<strong>{">"}</strong>
|
||||
<strong>{"❯"}</strong>
|
||||
</text>
|
||||
<box flexGrow={1} paddingLeft={1}>
|
||||
<textarea
|
||||
|
||||
@@ -27,7 +27,7 @@ export type ClineModelPickerEntry =
|
||||
function tagColor(tag: string): string {
|
||||
if (tag === "FREE") return palette.success;
|
||||
if (tag === "BEST") return "magenta";
|
||||
return "cyan";
|
||||
return palette.act;
|
||||
}
|
||||
|
||||
function resolveDisplayName(
|
||||
|
||||
@@ -17,7 +17,7 @@ type ClineModelEntriesState =
|
||||
function tagColor(tag: string): string {
|
||||
if (tag === "FREE") return palette.success;
|
||||
if (tag === "BEST") return "magenta";
|
||||
return "cyan";
|
||||
return palette.act;
|
||||
}
|
||||
|
||||
function resolveDisplayName(
|
||||
@@ -272,7 +272,7 @@ export function ClineModelSelectorDialogContent(
|
||||
if (state.status === "error") {
|
||||
return (
|
||||
<box flexDirection="column" gap={1}>
|
||||
<text fg="cyan">Choose a model</text>
|
||||
<text fg={palette.act}>Choose a model</text>
|
||||
<ProviderRow providerName={props.currentProviderName} focused={false} />
|
||||
<text fg="red">{state.message}</text>
|
||||
<text fg="gray">R to retry, Esc to go back</text>
|
||||
@@ -282,7 +282,7 @@ export function ClineModelSelectorDialogContent(
|
||||
|
||||
return (
|
||||
<box flexDirection="column" gap={1}>
|
||||
<text fg="cyan">Choose a model</text>
|
||||
<text fg={palette.act}>Choose a model</text>
|
||||
<ProviderRow providerName={props.currentProviderName} focused={false} />
|
||||
<text fg="gray">{state.message}</text>
|
||||
<text fg="gray">Esc to go back</text>
|
||||
|
||||
@@ -329,7 +329,8 @@ export function ThinkingLevelContent(
|
||||
) {
|
||||
const { resolve, dismiss, dialogId, modelName, currentLevel } = props;
|
||||
const [selected, setSelected] = useState(() => {
|
||||
const idx = THINKING_LEVELS.findIndex((l) => l.value === currentLevel);
|
||||
const initialLevel = currentLevel === "none" ? "medium" : currentLevel;
|
||||
const idx = THINKING_LEVELS.findIndex((l) => l.value === initialLevel);
|
||||
return idx >= 0 ? idx : 0;
|
||||
});
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export function ProviderRow({
|
||||
<text fg={focused ? palette.selection : "gray"} flexShrink={0}>
|
||||
{focused ? "❯" : " "}
|
||||
</text>
|
||||
<text fg={focused ? palette.selection : "cyan"} flexShrink={0}>
|
||||
<text fg={focused ? palette.selection : palette.act} flexShrink={0}>
|
||||
Provider:
|
||||
</text>
|
||||
<text fg="white">{providerName}</text>
|
||||
|
||||
@@ -14,14 +14,14 @@ describe("createContextBar", () => {
|
||||
it("keeps a stable width while changing segment lengths", () => {
|
||||
expect(createContextBar(0, 100)).toEqual({
|
||||
filled: "",
|
||||
empty: "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588",
|
||||
empty: "\u2588\u2588\u2588\u2588\u2588\u2588",
|
||||
});
|
||||
expect(createContextBar(50, 100)).toEqual({
|
||||
filled: "\u2588\u2588\u2588\u2588",
|
||||
empty: "\u2588\u2588\u2588\u2588",
|
||||
filled: "\u2588\u2588\u2588",
|
||||
empty: "\u2588\u2588\u2588",
|
||||
});
|
||||
expect(createContextBar(100, 100)).toEqual({
|
||||
filled: "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588",
|
||||
filled: "\u2588\u2588\u2588\u2588\u2588\u2588",
|
||||
empty: "",
|
||||
});
|
||||
});
|
||||
@@ -29,17 +29,17 @@ describe("createContextBar", () => {
|
||||
it("shows a non-empty fill when usage is above zero", () => {
|
||||
expect(createContextBar(7_000, 1_000_000)).toEqual({
|
||||
filled: "\u2588",
|
||||
empty: "\u2588\u2588\u2588\u2588\u2588\u2588\u2588",
|
||||
empty: "\u2588\u2588\u2588\u2588\u2588",
|
||||
});
|
||||
});
|
||||
|
||||
it("reserves the final segment for usage at or above the limit", () => {
|
||||
expect(createContextBar(999_999, 1_000_000)).toEqual({
|
||||
filled: "\u2588\u2588\u2588\u2588\u2588\u2588\u2588",
|
||||
filled: "\u2588\u2588\u2588\u2588\u2588",
|
||||
empty: "\u2588",
|
||||
});
|
||||
expect(createContextBar(1_000_000, 1_000_000)).toEqual({
|
||||
filled: "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588",
|
||||
filled: "\u2588\u2588\u2588\u2588\u2588\u2588",
|
||||
empty: "",
|
||||
});
|
||||
});
|
||||
@@ -58,22 +58,32 @@ describe("formatStatusBarUsageText", () => {
|
||||
totalCost: 0.123,
|
||||
providerId: "cline",
|
||||
}),
|
||||
).toBe("(12,345 tokens) $0.12");
|
||||
).toBe("(12,345) $0.12");
|
||||
});
|
||||
|
||||
it("displays subscription message when the provider is a subscription provider", () => {
|
||||
it("rounds cost to two decimals even when tiny", () => {
|
||||
expect(
|
||||
formatStatusBarUsageText({
|
||||
totalTokens: 12_345,
|
||||
totalCost: 0.0004,
|
||||
providerId: "cline",
|
||||
}),
|
||||
).toBe("(12,345) $0.00");
|
||||
});
|
||||
|
||||
it("hides cost entirely for subscription providers", () => {
|
||||
expect(
|
||||
formatStatusBarUsageText({
|
||||
totalTokens: 12_345,
|
||||
totalCost: 0.123,
|
||||
providerId: "cline-pass",
|
||||
}),
|
||||
).toBe("(12,345 tokens) $0.00 (included with subscription)");
|
||||
).toBe("(12,345)");
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveModelDisplayName", () => {
|
||||
it("keeps ClinePass visible when model ids have provider prefixes", () => {
|
||||
it("uses the friendly model name with a ClinePass prefix", () => {
|
||||
expect(
|
||||
resolveModelDisplayName({
|
||||
providerId: "cline-pass",
|
||||
@@ -82,7 +92,30 @@ describe("resolveModelDisplayName", () => {
|
||||
"zai/glm-5.2": { name: "GLM 5.2" },
|
||||
},
|
||||
}),
|
||||
).toBe("ClinePass/glm-5.2");
|
||||
).toBe("ClinePass: GLM 5.2");
|
||||
});
|
||||
|
||||
it("falls back to the bare model id with a ClinePass prefix when unknown", () => {
|
||||
expect(
|
||||
resolveModelDisplayName({
|
||||
providerId: "cline-pass",
|
||||
modelId: "zai/glm-5.2",
|
||||
}),
|
||||
).toBe("ClinePass: glm-5.2");
|
||||
});
|
||||
|
||||
it("keeps the reasoning effort next to the model name", () => {
|
||||
expect(
|
||||
resolveModelDisplayName({
|
||||
providerId: "cline-pass",
|
||||
modelId: "zai/glm-5.2",
|
||||
knownModels: {
|
||||
"zai/glm-5.2": { name: "GLM 5.2" },
|
||||
},
|
||||
thinking: true,
|
||||
reasoningEffort: "high",
|
||||
}),
|
||||
).toBe("ClinePass: GLM 5.2 (high)");
|
||||
});
|
||||
|
||||
it("uses the friendly model name for non-ClinePass providers", () => {
|
||||
|
||||
@@ -18,7 +18,7 @@ import { HOME_VIEW_MAX_WIDTH } from "../types";
|
||||
export function createContextBar(
|
||||
used: number,
|
||||
total?: number,
|
||||
width = 8,
|
||||
width = 6,
|
||||
): { filled: string; empty: string } {
|
||||
const normalizedWidth = Math.max(0, Math.floor(width));
|
||||
const ratio = total && total > 0 ? Math.min(used / total, 1) : 0;
|
||||
@@ -45,13 +45,13 @@ export function resolveContextBarFilledForeground(
|
||||
}
|
||||
|
||||
function formatCost(cost: number): string {
|
||||
if (cost < 0.01) return `$${cost.toFixed(4)}`;
|
||||
return `$${cost.toFixed(2)}`;
|
||||
}
|
||||
|
||||
function formatCostText(providerId: string, totalCost: number): string {
|
||||
// Subscription providers (ClinePass) have no per-use cost worth surfacing.
|
||||
if (shouldShowCliUsageCoveredBySubscription(providerId)) {
|
||||
return "$0.00 (included with subscription)";
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!shouldShowCliUsageCost(providerId)) {
|
||||
@@ -66,7 +66,7 @@ export function formatStatusBarUsageText(input: {
|
||||
totalCost: number;
|
||||
providerId: string;
|
||||
}): string {
|
||||
const tokens = `(${input.totalTokens.toLocaleString()} tokens)`;
|
||||
const tokens = `(${input.totalTokens.toLocaleString()})`;
|
||||
const costText = formatCostText(input.providerId, input.totalCost);
|
||||
|
||||
if (!costText) {
|
||||
@@ -102,12 +102,12 @@ export function resolveModelDisplayName(config: {
|
||||
}): string {
|
||||
const info = lookupModelInfo(config.modelId, config.knownModels);
|
||||
const modelIdTail = config.modelId.split("/").pop() ?? config.modelId;
|
||||
const displayName =
|
||||
config.providerId === "cline-pass"
|
||||
? `ClinePass/${modelIdTail}`
|
||||
: (info?.name ?? modelIdTail);
|
||||
let displayName = info?.name ?? modelIdTail;
|
||||
if (config.thinking && config.reasoningEffort) {
|
||||
return `${displayName} (${config.reasoningEffort})`;
|
||||
displayName = `${displayName} (${config.reasoningEffort})`;
|
||||
}
|
||||
if (config.providerId === "cline-pass") {
|
||||
displayName = `ClinePass: ${displayName}`;
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
@@ -103,9 +103,16 @@ export function SessionProvider(props: {
|
||||
const [hasSubmitted, setHasSubmitted] = useState(
|
||||
(initialEntries?.length ?? 0) > 0,
|
||||
);
|
||||
const [uiMode, setUiMode] = useState<AgentMode>(
|
||||
const [uiMode, _setUiMode] = useState<AgentMode>(
|
||||
config.mode === "plan" ? "plan" : "act",
|
||||
);
|
||||
// Mirror for appendEntry: entries are appended from event-handler
|
||||
// callbacks that must see the mode at append time, not at closure time.
|
||||
const uiModeRef = useRef<AgentMode>(config.mode === "plan" ? "plan" : "act");
|
||||
const setUiMode = useCallback((mode: AgentMode) => {
|
||||
uiModeRef.current = mode;
|
||||
_setUiMode(mode);
|
||||
}, []);
|
||||
const initialAutoApproveAll = config.toolPolicies["*"]?.autoApprove !== false;
|
||||
const autoApproveAllRef = useRef(initialAutoApproveAll);
|
||||
const [autoApproveAll, _setAutoApproveAll] = useState(initialAutoApproveAll);
|
||||
@@ -132,8 +139,9 @@ export function SessionProvider(props: {
|
||||
);
|
||||
|
||||
const appendEntry = useCallback((entry: ChatEntry) => {
|
||||
const stamped = entry.mode ? entry : { ...entry, mode: uiModeRef.current };
|
||||
setEntries((prev) => {
|
||||
const next = [...prev, entry];
|
||||
const next = [...prev, stamped];
|
||||
return next.length <= MAX_BUFFERED_LINES
|
||||
? next
|
||||
: next.slice(next.length - MAX_BUFFERED_LINES);
|
||||
@@ -188,8 +196,8 @@ export function SessionProvider(props: {
|
||||
}, []);
|
||||
|
||||
const toggleMode = useCallback(() => {
|
||||
setUiMode((m) => (m === "act" ? "plan" : "act"));
|
||||
}, []);
|
||||
setUiMode(uiModeRef.current === "act" ? "plan" : "act");
|
||||
}, [setUiMode]);
|
||||
|
||||
const toggleAutoApprove = useCallback(() => {
|
||||
const next = !autoApproveAllRef.current;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { AgentEvent, TeamEvent } from "@cline/core";
|
||||
import { formatDisplayUserInput } from "@cline/shared";
|
||||
import { useCallback, useRef } from "react";
|
||||
import type {
|
||||
PendingPromptSnapshot,
|
||||
@@ -296,7 +297,13 @@ export function useAgentEventHandlers(deps: AgentEventDeps) {
|
||||
const handlePendingPromptSubmitted = useCallback(
|
||||
(event: PendingPromptSubmittedEvent) => {
|
||||
knownPendingPromptIdsRef.current.delete(event.id);
|
||||
appendEntry({ kind: "user_submitted", text: event.prompt });
|
||||
// Display boundary: formatDisplayUserInput strips runtime-generated
|
||||
// notice elements (e.g. mode_notice) that normalizeUserInput must
|
||||
// preserve, since the latter also sanitizes model-bound prompts.
|
||||
appendEntry({
|
||||
kind: "user_submitted",
|
||||
text: formatDisplayUserInput(event.prompt),
|
||||
});
|
||||
},
|
||||
[appendEntry],
|
||||
);
|
||||
|
||||
@@ -75,9 +75,10 @@ export function useLocalCommandActions(input: {
|
||||
});
|
||||
} else {
|
||||
session.clearEntries();
|
||||
for (const entry of entries) {
|
||||
session.appendEntry(entry);
|
||||
}
|
||||
// replaceEntries rather than appendEntry: appendEntry
|
||||
// stamps unstamped entries with the CURRENT mode, which
|
||||
// would lock hydrated history to the resume-time accent.
|
||||
session.replaceEntries(entries);
|
||||
if (typeof result.currentContextSize === "number") {
|
||||
session.setLastTotalTokens(result.currentContextSize);
|
||||
}
|
||||
|
||||
@@ -23,15 +23,15 @@ describe("getTerminalTheme", () => {
|
||||
});
|
||||
|
||||
describe("theme-aware palette helpers", () => {
|
||||
it("preserves the existing named ANSI colors for dark terminals", () => {
|
||||
expect(getModeAccent("act", "dark")).toBe("cyan");
|
||||
expect(getModeAccent("plan", "dark")).toBe("yellow");
|
||||
expect(getSuccessColor("dark")).toBe("brightGreen");
|
||||
it("uses the brand accent colors for dark terminals", () => {
|
||||
expect(getModeAccent("act", "dark")).toBe("#79b8ff");
|
||||
expect(getModeAccent("plan", "dark")).toBe("#ffea7f");
|
||||
expect(getSuccessColor("dark")).toBe("#99e89b");
|
||||
});
|
||||
|
||||
it("uses darker accents on light terminals", () => {
|
||||
expect(getModeAccent("act", "light")).toBe("#0969da");
|
||||
expect(getModeAccent("plan", "light")).toBe("#9a6700");
|
||||
expect(getModeAccent("act", "light")).toBe("#0f72cb");
|
||||
expect(getModeAccent("plan", "light")).toBe("#867100");
|
||||
expect(getSuccessColor("light")).toBe("#116329");
|
||||
});
|
||||
});
|
||||
|
||||
+50
-17
@@ -1,9 +1,9 @@
|
||||
export const palette = {
|
||||
act: "cyan",
|
||||
plan: "yellow",
|
||||
selection: "cyan",
|
||||
act: "#79b8ff",
|
||||
plan: "#ffea7f",
|
||||
selection: "#79b8ff",
|
||||
error: "red",
|
||||
success: "brightGreen",
|
||||
success: "#99e89b",
|
||||
muted: "gray",
|
||||
textOnSelection: "black",
|
||||
} as const;
|
||||
@@ -16,9 +16,11 @@ export const themePalette = {
|
||||
plan: palette.plan,
|
||||
success: palette.success,
|
||||
},
|
||||
// Same OKLCH hues as the dark accents, darkened to hold >=4.5:1 contrast
|
||||
// on white so the plan/act identity carries across themes.
|
||||
light: {
|
||||
act: "#0969da",
|
||||
plan: "#9a6700",
|
||||
act: "#0f72cb",
|
||||
plan: "#867100",
|
||||
success: "#116329",
|
||||
},
|
||||
} as const;
|
||||
@@ -29,7 +31,7 @@ export const diffPalettes = {
|
||||
removedBg: "#4d1a1a",
|
||||
addedLineNumberBg: "#1a4d1a",
|
||||
removedLineNumberBg: "#4d1a1a",
|
||||
addedSignColor: "#22c55e",
|
||||
addedSignColor: "#99e89b",
|
||||
removedSignColor: "#ef4444",
|
||||
lineNumberFg: "#888888",
|
||||
},
|
||||
@@ -75,8 +77,8 @@ export function getSuccessColor(theme: TerminalTheme = "dark"): string {
|
||||
// overshoot.
|
||||
// 3. On dark themes, raise L (lighten). On light themes, lower L (darken).
|
||||
// 4. Nudge the a/b chromatic channels by CHROMA_NUDGE toward the mode's
|
||||
// accent color. For plan (warm/yellow): +a, +b. For act (cool/cyan):
|
||||
// -a, +b. At 0.003 this is ~10x below OKLAB's just-noticeable-difference
|
||||
// accent color. For plan (warm/yellow): +a, +b. For act (cool/blue):
|
||||
// -a, -b. At 0.003 this is ~10x below OKLAB's just-noticeable-difference
|
||||
// threshold (~0.03), so it registers as a "feel" rather than visible color.
|
||||
//
|
||||
// Sample outputs on common terminals (act mode / plan mode bg):
|
||||
@@ -131,22 +133,53 @@ export function getDefaultForeground(
|
||||
return isLightTheme(terminalBg) ? "#1a1a1a" : undefined;
|
||||
}
|
||||
|
||||
export function getModeInputBackground(
|
||||
mode: string,
|
||||
function liftedFromTerminalBg(
|
||||
terminalBg: string | null,
|
||||
baseLift: number,
|
||||
nudgeA: number,
|
||||
nudgeB: number,
|
||||
): string {
|
||||
const hex = normalizeHex(terminalBg) ?? "#000000";
|
||||
const base = hexToOklab(hex);
|
||||
const light = base.L > LIGHT_THEME_THRESHOLD;
|
||||
const lift = BASE_LIFT / (1 + (light ? 1 - base.L : base.L) * LIFT_DAMPING);
|
||||
const warm = mode === "plan";
|
||||
const lift = baseLift / (1 + (light ? 1 - base.L : base.L) * LIFT_DAMPING);
|
||||
return oklabToHex(
|
||||
base.L + (light ? -lift : lift),
|
||||
base.a + (warm ? CHROMA_NUDGE : -CHROMA_NUDGE),
|
||||
base.b + CHROMA_NUDGE,
|
||||
base.a + nudgeA,
|
||||
base.b + nudgeB,
|
||||
);
|
||||
}
|
||||
|
||||
export function getModeInputBackground(
|
||||
mode: string,
|
||||
terminalBg: string | null,
|
||||
): string {
|
||||
const warm = mode === "plan";
|
||||
return liftedFromTerminalBg(
|
||||
terminalBg,
|
||||
BASE_LIFT,
|
||||
warm ? CHROMA_NUDGE : -CHROMA_NUDGE,
|
||||
warm ? CHROMA_NUDGE : -CHROMA_NUDGE,
|
||||
);
|
||||
}
|
||||
|
||||
// The `─` rules framing the input field are thin foreground strokes rather
|
||||
// than filled cells, so they need a much larger lift than a background tint
|
||||
// to register at the same perceptual weight — this lands them around mid-gray
|
||||
// on both black and white terminals. They stay neutral (no mode chroma) so
|
||||
// the frame doesn't shift color when toggling plan/act.
|
||||
const RULE_BASE_LIFT = 0.5;
|
||||
|
||||
export function getInputRuleColor(terminalBg: string | null): string {
|
||||
return liftedFromTerminalBg(terminalBg, RULE_BASE_LIFT, 0, 0);
|
||||
}
|
||||
|
||||
// User message bubbles stay neutral (no mode chroma) so the transcript reads
|
||||
// as history rather than tracking whichever mode is currently active.
|
||||
export function getUserMessageBackground(terminalBg: string | null): string {
|
||||
return liftedFromTerminalBg(terminalBg, BASE_LIFT, 0, 0);
|
||||
}
|
||||
|
||||
export function getModeInputForeground(
|
||||
mode: string,
|
||||
terminalBg: string | null,
|
||||
@@ -157,7 +190,7 @@ export function getModeInputForeground(
|
||||
return oklabToHex(
|
||||
base.L,
|
||||
base.a + (warm ? CHROMA_NUDGE : -CHROMA_NUDGE),
|
||||
base.b + CHROMA_NUDGE,
|
||||
base.b + (warm ? CHROMA_NUDGE : -CHROMA_NUDGE),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -171,7 +204,7 @@ export function getModeInputPlaceholder(
|
||||
return oklabToHex(
|
||||
base.L,
|
||||
base.a + (warm ? CHROMA_NUDGE * 2 : -CHROMA_NUDGE * 2),
|
||||
base.b + CHROMA_NUDGE * 2,
|
||||
base.b + (warm ? CHROMA_NUDGE * 2 : -CHROMA_NUDGE * 2),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -401,9 +401,10 @@ function App(props: TuiProps) {
|
||||
if (lastEntry && lastEntry.kind === "user_submitted") {
|
||||
entries.pop();
|
||||
}
|
||||
for (const entry of entries) {
|
||||
session.appendEntry(entry);
|
||||
}
|
||||
// replaceEntries rather than appendEntry: appendEntry stamps
|
||||
// unstamped entries with the CURRENT mode, which would lock
|
||||
// hydrated history to the restore-time accent.
|
||||
session.replaceEntries(entries);
|
||||
session.setHasSubmitted(entries.length > 0);
|
||||
setAppView(entries.length > 0 ? "chat" : "home");
|
||||
populateInputRef.current(picked.fullText);
|
||||
|
||||
@@ -25,7 +25,7 @@ import type {
|
||||
} from "./interactive-config";
|
||||
import type { InteractiveSlashCommand } from "./interactive-welcome";
|
||||
|
||||
export type ChatEntry =
|
||||
export type ChatEntry = (
|
||||
| { kind: "user"; text: string }
|
||||
| { kind: "assistant_text"; text: string; streaming: boolean }
|
||||
| { kind: "reasoning"; text: string; streaming: boolean }
|
||||
@@ -52,7 +52,17 @@ export type ChatEntry =
|
||||
cost: number;
|
||||
elapsed: string;
|
||||
iterations: number;
|
||||
};
|
||||
}
|
||||
) & {
|
||||
/**
|
||||
* Agent mode active when the entry was produced. Stamped by appendEntry
|
||||
* (live sessions) and hydrateSessionMessages (resumed sessions) so the
|
||||
* transcript renders each entry with the accent of its own mode instead
|
||||
* of retinting everything to the current mode. Absent on entries from
|
||||
* transcripts that predate mode stamping.
|
||||
*/
|
||||
mode?: AgentMode;
|
||||
};
|
||||
|
||||
export interface InteractiveTurnResult {
|
||||
usage: {
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
import type { Message } from "@cline/shared";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { ACT_MODE_CONTINUATION_PROMPT } from "../../runtime/interactive/mode";
|
||||
import { hydrateSessionMessages } from "./hydrate-messages";
|
||||
|
||||
describe("hydrateSessionMessages", () => {
|
||||
it("renders regular user messages", () => {
|
||||
const messages = [
|
||||
{
|
||||
role: "user",
|
||||
content: '<user_input mode="plan">lets do it</user_input>',
|
||||
},
|
||||
] as Message[];
|
||||
|
||||
expect(hydrateSessionMessages(messages)).toEqual([
|
||||
{ kind: "user_submitted", text: "lets do it", mode: "plan" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("hides the synthetic act-mode continuation prompt", () => {
|
||||
const messages = [
|
||||
{
|
||||
role: "user",
|
||||
content: `<user_input mode="act">${ACT_MODE_CONTINUATION_PROMPT}</user_input>`,
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `<user_input mode="act">${ACT_MODE_CONTINUATION_PROMPT}</user_input>`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
content: "On it.",
|
||||
},
|
||||
] as Message[];
|
||||
|
||||
expect(hydrateSessionMessages(messages)).toEqual([
|
||||
{ kind: "assistant_text", text: "On it.", streaming: false, mode: "act" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("stamps entries with the mode of the user message that produced them", () => {
|
||||
const messages = [
|
||||
{
|
||||
role: "user",
|
||||
content: '<user_input mode="plan">plan this out</user_input>',
|
||||
},
|
||||
{ role: "assistant", content: "Here is the plan." },
|
||||
{
|
||||
role: "user",
|
||||
content: '<user_input mode="act">do it</user_input>',
|
||||
},
|
||||
{ role: "assistant", content: "Doing it." },
|
||||
] as Message[];
|
||||
|
||||
expect(hydrateSessionMessages(messages)).toEqual([
|
||||
{ kind: "user_submitted", text: "plan this out", mode: "plan" },
|
||||
{
|
||||
kind: "assistant_text",
|
||||
text: "Here is the plan.",
|
||||
streaming: false,
|
||||
mode: "plan",
|
||||
},
|
||||
{ kind: "user_submitted", text: "do it", mode: "act" },
|
||||
{
|
||||
kind: "assistant_text",
|
||||
text: "Doing it.",
|
||||
streaming: false,
|
||||
mode: "act",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("switches to act mode after a switch_to_act_mode tool call", () => {
|
||||
const messages = [
|
||||
{
|
||||
role: "user",
|
||||
content: '<user_input mode="plan">plan then build</user_input>',
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "text", text: "Plan looks good, switching." },
|
||||
{
|
||||
type: "tool_use",
|
||||
id: "tool-1",
|
||||
name: "switch_to_act_mode",
|
||||
input: {},
|
||||
},
|
||||
{ type: "text", text: "Building now." },
|
||||
],
|
||||
},
|
||||
] as Message[];
|
||||
|
||||
expect(hydrateSessionMessages(messages)).toEqual([
|
||||
{ kind: "user_submitted", text: "plan then build", mode: "plan" },
|
||||
{
|
||||
kind: "assistant_text",
|
||||
text: "Plan looks good, switching.",
|
||||
streaming: false,
|
||||
mode: "plan",
|
||||
},
|
||||
{
|
||||
kind: "tool_call",
|
||||
toolName: "switch_to_act_mode",
|
||||
inputSummary: expect.any(String),
|
||||
rawInput: {},
|
||||
streaming: false,
|
||||
mode: "plan",
|
||||
},
|
||||
{
|
||||
kind: "assistant_text",
|
||||
text: "Building now.",
|
||||
streaming: false,
|
||||
mode: "act",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("strips mode switch notices from displayed user text", () => {
|
||||
const messages = [
|
||||
{
|
||||
role: "user",
|
||||
content:
|
||||
'<user_input mode="plan"><mode_notice>The user switched from act mode to plan mode before sending this message.</mode_notice>\nare you okay?</user_input>',
|
||||
},
|
||||
] as Message[];
|
||||
|
||||
expect(hydrateSessionMessages(messages)).toEqual([
|
||||
{ kind: "user_submitted", text: "are you okay?", mode: "plan" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("leaves mode undefined for transcripts without user_input wrappers", () => {
|
||||
const messages = [
|
||||
{ role: "user", content: "plain old message" },
|
||||
{ role: "assistant", content: "reply" },
|
||||
] as Message[];
|
||||
|
||||
expect(hydrateSessionMessages(messages)).toEqual([
|
||||
{ kind: "user_submitted", text: "plain old message", mode: undefined },
|
||||
{
|
||||
kind: "assistant_text",
|
||||
text: "reply",
|
||||
streaming: false,
|
||||
mode: undefined,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,10 @@
|
||||
import { formatDisplayUserInput, type Message } from "@cline/shared";
|
||||
import type { AgentMode } from "@cline/core";
|
||||
import {
|
||||
formatDisplayUserInput,
|
||||
type Message,
|
||||
parseUserInputMode,
|
||||
} from "@cline/shared";
|
||||
import { ACT_MODE_CONTINUATION_PROMPT } from "../../runtime/interactive/mode";
|
||||
import { formatToolInput } from "../../utils/helpers";
|
||||
import type { ChatEntry } from "../types";
|
||||
|
||||
@@ -11,6 +17,12 @@ function getDisplayRole(msg: PersistedMessage): string | undefined {
|
||||
return typeof role === "string" ? role.trim().toLowerCase() : undefined;
|
||||
}
|
||||
|
||||
// The act-mode continuation prompt is runtime-generated, not typed by the
|
||||
// user, so it should not surface as a user bubble in the transcript.
|
||||
function isSyntheticUserText(text: string): boolean {
|
||||
return text === ACT_MODE_CONTINUATION_PROMPT;
|
||||
}
|
||||
|
||||
function stringifyToolResult(
|
||||
content: string | Array<{ type: string; text?: string; path?: string }>,
|
||||
): string {
|
||||
@@ -30,6 +42,12 @@ function stringifyToolResult(
|
||||
export function hydrateSessionMessages(messages: Message[]): ChatEntry[] {
|
||||
const entries: ChatEntry[] = [];
|
||||
const toolUseMap = new Map<string, number>();
|
||||
// Mode each entry was produced in, recovered from <user_input mode="...">
|
||||
// wrappers and switch_to_act_mode tool calls as we walk the transcript.
|
||||
// Stays undefined for transcripts with no mode markers (pre-wrapper
|
||||
// builds, or transcripts laundered by older builds that stripped the
|
||||
// wrappers on session restarts).
|
||||
let mode: AgentMode | undefined;
|
||||
|
||||
for (const msg of messages as PersistedMessage[]) {
|
||||
const displayRole = getDisplayRole(msg);
|
||||
@@ -39,13 +57,17 @@ export function hydrateSessionMessages(messages: Message[]): ChatEntry[] {
|
||||
|
||||
if (typeof msg.content === "string") {
|
||||
if (msg.role === "user") {
|
||||
mode = parseUserInputMode(msg.content) ?? mode;
|
||||
const text = formatDisplayUserInput(msg.content);
|
||||
if (text) entries.push({ kind: "user_submitted", text });
|
||||
if (text && !isSyntheticUserText(text)) {
|
||||
entries.push({ kind: "user_submitted", text, mode });
|
||||
}
|
||||
} else {
|
||||
entries.push({
|
||||
kind: "assistant_text",
|
||||
text: msg.content,
|
||||
streaming: false,
|
||||
mode,
|
||||
});
|
||||
}
|
||||
continue;
|
||||
@@ -62,6 +84,7 @@ export function hydrateSessionMessages(messages: Message[]): ChatEntry[] {
|
||||
kind: "assistant_text",
|
||||
text: block.text,
|
||||
streaming: false,
|
||||
mode,
|
||||
});
|
||||
}
|
||||
continue;
|
||||
@@ -72,6 +95,7 @@ export function hydrateSessionMessages(messages: Message[]): ChatEntry[] {
|
||||
kind: "reasoning",
|
||||
text: block.thinking,
|
||||
streaming: false,
|
||||
mode,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@@ -87,8 +111,14 @@ export function hydrateSessionMessages(messages: Message[]): ChatEntry[] {
|
||||
inputSummary: formatToolInput(block.name, block.input),
|
||||
rawInput: block.input,
|
||||
streaming: false,
|
||||
mode,
|
||||
});
|
||||
toolUseMap.set(block.id, entries.length - 1);
|
||||
// The switch tool flips the session to act mid-run; everything
|
||||
// after it was produced in act mode.
|
||||
if (block.name === "switch_to_act_mode") {
|
||||
mode = "act";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -114,9 +144,10 @@ export function hydrateSessionMessages(messages: Message[]): ChatEntry[] {
|
||||
|
||||
if (msg.role === "user" && userTextParts.length > 0) {
|
||||
const combined = userTextParts.join("\n");
|
||||
mode = parseUserInputMode(combined) ?? mode;
|
||||
const text = formatDisplayUserInput(combined);
|
||||
if (text) {
|
||||
entries.push({ kind: "user_submitted", text });
|
||||
if (text && !isSyntheticUserText(text)) {
|
||||
entries.push({ kind: "user_submitted", text, mode });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,4 +49,33 @@ describe("getSyntaxStyle", () => {
|
||||
|
||||
expect(style?.fg?.toInts()).toEqual([26, 26, 26, 255]);
|
||||
});
|
||||
|
||||
it("tints markdown accents by mode", () => {
|
||||
// act #79b8ff vs plan #ffea7f (dark theme accents)
|
||||
expect(
|
||||
getSyntaxStyle("dark", "act").getStyle("markup.heading")?.fg?.toInts(),
|
||||
).toEqual([0x79, 0xb8, 0xff, 255]);
|
||||
expect(
|
||||
getSyntaxStyle("dark", "plan").getStyle("markup.heading")?.fg?.toInts(),
|
||||
).toEqual([0xff, 0xea, 0x7f, 255]);
|
||||
expect(
|
||||
getSyntaxStyle("dark", "plan").getStyle("markup.link")?.fg?.toInts(),
|
||||
).toEqual([0xff, 0xea, 0x7f, 255]);
|
||||
});
|
||||
|
||||
it("tints light-theme markdown accents by mode", () => {
|
||||
// act #0f72cb vs plan #867100 (light theme accents)
|
||||
expect(
|
||||
getSyntaxStyle("light", "act").getStyle("markup.heading")?.fg?.toInts(),
|
||||
).toEqual([0x0f, 0x72, 0xcb, 255]);
|
||||
expect(
|
||||
getSyntaxStyle("light", "plan").getStyle("markup.heading")?.fg?.toInts(),
|
||||
).toEqual([0x86, 0x71, 0x00, 255]);
|
||||
});
|
||||
|
||||
it("keeps code token colors constant across modes", () => {
|
||||
expect(getSyntaxStyle("dark", "plan").getStyle("keyword")).toEqual(
|
||||
getSyntaxStyle("dark", "act").getStyle("keyword"),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { RGBA, type StyleDefinition, SyntaxStyle } from "@opentui/core";
|
||||
import type { TerminalTheme } from "../palette";
|
||||
import { type TerminalTheme, themePalette } from "../palette";
|
||||
|
||||
const instances: Record<TerminalTheme, SyntaxStyle | null> = {
|
||||
dark: null,
|
||||
light: null,
|
||||
};
|
||||
// Markdown's prominent elements (headings, bold, list markers, links) take
|
||||
// the accent of the mode the content was produced in, so assistant output
|
||||
// reads plan-yellow or act-blue alongside the rest of the transcript.
|
||||
export type SyntaxAccentMode = "act" | "plan";
|
||||
|
||||
const instances = new Map<string, SyntaxStyle>();
|
||||
|
||||
interface SyntaxColors {
|
||||
keyword: string;
|
||||
@@ -22,34 +24,34 @@ interface SyntaxColors {
|
||||
attribute: string;
|
||||
escape: string;
|
||||
markdownCode: string;
|
||||
markdownHeading: string;
|
||||
markdownMuted: string;
|
||||
markdownLink: string;
|
||||
markdownItalic: string;
|
||||
markdownDefault?: string;
|
||||
}
|
||||
|
||||
// Dark syntax colors are a pastel family harmonized with the brand accents
|
||||
// (act #79b8ff, plan #ffea7f, success #99e89b): every hue sits near the same
|
||||
// OKLCH lightness/chroma weight (~L 0.78, C 0.11) so code blocks feel like
|
||||
// part of the same palette instead of a bolted-on editor theme.
|
||||
const syntaxColors: Record<TerminalTheme, SyntaxColors> = {
|
||||
dark: {
|
||||
keyword: "#c678dd",
|
||||
operator: "#56b6c2",
|
||||
type: "#e5c07b",
|
||||
functionName: "#61afef",
|
||||
variable: "#e06c75",
|
||||
string: "#98c379",
|
||||
number: "#d19a66",
|
||||
keyword: "#d7a0e3",
|
||||
operator: "#9bbbdd",
|
||||
type: "#dfca7d",
|
||||
functionName: themePalette.dark.act,
|
||||
variable: "#ee939b",
|
||||
string: "#99e89b",
|
||||
number: "#f0ad7f",
|
||||
comment: "#5c6370",
|
||||
punctuation: "#abb2bf",
|
||||
property: "#e06c75",
|
||||
constant: "#d19a66",
|
||||
tag: "#e06c75",
|
||||
attribute: "#d19a66",
|
||||
escape: "#56b6c2",
|
||||
markdownCode: "#98c379",
|
||||
markdownHeading: "#56b6c2",
|
||||
property: "#ee939b",
|
||||
constant: "#f0ad7f",
|
||||
tag: "#ee939b",
|
||||
attribute: "#f0ad7f",
|
||||
escape: "#9bbbdd",
|
||||
markdownCode: "#99e89b",
|
||||
markdownMuted: "#808080",
|
||||
markdownLink: "#56b6c2",
|
||||
markdownItalic: "#e5c07b",
|
||||
markdownItalic: "#dfca7d",
|
||||
},
|
||||
light: {
|
||||
keyword: "#cf222e",
|
||||
@@ -67,9 +69,7 @@ const syntaxColors: Record<TerminalTheme, SyntaxColors> = {
|
||||
attribute: "#0550ae",
|
||||
escape: "#0550ae",
|
||||
markdownCode: "#116329",
|
||||
markdownHeading: "#0969da",
|
||||
markdownMuted: "#6e7781",
|
||||
markdownLink: "#0969da",
|
||||
markdownItalic: "#8250df",
|
||||
markdownDefault: "#1a1a1a",
|
||||
},
|
||||
@@ -91,16 +91,16 @@ function italic(hex: string): StyleDefinition {
|
||||
return { fg: color(hex), italic: true };
|
||||
}
|
||||
|
||||
function underline(hex: string): StyleDefinition {
|
||||
return { fg: color(hex), underline: true };
|
||||
}
|
||||
|
||||
function buildSyntaxStyle(theme: TerminalTheme): SyntaxStyle {
|
||||
function buildSyntaxStyle(
|
||||
theme: TerminalTheme,
|
||||
mode: SyntaxAccentMode,
|
||||
): SyntaxStyle {
|
||||
const colors = syntaxColors[theme];
|
||||
const markdownHeading = color(colors.markdownHeading);
|
||||
const accent = color(themePalette[theme][mode]);
|
||||
const markdownHeading = accent;
|
||||
const markdownCode = color(colors.markdownCode);
|
||||
const markdownMuted = color(colors.markdownMuted);
|
||||
const markdownLink = color(colors.markdownLink);
|
||||
const markdownLink = accent;
|
||||
|
||||
return SyntaxStyle.fromStyles({
|
||||
...(colors.markdownDefault ? { default: fg(colors.markdownDefault) } : {}),
|
||||
@@ -145,10 +145,19 @@ function buildSyntaxStyle(theme: TerminalTheme): SyntaxStyle {
|
||||
"markup.link.url": { fg: markdownLink, underline: true },
|
||||
label: { fg: markdownLink },
|
||||
conceal: { fg: markdownMuted },
|
||||
"string.special.url": underline(colors.markdownLink),
|
||||
"string.special.url": { fg: markdownLink, underline: true },
|
||||
});
|
||||
}
|
||||
|
||||
export function getSyntaxStyle(theme: TerminalTheme = "dark"): SyntaxStyle {
|
||||
return (instances[theme] ??= buildSyntaxStyle(theme));
|
||||
export function getSyntaxStyle(
|
||||
theme: TerminalTheme = "dark",
|
||||
mode: SyntaxAccentMode = "act",
|
||||
): SyntaxStyle {
|
||||
const key = `${theme}:${mode}`;
|
||||
let style = instances.get(key);
|
||||
if (!style) {
|
||||
style = buildSyntaxStyle(theme, mode);
|
||||
instances.set(key, style);
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
useTerminalTheme,
|
||||
} from "../hooks/use-terminal-background";
|
||||
import {
|
||||
getInputRuleColor,
|
||||
getModeAccent,
|
||||
getModeInputBackground,
|
||||
getModeInputForeground,
|
||||
@@ -76,6 +77,7 @@ export function ChatView(props: {
|
||||
const terminalTheme = useTerminalTheme();
|
||||
const accent = getModeAccent(session.uiMode, terminalTheme);
|
||||
const inputBackground = getModeInputBackground(session.uiMode, terminalBg);
|
||||
const inputRuleColor = getInputRuleColor(terminalBg);
|
||||
const inputForeground = getModeInputForeground(session.uiMode, terminalBg);
|
||||
const inputPlaceholder = getModeInputPlaceholder(session.uiMode, terminalBg);
|
||||
const placeholder =
|
||||
@@ -123,10 +125,10 @@ export function ChatView(props: {
|
||||
/>
|
||||
)}
|
||||
|
||||
<box marginBottom={1}>
|
||||
<box>
|
||||
<InputBar
|
||||
accent={accent}
|
||||
inputBackground={inputBackground}
|
||||
ruleColor={inputRuleColor}
|
||||
inputForeground={inputForeground}
|
||||
inputPlaceholder={inputPlaceholder}
|
||||
placeholder={placeholder}
|
||||
|
||||
@@ -721,7 +721,7 @@ export function ConfigPanelContent(props: ConfigPanelProps) {
|
||||
|
||||
return (
|
||||
<box flexDirection="column" paddingX={1}>
|
||||
<text fg="cyan">
|
||||
<text fg={palette.act}>
|
||||
<strong>Settings</strong>
|
||||
</text>
|
||||
|
||||
@@ -793,7 +793,7 @@ export function ConfigPanelContent(props: ConfigPanelProps) {
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<text fg={isSel ? "cyan" : undefined}>{pfx}Provider</text>
|
||||
<text fg={isSel ? palette.act : undefined}>{pfx}Provider</text>
|
||||
<text fg="white">{props.providerDisplayName}</text>
|
||||
</box>
|
||||
);
|
||||
@@ -804,7 +804,7 @@ export function ConfigPanelContent(props: ConfigPanelProps) {
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<text fg={isSel ? "cyan" : undefined}>{pfx}Model</text>
|
||||
<text fg={isSel ? palette.act : undefined}>{pfx}Model</text>
|
||||
<text fg="white">{displayName}</text>
|
||||
</box>
|
||||
);
|
||||
@@ -833,7 +833,7 @@ export function ConfigPanelContent(props: ConfigPanelProps) {
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<text fg={isSel ? "cyan" : undefined}>
|
||||
<text fg={isSel ? palette.act : undefined}>
|
||||
{pfx}
|
||||
{row.label}
|
||||
</text>
|
||||
@@ -866,7 +866,7 @@ export function ConfigPanelContent(props: ConfigPanelProps) {
|
||||
: enabledState === "partial"
|
||||
? "yellow"
|
||||
: isSel
|
||||
? "cyan"
|
||||
? palette.act
|
||||
: "gray";
|
||||
return (
|
||||
<box
|
||||
@@ -886,7 +886,7 @@ export function ConfigPanelContent(props: ConfigPanelProps) {
|
||||
}
|
||||
case "mcp-manager":
|
||||
return (
|
||||
<text key={absIdx} fg={isSel ? "cyan" : "gray"}>
|
||||
<text key={absIdx} fg={isSel ? palette.act : "gray"}>
|
||||
{pfx}Manage MCP Servers...
|
||||
</text>
|
||||
);
|
||||
|
||||
@@ -19,8 +19,8 @@ import {
|
||||
} from "../hooks/use-terminal-background";
|
||||
import {
|
||||
getDefaultForeground,
|
||||
getInputRuleColor,
|
||||
getModeAccent,
|
||||
getModeInputBackground,
|
||||
getModeInputForeground,
|
||||
getModeInputPlaceholder,
|
||||
} from "../palette";
|
||||
@@ -69,7 +69,7 @@ export function HomeView(props: {
|
||||
const terminalTheme = useTerminalTheme();
|
||||
const defaultFg = getDefaultForeground(terminalBg);
|
||||
const accent = getModeAccent(session.uiMode, terminalTheme);
|
||||
const inputBackground = getModeInputBackground(session.uiMode, terminalBg);
|
||||
const inputRuleColor = getInputRuleColor(terminalBg);
|
||||
const inputForeground = getModeInputForeground(session.uiMode, terminalBg);
|
||||
const inputPlaceholder = getModeInputPlaceholder(session.uiMode, terminalBg);
|
||||
const placeholder =
|
||||
@@ -80,7 +80,7 @@ export function HomeView(props: {
|
||||
props.autocomplete?.mode && props.autocomplete.options.length > 0;
|
||||
const contentWidth = Math.min(width, HOME_VIEW_MAX_WIDTH);
|
||||
const hasTypedInput = inputValue.trim().length > 0;
|
||||
const inputStartX = Math.floor((width - contentWidth) / 2) + 4;
|
||||
const inputStartX = Math.floor((width - contentWidth) / 2) + 2;
|
||||
const clamp = (value: number, min: number, max: number) =>
|
||||
Math.max(min, Math.min(max, value));
|
||||
const trackedCursorX = hasTypedInput
|
||||
@@ -116,7 +116,7 @@ export function HomeView(props: {
|
||||
<box flexDirection="column" width={contentWidth} flexShrink={0}>
|
||||
<InputBar
|
||||
accent={accent}
|
||||
inputBackground={inputBackground}
|
||||
ruleColor={inputRuleColor}
|
||||
inputForeground={inputForeground}
|
||||
inputPlaceholder={inputPlaceholder}
|
||||
placeholder={placeholder}
|
||||
|
||||
@@ -58,6 +58,7 @@ import { useOnboardingKeyboard } from "./keyboard";
|
||||
import {
|
||||
CLINE_PASS_SUBSCRIPTION_OPTIONS,
|
||||
type ClinePassSubscriptionStatus,
|
||||
DEFAULT_THINKING_LEVEL_INDEX,
|
||||
getMainMenuOptions,
|
||||
type ModelEntry,
|
||||
type OnboardingResult,
|
||||
@@ -237,7 +238,9 @@ export function useOnboardingController(props: OnboardingControllerProps) {
|
||||
}, []);
|
||||
|
||||
// Thinking level
|
||||
const [thinkingSelected, setThinkingSelected] = useState(0);
|
||||
const [thinkingSelected, setThinkingSelected] = useState(
|
||||
DEFAULT_THINKING_LEVEL_INDEX,
|
||||
);
|
||||
const [selectedModelName, setSelectedModelName] = useState("");
|
||||
const [selectedModelId, setSelectedModelId] = useState("");
|
||||
const [selectedThinking, setSelectedThinking] = useState(false);
|
||||
@@ -641,7 +644,7 @@ export function useOnboardingController(props: OnboardingControllerProps) {
|
||||
const entry = modelEntries.find((m) => m.id === modelId);
|
||||
if (entry?.supportsReasoning) {
|
||||
setSelectedModelName(entry.name);
|
||||
setThinkingSelected(0);
|
||||
setThinkingSelected(DEFAULT_THINKING_LEVEL_INDEX);
|
||||
setStep("thinking_level");
|
||||
} else {
|
||||
setStep("done");
|
||||
@@ -691,7 +694,7 @@ export function useOnboardingController(props: OnboardingControllerProps) {
|
||||
setSelectedModelId(modelId);
|
||||
if (clineModelReasoningIds.has(modelId)) {
|
||||
setSelectedModelName(modelName);
|
||||
setThinkingSelected(0);
|
||||
setThinkingSelected(DEFAULT_THINKING_LEVEL_INDEX);
|
||||
setStep("thinking_level");
|
||||
} else {
|
||||
setStep("done");
|
||||
|
||||
@@ -30,6 +30,10 @@ export const THINKING_LEVELS: {
|
||||
{ value: "xhigh", label: "Extra High", desc: "Maximum reasoning" },
|
||||
];
|
||||
|
||||
export const DEFAULT_THINKING_LEVEL_INDEX = THINKING_LEVELS.findIndex(
|
||||
(l) => l.value === "medium",
|
||||
);
|
||||
|
||||
export interface MenuOption {
|
||||
label: string;
|
||||
value: string;
|
||||
|
||||
@@ -384,7 +384,7 @@ export function OnboardingCodexCliScreen(props: {
|
||||
<text fg="yellow">Codex CLI was not found</text>
|
||||
<text fg="gray">{props.status.reason}</text>
|
||||
<text fg="gray">Install Codex CLI from:</text>
|
||||
<text fg="cyan" selectable>
|
||||
<text fg={palette.act} selectable>
|
||||
{CODEX_CLI_INSTALL_URL}
|
||||
</text>
|
||||
</box>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { formatDisplayUserInput } from "@cline/shared";
|
||||
import type {
|
||||
WebviewActionSessionSummary,
|
||||
WebviewChatMessage,
|
||||
@@ -213,10 +214,16 @@ export function mapHistoryToWebviewMessages(
|
||||
const currentToolBlockIndexes = new Map<string, number>();
|
||||
let reasoningRedacted = false;
|
||||
|
||||
// Persisted user text arrives raw, including runtime-generated
|
||||
// <user_input>/<mode_notice> wrappers -- format at this display
|
||||
// boundary so the webview never renders them.
|
||||
const displayText = (text: string): string =>
|
||||
role === "user" ? formatDisplayUserInput(text) : text;
|
||||
|
||||
const contentParts = historyContentParts(record.content);
|
||||
if (contentParts.length === 0) {
|
||||
const text = stringifyContent(record.content ?? record.text ?? record);
|
||||
pushTextBlock(blocks, textParts, messageKey, 0, text);
|
||||
pushTextBlock(blocks, textParts, messageKey, 0, displayText(text));
|
||||
}
|
||||
|
||||
for (const [partIndex, part] of contentParts.entries()) {
|
||||
@@ -227,7 +234,7 @@ export function mapHistoryToWebviewMessages(
|
||||
textParts,
|
||||
messageKey,
|
||||
partIndex,
|
||||
asString(part.text) ?? asString(part.content) ?? "",
|
||||
displayText(asString(part.text) ?? asString(part.content) ?? ""),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
},
|
||||
"apps/cli": {
|
||||
"name": "@cline/cli",
|
||||
"version": "3.0.34",
|
||||
"version": "3.0.37",
|
||||
"bin": {
|
||||
"cline": "src/index.ts",
|
||||
},
|
||||
@@ -616,7 +616,7 @@
|
||||
},
|
||||
"sdk/packages/agents": {
|
||||
"name": "@cline/agents",
|
||||
"version": "0.0.55",
|
||||
"version": "0.0.58",
|
||||
"dependencies": {
|
||||
"@cline/llms": "workspace:*",
|
||||
"@cline/shared": "workspace:*",
|
||||
@@ -625,7 +625,7 @@
|
||||
},
|
||||
"sdk/packages/core": {
|
||||
"name": "@cline/core",
|
||||
"version": "0.0.55",
|
||||
"version": "0.0.58",
|
||||
"dependencies": {
|
||||
"@cline/agents": "workspace:*",
|
||||
"@cline/llms": "workspace:*",
|
||||
@@ -663,7 +663,7 @@
|
||||
},
|
||||
"sdk/packages/llms": {
|
||||
"name": "@cline/llms",
|
||||
"version": "0.0.55",
|
||||
"version": "0.0.58",
|
||||
"dependencies": {
|
||||
"@ai-sdk/amazon-bedrock": "^4.0.89",
|
||||
"@ai-sdk/anthropic": "^3.0.68",
|
||||
@@ -697,14 +697,14 @@
|
||||
},
|
||||
"sdk/packages/sdk": {
|
||||
"name": "@cline/sdk",
|
||||
"version": "0.0.55",
|
||||
"version": "0.0.58",
|
||||
"dependencies": {
|
||||
"@cline/core": "workspace:*",
|
||||
},
|
||||
},
|
||||
"sdk/packages/shared": {
|
||||
"name": "@cline/shared",
|
||||
"version": "0.0.55",
|
||||
"version": "0.0.58",
|
||||
"dependencies": {
|
||||
"aws4fetch": "^1.0.20",
|
||||
"jsonrepair": "^3.13.2",
|
||||
@@ -741,27 +741,27 @@
|
||||
|
||||
"@agentclientprotocol/sdk": ["@agentclientprotocol/sdk@0.16.1", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-1ad+Sc/0sCtZGHthxxvgEUo5Wsbw16I+aF+YwdiLnPwkZG8KAGUEAPK6LM6Pf69lCyJPt1Aomk1d+8oE3C4ZEw=="],
|
||||
|
||||
"@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.122", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.87", "@ai-sdk/openai": "3.0.75", "@ai-sdk/provider": "3.0.11", "@ai-sdk/provider-utils": "4.0.31", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-XiSsWFfX0W8lGFWZ/7NwbmdWEk/16lArmdi7LDVJkskKWwoRM1pexL6E+UPmzJ4sBsz01be+stYXIjEs64h7lQ=="],
|
||||
"@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.125", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.90", "@ai-sdk/openai": "3.0.78", "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7C+ud1t6biknsr+fSOSOeFJXYrPAjOouSUPu2ZJ94pXywI2W7Y3E3Rn0s2/NYViknRgY0UBcLY9GR1KKwhf1Yg=="],
|
||||
|
||||
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.87", "", { "dependencies": { "@ai-sdk/provider": "3.0.11", "@ai-sdk/provider-utils": "4.0.31" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-4v7uoMblNYZ3X7S5a+manSKKqKVmWXTkJOtZ8ymArHdQbhgzMd+um1qDee8MiJbDhk6wjy8T/F+D1pVhB/7HTQ=="],
|
||||
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.90", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7K51KyEyyQPcvBdrxB+TPmHzmuXPhyDNwTZuqTcsYp2GbB0E2SzoM1qEJ4qLb1H2Q8xx5SkkOhATmDxC4oVo9A=="],
|
||||
|
||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.137", "", { "dependencies": { "@ai-sdk/provider": "3.0.11", "@ai-sdk/provider-utils": "4.0.31", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OIOBsRq8hrpML0kdT1QqC2s6nLnmX8G60xvukFJeWUd+jguY2WngzPVQkwlRBJN137LtEa7QyA0NMU3uxxVy3g=="],
|
||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.140", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-4VyQTHHqfZ0qI1fCcurJgYgzVDgLfV4svzBMOHGGxCu4srFkAn4ZmwFj2M0J00kNt7QLsjOtZ6PhueupeIJSjA=="],
|
||||
|
||||
"@ai-sdk/google": ["@ai-sdk/google@3.0.84", "", { "dependencies": { "@ai-sdk/provider": "3.0.11", "@ai-sdk/provider-utils": "4.0.31" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TVLcerZs7D70nHGPhtb5cwwX41CzKSVE00IEHRTRXXBa35g6BJdxi48YPglrrP9gDCAPSrl60/Nh5SBMMTwkwQ=="],
|
||||
"@ai-sdk/google": ["@ai-sdk/google@3.0.86", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-NZoFXTdK2/C7VuuGhAatoQ/wSiIvxVzw4Xr0AvcD3cotS5+iP/y0eN1J12pvFSZv+nAHa2Xl7xvFHDadzeU90g=="],
|
||||
|
||||
"@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@4.0.150", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.87", "@ai-sdk/google": "3.0.84", "@ai-sdk/openai-compatible": "2.0.52", "@ai-sdk/provider": "3.0.11", "@ai-sdk/provider-utils": "4.0.31", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-67hfINiuyXHlo4eiAc6gPH+8EPSrMg9c3t0bmC2Dm6DsjW1l7M5HTt+eKtetdJJh/yBWMeJKi2ujLrP6oXvPaQ=="],
|
||||
"@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@4.0.153", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.90", "@ai-sdk/google": "3.0.86", "@ai-sdk/openai-compatible": "2.0.54", "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZPPjMRkTmdRzDSjxlZFJXskuAtyTYffnPVQjbWDTNqiUTGOHQaxxRuqibepJqQ19pnDe72Yj1r+fL2kNkhml+g=="],
|
||||
|
||||
"@ai-sdk/mistral": ["@ai-sdk/mistral@3.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.11", "@ai-sdk/provider-utils": "4.0.31" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-xpZCV8cj/cFjPeTUK/ejlSGYCjWzY3RIo+4zKbwO7iIDu7zL/3Ezj5+Jgoi9pbd68jdScYyY9McTh5cp90wYjQ=="],
|
||||
"@ai-sdk/mistral": ["@ai-sdk/mistral@3.0.43", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-FtFcf0eXEm1v8JiDYe4fyQoRz9JmK5/LLH8nawFIttkxc309TsuPNFfwpSgj2Fm5osrBFL49FGPEL9phJVav7A=="],
|
||||
|
||||
"@ai-sdk/openai": ["@ai-sdk/openai@3.0.75", "", { "dependencies": { "@ai-sdk/provider": "3.0.11", "@ai-sdk/provider-utils": "4.0.31" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-xKW+ZSHOdsFIUR6H2uSVjQQmzuHG+onsBZQmsr1OagDK/G55Vhx7Msd/5itoIT/kfGIhOGtCY0DTxbP0RWT7hA=="],
|
||||
"@ai-sdk/openai": ["@ai-sdk/openai@3.0.78", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-XlRHyAe1zvetAO1lXVQSNy8acsdd+kznTfmedXBCe7Pvu7lEGGePL8iUg/jH2qLqnlrIpYovuCd3jC2hSTOTsA=="],
|
||||
|
||||
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.52", "", { "dependencies": { "@ai-sdk/provider": "3.0.11", "@ai-sdk/provider-utils": "4.0.31" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-WdVesd9VJQv8BLLla+x1AjLa40D3QUfnXH488+ydOcOIX7c4m6RF8Sh3JsAF+5ICa2Vknc9GTBlOvqCKoivE1w=="],
|
||||
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.54", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OyXt0zK8y2/ZIyWlbxTv2r1M7AK227S+Gl4BYOEF42q0wz1n5m4fwR8L4Fy/MQ4Ho6xje47MPsFcRdIqIyP6Rw=="],
|
||||
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@3.0.11", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-GKu3RxsfKGWjBiXmEdsKsGR9uVgJ56mzL1w7mLsn5k2TiNtpyS2IYQo3v1NJpK3oyv2OVavlK3g801VSe+gujg=="],
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@3.0.12", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-sj9DWTJ2Ze0WR9qsiOPqoqzNx3OxL6iMxHImbhvoe9qOspekbzxNDMiJ4TIGfYHYh9w4OmBjz3prvqhzTi96+Q=="],
|
||||
|
||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.31", "", { "dependencies": { "@ai-sdk/provider": "3.0.11", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-x4Q1NxNLw8V1AHKOunukpksbKCqzZdZEgpHgbZznUE3ZcWb2liI5j2321TlOvyfn1iL7NmNMFTD5mZYoChVx0g=="],
|
||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.33", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-nJ0bAfegMAIJtrzMJtbzer1cS3nb7c7DsyU1S4nrPm7ZU0Mn6SBBZv5IGZZGTbpWTJwqKTSPeZJTXalbAxt1BA=="],
|
||||
|
||||
"@ai-sdk/react": ["@ai-sdk/react@3.0.214", "", { "dependencies": { "@ai-sdk/provider-utils": "4.0.31", "ai": "6.0.212", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" } }, "sha512-GMmwzW6LAHMqrfDsv5NBnQ1EFYYHDt6SjjWdv/d2WRVx6wYUPqdfpr8JHfckVJNIr88trqrbrJAF2APWXkLTVQ=="],
|
||||
"@ai-sdk/react": ["@ai-sdk/react@3.0.218", "", { "dependencies": { "@ai-sdk/provider-utils": "4.0.33", "ai": "6.0.216", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1" } }, "sha512-gFtotqv2JmJeUIjmMigdIwwUbABXjJb786anZ26AcaLVSC/pKqhhtzYsT0uef5MuEcLquTzBAFtu6SY3Ov2I5Q=="],
|
||||
|
||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||
|
||||
@@ -769,30 +769,28 @@
|
||||
|
||||
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.3.193", "", { "optionalDependencies": { "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.193", "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.193", "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.193", "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.193", "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.193", "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.193", "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.193", "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.193" }, "peerDependencies": { "@anthropic-ai/sdk": ">=0.93.0", "@modelcontextprotocol/sdk": "^1.29.0", "zod": "^4.0.0" } }, "sha512-WzL03VJE1sT0Nz3rEpsYMYR+9n6iyQtLVt7ghMWnYC9pvDsiy6kwcMplZniWSjH8Dm6CfkUBN5t6KB4i/JfouA=="],
|
||||
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.3.196", "", { "optionalDependencies": { "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.196", "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.196", "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.196", "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.196", "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.196", "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.196", "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.196", "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.196" }, "peerDependencies": { "@anthropic-ai/sdk": ">=0.93.0", "@modelcontextprotocol/sdk": "^1.29.0", "zod": "^4.0.0" } }, "sha512-yqsp1/04T2/tJ54jz+7YLsTZOPeQ/myUCrv17/IVZ9dbl+izIMP9ULuLpPCH5pj5msXxR80es+hpVgHoFuNm0A=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-arm64": ["@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.193", "", { "os": "darwin", "cpu": "arm64" }, "sha512-1hT7b+KIm/3E1OSJofr7PF21Xq2zT1ccnjzuVcWQ5LYXJ09lgCMvA/ZfcDBKuoyCZ4lSnuicKXZ/h5vRbWfqrA=="],
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-arm64": ["@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.196", "", { "os": "darwin", "cpu": "arm64" }, "sha512-k1MKRDhSiNKpkTwhtU8QKGzfuRfr3YXS6oqsTuldMROX56L5iMXjzC7AYU1/KmPTeMl3SCQBQeDu0i8ciA0hQA=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-x64": ["@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.193", "", { "os": "darwin", "cpu": "x64" }, "sha512-9x5Y/L6iwETwEJFmPaYXfsE8q0cVgx75V7nL60HvSzi8K1XQNcG5u53jOzRvqDNah8mvGYOb+9AWrMCSJvmFyA=="],
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-x64": ["@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.196", "", { "os": "darwin", "cpu": "x64" }, "sha512-bBwx/7yKZMQ9NSUt4bg8P+zp6pgd/O/DTkzdqsRIivBvARmwo1QY/2qGrLO8RH0T8CG2lTjFNfDfOlJWbAkvAg=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64": ["@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.193", "", { "os": "linux", "cpu": "arm64" }, "sha512-gvfD9pKHXWxCkkIX6bC4/FOALTxqHYjAu83iT1bzn5mCv6QWSZRl6WLRRtvKpWtWuY1jpML1lL3YfKADsAX/rA=="],
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64": ["@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.196", "", { "os": "linux", "cpu": "arm64" }, "sha512-fR5fy+pSQSpKZK0zTtAl3LZEGQTuwVK7svutH1bZUS5RGT2HdUWc71oltSZgW4upGaslj+gyusHGJHA5eAc+dw=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": ["@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.193", "", { "os": "linux", "cpu": "arm64" }, "sha512-a3qsVTBe4G6ndsVavfIXEVAXLVXM8uvBUNYpm4jKqk2+ovWZQe/96CXOwmerg9U+/bllg4QJ9lSyYCsdtVIr6w=="],
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": ["@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.196", "", { "os": "linux", "cpu": "arm64" }, "sha512-BhLxfx4j6mC3Uzmve1IbhFS1uvNlwATeo6uWyYDOMW4n3XKjiSgjD8bTfkamijrxCMvJo5swLju2y14ayDsokA=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64": ["@anthropic-ai/claude-agent-sdk-linux-x64@0.3.193", "", { "os": "linux", "cpu": "x64" }, "sha512-1sz+7cn0iuh0ThInuAYF1jpFvLyOaZ0PZYQIF7eb9JDZbBohUf6INeTCwjAwUL0ASCq2xS7Odu/qDVuTtLTeDA=="],
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64": ["@anthropic-ai/claude-agent-sdk-linux-x64@0.3.196", "", { "os": "linux", "cpu": "x64" }, "sha512-9spZON7/tn0q9J+jICrdfHi7o7Fmjs9pIohCCxL+Yv7HbBXWVtEYJbYipBGLTl8ICG3mgPeEVMNsvOuh/jDTuA=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": ["@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.193", "", { "os": "linux", "cpu": "x64" }, "sha512-DLXlO4tlcWygz0Ft4nu6ai5KssByYt2tOeWdc4dFXKt6uBKXpbZVziUUq3ePO5zuAFyU6w7EjYLv8MMPURbAiQ=="],
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": ["@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.196", "", { "os": "linux", "cpu": "x64" }, "sha512-EOiNbxCXQLYzV7SQhMWkUC1ScWyTw/Qp+JyV2sEmIbzl/e7KMOxNE9J20k+lpPs6CXdxVzuMwH7yAGuDu5y+IQ=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-win32-arm64": ["@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.193", "", { "os": "win32", "cpu": "arm64" }, "sha512-36LJKiGuKusgaPTVeh9QanL00UcaE0RcC4pgK800/0SenApbh979ndxI0XKUVfLHzlGkqlhkhT3foMdqS+zx1w=="],
|
||||
"@anthropic-ai/claude-agent-sdk-win32-arm64": ["@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.196", "", { "os": "win32", "cpu": "arm64" }, "sha512-0xXkAWlDof/qFi3k5KJZ5WYbgp1X8hZHjyasOWTZWAmldoYaENI0vkL+PVMarvoAFYRRqcWoS81FSgm0QgH2sA=="],
|
||||
|
||||
"@anthropic-ai/claude-agent-sdk-win32-x64": ["@anthropic-ai/claude-agent-sdk-win32-x64@0.3.193", "", { "os": "win32", "cpu": "x64" }, "sha512-VyyKZlWQpbD6nkUTeNvgmLvpqt1QaPQQBOC30tbEYwYsV5MC1I35Li0H7nWwngGqPSTtMvHpjpz6Eb2FSTn7/A=="],
|
||||
"@anthropic-ai/claude-agent-sdk-win32-x64": ["@anthropic-ai/claude-agent-sdk-win32-x64@0.3.196", "", { "os": "win32", "cpu": "x64" }, "sha512-FxWLA3aOYgDf2J0o6Ov1/wgg9X6RkrgnX4ifUWO1i3+6mbc4efNLHkDZLxCHEnQgW8yBidX+iro19f9k64vV8A=="],
|
||||
|
||||
"@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.37.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-tHjX2YbkUBwEgg0JZU3EFSSAQPoK4qQR/NFYa8Vtzd5UAyXzZksCw2In69Rml4R/TyHPBfRYaLK35XiOe33pjw=="],
|
||||
|
||||
"@asamuzakjp/css-color": ["@asamuzakjp/css-color@3.2.0", "", { "dependencies": { "@csstools/css-calc": "^2.1.3", "@csstools/css-color-parser": "^3.0.9", "@csstools/css-parser-algorithms": "^3.0.4", "@csstools/css-tokenizer": "^3.0.3", "lru-cache": "^10.4.3" } }, "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw=="],
|
||||
|
||||
"@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="],
|
||||
|
||||
"@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="],
|
||||
|
||||
"@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="],
|
||||
@@ -801,41 +799,41 @@
|
||||
|
||||
"@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="],
|
||||
|
||||
"@aws-sdk/client-cognito-identity": ["@aws-sdk/client-cognito-identity@3.1075.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.23", "@aws-sdk/credential-provider-node": "^3.972.58", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/fetch-http-handler": "^5.4.6", "@smithy/node-http-handler": "^4.7.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-typFcdyFwIPt86QPKsO7xwcsYoEmNcDpoNqn0tqa4+Lss7niNKQzPe/765XNgAHO3I1ixiT1OKv8KD6M+CKw2w=="],
|
||||
"@aws-sdk/client-cognito-identity": ["@aws-sdk/client-cognito-identity@3.1076.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.24", "@aws-sdk/credential-provider-node": "^3.972.59", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/fetch-http-handler": "^5.6.0", "@smithy/node-http-handler": "^4.9.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-hSkEljVcPBXPSsB/GLeVZaNaIzrMLPAj//jg41rNObfMGa7qRvWHXtbDt7UVxXjAFlVw84wCFWNBMBSql5HynQ=="],
|
||||
|
||||
"@aws-sdk/core": ["@aws-sdk/core@3.974.23", "", { "dependencies": { "@aws-sdk/types": "^3.973.13", "@aws-sdk/xml-builder": "^3.972.31", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.6", "@smithy/signature-v4": "^5.4.6", "@smithy/types": "^4.14.3", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-MiWR/uWjxjFXGzrE0Ghc5lWxUxzHsUWFhV+OX7M4cR9SrmrnZs6TXavnCWnzzdwJeFri34xQo81rvGNzK3c4BQ=="],
|
||||
"@aws-sdk/core": ["@aws-sdk/core@3.974.24", "", { "dependencies": { "@aws-sdk/types": "^3.973.14", "@aws-sdk/xml-builder": "^3.972.32", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.27.0", "@smithy/signature-v4": "^5.5.3", "@smithy/types": "^4.15.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-vWB/qJl21vxGKBkBN8fKPTVXgm14v/bUQWTtR5oikrfAZbIN2bxuSiCY5rRAMR4gs3vtR2Vw0aTfVDU4tdfIPg=="],
|
||||
|
||||
"@aws-sdk/credential-provider-cognito-identity": ["@aws-sdk/credential-provider-cognito-identity@3.972.48", "", { "dependencies": { "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-dTSY4wCPx87Gd1peDcTop1li61f6KLAs3LSlq/omnCxpIOvMDpAQjylJ7ZDaZk6KA88+oZ0k/XuVSou1YuWI/w=="],
|
||||
"@aws-sdk/credential-provider-cognito-identity": ["@aws-sdk/credential-provider-cognito-identity@3.972.49", "", { "dependencies": { "@aws-sdk/nested-clients": "^3.997.24", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-PU8EJj5wMvTqp5oeBVCPK1vqraQ9ZlUVYTM5Bbvq1pBTY3WGr2wgvnGCRalFQpS7BFUQflpjumHcaQBmkOhfBA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.49", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-liB3yQNHCM9k/gu/w36XHMKPluT7HTlnGUhRbBGSISDQkcr/Sy1zsZabiuvQj8WG5yW573u9RehrBvvnIQ9OEQ=="],
|
||||
"@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.50", "", { "dependencies": { "@aws-sdk/core": "^3.974.24", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-l8bWzhPFTi9tDcvtURxeMlfsboul5/0sEN3SwwXxdpYudVB9+EuQcxo2pwlTzXwDo4Gm2VLGyiZ8zti3nfdOLw=="],
|
||||
|
||||
"@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.51", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/fetch-http-handler": "^5.4.6", "@smithy/node-http-handler": "^4.7.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-XET0H2oofciJ5lMRWNIvRjAP7Q3wv2XT+JtJJEdhPWUMwe3TvQ9qcxonpu7vXmNngncvFpi4E2It+Tamas/naA=="],
|
||||
"@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.52", "", { "dependencies": { "@aws-sdk/core": "^3.974.24", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/fetch-http-handler": "^5.6.0", "@smithy/node-http-handler": "^4.9.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-FjAlnsIvemWzO3JTM3ObuuxpqCyrqkXOewlYY2+NiR1MYO1JuFYSIJ8SJN5Q2KD1jkL5lIuab8awjb/AxsvjiQ=="],
|
||||
|
||||
"@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.56", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/credential-provider-env": "^3.972.49", "@aws-sdk/credential-provider-http": "^3.972.51", "@aws-sdk/credential-provider-login": "^3.972.55", "@aws-sdk/credential-provider-process": "^3.972.49", "@aws-sdk/credential-provider-sso": "^3.972.55", "@aws-sdk/credential-provider-web-identity": "^3.972.55", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/credential-provider-imds": "^4.3.7", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-IAmc61hbgQiHht9U3x0tnRwz0lzdwOwD/i9voRgdJrKamF+JtmrBOsW9GwB7mfFonNWOWL4qARWYrF8veEMe3w=="],
|
||||
"@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.57", "", { "dependencies": { "@aws-sdk/core": "^3.974.24", "@aws-sdk/credential-provider-env": "^3.972.50", "@aws-sdk/credential-provider-http": "^3.972.52", "@aws-sdk/credential-provider-login": "^3.972.56", "@aws-sdk/credential-provider-process": "^3.972.50", "@aws-sdk/credential-provider-sso": "^3.972.56", "@aws-sdk/credential-provider-web-identity": "^3.972.56", "@aws-sdk/nested-clients": "^3.997.24", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/credential-provider-imds": "^4.4.3", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-8qwNhQ0sK/1KaOpVEFC7TFxrWP3fxzJV1K049MzjouiMIbvTDvIGDEUtj5ND5aTmlHVK/YZxjoYnLCeV/GZU0w=="],
|
||||
|
||||
"@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.55", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-hBBkANo3cDn+h2qxxzER4a+J8JCO9o9Z/YYmU7iky6AcaarX5RRdRcHNC6SLdwY0vAXQygn6soUbDqPn3GghaA=="],
|
||||
"@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.56", "", { "dependencies": { "@aws-sdk/core": "^3.974.24", "@aws-sdk/nested-clients": "^3.997.24", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-S36dCrDaafakFMlaCVGAF4advbQKoJuMcyMtNWVBpUz65uqhbIAsUfvAyp+djA+jkzaEfgZGd+AELjIGzTqyhw=="],
|
||||
|
||||
"@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.58", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.49", "@aws-sdk/credential-provider-http": "^3.972.51", "@aws-sdk/credential-provider-ini": "^3.972.56", "@aws-sdk/credential-provider-process": "^3.972.49", "@aws-sdk/credential-provider-sso": "^3.972.55", "@aws-sdk/credential-provider-web-identity": "^3.972.55", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/credential-provider-imds": "^4.3.7", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-OyCLVmSI7pZO8hxwNVX6pXhTVlJqRBTp+ijdEfJSUj0RyjHnF602OfAarOzGq6wkGodeFkYBt8MmJ6A6ycRgWw=="],
|
||||
"@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.59", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.50", "@aws-sdk/credential-provider-http": "^3.972.52", "@aws-sdk/credential-provider-ini": "^3.972.57", "@aws-sdk/credential-provider-process": "^3.972.50", "@aws-sdk/credential-provider-sso": "^3.972.56", "@aws-sdk/credential-provider-web-identity": "^3.972.56", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/credential-provider-imds": "^4.4.3", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-LkczBXaEsdManijlEZwbKfEoo1C98Yri3LHF8gQI7CYWv+uFkmpS3OZH3BSew8g1A2ppKsScdPUSlhI6NV7a9g=="],
|
||||
|
||||
"@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.49", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-C8h36lBuC/RnBSsjlO+dn6xZm3KbAl5vpJaVPAfQnMmz2/OISmKOc8XZcqMQgO2ADwBYNRMM6Kf3vz9G/TulMQ=="],
|
||||
"@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.50", "", { "dependencies": { "@aws-sdk/core": "^3.974.24", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-ARBEVkOQzmowTU0a35smGVyldJ9FN/f57XIGrPatrul4mYN+vvOKxoc1njDOX3nugVze+0sHzQZWJ8kPARAtUA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.55", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/token-providers": "3.1074.0", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-1FkOz74Ea5QGS9jtIoXp55T/IkSS3spv+nLTT07fRY/+T5xmEOqaYBVIaEmX4zTNvbV6g2lrtlaVKWEoNyJt3w=="],
|
||||
"@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.56", "", { "dependencies": { "@aws-sdk/core": "^3.974.24", "@aws-sdk/nested-clients": "^3.997.24", "@aws-sdk/token-providers": "3.1076.0", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-LvbWiFcLI/D5RPaT68TrpLLHyv7x5X+dm59wJ5dFizyGPZggBC7OdgJTlP0X1bVjiSSAgE1u1oxxcBps0GCEnA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.55", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-g2BoECD1q01kTPByi56+VLVvdWDzMkKIcr77qixpqH0okw2t0U5CoPv+6S8v/D1Y2Wa6QKKtn6XAtDzP+Kfpvg=="],
|
||||
"@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.56", "", { "dependencies": { "@aws-sdk/core": "^3.974.24", "@aws-sdk/nested-clients": "^3.997.24", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-OV3JxmqMphVGMLWupYD2UhZxX07ATk1NwyYk7RgCnAEh0y3owHmtEnkWZ3ciCZ6liiFEwS8dYQpJGmKsR6ml4Q=="],
|
||||
|
||||
"@aws-sdk/credential-providers": ["@aws-sdk/credential-providers@3.1075.0", "", { "dependencies": { "@aws-sdk/client-cognito-identity": "3.1075.0", "@aws-sdk/core": "^3.974.23", "@aws-sdk/credential-provider-cognito-identity": "^3.972.48", "@aws-sdk/credential-provider-env": "^3.972.49", "@aws-sdk/credential-provider-http": "^3.972.51", "@aws-sdk/credential-provider-ini": "^3.972.56", "@aws-sdk/credential-provider-login": "^3.972.55", "@aws-sdk/credential-provider-node": "^3.972.58", "@aws-sdk/credential-provider-process": "^3.972.49", "@aws-sdk/credential-provider-sso": "^3.972.55", "@aws-sdk/credential-provider-web-identity": "^3.972.55", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/credential-provider-imds": "^4.3.7", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-2HoJ1IxwdzEryyUmZvl6dVKfgWBnS6NzSDl5hOqmbHns5Cy+wCQLDFU+HGVi+kTGZgSyMZIa0rH7fQvNf7v9jQ=="],
|
||||
"@aws-sdk/credential-providers": ["@aws-sdk/credential-providers@3.1076.0", "", { "dependencies": { "@aws-sdk/client-cognito-identity": "3.1076.0", "@aws-sdk/core": "^3.974.24", "@aws-sdk/credential-provider-cognito-identity": "^3.972.49", "@aws-sdk/credential-provider-env": "^3.972.50", "@aws-sdk/credential-provider-http": "^3.972.52", "@aws-sdk/credential-provider-ini": "^3.972.57", "@aws-sdk/credential-provider-login": "^3.972.56", "@aws-sdk/credential-provider-node": "^3.972.59", "@aws-sdk/credential-provider-process": "^3.972.50", "@aws-sdk/credential-provider-sso": "^3.972.56", "@aws-sdk/credential-provider-web-identity": "^3.972.56", "@aws-sdk/nested-clients": "^3.997.24", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/credential-provider-imds": "^4.4.3", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-1jmzAXZdQzZKT/edDehSuxBfFo9M90nyLMGV65joOaZusa/p3YEPtPdHhTQ1CWoYq9kBBsMcfMElSbKjAfYTJw=="],
|
||||
|
||||
"@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.23", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.23", "@aws-sdk/signature-v4-multi-region": "^3.996.35", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/fetch-http-handler": "^5.4.6", "@smithy/node-http-handler": "^4.7.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-gO93ZPsI2bxeFZD42f1/qjDw6FAZkNZcKRO94LIiT03fzOmcJ9e/tunxjVjA1Rl69ClmVJzz8H3G9CdKef10PA=="],
|
||||
"@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.24", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.24", "@aws-sdk/signature-v4-multi-region": "^3.996.36", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/fetch-http-handler": "^5.6.0", "@smithy/node-http-handler": "^4.9.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-+wFVfVofxeiXdRhUjRwYISB2mVfBCdiCq1wThkRipTeOc10Kyr+LS9QJTjgZuhWsna7jyLMPndrCnzLGWWvZXg=="],
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.35", "", { "dependencies": { "@aws-sdk/types": "^3.973.13", "@smithy/signature-v4": "^5.4.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-6L/VWs+Wch2stHemCGTmUNqKLMzURxQDK5boNG3Jn3kAOp71meDUuS5sbObpEvFxHDq0uWeSLFDNSYsjNt+Dlg=="],
|
||||
"@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.36", "", { "dependencies": { "@aws-sdk/types": "^3.973.14", "@smithy/signature-v4": "^5.5.3", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-VSOWIPkI+g3a7NkxIBCO24HnsR0BZXJAi3wrKaGIZwVKyrMtNRdHxPrQI/igazgla5J9FhDzmg4RgnOSr6UQBw=="],
|
||||
|
||||
"@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1074.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.23", "@aws-sdk/nested-clients": "^3.997.23", "@aws-sdk/types": "^3.973.13", "@smithy/core": "^3.24.6", "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-pv80IzgGW4RnXWtft692chZOM9i6PhebVsLCcnaM4dBEPZva2fE6FXAHs76G7Rc7s3yGyX/68G0nZMrUy+Vmpg=="],
|
||||
"@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1076.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.24", "@aws-sdk/nested-clients": "^3.997.24", "@aws-sdk/types": "^3.973.14", "@smithy/core": "^3.27.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-4rTHETRKe2JWAsFUMo5ENmlzc3i9FD4KqBVXgoaF8DLTADjGid8SA+1LR2nJWjefoafvKAHcQH9F2iKa8uHc6Q=="],
|
||||
|
||||
"@aws-sdk/types": ["@aws-sdk/types@3.973.13", "", { "dependencies": { "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-pEHZqRkAlHfnfAU9tK+WpKv/gBNjGJrHMgA3A0iYRGyswBS2t0pfez+lWlwktb3Bqa0ovh7w/QJTFwp3fDxLNg=="],
|
||||
"@aws-sdk/types": ["@aws-sdk/types@3.973.14", "", { "dependencies": { "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-vH4pEu9YBEwr67yT+GVcmKX0GzfIrIYUn+MF5vXg9OspouVnAekuyVyawFvZHEK7WlcwVDwNrqI3ZBDUAiyu9A=="],
|
||||
|
||||
"@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.8", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g=="],
|
||||
|
||||
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.31", "", { "dependencies": { "@smithy/types": "^4.14.3", "tslib": "^2.6.2" } }, "sha512-SzE4Pgyl+hDF+BuyuzxUSpwnuUu9lJuO1YGgteG89/4Qv0+2IQiVQqdbPV32IozLvXWQChPQcdkk/sKvb1QHiQ=="],
|
||||
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.32", "", { "dependencies": { "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-2loKuOMRFDg1nwdni5AtJ9S5juVbRNPNsPC7tWTfkHyycPwACMhxepspUHi8GhvfNlL2cQo3sPMod1uib+KZ0w=="],
|
||||
|
||||
"@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.4", "", {}, "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ=="],
|
||||
|
||||
@@ -1753,9 +1751,9 @@
|
||||
|
||||
"@playwright/test": ["@playwright/test@1.61.1", "", { "dependencies": { "playwright": "1.61.1" }, "bin": { "playwright": "cli.js" } }, "sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig=="],
|
||||
|
||||
"@posthog/core": ["@posthog/core@1.38.0", "", { "dependencies": { "@posthog/types": "^1.391.1" } }, "sha512-QLrJh0hMVpEJXHNyiJR9YhvIO5tzLDedw4UHdvB+ub4fXHMtHCA8H44qgl11HWR3ajpjxtJ8hs3HyOGVF3Zc1w=="],
|
||||
"@posthog/core": ["@posthog/core@1.38.1", "", { "dependencies": { "@posthog/types": "^1.392.0" } }, "sha512-tsJTugsKzx47eRMjNfG272/GFf0FF0LeI+gyJ/anibpbYAzdNuX5kr6enpmJrhdgLESqzJGH8QF0+I9075Xr1Q=="],
|
||||
|
||||
"@posthog/types": ["@posthog/types@1.391.1", "", {}, "sha512-ASwd7Nf4pViqdYRYaNRyPYRVKWa1CcHUAUWR0XeQJLGdNnsWACBwe0sSieb/cHnKsRXjRwO/23KIY83lm/Ccpw=="],
|
||||
"@posthog/types": ["@posthog/types@1.392.0", "", {}, "sha512-nctNujXL3FC1v99FktaTMSugSD9ZOZekEpahUSafkU2TSvW+XGKNkQZbokuJtiWvPBK208dwMJva8UfBkChqpw=="],
|
||||
|
||||
"@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="],
|
||||
|
||||
@@ -1777,7 +1775,7 @@
|
||||
|
||||
"@protobufjs/utf8": ["@protobufjs/utf8@1.1.1", "", {}, "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg=="],
|
||||
|
||||
"@puppeteer/browsers": ["@puppeteer/browsers@2.13.2", "", { "dependencies": { "debug": "^4.4.3", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", "semver": "^7.7.4", "tar-fs": "^3.1.1", "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" } }, "sha512-5EUZSUIc37H6aIXyWO0Z4y8NlF8NnjgmqeQgOGiswAU7pY0HOo16ho4+alIWmSfdZnjqBRawMsP3I5YqLSn6kw=="],
|
||||
"@puppeteer/browsers": ["@puppeteer/browsers@2.6.1", "", { "dependencies": { "debug": "^4.4.0", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", "semver": "^7.6.3", "tar-fs": "^3.0.6", "unbzip2-stream": "^1.4.3", "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" } }, "sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg=="],
|
||||
|
||||
"@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
|
||||
|
||||
@@ -2259,25 +2257,25 @@
|
||||
|
||||
"@slack/web-api": ["@slack/web-api@7.17.0", "", { "dependencies": { "@slack/logger": "^4.0.1", "@slack/types": "^2.21.0", "@types/node": ">=18", "@types/retry": "0.12.0", "axios": "^1.16.0", "eventemitter3": "^5.0.1", "form-data": "^4.0.4", "is-electron": "2.2.2", "is-stream": "^2", "p-queue": "^6", "p-retry": "^4", "retry": "^0.13.1" } }, "sha512-jejr34a8B4L5AS713wOAx1LAqNkW16HVMDEa6sYBvFDc/llUBl8hXaiI4BwF+Al+Sug19Vn2O7iokTVIhVvZ1Q=="],
|
||||
|
||||
"@smithy/core": ["@smithy/core@3.26.0", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-mLUktFAn+Pa2agl1J7VgtYNFWCX8/b4GMJSK1hCu4YCvtBfM6F8Os3EP4ry+DFFlXOf3wyvlgXhuUdFoy52D3g=="],
|
||||
"@smithy/core": ["@smithy/core@3.28.0", "", { "dependencies": { "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-N/LoLG8pZ1zv5cIWpdF6vmSjtZtXKK9G0OqT5yYCOZU+CzPq1+nYA95VoKJBGWRScs7YbMugZ7lZx8Fj1vdHoA=="],
|
||||
|
||||
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.4.2", "", { "dependencies": { "@smithy/core": "^3.26.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-18UMDMyrAbDcpmL1gLUA7ww0fRTcdCrSjSJOi2Sbld+tVjwD/pW+OAwjlScFLR7vvBnhZrIPQ7kVuTf1mnJLug=="],
|
||||
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.4.4", "", { "dependencies": { "@smithy/core": "^3.28.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-jT0WrDaM88L5na9FX1xRNywCS3B1n75wPY5Ksasjo0PHUtuI7d8FclksN1BbOSYTiaiKxUDqU23nUymH/V+AaQ=="],
|
||||
|
||||
"@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.4.2", "", { "dependencies": { "@smithy/core": "^3.26.0", "tslib": "^2.6.2" } }, "sha512-iv6jeGoL5dIGXglIe0aJb8vvTuJkGB4z0LeB2mKV0PH9iAlr4jNhRhEWU7ZGmIeNC+8Zj6jhmSumDez6DidTOA=="],
|
||||
"@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.4.4", "", { "dependencies": { "@smithy/core": "^3.28.0", "tslib": "^2.6.2" } }, "sha512-DStvMemWlcZRXkP9XdCsinolM6yZd4fL2NiQItC8n/I+JC6utkLr0Dc+wLjLqjPyAJR1zXt7inSflea217yGlw=="],
|
||||
|
||||
"@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.5.2", "", { "dependencies": { "@smithy/core": "^3.26.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-Ei/UK/QMhq0rKaMqGPlOAkE2yS9DZeYmZdk1RAKc3vp3zxgleZHZyBLlZv8yLsxljX4svCRuMTD6u3LLIcU4Bg=="],
|
||||
"@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.6.1", "", { "dependencies": { "@smithy/core": "^3.28.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-fW6l9rWoyk1iyzfuZaERnZLNjB6WIojgGm6Bo9Hpfpy3RUpltjLikNlxTsS/YtxVobcfbCGBuAncREYqT4hvqQ=="],
|
||||
|
||||
"@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
|
||||
"@smithy/node-http-handler": ["@smithy/node-http-handler@4.8.2", "", { "dependencies": { "@smithy/core": "^3.26.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-wfl1uwrAqMH9/pi4kqBo5LBcFwrJLxuDLqL7p7qNcJIFcyZDUc6pzhYk4CYv+DP7fIUpQCZumwNnkhPKS52osQ=="],
|
||||
"@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.1", "", { "dependencies": { "@smithy/core": "^3.28.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-m/f15di58P6NtLQ7eVEb5N19NdJWn+4c7zfkFHMT/i3JH7U8UtknpPoy8o2tm2R3OdliYvsvQhZHIfACQDqT+Q=="],
|
||||
|
||||
"@smithy/signature-v4": ["@smithy/signature-v4@5.5.2", "", { "dependencies": { "@smithy/core": "^3.26.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-7xHpmPY4rt0IOmeAA8EfjgEH8isT+587TCdy9H6a7d4OMi5CQ0oEHhWllunvPu4j4Cq0vTFwdxXN/kABWPjdyA=="],
|
||||
"@smithy/signature-v4": ["@smithy/signature-v4@5.6.0", "", { "dependencies": { "@smithy/core": "^3.28.0", "@smithy/types": "^4.15.0", "tslib": "^2.6.2" } }, "sha512-IkPHQdbyoebSwBCuMTzJ/2oIhKVqiZZAZxQYSlpDZqq/WhJUpmdgbHvP7ItddxsPzcDUJeI0V4PNMSNtlZ0aqA=="],
|
||||
|
||||
"@smithy/types": ["@smithy/types@4.15.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Z5TAOxygoFvybJV3igo5SloFflSokHx2hu1eFA+DxDTcn+FtKxUSui+rbTRG1pAafMA888Z3MVvCWUuvCrTXjg=="],
|
||||
|
||||
"@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@smithy/util-utf8": ["@smithy/util-utf8@4.4.2", "", { "dependencies": { "@smithy/core": "^3.26.0", "tslib": "^2.6.2" } }, "sha512-N5CpfaL+/LPQU9PFdOT55ayUo5T0QypG4Almzd1/efJvoDypuT1shkgJk1+hhg/02scYluW6Q2JGnSHIPwCEGQ=="],
|
||||
"@smithy/util-utf8": ["@smithy/util-utf8@4.4.4", "", { "dependencies": { "@smithy/core": "^3.28.0", "tslib": "^2.6.2" } }, "sha512-kvxCWygmILHgwuIQKxocTHblTsF1eWLF/rBN5qjY7QmHfIglcqJoe/p9mo7uOR/dA+h3eVZVLZcmscxp+WtDCA=="],
|
||||
|
||||
"@so-ric/colorspace": ["@so-ric/colorspace@1.1.6", "", { "dependencies": { "color": "^5.0.2", "text-hex": "1.0.x" } }, "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw=="],
|
||||
|
||||
@@ -2341,37 +2339,37 @@
|
||||
|
||||
"@swc/types": ["@swc/types@0.1.27", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-K6h3iUlqeM946U4sXFYeahefR1YBbXJvko+hv8WS8/0BNJ4OHiHRywMnQUJCqkR7Y9+hqQ1TvEpiKqUhz7NEFg=="],
|
||||
|
||||
"@tailwindcss/node": ["@tailwindcss/node@4.3.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "5.21.6", "jiti": "^2.7.0", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.1" } }, "sha512-6NDaqRoAMSXD1mr/RXu0HBvNE9a2n5tHPsxu9XHLws8o4Twes5rBM2205SUUiJ9goAtadrN6xTGX0UDEwp/N4A=="],
|
||||
"@tailwindcss/node": ["@tailwindcss/node@4.3.2", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "5.21.6", "jiti": "^2.7.0", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.2" } }, "sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg=="],
|
||||
|
||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.3.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.3.1", "@tailwindcss/oxide-darwin-arm64": "4.3.1", "@tailwindcss/oxide-darwin-x64": "4.3.1", "@tailwindcss/oxide-freebsd-x64": "4.3.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.3.1", "@tailwindcss/oxide-linux-arm64-musl": "4.3.1", "@tailwindcss/oxide-linux-x64-gnu": "4.3.1", "@tailwindcss/oxide-linux-x64-musl": "4.3.1", "@tailwindcss/oxide-wasm32-wasi": "4.3.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.3.1", "@tailwindcss/oxide-win32-x64-msvc": "4.3.1" } }, "sha512-yVPyo8RNkabVr3O2EhHEE0Rewu7YKzc1DhIqfL46LKveFrmu9XbDazNOJY7/GRuvw1h6u3utWnR29H/p5JPlgA=="],
|
||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.3.2", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.3.2", "@tailwindcss/oxide-darwin-arm64": "4.3.2", "@tailwindcss/oxide-darwin-x64": "4.3.2", "@tailwindcss/oxide-freebsd-x64": "4.3.2", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.2", "@tailwindcss/oxide-linux-arm64-gnu": "4.3.2", "@tailwindcss/oxide-linux-arm64-musl": "4.3.2", "@tailwindcss/oxide-linux-x64-gnu": "4.3.2", "@tailwindcss/oxide-linux-x64-musl": "4.3.2", "@tailwindcss/oxide-wasm32-wasi": "4.3.2", "@tailwindcss/oxide-win32-arm64-msvc": "4.3.2", "@tailwindcss/oxide-win32-x64-msvc": "4.3.2" } }, "sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag=="],
|
||||
|
||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.3.1", "", { "os": "android", "cpu": "arm64" }, "sha512-SVlyf61g374l5cHyg8x9kf5xmLcOaxvOTsbsqDnSsDJaKOEFZ7GCvi84VAVGpxojYOs1+3K6M0UjXfqPU8vmOQ=="],
|
||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.3.2", "", { "os": "android", "cpu": "arm64" }, "sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA=="],
|
||||
|
||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.3.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hVnWLwv+e/l7c4WKyVtHVrIPvYdqWHjRB3MDIqARynzFtnQg85kmQEFCbV9Ja0VVx4xXTIiDWY60Y7iz/iNoDA=="],
|
||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w=="],
|
||||
|
||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.3.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-Cf7abu0WVgbhU7ANgPUnSAvm7nCvMweusHb8FnaHlLfv/Caq4GYaEZg7ZImzzmjx4lIAfuS8q+eLIS7A7IzxIg=="],
|
||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ=="],
|
||||
|
||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.3.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-ZZqzX2Y+GXtXXfqSfpJhDm60OoZfvLHLCgm+J7NVqgHHJjG/m9ugZI77RwTsVd4fnBJuCFP6Ae6kTJb71UdS8g=="],
|
||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.3.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.3.1", "", { "os": "linux", "cpu": "arm" }, "sha512-/Ah/xik0LaMYfv9DZ0S/t4pBlBNYOcqtRwusjgovHkvT8ixueWCLyJjsaF5kQIckjb4IT8Q6K6p/iPmZMixYgg=="],
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2", "", { "os": "linux", "cpu": "arm" }, "sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gqdFoVJlw444GvpnheZLHmvTzSxI/cOUUh2KSNejQjTcYkW062SVD+En0rUgD+QV91bz1XGIGtt1HJd48xUGbQ=="],
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Bwv9KwOvE0VKa86xPFif9b9c3Y1NxOV1P0gLti/IYaWEsQYZXDlxfGEtA8mdDZ7SG3wyNXAWYT5SIn3giL57oA=="],
|
||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-Ymi8O8T15HYQdOUWUtTI6ldN0neHP85FC+Qz32xTcZ7iJXtem/x8ITev0o1e9e5rkqj4lONZfTRLvkmin1+tKg=="],
|
||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-M+P/91qJ6uILLw4k2G93GMDRAXj61SMvFQYt39AqvUqYgExXpLL5aepfns7sj4HiAQeolirQF9E0lzRvdf4zPQ=="],
|
||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.3.1", "", { "dependencies": { "@emnapi/core": "^1.10.0", "@emnapi/runtime": "^1.10.0", "@emnapi/wasi-threads": "^1.2.1", "@napi-rs/wasm-runtime": "^1.1.4", "@tybys/wasm-util": "^0.10.2", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-zsM8uOeqvVGHsAXsJxsT28ttosFahLJKCLOTUBqRAtKnVgGSRitds9T432QiT8b77Yga7JIBkulIRRlJPtYhRA=="],
|
||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.3.2", "", { "dependencies": { "@emnapi/core": "^1.11.1", "@emnapi/runtime": "^1.11.1", "@emnapi/wasi-threads": "^1.2.2", "@napi-rs/wasm-runtime": "^1.1.4", "@tybys/wasm-util": "^0.10.2", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw=="],
|
||||
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.3.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aiNvSq9BsVk8V513lDKlrCFAgf8qBMPZTpgEhInL+NwQqs97mYmupVMrPrgBBSL8Pv/0zXu9MrMF9rMun1ZeNg=="],
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.3.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ=="],
|
||||
|
||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.3.1", "", { "os": "win32", "cpu": "x64" }, "sha512-xDEyu1rg290472FEGaKHnzyDyh5QH+AlWvsU5hMoMtPpzmKlRI0jaYKCgSHDYtaQWZOYbMaduSyCwFwY4n1HmA=="],
|
||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.3.2", "", { "os": "win32", "cpu": "x64" }, "sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ=="],
|
||||
|
||||
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.3.1", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.3.1", "@tailwindcss/oxide": "4.3.1", "postcss": "8.5.15", "tailwindcss": "4.3.1" } }, "sha512-dNJuNbdEJT/SWRuXTYP1WSamelsz3ztkUsdtWQPjrexysrTpaEPM40P/71knXiXLYEojqPOEGitVLLpPMS5T6A=="],
|
||||
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.3.2", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.3.2", "@tailwindcss/oxide": "4.3.2", "postcss": "^8.5.15", "tailwindcss": "4.3.2" } }, "sha512-rjVWYCa7Ngbi5AarT6k8TkxUG3Wl1QKzHdIZVsjZSzf36Jmo2IKZt/NHRAwly8oDkbBOH0YTu+CHuf9jPxMc+g=="],
|
||||
|
||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.3.1", "", { "dependencies": { "@tailwindcss/node": "4.3.1", "@tailwindcss/oxide": "4.3.1", "tailwindcss": "4.3.1" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-hItDHuIIlEV61R+faXu66s1K36aTurO/Qw0e45Vskz57gXl9pWOT6eg3zmcEui6CZXddbN7zd41bwmvag4JGwQ=="],
|
||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.3.2", "", { "dependencies": { "@tailwindcss/node": "4.3.2", "@tailwindcss/oxide": "4.3.2", "tailwindcss": "4.3.2" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA=="],
|
||||
|
||||
"@tanstack/react-virtual": ["@tanstack/react-virtual@3.11.3", "", { "dependencies": { "@tanstack/virtual-core": "3.11.3" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-vCU+OTylXN3hdC8RKg68tPlBPjjxtzon7Ys46MgrSLE+JhSjSTPvoQifV6DQJeJmA8Q3KT6CphJbejupx85vFw=="],
|
||||
|
||||
@@ -2379,29 +2377,29 @@
|
||||
|
||||
"@tauri-apps/api": ["@tauri-apps/api@2.11.1", "", {}, "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA=="],
|
||||
|
||||
"@tauri-apps/cli": ["@tauri-apps/cli@2.11.3", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.11.3", "@tauri-apps/cli-darwin-x64": "2.11.3", "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.3", "@tauri-apps/cli-linux-arm64-gnu": "2.11.3", "@tauri-apps/cli-linux-arm64-musl": "2.11.3", "@tauri-apps/cli-linux-riscv64-gnu": "2.11.3", "@tauri-apps/cli-linux-x64-gnu": "2.11.3", "@tauri-apps/cli-linux-x64-musl": "2.11.3", "@tauri-apps/cli-win32-arm64-msvc": "2.11.3", "@tauri-apps/cli-win32-ia32-msvc": "2.11.3", "@tauri-apps/cli-win32-x64-msvc": "2.11.3" }, "bin": { "tauri": "tauri.js" } }, "sha512-EElQe8z8uD7Pi5++tJ/UfEwWuK08rd3oCDYdeIbJAb6pZRrxlqmoF5gh5H5YvzmUPhS4IRCaLSsQhvWkrfK+GQ=="],
|
||||
"@tauri-apps/cli": ["@tauri-apps/cli@2.11.4", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.11.4", "@tauri-apps/cli-darwin-x64": "2.11.4", "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.4", "@tauri-apps/cli-linux-arm64-gnu": "2.11.4", "@tauri-apps/cli-linux-arm64-musl": "2.11.4", "@tauri-apps/cli-linux-riscv64-gnu": "2.11.4", "@tauri-apps/cli-linux-x64-gnu": "2.11.4", "@tauri-apps/cli-linux-x64-musl": "2.11.4", "@tauri-apps/cli-win32-arm64-msvc": "2.11.4", "@tauri-apps/cli-win32-ia32-msvc": "2.11.4", "@tauri-apps/cli-win32-x64-msvc": "2.11.4" }, "bin": { "tauri": "tauri.js" } }, "sha512-R8xGtMpwyetawSqm9kYOuMmEqkhUbvcUy8n0aNXIxollKBLESUu5f4Fx+64hgASYm1H+jSWq6jCW6zqTnH6hqQ=="],
|
||||
|
||||
"@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.11.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BxpaM8bsCoXs3wd4WKYhas/G1gs7+r7B+e4WnyRk2GEoVOouJB1hoL6E6YLXZDXbYci6VFdrNnobQwd2uVL4ew=="],
|
||||
"@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.11.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-1ryOF3ZhpZ/nemHV5zVwBQBz9jDGKmKPvWPADOhc83ig0P4bMc2iER4NbC6r9sjeIZ6RVQ4g3RZIYvezhcl4TQ=="],
|
||||
|
||||
"@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.11.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-DbZYuPB1ZEzcAHYeyCvo3ltzM27+aXwPloCrtexPnmgPgulYJm3TOq6aC4S+wPhSXteddg8zImtNkvx/gQzmwg=="],
|
||||
"@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.11.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-uFsGQAAfuyz1k/yGLmkWfkBlgKAqZfxqlHmLWx81QU27RJWfmbNHCIq8T8w1e+VClleIuZUjpHWfoE4E3DLo3A=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.11.3", "", { "os": "linux", "cpu": "arm" }, "sha512-741NduqBmz1XkdU8yz3OI/kBZtqHbvxo9F9ytIeWYU69/Ba9dcZEbqOU++Dp0G/XU8vAI0TfTywEl+p+BbLvaA=="],
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.11.4", "", { "os": "linux", "cpu": "arm" }, "sha512-IaHZn5CdBL21oUmjiVOS1ctw6Ip1O0pjp70FwOWmYz1myWe0SY96ZIj2FYf7pT0m8bI2h/hrs5ZbEXXh44/MkQ=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.11.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-RWAXT8pTqIczXcoic+LXlo6uEbAXGB0cgh6Pg7Y9xVnEbzryQ1JHtRGj9SxzrKSemBIDBH6Qc24kK2G69i8ofA=="],
|
||||
"@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.11.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-N41/ukTRVe6XSuUTESuFdGeOW2i7k62tK+6gHK5Kd5/q5RPvvi19GaWAVPPb9u95HSGmTChSolBfzynUsssFaA=="],
|
||||
|
||||
"@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.11.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-qomqYS+yAkd0gXMRmhguWXc7RfVN+XKKXaEwbf5QmKURwydLFOTldd6F8/WoZDSsBMrV8dpNxz0YneGLmobiSA=="],
|
||||
"@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.11.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-v277UnT/fB64xAfSroL5N3Km3tLmvATWqJJw/wRI+g6o+HkeD0slyE7gOhNs1MbjE41R7bQOTxMVoL3aomUJmw=="],
|
||||
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.11.3", "", { "os": "linux", "cpu": "none" }, "sha512-jOCXbDqeDj5XcclsOBAaXjtTgwZCVg8zEZ+dbPUCoADOgljFgL0rOkYTc96vUYgOrYEfuHYihWMxIDGaD6GwJw=="],
|
||||
"@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.11.4", "", { "os": "linux", "cpu": "none" }, "sha512-qqgNkQ2u1yZHxjhxsZaxUtRDW8dIqIYm33rx/mzwQv0SfY9x1B+iraj8vWeFiXjjSVVhEMepXSOts1TqPzvXNQ=="],
|
||||
|
||||
"@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.11.3", "", { "os": "linux", "cpu": "x64" }, "sha512-+u3HO/F3gHwL48t9gWN/urqZvpaEJzBFmTaq5eSIhvy8TOvnhb+LgJr3Q3BG+5JxuBrCUjqtOEz6gMttdJFSBA=="],
|
||||
"@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.11.4", "", { "os": "linux", "cpu": "x64" }, "sha512-2VRNWl84FOH0m2giiDkO2h0QXlcMJeX+zJDpI5kDIQAx6s+geF3v48F4DXfJez4GS/FdoDGnPnw1C2iYGbQ7bQ=="],
|
||||
|
||||
"@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.11.3", "", { "os": "linux", "cpu": "x64" }, "sha512-spr5Jpr6KF/vehkLwJ0YmdGv8QwpWU+uw7J8bgijO0sox6ZCYsSNMbcsQjTqPi4xl+p0woIYpWXgChgHYpAc8g=="],
|
||||
"@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.11.4", "", { "os": "linux", "cpu": "x64" }, "sha512-o9GyhYor/nc7xarmwDE3ka2szuW3uuZzXjHWh64Q8YX5AtSgxdQkFWzrY4O8KiGtVNvFBI14H3Q49Qj5TOIP/A=="],
|
||||
|
||||
"@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.11.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-abkoRQih5xBa3vz2spWaex0kP/MzVzVPQHom2f8jnCq46R/luOD6Uy85EMU9/bfzf6ZzdorWJsgO+OMX90Fx2w=="],
|
||||
"@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.11.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-ld5Ehb598m0VkYyylRPNeCFsBe/km0jxis6KgMpl3IGY6I/i1RwQXO05I1AsXUXO2WC6AvB/Lw4qTf/asiuEiQ=="],
|
||||
|
||||
"@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.11.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-Vy6AvzFm1G40hg3r+OYDB3jkuu7R4wnMzbQBKuun9v6Cgg8IierpLL7toMzrZKs/8NlG8Sg4x1iLFR52oknyHg=="],
|
||||
"@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.11.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-12Hxi0XX/H5VFxO/bGgHkFWhml9VMgEOu9CidjeCeTNQ1l6fpUlbiGgSP7CLI3PFtW9/FfbeHieZ+kyWK5H7CA=="],
|
||||
|
||||
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.11.3", "", { "os": "win32", "cpu": "x64" }, "sha512-GlciF75GdbseajOyib2aCHwE3BXIqZ1liGKWLFRvCdN5wm8h8hFssEVKQ/6E+2jsMLg9v7LCTb983YFnn0QSww=="],
|
||||
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.11.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+vDiqBIU5dMISg/wNvX3sF+ZHfgJGJ5T0AcO+EHNXV9GGAG+P5fzodlDXD3QdKCRgZxMoCm5PPvj3BqLNjBthw=="],
|
||||
|
||||
"@testing-library/dom": ["@testing-library/dom@10.4.1", "", { "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", "aria-query": "5.3.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", "picocolors": "1.1.1", "pretty-format": "^27.0.2" } }, "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg=="],
|
||||
|
||||
@@ -2625,25 +2623,25 @@
|
||||
|
||||
"@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.62.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.62.0", "@typescript-eslint/type-utils": "8.62.0", "@typescript-eslint/utils": "8.62.0", "@typescript-eslint/visitor-keys": "8.62.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.62.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-o+mpz7EYiMzXoySXiKmzlabIvTVqUuK5yLrAedRPRDA0IpPFMUV1IXt6OqljIxX/kumN6EjUYp41Hqelh6p/Dw=="],
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.62.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.62.1", "@typescript-eslint/type-utils": "8.62.1", "@typescript-eslint/utils": "8.62.1", "@typescript-eslint/visitor-keys": "8.62.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.62.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-4EQM77WgVNxj7OkL/5b/D/xZsw00G577+UriYTC7JF5opcF3T2AuoeY7ueLaZgSVjSgCS6yOAJB5bRGLPSJUzA=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.62.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.62.0", "@typescript-eslint/types": "8.62.0", "@typescript-eslint/typescript-estree": "8.62.0", "@typescript-eslint/visitor-keys": "8.62.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-dzHeT2gySzZtLDsuqxU9AkYgIsQoHAHtRBpOqM+Ofzx1Bwrd2RcCjQJ+6iQbsHOIR6NS33bF2W1k3blN1zLDrA=="],
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.62.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.62.1", "@typescript-eslint/types": "8.62.1", "@typescript-eslint/typescript-estree": "8.62.1", "@typescript-eslint/visitor-keys": "8.62.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-sPhE4iHuJDSvoAiec+Ro8JyXw8f0ql13HFR82P99nCm9GwTEKG0KYLvDe6REk8BCXuit6vJAv/Yxg5ABaNS2rA=="],
|
||||
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.62.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.62.0", "@typescript-eslint/types": "^8.62.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-wexnCqiTg7BOGtbLDftYpRWlmLq4xfoMd7BKFR6Y75sZS3QmRKLdN3yWLhmIYgqMmP/OXWpj3H8odkb5nGURCQ=="],
|
||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.62.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.62.1", "@typescript-eslint/types": "^8.62.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg=="],
|
||||
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.62.0", "", { "dependencies": { "@typescript-eslint/types": "8.62.0", "@typescript-eslint/visitor-keys": "8.62.0" } }, "sha512-1lX38kNxXIRb8mEc3lbq5mdHq1Pf2+U0nFU65KfT18mtPxxl0fvjuEE92mHuXPuCtElJhOrddOpyMlM3Z0umEA=="],
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.62.1", "", { "dependencies": { "@typescript-eslint/types": "8.62.1", "@typescript-eslint/visitor-keys": "8.62.1" } }, "sha512-r4d249KbQ1SFdpeStvob8Ih6aPPIzfqllPVOtvhve6ZcpuVcYo5/7zUWckKpHE7StASX4kTKZTLf0WQm/wPkcg=="],
|
||||
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.62.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g=="],
|
||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.62.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g=="],
|
||||
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.62.0", "", { "dependencies": { "@typescript-eslint/types": "8.62.0", "@typescript-eslint/typescript-estree": "8.62.0", "@typescript-eslint/utils": "8.62.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-+g5O3j0w2ldzC86Pv6fvbO/xhAonbJFIdf/MKQ1d30gndlsVzUOE83ldfSE15Qrl9fhFjK6AovHs5Wpp6vx86w=="],
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.62.1", "", { "dependencies": { "@typescript-eslint/types": "8.62.1", "@typescript-eslint/typescript-estree": "8.62.1", "@typescript-eslint/utils": "8.62.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-aXM5xlqXiTxPibXB93cLAURfT3rlizf7uMXISCXy66Isr/9hISJx3yDsKl0L7lKa51b8JpFuNKby0/O0pEm9jg=="],
|
||||
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.62.0", "", {}, "sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg=="],
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.62.1", "", {}, "sha512-ooCzJFaf+Hg+uG6fA3NRFGuFjlfNlDhBthbv4ZPU/0elCAFUfnyXUvf/WOpHz/jYwSmvU2GkR2LtyUfy1AxZ1Q=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.62.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.62.0", "@typescript-eslint/tsconfig-utils": "8.62.0", "@typescript-eslint/types": "8.62.0", "@typescript-eslint/visitor-keys": "8.62.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-+hVbNxtW64pIcZWDPGbyaKF7vp2IBTVY5ma1blwwksrjdsbdqqEKvJWMGbBofei4F6Dovx1M0RJgoFeNu2279A=="],
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.62.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.62.1", "@typescript-eslint/tsconfig-utils": "8.62.1", "@typescript-eslint/types": "8.62.1", "@typescript-eslint/visitor-keys": "8.62.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.62.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.62.0", "@typescript-eslint/types": "8.62.0", "@typescript-eslint/typescript-estree": "8.62.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-82r66fi9zYwZ+mTq3vKgwjbZ1PVk/DJzrXFLpG6RnBbdvH8TEGVHIs9H4d2drhkOzf0syZuD/OZvvlu6GDbP4g=="],
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.62.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.62.1", "@typescript-eslint/types": "8.62.1", "@typescript-eslint/typescript-estree": "8.62.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-sHtbPfuKNZCG+ih8SyjjucqRntSVmp8XgL5u6o9mAhiSn8ds5o/M/XdM0abweme2Tln3szOstOrZ9OXitvPh0g=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.62.0", "", { "dependencies": { "@typescript-eslint/types": "8.62.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ=="],
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.62.1", "", { "dependencies": { "@typescript-eslint/types": "8.62.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-4g3BLxfdTMy8iZG0MaBkadnlRrCJ74cQiFbyEVMrkwIoqdyaXXQM22cotDvrl4x28wgIZ9rEJRoM+mmhSJpJ1g=="],
|
||||
|
||||
"@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.6", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-jIXhD0eWQ1JA6ln/5Dltyx22UxWNrw0hZmhy2rlv6m6KgF7kplHx3g0fzi09lNmTJQRR91OlemYp3xFnvDK9og=="],
|
||||
|
||||
@@ -2739,7 +2737,7 @@
|
||||
|
||||
"agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="],
|
||||
|
||||
"ai": ["ai@6.0.212", "", { "dependencies": { "@ai-sdk/gateway": "3.0.137", "@ai-sdk/provider": "3.0.11", "@ai-sdk/provider-utils": "4.0.31", "@opentelemetry/api": "^1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-BDng0yuyqUtlLz565Yy85QPpCLmOQHRd+HkpOVIKo0PXKj0GZWsbfIoDWvOkfH1kz8h2fj0MxALhTJowubuxOw=="],
|
||||
"ai": ["ai@6.0.216", "", { "dependencies": { "@ai-sdk/gateway": "3.0.140", "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.33", "@opentelemetry/api": "^1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-K6/H1H6b+IJuz79Nc44A/tEPzAH+dUCmQhHtP2In943OxvLekosVYBwUUsr1oQjc/JvN8WRpL1mLuefUBHxs/w=="],
|
||||
|
||||
"ai-sdk-provider-claude-code": ["ai-sdk-provider-claude-code@3.5.0", "", { "dependencies": { "@ai-sdk/provider": "^3.0.0", "@ai-sdk/provider-utils": "^4.0.1", "@anthropic-ai/claude-agent-sdk": "^0.3.170" }, "peerDependencies": { "zod": "^4.0.0" } }, "sha512-7SZrTGkuR4G4zeNrjnJgDzYkrKZqzq7GUQJcFBKCxFH5dJpS9lbs+g9BCt7bwT1gDm4SAUmOQ0T5rKqcC2HkVQ=="],
|
||||
|
||||
@@ -2823,7 +2821,7 @@
|
||||
|
||||
"bare-fs": ["bare-fs@4.7.2", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-aTvMFUWkBmjzKtEQMDGGDNF8bkfpD5N1b/FCwt7A3wrU4t1o/e/85Wzkluh6JlODCjqVESYCkQCdTXqZ9G7VFg=="],
|
||||
|
||||
"bare-os": ["bare-os@3.9.1", "", {}, "sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ=="],
|
||||
"bare-os": ["bare-os@3.9.3", "", {}, "sha512-fF4Q7QsyKVF5Rj0qvI8BgUNjqzC2JvQlpTaPLjVJVxYVUX5Zr9un+y3w1HmA4nNKdFmRBT8z/WmrjvXzXVerKQ=="],
|
||||
|
||||
"bare-path": ["bare-path@3.0.1", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ=="],
|
||||
|
||||
@@ -3259,7 +3257,7 @@
|
||||
|
||||
"eight-colors": ["eight-colors@1.3.3", "", {}, "sha512-4B54S2Qi4pJjeHmCbDIsveQZWQ/TSSQng4ixYJ9/SYHHpeS5nYK0pzcHvWzWUfRsvJQjwoIENhAwqg59thQceg=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.379", "", {}, "sha512-v/qV5aV5EUA2pGilzUCq5/eyOloZAqDZBu9UMBIzgPpLlprjSR6zswsWBTv0KpqxLGUAZEwhO95ZCt7srymNVA=="],
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.381", "", {}, "sha512-n9Wa6yB+vDsGuA8AKbl/0z7HbvWqt5jxIdvr1IUicd0ryPrk7/xzwqLv8D9AbbvZ6avVNtXYLTfmgFHkwkyelg=="],
|
||||
|
||||
"embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="],
|
||||
|
||||
@@ -3295,7 +3293,7 @@
|
||||
|
||||
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||
|
||||
"es-module-lexer": ["es-module-lexer@2.1.0", "", {}, "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ=="],
|
||||
"es-module-lexer": ["es-module-lexer@2.2.0", "", {}, "sha512-3lGxdTXCLfe1MYfTz1y2ksAAUM4NAOP6rPEjxGJVKO7TZ5+tvHCaQWGpC4Y3IXvW3ece0Cz1cIP4FWBxOnGCTQ=="],
|
||||
|
||||
"es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="],
|
||||
|
||||
@@ -3403,7 +3401,7 @@
|
||||
|
||||
"fast-string-width": ["fast-string-width@3.0.2", "", { "dependencies": { "fast-string-truncated-width": "^3.0.2" } }, "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg=="],
|
||||
|
||||
"fast-uri": ["fast-uri@3.1.2", "", {}, "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ=="],
|
||||
"fast-uri": ["fast-uri@3.1.3", "", {}, "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg=="],
|
||||
|
||||
"fast-wrap-ansi": ["fast-wrap-ansi@0.2.2", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q=="],
|
||||
|
||||
@@ -3471,7 +3469,7 @@
|
||||
|
||||
"fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
|
||||
|
||||
"fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="],
|
||||
"fs-extra": ["fs-extra@11.3.6", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA=="],
|
||||
|
||||
"fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
|
||||
|
||||
@@ -3781,7 +3779,7 @@
|
||||
|
||||
"js-tokens": ["js-tokens@10.0.0", "", {}, "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.2.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw=="],
|
||||
"js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="],
|
||||
|
||||
"jschardet": ["jschardet@3.1.4", "", {}, "sha512-/kmVISmrwVwtyYU40iQUOp3SUPk2dhNCMsZBQX0R1/jZ8maaXJ/oZIzUOiyOqcgtLnETFKYChbJ5iDC/eWmFHg=="],
|
||||
|
||||
@@ -4247,7 +4245,7 @@
|
||||
|
||||
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
|
||||
|
||||
"p-map": ["p-map@7.0.4", "", {}, "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ=="],
|
||||
"p-map": ["p-map@7.0.5", "", {}, "sha512-e8vJF4XdVkzqqSHguEMz41mQO1wKwxKm5ENrUJQUu9kLDCtn83cxbyHZcszr4QC5zEA7WffRRC4gsTecC7J9oA=="],
|
||||
|
||||
"p-mutex": ["p-mutex@1.0.0", "", { "dependencies": { "yocto-queue": "^1.2.1" } }, "sha512-UlthGzEMsg2VnZAR58wkzL7muskxtNamoTR1Q6/VYBUKqPaMM+YtSncjWIvyjfUvVECKck1SYC/4XIWWJU3gBw=="],
|
||||
|
||||
@@ -4353,15 +4351,15 @@
|
||||
|
||||
"points-on-path": ["points-on-path@0.2.1", "", { "dependencies": { "path-data-parser": "0.1.0", "points-on-curve": "0.2.0" } }, "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="],
|
||||
|
||||
"postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="],
|
||||
"postcss": ["postcss@8.5.16", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg=="],
|
||||
|
||||
"postcss-selector-parser": ["postcss-selector-parser@7.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg=="],
|
||||
|
||||
"postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
|
||||
|
||||
"posthog-js": ["posthog-js@1.395.0", "", { "dependencies": { "@posthog/core": "^1.38.0", "@posthog/types": "^1.391.1", "core-js": "^3.38.1", "dompurify": "^3.3.2", "fflate": "^0.4.8", "preact": "^10.29.2", "query-selector-shadow-dom": "^1.0.1", "web-vitals": "^5.3.0" } }, "sha512-5iTb00CGt2eQUUiBQysQiX89RAbCN6wK2sDNzvs9zv0alaY8mJ0ZySrUD3LQ+XyLhgM5pCpacBuUwChqiYDLDw=="],
|
||||
"posthog-js": ["posthog-js@1.396.2", "", { "dependencies": { "@posthog/core": "^1.38.1", "@posthog/types": "^1.392.0", "core-js": "^3.38.1", "dompurify": "^3.3.2", "fflate": "^0.4.8", "preact": "^10.29.2", "query-selector-shadow-dom": "^1.0.1", "web-vitals": "^5.3.0" } }, "sha512-WFdS0JL+r/M7A9XQwIGbw1Xn6W7/V5TEmv1wgrq7GFcPxZ0I3TktNGtGQNmzARbI8nKedAHFkY9UPDDg+NTSQg=="],
|
||||
|
||||
"posthog-node": ["posthog-node@5.38.6", "", { "dependencies": { "@posthog/core": "^1.38.0" }, "peerDependencies": { "rxjs": "^7.0.0" }, "optionalPeers": ["rxjs"] }, "sha512-Sm2mCAa9/lTTYppnKyy0AhQrriq8fOd8B2vwd3EE/9uihyIx9qkJ1xGYbvADxQJlF7HqM1/TIFCKsI0JvF8gjQ=="],
|
||||
"posthog-node": ["posthog-node@5.38.8", "", { "dependencies": { "@posthog/core": "^1.38.1" }, "peerDependencies": { "rxjs": "^7.0.0" }, "optionalPeers": ["rxjs"] }, "sha512-AWsp9Tigf4iZepabPErAt/2sLTGwJ7w6631JP+3ifDqWzaBPyzcukD7cTPeoNDKGwJreQ69Ju4l53n9g2+X6nQ=="],
|
||||
|
||||
"powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="],
|
||||
|
||||
@@ -4483,7 +4481,7 @@
|
||||
|
||||
"react-use": ["react-use@17.6.1", "", { "dependencies": { "@types/js-cookie": "^3.0.0", "@xobotyi/scrollbar-width": "^1.9.5", "copy-to-clipboard": "^3.3.1", "fast-deep-equal": "^3.1.3", "fast-shallow-equal": "^1.0.0", "js-cookie": "^3.0.0", "nano-css": "^5.6.2", "react-universal-interface": "^0.6.2", "resize-observer-polyfill": "^1.5.1", "screenfull": "^5.1.0", "set-harmonic-interval": "^1.0.1", "throttle-debounce": "^3.0.1", "ts-easing": "^0.2.0", "tslib": "^2.1.0" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-uibb3pgzV4LFsYPHyXYGu7dD2+pyk/ZJlPH+AizBR3zolqPWyCleKcWWbUQaKSKfydwgnQ3ymGm1Ab3/saGHCA=="],
|
||||
|
||||
"react-virtuoso": ["react-virtuoso@4.18.9", "", { "peerDependencies": { "react": ">=16 || >=17 || >= 18 || >= 19", "react-dom": ">=16 || >=17 || >= 18 || >=19" } }, "sha512-hnS+4ip23UfMOAbiEfkpUu9OHau9SAYWgu3fUcKKnCmngV4eorkPSMm7/4XzjLqj4EKwIXk6Jeyd1azIbVnMkQ=="],
|
||||
"react-virtuoso": ["react-virtuoso@4.18.10", "", { "peerDependencies": { "react": ">=16 || >=17 || >= 18 || >= 19", "react-dom": ">=16 || >=17 || >= 18 || >=19" } }, "sha512-P6GIZ7kWAPOYB2H16yRQNgy+VF9pJOuTFw1EUc1EAtCj5WxVSAF1Sql3x3fbLwaLeBFsiPnu+3U9o6sIOyTdFw=="],
|
||||
|
||||
"read": ["read@1.0.7", "", { "dependencies": { "mute-stream": "~0.0.4" } }, "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ=="],
|
||||
|
||||
@@ -4499,7 +4497,7 @@
|
||||
|
||||
"real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="],
|
||||
|
||||
"recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="],
|
||||
"recast": ["recast@0.23.12", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA=="],
|
||||
|
||||
"recharts": ["recharts@2.15.4", "", { "dependencies": { "clsx": "^2.0.0", "eventemitter3": "^4.0.1", "lodash": "^4.17.21", "react-is": "^18.3.1", "react-smooth": "^4.0.4", "recharts-scale": "^0.4.4", "tiny-invariant": "^1.3.1", "victory-vendor": "^36.6.8" }, "peerDependencies": { "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw=="],
|
||||
|
||||
@@ -4627,7 +4625,7 @@
|
||||
|
||||
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
||||
|
||||
"shadcn": ["shadcn@4.11.1", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "kleur": "^4.1.5", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "undici": "^7.27.2", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-r3P4EWKQ+XDiwBGi7BdHKri3aGUK6mE1rdoSWS7ARU0wqsfzJNW2KBB+NEfg/LIpzThb+AoeQD2T01wORADXVQ=="],
|
||||
"shadcn": ["shadcn@4.12.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "kleur": "^4.1.5", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "undici": "^7.27.2", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-o781ieQziCnXH2FKsEqxp1fnbHdbgAPO9inTSPeZ59hQfsZXuMGp3ul8oFSV5KQS4nbUK9b+DrDE6C7OvfKKQQ=="],
|
||||
|
||||
"shallow-clone": ["shallow-clone@3.0.1", "", { "dependencies": { "kind-of": "^6.0.2" } }, "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA=="],
|
||||
|
||||
@@ -4801,15 +4799,15 @@
|
||||
|
||||
"tailwind-variants": ["tailwind-variants@3.2.2", "", { "peerDependencies": { "tailwind-merge": ">=3.0.0", "tailwindcss": "*" }, "optionalPeers": ["tailwind-merge"] }, "sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg=="],
|
||||
|
||||
"tailwindcss": ["tailwindcss@4.3.1", "", {}, "sha512-hk+TB1m+K8CYNrP6rjQaq/Y+4Zylwpa87mLYBKCunwnnQ9p+fHb7kmSfGqyEJoxF/O6CDyABWVFEafNSYKll+Q=="],
|
||||
"tailwindcss": ["tailwindcss@4.3.2", "", {}, "sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA=="],
|
||||
|
||||
"tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="],
|
||||
|
||||
"tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
|
||||
|
||||
"tar": ["tar@7.5.17", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-wPEBwzapC+2PaTYPH6e2L+cNOEE227S47wUYFqlegcs8zlLLmeb9Fcff1HVZY4Fwku/1Eyv38n7GYwB2aaS71g=="],
|
||||
"tar": ["tar@7.5.19", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw=="],
|
||||
|
||||
"tar-fs": ["tar-fs@3.1.2", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw=="],
|
||||
"tar-fs": ["tar-fs@3.1.3", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-/hU4AXnIdZu+Gvl1pk0oI5f5HxWsCJRtY2aFaJdk9VvyL48DWU6iU5WAIPG+wIi1YvWA6eTJvIviP/tMAZZNwQ=="],
|
||||
|
||||
"tar-stream": ["tar-stream@3.2.0", "", { "dependencies": { "b4a": "^1.6.4", "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg=="],
|
||||
|
||||
@@ -4903,7 +4901,7 @@
|
||||
|
||||
"ts-poet": ["ts-poet@6.12.0", "", { "dependencies": { "dprint-node": "^1.0.8" } }, "sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA=="],
|
||||
|
||||
"ts-proto": ["ts-proto@2.11.8", "", { "dependencies": { "@bufbuild/protobuf": "^2.10.2", "case-anything": "^2.1.13", "ts-poet": "^6.12.0", "ts-proto-descriptors": "2.1.0" }, "bin": { "protoc-gen-ts_proto": "protoc-gen-ts_proto" } }, "sha512-+5hzECnyVB33jxjG1BIdzAHcRBm7hjnm8womdJVp2A7xJWihP0drHHVsXYTr9i/LpWNGfh80I+AVVNzFM5AwJw=="],
|
||||
"ts-proto": ["ts-proto@2.11.10", "", { "dependencies": { "@bufbuild/protobuf": "^2.10.2", "case-anything": "^2.1.13", "ts-poet": "^6.12.0", "ts-proto-descriptors": "2.1.0" }, "bin": { "protoc-gen-ts_proto": "protoc-gen-ts_proto" } }, "sha512-7mvz2RbOZc0J/+x8biIcVHJ0nx7xjH79vtoEnkpKT5l8yFF5ERe03dee2W3CbB5vb1QgnbQXGzeBGGryJ+Q9EA=="],
|
||||
|
||||
"ts-proto-descriptors": ["ts-proto-descriptors@2.1.0", "", { "dependencies": { "@bufbuild/protobuf": "^2.0.0" } }, "sha512-S5EZYEQ6L9KLFfjSRpZWDIXDV/W7tAj8uW7pLsihIxyr62EAVSiKuVPwE8iWnr849Bqa53enex1jhDUcpgquzA=="],
|
||||
|
||||
@@ -4933,7 +4931,7 @@
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"typescript-eslint": ["typescript-eslint@8.62.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.62.0", "@typescript-eslint/parser": "8.62.0", "@typescript-eslint/typescript-estree": "8.62.0", "@typescript-eslint/utils": "8.62.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8QxXi+ZACKX0kaqO4gY8kn0RSD9gFfaHDWwjqtEN48aWCBkX4MJaufWN+c3BzlrXLOxfywDL8CaoqUwcRq4j4Q=="],
|
||||
"typescript-eslint": ["typescript-eslint@8.62.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.62.1", "@typescript-eslint/parser": "8.62.1", "@typescript-eslint/typescript-estree": "8.62.1", "@typescript-eslint/utils": "8.62.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-vymnnM5g0AKQDSAyfP12nMIBvgwgA42syg74kkuZ4x1VuTzwQKwc5h9rGxeShCjny5o+zWAb6OEoz7XLgrIkIw=="],
|
||||
|
||||
"uc.micro": ["uc.micro@1.0.6", "", {}, "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="],
|
||||
|
||||
@@ -5835,7 +5833,7 @@
|
||||
|
||||
"dify-ai-provider/@ai-sdk/provider": ["@ai-sdk/provider@2.0.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-h88OPkavHTiN9tMn2l5awAznGB0lXzjcLhgR1/rvjB2zlLprsNxbM2tt6OJsHUxduLC3klq0/eqaSf6fX5XVww=="],
|
||||
|
||||
"dify-ai-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.27", "", { "dependencies": { "@ai-sdk/provider": "2.0.3", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-JFhJK5ynprll2FR3e+sHagJJIwvIagsNA0FLbLPq2Os4yLUK2/eiaCU0jXsADik73/hhvcPPLmD+Uo8eu5kFaQ=="],
|
||||
"dify-ai-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.28", "", { "dependencies": { "@ai-sdk/provider": "2.0.3", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bXlX1WX7E50a2N+AJW+1a/x63m52aPhm+6xYe5THxWrx9vW9NR7E2Ay+1G1ndlCdMdYKo2Fnsd7kBhuyQPaphw=="],
|
||||
|
||||
"dify-ai-provider/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
||||
|
||||
@@ -6025,8 +6023,6 @@
|
||||
|
||||
"proxy-agent/proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
||||
|
||||
"puppeteer-core/@puppeteer/browsers": ["@puppeteer/browsers@2.6.1", "", { "dependencies": { "debug": "^4.4.0", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", "semver": "^7.6.3", "tar-fs": "^3.0.6", "unbzip2-stream": "^1.4.3", "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" } }, "sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg=="],
|
||||
|
||||
"radix-ui/@radix-ui/primitive": ["@radix-ui/primitive@1.1.4", "", {}, "sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ=="],
|
||||
|
||||
"radix-ui/@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collapsible": "1.1.14", "@radix-ui/react-collection": "1.1.10", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-iE8YB9nmTBH8zd73ofBISZ8JCzgMoMkATJr7qDwa6u5F1+7mTM81V6fa71jgZ65rpjVpecDf1vSnwIFP9Ly1zw=="],
|
||||
@@ -6219,6 +6215,8 @@
|
||||
|
||||
"unzipper/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.17", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.13", "@radix-ui/react-focus-guards": "1.1.4", "@radix-ui/react-focus-scope": "1.1.10", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-portal": "1.1.12", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-slot": "1.3.0", "@radix-ui/react-use-controllable-state": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TDTYmpdq8dI2+Xgvgj9AJ8Ghqq+Eph/TRVEdaFQPDItIY+6QSkU7MJMeevw1568Yw/2Ijz8BTphPSP2XejKphw=="],
|
||||
|
||||
"verror/core-util-is": ["core-util-is@1.0.2", "", {}, "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="],
|
||||
|
||||
"vite-node/es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="],
|
||||
@@ -6613,7 +6611,7 @@
|
||||
|
||||
"@types/jest/pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.7", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA=="],
|
||||
|
||||
"@vscode/test-cli/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
@@ -6627,7 +6625,7 @@
|
||||
|
||||
"@vscode/vsce/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
|
||||
"@vscode/vsce/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
|
||||
"@vscode/vsce/minimatch/brace-expansion": ["brace-expansion@5.0.7", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA=="],
|
||||
|
||||
"ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
|
||||
@@ -6787,7 +6785,7 @@
|
||||
|
||||
"gauge/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"glob/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
|
||||
"glob/minimatch/brace-expansion": ["brace-expansion@5.0.7", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA=="],
|
||||
|
||||
"googleapis-common/gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
|
||||
|
||||
@@ -6989,12 +6987,34 @@
|
||||
|
||||
"test-exclude/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||
|
||||
"test-exclude/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
|
||||
"test-exclude/minimatch/brace-expansion": ["brace-expansion@5.0.7", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA=="],
|
||||
|
||||
"unzipper/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||
|
||||
"unzipper/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/primitive": ["@radix-ui/primitive@1.1.4", "", {}, "sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-context": ["@radix-ui/react-context@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-escape-keydown": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-2v+zNAWWe0ySxgC0D0yeXMPQ23xZVgXZTerTz+JKlmdRj6gfTqmCcR29jb6d290DezXPGgruHWDX/vYUebtErg=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.10", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-callback-ref": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fas/lXQqhVvqwAb64s5RFeHiHYElZ6SUQbZaNd6EkfhP/Al7wTIQ9WIR4QVX475tlu5yFCEdDcJH6/UwsZjMWw=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-id": ["@radix-ui/react-id@1.1.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.12", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m309havGzsjLHHaIX50G5PlvRs3xkgPCsGk/5PTvYm8D5q33yG0J7w/712PTOhid7NTaFETtnSXjngHQavvhVw=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.6", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.6", "", { "dependencies": { "@radix-ui/react-slot": "1.3.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wetd0QI77DbvrPpTAvH1SqOxsYF2wZe5TNxqwOd5Ty4XDpV3dpV0s8K/1MGMJBeY5o7lg8ub5VIt1Ub+yVen6g=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.3.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA=="],
|
||||
|
||||
"webview-ui/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||
|
||||
"webview-ui/@vitejs/plugin-react-swc/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="],
|
||||
@@ -7215,7 +7235,7 @@
|
||||
|
||||
"react-remark/unified/vfile/vfile-message": ["vfile-message@2.0.4", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-stringify-position": "^2.0.0" } }, "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ=="],
|
||||
|
||||
"rimraf/glob/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
|
||||
"rimraf/glob/minimatch/brace-expansion": ["brace-expansion@5.0.7", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA=="],
|
||||
|
||||
"shadcn/open/wsl-utils/is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="],
|
||||
|
||||
@@ -7241,6 +7261,10 @@
|
||||
|
||||
"test-exclude/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw=="],
|
||||
|
||||
"vaul/@radix-ui/react-dialog/@radix-ui/react-focus-scope/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw=="],
|
||||
|
||||
"webview-ui/vitest/@vitest/utils/loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
|
||||
|
||||
"webview-ui/vitest/chai/check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="],
|
||||
@@ -7341,7 +7365,7 @@
|
||||
|
||||
"rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"shadcn/ts-morph/@ts-morph/common/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
|
||||
"shadcn/ts-morph/@ts-morph/common/minimatch/brace-expansion": ["brace-expansion@5.0.7", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA=="],
|
||||
|
||||
"test-exclude/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# Cline SDK Changelog
|
||||
|
||||
## 0.0.58
|
||||
|
||||
- `read_files` now tolerates malformed input from weaker models: line-range entries (`start_line`/`end_line`) sent as separate array items are coalesced back onto the preceding file path instead of being rejected
|
||||
|
||||
## 0.0.57
|
||||
|
||||
- Models in the live catalog that don't report a context window now default to a 128K input-token limit (up from 4,096), so under-specified models get a usable context budget
|
||||
- The default max input-token budget used for context compaction is now 128K
|
||||
- Added a shared prompt-format helper in `@cline/shared` and simplified runtime host support
|
||||
|
||||
## 0.0.56
|
||||
|
||||
- Tool calls from weaker models that use slightly-off argument shapes (e.g. a bare string where an array is expected) or malformed/truncated JSON are now coerced or repaired and executed, instead of being rejected before the tools can handle them
|
||||
- Fixed plan/act mode notices being stripped from outbound prompts
|
||||
- Added support for surfacing plan/act mode switches to the model
|
||||
|
||||
## 0.0.55
|
||||
|
||||
- Add Tencent TokenHub as a provider
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@cline/agents",
|
||||
"version": "0.0.55",
|
||||
"version": "0.0.58",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cline/cline",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@cline/core",
|
||||
"description": "Cline Core SDK for Node Runtime",
|
||||
"version": "0.0.55",
|
||||
"version": "0.0.58",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cline/cline",
|
||||
|
||||
@@ -13,7 +13,7 @@ import type {
|
||||
} from "../../types/config";
|
||||
import type { ProviderConfig } from "../../types/provider-settings";
|
||||
|
||||
export const DEFAULT_MAX_INPUT_TOKENS = 200_000;
|
||||
export const DEFAULT_MAX_INPUT_TOKENS = 128_000;
|
||||
export const DEFAULT_THRESHOLD_RATIO = 0.9;
|
||||
export const DEFAULT_TARGET_RATIO = 0.7;
|
||||
export const DEFAULT_RESERVE_TOKENS = 16_384;
|
||||
|
||||
@@ -1428,6 +1428,89 @@ describe("default read_files tool", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("folds orphan range entries into the preceding file entry", async () => {
|
||||
const execute = vi.fn(
|
||||
async (request: { path: string }) => `content:${request.path}`,
|
||||
);
|
||||
const tool = createReadFilesTool(execute);
|
||||
|
||||
await tool.execute(
|
||||
{
|
||||
files: [
|
||||
{ path: "/tmp/example.ips" },
|
||||
{ start_line: 45, end_line: 100 },
|
||||
],
|
||||
} as never,
|
||||
{
|
||||
agentId: "agent-1",
|
||||
conversationId: "conv-1",
|
||||
iteration: 1,
|
||||
},
|
||||
);
|
||||
await tool.execute(
|
||||
{ paths: ["/tmp/a.ts", { end_line: 4 }, "/tmp/b.ts"] } as never,
|
||||
{
|
||||
agentId: "agent-1",
|
||||
conversationId: "conv-1",
|
||||
iteration: 2,
|
||||
},
|
||||
);
|
||||
|
||||
expect(execute).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
{ path: "/tmp/example.ips", start_line: 45, end_line: 100 },
|
||||
expect.objectContaining({ iteration: 1 }),
|
||||
);
|
||||
expect(execute).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
{ path: "/tmp/a.ts", end_line: 4 },
|
||||
expect.objectContaining({ iteration: 2 }),
|
||||
);
|
||||
expect(execute).toHaveBeenNthCalledWith(
|
||||
3,
|
||||
{ path: "/tmp/b.ts" },
|
||||
expect.objectContaining({ iteration: 2 }),
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects orphan range entries that cannot be attached to a file entry", async () => {
|
||||
const execute = vi.fn(async () => "should not run");
|
||||
const tool = createReadFilesTool(execute);
|
||||
|
||||
// Leading orphan range: no preceding file entry to fold into.
|
||||
await expect(
|
||||
tool.execute(
|
||||
{
|
||||
files: [{ start_line: 1, end_line: 2 }, { path: "/tmp/a.ts" }],
|
||||
} as never,
|
||||
{
|
||||
agentId: "agent-1",
|
||||
conversationId: "conv-1",
|
||||
iteration: 1,
|
||||
},
|
||||
),
|
||||
).rejects.toThrow();
|
||||
|
||||
// Preceding entry already has its own range: keep the conflict visible.
|
||||
await expect(
|
||||
tool.execute(
|
||||
{
|
||||
files: [
|
||||
{ path: "/tmp/a.ts", start_line: 1 },
|
||||
{ start_line: 4, end_line: 8 },
|
||||
],
|
||||
} as never,
|
||||
{
|
||||
agentId: "agent-1",
|
||||
conversationId: "conv-1",
|
||||
iteration: 2,
|
||||
},
|
||||
),
|
||||
).rejects.toThrow();
|
||||
|
||||
expect(execute).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects invalid union inputs before calling the executor", async () => {
|
||||
const execute = vi.fn(async () => "should not run");
|
||||
const tool = createReadFilesTool(execute);
|
||||
@@ -1609,7 +1692,7 @@ describe("zod schema conversion", () => {
|
||||
required: ["path"],
|
||||
},
|
||||
description:
|
||||
"Array of file read requests. Omit start_line/end_line or set them to null to read from the start; provide integers to return only that inclusive one-based line range. Reads are capped, so page through long files with start_line/end_line. Prefer this tool over running terminal command to get file content for better performance and reliability.",
|
||||
"Array of file read requests; each element is one file and must include path. Omit start_line/end_line or set them to null to read from the start; provide integers on the same object as the path to return only that inclusive one-based line range — never emit a range as its own array element. Reads are capped, so page through long files with start_line/end_line. Prefer this tool over running terminal command to get file content for better performance and reliability.",
|
||||
});
|
||||
expect(inputSchema.required).toEqual(["files"]);
|
||||
});
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
MAX_SEARCH_OUTPUT_CHARS,
|
||||
} from "./executors/output-limits";
|
||||
import {
|
||||
coalesceOrphanReadRanges,
|
||||
formatError,
|
||||
formatReadFileQuery,
|
||||
formatRunCommandQueryPreview,
|
||||
@@ -246,9 +247,9 @@ export function createReadFilesTool(
|
||||
return createTool<ReadFilesInput, ToolOperationResult[]>({
|
||||
name: "read_files",
|
||||
description:
|
||||
"Read the content of text or image files at the provided absolute paths, or return only an inclusive one-based line range when start_line/end_line are provided. " +
|
||||
"Read the content of text or image files at the provided absolute paths, or return only an inclusive one-based line range when start_line/end_line are provided on the same file entry as its path. " +
|
||||
"When you already know multiple files you need, read them together in one call, and call this tool in the same response as other independent tool calls. " +
|
||||
`Each read returns at most ${MAX_READ_LINES} lines / ~${Math.round(MAX_READ_OUTPUT_CHARS / 1024)}k characters; longer files report their total line count, page through them with start_line/end_line. ` +
|
||||
`Each read returns at most ${MAX_READ_LINES} lines / ~${Math.round(MAX_READ_OUTPUT_CHARS / 1024)}k characters; longer files report their total line count, page through them with start_line/end_line on that file's entry. ` +
|
||||
"Binary files that are not image and large files are not supported. " +
|
||||
"Returns file contents or error messages for each path. ",
|
||||
inputSchema: zodToJsonSchema(ReadFilesInputSchema),
|
||||
@@ -256,7 +257,10 @@ export function createReadFilesTool(
|
||||
retryable: true,
|
||||
maxRetries: 1,
|
||||
execute: async (input, context) => {
|
||||
const validate = validateWithZod(ReadFilesInputUnionSchema, input);
|
||||
const validate = validateWithZod(
|
||||
ReadFilesInputUnionSchema,
|
||||
coalesceOrphanReadRanges(input),
|
||||
);
|
||||
let requests: ReadFileRequest[];
|
||||
if (typeof validate === "string") {
|
||||
requests = [{ path: validate }];
|
||||
|
||||
@@ -77,6 +77,63 @@ export function getReadFileRangeError(request: ReadFileRequest): string | null {
|
||||
return `start_line must be less than or equal to end_line (received start_line: ${start_line}, end_line: ${end_line})`;
|
||||
}
|
||||
|
||||
const READ_RANGE_KEYS = new Set(["start_line", "end_line"]);
|
||||
|
||||
function isOrphanReadRangeEntry(
|
||||
value: unknown,
|
||||
): value is Record<string, unknown> {
|
||||
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
||||
return false;
|
||||
}
|
||||
const keys = Object.keys(value);
|
||||
return keys.length > 0 && keys.every((key) => READ_RANGE_KEYS.has(key));
|
||||
}
|
||||
|
||||
function coalesceOrphanReadRangeEntries(entries: unknown[]): unknown[] {
|
||||
const coalesced: unknown[] = [];
|
||||
for (const entry of entries) {
|
||||
if (isOrphanReadRangeEntry(entry)) {
|
||||
const previous = coalesced[coalesced.length - 1];
|
||||
if (typeof previous === "string") {
|
||||
coalesced[coalesced.length - 1] = { path: previous, ...entry };
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
previous !== null &&
|
||||
typeof previous === "object" &&
|
||||
!Array.isArray(previous) &&
|
||||
"path" in previous &&
|
||||
Object.keys(entry).every((key) => !(key in previous))
|
||||
) {
|
||||
coalesced[coalesced.length - 1] = { ...previous, ...entry };
|
||||
continue;
|
||||
}
|
||||
}
|
||||
coalesced.push(entry);
|
||||
}
|
||||
return coalesced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some models emit a file's line range as a separate array element instead of
|
||||
* placing start_line/end_line on the same object as its path. Fold such
|
||||
* orphan range entries into the preceding file entry before validation.
|
||||
*/
|
||||
export function coalesceOrphanReadRanges(input: unknown): unknown {
|
||||
if (Array.isArray(input)) {
|
||||
return coalesceOrphanReadRangeEntries(input);
|
||||
}
|
||||
if (input !== null && typeof input === "object") {
|
||||
for (const key of ["files", "paths"] as const) {
|
||||
const value = (input as Record<string, unknown>)[key];
|
||||
if (Array.isArray(value)) {
|
||||
return { ...input, [key]: coalesceOrphanReadRangeEntries(value) };
|
||||
}
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
export function normalizeRunCommandsInput(
|
||||
input: unknown,
|
||||
): Array<string | StructuredCommandInput> {
|
||||
|
||||
@@ -46,7 +46,7 @@ export const ReadFileRequestSchema = z
|
||||
end_line: ReadFileLineRangeSchema.shape.end_line,
|
||||
})
|
||||
.describe(
|
||||
"A file read request with optional inclusive one-based line bounds",
|
||||
"A file read request with optional inclusive one-based line bounds. Always include path; start_line/end_line must be on the same object as the path they apply to, never in a separate array element",
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -56,7 +56,7 @@ export const ReadFilesInputSchema = z.object({
|
||||
files: z
|
||||
.array(ReadFileRequestSchema)
|
||||
.describe(
|
||||
"Array of file read requests. Omit start_line/end_line or set them to null to read from the start; provide integers to return only that inclusive one-based line range. Reads are capped, so page through long files with start_line/end_line. Prefer this tool over running terminal command to get file content for better performance and reliability.",
|
||||
"Array of file read requests; each element is one file and must include path. Omit start_line/end_line or set them to null to read from the start; provide integers on the same object as the path to return only that inclusive one-based line range — never emit a range as its own array element. Reads are capped, so page through long files with start_line/end_line. Prefer this tool over running terminal command to get file content for better performance and reliability.",
|
||||
),
|
||||
});
|
||||
|
||||
|
||||
@@ -13,7 +13,11 @@ afterEach(async () => {
|
||||
});
|
||||
|
||||
describe("readPersistedMessagesFile", () => {
|
||||
it("strips wrapped user_input envelopes from user history messages", async () => {
|
||||
it("returns persisted messages verbatim, wrappers included", async () => {
|
||||
// The user_input wrapper records which mode each message was sent in
|
||||
// and session restarts re-seed through this read path, so stripping
|
||||
// here would destroy that history a little more on every restart.
|
||||
// Display surfaces format for themselves via formatDisplayUserInput.
|
||||
const dir = await mkdtemp(join(tmpdir(), "runtime-host-support-"));
|
||||
tempDirs.push(dir);
|
||||
const messagesPath = join(dir, "messages.json");
|
||||
@@ -33,7 +37,7 @@ describe("readPersistedMessagesFile", () => {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: '<user_input mode="plan">inspect repo</user_input>',
|
||||
text: '<user_input mode="plan"><mode_notice>The user switched from act mode to plan mode before sending this message.</mode_notice>\ninspect repo</user_input>',
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -43,12 +47,14 @@ describe("readPersistedMessagesFile", () => {
|
||||
|
||||
const messages = await readPersistedMessagesFile(messagesPath);
|
||||
|
||||
expect(messages[0]?.content).toBe("spawn a team of agents");
|
||||
expect(messages[0]?.content).toBe(
|
||||
'<user_input mode="act">spawn a team of agents</user_input>',
|
||||
);
|
||||
expect(messages[1]?.content).toBe("Working on it.");
|
||||
expect(messages[2]?.content).toEqual([
|
||||
{
|
||||
type: "text",
|
||||
text: "inspect repo",
|
||||
text: '<user_input mode="plan"><mode_notice>The user switched from act mode to plan mode before sending this message.</mode_notice>\ninspect repo</user_input>',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { existsSync } from "node:fs";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import type * as LlmsProviders from "@cline/llms";
|
||||
import { formatDisplayUserInput } from "@cline/shared";
|
||||
import type { HookEventPayload } from "../../hooks";
|
||||
import type { CoreSessionEvent } from "../../types/events";
|
||||
import type {
|
||||
@@ -44,6 +43,13 @@ export class RuntimeHostEventBus {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the persisted messages verbatim. User messages keep their
|
||||
// runtime-generated <user_input mode="..."> wrappers and <mode_notice>
|
||||
// elements: they are the durable record of which mode each message was sent
|
||||
// in, and session restarts re-seed new sessions through this read path, so
|
||||
// stripping here would launder that history off disk (and out of the model's
|
||||
// context) a little more on every restart. Display surfaces are responsible
|
||||
// for their own formatting via formatDisplayUserInput.
|
||||
export async function readPersistedMessagesFile(
|
||||
messagesPath?: string | null,
|
||||
): Promise<LlmsProviders.Message[]> {
|
||||
@@ -54,12 +60,12 @@ export async function readPersistedMessagesFile(
|
||||
if (!raw) return [];
|
||||
const parsed = JSON.parse(raw) as unknown;
|
||||
if (Array.isArray(parsed)) {
|
||||
return sanitizeDisplayMessages(parsed as LlmsProviders.Message[]);
|
||||
return parsed as LlmsProviders.Message[];
|
||||
}
|
||||
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
||||
const messages = (parsed as { messages?: unknown }).messages;
|
||||
if (Array.isArray(messages)) {
|
||||
return sanitizeDisplayMessages(messages as LlmsProviders.Message[]);
|
||||
return messages as LlmsProviders.Message[];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
@@ -68,38 +74,6 @@ export async function readPersistedMessagesFile(
|
||||
}
|
||||
}
|
||||
|
||||
function sanitizeDisplayMessage(
|
||||
message: LlmsProviders.Message,
|
||||
): LlmsProviders.Message {
|
||||
if (message.role !== "user") {
|
||||
return message;
|
||||
}
|
||||
if (typeof message.content === "string") {
|
||||
return {
|
||||
...message,
|
||||
content: formatDisplayUserInput(message.content),
|
||||
};
|
||||
}
|
||||
return {
|
||||
...message,
|
||||
content: message.content.map((part) => {
|
||||
if (part.type !== "text" || typeof part.text !== "string") {
|
||||
return part;
|
||||
}
|
||||
return {
|
||||
...part,
|
||||
text: formatDisplayUserInput(part.text),
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function sanitizeDisplayMessages(
|
||||
messages: LlmsProviders.Message[],
|
||||
): LlmsProviders.Message[] {
|
||||
return messages.map(sanitizeDisplayMessage);
|
||||
}
|
||||
|
||||
export function cloneAccumulatedUsage(
|
||||
usage: SessionAccumulatedUsage | undefined,
|
||||
): SessionAccumulatedUsage | undefined {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { mkdirSync, writeFileSync } from "node:fs";
|
||||
import { dirname } from "node:path";
|
||||
import type * as LlmsProviders from "@cline/llms";
|
||||
import type { AgentConfig, AgentEvent, AgentResult } from "@cline/shared";
|
||||
import { normalizeUserInput } from "@cline/shared";
|
||||
import { normalizeUserInput, stripModeNotices } from "@cline/shared";
|
||||
import { nanoid } from "nanoid";
|
||||
import {
|
||||
parseSubSessionId,
|
||||
@@ -231,7 +231,11 @@ export function normalizeTitle(title?: string | null): string | undefined {
|
||||
export function deriveTitleFromPrompt(
|
||||
prompt?: string | null,
|
||||
): string | undefined {
|
||||
const normalized = normalizeUserInput(prompt ?? "").trim();
|
||||
// Titles are display-only, so runtime-generated notice elements are
|
||||
// stripped here rather than inside normalizeUserInput -- that function also
|
||||
// sanitizes model-bound prompts (prepareTurnInput), where the notice must
|
||||
// survive to reach the model.
|
||||
const normalized = stripModeNotices(normalizeUserInput(prompt ?? "")).trim();
|
||||
if (!normalized) return undefined;
|
||||
return normalizeTitle(normalized.split("\n")[0]?.trim());
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@cline/llms",
|
||||
"version": "0.0.55",
|
||||
"version": "0.0.58",
|
||||
"description": "Config-driven SDK for selecting, extending, and instantiating LLM providers and models",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -113,6 +113,7 @@ describe("models-dev-catalog", () => {
|
||||
});
|
||||
|
||||
it("uses input limits as the model request context window", () => {
|
||||
expect(resolveMaxInputTokens(undefined)).toBe(128_000);
|
||||
expect(
|
||||
resolveMaxInputTokens({
|
||||
context: 400_000,
|
||||
@@ -274,7 +275,7 @@ describe("models-dev-catalog", () => {
|
||||
id: "claude-defaults",
|
||||
name: "claude-defaults",
|
||||
contextWindow: undefined,
|
||||
maxInputTokens: 4096,
|
||||
maxInputTokens: 128_000,
|
||||
maxTokens: 4096,
|
||||
capabilities: ["tools"],
|
||||
pricing: {
|
||||
@@ -291,7 +292,7 @@ describe("models-dev-catalog", () => {
|
||||
id: "claude-older",
|
||||
name: "claude-older",
|
||||
contextWindow: undefined,
|
||||
maxInputTokens: 4096,
|
||||
maxInputTokens: 128_000,
|
||||
maxTokens: 4096,
|
||||
capabilities: ["tools"],
|
||||
pricing: {
|
||||
|
||||
@@ -37,7 +37,7 @@ interface ModelsDevProviderPayload {
|
||||
export type ModelsDevPayload = Record<string, ModelsDevProviderPayload>;
|
||||
export type ModelsDevProviderKeyMap = Record<string, string>;
|
||||
|
||||
const DEFAULT_MAX_INPUT_TOKENS = 4096;
|
||||
const DEFAULT_MAX_INPUT_TOKENS = 128_000;
|
||||
const DEFAULT_MAX_TOKENS = 4096;
|
||||
|
||||
function parseReleaseDate(value: string | undefined): number {
|
||||
|
||||
@@ -14,7 +14,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
version: number;
|
||||
providers: Record<string, Record<string, ModelInfo>>;
|
||||
} = {
|
||||
version: 1783097653299,
|
||||
version: 1783386091437,
|
||||
providers: {
|
||||
aihubmix: {
|
||||
"glm-5.2": {
|
||||
@@ -1229,14 +1229,21 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
contextWindow: 1000000,
|
||||
maxInputTokens: 1000000,
|
||||
maxTokens: 128000,
|
||||
capabilities: ["images", "files", "tools", "reasoning", "prompt-cache"],
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 2,
|
||||
output: 10,
|
||||
cacheRead: 0.2,
|
||||
cacheWrite: 2.5,
|
||||
},
|
||||
releaseDate: "2026-06-30",
|
||||
releaseDate: "2026-06-29",
|
||||
family: "claude-sonnet",
|
||||
},
|
||||
"claude-fable-5": {
|
||||
@@ -1245,14 +1252,21 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
contextWindow: 1000000,
|
||||
maxInputTokens: 1000000,
|
||||
maxTokens: 128000,
|
||||
capabilities: ["images", "files", "tools", "reasoning", "prompt-cache"],
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 10,
|
||||
output: 50,
|
||||
cacheRead: 1,
|
||||
cacheWrite: 12.5,
|
||||
},
|
||||
releaseDate: "2026-06-09",
|
||||
releaseDate: "2026-06-07",
|
||||
family: "claude-fable",
|
||||
},
|
||||
"claude-opus-4-8": {
|
||||
@@ -1261,7 +1275,14 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
contextWindow: 1000000,
|
||||
maxInputTokens: 1000000,
|
||||
maxTokens: 128000,
|
||||
capabilities: ["images", "files", "tools", "reasoning", "prompt-cache"],
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 5,
|
||||
output: 25,
|
||||
@@ -1277,14 +1298,21 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
contextWindow: 1000000,
|
||||
maxInputTokens: 1000000,
|
||||
maxTokens: 128000,
|
||||
capabilities: ["images", "files", "tools", "reasoning", "prompt-cache"],
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 5,
|
||||
output: 25,
|
||||
cacheRead: 0.5,
|
||||
cacheWrite: 6.25,
|
||||
},
|
||||
releaseDate: "2026-04-16",
|
||||
releaseDate: "2026-04-14",
|
||||
family: "claude-opus",
|
||||
},
|
||||
"claude-sonnet-4-6": {
|
||||
@@ -1292,12 +1320,13 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
name: "Claude Sonnet 4.6",
|
||||
contextWindow: 1000000,
|
||||
maxInputTokens: 1000000,
|
||||
maxTokens: 64000,
|
||||
maxTokens: 128000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
@@ -1321,6 +1350,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
@@ -1330,7 +1360,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
cacheRead: 0.5,
|
||||
cacheWrite: 6.25,
|
||||
},
|
||||
releaseDate: "2026-02-05",
|
||||
releaseDate: "2026-02-04",
|
||||
family: "claude-opus",
|
||||
},
|
||||
"claude-opus-4-5": {
|
||||
@@ -1344,6 +1374,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
@@ -1367,6 +1398,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
@@ -1376,7 +1408,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
cacheRead: 0.5,
|
||||
cacheWrite: 6.25,
|
||||
},
|
||||
releaseDate: "2025-11-01",
|
||||
releaseDate: "2025-11-24",
|
||||
family: "claude-opus",
|
||||
},
|
||||
"claude-haiku-4-5": {
|
||||
@@ -1390,6 +1422,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
@@ -1413,6 +1446,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
@@ -1428,14 +1462,15 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"claude-sonnet-4-5": {
|
||||
id: "claude-sonnet-4-5",
|
||||
name: "Claude Sonnet 4.5 (latest)",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
contextWindow: 1000000,
|
||||
maxInputTokens: 1000000,
|
||||
maxTokens: 64000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
@@ -1451,14 +1486,15 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"claude-sonnet-4-5-20250929": {
|
||||
id: "claude-sonnet-4-5-20250929",
|
||||
name: "Claude Sonnet 4.5",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
contextWindow: 1000000,
|
||||
maxInputTokens: 1000000,
|
||||
maxTokens: 64000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
@@ -1471,144 +1507,6 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
releaseDate: "2025-09-29",
|
||||
family: "claude-sonnet",
|
||||
},
|
||||
"claude-opus-4-1": {
|
||||
id: "claude-opus-4-1",
|
||||
name: "Claude Opus 4.1 (latest)",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
maxTokens: 32000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 15,
|
||||
output: 75,
|
||||
cacheRead: 1.5,
|
||||
cacheWrite: 18.75,
|
||||
},
|
||||
releaseDate: "2025-08-05",
|
||||
family: "claude-opus",
|
||||
},
|
||||
"claude-opus-4-1-20250805": {
|
||||
id: "claude-opus-4-1-20250805",
|
||||
name: "Claude Opus 4.1",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
maxTokens: 32000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 15,
|
||||
output: 75,
|
||||
cacheRead: 1.5,
|
||||
cacheWrite: 18.75,
|
||||
},
|
||||
releaseDate: "2025-08-05",
|
||||
family: "claude-opus",
|
||||
},
|
||||
"claude-opus-4-0": {
|
||||
id: "claude-opus-4-0",
|
||||
name: "Claude Opus 4 (latest)",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
maxTokens: 32000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 15,
|
||||
output: 75,
|
||||
cacheRead: 1.5,
|
||||
cacheWrite: 18.75,
|
||||
},
|
||||
releaseDate: "2025-05-22",
|
||||
family: "claude-opus",
|
||||
},
|
||||
"claude-opus-4-20250514": {
|
||||
id: "claude-opus-4-20250514",
|
||||
name: "Claude Opus 4",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
maxTokens: 32000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 15,
|
||||
output: 75,
|
||||
cacheRead: 1.5,
|
||||
cacheWrite: 18.75,
|
||||
},
|
||||
releaseDate: "2025-05-22",
|
||||
family: "claude-opus",
|
||||
},
|
||||
"claude-sonnet-4-0": {
|
||||
id: "claude-sonnet-4-0",
|
||||
name: "Claude Sonnet 4 (latest)",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
maxTokens: 64000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 3,
|
||||
output: 15,
|
||||
cacheRead: 0.3,
|
||||
cacheWrite: 3.75,
|
||||
},
|
||||
releaseDate: "2025-05-22",
|
||||
family: "claude-sonnet",
|
||||
},
|
||||
"claude-sonnet-4-20250514": {
|
||||
id: "claude-sonnet-4-20250514",
|
||||
name: "Claude Sonnet 4",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
maxTokens: 64000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 3,
|
||||
output: 15,
|
||||
cacheRead: 0.3,
|
||||
cacheWrite: 3.75,
|
||||
},
|
||||
releaseDate: "2025-05-22",
|
||||
family: "claude-sonnet",
|
||||
},
|
||||
},
|
||||
baseten: {
|
||||
"zai-org/GLM-5.2": {
|
||||
@@ -3100,6 +2998,30 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
releaseDate: "2025-10-15",
|
||||
family: "claude-haiku",
|
||||
},
|
||||
"jp.anthropic.claude-haiku-4-5-20251001-v1:0": {
|
||||
id: "jp.anthropic.claude-haiku-4-5-20251001-v1:0",
|
||||
name: "Claude Haiku 4.5 (JP)",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
maxTokens: 64000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 1,
|
||||
output: 5,
|
||||
cacheRead: 0.1,
|
||||
cacheWrite: 1.25,
|
||||
},
|
||||
releaseDate: "2025-10-15",
|
||||
family: "claude-haiku",
|
||||
},
|
||||
"us.anthropic.claude-haiku-4-5-20251001-v1:0": {
|
||||
id: "us.anthropic.claude-haiku-4-5-20251001-v1:0",
|
||||
name: "Claude Haiku 4.5 (US)",
|
||||
@@ -4070,7 +3992,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
id: "cline-pass/glm-5.2",
|
||||
contextWindow: 1048576,
|
||||
maxInputTokens: 1048576,
|
||||
maxTokens: 32768,
|
||||
maxTokens: 131072,
|
||||
capabilities: [
|
||||
"tools",
|
||||
"reasoning",
|
||||
@@ -4079,9 +4001,9 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.93,
|
||||
output: 3,
|
||||
cacheRead: 0.18,
|
||||
input: 0.9086,
|
||||
output: 2.8556,
|
||||
cacheRead: 0.16874,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
releaseDate: "2026-06-13",
|
||||
@@ -4100,11 +4022,12 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.105,
|
||||
output: 0.28,
|
||||
cacheRead: 0,
|
||||
cacheRead: 0.028,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
releaseDate: "2026-04-22",
|
||||
@@ -5696,6 +5619,27 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
releaseDate: "2025-08-05",
|
||||
family: "gpt-oss",
|
||||
},
|
||||
"openai/gpt-oss-20b": {
|
||||
id: "openai/gpt-oss-20b",
|
||||
name: "GPT OSS 20B",
|
||||
contextWindow: 131072,
|
||||
maxInputTokens: 131072,
|
||||
maxTokens: 32768,
|
||||
capabilities: [
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.1,
|
||||
output: 0.5,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
releaseDate: "2025-08-05",
|
||||
family: "gpt-oss",
|
||||
},
|
||||
"zai-org/GLM-4.5": {
|
||||
id: "zai-org/GLM-4.5",
|
||||
name: "GLM-4.5",
|
||||
@@ -12190,6 +12134,49 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
},
|
||||
},
|
||||
openrouter: {
|
||||
"tencent/hy3": {
|
||||
id: "tencent/hy3",
|
||||
name: "Hy3",
|
||||
contextWindow: 202752,
|
||||
maxInputTokens: 202752,
|
||||
maxTokens: 131072,
|
||||
capabilities: [
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.14,
|
||||
output: 0.58,
|
||||
cacheRead: 0.035,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
releaseDate: "2026-07-06",
|
||||
family: "hy3",
|
||||
},
|
||||
"tencent/hy3:free": {
|
||||
id: "tencent/hy3:free",
|
||||
name: "Hy3 (free)",
|
||||
contextWindow: 262144,
|
||||
maxInputTokens: 262144,
|
||||
maxTokens: 262144,
|
||||
capabilities: [
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
],
|
||||
pricing: {
|
||||
input: 0,
|
||||
output: 0,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
releaseDate: "2026-07-06",
|
||||
family: "hy3",
|
||||
},
|
||||
"poolside/laguna-xs-2.1": {
|
||||
id: "poolside/laguna-xs-2.1",
|
||||
name: "Laguna XS 2.1",
|
||||
@@ -12243,6 +12230,29 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
releaseDate: "2026-06-30",
|
||||
family: "claude-sonnet",
|
||||
},
|
||||
"nex-agi/nex-n2-mini": {
|
||||
id: "nex-agi/nex-n2-mini",
|
||||
name: "Nex-N2-Mini",
|
||||
contextWindow: 262144,
|
||||
maxInputTokens: 262144,
|
||||
maxTokens: 262144,
|
||||
capabilities: [
|
||||
"images",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.025,
|
||||
output: 0.1,
|
||||
cacheRead: 0.0025,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
releaseDate: "2026-06-24",
|
||||
family: "agi",
|
||||
},
|
||||
"sakana/fugu-ultra": {
|
||||
id: "sakana/fugu-ultra",
|
||||
name: "Fugu Ultra",
|
||||
@@ -12309,7 +12319,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
name: "GLM-5.2",
|
||||
contextWindow: 1048576,
|
||||
maxInputTokens: 1048576,
|
||||
maxTokens: 32768,
|
||||
maxTokens: 131072,
|
||||
capabilities: [
|
||||
"tools",
|
||||
"reasoning",
|
||||
@@ -12318,9 +12328,9 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.93,
|
||||
output: 3,
|
||||
cacheRead: 0.18,
|
||||
input: 0.9086,
|
||||
output: 2.8556,
|
||||
cacheRead: 0.16874,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
releaseDate: "2026-06-13",
|
||||
@@ -13153,11 +13163,12 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.105,
|
||||
output: 0.28,
|
||||
cacheRead: 0,
|
||||
cacheRead: 0.028,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
releaseDate: "2026-04-22",
|
||||
@@ -13728,8 +13739,8 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"temperature",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.085,
|
||||
output: 0.4,
|
||||
input: 0.08,
|
||||
output: 0.45,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
@@ -14131,11 +14142,12 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.385,
|
||||
output: 2.45,
|
||||
cacheRead: 0,
|
||||
cacheRead: 0.111,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
releaseDate: "2026-02-15",
|
||||
@@ -14418,11 +14430,12 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.375,
|
||||
output: 2.025,
|
||||
cacheRead: 0,
|
||||
cacheRead: 0.203,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
releaseDate: "2026-01",
|
||||
@@ -15789,7 +15802,7 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
},
|
||||
"openai/gpt-oss-20b": {
|
||||
id: "openai/gpt-oss-20b",
|
||||
name: "gpt-oss-20b",
|
||||
name: "GPT OSS 20B",
|
||||
contextWindow: 131072,
|
||||
maxInputTokens: 131072,
|
||||
maxTokens: 131072,
|
||||
@@ -21187,14 +21200,15 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"anthropic/claude-sonnet-4.5": {
|
||||
id: "anthropic/claude-sonnet-4.5",
|
||||
name: "Claude Sonnet 4.5",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
contextWindow: 1000000,
|
||||
maxInputTokens: 1000000,
|
||||
maxTokens: 64000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
@@ -21560,29 +21574,6 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
releaseDate: "2025-08-07",
|
||||
family: "gpt-nano",
|
||||
},
|
||||
"anthropic/claude-opus-4.1": {
|
||||
id: "anthropic/claude-opus-4.1",
|
||||
name: "Claude Opus 4.1",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
maxTokens: 32000,
|
||||
capabilities: [
|
||||
"images",
|
||||
"files",
|
||||
"tools",
|
||||
"reasoning",
|
||||
"temperature",
|
||||
"prompt-cache",
|
||||
],
|
||||
pricing: {
|
||||
input: 15,
|
||||
output: 75,
|
||||
cacheRead: 1.5,
|
||||
cacheWrite: 18.75,
|
||||
},
|
||||
releaseDate: "2025-08-05",
|
||||
family: "claude-opus",
|
||||
},
|
||||
"openai/gpt-oss-120b": {
|
||||
id: "openai/gpt-oss-120b",
|
||||
name: "GPT OSS 120B",
|
||||
@@ -21610,7 +21601,12 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
contextWindow: 131072,
|
||||
maxInputTokens: 122880,
|
||||
maxTokens: 8192,
|
||||
capabilities: ["tools", "reasoning", "temperature"],
|
||||
capabilities: [
|
||||
"tools",
|
||||
"reasoning",
|
||||
"structured_output",
|
||||
"temperature",
|
||||
],
|
||||
pricing: {
|
||||
input: 0.05,
|
||||
output: 0.2,
|
||||
@@ -21876,8 +21872,8 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
"anthropic/claude-sonnet-4": {
|
||||
id: "anthropic/claude-sonnet-4",
|
||||
name: "Claude Sonnet 4",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
contextWindow: 1000000,
|
||||
maxInputTokens: 1000000,
|
||||
maxTokens: 64000,
|
||||
capabilities: [
|
||||
"images",
|
||||
@@ -22617,6 +22613,22 @@ export const GENERATED_PROVIDER_MODELS: {
|
||||
releaseDate: "2024-05-13",
|
||||
family: "gpt",
|
||||
},
|
||||
"anthropic/claude-3-haiku": {
|
||||
id: "anthropic/claude-3-haiku",
|
||||
name: "Claude Haiku 3",
|
||||
contextWindow: 200000,
|
||||
maxInputTokens: 200000,
|
||||
maxTokens: 4096,
|
||||
capabilities: ["images", "tools", "temperature", "prompt-cache"],
|
||||
pricing: {
|
||||
input: 0.25,
|
||||
output: 1.25,
|
||||
cacheRead: 0.03,
|
||||
cacheWrite: 0.3,
|
||||
},
|
||||
releaseDate: "2024-03-13",
|
||||
family: "claude-haiku",
|
||||
},
|
||||
"openai/gpt-4-turbo": {
|
||||
id: "openai/gpt-4-turbo",
|
||||
name: "GPT-4 Turbo",
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
import type {
|
||||
AgentModelEvent,
|
||||
AgentToolDefinition,
|
||||
GatewayProviderContext,
|
||||
GatewayStreamRequest,
|
||||
} from "@cline/shared";
|
||||
import { NoSuchToolError } from "ai";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
createOpenAICompatibleProvider,
|
||||
repairMalformedToolCall,
|
||||
} from "./ai-sdk";
|
||||
|
||||
/**
|
||||
* Integration tests for malformed tool-call handling in the AI SDK adapter.
|
||||
*
|
||||
* Weaker models routinely emit tool calls with type mismatches (a bare string
|
||||
* where the schema wants an array) or arguments that are not valid JSON
|
||||
* (truncated payloads, single quotes). These tests drive the real adapter
|
||||
* with a fake OpenAI-compatible SSE response and assert that such calls are
|
||||
* coerced/repaired instead of being rejected before execution
|
||||
* (`metadata.inputParseError`), which surfaced as the
|
||||
* tool_call_type_validation / tool_call_invalid_json buckets under
|
||||
* task.provider_api_error.
|
||||
*/
|
||||
|
||||
const RUN_COMMANDS_TOOL: AgentToolDefinition = {
|
||||
name: "run_commands",
|
||||
description: "Run shell commands",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
commands: { type: "array", items: { type: "string" } },
|
||||
},
|
||||
required: ["commands"],
|
||||
},
|
||||
};
|
||||
|
||||
const READ_FILES_TOOL: AgentToolDefinition = {
|
||||
name: "read_files",
|
||||
description: "Read files",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
files: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: { path: { type: "string" } },
|
||||
required: ["path"],
|
||||
},
|
||||
},
|
||||
},
|
||||
required: ["files"],
|
||||
},
|
||||
};
|
||||
|
||||
function sseToolCall(toolName: string, args: string): string {
|
||||
const chunk = (delta: unknown, finish: string | null = null) =>
|
||||
`data: ${JSON.stringify({
|
||||
id: "cmpl-1",
|
||||
object: "chat.completion.chunk",
|
||||
created: 1,
|
||||
model: "test-model",
|
||||
choices: [{ index: 0, delta, finish_reason: finish }],
|
||||
})}\n\n`;
|
||||
return (
|
||||
chunk({
|
||||
role: "assistant",
|
||||
tool_calls: [
|
||||
{
|
||||
index: 0,
|
||||
id: "call_1",
|
||||
type: "function",
|
||||
function: { name: toolName, arguments: "" },
|
||||
},
|
||||
],
|
||||
}) +
|
||||
chunk({ tool_calls: [{ index: 0, function: { arguments: args } }] }) +
|
||||
chunk({}, "tool_calls") +
|
||||
"data: [DONE]\n\n"
|
||||
);
|
||||
}
|
||||
|
||||
async function streamToolCallEvents(
|
||||
sseBody: string,
|
||||
tools: AgentToolDefinition[],
|
||||
): Promise<AgentModelEvent[]> {
|
||||
const config = {
|
||||
providerId: "openai-compatible",
|
||||
apiKey: "test-key",
|
||||
baseUrl: "http://fake.local/v1",
|
||||
fetch: (async () =>
|
||||
new Response(sseBody, {
|
||||
status: 200,
|
||||
headers: { "content-type": "text/event-stream" },
|
||||
})) as unknown as typeof fetch,
|
||||
};
|
||||
const provider = await createOpenAICompatibleProvider(config);
|
||||
const model = {
|
||||
id: "test-model",
|
||||
providerId: "openai-compatible",
|
||||
name: "test-model",
|
||||
};
|
||||
const context = {
|
||||
provider: {
|
||||
id: "openai-compatible",
|
||||
name: "OpenAI Compatible",
|
||||
defaultModelId: "test-model",
|
||||
models: [model],
|
||||
},
|
||||
model,
|
||||
config,
|
||||
} as unknown as GatewayProviderContext;
|
||||
const request = {
|
||||
providerId: "openai-compatible",
|
||||
modelId: "test-model",
|
||||
messages: [
|
||||
{
|
||||
id: "msg_user",
|
||||
role: "user",
|
||||
content: [{ type: "text", text: "do the thing" }],
|
||||
createdAt: new Date(),
|
||||
},
|
||||
],
|
||||
tools,
|
||||
} as unknown as GatewayStreamRequest;
|
||||
|
||||
const events: AgentModelEvent[] = [];
|
||||
for await (const event of await provider.stream(request, context)) {
|
||||
events.push(event);
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
function findParseError(events: AgentModelEvent[]): string | undefined {
|
||||
for (const event of events) {
|
||||
if (event.type !== "tool-call-delta") continue;
|
||||
const metadata = event.metadata as Record<string, unknown> | undefined;
|
||||
if (typeof metadata?.inputParseError === "string") {
|
||||
return metadata.inputParseError;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function findToolInput(events: AgentModelEvent[]): unknown {
|
||||
for (const event of events) {
|
||||
if (event.type === "tool-call-delta" && event.input !== undefined) {
|
||||
return event.input;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
describe("ai-sdk adapter malformed tool calls", () => {
|
||||
it("passes schema-mismatched input through to the tool instead of rejecting", async () => {
|
||||
// The executor's lenient union schema accepts a bare string for a
|
||||
// string[] property; rejecting at the adapter would prevent that.
|
||||
const events = await streamToolCallEvents(
|
||||
sseToolCall("run_commands", '{"commands": "ls -la"}'),
|
||||
[RUN_COMMANDS_TOOL],
|
||||
);
|
||||
|
||||
expect(findParseError(events)).toBeUndefined();
|
||||
expect(findToolInput(events)).toEqual({ commands: "ls -la" });
|
||||
});
|
||||
|
||||
it("passes well-formed input through unchanged", async () => {
|
||||
const events = await streamToolCallEvents(
|
||||
sseToolCall("run_commands", '{"commands": ["ls", "pwd"]}'),
|
||||
[RUN_COMMANDS_TOOL],
|
||||
);
|
||||
|
||||
expect(findParseError(events)).toBeUndefined();
|
||||
expect(findToolInput(events)).toEqual({ commands: ["ls", "pwd"] });
|
||||
});
|
||||
|
||||
it("repairs truncated JSON arguments", async () => {
|
||||
const events = await streamToolCallEvents(
|
||||
sseToolCall("read_files", '{"files": [{"path": "/tmp/a.txt"}]'),
|
||||
[READ_FILES_TOOL],
|
||||
);
|
||||
|
||||
expect(findParseError(events)).toBeUndefined();
|
||||
expect(findToolInput(events)).toEqual({ files: [{ path: "/tmp/a.txt" }] });
|
||||
});
|
||||
|
||||
it("repairs single-quoted JSON arguments", async () => {
|
||||
const events = await streamToolCallEvents(
|
||||
sseToolCall("run_commands", "{'commands': ['ls']}"),
|
||||
[RUN_COMMANDS_TOOL],
|
||||
);
|
||||
|
||||
expect(findParseError(events)).toBeUndefined();
|
||||
expect(findToolInput(events)).toEqual({ commands: ["ls"] });
|
||||
});
|
||||
|
||||
it("still surfaces a parse error for unrepairable argument text", async () => {
|
||||
const events = await streamToolCallEvents(
|
||||
sseToolCall("run_commands", "run ls for me please"),
|
||||
[RUN_COMMANDS_TOOL],
|
||||
);
|
||||
|
||||
expect(findParseError(events)).toContain("Invalid input");
|
||||
});
|
||||
|
||||
it("keeps the unavailable-tool error for unknown tools", async () => {
|
||||
const events = await streamToolCallEvents(
|
||||
sseToolCall("editor", '{"path": "/tmp/a.txt", "new_text": "x"}'),
|
||||
[RUN_COMMANDS_TOOL, READ_FILES_TOOL],
|
||||
);
|
||||
|
||||
expect(findParseError(events)).toContain("unavailable tool 'editor'");
|
||||
});
|
||||
});
|
||||
|
||||
describe("repairMalformedToolCall", () => {
|
||||
const toolCall = (input: string) => ({
|
||||
toolCallId: "call_1",
|
||||
toolName: "run_commands",
|
||||
input,
|
||||
});
|
||||
|
||||
it("repairs truncated JSON", async () => {
|
||||
const repaired = await repairMalformedToolCall({
|
||||
toolCall: toolCall('{"commands": ["ls"'),
|
||||
error: new Error("JSON parsing failed"),
|
||||
});
|
||||
expect(repaired?.input).toBe('{"commands":["ls"]}');
|
||||
});
|
||||
|
||||
it("repairs single-quoted JSON", async () => {
|
||||
const repaired = await repairMalformedToolCall({
|
||||
toolCall: toolCall("{'commands': ['ls']}"),
|
||||
error: new Error("JSON parsing failed"),
|
||||
});
|
||||
expect(repaired?.input).toBe('{"commands":["ls"]}');
|
||||
});
|
||||
|
||||
it("returns null for already-valid JSON (schema failures are not repairable here)", async () => {
|
||||
const repaired = await repairMalformedToolCall({
|
||||
toolCall: toolCall('{"commands": "ls"}'),
|
||||
error: new Error("Type validation failed"),
|
||||
});
|
||||
expect(repaired).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null for unknown-tool errors", async () => {
|
||||
const repaired = await repairMalformedToolCall({
|
||||
toolCall: toolCall('{"commands": ["ls"]}'),
|
||||
error: new NoSuchToolError({ toolName: "run_commands" }),
|
||||
});
|
||||
expect(repaired).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null for unrepairable garbage", async () => {
|
||||
const repaired = await repairMalformedToolCall({
|
||||
toolCall: toolCall("run ls for me"),
|
||||
error: new Error("JSON parsing failed"),
|
||||
});
|
||||
expect(repaired).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -12,11 +12,11 @@ import {
|
||||
type AiSdkFormatterPart,
|
||||
captureSdkError,
|
||||
formatMessagesForAiSdk,
|
||||
parseJsonStream,
|
||||
sanitizeSurrogates,
|
||||
} from "@cline/shared";
|
||||
import { jsonSchema, streamText } from "ai";
|
||||
import { jsonSchema, NoSuchToolError, streamText } from "ai";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { extractErrorMessage } from "./format";
|
||||
import {
|
||||
isAnthropicCompatibleModel,
|
||||
@@ -373,6 +373,11 @@ function toAiSdkTools(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// No validate callback on purpose: schema validation belongs to the tools
|
||||
// themselves (core executors validate with lenient union schemas that
|
||||
// accept common weak-model shapes like a bare string for a string[]
|
||||
// property). Rejecting here would return an error to the model without
|
||||
// the tool's own input handling ever seeing the call.
|
||||
return Object.fromEntries(
|
||||
request.tools.map((definition) => [
|
||||
definition.name,
|
||||
@@ -380,22 +385,54 @@ function toAiSdkTools(
|
||||
description: definition.description,
|
||||
inputSchema: jsonSchema(
|
||||
normalizeAiSdkToolInputSchema(definition.inputSchema),
|
||||
{
|
||||
validate: async (value) => {
|
||||
const result = await z
|
||||
.fromJSONSchema(definition.inputSchema)
|
||||
.safeParseAsync(value);
|
||||
return result.success
|
||||
? { success: true, value: result.data }
|
||||
: { success: false, error: result.error };
|
||||
},
|
||||
},
|
||||
) as never,
|
||||
} as unknown,
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
interface RepairableToolCall {
|
||||
toolCallId: string;
|
||||
toolName: string;
|
||||
input: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Last-chance repair for tool calls whose arguments are not valid JSON
|
||||
* (truncated payloads, single quotes, unescaped newlines — common with
|
||||
* weaker models). Runs the raw argument text through the shared jsonrepair
|
||||
* strategies; unknown tool names and already-valid JSON are not repairable
|
||||
* here, and returning null preserves the AI SDK's original error behavior.
|
||||
*/
|
||||
export async function repairMalformedToolCall<T extends RepairableToolCall>({
|
||||
toolCall,
|
||||
error,
|
||||
}: {
|
||||
toolCall: T;
|
||||
error: unknown;
|
||||
}): Promise<T | null> {
|
||||
if (NoSuchToolError.isInstance(error)) {
|
||||
return null;
|
||||
}
|
||||
if (typeof toolCall.input !== "string" || toolCall.input.trim() === "") {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
JSON.parse(toolCall.input);
|
||||
// Valid JSON means the failure was a schema mismatch, not a parse
|
||||
// error. That is left to the tool executor's own lenient union
|
||||
// schemas; there is nothing to repair here.
|
||||
return null;
|
||||
} catch {
|
||||
// Not valid JSON — attempt repair below.
|
||||
}
|
||||
const repaired = parseJsonStream(toolCall.input);
|
||||
if (repaired === toolCall.input || typeof repaired === "string") {
|
||||
return null;
|
||||
}
|
||||
return { ...toolCall, input: JSON.stringify(repaired) };
|
||||
}
|
||||
|
||||
function normalizeAiSdkToolInputSchema(
|
||||
inputSchema: Record<string, unknown>,
|
||||
): Record<string, unknown> {
|
||||
@@ -1160,6 +1197,7 @@ function createAiSdkProvider(kind: ProviderModuleKind): GatewayProviderFactory {
|
||||
? { maxOutputTokens: request.maxTokens }
|
||||
: {}),
|
||||
abortSignal: request.signal,
|
||||
experimental_repairToolCall: repairMalformedToolCall as never,
|
||||
experimental_telemetry: {
|
||||
isEnabled: langfuse,
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@cline/sdk",
|
||||
"description": "Cline SDK - user-facing alias for @cline/core",
|
||||
"version": "0.0.55",
|
||||
"version": "0.0.58",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cline/cline",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@cline/shared",
|
||||
"version": "0.0.55",
|
||||
"version": "0.0.58",
|
||||
"description": "Shared utilities, types, and schemas for Cline packages",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -229,10 +229,12 @@ export { buildClineSystemPrompt } from "./prompt/cline";
|
||||
export {
|
||||
formatDisplayUserInput,
|
||||
formatFileContentBlock,
|
||||
formatModeSwitchNotice,
|
||||
formatUserCommandBlock,
|
||||
formatUserInputBlock,
|
||||
normalizeUserInput,
|
||||
parseUserCommandEnvelope,
|
||||
stripModeNotices,
|
||||
xmlTagsRemoval,
|
||||
} from "./prompt/format";
|
||||
export { isClineProvider } from "./providers/utils";
|
||||
|
||||
@@ -243,10 +243,13 @@ export { buildClineSystemPrompt, processWorkspaceInfo } from "./prompt/cline";
|
||||
export {
|
||||
formatDisplayUserInput,
|
||||
formatFileContentBlock,
|
||||
formatModeSwitchNotice,
|
||||
formatUserCommandBlock,
|
||||
formatUserInputBlock,
|
||||
normalizeUserInput,
|
||||
parseUserCommandEnvelope,
|
||||
parseUserInputMode,
|
||||
stripModeNotices,
|
||||
xmlTagsRemoval,
|
||||
} from "./prompt/format";
|
||||
export { isClineProvider } from "./providers/utils";
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
formatDisplayUserInput,
|
||||
formatModeSwitchNotice,
|
||||
formatUserCommandBlock,
|
||||
formatUserInputBlock,
|
||||
normalizeUserInput,
|
||||
parseUserCommandEnvelope,
|
||||
parseUserInputMode,
|
||||
stripModeNotices,
|
||||
} from "./format";
|
||||
|
||||
describe("prompt format helpers", () => {
|
||||
@@ -36,4 +40,71 @@ describe("prompt format helpers", () => {
|
||||
);
|
||||
expect(formatDisplayUserInput(wrapped)).toBe("/team inspect rpc startup");
|
||||
});
|
||||
|
||||
it("parses the mode attribute from a user_input wrapper", () => {
|
||||
expect(parseUserInputMode(formatUserInputBlock("hello", "plan"))).toBe(
|
||||
"plan",
|
||||
);
|
||||
expect(parseUserInputMode(formatUserInputBlock("hello", "act"))).toBe(
|
||||
"act",
|
||||
);
|
||||
});
|
||||
|
||||
it("parses the mode when a mode notice precedes the wrapper", () => {
|
||||
const input = `${formatModeSwitchNotice("act", "plan")}${formatUserInputBlock("hello", "plan")}`;
|
||||
expect(parseUserInputMode(input)).toBe("plan");
|
||||
});
|
||||
|
||||
it("returns undefined for unwrapped or unknown-mode input", () => {
|
||||
expect(parseUserInputMode("plain text")).toBeUndefined();
|
||||
expect(parseUserInputMode(undefined)).toBeUndefined();
|
||||
expect(
|
||||
parseUserInputMode('<user_input mode="warp">hello</user_input>'),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("formats a mode switch notice", () => {
|
||||
expect(formatModeSwitchNotice("plan", "act")).toBe(
|
||||
"<mode_notice>The user switched from plan mode to act mode before sending this message.</mode_notice>",
|
||||
);
|
||||
});
|
||||
|
||||
it("hides mode switch notices from displayed user input", () => {
|
||||
const wrapped = formatUserInputBlock(
|
||||
`${formatModeSwitchNotice("act", "plan")}\nhow should we refactor this?`,
|
||||
"plan",
|
||||
);
|
||||
expect(formatDisplayUserInput(wrapped)).toBe(
|
||||
"how should we refactor this?",
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps mode switch notices when normalizing outbound prompts", () => {
|
||||
// prepareTurnInput sanitizes prompts with normalizeUserInput before the
|
||||
// host wraps them; stripping notices here would delete the switch
|
||||
// signal before the model ever sees it.
|
||||
const prompt = `${formatModeSwitchNotice("plan", "act")}\ndo it`;
|
||||
expect(normalizeUserInput(prompt)).toBe(prompt);
|
||||
});
|
||||
|
||||
it("removes every mode notice and leaves unclosed ones intact", () => {
|
||||
expect(
|
||||
stripModeNotices(
|
||||
"<mode_notice>a</mode_notice>hello<mode_notice>b</mode_notice> there",
|
||||
),
|
||||
).toBe("hello there");
|
||||
expect(stripModeNotices("<mode_notice>dangling")).toBe(
|
||||
"<mode_notice>dangling",
|
||||
);
|
||||
});
|
||||
|
||||
it("strips adversarial repeated open tags in linear time", () => {
|
||||
// Regression guard for CodeQL js/polynomial-redos: many unmatched
|
||||
// opening tags must not trigger quadratic rescanning.
|
||||
const hostile = "<mode_notice>".repeat(50_000);
|
||||
const started = performance.now();
|
||||
const result = stripModeNotices(hostile);
|
||||
expect(performance.now() - started).toBeLessThan(1_000);
|
||||
expect(result).toBe(hostile);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,6 +13,38 @@ export function formatUserCommandBlock(input: string, slash: string): string {
|
||||
return `<user_command slash="${slash}">${input}</user_command>`;
|
||||
}
|
||||
|
||||
// Mirrors exactly what formatUserInputBlock writes (lowercase tag, lowercase
|
||||
// mode values), but searches rather than anchors: persisted user content can
|
||||
// carry prepended <mode_notice> elements or trailing attachment blocks
|
||||
// around the wrapper.
|
||||
const USER_INPUT_MODE_RE = /<user_input\b[^>]*\bmode="(act|plan|yolo)"/;
|
||||
|
||||
/**
|
||||
* Recovers the agent mode a persisted user message was sent in from its
|
||||
* <user_input mode="..."> wrapper. Returns undefined when the input isn't
|
||||
* wrapped (plain text, user_command envelopes, older transcripts).
|
||||
*/
|
||||
export function parseUserInputMode(
|
||||
input?: string,
|
||||
): "act" | "plan" | "yolo" | undefined {
|
||||
const match = USER_INPUT_MODE_RE.exec(input ?? "");
|
||||
return match ? (match[1] as "act" | "plan" | "yolo") : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the exact point in the conversation where the user switched between
|
||||
* plan and act modes. Prepended to the first user message sent after the
|
||||
* switch. It survives normalizeUserInput (so the outbound sanitize in
|
||||
* prepareTurnInput delivers it to the model) and is hidden from transcript
|
||||
* display by stripModeNotices at display boundaries.
|
||||
*/
|
||||
export function formatModeSwitchNotice(
|
||||
from: "act" | "plan",
|
||||
to: "act" | "plan",
|
||||
): string {
|
||||
return `<mode_notice>The user switched from ${from} mode to ${to} mode before sending this message.</mode_notice>`;
|
||||
}
|
||||
|
||||
export type UserCommandEnvelope = {
|
||||
slash: string;
|
||||
content: string;
|
||||
@@ -75,8 +107,39 @@ export function normalizeUserInput(input?: string): string {
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes runtime-generated <mode_notice> elements (content included): they
|
||||
* are not user-typed text and must not render as such. Deliberately NOT part
|
||||
* of normalizeUserInput -- that function also sanitizes outbound prompts
|
||||
* before the host wraps them (prepareTurnInput), and stripping there deletes
|
||||
* the notice before the model ever sees it.
|
||||
*/
|
||||
export function stripModeNotices(input?: string): string {
|
||||
if (!input?.trim()) return "";
|
||||
return removeTagElements(input, "mode_notice").trim();
|
||||
}
|
||||
|
||||
// indexOf-based rather than a regex: a lazy dot-all pattern re-scans to the
|
||||
// end of the string from every unmatched opening tag, which is polynomial on
|
||||
// adversarial transcript content (CodeQL js/polynomial-redos).
|
||||
function removeTagElements(input: string, tag: string): string {
|
||||
const open = `<${tag}>`;
|
||||
const close = `</${tag}>`;
|
||||
let result = input;
|
||||
let start = result.indexOf(open);
|
||||
while (start !== -1) {
|
||||
const end = result.indexOf(close, start + open.length);
|
||||
if (end === -1) {
|
||||
break;
|
||||
}
|
||||
result = result.slice(0, start) + result.slice(end + close.length);
|
||||
start = result.indexOf(open, start);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function formatDisplayUserInput(input?: string): string {
|
||||
const normalized = normalizeUserInput(input);
|
||||
const normalized = stripModeNotices(normalizeUserInput(input));
|
||||
const envelope = parseUserCommandEnvelope(input);
|
||||
if (!envelope) {
|
||||
return normalized;
|
||||
|
||||
Reference in New Issue
Block a user