Compare commits

...

4 commits

Author SHA1 Message Date
roomote-v0[bot]
a4e0697324
Merge c3f23c5eac into 2bb826039b 2026-04-21 02:44:03 +00:00
Chiranjeevisantosh Madugundi
2bb826039b
feat(chat): add previous checkpoint navigation controls and i18n (#12139)
Some checks are pending
Code QA Roo Code / check-translations (push) Waiting to run
Code QA Roo Code / knip (push) Waiting to run
Code QA Roo Code / compile (push) Waiting to run
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Waiting to run
Code QA Roo Code / platform-unit-test (windows-latest) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Nightly Publish / publish-nightly (push) Waiting to run
2026-04-20 16:12:10 -06:00
Chiranjeevisantosh Madugundi
3e202ebf5b
feat(vertex): add Claude Opus 4.7 support (#12135) 2026-04-20 11:42:10 -06:00
Roo Code
c3f23c5eac fix: show correct status for execute_command UI (Running vs Executed)
EXT-672: The execute_command UI now accurately shows the terminal state:
- Shows "Running" when a command is actively executing
- Shows "Executed" when the command has completed

Added "executed" translation key to all 18 locale files.
2026-01-28 17:28:09 +00:00
27 changed files with 307 additions and 16 deletions

View file

@ -374,6 +374,27 @@ export const vertexModels = {
},
],
},
"claude-opus-4-7": {
maxTokens: 8192,
contextWindow: 200_000, // Default 200K, extendable to 1M with beta flag 'context-1m-2025-08-07'
supportsImages: true,
supportsPromptCache: true,
inputPrice: 5.0, // $5 per million input tokens (≤200K context)
outputPrice: 25.0, // $25 per million output tokens (≤200K context)
cacheWritesPrice: 6.25, // $6.25 per million tokens
cacheReadsPrice: 0.5, // $0.50 per million tokens
supportsReasoningBudget: true,
// Tiered pricing for extended context (requires beta flag 'context-1m-2025-08-07')
tiers: [
{
contextWindow: 1_000_000, // 1M tokens with beta flag
inputPrice: 10.0, // $10 per million input tokens (>200K context)
outputPrice: 37.5, // $37.50 per million output tokens (>200K context)
cacheWritesPrice: 12.5, // $12.50 per million tokens (>200K context)
cacheReadsPrice: 1.0, // $1.00 per million tokens (>200K context)
},
],
},
"claude-opus-4-5@20251101": {
maxTokens: 8192,
contextWindow: 200_000,
@ -572,6 +593,7 @@ export const VERTEX_1M_CONTEXT_MODEL_IDS = [
"claude-sonnet-4-5@20250929",
"claude-sonnet-4-6",
"claude-opus-4-6",
"claude-opus-4-7",
] as const
export const VERTEX_REGIONS = [

View file

@ -914,6 +914,21 @@ describe("VertexHandler", () => {
expect(model.betas).toContain("context-1m-2025-08-07")
})
it("should enable 1M context for Claude Opus 4.7 when beta flag is set", () => {
const handler = new AnthropicVertexHandler({
apiModelId: "claude-opus-4-7",
vertexProjectId: "test-project",
vertexRegion: "us-central1",
vertex1MContext: true,
})
const model = handler.getModel()
expect(model.info.contextWindow).toBe(1_000_000)
expect(model.info.inputPrice).toBe(10.0)
expect(model.info.outputPrice).toBe(37.5)
expect(model.betas).toContain("context-1m-2025-08-07")
})
it("should not enable 1M context when flag is disabled", () => {
const handler = new AnthropicVertexHandler({
apiModelId: VERTEX_1M_CONTEXT_MODEL_IDS[0],

View file

@ -10,6 +10,24 @@ import { copyPaths, copyWasms, copyLocales, setupLocaleWatcher } from "@roo-code
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
async function removeDirWithRetries(dirPath, retries = 5, retryDelayMs = 200) {
for (let attempt = 0; attempt <= retries; attempt++) {
try {
await fs.promises.rm(dirPath, { recursive: true, force: true })
return
} catch (error) {
const isRetryable = error?.code === "ENOTEMPTY" || error?.code === "EBUSY" || error?.code === "EPERM"
const isLastAttempt = attempt === retries
if (!isRetryable || isLastAttempt) {
throw error
}
await new Promise((resolve) => globalThis.setTimeout(resolve, retryDelayMs * (attempt + 1)))
}
}
}
async function main() {
const name = "extension"
const production = process.argv.includes("--production")
@ -36,7 +54,7 @@ async function main() {
if (fs.existsSync(distDir)) {
console.log(`[${name}] Cleaning dist directory: ${distDir}`)
fs.rmSync(distDir, { recursive: true, force: true })
await removeDirWithRetries(distDir)
}
/**

View file

@ -124,6 +124,7 @@ interface ChatRowProps {
isFollowUpAutoApprovalPaused?: boolean
editable?: boolean
hasCheckpoint?: boolean
onJumpToPreviousCheckpoint?: () => void
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
@ -177,6 +178,7 @@ export const ChatRowContent = ({
onBatchFileResponse,
isFollowUpAnswered,
isFollowUpAutoApprovalPaused,
onJumpToPreviousCheckpoint,
}: ChatRowContentProps) => {
const { t, i18n } = useTranslation()
@ -283,7 +285,7 @@ export const ChatRowContent = ({
<TerminalSquare className="size-4" aria-label="Terminal icon" />
),
<span style={{ color: normalColor, fontWeight: "bold" }}>
{t("chat:commandExecution.running")}
{isCommandExecuting ? t("chat:commandExecution.running") : t("chat:commandExecution.executed")}
</span>,
]
case "use_mcp_server":
@ -1341,6 +1343,7 @@ export const ChatRowContent = ({
commitHash={message.text!}
currentHash={currentCheckpoint}
checkpoint={message.checkpoint}
onJumpToPreviousCheckpoint={onJumpToPreviousCheckpoint}
/>
)
case "condense_context":

View file

@ -1261,6 +1261,23 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
return result
}, [isCondensing, visibleMessages])
const checkpointIndices = useMemo(() => {
const indices: number[] = []
for (let i = 0; i < groupedMessages.length; i++) {
if (groupedMessages[i]?.say === "checkpoint_saved") {
indices.push(i)
}
}
return indices
}, [groupedMessages])
const hasLatestCheckpoint = checkpointIndices.length > 0
const checkpointJumpCursorRef = useRef<number | null>(null)
useEffect(() => {
checkpointJumpCursorRef.current = null
}, [task?.ts, checkpointIndices])
// Scroll lifecycle is managed by a dedicated hook to keep ChatView focused
// on message handling and UI orchestration.
const {
@ -1394,6 +1411,29 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
vscode.postMessage({ type: "cancelAutoApproval" })
}, [])
const handleScrollToBottomAndResetCheckpointCursor = useCallback(() => {
checkpointJumpCursorRef.current = null
handleScrollToBottomClick()
}, [handleScrollToBottomClick])
const handleScrollToLatestCheckpoint = useCallback(() => {
if (checkpointIndices.length === 0) {
return
}
const previousCursor = checkpointJumpCursorRef.current
const nextCursor = previousCursor === null ? checkpointIndices.length - 1 : Math.max(0, previousCursor - 1)
const nextCheckpointIndex = checkpointIndices[nextCursor]
checkpointJumpCursorRef.current = nextCursor
enterUserBrowsingHistory("keyboard-nav-up")
virtuosoRef.current?.scrollToIndex({
index: nextCheckpointIndex,
align: "center",
behavior: "smooth",
})
}, [checkpointIndices, enterUserBrowsingHistory])
const itemContent = useCallback(
(index: number, messageOrGroup: ClineMessage) => {
const hasCheckpoint = modifiedMessages.some((message) => message.say === "checkpoint_saved")
@ -1430,6 +1470,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
})()
}
hasCheckpoint={hasCheckpoint}
onJumpToPreviousCheckpoint={handleScrollToLatestCheckpoint}
/>
)
},
@ -1447,6 +1488,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
isFollowUpAutoApprovalPaused,
enableButtons,
primaryButtonText,
handleScrollToLatestCheckpoint,
],
)
@ -1641,14 +1683,27 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
showScrollToBottom ? "opacity-100" : enableButtons ? "opacity-100" : "opacity-50"
}`}>
{showScrollToBottom ? (
<StandardTooltip content={t("chat:scrollToBottom")}>
<Button
variant="secondary"
className="flex-[2]"
onClick={handleScrollToBottomClick}>
<span className="codicon codicon-chevron-down"></span>
</Button>
</StandardTooltip>
<>
<StandardTooltip content={t("chat:scrollToBottom")}>
<Button
variant="secondary"
className={hasLatestCheckpoint ? "flex-1 mr-[6px]" : "flex-[2]"}
onClick={handleScrollToBottomAndResetCheckpointCursor}>
<span className="codicon codicon-chevron-down"></span>
</Button>
</StandardTooltip>
{hasLatestCheckpoint && (
<StandardTooltip content={t("chat:scrollToLatestCheckpoint")}>
<Button
variant="secondary"
className="flex-1 ml-[6px]"
onClick={handleScrollToLatestCheckpoint}
aria-label={t("chat:scrollToLatestCheckpoint")}>
<span className="codicon codicon-history"></span>
</Button>
</StandardTooltip>
)}
</>
) : (
<>
{primaryButtonText && (

View file

@ -43,6 +43,11 @@ interface MockVirtuosoProps {
interface VirtuosoHarnessState {
scrollCalls: number
scrollToIndexArgs: Array<{
index: number | "LAST"
align?: "end" | "start" | "center"
behavior?: "auto" | "smooth"
}>
atBottomAfterCalls: number
signalDelayMs: number
emitFalseOnDataChange: boolean
@ -54,6 +59,7 @@ interface VirtuosoHarnessState {
const harness = vi.hoisted<VirtuosoHarnessState>(() => ({
scrollCalls: 0,
scrollToIndexArgs: [],
atBottomAfterCalls: Number.POSITIVE_INFINITY,
signalDelayMs: 20,
emitFalseOnDataChange: true,
@ -152,8 +158,9 @@ vi.mock("react-virtuoso", () => {
}
useImperativeHandle(ref, () => ({
scrollToIndex: () => {
scrollToIndex: (options) => {
harness.scrollCalls += 1
harness.scrollToIndexArgs.push(options)
const reachedBottom = harness.scrollCalls >= harness.atBottomAfterCalls
const timeoutId = window.setTimeout(() => {
atBottomRef.current?.(reachedBottom)
@ -215,6 +222,23 @@ const buildMessages = (baseTs: number): ClineMessage[] => [
{ type: "say", say: "text", ts: baseTs + 2, text: "row-2" },
]
const buildMessagesWithCheckpoint = (baseTs: number): ClineMessage[] => [
{ type: "say", say: "text", ts: baseTs, text: "task" },
{ type: "say", say: "text", ts: baseTs + 1, text: "row-1" },
{ type: "say", say: "checkpoint_saved", ts: baseTs + 2, text: "checkpoint-1" },
{ type: "say", say: "text", ts: baseTs + 3, text: "row-2" },
]
const buildMessagesWithMultipleCheckpoints = (baseTs: number): ClineMessage[] => [
{ type: "say", say: "text", ts: baseTs, text: "task" },
{ type: "say", say: "checkpoint_saved", ts: baseTs + 1, text: "checkpoint-1" },
{ type: "say", say: "text", ts: baseTs + 2, text: "row-2" },
{ type: "say", say: "checkpoint_saved", ts: baseTs + 3, text: "checkpoint-2" },
{ type: "say", say: "text", ts: baseTs + 4, text: "row-4" },
{ type: "say", say: "checkpoint_saved", ts: baseTs + 5, text: "checkpoint-3" },
{ type: "say", say: "text", ts: baseTs + 6, text: "row-6" },
]
const resolveFollowOutput = (isAtBottom: boolean): "auto" | false => {
const followOutput = harness.followOutput
if (typeof followOutput === "function") {
@ -254,19 +278,19 @@ const renderView = () =>
</ExtensionStateContextProvider>,
)
const hydrate = async (atBottomAfterCalls: number) => {
const hydrate = async (atBottomAfterCalls: number, clineMessages = buildMessages(Date.now() - 3_000)) => {
harness.atBottomAfterCalls = atBottomAfterCalls
renderView()
await act(async () => {
await Promise.resolve()
})
await act(async () => {
postState(buildMessages(Date.now() - 3_000))
postState(clineMessages)
})
await waitFor(() => {
const list = document.querySelector("[data-testid='virtuoso-item-list']")
expect(list).toBeTruthy()
expect(list?.getAttribute("data-count")).toBe("2")
expect(list?.getAttribute("data-count")).toBe(String(Math.max(0, clineMessages.length - 1)))
})
}
@ -317,9 +341,19 @@ const getScrollToBottomButton = (): HTMLButtonElement => {
return button
}
const getScrollToCheckpointButton = (): HTMLButtonElement => {
const button = document.querySelector("button[aria-label='chat:scrollToLatestCheckpoint']")
if (!(button instanceof HTMLButtonElement)) {
throw new Error("Expected scroll-to-checkpoint button")
}
return button
}
describe("ChatView scroll behavior regression coverage", () => {
beforeEach(() => {
harness.scrollCalls = 0
harness.scrollToIndexArgs = []
harness.atBottomAfterCalls = Number.POSITIVE_INFINITY
harness.signalDelayMs = 20
harness.emitFalseOnDataChange = true
@ -503,4 +537,71 @@ describe("ChatView scroll behavior regression coverage", () => {
})
await waitFor(() => expect(document.querySelector(".codicon-chevron-down")).toBeNull(), { timeout: 1_200 })
})
it("shows jump-to-checkpoint button and scrolls to latest checkpoint", async () => {
await hydrate(2, buildMessagesWithCheckpoint(Date.now() - 3_000))
await waitForCalls(2)
await waitForCallsSettled()
await act(async () => {
fireEvent.keyDown(window, { key: "PageUp" })
})
await waitFor(() => expect(document.querySelector(".codicon-chevron-down")).toBeTruthy(), {
timeout: 1_200,
})
const checkpointButton = document.querySelector("button[aria-label='chat:scrollToLatestCheckpoint']")
expect(checkpointButton).toBeInstanceOf(HTMLButtonElement)
const callsBeforeClick = harness.scrollCalls
await act(async () => {
;(checkpointButton as HTMLButtonElement).click()
})
expect(harness.scrollCalls).toBe(callsBeforeClick + 1)
expect(harness.scrollToIndexArgs.at(-1)).toMatchObject({
index: 1,
align: "center",
behavior: "smooth",
})
})
it("repeated checkpoint clicks step backward through previous checkpoints", async () => {
await hydrate(2, buildMessagesWithMultipleCheckpoints(Date.now() - 3_000))
await waitForCalls(2)
await waitForCallsSettled()
await act(async () => {
fireEvent.keyDown(window, { key: "PageUp" })
})
await waitFor(() => expect(document.querySelector(".codicon-chevron-down")).toBeTruthy(), {
timeout: 1_200,
})
const checkpointButton = getScrollToCheckpointButton()
await act(async () => {
;(checkpointButton as HTMLButtonElement).click()
})
expect(harness.scrollToIndexArgs.at(-1)).toMatchObject({ index: 4, align: "center", behavior: "smooth" })
await act(async () => {
;(checkpointButton as HTMLButtonElement).click()
})
expect(harness.scrollToIndexArgs.at(-1)).toMatchObject({ index: 2, align: "center", behavior: "smooth" })
await act(async () => {
;(checkpointButton as HTMLButtonElement).click()
})
expect(harness.scrollToIndexArgs.at(-1)).toMatchObject({ index: 0, align: "center", behavior: "smooth" })
// Once at the oldest checkpoint, additional clicks keep targeting it.
await act(async () => {
;(checkpointButton as HTMLButtonElement).click()
})
expect(harness.scrollToIndexArgs.at(-1)).toMatchObject({ index: 0, align: "center", behavior: "smooth" })
})
})

View file

@ -12,6 +12,7 @@ type CheckpointMenuBaseProps = {
ts: number
commitHash: string
checkpoint: Checkpoint
onJumpToPreviousCheckpoint?: () => void
}
type CheckpointMenuControlledProps = {
onOpenChange: (open: boolean) => void
@ -21,7 +22,13 @@ type CheckpointMenuUncontrolledProps = {
}
type CheckpointMenuProps = CheckpointMenuBaseProps & (CheckpointMenuControlledProps | CheckpointMenuUncontrolledProps)
export const CheckpointMenu = ({ ts, commitHash, checkpoint, onOpenChange }: CheckpointMenuProps) => {
export const CheckpointMenu = ({
ts,
commitHash,
checkpoint,
onOpenChange,
onJumpToPreviousCheckpoint,
}: CheckpointMenuProps) => {
const { t } = useTranslation()
const [internalRestoreOpen, setInternalRestoreOpen] = useState(false)
const [restoreConfirming, setRestoreConfirming] = useState(false)
@ -165,6 +172,16 @@ export const CheckpointMenu = ({ ts, commitHash, checkpoint, onOpenChange }: Che
</div>
</PopoverContent>
</Popover>
<StandardTooltip content={t("chat:scrollToLatestCheckpoint")}>
<Button
variant="ghost"
size="icon"
onClick={onJumpToPreviousCheckpoint}
data-testid="jump-previous-checkpoint-btn"
aria-label={t("chat:scrollToLatestCheckpoint")}>
<span className="codicon codicon-chevron-up" />
</Button>
</StandardTooltip>
<Popover open={moreOpen} onOpenChange={(open) => setMoreOpen(open)} data-testid="more-popover">
<StandardTooltip content={t("chat:task.seeMore")}>
<PopoverTrigger asChild>

View file

@ -11,9 +11,15 @@ type CheckpointSavedProps = {
commitHash: string
currentHash?: string
checkpoint?: Record<string, unknown>
onJumpToPreviousCheckpoint?: () => void
}
export const CheckpointSaved = ({ checkpoint, currentHash, ...props }: CheckpointSavedProps) => {
export const CheckpointSaved = ({
checkpoint,
currentHash,
onJumpToPreviousCheckpoint,
...props
}: CheckpointSavedProps) => {
const { t } = useTranslation()
const isCurrent = currentHash === props.commitHash
const [isPopoverOpen, setIsPopoverOpen] = useState(false)
@ -100,6 +106,7 @@ export const CheckpointSaved = ({ checkpoint, currentHash, ...props }: Checkpoin
commitHash={props.commitHash}
checkpoint={metadata}
onOpenChange={handlePopoverOpenChange}
onJumpToPreviousCheckpoint={onJumpToPreviousCheckpoint}
/>
</div>
</div>

View file

@ -185,4 +185,21 @@ describe("CheckpointSaved popover visibility", () => {
expect(getMenu().className).toContain("hidden")
})
})
it("renders jump-to-previous-checkpoint control and triggers callback", async () => {
const onJumpToPreviousCheckpoint = vi.fn()
const { getByTestId, container } = render(
<CheckpointSaved {...baseProps} onJumpToPreviousCheckpoint={onJumpToPreviousCheckpoint} />,
)
const getParentDiv = () =>
container.querySelector("[class*='flex items-center justify-between']") as HTMLElement
fireEvent.mouseEnter(getParentDiv())
const jumpButton = await waitFor(() => getByTestId("jump-previous-checkpoint-btn"))
await userEvent.click(jumpButton)
expect(onJumpToPreviousCheckpoint).toHaveBeenCalledTimes(1)
})
})

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Afegeix el missatge a la cua (s'enviarà quan acabi la tasca actual)",
"scrollToBottom": "Desplaça't al final del xat",
"scrollToLatestCheckpoint": "Desplaça't al checkpoint anterior",
"about": "Roo Code és tot un equip de desenvolupament d'IA al teu editor.",
"docs": "Consulta els nostres <DocsLink>documents</DocsLink> per a més informació.",
"onboarding": "La teva llista de tasques en aquest espai de treball està buida.",
@ -228,6 +229,7 @@
"commandExecution": {
"abort": "Avortar",
"running": "En execució",
"executed": "Executat",
"pid": "PID: {{pid}}",
"exitStatus": "S'ha sortit amb l'estat {{exitCode}}",
"manageCommands": "Comandes aprovades automàticament",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Nachricht zur Warteschlange hinzufügen (wird nach Abschluss der aktuellen Aufgabe gesendet)",
"scrollToBottom": "Zum Chat-Ende scrollen",
"scrollToLatestCheckpoint": "Zum vorherigen Checkpoint scrollen",
"about": "Roo Code ist ein ganzes KI-Entwicklerteam in deinem Editor.",
"docs": "Schau in unsere <DocsLink>Dokumentation</DocsLink>, um mehr zu erfahren.",
"onboarding": "Deine Aufgabenliste in diesem Arbeitsbereich ist leer.",
@ -228,6 +229,7 @@
"commandExecution": {
"abort": "Abbrechen",
"running": "Wird ausgeführt",
"executed": "Ausgeführt",
"pid": "PID: {{pid}}",
"exitStatus": "Beendet mit Status {{exitCode}}",
"manageCommands": "Automatisch genehmigte Befehle",

View file

@ -124,6 +124,7 @@
"placeholder": "Edit your message..."
},
"scrollToBottom": "Scroll to bottom of chat",
"scrollToLatestCheckpoint": "Scroll to previous checkpoint",
"about": "Roo is a whole AI dev team in your editor",
"docs": "Check our <DocsLink>docs</DocsLink> to get started",
"onboarding": "What would you like to do?",
@ -271,6 +272,7 @@
"commandExecution": {
"abort": "Abort",
"running": "Running",
"executed": "Executed",
"pid": "PID: {{pid}}",
"exitStatus": "Exited with status {{exitCode}}",
"manageCommands": "Auto-approved commands",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Agregar mensaje a la cola (se enviará después de que termine la tarea actual)",
"scrollToBottom": "Desplazarse al final del chat",
"scrollToLatestCheckpoint": "Desplazarse al checkpoint anterior",
"about": "Roo Code es todo un equipo de desarrollo de IA en tu editor.",
"docs": "Consulta nuestra <DocsLink>documentación</DocsLink> para saber más.",
"onboarding": "Tu lista de tareas en este espacio de trabajo está vacía.",
@ -228,6 +229,7 @@
"commandExecution": {
"abort": "Abortar",
"running": "Ejecutando",
"executed": "Ejecutado",
"pid": "PID: {{pid}}",
"exitStatus": "Salió con el estado {{exitCode}}",
"manageCommands": "Comandos aprobados automáticamente",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Ajouter le message à la file d'attente (sera envoyé après la fin de la tâche en cours)",
"scrollToBottom": "Défiler jusqu'au bas du chat",
"scrollToLatestCheckpoint": "Défiler jusqu'au checkpoint précédent",
"about": "Roo Code est une équipe complète de développeurs IA dans votre éditeur.",
"docs": "Consultez notre <DocsLink>documentation</DocsLink> pour en savoir plus.",
"onboarding": "Votre liste de tâches dans cet espace de travail est vide.",
@ -228,6 +229,7 @@
"commandExecution": {
"abort": "Abandonner",
"running": "En cours d'exécution",
"executed": "Exécuté",
"pid": "PID : {{pid}}",
"exitStatus": "Terminé avec le statut {{exitCode}}",
"manageCommands": "Commandes approuvées automatiquement",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "संदेश को कतार में जोड़ें (वर्तमान कार्य पूरा होने के बाद भेजा जाएगा)",
"scrollToBottom": "चैट के निचले हिस्से तक स्क्रॉल करें",
"scrollToLatestCheckpoint": "पिछले चेकपॉइंट तक स्क्रॉल करें",
"about": "Roo Code आपके संपादक में एक पूरी AI देव टीम है।",
"docs": "और जानने के लिए हमारे <DocsLink>दस्तावेज़</DocsLink> देखें।",
"onboarding": "इस कार्यक्षेत्र में आपकी कार्य सूची खाली है।",
@ -228,6 +229,7 @@
"commandExecution": {
"abort": "रद्द करें",
"running": "चल रहा है",
"executed": "निष्पादित",
"pid": "पीआईडी: {{pid}}",
"exitStatus": "{{exitCode}} स्थिति के साथ बाहर निकल गया",
"manageCommands": "स्वतः-अनुमोदित कमांड",

View file

@ -127,6 +127,7 @@
},
"enqueueMessage": "Tambahkan pesan ke antrean (akan dikirim setelah tugas saat ini selesai)",
"scrollToBottom": "Gulir ke bawah chat",
"scrollToLatestCheckpoint": "Gulir ke checkpoint sebelumnya",
"about": "Roo Code adalah seluruh tim pengembang AI di editor Anda.",
"docs": "Lihat <DocsLink>dokumentasi</DocsLink> kami untuk mempelajari lebih lanjut.",
"onboarding": "Daftar tugas Anda di ruang kerja ini kosong.",
@ -279,6 +280,7 @@
"commandExecution": {
"abort": "Batalkan",
"running": "Menjalankan",
"executed": "Dijalankan",
"pid": "PID: {{pid}}",
"exitStatus": "Keluar dengan status {{exitCode}}",
"manageCommands": "Perintah yang disetujui secara otomatis",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Aggiungi il messaggio alla coda (sarà inviato dopo che l'attività corrente sarà terminata)",
"scrollToBottom": "Scorri fino alla fine della chat",
"scrollToLatestCheckpoint": "Scorri al checkpoint precedente",
"about": "Roo Code è un intero team di sviluppo AI nel tuo editor.",
"docs": "Consulta la nostra <DocsLink>documentazione</DocsLink> per saperne di più.",
"onboarding": "La tua lista di attività in questo spazio di lavoro è vuota.",
@ -228,6 +229,7 @@
"commandExecution": {
"abort": "Interrompi",
"running": "In esecuzione",
"executed": "Eseguito",
"pid": "PID: {{pid}}",
"exitStatus": "Uscito con stato {{exitCode}}",
"manageCommands": "Comandi approvati automaticamente",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "メッセージをキューに追加(現在のタスク完了後に送信されます)",
"scrollToBottom": "チャットの最下部にスクロール",
"scrollToLatestCheckpoint": "前のチェックポイントまでスクロール",
"about": "Roo Codeは、エディタに常駐するAI開発チームです。",
"docs": "詳細については、<DocsLink>ドキュメント</DocsLink>をご確認ください。",
"onboarding": "このワークスペースのタスクリストは空です。",
@ -228,6 +229,7 @@
"commandExecution": {
"abort": "中止",
"running": "実行中",
"executed": "実行済み",
"pid": "PID: {{pid}}",
"exitStatus": "ステータス {{exitCode}} で終了しました",
"manageCommands": "自動承認されたコマンド",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "메시지를 대기열에 추가 (현재 작업 완료 후 전송)",
"scrollToBottom": "채팅 하단으로 스크롤",
"scrollToLatestCheckpoint": "이전 체크포인트로 스크롤",
"about": "Roo Code는 편집기 안에 있는 전체 AI 개발팀입니다.",
"docs": "더 알아보려면 <DocsLink>문서</DocsLink>를 확인하세요.",
"onboarding": "이 작업 공간의 작업 목록이 비어 있습니다.",
@ -228,6 +229,7 @@
"commandExecution": {
"abort": "중단",
"running": "실행 중",
"executed": "실행됨",
"pid": "PID: {{pid}}",
"exitStatus": "상태 {{exitCode}}(으)로 종료됨",
"manageCommands": "자동 승인된 명령",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Bericht aan de wachtrij toevoegen (wordt verzonden nadat de huidige taak is voltooid)",
"scrollToBottom": "Scroll naar onderaan de chat",
"scrollToLatestCheckpoint": "Scroll naar het vorige checkpoint",
"about": "Roo Code is een heel AI-ontwikkelteam in je editor.",
"docs": "Bekijk onze <DocsLink>documentatie</DocsLink> voor meer informatie.",
"onboarding": "Je takenlijst in deze werkruimte is leeg.",
@ -222,6 +223,7 @@
"commandOutput": "Commando-uitvoer",
"commandExecution": {
"running": "Lopend",
"executed": "Uitgevoerd",
"abort": "Afbreken",
"pid": "PID: {{pid}}",
"exitStatus": "Afgesloten met status {{exitCode}}",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Dodaj wiadomość do kolejki (zostanie wysłana po zakończeniu bieżącego zadania)",
"scrollToBottom": "Przewiń do dołu czatu",
"scrollToLatestCheckpoint": "Przewiń do poprzedniego punktu kontrolnego",
"about": "Roo Code to cały zespół deweloperów AI w Twoim edytorze.",
"docs": "Sprawdź naszą <DocsLink>dokumentację</DocsLink>, aby dowiedzieć się więcej.",
"onboarding": "Twoja lista zadań w tym obszarze roboczym jest pusta.",
@ -227,6 +228,7 @@
"commandOutput": "Wyjście polecenia",
"commandExecution": {
"running": "Wykonywanie",
"executed": "Wykonano",
"abort": "Przerwij",
"pid": "PID: {{pid}}",
"exitStatus": "Zakończono ze statusem {{exitCode}}",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Adicionar mensagem à fila (será enviada após a conclusão da tarefa atual)",
"scrollToBottom": "Rolar para o final do chat",
"scrollToLatestCheckpoint": "Rolar para o checkpoint anterior",
"about": "Roo Code é uma equipe inteira de desenvolvimento de IA em seu editor.",
"docs": "Confira nossa <DocsLink>documentação</DocsLink> para saber mais.",
"onboarding": "Sua lista de tarefas neste espaço de trabalho está vazia.",
@ -227,6 +228,7 @@
"commandOutput": "Saída do comando",
"commandExecution": {
"running": "Executando",
"executed": "Executado",
"abort": "Interromper",
"pid": "PID: {{pid}}",
"exitStatus": "Saiu com o status {{exitCode}}",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Добавить сообщение в очередь (будет отправлено после завершения текущей задачи)",
"scrollToBottom": "Прокрутить чат вниз",
"scrollToLatestCheckpoint": "Прокрутить к предыдущему чекпоинту",
"about": "Roo Code — это целая команда разработчиков ИИ в вашем редакторе.",
"docs": "Ознакомьтесь с нашей <DocsLink>документацией</DocsLink>, чтобы узнать больше.",
"onboarding": "Ваш список задач в этом рабочем пространстве пуст.",
@ -222,6 +223,7 @@
"commandOutput": "Вывод команды",
"commandExecution": {
"running": "Выполняется",
"executed": "Выполнено",
"abort": "Прервать",
"pid": "PID: {{pid}}",
"exitStatus": "Завершено со статусом {{exitCode}}",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Mesajı kuyruğa ekle (mevcut görev tamamlandıktan sonra gönderilecek)",
"scrollToBottom": "Sohbetin altına kaydır",
"scrollToLatestCheckpoint": "Önceki checkpoint'e kaydır",
"about": "Roo Code, düzenleyicinizdeki bütün bir yapay zeka geliştirme ekibidir.",
"docs": "Daha fazla bilgi için <DocsLink>belgelerimize</DocsLink> göz atın.",
"onboarding": "Bu çalışma alanındaki görev listeniz boş.",
@ -227,6 +228,7 @@
"commandOutput": "Komut Çıktısı",
"commandExecution": {
"running": "Çalışıyor",
"executed": "Yürütüldü",
"abort": "İptal Et",
"pid": "PID: {{pid}}",
"exitStatus": "{{exitCode}} durumuyla çıkıldı",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "Thêm tin nhắn vào hàng đợi (sẽ gửi sau khi nhiệm vụ hiện tại hoàn tất)",
"scrollToBottom": "Cuộn xuống cuối cuộc trò chuyện",
"scrollToLatestCheckpoint": "Cuộn đến checkpoint trước đó",
"about": "Roo Code là một đội ngũ phát triển AI đầy đủ trong trình chỉnh sửa của bạn.",
"docs": "Kiểm tra <DocsLink>tài liệu</DocsLink> của chúng tôi để tìm hiểu thêm.",
"onboarding": "Danh sách nhiệm vụ của bạn trong không gian làm việc này đang trống.",
@ -227,6 +228,7 @@
"commandOutput": "Kết quả lệnh",
"commandExecution": {
"running": "Đang chạy",
"executed": "Đã thực thi",
"abort": "Hủy bỏ",
"pid": "PID: {{pid}}",
"exitStatus": "Đã thoát với trạng thái {{exitCode}}",

View file

@ -97,6 +97,7 @@
},
"enqueueMessage": "将消息加入队列(当前任务完成后发送)",
"scrollToBottom": "滚动到聊天底部",
"scrollToLatestCheckpoint": "滚动到上一个检查点",
"about": "Roo Code 是您编辑器中的整个 AI 开发团队。",
"docs": "查看我们的 <DocsLink>文档</DocsLink> 了解更多信息。",
"onboarding": "此工作区中的任务列表为空。",
@ -227,6 +228,7 @@
"commandOutput": "命令输出",
"commandExecution": {
"running": "正在运行",
"executed": "已执行",
"abort": "中止",
"pid": "PID: {{pid}}",
"exitStatus": "已退出,状态码 {{exitCode}}",

View file

@ -124,6 +124,7 @@
"placeholder": "編輯訊息..."
},
"scrollToBottom": "捲動至對話底部",
"scrollToLatestCheckpoint": "捲動至上一個檢查點",
"about": "Roo 是編輯器中的完整 AI 開發團隊。",
"docs": "請參閱 <DocsLink>說明文件</DocsLink> 開始使用。",
"onboarding": "想要做什麼呢?",
@ -274,6 +275,7 @@
"commandExecution": {
"abort": "中止",
"running": "執行中",
"executed": "已執行",
"pid": "PID: {{pid}}",
"exitStatus": "已結束,狀態碼 {{exitCode}}",
"manageCommands": "自動核准的命令",