diff --git a/mobile/src/session/mobile-structured-operation-id-retirement.test.ts b/mobile/src/session/mobile-structured-operation-id-retirement.test.ts index 6ca27074568..03181db4100 100644 --- a/mobile/src/session/mobile-structured-operation-id-retirement.test.ts +++ b/mobile/src/session/mobile-structured-operation-id-retirement.test.ts @@ -297,7 +297,8 @@ describe('what a structured refusal says on the phone', () => { expect(result).toEqual({ status: 'failed', - message: "The Orca running this chat doesn't support this. Update Orca, then try again." + message: + 'This needs a newer Orca on the computer running this chat. Update Orca there, then try again.' }) }) }) diff --git a/src/main/native-chat/agent-session-journal/journal-corruption-repair.test.ts b/src/main/native-chat/agent-session-journal/journal-corruption-repair.test.ts index a5e7506d1bd..8c4db243aa7 100644 --- a/src/main/native-chat/agent-session-journal/journal-corruption-repair.test.ts +++ b/src/main/native-chat/agent-session-journal/journal-corruption-repair.test.ts @@ -146,10 +146,12 @@ describe('a malformed row', () => { .snapshot() .items.map((entry) => entry.body) .find((entry) => entry.kind === 'status') - expect(disclosure).toMatchObject({ kind: 'status' }) - expect(disclosure && 'text' in disclosure ? disclosure.text : '').toContain( - '1 journal line could not be read' - ) + // Named for the client to word, with English for a client that can't. + expect(disclosure).toEqual({ + kind: 'status', + text: "Part of this chat's history couldn't be loaded.", + presentation: 'history-repaired' + }) }) }) diff --git a/src/main/native-chat/agent-session-journal/journal-repair-disclosure.ts b/src/main/native-chat/agent-session-journal/journal-repair-disclosure.ts index fee5edf142b..83846333300 100644 --- a/src/main/native-chat/agent-session-journal/journal-repair-disclosure.ts +++ b/src/main/native-chat/agent-session-journal/journal-repair-disclosure.ts @@ -4,8 +4,12 @@ // nothing but its anchor and this row is a repair that has not been // reconstructed yet, not a timeline. +import { agentSessionHostStatusBody } from '../../../shared/agent-session-host-status-rows' import { agentJournalItemKey } from '../../../shared/agent-session-journal-item-key' -import type { AgentJournalItemIdentity } from '../../../shared/agent-session-journal-types' +import type { + AgentJournalItemIdentity, + AgentJournalPlainStatusItem +} from '../../../shared/agent-session-journal-types' /** One stable identity, so a reopen upserts the same row instead of adding one. */ export const JOURNAL_REPAIR_DISCLOSURE_IDENTITY: AgentJournalItemIdentity = { @@ -19,14 +23,13 @@ export const JOURNAL_REPAIR_DISCLOSURE_ITEM_ID = agentJournalItemKey( export type JournalRepairDisclosure = { identity: AgentJournalItemIdentity - body: { kind: 'status'; text: string } + body: AgentJournalPlainStatusItem } /** Disclosed when a repair skipped a row it could not read. */ -export function journalRepairDisclosure(input: { malformedRows: number }): JournalRepairDisclosure { - const lines = `${input.malformedRows} journal line${input.malformedRows === 1 ? '' : 's'}` +export function journalRepairDisclosure(): JournalRepairDisclosure { return { identity: JOURNAL_REPAIR_DISCLOSURE_IDENTITY, - body: { kind: 'status', text: `${lines} could not be read` } + body: agentSessionHostStatusBody('history-repaired') } } diff --git a/src/main/native-chat/agent-session-journal/journal-store-open.ts b/src/main/native-chat/agent-session-journal/journal-store-open.ts index a7163860be9..c8674e0dbd5 100644 --- a/src/main/native-chat/agent-session-journal/journal-store-open.ts +++ b/src/main/native-chat/agent-session-journal/journal-store-open.ts @@ -66,7 +66,7 @@ export async function openJournalStoreState(input: { input.setMalformedRows(loaded.malformedRows) } if (input.malformedRows() > 0 && !input.readOnly()) { - const disclosure = journalRepairDisclosure({ malformedRows: input.malformedRows() }) + const disclosure = journalRepairDisclosure() await input.appendItem(disclosure.identity, disclosure.body, input.highestFence()) } await settleStaleSubagentRosters(input, loaded) diff --git a/src/main/native-chat/agent-session-journal/journal-store-schema.test.ts b/src/main/native-chat/agent-session-journal/journal-store-schema.test.ts index da6ffc84feb..d7c5e521c82 100644 --- a/src/main/native-chat/agent-session-journal/journal-store-schema.test.ts +++ b/src/main/native-chat/agent-session-journal/journal-store-schema.test.ts @@ -18,6 +18,7 @@ import type { } from '../../../shared/agent-session-journal-types' import type Database from '../../sqlite/sync-database' import { JOURNAL_DB_SCHEMA_VERSION } from './journal-database-schema' +import { journalRepairDisclosure } from './journal-repair-disclosure' import { journalDatabasePath } from './journal-host-database' import type { AgentSessionJournal } from './journal-store' import { @@ -109,6 +110,7 @@ afterEach(async () => { await rm(root, { recursive: true, force: true }) }) +const REPAIR_TEXT = journalRepairDisclosure().body.text describe('axis 1: the database shape', () => { // A newer build's database opens read-only: its chats read, and nothing here writes to it. it('reads a database a newer build stamped, refuses every write, and writes nothing', async () => { @@ -242,9 +244,7 @@ describe('axis 2: the row body shape', () => { expect(items.some((entry) => entry.body.kind === 'message')).toBe(true) // …and the skip is visible in the timeline instead of silently swallowed. expect( - items.some( - (entry) => entry.body.kind === 'status' && entry.body.text.includes('could not be read') - ) + items.some((entry) => entry.body.kind === 'status' && entry.body.text === REPAIR_TEXT) ).toBe(true) }) @@ -264,9 +264,7 @@ describe('axis 2: the row body shape', () => { expect( reopened .snapshot() - .items.filter( - (entry) => entry.body.kind === 'status' && entry.body.text.includes('could not be read') - ) + .items.filter((entry) => entry.body.kind === 'status' && entry.body.text === REPAIR_TEXT) ).toHaveLength(1) }) diff --git a/src/main/native-chat/agent-session-wire/agent-session-history-page-bounds.ts b/src/main/native-chat/agent-session-wire/agent-session-history-page-bounds.ts index f305b9cc149..3e1c574f9cd 100644 --- a/src/main/native-chat/agent-session-wire/agent-session-history-page-bounds.ts +++ b/src/main/native-chat/agent-session-wire/agent-session-history-page-bounds.ts @@ -7,6 +7,7 @@ import type { AgentJournalSubmission } from '../../../shared/agent-session-journal-types' import { REMOTE_RUNTIME_MAX_OUTBOUND_JSON_BYTES } from '../../../shared/remote-runtime-memory-limits' +import { agentSessionHostStatusBody } from '../../../shared/agent-session-host-status-rows' export const AGENT_SESSION_HISTORY_MAX_PAGE_BYTES = REMOTE_RUNTIME_MAX_OUTBOUND_JSON_BYTES / 2 @@ -46,17 +47,11 @@ export function submissionBytesByItemId( return bytes } -export function oversizedHistoryItem( - item: AgentJournalRenderItem, - byteLength: number -): AgentJournalRenderItem { +export function oversizedHistoryItem(item: AgentJournalRenderItem): AgentJournalRenderItem { return { ...item, itemId: boundJournalKeyComponent(item.itemId), - body: { - kind: 'status', - text: `[Orca: item truncated — ${byteLength} bytes exceeds the history page budget]` - } + body: agentSessionHostStatusBody('history-item-too-large') } } @@ -72,7 +67,7 @@ export function boundHistoryItemsByBytes( for (const group of ordered) { const bytes = group.reduce((sum, item) => sum + historyEntryBytes(item, submissionBytes), 0) if (kept.length === 0 && bytes > maxBytes) { - kept.push(group.map((item) => oversizedHistoryItem(item, bytes))) + kept.push(group.map((item) => oversizedHistoryItem(item))) break } if (total + bytes > maxBytes) { diff --git a/src/main/native-chat/agent-session-wire/agent-session-history-page-grouping-parity.test.ts b/src/main/native-chat/agent-session-wire/agent-session-history-page-grouping-parity.test.ts index 677e75edc7d..995c38a08b2 100644 --- a/src/main/native-chat/agent-session-wire/agent-session-history-page-grouping-parity.test.ts +++ b/src/main/native-chat/agent-session-wire/agent-session-history-page-grouping-parity.test.ts @@ -50,7 +50,7 @@ function referenceBoundHistoryItemsByBytes( for (const group of ordered) { const bytes = group.reduce((sum, item) => sum + historyEntryBytes(item, submissionBytes), 0) if (kept.length === 0 && bytes > maxBytes) { - kept.push(group.map((item) => oversizedHistoryItem(item, bytes))) + kept.push(group.map((item) => oversizedHistoryItem(item))) break } if (total + bytes > maxBytes) { @@ -153,7 +153,9 @@ it('matches eager byte bounding at every budget boundary in both directions', () ).toEqual(expected) if ( actual.items.some( - (entry) => entry.body.kind === 'status' && /truncated/.test(entry.body.text) + (entry) => + entry.body.kind === 'status' && + entry.body.presentation === 'history-item-too-large' ) ) { truncatedCases += 1 diff --git a/src/main/native-chat/agent-session-wire/agent-session-history-page.test.ts b/src/main/native-chat/agent-session-wire/agent-session-history-page.test.ts index ea6f44edb28..e40ebcf326e 100644 --- a/src/main/native-chat/agent-session-wire/agent-session-history-page.test.ts +++ b/src/main/native-chat/agent-session-wire/agent-session-history-page.test.ts @@ -319,9 +319,12 @@ describe('history page byte ceiling', () => { readAgentSessionHistory(journal, { sessionId: 'session-1', direction: 'tail', limit: 40 }) ) expect(tail.items).toHaveLength(1) - const bodyOnPage = tail.items[0]?.body - expect(bodyOnPage?.kind).toBe('status') - expect(bodyOnPage?.kind === 'status' ? bodyOnPage.text : '').toContain('[Orca: item truncated') + // Named for the client to word, with English for a client that can't. + expect(tail.items[0]?.body).toEqual({ + kind: 'status', + text: 'This part of the chat was too large to show.', + presentation: 'history-item-too-large' + }) }) }) diff --git a/src/main/native-chat/agent-session-wire/agent-session-history-page.ts b/src/main/native-chat/agent-session-wire/agent-session-history-page.ts index 1fd376e2aae..b780e3d1154 100644 --- a/src/main/native-chat/agent-session-wire/agent-session-history-page.ts +++ b/src/main/native-chat/agent-session-wire/agent-session-history-page.ts @@ -248,7 +248,7 @@ function readForward( if (contentBytes > HISTORY_PAGE_CONTENT_BUDGET_BYTES) { items = items.map((item) => { const bytes = historyEntryBytes(item, submissionBytes) - return bytes > HISTORY_PAGE_CONTENT_BUDGET_BYTES ? oversizedHistoryItem(item, bytes) : item + return bytes > HISTORY_PAGE_CONTENT_BUDGET_BYTES ? oversizedHistoryItem(item) : item }) contentBytes = pageContentBytes(items, projected.batch.removedItemIds) } diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-claude-unproven-stop-send.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-claude-unproven-stop-send.test.ts index d318e962a12..65dcfa42073 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-claude-unproven-stop-send.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-claude-unproven-stop-send.test.ts @@ -280,7 +280,7 @@ it('holds the message with its reason while the exit stays unverifiable, and sen { kind: 'status', tone: 'warning', - text: "Orca couldn't confirm Claude's previous process ended. Messages wait to be sent until Orca confirms it has ended.", + text: 'Claude from before may still be running. Your messages will send once it stops.', failure: { kind: 'previousExitUnverifiable' } } ]) diff --git a/src/renderer/src/components/agent-child-row-text.ts b/src/renderer/src/components/agent-child-row-text.ts index 96ef7d1d5c7..b48cff3dbd8 100644 --- a/src/renderer/src/components/agent-child-row-text.ts +++ b/src/renderer/src/components/agent-child-row-text.ts @@ -1,7 +1,10 @@ import type { AgentChildRowModel } from '../../../shared/agent-child-row-model' import { formatAgentTypeLabel } from '../../../shared/agent-type-label' import { agentStateLabel } from '@/components/AgentStateDot' -import { backgroundTaskStateReason } from '@/components/native-chat/background-task-roster' +import { + backgroundTaskStateReason, + backgroundTaskStateWord +} from '@/components/native-chat/background-task-roster' import { translate } from '@/i18n/i18n' import { agentNoUpdateLabel } from '@/lib/agent-row-decay-state' import { formatAgentToolPreview } from '@/lib/agent-row-tool-preview' @@ -41,7 +44,7 @@ export function agentChildRowDetailText(row: AgentChildRowModel, now: number): s case 'role': return formatAgentTypeLabel(detail.agentType) case 'reason': - return backgroundTaskStateReason(detail.state) ?? '' + return backgroundTaskStateReason(detail.state) ?? backgroundTaskStateWord(detail.state) } } diff --git a/src/renderer/src/components/native-chat/NativeChatAutocompleteMenus.test.tsx b/src/renderer/src/components/native-chat/NativeChatAutocompleteMenus.test.tsx index 60c70baee66..d07ae3ae745 100644 --- a/src/renderer/src/components/native-chat/NativeChatAutocompleteMenus.test.tsx +++ b/src/renderer/src/components/native-chat/NativeChatAutocompleteMenus.test.tsx @@ -106,12 +106,32 @@ describe('NativeChatPickerMenu', () => { /> ) - expect(screen.getAllByText('Could not load skills from this host')).toHaveLength(2) + expect(screen.getAllByText("Couldn't load skills")).toHaveLength(2) expect(screen.queryByText('Loading skills...')).toBeNull() fireEvent.click(screen.getByRole('button', { name: 'Retry' })) expect(onRetry).toHaveBeenCalledOnce() }) + it('announces the same unavailable sentence it shows, with no Retry', () => { + render( + + ) + + expect(screen.getAllByText("Skills aren't available in SSH chats")).toHaveLength(2) + expect(screen.queryByText("Couldn't load skills")).toBeNull() + expect(screen.queryByRole('button', { name: 'Retry' })).toBeNull() + }) + it('uses command-only empty copy for a picker without skill support', () => { render( item.skillCollision) const duplicate = skills.find((item) => item.sources.length > 1) + // One sentence for the line and the screen reader, so the two never disagree. + const skillErrorText = + autocomplete.skillErrorKind === 'unavailable' + ? translate( + 'components.native-chat.composer.skillsUnavailableHost', + "Skills aren't available in SSH chats" + ) + : translate('components.native-chat.composer.skillsLoadFailed', "Couldn't load skills") let optionIndex = 0 return ( @@ -71,17 +79,7 @@ export const NativeChatPickerMenu = memo(function NativeChatPickerMenu({ ) : null} {autocomplete.skillStatus === 'error' ? ( - - {autocomplete.skillErrorKind === 'unavailable' - ? translate( - 'components.native-chat.composer.skillsUnavailableHost', - 'Skills are unavailable for this host' - ) - : translate( - 'components.native-chat.composer.skillsLoadFailed', - 'Could not load skills from this host' - )} - + {skillErrorText} {autocomplete.skillErrorKind !== 'unavailable' ? (

Agents

  • Failed child · failed
  • Background agent · no contact
  • Cancelled child
  • Approve edits · needs approval
  • Summarize logs900
  • Review the parser18.2k · 10m 0s
  • Explore · failed8m 20s
  • Old host child6m 40s

Shell

  • npm run dev11m 40s

Monitors

  • tail -f server.log
"`; +exports[`chat strip rows from a legacy background-task roster > render exactly as before 1`] = `"

Agents

  • Failed child · failed
  • Background agent · no recent update
  • Cancelled child
  • Approve edits · needs approval
  • Summarize logs900
  • Review the parser18.2k · 10m 0s
  • Explore · failed8m 20s
  • Old host child6m 40s

Shell

  • npm run dev11m 40s

Monitors

  • tail -f server.log
"`; -exports[`chat strip rows from a legacy background-task roster > render exactly as before 2`] = `"

Agents

  • Failed child · failed
  • Background agent · no contact
  • Cancelled child
  • Approve edits · needs approval
  • Summarize logs900
  • Review the parser18.2k · 10m 0s
  • Explore · failed8m 20s
  • Old host child6m 40s

Shell

  • npm run dev11m 40s

Monitors

  • tail -f server.log
"`; +exports[`chat strip rows from a legacy background-task roster > render exactly as before 2`] = `"

Agents

  • Failed child · failed
  • Background agent · no recent update
  • Cancelled child
  • Approve edits · needs approval
  • Summarize logs900
  • Review the parser18.2k · 10m 0s
  • Explore · failed8m 20s
  • Old host child6m 40s

Shell

  • npm run dev11m 40s

Monitors

  • tail -f server.log
"`; exports[`sidebar child rows from a legacy subagents snapshot > render a stale parent and a lost transport exactly as before 1`] = ` [ diff --git a/src/renderer/src/components/sidebar/subagent-child-row-fallback-pixels.test.tsx b/src/renderer/src/components/sidebar/subagent-child-row-fallback-pixels.test.tsx index 0be9f5ae546..3307d2f9dce 100644 --- a/src/renderer/src/components/sidebar/subagent-child-row-fallback-pixels.test.tsx +++ b/src/renderer/src/components/sidebar/subagent-child-row-fallback-pixels.test.tsx @@ -221,7 +221,7 @@ describe('chat strip rows from a legacy background-task roster', () => { container.innerHTML = markup expect([...container.querySelectorAll('li')].map((row) => row.textContent)).toEqual([ 'Failed child · failed', - 'Background agent · no contactStop', + 'Background agent · no recent updateStop', 'Cancelled child', 'Approve edits · needs approvalStop', 'Summarize logs900', diff --git a/src/renderer/src/i18n/en-runtime-required.json b/src/renderer/src/i18n/en-runtime-required.json index dd7c81ac47f..ff1d4e95cac 100644 --- a/src/renderer/src/i18n/en-runtime-required.json +++ b/src/renderer/src/i18n/en-runtime-required.json @@ -2763,7 +2763,7 @@ "notDelivered": "This message was not delivered.", "notDeliveredSendAgain": "This message was not delivered. Send it again to continue.", "notSignedIn": "{{agent}} is not signed in for the selected account.", - "previousExitUnverifiable": "Orca couldn't confirm {{agent}}'s previous process ended. Messages wait to be sent until Orca confirms it has ended.", + "previousExitUnverifiable": "{{agent}} from before may still be running. Your messages will send once it stops.", "providerExitedRejection": "{{agent}} stopped before this message was sent.", "providerExitedRow": "{{agent}} stopped while this response was in progress. You can continue in this conversation.", "providerRateLimited": "{{agent}} is rate-limited and retrying.", @@ -2783,6 +2783,10 @@ "theAgent": "The agent", "writeFailed": "Orca couldn't hand this message to the agent, so it was not sent." }, + "notices": { + "historyItemTooLarge": "This part of the chat was too large to show.", + "historyRepaired": "Part of this chat's history couldn't be loaded." + }, "question": { "other": "Other…" }, @@ -2792,8 +2796,6 @@ "title": "Start a chat with {{value0}}" }, "error": { - "keepsTrying": "Orca keeps trying to load it.", - "retryingSubtitle": "The transcript could not be read. Orca keeps trying to load it.", "subtitle": "The transcript could not be read. Toggle back to the terminal to keep working.", "title": "Could not load conversation" }, @@ -2838,7 +2840,7 @@ "answerFirst": "Answer the question or approval first.", "backgroundTasksRunning": "Background tasks are still running.", "capacity": "Orca has received too many requests in the last day.", - "chatNotFound": "The Orca running this chat has no record of it.", + "chatNotFound": "Orca can't find this chat.", "clearUnfinished": "The last /clear didn't finish.", "commandRunning": "A /compact or /clear is still running.", "conversationCleared": "This conversation has been cleared.", @@ -2847,7 +2849,9 @@ "historyUnreadable": "Orca couldn't read this chat's saved history.", "historyUnusable": "Unable to load this chat.", "hostReconciling": "Orca is still checking on this chat after restarting.", - "messagesUnsettled": "A message you sent earlier hasn't been confirmed yet.", + "messageNotSaved": "Couldn't save your message.", + "messagesUnsettled": "A message you sent earlier isn't confirmed yet.", + "notAvailable": "This isn't available in this chat.", "notDoneAnswer": "Your answer was not sent.", "notDoneCommand": "The command didn't run.", "notDoneGoal": "The goal wasn't changed.", @@ -2860,11 +2864,12 @@ "openCurrentConversation": "Open the current conversation to continue.", "optionRejected": "The agent didn't accept this setting.", "outcomeUnknown": "Orca couldn't confirm what happened. Check the chat.", - "ownerUnproven": "Orca hasn't confirmed that this chat's previous agent stopped.", + "sendOutcomeLost": "Orca couldn't confirm your message reached the agent. Check the chat, then send it again if needed.", + "ownerUnproven": "The previous agent in this chat may still be running.", "promptPending": "The agent is waiting for an answer to a question or approval.", "questionChanged": "This question was already answered or has changed.", "quitTerminalAgent": "Quit that agent to continue the chat here.", - "recordFailed": "Orca couldn't record it in this chat's history.", + "recordFailed": "Orca couldn't save this to the chat's history.", "recordUnreadable": "Orca couldn't read this chat's saved state.", "reopenChat": "Reopen the chat to check again.", "restartFailed": "The agent couldn't restart.", @@ -2876,7 +2881,7 @@ "tryAgainComposerSend": "Send it again.", "turnActive": "The agent is still responding.", "unreachable": "Orca couldn't reach the agent.", - "unsupported": "The Orca running this chat doesn't support this. Update Orca, then try again.", + "unsupported": "This needs a newer Orca on the computer running this chat. Update Orca there, then try again.", "updateOrcaToKeepUsing": "Update Orca to keep using them.", "waitForBackgroundTasks": "Wait for the background tasks to finish.", "waitForCommand": "Wait for the /compact or /clear to finish.", diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json index 82b8bdef27c..c8b18407251 100644 --- a/src/renderer/src/i18n/locales/en.json +++ b/src/renderer/src/i18n/locales/en.json @@ -17565,12 +17565,13 @@ "providerRateLimited": "{{agent}} is rate-limited and retrying.", "providerRetrying": "{{agent}} hit a temporary problem and is retrying.", "providerRetryingQuoted": "{{agent}} is retrying: {{detail}}.", - "previousExitUnverifiable": "Orca couldn't confirm {{agent}}'s previous process ended. Messages wait to be sent until Orca confirms it has ended." + "previousExitUnverifiable": "{{agent}} from before may still be running. Your messages will send once it stops." }, "writeNotice": { "notDoneReadHistory": "This chat's history couldn't be loaded.", "notDoneSend": "Your message was not sent.", "tryAgainComposerSend": "Send it again.", + "messageNotSaved": "Couldn't save your message.", "notDoneStop": "The agent wasn't stopped.", "notDoneStopTask": "The background task wasn't stopped.", "notDoneStopTasks": "The background tasks weren't stopped.", @@ -17581,15 +17582,17 @@ "restartFailed": "The agent couldn't restart.", "capacity": "Orca has received too many requests in the last day.", "outcomeUnknown": "Orca couldn't confirm what happened. Check the chat.", + "sendOutcomeLost": "Orca couldn't confirm your message reached the agent. Check the chat, then send it again if needed.", "questionChanged": "This question was already answered or has changed.", "historyUnreadable": "Orca couldn't read this chat's saved history.", "historyUnusable": "Unable to load this chat.", "historyUnavailable": "Orca couldn't open this chat's history right now.", "savedByNewerOrca": "Chats were saved by a newer Orca.", "updateOrcaToKeepUsing": "Update Orca to keep using them.", - "unsupported": "The Orca running this chat doesn't support this. Update Orca, then try again.", + "unsupported": "This needs a newer Orca on the computer running this chat. Update Orca there, then try again.", + "notAvailable": "This isn't available in this chat.", "unreachable": "Orca couldn't reach the agent.", - "recordFailed": "Orca couldn't record it in this chat's history.", + "recordFailed": "Orca couldn't save this to the chat's history.", "conversationCleared": "This conversation has been cleared.", "openCurrentConversation": "Open the current conversation to continue.", "clearUnfinished": "The last /clear didn't finish.", @@ -17603,19 +17606,19 @@ "answerFirst": "Answer the question or approval first.", "backgroundTasksRunning": "Background tasks are still running.", "waitForBackgroundTasks": "Wait for the background tasks to finish.", - "messagesUnsettled": "A message you sent earlier hasn't been confirmed yet.", + "messagesUnsettled": "A message you sent earlier isn't confirmed yet.", "settleEarlierMessage": "Wait for your earlier message to go through, or retry it.", "optionRejected": "The agent didn't accept this setting.", "goalsUnsupported": "This agent doesn't support goals.", "agentRefused": "The agent turned this down.", - "ownerUnproven": "Orca hasn't confirmed that this chat's previous agent stopped.", + "ownerUnproven": "The previous agent in this chat may still be running.", "reopenChat": "Reopen the chat to check again.", "terminalAgentHoldsChat": "This chat is still open in a terminal agent.", "quitTerminalAgent": "Quit that agent to continue the chat here.", "hostReconciling": "Orca is still checking on this chat after restarting.", "waitMoment": "Wait a moment.", "recordUnreadable": "Orca couldn't read this chat's saved state.", - "chatNotFound": "The Orca running this chat has no record of it.", + "chatNotFound": "Orca can't find this chat.", "startNewChat": "Start a new chat to continue.", "tryAgain": "Try again." }, @@ -17651,7 +17654,9 @@ "notices": { "compaction": "Context compacted", "details": "Details", - "plan": "Plan" + "plan": "Plan", + "historyRepaired": "Part of this chat's history couldn't be loaded.", + "historyItemTooLarge": "This part of the chat was too large to show." }, "composer": { "imageUnsupported": "Image paste is not supported for this agent.", @@ -17670,8 +17675,8 @@ "skills": "Skills", "loadingSkills": "Loading skills...", "skillsLoaded": "Skills loaded", - "skillsUnavailableHost": "Skills are unavailable for this host", - "skillsLoadFailed": "Could not load skills from this host", + "skillsUnavailableHost": "Skills aren't available in SSH chats", + "skillsLoadFailed": "Couldn't load skills", "retrySkills": "Retry", "skillCommandCollision": "Also a skill name - agent decides", "skillMultipleSources": "{{sourceCount}} sources - agent resolves", @@ -17831,9 +17836,9 @@ "stateBlocked": "blocked", "stateDone": "done", "stateIdle": "stopped", - "stateUnverifiable": "unverifiable", + "stateUnverifiable": "no recent update", + "stateUnverifiableCount": "{{value0}} with no recent update", "reasonWaiting": "needs approval", - "reasonUnverifiable": "no contact", "reasonBlocked": "failed", "groupAgents": "Agents", "groupShell": "Shell", @@ -17854,9 +17859,7 @@ }, "error": { "title": "Could not load conversation", - "subtitle": "The transcript could not be read. Toggle back to the terminal to keep working.", - "retryingSubtitle": "The transcript could not be read. Orca keeps trying to load it.", - "keepsTrying": "Orca keeps trying to load it." + "subtitle": "The transcript could not be read. Toggle back to the terminal to keep working." }, "reconnecting": "Reconnecting to this chat…", "pairHost": "Pair a host to view agent chat history.", @@ -17917,12 +17920,12 @@ "idle": "idle", "failed": "failed", "stopped": "stopped", - "unverifiable": "unverifiable", + "unverifiable": "no recent update", "workingCount": "{{value0}} working", "idleCount": "{{value0}} idle", "failedCount": "{{value0}} failed", "stoppedCount": "{{value0}} stopped", - "unverifiableCount": "{{value0}} unverifiable" + "unverifiableCount": "{{value0}} with no recent update" }, "startedOne": "Kicked off 1 subagent", "startedN": "Kicked off {{value0}} subagents", diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json index d1cf64cc782..abb19a1afff 100644 --- a/src/renderer/src/i18n/locales/es.json +++ b/src/renderer/src/i18n/locales/es.json @@ -14993,12 +14993,13 @@ "providerRateLimited": "{{agent}} alcanzó un límite de solicitudes y está reintentando.", "providerRetrying": "{{agent}} tuvo un problema temporal y está reintentando.", "providerRetryingQuoted": "{{agent}} está reintentando: {{detail}}.", - "previousExitUnverifiable": "Orca no pudo confirmar que el proceso anterior de {{agent}} terminó. Los mensajes esperan para enviarse hasta que Orca confirme que terminó." + "previousExitUnverifiable": "Es posible que {{agent}} siga en ejecución desde antes. Sus mensajes se enviarán cuando se detenga." }, "writeNotice": { "notDoneReadHistory": "No se pudo cargar el historial de este chat.", "notDoneSend": "Su mensaje no se envió.", "tryAgainComposerSend": "Vuelva a enviarlo.", + "messageNotSaved": "No se pudo guardar su mensaje.", "notDoneStop": "El agente no se detuvo.", "notDoneStopTask": "La tarea en segundo plano no se detuvo.", "notDoneStopTasks": "Las tareas en segundo plano no se detuvieron.", @@ -15009,15 +15010,17 @@ "restartFailed": "El agente no pudo reiniciarse.", "capacity": "Orca ha recibido demasiadas solicitudes en el último día.", "outcomeUnknown": "Orca no pudo confirmar qué pasó. Revise el chat.", + "sendOutcomeLost": "Orca no pudo confirmar que su mensaje llegó al agente. Revise el chat y vuelva a enviarlo si es necesario.", "questionChanged": "Esta pregunta ya se respondió o ha cambiado.", "historyUnreadable": "Orca no pudo leer el historial guardado de este chat.", "historyUnusable": "No se puede cargar este chat.", "historyUnavailable": "Orca no pudo abrir el historial de este chat en este momento.", "savedByNewerOrca": "Los chats se guardaron con una versión más reciente de Orca.", "updateOrcaToKeepUsing": "Actualice Orca para seguir usándolos.", - "unsupported": "La versión de Orca que ejecuta este chat no lo admite. Actualice Orca y vuelva a intentarlo.", + "unsupported": "Esto requiere una versión más reciente de Orca en el equipo que ejecuta este chat. Actualice Orca allí y vuelva a intentarlo.", + "notAvailable": "Esto no está disponible en este chat.", "unreachable": "Orca no pudo comunicarse con el agente.", - "recordFailed": "Orca no pudo registrarlo en el historial de este chat.", + "recordFailed": "Orca no pudo guardar esto en el historial del chat.", "conversationCleared": "Esta conversación se borró.", "openCurrentConversation": "Abra la conversación actual para continuar.", "clearUnfinished": "El último /clear no terminó.", @@ -15031,19 +15034,19 @@ "answerFirst": "Responda primero a la pregunta o aprobación.", "backgroundTasksRunning": "Todavía hay tareas en segundo plano en ejecución.", "waitForBackgroundTasks": "Espere a que terminen las tareas en segundo plano.", - "messagesUnsettled": "Un mensaje que envió antes todavía no se ha confirmado.", + "messagesUnsettled": "Un mensaje que envió antes todavía no está confirmado.", "settleEarlierMessage": "Espere a que se entregue su mensaje anterior o vuelva a intentarlo.", "optionRejected": "El agente no aceptó este ajuste.", "goalsUnsupported": "Este agente no admite objetivos.", "agentRefused": "El agente lo rechazó.", - "ownerUnproven": "Orca no ha confirmado que el agente anterior de este chat se haya detenido.", + "ownerUnproven": "Es posible que el agente anterior de este chat siga en ejecución.", "reopenChat": "Vuelva a abrir el chat para comprobarlo de nuevo.", "terminalAgentHoldsChat": "Este chat sigue abierto en un agente de terminal.", "quitTerminalAgent": "Cierre ese agente para continuar el chat aquí.", "hostReconciling": "Orca todavía está comprobando este chat después de reiniciarse.", "waitMoment": "Espere un momento.", "recordUnreadable": "Orca no pudo leer el estado guardado de este chat.", - "chatNotFound": "La versión de Orca que ejecuta este chat no tiene ningún registro de él.", + "chatNotFound": "Orca no encuentra este chat.", "startNewChat": "Inicie un chat nuevo para continuar.", "tryAgain": "Vuelva a intentarlo." }, @@ -15092,8 +15095,8 @@ "commands": "Comandos", "skills": "Habilidades", "loadingSkills": "Cargando habilidades…", - "skillsUnavailableHost": "Las habilidades no están disponibles para este host", - "skillsLoadFailed": "No se pudieron cargar las habilidades de este host", + "skillsUnavailableHost": "Las habilidades no están disponibles en los chats SSH", + "skillsLoadFailed": "No se pudieron cargar las habilidades", "retrySkills": "Reintentar", "skillCommandCollision": "También es un nombre de habilidad - el agente decide", "skillMultipleSources": "{{sourceCount}} fuentes - el agente resuelve", @@ -15126,9 +15129,7 @@ }, "error": { "title": "No se pudo cargar la conversación", - "subtitle": "No se pudo leer la transcripción. Vuelva a la terminal para seguir trabajando.", - "retryingSubtitle": "No se pudo leer la transcripción. Orca sigue intentando cargarla.", - "keepsTrying": "Orca sigue intentando cargarlo." + "subtitle": "No se pudo leer la transcripción. Vuelva a la terminal para seguir trabajando." }, "reconnecting": "Reconectando con este chat…", "pairHost": "Empareje un host para ver el historial de chat del agente.", diff --git a/src/renderer/src/i18n/locales/fr.json b/src/renderer/src/i18n/locales/fr.json index eec01269afc..017ee021cf8 100644 --- a/src/renderer/src/i18n/locales/fr.json +++ b/src/renderer/src/i18n/locales/fr.json @@ -17463,12 +17463,13 @@ "providerRateLimited": "{{agent}} est limité en débit et réessaie.", "providerRetrying": "{{agent}} a rencontré un problème temporaire et réessaie.", "providerRetryingQuoted": "{{agent}} réessaie : {{detail}}.", - "previousExitUnverifiable": "Orca n'a pas pu confirmer que le processus précédent de {{agent}} s'est arrêté. Les messages attendent d'être envoyés jusqu'à ce qu'Orca confirme son arrêt." + "previousExitUnverifiable": "L'exécution précédente de {{agent}} est peut-être toujours en cours. Vos messages seront envoyés dès qu'elle s'arrêtera." }, "writeNotice": { "notDoneReadHistory": "L'historique de ce chat n'a pas pu être chargé.", "notDoneSend": "Votre message n'a pas été envoyé.", "tryAgainComposerSend": "Renvoyez-le.", + "messageNotSaved": "Impossible d'enregistrer votre message.", "notDoneStop": "L'agent n'a pas été arrêté.", "notDoneStopTask": "La tâche en arrière-plan n'a pas été arrêtée.", "notDoneStopTasks": "Les tâches en arrière-plan n'ont pas été arrêtées.", @@ -17479,15 +17480,17 @@ "restartFailed": "L'agent n'a pas pu redémarrer.", "capacity": "Orca a reçu trop de requêtes au cours de la dernière journée.", "outcomeUnknown": "Orca n'a pas pu confirmer ce qui s'est passé. Vérifiez le chat.", + "sendOutcomeLost": "Orca n'a pas pu confirmer que votre message est parvenu à l'agent. Vérifiez le chat, puis renvoyez-le si nécessaire.", "questionChanged": "Cette question a déjà reçu une réponse ou a changé.", "historyUnreadable": "Orca n'a pas pu lire l'historique enregistré de ce chat.", "historyUnusable": "Impossible de charger ce chat.", "historyUnavailable": "Orca n'a pas pu ouvrir l'historique de ce chat pour le moment.", "savedByNewerOrca": "Les chats ont été enregistrés par une version plus récente d'Orca.", "updateOrcaToKeepUsing": "Mettez à jour Orca pour continuer à les utiliser.", - "unsupported": "L'instance d'Orca qui exécute ce chat ne le prend pas en charge. Mettez Orca à jour, puis réessayez.", + "unsupported": "Cela nécessite une version plus récente d'Orca sur l'ordinateur qui exécute ce chat. Mettez Orca à jour sur cet ordinateur, puis réessayez.", + "notAvailable": "Ceci n'est pas disponible dans ce chat.", "unreachable": "Orca n'a pas pu joindre l'agent.", - "recordFailed": "Orca n'a pas pu l'enregistrer dans l'historique de ce chat.", + "recordFailed": "Orca n'a pas pu enregistrer ceci dans l'historique du chat.", "conversationCleared": "Cette conversation a été effacée.", "openCurrentConversation": "Ouvrez la conversation actuelle pour continuer.", "clearUnfinished": "Le dernier /clear ne s'est pas terminé.", @@ -17501,19 +17504,19 @@ "answerFirst": "Répondez d'abord à la question ou à la demande d'approbation.", "backgroundTasksRunning": "Des tâches en arrière-plan sont encore en cours.", "waitForBackgroundTasks": "Attendez la fin des tâches en arrière-plan.", - "messagesUnsettled": "Un message que vous avez envoyé plus tôt n'a pas encore été confirmé.", + "messagesUnsettled": "Un message que vous avez envoyé plus tôt n'est pas encore confirmé.", "settleEarlierMessage": "Attendez que votre message précédent soit transmis, ou renvoyez-le.", "optionRejected": "L'agent n'a pas accepté ce réglage.", "goalsUnsupported": "Cet agent ne prend pas en charge les objectifs.", "agentRefused": "L'agent l'a refusé.", - "ownerUnproven": "Orca n'a pas confirmé l'arrêt de l'agent précédent de ce chat.", + "ownerUnproven": "L'agent précédent de ce chat est peut-être encore en cours d'exécution.", "reopenChat": "Rouvrez le chat pour vérifier à nouveau.", "terminalAgentHoldsChat": "Ce chat est encore ouvert dans un agent de terminal.", "quitTerminalAgent": "Quittez cet agent pour continuer le chat ici.", "hostReconciling": "Orca vérifie encore ce chat après son redémarrage.", "waitMoment": "Patientez un instant.", "recordUnreadable": "Orca n'a pas pu lire l'état enregistré de ce chat.", - "chatNotFound": "L'instance d'Orca qui exécute ce chat n'en a aucune trace.", + "chatNotFound": "Orca ne trouve pas ce chat.", "startNewChat": "Démarrez un nouveau chat pour continuer.", "tryAgain": "Réessayez." }, @@ -17534,8 +17537,8 @@ "skills": "Skills", "loadingSkills": "Chargement des skills...", "skillsLoaded": "Skills chargées", - "skillsUnavailableHost": "Les skills sont indisponibles pour cet hôte", - "skillsLoadFailed": "Impossible de charger les skills depuis cet hôte", + "skillsUnavailableHost": "Les skills ne sont pas disponibles dans les chats SSH", + "skillsLoadFailed": "Impossible de charger les skills", "retrySkills": "Réessayer", "skillCommandCollision": "Aussi un nom de skill - l'agent décide", "skillMultipleSources": "{{sourceCount}} sources - l'agent décide", @@ -17675,9 +17678,7 @@ }, "error": { "title": "Impossible de charger la conversation", - "subtitle": "La transcription n'a pas pu être lue. Rebasculez sur le terminal pour continuer à travailler.", - "retryingSubtitle": "La transcription n'a pas pu être lue. Orca continue d'essayer de la charger.", - "keepsTrying": "Orca continue d'essayer de le charger." + "subtitle": "La transcription n'a pas pu être lue. Rebasculez sur le terminal pour continuer à travailler." }, "reconnecting": "Reconnexion à ce chat…", "pairHost": "Associez un hôte pour consulter l'historique de chat des agents.", @@ -17754,7 +17755,9 @@ "notices": { "compaction": "Contexte compacté", "details": "Détails", - "plan": "Plan" + "plan": "Plan", + "historyRepaired": "Une partie de l'historique de ce chat n'a pas pu être chargée.", + "historyItemTooLarge": "Cette partie du chat était trop volumineuse pour être affichée." }, "providerFrame": { "byteLength": "{{value0}} octets" @@ -17789,9 +17792,9 @@ "stateBlocked": "bloqué", "stateDone": "fait", "stateIdle": "arrêté", - "stateUnverifiable": "invérifiable", + "stateUnverifiable": "aucune mise à jour récente", + "stateUnverifiableCount": "{{value0}} sans mise à jour récente", "reasonWaiting": "a besoin d'approbation", - "reasonUnverifiable": "aucun contact", "reasonBlocked": "échoué", "groupAgents": "Agents", "groupShell": "Coquille", @@ -17815,12 +17818,12 @@ "idle": "idle", "failed": "échoué", "stopped": "arrêté", - "unverifiable": "invérifiable", + "unverifiable": "aucune mise à jour récente", "workingCount": "{{value0}} fonctionne", "idleCount": "{{value0}} inactif", "failedCount": "{{value0}} a échoué", "stoppedCount": "{{value0}} arrêté", - "unverifiableCount": "{{value0}} invérifiable" + "unverifiableCount": "{{value0}} sans mise à jour récente" }, "startedOne": "A lancé 1 sous-agent", "startedN": "Lancement des sous-agents {{value0}}", diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json index b80969c4785..da7e1da6d95 100644 --- a/src/renderer/src/i18n/locales/ja.json +++ b/src/renderer/src/i18n/locales/ja.json @@ -17399,12 +17399,13 @@ "providerRateLimited": "{{agent}} はレート制限を受けているため、再試行しています。", "providerRetrying": "{{agent}} で一時的な問題が発生したため、再試行しています。", "providerRetryingQuoted": "{{agent}} は再試行しています: {{detail}}。", - "previousExitUnverifiable": "Orca は {{agent}} の前のプロセスが終了したことを確認できませんでした。Orca が終了を確認するまで、メッセージは送信を待機します。" + "previousExitUnverifiable": "以前の {{agent}} がまだ実行中の可能性があります。停止するとメッセージが送信されます。" }, "writeNotice": { "notDoneReadHistory": "このチャットの履歴を読み込めませんでした。", "notDoneSend": "メッセージは送信されませんでした。", "tryAgainComposerSend": "もう一度送信してください。", + "messageNotSaved": "メッセージを保存できませんでした。", "notDoneStop": "Agent は停止されませんでした。", "notDoneStopTask": "バックグラウンドタスクは停止されませんでした。", "notDoneStopTasks": "バックグラウンドタスクは停止されませんでした。", @@ -17415,15 +17416,17 @@ "restartFailed": "Agent を再起動できませんでした。", "capacity": "Orca が過去 1 日に受け取ったリクエストが多すぎます。", "outcomeUnknown": "Orca は何が起きたかを確認できませんでした。チャットを確認してください。", + "sendOutcomeLost": "Orca はメッセージが Agent に届いたことを確認できませんでした。チャットを確認し、必要であればもう一度送信してください。", "questionChanged": "この質問はすでに回答済みか、変更されています。", "historyUnreadable": "Orca はこのチャットの保存済み履歴を読み取れませんでした。", "historyUnusable": "このチャットを読み込めません。", "historyUnavailable": "Orca は現在このチャットの履歴を開けませんでした。", "savedByNewerOrca": "チャットは新しいバージョンの Orca で保存されました。", "updateOrcaToKeepUsing": "引き続き使用するには、Orca を更新してください。", - "unsupported": "このチャットを実行している Orca はこの操作に対応していません。Orca を更新してから、もう一度お試しください。", + "unsupported": "このチャットを実行しているコンピューターに新しいバージョンの Orca が必要です。そのコンピューターで Orca を更新してから、もう一度お試しください。", + "notAvailable": "このチャットでは利用できません。", "unreachable": "Orca は Agent に接続できませんでした。", - "recordFailed": "Orca はこのチャットの履歴に記録できませんでした。", + "recordFailed": "Orca はこれをチャットの履歴に保存できませんでした。", "conversationCleared": "この会話はクリアされました。", "openCurrentConversation": "続けるには、現在の会話を開いてください。", "clearUnfinished": "前回の /clear は完了しませんでした。", @@ -17437,19 +17440,19 @@ "answerFirst": "先に質問または承認に回答してください。", "backgroundTasksRunning": "バックグラウンドタスクがまだ実行中です。", "waitForBackgroundTasks": "バックグラウンドタスクが終わるまでお待ちください。", - "messagesUnsettled": "以前に送信したメッセージがまだ確認されていません。", + "messagesUnsettled": "以前に送信したメッセージはまだ確認されていません。", "settleEarlierMessage": "以前のメッセージが届くまで待つか、再試行してください。", "optionRejected": "Agent はこの設定を受け入れませんでした。", "goalsUnsupported": "この Agent は目標に対応していません。", "agentRefused": "Agent がこれを拒否しました。", - "ownerUnproven": "Orca は、このチャットの以前の Agent が停止したことをまだ確認できていません。", + "ownerUnproven": "このチャットの以前の Agent がまだ実行中の可能性があります。", "reopenChat": "もう一度確認するには、チャットを開き直してください。", "terminalAgentHoldsChat": "このチャットはまだターミナルの Agent で開かれています。", "quitTerminalAgent": "ここでチャットを続けるには、その Agent を終了してください。", "hostReconciling": "Orca は再起動後、このチャットをまだ確認しています。", "waitMoment": "しばらくお待ちください。", "recordUnreadable": "Orca はこのチャットの保存済みの状態を読み取れませんでした。", - "chatNotFound": "このチャットを実行している Orca には、このチャットの記録がありません。", + "chatNotFound": "Orca はこのチャットを見つけられません。", "startNewChat": "続けるには、新しいチャットを開始してください。", "tryAgain": "もう一度お試しください。" }, @@ -17498,8 +17501,8 @@ "commands": "コマンド", "skills": "スキル", "loadingSkills": "スキルを読み込み中…", - "skillsUnavailableHost": "このホストではスキルが利用できません", - "skillsLoadFailed": "このホストからスキルを読み込めませんでした", + "skillsUnavailableHost": "SSH チャットではスキルを利用できません", + "skillsLoadFailed": "スキルを読み込めませんでした", "retrySkills": "再試行", "skillCommandCollision": "スキル名でもあります - Agent が判断します", "skillMultipleSources": "{{sourceCount}} 個のソース - Agent が解決します", @@ -17611,9 +17614,7 @@ }, "error": { "title": "会話を読み込めませんでした", - "subtitle": "トランスクリプトを読み取ることができませんでした。作業を続けるには、ターミナルに切り替えてください。", - "retryingSubtitle": "トランスクリプトを読み取ることができませんでした。Orca は読み込みを再試行し続けます。", - "keepsTrying": "Orca は読み込みを再試行し続けます。" + "subtitle": "トランスクリプトを読み取ることができませんでした。作業を続けるには、ターミナルに切り替えてください。" }, "reconnecting": "このチャットに再接続しています…", "pairHost": "ホストをペアリングして、Agent のチャット履歴を表示します。", @@ -17690,7 +17691,9 @@ "notices": { "compaction": "圧縮されたコンテキスト", "details": "詳細", - "plan": "プラン" + "plan": "プラン", + "historyRepaired": "このチャットの履歴の一部を読み込めませんでした。", + "historyItemTooLarge": "チャットのこの部分は大きすぎるため表示できません。" }, "providerFrame": { "byteLength": "{{value0}}バイト" @@ -17725,9 +17728,9 @@ "stateBlocked": "ブロックされました", "stateDone": "終わり", "stateIdle": "止まった", - "stateUnverifiable": "検証不能", + "stateUnverifiable": "最近の更新なし", + "stateUnverifiableCount": "{{value0}} は最近の更新なし", "reasonWaiting": "承認が必要です", - "reasonUnverifiable": "連絡がありません", "reasonBlocked": "失敗した", "groupAgents": "Agent", "groupShell": "シェル", @@ -17751,12 +17754,12 @@ "idle": "idle", "failed": "失敗した", "stopped": "止まった", - "unverifiable": "検証不能", + "unverifiable": "最近の更新なし", "workingCount": "{{value0}} は動作しています", "idleCount": "{{value0}} アイドル状態", "failedCount": "{{value0}} 件失敗", "stoppedCount": "{{value0}} が停止しました", - "unverifiableCount": "{{value0}} 検証不能" + "unverifiableCount": "{{value0}} は最近の更新なし" }, "startedOne": "1 人のサブ Agent を解雇しました", "startedN": "{{value0}} サブ Agent をキックオフしました", diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json index b11c2e8ae71..78504ce8971 100644 --- a/src/renderer/src/i18n/locales/ko.json +++ b/src/renderer/src/i18n/locales/ko.json @@ -17399,12 +17399,13 @@ "providerRateLimited": "{{agent}}이(가) 속도 제한에 걸려 다시 시도하고 있습니다.", "providerRetrying": "{{agent}}에 일시적인 문제가 발생하여 다시 시도하고 있습니다.", "providerRetryingQuoted": "{{agent}}이(가) 다시 시도하고 있습니다: {{detail}}.", - "previousExitUnverifiable": "Orca가 {{agent}}의 이전 프로세스가 종료되었는지 확인하지 못했습니다. Orca가 종료를 확인할 때까지 메시지는 전송을 기다립니다." + "previousExitUnverifiable": "이전에 실행된 {{agent}}이(가) 아직 실행 중일 수 있습니다. 중지되면 메시지가 전송됩니다." }, "writeNotice": { "notDoneReadHistory": "이 채팅의 기록을 불러오지 못했습니다.", "notDoneSend": "메시지가 전송되지 않았습니다.", "tryAgainComposerSend": "다시 보내세요.", + "messageNotSaved": "메시지를 저장할 수 없습니다.", "notDoneStop": "에이전트가 중지되지 않았습니다.", "notDoneStopTask": "백그라운드 작업이 중지되지 않았습니다.", "notDoneStopTasks": "백그라운드 작업이 중지되지 않았습니다.", @@ -17415,15 +17416,17 @@ "restartFailed": "에이전트를 다시 시작하지 못했습니다.", "capacity": "Orca가 지난 하루 동안 너무 많은 요청을 받았습니다.", "outcomeUnknown": "Orca가 무슨 일이 있었는지 확인하지 못했습니다. 채팅을 확인하세요.", + "sendOutcomeLost": "Orca가 메시지가 에이전트에 전달되었는지 확인하지 못했습니다. 채팅을 확인하고 필요하면 다시 보내세요.", "questionChanged": "이 질문은 이미 답변되었거나 변경되었습니다.", "historyUnreadable": "Orca가 이 채팅의 저장된 기록을 읽지 못했습니다.", "historyUnusable": "이 채팅을 불러올 수 없습니다.", "historyUnavailable": "Orca가 지금 이 채팅의 기록을 열지 못했습니다.", "savedByNewerOrca": "채팅이 최신 버전의 Orca에서 저장되었습니다.", "updateOrcaToKeepUsing": "계속 사용하려면 Orca를 업데이트하세요.", - "unsupported": "이 채팅을 실행 중인 Orca가 이 기능을 지원하지 않습니다. Orca를 업데이트한 후 다시 시도하세요.", + "unsupported": "이 채팅을 실행 중인 컴퓨터에 최신 버전의 Orca가 필요합니다. 해당 컴퓨터에서 Orca를 업데이트한 후 다시 시도하세요.", + "notAvailable": "이 채팅에서는 사용할 수 없습니다.", "unreachable": "Orca가 에이전트에 연결하지 못했습니다.", - "recordFailed": "Orca가 이 채팅의 기록에 저장하지 못했습니다.", + "recordFailed": "Orca가 이 내용을 채팅 기록에 저장하지 못했습니다.", "conversationCleared": "이 대화는 지워졌습니다.", "openCurrentConversation": "계속하려면 현재 대화를 여세요.", "clearUnfinished": "마지막 /clear가 완료되지 않았습니다.", @@ -17442,14 +17445,14 @@ "optionRejected": "에이전트가 이 설정을 받아들이지 않았습니다.", "goalsUnsupported": "이 에이전트는 목표를 지원하지 않습니다.", "agentRefused": "에이전트가 이를 거부했습니다.", - "ownerUnproven": "Orca가 이 채팅의 이전 에이전트가 중지되었는지 아직 확인하지 못했습니다.", + "ownerUnproven": "이 채팅의 이전 에이전트가 아직 실행 중일 수 있습니다.", "reopenChat": "다시 확인하려면 채팅을 다시 여세요.", "terminalAgentHoldsChat": "이 채팅은 아직 터미널 에이전트에서 열려 있습니다.", "quitTerminalAgent": "여기에서 채팅을 계속하려면 해당 에이전트를 종료하세요.", "hostReconciling": "Orca가 다시 시작된 후 이 채팅을 아직 확인하고 있습니다.", "waitMoment": "잠시 기다리세요.", "recordUnreadable": "Orca가 이 채팅의 저장된 상태를 읽지 못했습니다.", - "chatNotFound": "이 채팅을 실행하는 Orca에 이 채팅의 기록이 없습니다.", + "chatNotFound": "Orca에서 이 채팅을 찾을 수 없습니다.", "startNewChat": "계속하려면 새 채팅을 시작하세요.", "tryAgain": "다시 시도하세요." }, @@ -17498,8 +17501,8 @@ "commands": "명령어", "skills": "스킬", "loadingSkills": "스킬 로딩 중…", - "skillsUnavailableHost": "이 호스트에서는 스킬을 사용할 수 없습니다", - "skillsLoadFailed": "이 호스트에서 스킬을 불러올 수 없습니다", + "skillsUnavailableHost": "SSH 채팅에서는 스킬을 사용할 수 없습니다", + "skillsLoadFailed": "스킬을 불러올 수 없습니다", "retrySkills": "재시도", "skillCommandCollision": "스킬 이름이기도 합니다 - 에이전트가 결정합니다", "skillMultipleSources": "{{sourceCount}}개 소스 - 에이전트가 해결합니다", @@ -17611,9 +17614,7 @@ }, "error": { "title": "대화를 로드할 수 없습니다.", - "subtitle": "스크립트를 읽을 수 없습니다. 계속 작업하려면 terminal로 다시 전환하세요.", - "retryingSubtitle": "스크립트를 읽을 수 없습니다. Orca가 계속 다시 불러오기를 시도합니다.", - "keepsTrying": "Orca가 계속 다시 불러오기를 시도합니다." + "subtitle": "스크립트를 읽을 수 없습니다. 계속 작업하려면 terminal로 다시 전환하세요." }, "reconnecting": "이 채팅에 다시 연결하는 중…", "pairHost": "호스트를 페어링하여 에이전트 채팅 기록을 확인하세요.", @@ -17690,7 +17691,9 @@ "notices": { "compaction": "컨텍스트가 압축됨", "details": "세부", - "plan": "계획" + "plan": "계획", + "historyRepaired": "이 채팅 기록의 일부를 불러올 수 없습니다.", + "historyItemTooLarge": "채팅의 이 부분은 너무 커서 표시할 수 없습니다." }, "providerFrame": { "byteLength": "{{value0}}바이트" @@ -17725,9 +17728,9 @@ "stateBlocked": "막힌", "stateDone": "완료", "stateIdle": "중지됨", - "stateUnverifiable": "검증할 수 없는", + "stateUnverifiable": "최근 업데이트 없음", + "stateUnverifiableCount": "{{value0}} 최근 업데이트 없음", "reasonWaiting": "승인이 필요합니다", - "reasonUnverifiable": "연락 없음", "reasonBlocked": "실패한", "groupAgents": "에이전트", "groupShell": "셸", @@ -17751,12 +17754,12 @@ "idle": "idle", "failed": "실패한", "stopped": "중지됨", - "unverifiable": "검증할 수 없는", + "unverifiable": "최근 업데이트 없음", "workingCount": "{{value0}} 작업 중", "idleCount": "{{value0}} 유휴", "failedCount": "{{value0}} 실패", "stoppedCount": "{{value0}} 중지됨", - "unverifiableCount": "{{value0}} 확인할 수 없음" + "unverifiableCount": "{{value0}} 최근 업데이트 없음" }, "startedOne": "서브에이전트 1명 추방", "startedN": "{{value0}} 하위 에이전트가 시작되었습니다.", diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json index c8baec3cd23..0f452b5617f 100644 --- a/src/renderer/src/i18n/locales/zh.json +++ b/src/renderer/src/i18n/locales/zh.json @@ -17364,12 +17364,13 @@ "providerRateLimited": "{{agent}} 已被限流,正在重试。", "providerRetrying": "{{agent}} 遇到临时问题,正在重试。", "providerRetryingQuoted": "{{agent}} 正在重试:{{detail}}。", - "previousExitUnverifiable": "Orca 无法确认 {{agent}} 的上一个进程已结束。在 Orca 确认其已结束之前,消息会等待发送。" + "previousExitUnverifiable": "之前的 {{agent}} 可能仍在运行。它停止后,您的消息就会发送。" }, "writeNotice": { "notDoneReadHistory": "无法加载此聊天的历史记录。", "notDoneSend": "您的消息未发送。", "tryAgainComposerSend": "请重新发送。", + "messageNotSaved": "无法保存您的消息。", "notDoneStop": "智能体未停止。", "notDoneStopTask": "后台任务未停止。", "notDoneStopTasks": "后台任务未停止。", @@ -17380,15 +17381,17 @@ "restartFailed": "智能体无法重新启动。", "capacity": "Orca 在过去一天内收到的请求过多。", "outcomeUnknown": "Orca 无法确认发生了什么。请查看聊天。", + "sendOutcomeLost": "Orca 无法确认你的消息已送达代理。请查看聊天,如有需要请重新发送。", "questionChanged": "此问题已被回答或已更改。", "historyUnreadable": "Orca 无法读取此聊天的已保存历史记录。", "historyUnusable": "无法加载此聊天。", "historyUnavailable": "Orca 目前无法打开此聊天的历史记录。", "savedByNewerOrca": "这些聊天由更新版本的 Orca 保存。", "updateOrcaToKeepUsing": "请更新 Orca 以继续使用这些聊天。", - "unsupported": "运行此聊天的 Orca 不支持此操作。请更新 Orca 后重试。", + "unsupported": "运行此聊天的计算机需要更新版本的 Orca。请在该计算机上更新 Orca 后重试。", + "notAvailable": "此聊天中无法使用此功能。", "unreachable": "Orca 无法连接到智能体。", - "recordFailed": "Orca 无法将其记录到此聊天的历史记录中。", + "recordFailed": "Orca 无法将此内容保存到聊天历史记录中。", "conversationCleared": "此对话已被清除。", "openCurrentConversation": "请打开当前对话以继续。", "clearUnfinished": "上一次 /clear 未完成。", @@ -17407,14 +17410,14 @@ "optionRejected": "智能体未接受此设置。", "goalsUnsupported": "此智能体不支持目标。", "agentRefused": "智能体拒绝了此请求。", - "ownerUnproven": "Orca 尚未确认此聊天之前的智能体已停止。", + "ownerUnproven": "此聊天之前的智能体可能仍在运行。", "reopenChat": "请重新打开聊天以再次检查。", "terminalAgentHoldsChat": "此聊天仍在终端智能体中打开。", "quitTerminalAgent": "请退出该智能体,以便在此处继续聊天。", "hostReconciling": "Orca 重启后仍在检查此聊天。", "waitMoment": "请稍候。", "recordUnreadable": "Orca 无法读取此聊天的已保存状态。", - "chatNotFound": "运行此聊天的 Orca 没有此聊天的记录。", + "chatNotFound": "Orca 找不到此聊天。", "startNewChat": "请开始新的聊天以继续。", "tryAgain": "请重试。" }, @@ -17463,8 +17466,8 @@ "commands": "命令", "skills": "技能", "loadingSkills": "正在加载技能…", - "skillsUnavailableHost": "此主机上无法使用技能", - "skillsLoadFailed": "无法从此主机加载技能", + "skillsUnavailableHost": "SSH 聊天中无法使用技能", + "skillsLoadFailed": "无法加载技能", "retrySkills": "重试", "skillCommandCollision": "也是技能名称 — 由智能体决定", "skillMultipleSources": "{{sourceCount}} 个来源 — 由智能体处理", @@ -17576,9 +17579,7 @@ }, "error": { "title": "无法加载对话", - "subtitle": "无法读取记录。请切回终端继续工作。", - "retryingSubtitle": "无法读取记录。Orca 会继续尝试加载。", - "keepsTrying": "Orca 会继续尝试加载。" + "subtitle": "无法读取记录。请切回终端继续工作。" }, "reconnecting": "正在重新连接此聊天…", "pairHost": "配对主机以查看智能体聊天记录。", @@ -17655,7 +17656,9 @@ "notices": { "compaction": "上下文压缩", "details": "细节", - "plan": "计划" + "plan": "计划", + "historyRepaired": "此聊天的部分历史记录无法加载。", + "historyItemTooLarge": "聊天的这一部分过大,无法显示。" }, "providerFrame": { "byteLength": "{{value0}} 字节" @@ -17690,9 +17693,9 @@ "stateBlocked": "被阻止", "stateDone": "完毕", "stateIdle": "停止了", - "stateUnverifiable": "无法验证的", + "stateUnverifiable": "暂无近期更新", + "stateUnverifiableCount": "{{value0}} 暂无近期更新", "reasonWaiting": "需要批准", - "reasonUnverifiable": "没有联系", "reasonBlocked": "失败的", "groupAgents": "代理", "groupShell": "壳", @@ -17716,12 +17719,12 @@ "idle": "idle", "failed": "失败的", "stopped": "停止了", - "unverifiable": "无法验证的", + "unverifiable": "暂无近期更新", "workingCount": "{{value0}} 工作", "idleCount": "{{value0}} 空闲", "failedCount": "{{value0}} 失败", "stoppedCount": "{{value0}} 已停止", - "unverifiableCount": "{{value0}} 无法验证" + "unverifiableCount": "{{value0}} 暂无近期更新" }, "startedOne": "踢掉 1 个子代理", "startedN": "启动 {{value0}} 子代理", diff --git a/src/shared/agent-session-failure-copy.ts b/src/shared/agent-session-failure-copy.ts index e6eeab28222..1f3a58f3bad 100644 --- a/src/shared/agent-session-failure-copy.ts +++ b/src/shared/agent-session-failure-copy.ts @@ -82,7 +82,7 @@ export const AGENT_SESSION_FAILURE_COPY = { providerRetrying: '{{agent}} hit a temporary problem and is retrying.', providerRetryingQuoted: '{{agent}} is retrying: {{detail}}.', previousExitUnverifiable: - "Orca couldn't confirm {{agent}}'s previous process ended. Messages wait to be sent until Orca confirms it has ended." + '{{agent}} from before may still be running. Your messages will send once it stops.' } as const export type AgentSessionFailureCopyId = keyof typeof AGENT_SESSION_FAILURE_COPY diff --git a/src/shared/agent-session-host-status-rows.ts b/src/shared/agent-session-host-status-rows.ts new file mode 100644 index 00000000000..880eb105ed0 --- /dev/null +++ b/src/shared/agent-session-host-status-rows.ts @@ -0,0 +1,25 @@ +// Status rows a host writes in its own words. Each names itself with a presentation so a client can +// say it in the reader's language; its `text` stays the words for a client that can't. + +import type { AgentJournalPlainStatusItem } from './agent-session-journal-types' + +export const AGENT_SESSION_HOST_STATUS_COPY = { + /** A repair skipped rows it could not read. */ + 'history-repaired': "Part of this chat's history couldn't be loaded.", + /** In place of an item too large for any history page. */ + 'history-item-too-large': 'This part of the chat was too large to show.' +} as const + +export type AgentSessionHostStatusPresentation = keyof typeof AGENT_SESSION_HOST_STATUS_COPY + +export function agentSessionHostStatusBody( + presentation: AgentSessionHostStatusPresentation +): AgentJournalPlainStatusItem { + return { kind: 'status', text: AGENT_SESSION_HOST_STATUS_COPY[presentation], presentation } +} + +export function isAgentSessionHostStatusPresentation( + presentation: string | undefined +): presentation is AgentSessionHostStatusPresentation { + return presentation !== undefined && Object.hasOwn(AGENT_SESSION_HOST_STATUS_COPY, presentation) +} diff --git a/src/shared/agent-session-refusal-notice.test.ts b/src/shared/agent-session-refusal-notice.test.ts index 9037e219044..b60356965c0 100644 --- a/src/shared/agent-session-refusal-notice.test.ts +++ b/src/shared/agent-session-refusal-notice.test.ts @@ -14,7 +14,6 @@ import { } from './agent-session-refusal-notice' import { AGENT_SESSION_WRITE_NOTICE_COPY, - agentSessionNoticeSaysThisChatUnread, type AgentSessionWriteNoticeSentence } from './agent-session-write-notice-copy' import { AGENT_SESSION_REFUSAL_REASONS } from './agent-session-refusal-details' @@ -63,7 +62,8 @@ const CAUSES: Partial { })) ) + // An unsupported location or agent, or no chat host, is not fixed by updating Orca. A read asked + // for nothing "this" could name, so it says only that the history didn't load. + it('says an unsupported write only is not available when the host names why', () => { + for (const { failure, write, parts, cell } of cells) { + if (failure.code === 'structured_agent_session_unsupported') { + expect(parts, cell).toEqual( + write === 'read-history' ? ['notDoneReadHistory'] : ['notAvailable'] + ) + } + } + }) + it('has words for every reason', () => { for (const { words, cell } of cells) { expect(words, cell).toBeDefined() @@ -428,7 +440,8 @@ describe('the notice for every reason a host names', () => { } const notDone = parts.filter((part) => typeof part === 'string' && part.startsWith('notDone')) const answeredAway = write === 'answer' && parts.includes('questionChanged') - const unsupported = failure.code === 'structured_agent_session_unsupported' + const unsupported = + failure.code === 'structured_agent_session_unsupported' && write !== 'read-history' const saysNotDone = write === 'read-history' && failure.code === 'agent_session_journal_unreadable' expect(notDone, cell).toEqual( @@ -580,23 +593,6 @@ describe('a chat whose history the host could not open', () => { ).toEqual(['historyUnreadable']) }) - // A pane headed by such words drops its own "didn't load", so each one must count. - it("knows which read notices already say this chat's history did not load", () => { - for (const failure of [...FAILURES, ...REASONED]) { - for (const retryControl of [false, true]) { - const parts = agentSessionWriteNoticeParts(failure, 'read-history', { retryControl }) - // "Chats were saved by a newer Orca" is about every chat, not this one. - const notAboutThisRead = - mayHaveRun(failure) || - codeOf(failure) === 'structured_agent_session_unsupported' || - parts.includes('savedByNewerOrca') - expect(agentSessionNoticeSaysThisChatUnread(parts), JSON.stringify(parts)).toBe( - !notAboutThisRead - ) - } - } - }) - it('says only that the history did not load for any other read refusal', () => { expect(agentSessionReadHistoryRefusalParts('agent_session_ownership_unknown')).toEqual([ 'notDoneReadHistory' diff --git a/src/shared/agent-session-refusal-notice.ts b/src/shared/agent-session-refusal-notice.ts index 0f9c47ded03..93a1409de03 100644 --- a/src/shared/agent-session-refusal-notice.ts +++ b/src/shared/agent-session-refusal-notice.ts @@ -206,11 +206,14 @@ const REASON_WORDS = { journalUnavailable: causeWords('historyUnavailable', 'retry', 'tryAgain'), journalWrittenByNewerOrca: causeWords('savedByNewerOrca', 'updateOrca', 'updateOrcaToKeepUsing') }, - // Thrown, so a client meets these only as an RPC error; the code's words stand. + // Thrown, so a client meets these only as an RPC error. The code's own words ask for an update, + // which only a method the host doesn't know proves; no reason here means an older Orca. An + // unsupported location or agent, or no chat host, is not fixed by updating, and a client missing + // the capability words this with its own older copy. structured_agent_session_unsupported: { - clientCapabilityMissing: codeWords('updateOrca'), - hostDisabled: codeWords('hostFinding'), - hostUnsupported: codeWords('updateOrca') + clientCapabilityMissing: causeWords('notAvailable', 'hostFinding'), + hostDisabled: causeWords('notAvailable', 'hostFinding'), + hostUnsupported: causeWords('notAvailable', 'hostFinding') }, agent_session_owner_restart_failed: {} } satisfies { @@ -235,6 +238,10 @@ function causeParts( cause: AgentSessionWriteNoticeSentence, write: AgentSessionWriteKind ): AgentSessionWriteNoticeSentence[] { + // Says the request didn't happen, but a read asked for nothing "this" could name. + if (cause === 'notAvailable') { + return write === 'read-history' ? [NOT_DONE[write]] : [cause] + } const saysNotDone = (write === 'read-history' && AGENT_SESSION_HISTORY_UNREAD_CAUSES.has(cause)) || (cause === 'questionChanged' && write === 'answer') diff --git a/src/shared/agent-session-write-notice-copy.ts b/src/shared/agent-session-write-notice-copy.ts index e5e6d011311..08fd7a90a60 100644 --- a/src/shared/agent-session-write-notice-copy.ts +++ b/src/shared/agent-session-write-notice-copy.ts @@ -17,6 +17,7 @@ export const AGENT_SESSION_WRITE_NOTICE_COPY = { notDoneReadHistory: "This chat's history couldn't be loaded.", notDoneSend: 'Your message was not sent.', tryAgainComposerSend: 'Send it again.', + messageNotSaved: "Couldn't save your message.", notDoneStop: "The agent wasn't stopped.", notDoneStopTask: "The background task wasn't stopped.", notDoneStopTasks: "The background tasks weren't stopped.", @@ -27,15 +28,19 @@ export const AGENT_SESSION_WRITE_NOTICE_COPY = { restartFailed: "The agent couldn't restart.", capacity: 'Orca has received too many requests in the last day.', outcomeUnknown: "Orca couldn't confirm what happened. Check the chat.", + sendOutcomeLost: + "Orca couldn't confirm your message reached the agent. Check the chat, then send it again if needed.", questionChanged: 'This question was already answered or has changed.', historyUnreadable: "Orca couldn't read this chat's saved history.", historyUnusable: 'Unable to load this chat.', historyUnavailable: "Orca couldn't open this chat's history right now.", savedByNewerOrca: 'Chats were saved by a newer Orca.', updateOrcaToKeepUsing: 'Update Orca to keep using them.', - unsupported: "The Orca running this chat doesn't support this. Update Orca, then try again.", + unsupported: + 'This needs a newer Orca on the computer running this chat. Update Orca there, then try again.', + notAvailable: "This isn't available in this chat.", unreachable: "Orca couldn't reach the agent.", - recordFailed: "Orca couldn't record it in this chat's history.", + recordFailed: "Orca couldn't save this to the chat's history.", conversationCleared: 'This conversation has been cleared.', openCurrentConversation: 'Open the current conversation to continue.', clearUnfinished: "The last /clear didn't finish.", @@ -49,19 +54,19 @@ export const AGENT_SESSION_WRITE_NOTICE_COPY = { answerFirst: 'Answer the question or approval first.', backgroundTasksRunning: 'Background tasks are still running.', waitForBackgroundTasks: 'Wait for the background tasks to finish.', - messagesUnsettled: "A message you sent earlier hasn't been confirmed yet.", + messagesUnsettled: "A message you sent earlier isn't confirmed yet.", settleEarlierMessage: 'Wait for your earlier message to go through, or retry it.', optionRejected: "The agent didn't accept this setting.", goalsUnsupported: "This agent doesn't support goals.", agentRefused: 'The agent turned this down.', - ownerUnproven: "Orca hasn't confirmed that this chat's previous agent stopped.", + ownerUnproven: 'The previous agent in this chat may still be running.', reopenChat: 'Reopen the chat to check again.', terminalAgentHoldsChat: TERMINAL_AGENT_HOLDS_CHAT, quitTerminalAgent: QUIT_TERMINAL_AGENT, hostReconciling: 'Orca is still checking on this chat after restarting.', waitMoment: 'Wait a moment.', recordUnreadable: "Orca couldn't read this chat's saved state.", - chatNotFound: 'The Orca running this chat has no record of it.', + chatNotFound: "Orca can't find this chat.", startNewChat: START_NEW_CHAT, tryAgain: 'Try again.' } as const @@ -84,16 +89,3 @@ export type AgentSessionWriteNoticePart = * again. */ export const AGENT_SESSION_HISTORY_UNREAD_CAUSES: ReadonlySet = new Set(['historyUnusable', 'historyUnavailable', 'historyUnreadable', 'savedByNewerOrca']) - -/** Whether these words already say this chat's history didn't load, so a pane headed by them need - * only add that it keeps trying. "Chats were saved by a newer Orca" names no one chat for "it". */ -export function agentSessionNoticeSaysThisChatUnread( - parts: readonly AgentSessionWriteNoticePart[] -): boolean { - return parts.some( - (part) => - typeof part === 'string' && - part !== 'savedByNewerOrca' && - (part === 'notDoneReadHistory' || AGENT_SESSION_HISTORY_UNREAD_CAUSES.has(part)) - ) -} diff --git a/src/shared/native-chat-empty-state.ts b/src/shared/native-chat-empty-state.ts index 2957698ae09..2797648afd0 100644 --- a/src/shared/native-chat-empty-state.ts +++ b/src/shared/native-chat-empty-state.ts @@ -19,20 +19,12 @@ export const NATIVE_CHAT_EMPTY_STATE_COPY = { title: 'Could not load conversation', subtitle: 'The transcript could not be read. Toggle back to the terminal to keep working.' }, - // The structured chat's read reconnects on its own; the terminal-backed read does not. - retryingError: { - title: 'Could not load conversation', - subtitle: 'The transcript could not be read. Orca keeps trying to load it.' - }, notAgent: { title: 'No conversation here', subtitle: 'This terminal is not running a recognized coding agent.' } } as const satisfies Record -/** The retrying half alone, under a title that already says the history didn't load. */ -export const NATIVE_CHAT_KEEPS_TRYING_COPY = 'Orca keeps trying to load it.' - /** Resolve the empty-state copy with the agent label substituted for `{{value0}}`. * For platforms without an i18n layer (mobile). */ export function formatNativeChatEmptyStateCopy( diff --git a/src/shared/structured-agent-session-send-disposition.ts b/src/shared/structured-agent-session-send-disposition.ts index f717e54f2d4..d503b453b8e 100644 --- a/src/shared/structured-agent-session-send-disposition.ts +++ b/src/shared/structured-agent-session-send-disposition.ts @@ -33,9 +33,16 @@ import { export type StructuredAgentSessionSendDisposition = { entries: StructuredAgentSessionOutboxEntry[] /** Only for an outcome with no entry left to carry it; a kept entry holds its own failure. */ - error: string | null + error: AgentSessionWriteNoticePart[] | null } +/** A message this client couldn't store to send; the composer's draft or the row's Retry still + * has it. */ +export const STRUCTURED_AGENT_SESSION_OUTBOX_NOT_SAVED: readonly AgentSessionWriteNoticePart[] = [ + 'messageNotSaved', + 'tryAgain' +] + type SendDispositionInput = { entries: readonly StructuredAgentSessionOutboxEntry[] entry: StructuredAgentSessionOutboxEntry @@ -247,7 +254,7 @@ export function disposeStructuredAgentSessionSendResult( if (refusedRedelivery(input.entry, submission)) { return { entries: dropEntry(input), - error: 'Message delivery is unconfirmed and Orca will not send it again' + error: ['sendOutcomeLost'] } } if (submission.dispatchState === 'accepted') {